cancel
Showing results for 
Search instead for 
Did you mean: 

Problem communicating with bootloader on STM32F7

is45
Associate III

Hello, I am trying to use one MCU to program another MCU, both of which are STM32 F746ZG boards.

Let the MCU that is sending the commands be MCU 1, and the MCU in the bootloader mode be MCU2.

I use the following command in the MCU2 to start its default bootloader:

BOOT_JumpToAddress(DEFAULT_BOOTLOADER_ADDRESS);

void BOOT_JumpToAddress(uint32_t address)
{
    printf("Jumping to 0x%08X\r\n", address);

    // Function pointer to reset handler
    void (*app_reset_handler)(void) = (void *)(*((volatile uint32_t *)(address + 4U)));

    // Disable RCC, HAL, reset SYSTICK, and remap vector table offset
    HAL_RCC_DeInit();
    HAL_DeInit();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    SCB->VTOR = address;
    uint32_t msp_value = *((volatile uint32_t *)address);
    __set_MSP(msp_value);
    // Jump into application
    app_reset_handler();
}

Then, on MCU1, I have coded the following functions so that I can send certain commands by typing them into my serial emulator PuTTY:

printf("cmd: ");
while (1)
{
    if (HAL_UART_Receive(uartHandleDebug, &receivedByte, 1, 100) == HAL_OK)
    {
        printf("%c\r\n", receivedByte);
        switch (receivedByte)
        {
            case 'h':
                printf("h -> help\r\n");
                printf("i -> initialize communication\r\n");
                printf("g -> get command set\r\n");
                printf("v -> version\r\n");
                break;
            case 'i':
                printf("Initializing communication \r\n");
                cmd[0] = 0x7F;

                HAL_UART_Transmit(uartHandleComm, cmd, 1, HAL_MAX_DELAY);
                
                printf("Bytes sent: ");
                for (uint8_t i = 0; i < 1; i++)
                {
                    printf("%02X, ", cmd[i]);
                }
                printf("\r\n");

                startTick = HAL_GetTick(); //In milliseconds
                timePassed = 0;
                complete = 0;
                while (!complete){
                    while (!rxComplete)
                    {
                        timePassed = HAL_GetTick() - startTick;
                        if (timePassed > 5000){
                            printf("Timeout waiting for frame\r\n");
                            complete = 1;
                            break;
                        }
                        __NOP();
                    }
                    if (rxComplete){
                        char printbuf[64];
                        sprintf(printbuf, "Bootloader Response: %02X\r\n", response[0]);
                        printf("%s", printbuf);
                        rxComplete = 0;
                        if (HAL_UART_Receive_DMA(uartHandleComm, response, sizeof(response)) != HAL_OK)
                        {
                            printf("Error: Failed to initialize UART receive DMA.\r\n");
                        }
                    }
                }
                break;
            case 'g':
                printf("Getting command set \r\n");
                cmd[0] = 0x00;
                cmd[1] = 0xFF;

                HAL_UART_Transmit(uartHandleComm, cmd, 2, HAL_MAX_DELAY);
                
                printf("Bytes sent: ");
                for (uint8_t i = 0; i < 2; i++)
                {
                    printf("%02X, ", cmd[i]);
                }
                printf("\r\n");

                startTick = HAL_GetTick(); //In milliseconds
                timePassed = 0;
                complete = 0;
                while (!complete){
                    while (!rxComplete)
                    {
                        timePassed = HAL_GetTick() - startTick;
                        if (timePassed > 5000){
                            printf("Timeout waiting for frame\r\n");
                            complete = 1;
                            break;
                        }
                        __NOP();
                    }
                    if (rxComplete){
                        char printbuf[64];
                        sprintf(printbuf, "Bootloader Response: %02X\r\n", response[0]);
                        printf("%s", printbuf);
                        rxComplete = 0;
                        if (HAL_UART_Receive_DMA(uartHandleComm, response, sizeof(response)) != HAL_OK)
                        {
                            printf("Error: Failed to initialize UART receive DMA.\r\n");
                        }
                    }
                }
                break;
            case 'v':
                printf("Getting version\r\n");
                cmd[0] = 0x01;
                cmd[1] = 0xFE;

                HAL_UART_Transmit(uartHandleComm, cmd, 2, HAL_MAX_DELAY);
                
                printf("Bytes sent: ");
                for (uint8_t i = 0; i < 2; i++)
                {
                    printf("%02X, ", cmd[i]);
                }
                printf("\r\n");

                startTick = HAL_GetTick(); //In milliseconds
                timePassed = 0;
                complete = 0;
                while (!complete){
                    while (!rxComplete)
                    {
                        timePassed = HAL_GetTick() - startTick;
                        if (timePassed > 5000){
                            printf("Timeout waiting for frame\r\n");
                            complete = 1;
                            break;
                        }
                        __NOP();
                    }
                    if (rxComplete){
                        char printbuf[64];
                        sprintf(printbuf, "Bootloader Response: %02X\r\n", response[0]);
                        printf("%s", printbuf);
                        rxComplete = 0;
                        if (HAL_UART_Receive_DMA(uartHandleComm, response, sizeof(response)) != HAL_OK)
                        {
                            printf("Error: Failed to initialize UART receive DMA.\r\n");
                        }
                    }
                }
        }
    }
}

 

