puart_write() crashing on BCM20736?

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

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hi!

So I've been trying to update my one-wire PUART application to work with SDK 2.0.1 on a BCM20736, but haven't been able to get it to work.

Here is the new code:

odbol/broadcom-wiced-ble-uart at sdk2 · GitHub

So I'm having a couple problems:

  1. Calling puart_write() the second time seems to crash the chip and it restarts. Set the ENABLE_CRASHING_ON_SEND_PUART define to 1 in hello_sensor.h to see this. (log is attached)
  2. Even when I disable the puart_write() crashing part, the puart_rxCb interrupt is never called when I send data from the Arduino.

This similar code worked in SDK 1.1 with a BCM20732, so I'm wondering what I'm missing. All I did was update a few function calls according to the "uart_firmware_upgrade" example. Here's the diff: Comparing master...sdk2 · odbol/broadcom-wiced-ble-uart · GitHub

A couple questions/avenues of investigation for the differences between SDK 1.1 and 2.0:

  1. Do I no longer need to call "bleprofile_PUARTRxOn()"?
  2. I also no longer call "devlpm_init()" before devlpm_registerForLowPowerQueries(). Could that be a problem?
  3. Do I need to use puart_setBaudrate() or can I just modify puart_UartConfig directly?
  4. If so, do I call puart_setBaudrate() before puart_init() or after?
  5. Will pin 25 for RX and 32 for TX still work on the BCM20736?

Thanks!

0 Likes
1 Solution
Anonymous
Not applicable

Tyler,

I was finally able to have two-way serial communications between a host and the WICED tag using the peripheral UART.  Some things that I discovered along the way may be useful to you:

1. The documented API for this functions seems incorrect.  They return 0 (FALSE) on success:

/// (...)

/// \return TRUE when successful; else FALSE.

BOOL32 puart_selectUartPads(UINT8 rxdPortPin, UINT8 txdPortPin, UINT8 ctsPortPin, UINT8 rtsPortPin);

   

/// (...)

/// \return TRUE if valid; else FALSE.

BOOL32 puart_checkRxdPortPin(UINT8 rxdPortPin);

/// (...)

/// \return TRUE if valid; else FALSE.

BOOL32 puart_checkTxdPortPin(UINT8 txdPortPin);

2. As documented in the HW Interfaces doc, disabling sleep is a must.  Without that the UART won't work.  The document mentions that only GPIOs can wake up the device when asleep.  It's surprising that one cannot configure the UART interrupt just as well, but I guess that's what it is.

3. The peripheral UART is also connected to the FTDI chip, which makes it available to your development host as a second USB/serial port.  On Linux this would by /dev/ttyUSB1.  So testing the PUART functionality is much easier than having to attach a second device (Arduino, etc.)

4. You can redirect all your ble_tracen output to the peripheral uart by editing:

diff --git a/Wiced-Smart/spar/common/sparinit.c b/Wiced-Smart/spar/common/sparinit.c

index 5128819..6f8f3b9 100755

--- a/Wiced-Smart/spar/common/sparinit.c

+++ b/Wiced-Smart/spar/common/sparinit.c

@@ -67,7 +67,7 @@ void application_setup(void)

     extern UINT8 *bleapp_sram_addr;

     bleapp_sram_addr = (UINT8 *)0x200000;

     bleapp_pre_init = application_init;

-    BLE_APP_ENABLE_TRACING_ON_HCI_UART();

+    BLE_APP_ENABLE_TRACING_ON_PUART();

