Peripheral UART missing bytes

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I am using the peripheral UART on the BCM920732 and seem to be missing some bytes

I have followed the sample code put on github and I can read 1 byte easily, I receive the interrupt and can read back the byte. But why I try read a buffer of bytes (say around 7 bytes) sometimes I am missing 3 bytes and sometimes I can read only 2.

I have set the watermark to interrupt after every byte, are there are anymore settings I should be adjusting for this to work? I am currently using the latest IDE for this chip (1.1.0).

Any help would be much appreciated.

Thanks,

Paul

0 Likes
1 Solution

PUART does not function when the chip enters sleep mode (which it will quite aggressively). And if the MCU sends data over when the device is asleep, these bytes will not be received. Did you try with sleep disabled?

As an optimization, you can disable sleep only for the duration when you send/receive the multi-byte message over PUART and let the system sleep when TX/RX is not going to be actively used by the app (P_UART_RX_FIFO_NOT_EMPTY() and P_UART_TX_FIFO_IS_EMPTY() from puart.h will be helpful in addition to your other logic that determines message boundaries).

View solution in original post

6 Replies
Anonymous
Not applicable

Just to clarify, I can always read the first byte sent (if there is more than 1 byte), but sometimes I cannot read the bytes following that first one. Is there a certain amount of time between bytes that is optimal?

I am currently using a buad rate of 9600, because the other MCU I am communicating with only supports this speed.

0 Likes

PUART does not function when the chip enters sleep mode (which it will quite aggressively). And if the MCU sends data over when the device is asleep, these bytes will not be received. Did you try with sleep disabled?

As an optimization, you can disable sleep only for the duration when you send/receive the multi-byte message over PUART and let the system sleep when TX/RX is not going to be actively used by the app (P_UART_RX_FIFO_NOT_EMPTY() and P_UART_TX_FIFO_IS_EMPTY() from puart.h will be helpful in addition to your other logic that determines message boundaries).

Anonymous
Not applicable

Hi Arvinds,

In wha way can I disable sleep only for that specific duration? The only way I have seen is to disable sleep fully, what methods can I use to disable sleep only a portion of the time?

In the callback function (ws_upgrade_uart_device_lpm_queriable), I have tried to change the return value from 0 to 0xFFFFFFFF and if it is a non 0 value, sometime the PUART is not fully functional, sending bytes does not work. Which way would you advice to do this?

Cheers,

0 Likes
Anonymous
Not applicable

To your questions regarding disabling sleep (assuming you're still looking for an answer!)...

As per the recommended sequence for programming puart (see http://community.broadcom.com/message/3930), since you're not using flow control, you'll need to disable sleep while receiving data from the peer. Because if the peer were to send you data while you're sleeping, you'll end up missing some data.


As you already know, the recommended method to disable sleep is using a call to devlpm_registerForLowPowerQueries, which takes a function name as parameter. To disable sleep, this function needs to return 0, so it will never sleep (bad for battery, but puart should work!)


However if the return value is non-zero, it may have a specific meaning (that's not related to when exactly it will go to sleep). See http://community.broadcom.com/message/4702#4702


A non-zero parameter requests the LE stack firmware to put it to sleep, whenever the firmware deems it appropriate to save power. Specifying non-zero is however not guaranteed to enter sleep immediately, because some other processing block could hold off sleep.


Once it does enter sleep, the non-zero parameter is treated as the max number of microseconds to allow it in sleep state. So x return value means it is OK to sleep (it will enter sleep whenever the firmware deems it appropriate to save power), but please don't sleep more than x microseconds!


That way, 0xFFFFFFFF means you don't care how long it sleeps! But it does sleep (whenever the firmware deems it appropriate to save power, as usual). So changing the return value from 0 to 0xFFFFFFFF may have no control over when exactly it will go to sleep (this is decided by firmware), but rather how long it will remain in sleep state. So specifying this non-zero value is perhaps useful only in situations where it is known by design that some data will arrive by that time anyway (not based on any conditions), and that we should not remain sleeping at that time!


I hope that gives a clue as to why sending bytes is not fully functional for you now. So with sleep disabled (return 0), please also check and report if your original problem of missing some bytes while receiving on UART is resolved.

Cheers,

Ram


0 Likes
Anonymous
Not applicable

Regarding power optimization (since having sleep disabled always is bad for battery)...

(But please make sure first that basic puart operations (tx and rx) are working correctly with sleep disabled!)

Not sure what you mean by "specific duration" and "disable sleep only a portion of the time". Suggest to make sure you understand the exact condition(s) when the app is not using puart, so that you can request the firmware to sleep/power save.


See Arvinds earlier suggestion that "you can disable sleep only for the duration when you send/receive the multi-byte message over PUART and let the system sleep when TX/RX is not going to be actively used by the app", by using the helper macros P_UART_RX_FIFO_NOT_EMPTY() and P_UART_TX_FIFO_IS_EMPTY(), defined in puart.h, to check the current status of the Rx/Tx hardware FIFOs. This is in addition to app level checking of the custom message structure that you may have defined with your peer for your application. (Suggested code snippet below):

bool puartLastMessageReceivedFully; //app specific, global state flag to indicate that the entire message was received over puart

UINT32 ws_upgrade_uart_device_lpm_queriable(LowPowerModePollType type, UINT32 context)
{

    //If the Rx FIFO is empty, which means the app has copied it over
       //AND
   //If the Tx FIFO is empty, which means whatever app had output is already transmitted to peer

       //AND

   //Your last message was received fully

    if (!P_UART_RX_FIFO_NOT_EMPTY() && P_UART_TX_FIFO_IS_EMPTY() && puartLastMessageReceivedFully)
        return 1; //Enable sleep/power save in this condition
    else
       return 0;    // Disable sleep.
}


Not sure if we need to reinitialize the puart, a la Re: how to reduce the power consumption when use puart ?


Anyway, since you've set Rx watermark level to 1 byte, it ensures the chip is interrupted on every byte received on puart. Haven't found it (yet) in the documentation, but I'm assuming it will also wake up the chip if it's in sleep state, since puart is a kind of pin mux-ed GPIO.


Arvinds or someone @ BRCM, please confirm it will automatically wake up on arrival of bytes on puart?


Cheers,

Ram


0 Likes

Thanks for the contribution rammierk123

0 Likes