I am able to get back responses some times, like when I enter 'i', I get back 0x79. However, this is quite inconsistent. When I click g, I only get the first few bytes of the response. However, when I look at the logic analyzer, I can see that MCU 2 sent around 11 bytes, but on the terminal it only shows 2.

For the USART1 on MCU1, I have configured it with the following functions:

/**
 * @brief USART1 Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_USART1_UART_Init(void)
{

    /* USER CODE BEGIN USART1_Init 0 */

    /* USER CODE END USART1_Init 0 */

    /* USER CODE BEGIN USART1_Init 1 */

    /* USER CODE END USART1_Init 1 */
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_9B;
    huart1.Init.StopBits = UART_STOPBITS_2;
    huart1.Init.Parity = UART_PARITY_EVEN;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        Error_Handler();
    }
    /* USER CODE BEGIN USART1_Init 2 */

    /* USER CODE END USART1_Init 2 */
}

 

I tried messing around with the configurations for USART on MCU1, and see what the Logic analyzer outputted, with the following results:

1)
word length: 9B
parity: even
stop bits: 1
baud rate: 115200

Result:
on terminal: no bytes received back for both start and getID commands
logic: got back 0x1F for start and getID commands

2)
word length: 8B
parity: even
stop bits: 1
baud rate: 115200

Result:
on terminal: no bytes received back for both start and getID commands
logic: nothing for start, but get back parity error for responses to getID commands

3)
word length: 8B
parity: even
stop bits: 2
baud rate: 115200

Result:
on terminal: no response to start, but get back 0xFE for responses to getID commands
logic: nothing for start, but get back parity error for responses to getID commands

4)
word length: 9B
parity: even
stop bits: 2
baud rate: 115200

Result:
on terminal: inconsistently correct responses for start and getID commands, and only receive the first few bytes for response to getID commands
logic: correct responses for start and getID commands

For reference, according to the application notes, the following must be set for USART1 communication with the bootloader:

is45_0-1750677679135.png

 


For all the configurations, my logic analyzer was set to 115200 bits per second, 8 bits per transfer, 1 stop bit, even parity bit.

If I can read a response using configuration 4, shouldn't that mean that commands are correctly being sent from MCU 1, commands are being correctly read by MCU 2, response is being correctly sent from MCU 2, but the response is sometimes incorrectly and sometimes correctly read by MCU 1. Would anyone know how I can fix this?

Thank you!

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

You need to be ready to receive BEFORE the mcu sends data back. If your printf is blocking, this is an issue here.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Super User

You need to be ready to receive BEFORE the mcu sends data back. If your printf is blocking, this is an issue here.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Super User

Between sending the command (line  19) you need to start receive. Where do you do it?

Hi, I do it here, just before the first snippet of code in the original post:

else if (bootType == 'd')
                {
                    //CHANGE THIS
                    uint8_t cmd[10];
                    uint8_t response[1];
                    HAL_UART_DMAStop(uartHandleComm);

                    __HAL_UART_CLEAR_OREFLAG(uartHandleComm);
                    __HAL_UART_CLEAR_FEFLAG(uartHandleComm);
                    __HAL_UART_CLEAR_NEFLAG(uartHandleComm);

                    while (__HAL_UART_GET_FLAG(uartHandleComm, UART_FLAG_RXNE)) {
                        volatile uint8_t dummy = uartHandleComm->Instance->RDR;
                    }

                    if (HAL_UART_Receive_DMA(uartHandleComm, response, sizeof(response)) != HAL_OK)
                    {
                        printf("Error: Failed to initialize UART receive DMA.\r\n");
                    }

                    printf("Protocol initialized\r\n");
                    rxComplete = 0;

                    printf("cmd: ");
                    while (1)
                    {

 

What I was doing was receive one byte, print it, then re-arm the DMA to receive and print the second byte.

However, based on what @TDK mentioned, I am modifying the DMA to receive more bytes at once. I originally only wanted it to receive it only one byte at a time, since I wasn't sure how many bytes the response would have.

is45
Associate III

I am not exactly sure if this was the core issue, but removing these printf statements and updating the startTick variable before each rxComplete loop seemed to fix it, thanks!