1 2 Previous Next 29 Replies Latest reply on Sep 26, 2014 4:16 PM by mkim Go to original post
      • 15. Re: UART Routines
        userc_6531

        Okay, my write of a single byte triggers a bunch of Tx characters.  The timing is correct and changes when I change it.  So it is my trigger, but I am now simply trying to output a single "H" character.  But I end up with a bunch of junk characters going out.  Why?  I certainly don't know.  But I am guessing it has to do with the UART initialization and setup.  Somehow calling puart_write with a single character is generating a stream of output.  Perhaps if the TX watermark and interrupt are being used incorrectly.  But since there is no documentation of the peripheral uart APIs and no example with a TX interrupt or multiple TX bytes being sent, I am flying completely blind.

        • 16. Re: UART Routines
          ArvindS_76

          Have you checked the electrical connections? Are the levels correct? I added this to the uart_firmware_upgrade sample app and it works right (I just chose it because it initializes peripheral uart in a way that is known to work). I see the expected sequence of bytes on a terminal app using 115200, no flow control, 1 stop bit, no parity.

           

          //// Global definitions

          // Array of bytes to send

          UINT8 ascii_array[64] = { 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,

                                               65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,

                                               82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,

                                               99,100,101,102,103,104,105,106,107,108,109,110,111 };

           

          // TX done callback

          static void puart_tx_done_callback(void);

           

          int ws_upgrade_uart_init(BLE_PROFILE_PUART_CFG *puart_cfg, void (*puart_rx_callback)(void*))

          {

               ///// All the rest of the init function here.

           

              /////////// ---> Register the TX done interrupt callback function.

              puart_txCb = puart_tx_done_callback;

           

              // Enable the CPU level interrupt

              puart_enableInterrupt();

           

              /* END - puart interrupt */

              return (TRUE);

          }

           

           

          UINT32 bytes_to_print = 0;

          UINT32 uart_write_byte_index = 0;

           

          void puart_print_some_bytes(UINT32 num_bytes_to_print)

          {

              if(!num_bytes_to_print)

                  return;

           

              bytes_to_print = num_bytes_to_print;

           

              ble_trace1("Printing bytes: %d", num_bytes_to_print);

           

              // 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.

                  UINT8 i;

                  for(i = 0; i < 16; i++)

                  {

                      puart_write( ascii_array[(uart_write_byte_index++) & (sizeof(ascii_array) - 1)] );

                      bytes_to_print--;

           

                      if(!bytes_to_print)

                          break;

                  }

              }

              else

              {

                  ble_trace0("TX FIFO is not empty");

              }

           

              // Enable uart interrupt.

              P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;

          }

           

          void puart_tx_done_callback(void)

          {

              P_UART_INT_CLEAR(P_UART_ISR_TX_FAE_MASK);

           

              // Put more bytes if required.

              if(bytes_to_print)

              {

                  UINT8 i;

                  P_UART_WATER_MARK_TX_LEVEL(0);

           

                  // Enqueue at most 16 bytes here.

                  for(i = 0; i < 16; i++)

                  {

                      puart_write( ascii_array[(uart_write_byte_index++) & (sizeof(ascii_array) - 1)] );

                      bytes_to_print--;

           

                      if(!bytes_to_print)

                          break;

                  }

           

                  // Enable uart interrupt.

                  P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;

              }

              else

              {

                  ble_trace0("Done printing all bytes");

              }

          }

           

          ---------------------------------------

          In hello_sensor.c, I call puart_print_some_bytes() every 1s.

           

          void hello_sensor_timeout(UINT32 arg)

          {

              extern void puart_print_some_bytes(UINT32 n);

           

              ble_trace1("hello_sensor_timeout:%d\n", hello_sensor_timer_count);

           

              switch(arg)

              {

                  case BLEPROFILE_GENERIC_APP_TIMER:

                  {

                      hello_sensor_timer_count++;

                  }

                  break;

              }

           

              ////////// Print some bytes

              puart_print_some_bytes((hello_sensor_timer_count * 10) % 100);

          }

           

          On the terminal app:

          0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm

           

           

          This goes on 10, 20, 30, 40, 50, 60, 70, 80, 90, 10 .... bytes/characters at a time forever.

          • 17. Re: UART Routines
            userc_6531

            Here is where I am at.

             

            Put yourself in my shoes for 5 minutes.

             

            I have no debug capability in this system.  If I turn the trace on my timing falls apart and the app doesn’t work.  What does that leave me to work with?  Not much.  I can watch beacons and see if their timing and parameters are correct.  (by the way the type and subtype in your my beacon example app output a beacon with the endianess of those fields backwards).  And I can watch the output of the uart I am trying to generate responses on.  That’s it.  Not a very good way to develop code, is it?  I have no clue what is going on in the code.  No way to look inside the system.  How frustrated would you be trying to use a system with those limitations?  And no documentation to boot.

             

            Where I am at now is removing lines of code and calls to see what is causing the burst of spurious data.  What I just found is that my routine that is parsing through a dummy receive message (no app on the other side yet), to create a response message is somehow causing this message.  It makes no uart API calls.  It merely parses the receive buffer and builds a response buffer (but does not send anything) and returns.  All I can GUESS at this point is that there is something illegal going on and sending me through a reset that is generating the BS uart message traffic.  But how can I tell if that is happening?  I can’t.  How lovely.  Welcome to my nightmare.

             

            I need debug ability for this so I can output to the HCI UART and monitor it for errors and or flow.  Is there a way to do this without losing the timer interrupt?   How can I determine what is going on in the code from the outside?

            • 18. Re: UART Routines
              userc_6531

              Found the lowest denominator to the spurious data on the uart.  Not surprisingly it is a routine that I could never verify if it was working properly.  I tried, but without debug could not tell if/what was wrong.  I added a checksum byte to verify the readback, and it never seemed to work, but no way to know for sure without debug.  I am attempting to write a 113 byte buffer to NVM.  The last call to NVMWrite is the culprit on the UART as when I comment it out, I only see single byte transmissions of the same byte every time period.  Not the “H” that I am trying to write, but perhaps a reflection (I haven’t checked yet and didn’t I ask about that yesterday?).  At least it isn’t sending a bunch of junk.  So if you can tell me why this is a problem that would be great.

              Master_beacon_table is 112 bytes (plus the added 1 byte checksum for verification).

               

              void SaveBeaconConfig()

              {

                     UINT8 local_buffer[sizeof(master_beacon_table) + 1];

                     UINT8 i, csum;

               

                     memcpy(&local_buffer, &master_beacon_table, sizeof(master_beacon_table));

                     csum = 0;

                     for (i = 0; i < sizeof(master_beacon_table); i++)

                     {

                           csum += local_buffer[i];

                     }

                     local_buffer[i] = ~(csum) + 1;

                     bleprofile_WriteNVRAM(0x20, (UINT8)(sizeof(master_beacon_table) + 1), (UINT8 *)&local_buffer);

              }

              • 19. Re: UART Routines
                ArvindS_76

                The default stack size is 1024 bytes. One possibility is that you are very close to running out of stack because of that 113 byte local array and when you invoke bleprofile_WriteNVRAM(), you end up clobbering the stack.

                 

                > Not the “H” that I am trying to write, but perhaps a reflection (I haven’t checked yet and didn’t I ask about that yesterday?).

                Yes, you did, and I answered it too. The uart HW/driver do not reflect any bytes (TX or RX) and the app is not required to reflect any bytes either.

                • 20. Re: UART Routines
                  userc_6531

                  Okay, so you are suggesting I create more global variables for any kind of buffers being used.  I can do that.  But it would be EXTREMELY helpful if there was actual documentation on all this stuff.  It doesn’t say anything anywhere about a 1k stack limit.

                  • 21. Re: UART Routines
                    userc_6531

                    Still not able to get buffers bigger than 15 bytes to work.  Only the first 15 bytes go out.  Obviously my callback is not working  I think I did what you said, but I am still rather unclear on exactly how the watermark is used.  I am setting it to 15 initially.

                     

                    I am still very confused on the P_UART_WATER_MARK setup.  Does this tell how many bytes to transmit before generating interrupt callback?  And if so, shouldn't it be setup prior to stuffing the TX FIFO, not after?  No documentation on any of these functions confuses the issues horribly.  Bottom line is my first 15 bytes go out, and then nothing.  Looks like my callback is set up properly, but I get no other bytes transmitted.  What is the problem?

                     

                    Here is my basic setup:

                     

                    void App_Create(void)

                    {

                         P_UART_WATER_MARK_TX_LEVEL (15);

                         puart_txCb = puart_tx_callback;

                    }

                     

                    void App_tx_data(void)

                    {

                         P_UART_WATER_MARK_TX_LEVEL(bytes transmitting this loop);

                        if (P_UART_TX_FIFO_IS_EMPTY())

                         {

                              fill Tx buffer with up to 15 bytes

                         }

                         P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;

                    }

                     

                    void puart_tx_callback(void)

                    {

                         P_UART_INT_CLEAR(P_UART_ISR_FAE_MASK);

                         if more data to transmit

                         {

                              P_UART_WATER_MARK_TX_LEVEL(bytes transmitting this loop);

                              fill Tx buffer with up to 15 bytes

                              P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;

                         }

                    }

                    • 22. Re: UART Routines
                      userc_6531

                      Perhaps here is a clue:

                       

                      I had to declare puart_txCb locally in my module.  It would otherwise end up being undefined.  Did you build the above in SDK 1.1.0??? Could this be the problem?  What variable contains the tx callback in SDK 1.1.0?

                       

                      That could explain why the callback never happens.  I need to set up the callback into your global variable.  When I just tried to set puart_txCb to the callback routine in my init routine, it told me puart_txCb was undefined.  So I had to declare it locally.

                      • 23. Re: UART Routines
                        userc_6531

                        Arvinds,

                         

                              I did notice a big difference in my program vs your sample.  In your sample you set puart_txCb to your callback routine.  When I did that in my module, I needed to declare puart_txCb because the linker said it was undefined.  I am using SDK 1.1.0.  Could this be the problem that puart_txCb is not in SDK 1.1.0?  It would explain the lack of callback and no additional characters going out.  I hope there is either another variable or a patch for SDK 1.1.0.

                         

                              Can you please respond and let me know if this is the problem, and then later if you need with a solution.

                        • 24. Re: UART Routines
                          userc_7511

                          Just got started on my bcm92073x_le_kit.  I plan on developing a UART interface to my matab signal processing software running on laptop.  It uses a custom fixed format frame to send upt to 8 channels of data from ADC to MATLAB.  I am porting it from TI CC2540 (8051 based processor).  Any helpful hints are appreciated.  Also if I can help in return let me know.

                          • 25. Re: UART Routines
                            userc_6531

                            My main problem is the Tx message.  If I need to transmit more than 16 bytes, the callback function doesn't appear to be supported in SDK 1.1.0.  Not good if you are using the 920732 chip.  Other than that, I can probably help you if you have other things you are trying to do.

                            • 26. Re: UART Routines
                              ArvindS_76

                              > I am still very confused on the P_UART_WATER_MARK setup.  Does this tell how many bytes to transmit before

                              > generating interrupt callback?  And if so, shouldn't it be setup prior to stuffing the TX FIFO, not after?

                               

                              The watermark is the level (number of bytes remaining in the TX FIFO) at which you want the interrupt to trigger as the HW is emptying it. It is not the number of bytes after which you want the interrupt. If you set the watermark to 0, the interrupt will be triggered when the TX FIFO is emptied (so you can enqueue up to 16 more bytes for transmission). So, you must set it to a value less than the number of bytes you put in the FIFO. In my sample code above, I set the watermark to 0 so the app can be notified that there are no more bytes to transmit. I then enqueue up to 16 more bytes to transmit.

                               

                              > Did you build the above in SDK 1.1.0??? Could this be the problem?  What variable contains the tx callback in SDK

                              > 1.1.0?

                               

                              No. I used SDK 2.x for my sample code. 20732 and SDK 1.1 does not support TX watermark interrupts. This was an enhancement we added to 20736/7 and SDK 2.x.

                               

                              ----   EDIT ----

                              As a workaround for 20732 based programs using SDK 1.x, you can poll the TX FIFO to check if it is empty in the fine timer callback and then enqueue more bytes if it is.

                              1 of 1 people found this helpful
                              • 27. Re: UART Routines
                                mkim

                                Hi Arvinds,

                                 

                                I have some follow up questions on your sample UART TX codes.

                                 

                                >> void puart_tx_done_callback(void)

                                >> {

                                >>    P_UART_INT_CLEAR(P_UART_ISR_TX_FAE_MASK);

                                 

                                I want to understand why TX_FAE is cleared here on callback. 'puart_txCb' is from serialized through Task and not directly invoked from ISR. If that is the case, it seems to me that the TX_FAE interrupt should have been cleared by ISR, otherwise the deferring Task that invokes 'puart_txCb' would not have a chance to run.

                                 

                                >>        // Enable uart interrupt.

                                >>        P_UART_INT_ENABLE |= P_UART_ISR_TX_FAE_MASK;

                                 

                                Why does it keep enable TX_FAE interrupt again? There is no place in your codes that disables TX_FAE.

                                So, once TX_FAE is enabled by puart_print_some_bytes(), it should remain enabled.



                                Unless TX_FAE interrupt is being disabled by low level codes before invoking 'puart_txCb', the above part of codes doesn't seem to make sense. Can you provide clarification on this? TX_FAE interrupt is disabled internally by low level ISR before deferring to a Task for invoking 'puart_txCb'?



                                Thanks in advance!!



                                • 28. Re: UART Routines
                                  ArvindS_76

                                  The ISR context handler does not clear the interrupt. It only disables the interrupt. Since the thread context handler is responsible for handling the interrupt (the real action that needs to be taken here), the thread context interrupt callback has to clear the interrupt state and re-enable it when required.

                                  • 29. Re: UART Routines
                                    mkim

                                    Hi Arvinds, Thanks for the quick clarification!!

                                    1 2 Previous Next