Thanks to everyone who gives an answer. But the problem is related to the compiler. I used Cosmos and STVD, it does not bind the interrupt function. When I immigrate the project to IAR, The problem is solved.
I am dealing with STM8S103F3P6 IC. I try to send a message using TX interrupt but I have never succeeded.
I have checked the example of the UART interrupt. Also, I tried to develop the same code. However, I got still zero. I took the interrupt vector function from STM8 examples. Where is my mistake? How can I figure out?
Here my init, main, and interrupt vector function;
void init_handler(void){
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
UART1_DeInit();
UART1_Init((uint32_t)9600, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
UART1_ITConfig(UART1_IT_TXE,ENABLE);
enableInterrupts();
UART1_Cmd(ENABLE);
}
main(){
init_handler();
while(1);
}
INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17){
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
UART1_SendData8('a');
while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}
It sends nothing. I do not have any logic analyzer, I have only checked using terminal applications.
You asked where your mistake is: that's hard to tell if you use library functions that mask the usage of peripheral configuration registers and flags by making them "readable". If you don't have a logic analyzer, pin debugging helps most of the time (e.g. toggle a GPIO when entering the ISR).
My advise is to look at the actual register manipulations and to compare those with the descriptions in the STM8S Reference Manual (even if it doesn't provide concise guidance on how to initialize, start, spin down and end a transmission).
In order to make that a little easier, I'd like to share what I learned about using a UART ISR:
Sending the contents of a buffer with UART TXE and TC interrupt events turns out not to work like in e.g. MCS51: most of it has to be done with the interrupt enable flags TIEN and TCIEN in UART_CR2.
This is what worked for me:
both TIEN and TCIEN should be normally disabled
after setting up buffers and pointers, enable TIEN to start a transmission
in the ISR, during the transmission, writing to UART_DR clears the interrupt event
in the ISR, when the buffer is empty, disable TIEN and enable TCIEN to spin down the ISR chain
in the ISR, read UART_SR to check if TC is set. If that's the case, clear TCIEN
The advantage of this procedure is that media access control, e.g. for RS485, can be done in the last step of the chain.
An example in STM8 eForth is here.
SPL and opinions about that have nothing to do with the problem. As the SPL code is open sourced you can have a look and even copy it.
UART1_IT_TXE occurs after the UART has transmitted something.
Since you don't send anything (yet) the IRQ is not triggered.
You can send a series of characters using the UART1_IT_TXE IRQ by sending the first character using the UART1_SendData and then let the IRQ handle the remaining ones.
Related
Hello in the article from https://www.embedded.com/design/operating-systems/4008268/2/Back-to-the-Basics--Practical-Embedded-Coding-Tips-Part-1, there is mention on how to make a function reentrant.
long i;
void do_something(void){
disable_interrupts();
i+=0x1234;
enable_interrupts();
}
Autor tells: "This solution does not work. If do_something() is a generic routine, perhaps called from many places, and is invoked with interrupts disabled, it returns after turning them back on. The machine's context is changed, probably in a very dangerous manner."
I do not understand exactly how changed the machine's context is dangerous? Could somebody give some example where this could lead to harmful consequences to clarify it?
Note that do_something() can be called both from places where interrupts are enabled, and from places where interrupts are already disabled. Enabling interrupts on the second case goes against the expectations of the caller in a vary dangerous way.
What you really need is to save the previous state of interrupts while disabling them, and restore it afterwards.
So, a better version would be:
long i;
void do_something(void){
irq_state_t prev_int_state = disable_interrupts_save();
i+=0x1234;
restore_interrupts(prev_int_state);
}
I am trying to write an FIQ handler for arm64(AArch64) in assembly. I already have written an IRQ handler which works well so far. I was just wondering if my FIQ handler should be different from what my IRQ looks like.
My FIQ handler does the following:
Push Registers onto stack
Read GIC Interrupt Ack Register to identify the interrupt no.
Check if it is not spurious interrupt. If it is spurious branch to end of irq handler.
branch to corresponding high level C ISR for interrupt servicing.
write GIC EOIR to mark the completion of interrupt
pop registers from stack.
return to the main code.
In AArh32 FIQ used to have banked registers R8-R12,LR,SP; which were not required to push onto stack. So this was one difference from IRQ in AArch32 where all registers(except LR,SP) were required to push onto stack.
But I couldn't find what registers are banked in arm64 (except LR & SP).
Could someone please tell me what should go into my FIQ for arm64. Better if someone could direct me towards an example FIQ handler for arm64.
Theoretically, you only need to save those registers clobbered in your interrupt handler. But from the perspective of generality, you should save all the general purpose registers (X0 to X30).
LR (Link Register) is the alias of X30 in arm64. You don't need to save SP, but you must make sure SP is unchanged while returning from FIQ handler, especially when you are programming the FIQ handler in assembly language. C compiler will take care of the stack pointer so you don't worry about that in C ISR.
I'm doing some development in C with a STM32F107 chip and, at some point, the device began to reset when I call a specific function. I don't have a debugger and my debugging is just plain text over a serial port.
I've used some other microcontrollers in which I was able to access a register to see the cause of the reset, but I can't seem to find an equivalent for this device. I'm aware of the hardware exceptions of the Cortex-M3, but I don't know if one of them is being triggered since I can't seem to send text over usart when I'm inside those handlers (maybe because my TX functions use interruptions?).
So, I decided to ask people with more experience than I in this device: what is usually done to debug situations like these?
EDIT
One of the developers activated the WWDG watchdog and it was reseting the hardware before I could get my info from the fault handlers. It was a Hard Fault due to calling a function by a pointer that was pointing to the wrong place. However, I will keep this question in the hope that someone will give more details (or material about it) for pointing back to C code from the registers saved in, lets say, a Hard Fault (#dwelch idea).
The Cortex M3 has excellent fault handling features that will make your life easier. On hitting a fault, it automatically stacks several registers like PC and LR, and fault status registers will tell you things like address of bus fault, etc.
You should implement a good fault handler (for example, the hard fault handler here: http://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/) to print out the stacked registers and debug fault status registers.
You should use the UART for printing, just write your own simple custom version of printf for use from your fault handler that doesn't depend on interrupts. Just write bytes directly to uart Tx data register and poll for byte completion.
Aside from what has been mentioned about the interrupt handlers for debugging, some ST micros also have a reset source register that you can read on power-up (that is after a reset). For the cortex M family (m0/m3/m4) the register is RCC_CSR. http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf
Unfortunately you wouldn't be able to know whether the specifics, such as hard fault but it would tell you if the watchdog (window or independent) had tripped.
Given that you don't have a debugger, I would suggest that you find some peripheral on the microcontroller to help you. Perhaps you have an LED you can toggle or a simple GPIO pin that isn't being used that you can hook up to an oscilloscope. If you toggle a GPIO pin slowly enough (no faster than 1 Hz and maybe more slowly depending on the meter) you can use a volt meter instead of a scope. Put the code to toggle the LED or GPIO pin in each of the exception handlers one at a time until you track it down. If you have more than one GPIO pin available you can speed up the process. You can also write a wrapper for the specific function that is causing the reset. The wrapper function would send a list of interrupts that are enabled just before the breaking function is executed. This way you don't have to waste time testing the ones that are not enabled.
One advantage of GPIO pins in this case is they don't require an interrupt. It is best to stay away from anything that requires an interrupt (like your USART in this case). If the reset is being caused by a higher priority exception your debugging code will never execute.
It is also common that the reset is caused by an uninitialized pointer. A function pointer set to zero would cause execution to look a lot like a reset. If this is the case, the USART initialization code is probably being executed before a byte can be fully transmitted by the USART which would render the USART useless as a debugging tool in this instance.
When you say reset I think in terms of you hit the reset vector, not one of the interrupts or handlers. Are you saying that it does indeed reset the chip and start your software over again or are you saying that it is hanging somewhere? or do you have the vector table all point at the reset vector?
How to proceed depends on what you are really seeing, you need to be more clear or specific, or maybe you want help figuring that out.
Normally I map the unused vectors to a simple hang line of code which branches to itself. Later I may remap some of them to real code.
the cortex-m is very nice in that you can point at C code. If you think you are getting an exception have it point at a routine that grabs something that helps you figure out what mode you are in, the link register might have that info, or a csr somewhere, print that out and go into an infinite loop. Fill up the unused portions of the vector table with the address to this generic debug function.
From there you need to figure out why you are hitting that exception, it could be something like an unaligned access for example. It could be that you have generated an interrupt when trying to initalize a device before completely setting up the handler, who knows.
edit your question with more answers or information as you work through this.
You can use below code for debugging.
void HardFault_Handler(void)
{
__asm volatile
(
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" ldr r1, [r0, #24] \n"
" ldr r2, handler2_address_const \n"
" bx r2 \n"
" handler2_address_const: .word prvGetRegistersFromStack \n"
);
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
Also add this as well.
void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
/* These are volatile to try and prevent the compiler/linker optimising them
away as the variables never actually get used. If the debugger won't show the
values of the variables, make them global my moving their declaration outside
of this function. */
volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */
volatile uint32_t pc; /* Program counter. */
volatile uint32_t psr;/* Program status register. */
r0 = pulFaultStackAddress[ 0 ];
r1 = pulFaultStackAddress[ 1 ];
r2 = pulFaultStackAddress[ 2 ];
r3 = pulFaultStackAddress[ 3 ];
r12 = pulFaultStackAddress[ 4 ];
lr = pulFaultStackAddress[ 5 ];
pc = pulFaultStackAddress[ 6 ];
psr = pulFaultStackAddress[ 7 ];
/* When the following line is hit, the variables contain the register values. */
for( ;; );
}
I am using this to get any value of the register before going into hardfault. You can also add more registers if you like.
The "right" thing to do, is, unfortunately not practical with an STM32. That would be to put in a big exception handler that has knowledge of the source code, and can unwind the stack and give you the full call stack and line number that cause the fault. This would require adding all the debug information from your application into the flash memory of the STM32, and that's not practical.
There are ways of tricking your IDE to sometimes give you the call stack. I'd give details but I forgot to write them down, so I've forgotten. I think it has to manually changing the stack pointer from one shadow register to another.
What I usually do is to put a breakpoint at the hard fault exception vector, and then look at all the registers when the break point hits. Consider them forensic evidence from a murder, done with plastic explosives. The values of the registers will give you ideas. Register values that start with 0x20000000 are RAM addresses. Register values that start with 0x08000000 are Flash addresses. Open up the disassembler and type in those addresses. It will probably go straight to the variable or function at those memory locations. If that doesn't help, then look at the stack pointer. Look at the memory locations at the stack pointer, and do the same trick. I have always found enough shrapnel to location the function where the exception was happening.
consider we're writing a firmware for a baremetal MCU, i.e. no OS. I'm told it's not possible (illegal?) to pass arguments to interrupt handler function?
I can't precisely understand why it is so? What's wrong with this?
PS. is it possible to do in some RTOS-es, embedded Linux etc. or it si fundamentally wrong ?
Interrupts. do just that...interrupt. Imagine the doorbell at your home, interrupting you at any particular random time day or night. Can you be expected to at any moment have all the right items in your hand for any particular interrupt that can occur. You have to be able to cook dinner, take a shower, fold the laundry but just BEFORE the doorbell rings you must have exactly the correct items in both hands depending on the person ringing the bell, without any way of knowing they are there or are coming or are about to ring the bell. Not really possible. Same deal here, interrupts come at any particular time, for most processors immediately after the currently executing instruction, the interrupt handler is called, which means every single instruction would have to be trying to perform the foreground application while keeping all the parameters for the interrupt handler, and do all of this in one instructions time.
Now what is possible is with an operating system, or rtos or call it what you will, some layer. To have the real interrupt handler that knows nothing going in and has to figure it out, once it figures out what the interrupt is about to gather info and then call a high level interrupt handler that is passed parameters. Certainly possible and most/many operating systems do it this way.
No parameters can be explicitly passed to an interrupt handler because it is designed to be called by the hardware. Each architecture imposes a particular stack frame when it is called, typically including the saved state of the CPU.
If you also intend to call the interrupt handler from elsewhere in the code, you have either a design flaw, or there is some common code which could be factored out to be shared between the interrupt handler and the algorithmic code.
The only other thing I'll point out (that hasn't been mentioned so far) is the concept of a "software interrupt" (sometimes called a "trap"), which most processors support.
The idea is that a special instruction causes an exception to take place, and often with a software interrupt, either the opcode causing the exception, or registers set up prior to the exception, can contain values/arguments.
For example, in ARM processors, look up "SWI" or "SVC", depending on your architecture. I believe with the SWI instruction, the lower 8 bits are not part of the opcode - you can fill in whatever you want & pass a value from 0-255 (memory a little fuzzy here).
Unlike a hardware-initiated interrupt, which is totally asynchronous to the code running on the CPU, a software interrupt is synchronous - it occurs when the initiating instruction is executed (barring interrupt masking, nesting, etc.)
An interrupt handler is called by the hardware. It is "passed" whatever "arguments" the hardware passes it.
That's all there is.
when you setup an interrupt handler using the call below, it looks like the interrupt handler takes some args and returns irqreturn_t. Is this not the same interrupt handler OP is talking about?
int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long flags,
const char *dev_name,
void *dev_id);
You can use shared variables set during normal code flow to affect the behaviour of an interrupt handler the next time it runs. But because you do not call the ISR directly, you cannot pass arguments. It is not a matter of legality, but rather technicality.
eg:
volatile enum
{
DO_NOTHING,
DO_A,
DO_B,
DO_C
} isr_action ;
__interrupt (SOME_IRQ) myISR()
{
switch isr_action
{
case DO_A :
{
// A
}
break ;
case DO_B :
{
// B
}
break ;
case DO_C :
{
// C
}
break ;
}
}
int main()
{
// Make ISR do A on next SOME_IRQ
isr_action = DO_A ;
for(;;)
{
// wait for interrupt
}
}
I would like to use printf to diplay text on a serial port of an ARM microcontroller. I am unable to do so. Any help is appreciated.
My init_serial looks like this
void init_serial (void)
{
PINSEL0 = 0x00050000; /* Enable RXD1 TxD1 */
U1LCR = 0x00000083; /*8 bits, 1 Stop bit */
U1DLL = 0x000000C2; /*9600 Baud Rate #12MHz VPB Clock */
U1LCR = 0x00000003; /* DLAB=0*/
}
which is obviously wrong.
For microcontollers, you typically have to define your own putc function to send bytes to whichever UART you're using. print will then call your putc.
Check the documentation for the libraries supplied with your compiler.
Note that this is entirely unrelated to how you intialise your UART. All that matters is which UART you're using.
(On an unrelated issue, rather than saying:
PINSEL0 = 0x00050000; /* Enable RXD1 TxD1 */
U1LCR = 0x00000083; /*8 bits, 1 Stop bit */
there are typically #defines for registers which (usually) aid readability, provide a link to the bit names in the documentation, and reduce the need for comments to be added and maintained on every line like these. For example:
PINSEL0 = PICSEL0_RXD1EN | PICSEL0_TXD1EN;
U1LCR = U1LCR_8BITS | U1LCR_1STOPBIT;
..and so on.)
To make printf(), puts() etc work on an embedded platform, you need to implement some hooks that work with the C library. This is typically dependent on the C libraries provided with your compiler, so is probably compiler-dependent. But in many cases the library just requires you to provide a putc() function (or similar name), which takes a character (generated by the printf() library function) and sends it to your chosen output device. That could be a memory buffer, serial port, USB message, whatever.
From the point of view of the C library, the putc() function would be run-to-completion, so it's up to you whether you implement it to be a simple blocking function (waiting until the serial port is free and sending the character), or non-blocking (putting it into a buffer, to be sent by a background interrupt task; but the buffer might fill up if you output enough bytes fast enough, and then you have to either block or discard characters). You can also make it work properly with your RTOS if you have one, implementing a blocking write that sleeps on a semaphore until the serial port is available.
So, in summary, read the documentation for your compiler and its C library, and it should tell you what you need to do to make printf() work.
Example links for AVR micro with GCC compiler:
AVR libc stdio docs
a blog post
ARM GCC compiler using newlib C library:
Newlib C library docs
Defining host interface - syscalls - write() function
I'm not sure about ARM in particular...
For some chips, within the IDE, you need to specify that you need a heap to use the printf, and how big it should be. The programmer won't automatically put one on.
Check in the menus of your programmer/IDE and see if there is a place to specify the heap size.
And I agree with Steve, this is only if you can actually use the printf, otherwise write your own little snippet.