cancel
Showing results for 
Search instead for 
Did you mean: 

Ymodem UART missing characters on SBSFU port

Arno1
Senior

Hi,

In my port of SBSFU (v2.4.0, not yet 2.5.0) I'm having trouble transferring SFU files over YMODEM due to missing characters at the receiver. This makes it seem the com loader is too slow however it is the same as from the H753 on which it is based.

I've split the logging and ymodem transfers to uart3 (logs) and uart1 (ymodem). Uart1 uses the Arduino header on the STM32H735G-DK board however I have the same issue when just using uart3 with MINICOM_YMODEM defined and using minicom sb.

During transmission I'm not logging anything to avoid slowing down the com loader data reception.

When I use a simple loop that receives 1 character at a time and outputs once a small buffer is full and constantly send data from another STM32H735G-DK to the one with this receive loop, I get all data. But the smallest delay causes data to be missed and I believe this is why the com loader doesn't work.

Any idea how I can avoid missing characters during transmission?

I guess maybe my uart configuration is not right

This is a list of code showing how the uart is configured:

#define SFU_UART_YMODEM                             USART1
#define SFU_UART_YMODEM_CLK_ENABLE()                __HAL_RCC_USART1_CLK_ENABLE()
#define SFU_UART_YMODEM_CLK_DISABLE()               __HAL_RCC_USART1_CLK_DISABLE()
 
#define SFU_UART_YMODEM_TX_AF                       GPIO_AF4_USART1
#define SFU_UART_YMODEM_TX_GPIO_PORT                GPIOB
#define SFU_UART_YMODEM_TX_PIN                      GPIO_PIN_14
#define SFU_UART_YMODEM_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
#define SFU_UART_YMODEM_TX_GPIO_CLK_DISABLE()       __HAL_RCC_GPIOB_CLK_DISABLE()
 
#define SFU_UART_YMODEM_RX_AF                       GPIO_AF4_USART1
#define SFU_UART_YMODEM_RX_GPIO_PORT                GPIOB
#define SFU_UART_YMODEM_RX_PIN                      GPIO_PIN_15
#define SFU_UART_YMODEM_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
#define SFU_UART_YMODEM_RX_GPIO_CLK_DISABLE()       __HAL_RCC_GPIOB_CLK_DISABLE()

Uart handle init:

SFU_ErrorStatus SFU_LL_UART_YMODEM_Init(void)
{
 
    UartYmodemHandle.Instance = USART1;
    UartYmodemHandle.Init.BaudRate = 115200;
    UartYmodemHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartYmodemHandle.Init.StopBits = UART_STOPBITS_1;
    UartYmodemHandle.Init.Parity = UART_PARITY_NONE;
    UartYmodemHandle.Init.Mode = UART_MODE_TX_RX;
    UartYmodemHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartYmodemHandle.Init.OverSampling = UART_OVERSAMPLING_16;
    UartYmodemHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    UartYmodemHandle.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    UartYmodemHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT;
    UartYmodemHandle.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
    if (HAL_UART_Init(&UartYmodemHandle) != HAL_OK)
    {
        return SFU_ERROR;
    }
    return SFU_SUCCESS;
}

This is the clock config:

