Unable to program BCM20736S on custom board

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

cross mob
Anonymous
Not applicable

Hi all,

I have a custom board with BCM20736S connected to the UART1 of a microcontroller. On the board there is also an external connector with the UART2.

See schematic:

pastedImage_2.png

I want to program the BLE device and I do it in this way (I have no access directly to the UART pins of bcm):

FTDI connected to UART2;

A simple code on MCU sends everything that arrive on the UART2 to UART1.

With this configuration I try to program the BLE with WICED IDE, it finds the device but the download fails (see screenshot)

pastedImage_0.png

I also try the Reset Test described in the application note "Manufacturing Bluetooth Test Tool" and the BLE chip replies correctly (see screenshot)

pastedImage_1.png

What is the problem?

Kind regards,

Marco

0 Likes
1 Solution
Anonymous
Not applicable

Now I'm able to program the chip.

I solved the issue increasing the clock speed of the MCU, so the delay between the commands in tx and rx is lower.

View solution in original post

18 Replies
Anonymous
Not applicable

Just an idea: did you pull RX low and reset the Bluetooth module to get it into programming mode?

in your schematic, you have a 10k pullup (R9) on RX, so that normally, whenever you reset it, it will start in application mode. If I understood correctly, for programming, you need to pull the BLE modules RX pin low using your microcontroller (pin PG14), reset the BLE module (while keeping the pin low), and only then attempt the upload.

I don't know if relaying the information between UART1 and UART2 will have any negative effects, but I assume if you're doing that quick enough (eg directly in the interrupt routines), then there should be no issues.

Oliver

0 Likes
Anonymous
Not applicable

Thanks for your reply Oliver,

I've tried what you said but I still have the same problem.

For the UART, yes I use interrupt routines.

Marco

0 Likes

The minidriver MUST be used when programming any of the BCM2073XS devices over the HCI UART.

To use the Minidriver, you must leverage the SDK or the Command lines tools.

Unless, you go through one of the organizations we have worked with to setup mass programming, like EDOM or Avnet.

There are many threads on this topic.

Let me know if I am misunderstanding your proposed setup.

david_armourcgariss

0 Likes
Anonymous
Not applicable

How can I leverage the SDK?

0 Likes

Not sure I follow. The SDK uses the same tools described here: Programming the TAG2/TAG3 Board using command line tools​, only wrapped inside of the Eclipse IDE.

david_armourcgariss

0 Likes
Anonymous
Not applicable

I believe the two of you are talking about two different things:

From what I understand, nyquist​ HAS only been trying to use the SDK/ Wiced IDE as you suggested, mwf_mmfae​. He does have an MCU sitting between the PC and the BCM20736S - but this MCU is configured in such a way, that (at least during the firmware update) it acts just as a cable. (any character coming in on UART1 (from the SDK/Wiced IDE) is relayed directly (in the UART RX interrupt) to UART2 TX, which is connected to the BCM20736S' RX PIN.

Same the other way round, and any response from the BLE Module is passed from UART2 RX to UART1 TX back to the PC running the SDK.

mwf_mmfae​ is suggesting that you can't program the BLE module from the Microcontroller, because there is no mini-driver available for anything other than a PC running the SDK/Wiced IDE, or to be more precise, the command line utility chipload.

My approach would be to hook up a Logic Analyser to all 4 UART lines, to make sure that relaying the characters from UART1 to UART2 is working as expected (with no significant delays that might throw off the driver), and then, as a second step to also compare the data with an upload to one of the official development boards.

For this, you might have to scratch the solder mask off some of the traces and hold a probe directly on the traces between the MCU and BLE Module - I hope they're not in one of the middle layers of a multilayer board.

If you don't yet have a Logic Analyser - get one from Saleae - their cheapest one will be plenty for this type of work.

nyquist

Did you make any progress? From what you described, a viable option would be the uart-programming (with recommended ftdi cable) method. Only then, you can make use of the sdk to program your customized board.

Information: Programming your BCM20732S-based board from an onboard UART header

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hi,

It's not a problem of FTDI cable because I'm able to program the BCM20737 TAG board with the same cable connected to J10 header.

I used the Logic Analyzer (from Saleae) on the HCI UART of the development board while it was downoading the firmware and then on the external uart of my custom board. See attached the 2 files.

I've not scratched the solder mask to see what happens on the uart connected to the BLE yet.

Another question: has the BLE chip a factory firmware when it is delivered? If I power it and then I scan fo bluetooth devices with my smartphone, can I see it?

0 Likes

Firmware is programmed into the EEPROM of the module during its manufacturing. The firmware is used to validate the module prior to shipment. It's content is proprietary. I don't think the Smartphone can 'see' it during a scan.

0 Likes

For all practical purposes, you may treat it as transparent and the eeprom as "empty".

0 Likes
Anonymous
Not applicable

I just had a quick look at your logicdata.

I noticed two things:

1) there's a significant delay between command and response compared to when you're programming the TAG board. (1.5ms as opposed to 0.3ms between end of TX and start or RX packet)

