fread always returns old buffer

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

fread always returns old buffer

跳至解决方案
2,801 次查看
Cdn_aye
Senior Contributor I

Hi

I may have a short coming in my understanding, but I am using the following to read serial data from  UART0 built as ittya: interrupt mode, ca_rs485_rx_buff is for any characters received,

gs_File_RS485 is the file block and I only have one for the read and write.

MQX_FILE_PTR                                gs_File_RS485 = NULL;

            u32_result = fread(ca_rs485_rx_buff, 1, sizeof(ca_rs485_rx_buff), gs_File_RS485);

The input buffer is size of 80. When I do a read I always get 80 as the # chars received. But the buffer contains old transmissions (this is a BT connection and the BTM is sending 'OK' etc for every transmission).

I expected to get 0 when nothing was received and I thought the buffer would be cleared. It is not, the last string still is in there. I rebuilt all the MQX libraries etc, the Tx is working correctly.

I have read through the posts and doc set but don't see where the error is. Is this an error on my side? If does the buffer get cleared in the FB, and should there be 0 for no new char's??

Any suggestion as to where this is going sideways would be appreciated.

////-------------------------///

I just found that IO_SERIAL_ECHO, was enabled. I disabled this in twrk40x256.h rebuilt mqx.

Now I don't see the Rx buffer filling with Tx characters. I have a logic analyzer on the Rx, Tx lines and can see char's on the Rx line but now the fread(...) does not return.

I am using ittya:, UART0, the Tx works, but not the Rx now. I enabled ittya: in user_config.h, it must be ok because the fwrite(...) works.

I thought this was non blocking, ie: that if there were no characters it would return 0, or the number it found with the buffer filled in. Is there something else that needs to be built / enabled to get this to work.

Thanks

Robert

Robert

0 项奖励
回复
1 解答
1,970 次查看
Martin_
NXP Employee
NXP Employee

What might be an issue is that the interrupt non-blocking mode is asynchronous with respect to the user application.

For fread it means:

-there is a queue internal to the serial io driver. the size of the input queue is specified at build time, default size is 64 characters, but BSP can make this input queue larger (#define BSPCFG_SCIn_QUEUE_SIZE in user_config.h for example)

-as soon the serial io driver opens (fopen), Rx interrupt is enabled for that UART module

-any character received, Rx interrupt routine is invoked and the character is put into the input queue (internal to the serial io driver), if there is an empty slot in the input queue.

-if the application doesn't call fread(), it is possible that the input queue will become full (external device sends "size of input queue" characters, in such a case all following incoming characters are dropped, only the counter RX_DROPPED_INPUT increments

-if the application makes a call to fread(), the characters, that are sitting in the input queue, will be copied into the application receive buffer and the intput queue becomes empty; fread() returns with the number of characters read.

-if the application makes a call to fread(), and the intput queue is empty, fread() returns immediately with zero.


The application should assure that fread() is called so frequently that the input queue of the serial io driver doesn't become full.

num = fread() if(0 == num) {    /* no characters. let other tasks execute. */    _time_delay(200); } else if(IO_ERROR == num) {    printf("Unexpected error during serial io read\n!!");    _task_block(); } else {    /* some characters have been received. process them. only the "num" characters are valid in */    /* in the application buffer. */

}

在原帖中查看解决方案

0 项奖励
回复
5 回复数
1,970 次查看
Martin_
NXP Employee
NXP Employee

Hi Robert,

do you open the gs_File_RS485 with the IO_SERIAL_NON_BLOCKING flag ?

In non-blocking mode, fread() returns immediately with the number of new chars received.

If there are no new chars, the fread() function returns 0 and nothing is done to the ca_rs485_rx_buff. (there is no invalidation/clearing of the receive buffer).

If used in default blocking mode with interrupts, if there are no new chars in the input queue, the fread() blocks the caller task. An incoming character would make the caller task ready and once active, fread() would continue until requested number of chars are received and fread returns.


0 项奖励
回复
1,970 次查看
Cdn_aye
Senior Contributor I

Hi Martin

Message was edited by: Robert Lewis

I was able to get the IO BLOCKING to work with this code 

b_serial_flags |= IO_SERIAL_NON_BLOCKING;           // do not want blocking, will hang 

u32_result = ioctl( gs_File_RS485, IO_IOCTL_SERIAL_SET_FLAGS, &b_serial_flags );

but there is still the same garbage in the receive buffer. I clear the local receive buffer before the fread and can see on the logic analyzer what is received on the Rx line, but that it is not what is going into the receive buffer at the time of my read.

The driver is interrupt driven so maybe there are garbage characters on the line before my command to read is issued and then I am getting the results of past traffic. Is there a command to clear the read buffer before the fread(...) and is that what should be done?

I can see a flush for the fwrite(...) but do not see a clear/flush for the read buffer. Or is this a mistake in understanding on my side... and this is not needed? I would have expected the driver to use a cleared buffer, is that a false assumption.

Thank you.

Robert

0 项奖励
回复
1,971 次查看
Martin_
NXP Employee
NXP Employee

What might be an issue is that the interrupt non-blocking mode is asynchronous with respect to the user application.

For fread it means:

-there is a queue internal to the serial io driver. the size of the input queue is specified at build time, default size is 64 characters, but BSP can make this input queue larger (#define BSPCFG_SCIn_QUEUE_SIZE in user_config.h for example)

-as soon the serial io driver opens (fopen), Rx interrupt is enabled for that UART module

-any character received, Rx interrupt routine is invoked and the character is put into the input queue (internal to the serial io driver), if there is an empty slot in the input queue.

-if the application doesn't call fread(), it is possible that the input queue will become full (external device sends "size of input queue" characters, in such a case all following incoming characters are dropped, only the counter RX_DROPPED_INPUT increments

-if the application makes a call to fread(), the characters, that are sitting in the input queue, will be copied into the application receive buffer and the intput queue becomes empty; fread() returns with the number of characters read.

-if the application makes a call to fread(), and the intput queue is empty, fread() returns immediately with zero.


The application should assure that fread() is called so frequently that the input queue of the serial io driver doesn't become full.

num = fread() if(0 == num) {    /* no characters. let other tasks execute. */    _time_delay(200); } else if(IO_ERROR == num) {    printf("Unexpected error during serial io read\n!!");    _task_block(); } else {    /* some characters have been received. process them. only the "num" characters are valid in */    /* in the application buffer. */

}

0 项奖励
回复
1,970 次查看
Cdn_aye
Senior Contributor I

Hi Martin

That was very helpful, thank you. I knew that the queue was full but now understand the mechanism to clear it. This makes sense.

If I understand, it seems that the call to fread(), is just a copy from the queue and a clear of the driver buffer, I was looking for a method to flush the input queue but as you pointed out it is just the call to the driver; I will try the code as you have suggested and then return and mark this complete. Thanks again.

Robert

0 项奖励
回复
1,970 次查看
Cdn_aye
Senior Contributor I

That was the solution; just do a read to clear the buffer if there are char's that need to be cleared. Thanks Martin

Robert

0 项奖励
回复