vicui wrote on Tuesday, July 02, 2013:

I have a 485 task to talk slave device, and need wait some time to receive response data from slave device after sending command, i use following delay function to wait 50ms to be sure master can receive all response data from slave.
void delay1ms(void)
uint32_t i = 0;
for (i = 0; i < 30000; i++) ;

but the polling method waster more cpu resource indeed, i change it to vTaskDelay(50) to wait,  the result is wrong data or less data received sometimes. I trace it and find that FreeRTOS  call taskENTER_CRITICAL to mask all interrupt to protect some piece code. then taskEXIT_CRITICAL to enable all interrupt again. but it may cause 485 interrupt lose in this case. so master can’ t receive all data correctly,  Is there a way to avoid this ?

apprecaite you in advance.


rtel wrote on Tuesday, July 02, 2013:

It is doubtful that a critical section in FreeRTOS would cause loss of 485 data.

Which port are you using?
What is configCPU_CLOCK_HZ set to?
What is the 485 baud rate?
How is 485 reception handled (DMA, interrupts placing characters in a RAM buffer, or something else)?


vicui wrote on Wednesday, July 03, 2013:

I define following in freertosconfig.h
#define configCPU_CLOCK_HZ          ( ( unsigned long ) 120000000 )
#define configTICK_RATE_HZ         ( ( portTickType ) 500 )
the 485 baud rate is 19200
485 reception is deal with in interrrupt which handler routine will put receivce byte in RAM buffer.

when i use delay1ms, everything works well


davedoors wrote on Wednesday, July 03, 2013:

You are using a slow baud rate and should not have a problem. The length of the critical section is not related in any way to the length of time you delay. In fact, using a delay of 1ms will mean you enter and exit critical sections at least 50 times more than when using your original 50ms delay. I think something else is wrong.

You are calling vTaskDelay(50) to wait 50ms, but 50 only means 50ms when configTICK_RATE_HS is 1000. If you want to wait 50ms then call vTaskDelay(50/portTICK_RATE_MS), which in this case will be the same as calling vTaskDelay(25).

A common architecture has the task using the RS485 block on a semaphore to wait for reception, then the 485 interrupt gives the semaphore when a complete message has been received. That way the task does not use excess CPU time and unblocks immediately and automatically when data has been received so also does not waste time in the blocked state.

vicui wrote on Thursday, July 04, 2013:

what confuse me is that what will happen once cpu enter into critical section but 485 interrtupt coming, it will be pending ?

if i use a semaphore to wait for reception, it the 485 transfer error, cpu will always wait now . so, time out feature must need.

rtel wrote on Thursday, July 04, 2013:

Most MCUs will pend interrupts that arrive when inside a critical section. Newer FreeRTOS ports keep a set of interrupt priorities enabled all the time.

Semaphores have a block time. If the semaphore does not become available before the block time expires the task will unblock and the semaphore take function will return an error so the task knows it does not have the semaphore. There is lots of documentation on this on the website, as well as API documentation with examples of these functions being used, and lots of demos in the download that shows how this is done.


vicui wrote on Monday, July 22, 2013:

i check the sample code for serial, and found that GET or PUT one charactor need call more APIs about QUEUE, is this more lower efficient ? my application need get data via 485 in loop,

vicui wrote on Monday, July 22, 2013:

Semaphores have a block time.  what value the default block time for semaphore is ?

rtel wrote on Monday, July 22, 2013:

A lot of demo applications provide a serial driver that is designed to demonstrate queues being used from interrupts and to test the port layer - they are not intended to be examples of how to write an efficient driver and generally queues should not be used to pass individual characters into and out of an interrupt unless the throughput requirements are very low (for example, so handle key presses).  It is much better to use a DMA, or to use the interrupt to buffer characters in a circular RAM buffer.

The block time used by a semaphore is passed into the semaphore give and take functions by the application.  There is no default:


vicui wrote on Monday, July 22, 2013:

yes,  you are really right. but putting all characters in a cricular RAM buffer need some time,  in general, i use delay to wait for receiving all data via serial, but cpu can’t do anything  in it. i just wonder to find a way to solve this .