2) while responses after the first few shorter packets seem to work, after the first "long" packet, your custom board does not respond at all.

My guess: you're not relaying the individual characters quick enough, or are buffering it in a way that introduces long delays, which the BLE chip won't accept.

My approach would be to make sure the rx interrupt fires on every single character received and not just when the RX buffer is (nearly) full. If you're using STM32's HAL drivers, the following code might do the trick:

uint8_t c1;

uint8_t c2;

void uart_init()

{

    ...

    HAL_UART_Receive_IT(&huart2, &c2, 1);   //begin listening for a single character

    HAL_UART_Receive_IT(&huart2, &c2, 1);

}

HAL_StatusTypeDef HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

    if(huart->Instance==USART1)

    {

        HAL_UART_Transmit_IT(&huart2, &c1, 1);  // relay that single character

        HAL_UART_Receive_IT(&huart1, &c1, 1);   //continue listening for a single character

    }

    else if(huart->Instance==USART2)

    {

        HAL_UART_Transmit_IT(&huart1, &c2, 1);

        HAL_UART_Receive_IT(&huart2, &c2, 1);

    }

}

(note: I did not test this code - and dont' forget to activate the USART interrupts!)

One thing I just realized: the above code allows RX to overwrite c1 or c2, maybe before tx had the chance to copy it. So before transmitting it, you might want to copy it into a second uint8_t. Or, even better: make a small ring-buffer to use (2-4 characters should be enough)

if you're not using HAL, you can use the RXNE Interrupt ISR directly, theoretically speeding eveything up even more.

in theory, now the additional delay should be close to the time it takes to transmit a single byte, which at 115200 would be 0.087ms, and not 0.6ms as I saw in your logicdata. (1.5ms-0.3ms=1.2ms was the additional delay for both directions)

Check if that works.

Oliver

Thanks for the excellent feedback Oliver (foolography​)

0 Likes
Anonymous
Not applicable

foolography​ I use CooCox IDE and this is how I relay the characters (I use UART1 for BLE and UART6 for the external connector:

//external UART (UART6)

void InitExtUART()

{

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

/* enable peripheral clock for USART6 */

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);

/* GPIOG clock enable */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_9;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOG, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_USART6);

      GPIO_PinAFConfig(GPIOG, GPIO_PinSource9, GPIO_AF_USART6);

       USART_InitStructure.USART_BaudRate = 115200;

        USART_InitStructure.USART_WordLength = USART_WordLength_8b;

        USART_InitStructure.USART_StopBits = USART_StopBits_1;

        USART_InitStructure.USART_Parity = USART_Parity_No;

        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

       USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

        USART_Init(USART6, &USART_InitStructure);

    USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);

   //Now enable NVIC for UART6

    NVIC_InitTypeDef UART6_NVIC_Init;

    UART6_NVIC_Init.NVIC_IRQChannel = USART6_IRQn;

    UART6_NVIC_Init.NVIC_IRQChannelPreemptionPriority = 0;

    UART6_NVIC_Init.NVIC_IRQChannelSubPriority = 0;

    UART6_NVIC_Init.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&UART6_NVIC_Init);

    USART_Cmd(USART6, ENABLE); // enable USART6

}

