1 2 Previous Next 18 Replies Latest reply on Apr 20, 2016 4:16 AM by MichaelF_56

    Unable to program BCM20736S on custom board

      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:

       

      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)

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

       

      What is the problem?

       

      Kind regards,

       

      Marco

        • 1. Re: Unable to program BCM20736S on custom board

          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

          • 2. Re: Unable to program BCM20736S on custom board

            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

            • 3. Re: Unable to program BCM20736S on custom board
              MichaelF_56

              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.

               

              davida_06 ChristopherA_76

              • 4. Re: Unable to program BCM20736S on custom board

                How can I leverage the SDK?

                • 5. Re: Unable to program BCM20736S on custom board
                  MichaelF_56

                  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.

                   

                  davida_06 ChristopherA_76

                  • 6. Re: Unable to program BCM20736S on custom board

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

                     

                    From what I understand, user_2160001 HAS only been trying to use the SDK/ Wiced IDE as you suggested, MichaelF_56. 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.

                     

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

                    • 7. Re: Unable to program BCM20736S on custom board
                      BoonT_56

                      user_2160001

                      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

                      • 8. Re: Unable to program BCM20736S on custom board

                        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?

                        • 9. Re: Unable to program BCM20736S on custom board
                          ShawnA_01

                          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.

                          • 10. Re: Unable to program BCM20736S on custom board
                            BoonT_56

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

                            • 11. Re: Unable to program BCM20736S on custom board

                              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

                              1 of 1 people found this helpful
                              • 12. Re: Unable to program BCM20736S on custom board
                                MichaelF_56

                                Thanks for the excellent feedback Oliver (op_2169936)

                                • 13. Re: Unable to program BCM20736S on custom board

                                  op_2169936 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)

                                  • 14. Re: Unable to program BCM20736S on custom board
                                    MichaelF_56

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

                                    1 of 1 people found this helpful
                                    1 2 Previous Next