2025-06-23 4:22 AM
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:
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!
Solved! Go to Solution.
2025-06-23 5:39 AM
You need to be ready to receive BEFORE the mcu sends data back. If your printf is blocking, this is an issue here.
2025-06-23 5:39 AM
You need to be ready to receive BEFORE the mcu sends data back. If your printf is blocking, this is an issue here.
2025-06-23 6:26 AM
Between sending the command (line 19) you need to start receive. Where do you do it?
2025-06-23 6:40 AM - edited 2025-06-23 6:41 AM
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.
2025-06-23 7:09 AM
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!