//BLE UART (UART1)

void InitBLEUART()

{

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

     NVIC_InitTypeDef NVIC_InitStructure;

     /* enable peripheral clock for USART2 */

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    /* GPIOB clock enable */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

      

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);

      GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

USART_InitStructure.USART_BaudRate = 115200;

        USART_InitStructure.USART_WordLength = USART_WordLength_8b;

        USART_InitStructure.USART_StopBits = USART_StopBits_1;

        USART_InitStructure.USART_Parity = USART_Parity_No;

        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

        USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

        USART_Init(USART1, &USART_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

   //Now enable NVIC for UART6

    NVIC_InitTypeDef UART1_NVIC_Init;

    UART1_NVIC_Init.NVIC_IRQChannel = USART1_IRQn;

    UART1_NVIC_Init.NVIC_IRQChannelPreemptionPriority = 0;

    UART1_NVIC_Init.NVIC_IRQChannelSubPriority = 0;

    UART1_NVIC_Init.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&UART1_NVIC_Init);

    USART_Cmd(USART1, ENABLE); // enable USART6

}

void USART1_IRQHandler(void){

     USART_SendData(USART6, USART_ReceiveData(USART1));

}

void USART6_IRQHandler(void){

     USART_SendData(USART1, USART_ReceiveData(USART6));

}

uint16_t USART_ReceiveData(USART_TypeDef* USARTx)

{

  /* Check the parameters */

  assert_param(IS_USART_ALL_PERIPH(USARTx));

 

/* Receive Data */

  return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);

}

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)

{

/* Check the parameters */

  assert_param(IS_USART_ALL_PERIPH(USARTx));

  assert_param(IS_USART_DATA(Data));

   

  /* Transmit Data */

  USARTx->DR = (Data & (uint16_t)0x01FF);

}

Another thing:

If you look at the schematic see the pin 25 of the BLE chip connected to 3.3V with a 10K resistor, but this pin is connected to the WP pin of the internal EEPROM and should be at a low level if I want to write, is it right?

So I removed the 3.3V on that pin and connected it to ground. But I'm still having the same problem (device found, download failed)

0 Likes

The minidriver which is required when programming the BCM2073XS module will over-ride the setting of the WP pin during programming.

Anonymous
Not applicable

I haven't used coocox and am fairly new to the STM32, but from what I've learned so far, most of it looks fine.

The one place where I could imagine something going wrong is with your senddata function:

what happens if your MCU is a little too busy to instantly react to the RXNE ISR?

-> it should be called twice in a row quite quickly, or it'll skip being called once (after all, if there are 2 characters in the RX buffer, it's still "not empty" right?)

in the first case, it'll depend on how the hardware TX is buffered. if it's just the one character, then you might overwrite that one character before it's been transmitted, if it's more, you should be fine

in the second case, it'll depend on how the IDE, or rather the drivers you're using in that IDE: is the "IRQHandler" the actual ISR or is the IRQHandler being called by the ISR? and where is the RXNE interrupt flag being cleared?

The easiest solution might be to add something like

while(USART_RX_not_empty(USART1))

{

     USART_SendData(USART6, USART_ReceiveData(USART1));

}

to your IRQ_Handlers.

that way, if one call to the IRQHandler is skipped for some reason you'll be able to catch up. but if you're generally too slow getting that data out again, you'll run into trouble like with long transfers anyway - then you'll have to use a ring-buffer large enough to compensate that, put your tx data in there, and fetch a new character from that buffer in a TXE IRQ_handler

I don't know if a USART_RX_not_empty function exists - you might have to check the RXNE Flag (not the RXNE Interrupt flag)

probably using the USART_GetFlagStatus() function.

Oliver

0 Likes

So have you make any progress?

nyquist

0 Likes
Anonymous
Not applicable

Now I'm able to program the chip.

I solved the issue increasing the clock speed of the MCU, so the delay between the commands in tx and rx is lower.

Thanks for reporting your findings back to the thread.

0 Likes