holim wrote on Thursday, June 15, 2017:
Hello,
I’m working on a custom board with STM32F407 MCU.
The code was generated by CubeMX of ST Micro.
And it has FreeRTOS v8.2.3.
The issue resides in Ethernet side.
From a PC, I ping the custom board.
Ethernet communication is ok after reset.
But the traffic is blocked after some time (minutes or hours).
Only power reset resolves the situation.
From my investigation, I’ve found this issue is related with semaphore.
ISR (Interrupt Service Routine) releases the semaphore.
And ethernet thread obtains the semaphore to handle the frames.
When the problem happens, ISR continuously tries to release the semaphore,
but fails 'cause the semaphore is already full.
But the thread doesn’t receive the semaphore but seems to be suspended forever.
The thread stops LED blinking, which is fine until it blocks.
I tried replacing the semaphore in thread with osDelay(1). (1 ms Sleep).
Then the communication was OK for half a day.
But it shows a performance degradation of ethernet.
Please, refer to the following codes which is unchanged after being taken from CubeMX.
I also tested the counting semaphore with max count 10.
(Original code has binary semaphore.)
Count 10 is consumed very quickly.
And thread waits for the semaphore forever.
FreeRTOS v9.0 was also tried, but no change.
Any idea or suggestion will be greatly appreciated.
Thank you so much.
static void low_level_init(struct netif netif)
{
…
/ create a binary semaphore used for informing ethernetif of frame reception */
osSemaphoreDef(SEM);
s_xSemaphore = osSemaphoreCreate(osSemaphore(SEM) , 1 );
/* create the task that handles the ETH_MAC */
osThreadDef(EthIf, ethernetif_input, osPriorityRealtime, 0, INTERFACE_THREAD_STACK_SIZE);
eth_input_handle = osThreadCreate (osThread(EthIf), netif);
…
}
void ethernetif_input( void const * argument )
{
struct pbuf *p;
struct netif *netif = (struct netif *) argument;
for( ;; )
{
if (osSemaphoreWait( s_xSemaphore, TIME_WAITING_FOR_INPUT)==osOK)
{
do
{
p = low_level_input( netif );
if (p != NULL)
{
if (netif->input( p, netif) != ERR_OK )
{
pbuf_free§;
}
}
} while(p!=NULL);
}
}
}