Hi,
I get an abort exception when using the ulTaskNotifyTake function and executing the portYIELD_WITHIN_API macro (row 3874 in tasks.c). I don’t get it in other functions, e.g. xQueueGenericReceive.
The portYIELD_WITHIN_API() macro expands to:
{ portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); }
I have copied a 8.1.2 project in CCS and replaced the old OS files with the new 8.2.0 version.
The FreeRTOSConfig.h files are identical except for the #define configUSE_TASK_NOTIFICATIONS 1
Does this happen the first time you call ulTaskNotifyTake(), or are you
able to call it a few times successfully before it happens?
Does the abort happen on one of the lines in the macro, or can you step
the code a little further through the function before it happens.
In your case calling portYIELD_WITHIN_API() should pend a software
interrupt, but because the call is inside a critical section the
interrupt should remain pending until you exit the critical section on
line 3886. So you should be able to step through the
portYEIDL_WITHIN_API() macro, then onto the taskEXIT_CRITICAL(), without
the yield being attempted. If you can step through this code and let us
know exactly on which instruction the abort occurs that will be very
helpful in diagnosing its cause.
Does this happen the first time you call ulTaskNotifyTake()…
No, it happens the second time because the first time I got the semaphore and the macro isn’t executed. So, the abort happens the FIRST time the MACRO is executed.
Does the abort happen on one of the lines in the macro…
I will test this on tuesday when I come to the office.
The xQueueReceive works but not ulTaskNotifyTake. When I get the first interrupt, ulTaskNotifyTake returns pdTRUE but when ulTaskNotifyTake is called again (and the macro executes), I get the abort exception.
I might very well have messed up it in some other area of the code (which I may have missed when did the copy [and also did comparisons afterwards]) but it’s a bit strange that xQueueReceive works but not ulTaskNotifyTake.
I get back to you when I have stepped through the macro.
#!c
<snip>
/* All ports are written to allow a yield in a critical
section (some will yield immediately, others wait until the
critical section exits) - but it is not something that
application code should ever do. */
// portYIELD_WITHIN_API();
portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; <-- abort
asm( " DSB " );
asm( " ISB " );
<snip>
It seems it’s not allowed to write to the address 0xFFFFFFB0 in ulTaskNotifyTake.
I have also posted a topic to the TI HALCoGen guys about this and asked when they will have a HALCoGen version for 8.2.0. As I said, I could very well have messed up something which I’ve missed. We could wait for the answer from Texas. One thing is that I’ve used HALCoGen’s sys_link.cmd file and not the file from your demo project. But I use the same sys_link.cmd file for the 8.1.2 project.
In the xQueueGenericReeive() case the portYIELD_WITHIN_API() call is not inside a critical section. In the ulTaskNotifyTake() case it is. I wonder if that has anything to do with it - although it would seem odd if it were the case as the yield in the TMS570 case is performed by pending a software interrupt - if the software interrupt is masked by the critical section that I would have thought it would just remain pending until the critical section was exited (which is how ports such as the Cortex-M3 and RX work, which use a similar pended software interrupt scheme for yielding).
There was a time when yielding from a critical section was done all over the place, whereas having just had a quick scan of the code that does not seem to be the case any more.
We can check this theory quickly by exiting then entering the critical section around the call to taskYIELD():
Only do that for this quick test though - don’t leave it in the code as there is the potential for a race condition with an interrupt.
If that is proven to fix the issue then I will have to get the TMS570 manual out, it might be something to do with the priority of the software interrupt, if it is configurable, I can’t remember. Although perhaps if this is an issue just restructuring the function to use a scheduler lock could also be an option.
#!c
/* All ports are written to allow a yield in a critical
section (some will yield immediately, others wait until the
critical section exits) - but it is not something that
application code should ever do. */
// portYIELD_WITHIN_API();
taskEXIT_CRITICAL();
portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY;
asm( " DSB " );
asm( " ISB " );
taskENTER_CRITICAL();
The portSYS_SSIR1_REG expands to ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
It seems that accessing this address is illegal at that moment?
…and calling taskEXIT_CRITICAL() caused interrupts to be re-enabled?
The only reason they wouldn’t would be if critical sections were nested.
Just to check - you are calling the function from a task, not an interrupt?
I will have to dig out the manual to see what could be causing this. I
don’t have the compiler installed at the moment, and it will take a long
time to install (its of non-trivial size!).
Hi again,
I mentioned this above:
“One thing is that I’ve used HALCoGen’s sys_link.cmd file and not the file from your demo project. But I use the same sys_link.cmd file (HALCoGen produced) for the 8.1.2 project.”
I have now tested the demo project with 8.2.0. Added some of my code with the GIO ISR and the notification stuff, and it works!!
So maybe the Texas (HALCoGen) memory mapping and the section configuration is causing this abort. I don’t know but maybe it’s a hint.
But as I said, I can continue with 8.1.2. I will share this information to the HALCoGen team too. But if you have an idea to what to do/change to make it work I will of course be grateful. Regards, Lars
I encountered the same problem. FreeRTOS is 8.2.0, hardware is Freescale Kinetis Cortex M4F. So this is not TI CPU related. Any updates on this issue? Anybody else sees the same error?
Thanks,
Sergei