#ifdef RAMBUFENABLE

     {

And with all this new found knowledge, this is the configuration magic that worked for me:

int XXX_uart_init(BLE_PROFILE_PUART_CFG *puart_cfg)

{

    puart_init();

    if (puart_checkRxdPortPin(puart_cfg->rxpin)) {

        ble_trace1("\nFailed to set PUART RX pin %d", puart_cfg->rxpin);

        return FALSE;

    }

    if (puart_checkRxdPortPin(puart_cfg->txpin)) {

        ble_trace1("\nFailed to set PUART TX pin %d", puart_cfg->txpin);

        return FALSE;

    }

    if (puart_selectUartPads(puart_cfg->rxpin, puart_cfg->txpin, 0x00, 0x00)) {

        ble_trace0("\nFailed to select UartPads");

        return FALSE;

    }

    puart_setBaudrate(0, 0, puart_cfg->baudrate);

    puart_flowOff();

    puart_enableTx();

    devlpm_init();

    devlpm_registerForLowPowerQueries(lpm_callback, 0);

    P_UART_INT_CLEAR(P_UART_ISR_RX_AFF_MASK);

    /* set watermark to 1 byte - will interrupt on every byte received. */

    P_UART_WATER_MARK_RX_LEVEL (1);

    // Almost Full interrupt

    P_UART_INT_ENABLE |= P_UART_ISR_RX_AFF_MASK;

    // Set callback function to app callback function.

    puart_rxCb = application_puart_interrupt_callback;

    // Enable the CPU level interrupt

    puart_enableInterrupt();

    return (TRUE);

}

I hope that it helps.

Best,

View solution in original post

10 Replies
Anonymous
Not applicable

Hi Tyler,

  Can you ensure that you call devlpm_init() as you had done prior?  This needs to be called before any other devlpm functions can be used.  Let us know if this fixes your issue.

Regards,

Frank

0 Likes
Anonymous
Not applicable

Hi Frank,

I did try something similar to what odbol is doing, following the example code from uart_firmware_upgrade/ws_upgrade_uart.c and no luck.  (I double-checked I was calling devlpm_init() gets called, as you suggest)

I just need basic two-way serial communication between the host and the WICED for unit testing.  I'm using SDK2 with a 2073TAG and no luck.  I can get traces from the device (with ble_trace<N>()) to the host but none of the puart functions seems to work neither for writing (puart_printf, puart_write) nor receiving (puart_rxCb is never called).

Is there any chance that someone reviews/updates the Peripheral UART Sample Code in the 'WICED Smart HW Interfaces' document for SDK 2.0?  This seems to be basic functionality that shouldn't require that much experimentation to get it working.

Thanks!

Javier

0 Likes
Anonymous
Not applicable

Tyler,

I was finally able to have two-way serial communications between a host and the WICED tag using the peripheral UART.  Some things that I discovered along the way may be useful to you:

1. The documented API for this functions seems incorrect.  They return 0 (FALSE) on success:

/// (...)

/// \return TRUE when successful; else FALSE.

BOOL32 puart_selectUartPads(UINT8 rxdPortPin, UINT8 txdPortPin, UINT8 ctsPortPin, UINT8 rtsPortPin);

   

/// (...)

/// \return TRUE if valid; else FALSE.

BOOL32 puart_checkRxdPortPin(UINT8 rxdPortPin);

/// (...)

/// \return TRUE if valid; else FALSE.

BOOL32 puart_checkTxdPortPin(UINT8 txdPortPin);

2. As documented in the HW Interfaces doc, disabling sleep is a must.  Without that the UART won't work.  The document mentions that only GPIOs can wake up the device when asleep.  It's surprising that one cannot configure the UART interrupt just as well, but I guess that's what it is.

3. The peripheral UART is also connected to the FTDI chip, which makes it available to your development host as a second USB/serial port.  On Linux this would by /dev/ttyUSB1.  So testing the PUART functionality is much easier than having to attach a second device (Arduino, etc.)

4. You can redirect all your ble_tracen output to the peripheral uart by editing:

diff --git a/Wiced-Smart/spar/common/sparinit.c b/Wiced-Smart/spar/common/sparinit.c

index 5128819..6f8f3b9 100755

--- a/Wiced-Smart/spar/common/sparinit.c

+++ b/Wiced-Smart/spar/common/sparinit.c

@@ -67,7 +67,7 @@ void application_setup(void)

     extern UINT8 *bleapp_sram_addr;

     bleapp_sram_addr = (UINT8 *)0x200000;

     bleapp_pre_init = application_init;

-    BLE_APP_ENABLE_TRACING_ON_HCI_UART();

+    BLE_APP_ENABLE_TRACING_ON_PUART();

#ifdef RAMBUFENABLE

     {

And with all this new found knowledge, this is the configuration magic that worked for me:

int XXX_uart_init(BLE_PROFILE_PUART_CFG *puart_cfg)

{

    puart_init();

    if (puart_checkRxdPortPin(puart_cfg->rxpin)) {

        ble_trace1("\nFailed to set PUART RX pin %d", puart_cfg->rxpin);

        return FALSE;

    }

    if (puart_checkRxdPortPin(puart_cfg->txpin)) {

        ble_trace1("\nFailed to set PUART TX pin %d", puart_cfg->txpin);

        return FALSE;

    }

    if (puart_selectUartPads(puart_cfg->rxpin, puart_cfg->txpin, 0x00, 0x00)) {

        ble_trace0("\nFailed to select UartPads");

        return FALSE;

    }

    puart_setBaudrate(0, 0, puart_cfg->baudrate);

    puart_flowOff();

    puart_enableTx();

    devlpm_init();

    devlpm_registerForLowPowerQueries(lpm_callback, 0);

    P_UART_INT_CLEAR(P_UART_ISR_RX_AFF_MASK);

    /* set watermark to 1 byte - will interrupt on every byte received. */

    P_UART_WATER_MARK_RX_LEVEL (1);

    // Almost Full interrupt

    P_UART_INT_ENABLE |= P_UART_ISR_RX_AFF_MASK;

    // Set callback function to app callback function.

    puart_rxCb = application_puart_interrupt_callback;

    // Enable the CPU level interrupt

    puart_enableInterrupt();

    return (TRUE);

}

I hope that it helps.

Best,

Anonymous
Not applicable

Ah, thanks for figuring out that the puart_checkRxdPortPin() functions return the opposite of what they should. That helps!

Also, I found that the real bug was in the IDE: for some reason it was compiling a different file than the one in the project. I had two projects with a "uart_one_wire.c" file, and even though I was making all kinds of changes to the one in my project directory, it was using some other function definition from a different file. I changed the "uart_init()" function to be named "peripheral_uart_init()", and then it used the correct function and everything worked swimmingly. Not sure what's going on with that or where it was finding the other "uart_init()" function. Aren't compilers supposed to figure this stuff out for you?

0 Likes
Anonymous
Not applicable

Ah, yes, I was also hit by that problem. I learned the hard way that you

can look at your platform's patch.symdefs to see what symbols are defined

in ROM and avoid them. The linker should look at that file and report an

error, but it does not.

Cheers,

Anonymous
Not applicable

jcardona: Thanks for writing up. We had tough time porting our puart interface from SDK-1.1.0 to SDK-2.0.1. Your writeup helped us a lot.

Anonymous
Not applicable

According to a message that a Broadcom support engineer send me some time ago, puart_init() should be called after puart_selectUartPads().  Apparently the other order works for you, but it does seem reasonable to establish the configuration before turning on the driver.  I wonder if your setup would still work with puart_init() done later?

0 Likes
Anonymous
Not applicable

wmb,

Yes, it works if I move the call to puart_init() after puart_selectUartPads().  In fact, it also works if I comment out the calls to puart_selectUartPads(), puart_checkTxdPortPin and puart_checkRxdPortPin() altogether.

Go figure

0 Likes
Anonymous
Not applicable

I’m not at all surprised that the calls to puart_check*xdPortPin() are unnecessary. As I understand it, they don’t actually change any state, they only tell you whether or not the supplied pin numbers are valid.

Does your app work if you omit puart_init()? Are you supplying a non-null BLE_PROFILE_PUART_CFG argument to bleapp_set_cfg() in your APPLICATION_INIT() ? According to puart.h, if you do the PUART_CFG thing, explicitly calling puart_init() should be unnecessary.

Anonymous
Not applicable

wmb,

Yes, it does work if I omit puart_init(), and yes, I'm calling bleapp_set_cfg() with a valid BLE_PROFILE_PUART_CFG.  So yes, looks like half of the initialization code was unnecessary after all...

Thanks,

0 Likes