1 2 Previous Next 29 Replies Latest reply on Sep 26, 2014 4:16 PM by mkim

    UART Routines

    userc_6531

      The only example code using the peripheral uart is the peripheral uart download example.  And that only reads and writes a single byte at a time.  I see the undocumented routines puart_synchronousRead and puart_synchronousWrite.  Can I start reading data a byte at a time until I determine the incoming message length, and then use this read routine to read the rest of the message?  Or will starting that routine reintialize the receive buffer and miss some bits if they already started?  And does this call return control to the OS until all the data bytes requested are read and placed in the specified buffer?  Same basic question for the write routine.  If I just pass the location of the start of the message buffer and length, will this routine transmit the message on the peripheral uart?

        • 1. Re: UART Routines
          ArvindS_76

          > Can I start reading data a byte at a time until I determine the incoming message length, and then use this read routine to read the rest of the message?

          Yes, you can. The bytes received are buffered in a HW FIFO, so invoking this function will not* reinitialize the receive. Calling this with a NULL pointer for buffer will dump (parameter) length bytes from the HW FIFO.

           

          > And does this call return control to the OS until all the data bytes requested are read and placed in the specified buffer?

          This is a synchronous call and will return from the function only after (parameter) length bytes have been read if length is <= 16. Behavior is undefined if a larger length read is attempted.

           

          > Same basic question for the write routine.  If I just pass the location of the start of the message buffer and length, will this routine transmit the message on the peripheral uart?

          Yes, and this is a synchronous call too. Behavior if more than 16 bytes (or less if there are un-transmitted bytes in the FIFO already) are written is undefined. Use P_UART_TX_FIFO_IS_EMPTY() to check if the TX FIFO still has bytes.

           

           

          * Edit

          1 of 1 people found this helpful
          • 2. Re: UART Routines
            userc_6531

            More confusion.  First question about the limit of the puart_synchronousRead and puart_synchronous write commands.  You say that trying to read or write more than 16 characters results in an undefined action.  So why in the world would you declare the length parameter as a UINT32 if it's use is limited to 16 characters?

             

            I am rather confused by your answer.  I would hope (If I had low level control, which I don't) that given the buffer location that we supply with these calls, that on a read, the data is read from the FIFO and moved to buffer requested in the call.  And likewise for the transmit with data being moved from the source buffer to the TX FIFO as needed.  I guess you don't have any DMA controllers on your processor.  Why no indicator of TX FIFO full so I can still push more data into the FIFO?  I have anywhere from 4 to 128 byte messages to send.  It sounds like that is not really achievable with your system.  And when I have figured the length, The following bytes are already in the process of being transmitted, so it sounds like using the read is not usable, as it will reinitialize the receive uart.  And transmitting any more than 16 bytes one has to wait til the FIFO is empty before transmitting more which results in a gap in the transmission.  You guys really didn't support any kind of useful uart functionality, did you?

             

             

            PS Your mybeacon example appears to have the beacon type and subtype in the wrong Endianess.

            • 3. Re: UART Routines
              userc_6531

              Okay, I get it that the two routines above are basically useless, unless your message length is under 16 bytes.  Now what I need to do is transmit a larger message.  You have a macro that tells us if the TX FIFO is empty, but not when the TX FIFO is full.  Wouldn't it be a good idea to have a TX FIFO full check so one can add TX bytes until the FIFO is full and again at the next interrupt?  Does this exist, or can it be checked somehow?

               

              Also how/when is the UART Interrupt Callback function called on the TX end of things?  It is called once per character on the RX side.

              • 4. Re: UART Routines
                ArvindS_76

                You can get register for and handle TX done interrupts in your app. Here is some pseudocode:

                 

                #include "puart.h"

                void application_puart_tx_done(void);

                 

                void application_create(void)

                {

                    // .... all other app create code

                 

                    // Register callback that will handle TX done.

                    puart_txCb = application_puart_tx_done;
                }

                 

                void application_tx_data(UINT8* buffer, UINT32 length)

                {

                     // Set watermark to 0 (when TX is done).

                     // Max watermark level is P_UART_WATER_MARK_TX_LEVEL_HIGHEST ( = 15)

                     P_UART_WATER_MARK_TX_LEVEL(0);

                 

                    if(P_UART_TX_FIFO_IS_EMPTY())

                     {

                          // Enqueue at most 16 bytes here.

                         

                     }

                 

                     // buffer remaining bytes and length.

                 

                     // Enable the TX interrupt. Callback registered with puart_txCb will be invoked when all bytes

                     // have been transmitted.

                     P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;

                }

                 

                void application_puart_tx_done(void)

                {

                     // Clear interrupt state

                     P_UART_INT_CLEAR(P_UART_ISR_TX_FAE_MASK);

                 

                     // TX FIFO is empty now. So send another at most 16 bytes here if required,

                     // set new watermark (if not 0) and re-enable TX interrupt.

                }

                 

                 

                > Also how/when is the UART Interrupt Callback function called on the TX end of things? It is called once per character on the RX side.

                It is called once per character if you set up the RX watermark to 1 which is what the uart_firmware_upgrade sample does. You can always set it to any value up to P_UART_WATER_MARK_RX_LEVEL_HIGHEST.

                1 of 1 people found this helpful
                • 5. Re: UART Routines
                  userc_6531

                  Can I start the transmission from the RX interrupt callback routine, and then let the TX callback routine refresh the buffer when it is empty (if I set the watermark to 15)?  Does a watermark of 15 bytes allow 16 bytes to be put in it?  And it will then generate a TX callback when the FIFO is empty so I can put another 16 bytes in?  I also assume I loop and put a byte at a time in using puart_write(nextbyte).  And when I finish putting the last group of bytes (probably less than 15) into the buffer, then I disable the interrupt and the rest of the bytes will be transmitted and message is sent with no more tx interrupts.

                  • 6. Re: UART Routines
                    ArvindS_76

                    > Can I start the transmission from the RX interrupt callback routine

                    Yes.

                     

                    > Does a watermark of 15 bytes allow 16 bytes to be put in it?

                    On the TX side, watermark interrupt will be generated when the watermark is reached from a higher number of bytes in the FIFO (so as the FIFO empties). So if you want to put in 16 bytes, use a watermark of 0, fill up to 16 bytes (with puart_write or puart_synchronousWrite) to transmit and then enable the TX interrupt. This will then generate an interrupt when the FIFO is empty.

                    • 7. Re: UART Routines
                      userc_6531

                      Arvinds,

                       

                           I am trying to test my UART functions.  I have nothing connected to the receiver, I am dummying input messages from out of a constant buffer that I process every 100th beacon I send (every 10 seconds).  My output does not look like anything that I am trying to send.  I also see another clock like signal at something much slower than 115200 baud every cycle also.  What in the world is going on?  Do I need to enable the TX interrupt if I don’t fill the 16 byte buffer?  Or can I just stuff up to 16 characters in and it will automatically transfer them, but without generating an interrupt callback?  Are the bits of each character sent in the proper order for a standard UART terminal program to interpret?  I see the reflection routine being used in firmware download and wonder why the need to reflect the bit pattern?  Do I need to do this?  Something is obviously wrong in that I am not seeing the output pattern I expect.

                       

                                                                Jay

                      • 8. Re: UART Routines
                        ArvindS_76

                        > I also see another clock like signal at something much slower than 115200 baud every cycle also.  What in the world is going on?

                        Do you have a scope trace of this?

                         

                        > Or can I just stuff up to 16 characters in and it will automatically transfer them, but without generating an interrupt callback?

                        Any time you fill up the TX buffer, it will start to be sent out whether you registered for the TX watermark interrupt or not. The interrupt is just a notification that the watermark was reached. If you set the watermark to 0, then the interrupt will trigger when all bytes have been transmitted. If you set it to 5 then the interrupt will trigger when 5 bytes remain in the TX FIFO, but the TX will still continue until the FIFO is empty. If you set the watermark to n then you must have greater than n bytes in the FIFO or the interrupt won't trigger. If you have n+1 bytes in the FIFO and you set the watermark to n, then you may or may not get the interrupt depending on when you enable the interrupt - if number of bytes in the TX FIFO < n by the time you write to the interrupt enable bit, the interrupt will not trigger.

                         

                        > Are the bits of each character sent in the proper order for a standard UART terminal program to interpret?

                        Yes. Are you using the right baud rate on the terminal app? Did you configure the right stop bits (generally 1)? Did you set the right parity (generally none)?

                         

                        > I see the reflection routine being used in firmware download and wonder why the need to reflect the bit pattern?  Do I need to do this?

                        This has nothing to do with the way uart transfers data. This is a part of the CRC verification step of the upgrade process.

                        • 9. Re: UART Routines
                          userc_6531

                          So if I understand you correctly, then if I have the watermark set to 0 (16 bytes), then if I put less than 16 bytes into the buffer, then I will not get an TX Interrupt callback, but the characters will be transmitted.  This is what I want/expect.  Don’t want an interrupt callback unless I have to transmit more than 16 characters.  So that should be okay.

                           

                          Hard to get a printout of the scope trace.  It might be my hardware that has the level shifter.  Until I can rule that out, not sure what is going on.  But my data being transmitted is definitely not what I am trying to send.

                           

                          Can you tell me anything about why that reflection routine exists and if I need to reflect my data before transmitting.

                          • 10. Re: UART Routines
                            ArvindS_76

                            > So if I understand you correctly, then if I have the watermark set to 0 (16 bytes), then if I put less than 16 bytes into the buffer, then I will not get an TX Interrupt callback, but the characters will be transmitted.

                             

                            No. If you set the watermark to 0, you will get the interrupt when the FIFO level reaches 0 regardless of how many bytes you put in the FIFO initially. The bytes will start to go out the instant FIFO count is non-zero. Because the processor is orders of magnitude faster than the uart baud rate, you will fill up the TX FIFO faster than the HW can empty it while transferring those bytes over the bus. Which is why you have the option of enabling an interrupt to notify you of some FIFO level being reached as the HW is emptying it.

                             

                            > Until I can rule that out, not sure what is going on.  But my data being transmitted is definitely not what I am trying to send.

                            Are you sending out binary data?

                             

                            > Can you tell me anything about why that reflection routine exists and if I need to reflect my data before transmitting.

                            This is related to CRC calculation for the FW upgrade process and has nothing to do with uart. You don't need to reflect anything unless your application protocol requires you to, and I suspect it does not. The FW upgrade protocol requires it, not because this is over uart, but because it is the upgrade protocol that Broadcom defined and implemented. Please see ota_firmware_upgrade (SDK 1.1 and above) ot ota_secure_firmware_upgrade (SDK 2.1) and you will see that these use reflection too.

                            1 of 1 people found this helpful
                            • 11. Re: UART Routines
                              userc_6531

                              This conversation is getting further off track and convoluted.

                               

                              Here is what I am doing:

                               

                              I set the TX watermark for 0 (16 bytes).

                              If I have don’t have more than 16 bytes to transmit, I don’t enable the TX interrupt.

                              P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;   // only executed if I have more than 16 bytes to transmit.

                               

                              So I don’t expect a TX interrupt, correct?  But the data will go out when loaded into the TX FIFO, correct?

                               

                              If I have more data and need to wait until the FIFO is empty I execute the above to enable the TX Interrupt callback that will send out another buffer of TX data of up to 16 bytes again either enabling the interrupt or not based on if there is still more data to transmit.  Should this scheme work?

                              • 12. Re: UART Routines
                                ArvindS_76

                                > I set the TX watermark for 0 (16 bytes)

                                Sorry, I am confused here. The watermark can be 0, but cannot be 16. But I will go with 0 for now.

                                 

                                > So I don’t expect a TX interrupt, correct?  But the data will go out when loaded into the TX FIFO, correct?... Should this scheme work?

                                All correct. This will work.

                                • 13. Re: UART Routines
                                  userc_6531

                                  How do I purge the TX Fifo at initialization???  It looks like the call to P_UART_TX_FIFO_IS_EMPTY() is always returning false now.

                                  • 14. Re: UART Routines
                                    userc_6531

                                    Arvinds,

                                     

                                         I have no idea of what is going on now.  I replaced all calls to puart_write to call puart_write(0x48) so I write a “H” character.  I searched the codebase for any other calls, but nothing.  Also searched for any calls to puart_synchronousWrite and there aren’t any.  Yet I am seeing a bunch of garbage data going out on the uart about once every 10 seconds (which should be my transmission rate).  I am at a complete loss, what is going on?  Where is this crap coming from????  It isn’t my app sending it, but it has to be.  How does data get into the tx buffer to start transmitting?  And is the initialization correct?  How do I debug this?  I can’t use HCI trace since that kills my timer interrupt.  I have no idea what is happening at the low levels of the uart, nor can I even look if I wanted to.  This is like hunting mosquitos with rifle while wearing a blindfold at night.

                                    1 2 Previous Next