Topic : Bootloader, Interrupts, and at <address>

Forum : ST7/STM8

Original Post
Post Information Post
September 21, 2011 - 5:04pm
Guest

I am creating a bootloader project and an application (firmware) project to run on our STM8s, which communicate over a CAN network. I got some very helpful advice earlier from Bruno, and I ended up needing to share my interrupt between the Bootloader and the Application, but the actual interrupt code is in the Bootloader project. The code looks something like #define CAN_GetDataFW (*((void(*)(void))0xB500)) void CAN_RX_IRQHandler (void) interrupt 8 { if(appStart) { CAN_GetDataFW(); } else { CAN_GetData(); } } So if in the bootloader portion of the code, CAN messages are handled with CAN_GetData in the Bootloader project. If the application has started, CAN messages are handled with CAN_GetDataFW in the Firmware project, which has an absolute address to keep the two projects separate. Now, CAN_GetDataFW looks something like: at 0xB500 void CAN_GetDataFW(void) { .....process CAN commands.... main_fw2(); } where main_fw2 is just the main waiting loop that the chip starts in after initialized, and waits in until it receives the next CAN command. I have to include this call because there is a problem where the code will never return back to the Interrupt CAN_RX_IRQHandler. If I placed a piece of code directly after CAN_GetDataFW(); in if(appStart), the program will never reach that line, it will just freeze. I had thought I had bypassed the problem by going directly back to the waiting loop before reaching this problem point. This solution, while messy, had seemed to work, although now I realize that the chips also freeze after about 20-40 iterations of CAN_GetDataFW(). I now believe THIS issue might be caused by never actually finishing the CAN_GetDataFW function, so the function and all the variables within it are never undeclared. The RAM is slowly filling up with these copies of CAN_GetDataFW and everything in it, until after 30 repetitions or so, the RAM is full and the chip freezes. I can't confirm this because, with the Bootloader and Application in 2 different projects, I cannot use Ride7's debug feature with the SWIM cable to check registry values. So, I was wondering if anyone had a suggested fix for this, which I believe could be solved in one of three ways: 1) Is there a fix to the problem about the program not able to return to "CAN_RX_IRQHandler (void) interrupt 8" after finishing "CAN_GetDataFW"? I am sure this is because CAN_GetDataFW is at an absolute address, but I don't know if there is a known problem and if there is a workaround 2) Is there a way to declare CAN_GetDataFW as a "static" function, but not the normal "function static" in C, which just makes a function local, but the "variable static", which causes a variable not to allocate memory when called multiple times. 3) Is there a way to just clear everything on the RAM, or something similar, that doesn't solve the problem of CAN_GetDataFW from being re-initialized everytime, but somehow prevents the memory from filling up and the base from freezing after 30 iterations. It doesn't need to be pretty, it just needs to work indefinitely. Thanks for any help you can suggest, -Dan

Replies
Post Information Post
+1
0
-1
September 26, 2011 - 8:56am
Raisonance Support Team

Hi,

First, please ensure that you are using the latest version of the tools (available from http://www.mcu-raisonance.com/mcu_downloads.html) in order to avoid working on a problem that has already been solved.

Also, there is a useful application note "AN61-Writing an STM8 bootloader" that you can read to find useful inforamtion about the STM8 toolchain.
However, it looks like you are pretty much aware about all our specificities already :cool:

To answer your specific questions:

1) There is no specific reason why your CAN_GetDataFW function call does not return to the IRQ handler. My guess is that this is hardware-related. You may try to remove the function contents and check whether it works better.

2) There is no such "all variables static" directive. This may be a good idea, so we will consider adding it to our compiler in the future. For now, you will have to declare each individual variable as static on its own.

3) memset() is your friend.

I hope this helps,
Best Regards,

+1
0
-1
September 26, 2011 - 8:03pm
Guest

Bruno,

None of those seems to work. Even a completely empty CAN_GetDataFW() call will not return to the interrupt function.

What if I try a direct IRET command? I know its not elegant, but I believe it will solve my problem of Interrupts stacking up. The default Raisonance libraries for STM8S seem to have _sim_, _rim_, _nop_, etc, but no _iret_

Is there anyway to simply and directly call IRET to pop the interrupts off the stack?

-Dan

+1
0
-1
September 27, 2011 - 9:41am
Raisonance Support Team

Hi,

2 things here:

- "The function will not return". How do you ensure that? Did you follow the assembly listing file? If you set a breakpoint, the function may never return if there is no code after it (in the caller function). So this can just be an artefact of the debugger interface.

- Can you try to remove all compiler optimizations ? The code will be slower but this will ensure that you do not have a compiler problem (forgotten "volatile" or the like).

Let us know if you find your way out.
Best Regards,