I am trying to run the latest demo project CORTEX_STM32F107_GCC_Rowley on my existing hardware(olimex stm32p107 rev b)-software setup using the latest stm32f10xSPL library and the olimex startup code. The setup is working with various applications outside of FreeRTOS.
In fact I can track the execution into startFirstTask() where somehow the WWDG interrupt causes my application to hang:
The difference to the given topic is that in my case the WWDG is not set as default handler in the startup code and the required handler defines in freertosconfig.h are already existing:
startup code:
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
freertosconfig.h:
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define __NVIC_PRIO_BITS=4;
/* Define configASSERT() to call vAssertCalled() if the assertion fails. The assertion
has failed if the value of the parameter passed into configASSERT() equals zero. */
#define configASSERT(x) if(x == 0 ) vAssertCalled( __FILE__, __LINE__ )
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
I have to admit that my knowledge about FreeRTOS is quite limited as this is my first project.
As far as I understand, for some reason the WWDG is called instead of SVC_Handler but i honestly have no clue where it might be triggered from.
I would be very happy if i could get a hint, where to look at to get the scheduler running.
I have attached the complete file.
In my eyes there is no obvious assignemnt of the WWDG IRQ as anything important.
I searched the file twice but I am not sure that i might have missed something…
My project is based on the aforementioned demo project and all i did was going through the steps for porting a demo project on different hardware from the freertos website.
I had to do some changes to make it use my stm32f10xspl library but i am sure that i did not touch the interrupts. I had to rename the define for the vector table but as simple led test projects are running, i am quite sure that the basic setup is fine. The problem occurs when the freertos scheduler tries to access the svc handler in the __asm volatile function (inside of prvstartfirsttask). At least thats what the debugger tells me…
But back to your question: I did not intend to disable wwdg and I did not find anything that should disable it.
Assuming that the interrupt is genuine, would it mean that the reference to my svc is faulty?
Interrupts will be masked until the first task starts. The first task starts when svc is called. Therefore if the watchdog interrupt has fired it will be held pending until svc is called. You need to determine if anything is disabling the watchdog or not, otherwise the interrupt could be genuine.
Here is the critical code fragment(port.c) where the execution gets stuck:
static void prvPortStartFirstTask( void )
{
__asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */
" dsb \n"
" isb \n"
" svc 0 \n" /* System call to start first task. */
" nop \n"
);
}
Here is my understanding:
cpsie enables the interrupts, dsb and isb dont disable the watchdog and afterwards svc is called. If i can trust the disassembly of the debugger, the wwdg comes from the nop line, so basically it is triggered directly after svc was called.
I have searched the whole workspace for all possible occurences of wwdg, wwdg_sr etc but all i found was the basic initialization, nothing that indicates disabling.
As the demo project is not my own code i cant be 100% sure if i missed something. I tried to find out if there is another way to test if the watchdog is disabled or not but that was not successful…
As i already said: All this is new for me and i have troubles understanding all at once.
Please excuse me if my questions seem stupid but i am learning and trying my best.
The thing i am wondering about is the fact that its a supported demo project for my hardware(but a different dev environment) that should be running with only minor tweaks to the code without touching anything at the level of enabeling and disabeling interrupts.
The way the watchdog is configured in the demo, should also work in my case, shouldnt it?
If the watchdog is enabled, which it is likely to be by default, and the interrupt is coming from the watchdog, which it would seem to be, then your problem is unlikely to be related to FreeRTOS - so try one step at a time.
Here is a verbose description of what you are going to have to do, note FreeRTOS is not mentioned in these instructions:
Get the user manual for the STM32 device you are using.
Look up the watchdog chapter in the manual.
In the watchdog chapter find the address of the register that enables and disables the watchdog interrupt.
In your debugger, look at the register and see if the watchdog is enabled or not.
If the watchdog is enabled then in main() write to the register to disable it. Or
If the watchdog is not enabled continue to debug to find out what the problem is.
This means that the interrupt is disabled and my problem is probably having a different source.
One thing made me wonder: For a certain reason i was not able to write to the CR and CFR registers using “WWDG->CR=…” as the library functions are doing to set the WWDG properties. It didnt give me an error but the values inside the registers did not change.
int main( void )
{
int a=WWDG->CR; //a=127, ok
WWDG_DeInit(); //reset WWDG registers
a=WWDG->CR; //a=127, ok
WWDG_EnableIT(); //set 9 bit in CFR register
a=WWDG->CFR; //a=127, wrong because bit 9 should be set
WWDG_Enable(0x50); //change cr value
a=WWDG->CR; //a=127, wrong because should be 0x50
int *adr=0x40002c00;
*adr=0x00; //manually write to CR
WWDG->CR=0x00; //manually write to CR
a=WWDG->CR; //a=127, wrong because should be 0x00
};
Is this maybe an indication for what might be going wrong?
Sorry - assuming the vector table is installed correctly (the VTOR register in the NVIC points to the correct vector table) I don’t have any other ideas.
My NVIC_VTOR is intialized with “NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );”
while NVIC_VectTab_FLASH contains the value 0x08000000.
Using the debugger i checked the memory locations(and followed addresses) 0x00000000 and 0x08000000 and found out that they contain exactly the same information with a pattern that fits to the vector table. Basically all interrupt handlers contain 0xF9F30008 and the vector table is in fact inside tha flash at 0x08000000.
Comparing the memory to my map file, i found the table definition at 0x00000000 and a reference to the vector at 0x08000000. What confused me was the fact that in my startup file and the library it is always used the “SVC_Handler” while in the map file at 0x00000000 there is following code: “PROVIDE (SVCHandler, 0x0)”.
There is a missing “_” and i have searched the whole project for occurrences of “SVCHandler” and found out that this first definition of the vector table is coming from the linker script which comes along with my pre assembled toolchain.
I will now have to investigate if the toolchain assembly ive been provided with is not incompatible to the latest spl library…
At least i now have a trace and hope that i dont have to come back to you.