static void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
    RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
 
    /** Supply configuration update enable
     */
    HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
    /** Configure the main internal regulator output voltage
     */
 
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
 
    while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
    /** Macro to configure the PLL clock source
     */
    __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
    /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
 
    RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 
    RCC_OscInitStruct.PLL.PLLM = 5;
    RCC_OscInitStruct.PLL.PLLN = 110;
    RCC_OscInitStruct.PLL.PLLP = 1;
    RCC_OscInitStruct.PLL.PLLQ = 4;
    RCC_OscInitStruct.PLL.PLLR = 2;
    RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
    RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
    RCC_OscInitStruct.PLL.PLLFRACN = 0;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        Error_Handler();
    }
 
    /** Initializes the CPU, AHB and APB buses clocks
     */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK
        | RCC_CLOCKTYPE_SYSCLK
        | RCC_CLOCKTYPE_PCLK1
        | RCC_CLOCKTYPE_PCLK2
        | RCC_CLOCKTYPE_D3PCLK1
        | RCC_CLOCKTYPE_D1PCLK1;
 
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
    RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
 
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) {
        Error_Handler();
    }
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC
        | RCC_PERIPHCLK_USART3
        | RCC_PERIPHCLK_FDCAN
        | RCC_PERIPHCLK_USART1
        | RCC_PERIPHCLK_RNG
        | RCC_PERIPHCLK_SAI1
        | RCC_PERIPHCLK_ADC
        | RCC_PERIPHCLK_I2C4
        | RCC_PERIPHCLK_USB
        | RCC_PERIPHCLK_OSPI;
    PeriphClkInitStruct.PLL2.PLL2M = 5;
    PeriphClkInitStruct.PLL2.PLL2N = 80;
    PeriphClkInitStruct.PLL2.PLL2P = 5;
    PeriphClkInitStruct.PLL2.PLL2Q = 2;
    PeriphClkInitStruct.PLL2.PLL2R = 2;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
    PeriphClkInitStruct.PLL3.PLL3M = 32;
    PeriphClkInitStruct.PLL3.PLL3N = 129;
    PeriphClkInitStruct.PLL3.PLL3P = 2;
    PeriphClkInitStruct.PLL3.PLL3Q = 2;
    PeriphClkInitStruct.PLL3.PLL3R = 2;
    PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_3;
    PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
    PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    PeriphClkInitStruct.OspiClockSelection = RCC_OSPICLKSOURCE_D1HCLK;
    PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL;
    PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL;
    PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
    PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16910CLKSOURCE_D2PCLK2;
    PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_HSI48;
    PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
    PeriphClkInitStruct.I2c4ClockSelection = RCC_I2C4CLKSOURCE_D3PCLK1;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
        Error_Handler();
    }
    /** Enable USB Voltage detector
     */
    HAL_PWREx_EnableUSBVoltageDetector();
}

And the MSP code:

void SFU_LL_UART_MspInit(UART_HandleTypeDef *huart)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  if (huart->Instance == SFU_UART_YMODEM)
  {
//    /* Peripheral Clock Enable */
    SFU_UART_YMODEM_CLK_ENABLE();
 
    /* GPIO Ports Clock Enable */
    SFU_UART_YMODEM_TX_GPIO_CLK_ENABLE();
    SFU_UART_YMODEM_RX_GPIO_CLK_ENABLE();
 
    /*Configure GPIO pins : SFU_UART_TX_Pin  */
    GPIO_InitStruct.Pin = SFU_UART_YMODEM_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = SFU_UART_YMODEM_TX_AF;
    HAL_GPIO_Init(SFU_UART_YMODEM_TX_GPIO_PORT, &GPIO_InitStruct);
 
    /*Configure GPIO pins : SFU_UART_RX_Pin  */
    GPIO_InitStruct.Pin = SFU_UART_YMODEM_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = SFU_UART_YMODEM_RX_AF;
    HAL_GPIO_Init(SFU_UART_YMODEM_RX_GPIO_PORT, &GPIO_InitStruct);
  } else if (huart->Instance == SFU_UART_LOG)
  {

Thanks for any help.

1 ACCEPTED SOLUTION

Accepted Solutions
Jocelyn RICARD
ST Employee

Hello @Arno​ ,

it seems you are using many peripherals.

Couldn't this issue come from some interrupt handling lasting too long?

If this is the case, you may need to use DMA to transfer Ymodem packets.

Current implementation is quite basic.

Best regards

Jocelyn

View solution in original post

2 REPLIES 2
Jocelyn RICARD
ST Employee

Hello @Arno​ ,

it seems you are using many peripherals.

Couldn't this issue come from some interrupt handling lasting too long?

If this is the case, you may need to use DMA to transfer Ymodem packets.

Current implementation is quite basic.

Best regards

Jocelyn

Hi Jocelyn,

Thanks for the response.

I used the default system clock configuration for the STM32H735G-DK board from CubeMX which is why al those peripherals were enabled. I disabled all peripherals in CubeMX except for those 2 uarts, regenerated and took the system clock configuration from that project into my SBSFU port.

That has indeed allowed me to perform a successful upload over YMODEM from minicom, thank you for your help!

I don't think any of these peripherals need to be enabled as the user app will enable and reconfigure what it needs anyway and there we will use DMA for UARTs. For the bootloader, the simple solution should suffice.