cancel
Showing results for 
Search instead for 
Did you mean: 

Example Selector: FatFs_USBDisk -> FatFs_USBDisk_RTOS

FBerg.1
Associate III

I use NUCLEO-F767Z board and was working on a Application Framework that uses RTOS with different tasks, and logging to serial console and USBDisk. This is quite a while ago (STM32CubeIDE 1.6.1). I couldn't make USBDisk work with RTOS then. I switched to other tasks. But now I want to get back to this.

Now I see, that in STM32CubeIDE there is an example FatFs_USBDisk_RTOS. This might be what I need. But this example can only be selected for other evaluation boards.

Is it possible to port the example FatFs_USBDisk_RTOS to NUCLEO-F767Z for a newbee?

When I download the FatFs_USBDisk_RTOS example for a board which is supported, and look at the sources, then I can see that this is not using the API USBH_Init(), USBH_RegisterClass(), etc, .... - for integration with RTOS.
Therfore, I guess, there is no use trying to adapt and incorporate the FatFs_USBDisk reference into an RTOS project.
Will it be more promising to take FatFs_USBDisk_RTOS from another board and adapt that for NUCLEO-F767Z?

 

12 REPLIES 12
Pavel A.
Evangelist III

>Is it possible to port the example FatFs_USBDisk_RTOS to NUCLEO-F767Z for a newbee?

If the newbee hires a Sherpa for the journey - definitely yes.

 

FBerg.1
Associate III

Let me ask differently:
Can I use the API USBH_Init(), USBH_RegisterClass(), etc, .... in an RTOS project, when I take take, that only a single thread is using this API?

Pavel A.
Evangelist III

Yes, these API should be protected from reentrancy, by calling them from a single thread for example. This is a necessary condition, but not sufficient.

 

FBerg.1
Associate III
  • I created the demo project "FatFs_USBDisk" and tested it - it creates the STM32.TXT on the USB disk (ok).
  • I merged working code for serial console from another project into the "FatFs_USBDisk" demo and tested again:
    • serial console output is successfully generated (ok)
    • but the "FatFs_USBDisk" demo's main() routine calles USBH_Process(...) in a while(1) loop, and that does not return anymore (NOK)

I looked for clashing use of MCU resources and found that both are using GPIO_PIN_8.
The "FatFs_USBDisk" demo defines in Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc.c:

#define MCO1_PIN              GPIO_PIN_8

and uses it in the same file here:

void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* Check the parameters */
  assert_param(IS_RCC_MCO(RCC_MCOx));
  assert_param(IS_RCC_MCODIV(RCC_MCODiv));
  /* RCC_MCO1 */
  if (RCC_MCOx == RCC_MCO1)
  {
    assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));

    /* MCO1 Clock Enable */
    MCO1_CLK_ENABLE();

    /* Configure the MCO1 pin in alternate function mode */
    GPIO_InitStruct.Pin = MCO1_PIN;               /* HERE! */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
    HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);

    /* Mask MCO1 and MCO1PRE[2:0] bits then Select MCO1 clock source and prescaler */
    MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCO1 | RCC_CFGR_MCO1PRE), (RCC_MCOSource | RCC_MCODiv));
  }

My code merged into this example for support of the serial console has added

#define STLK_RX_Pin GPIO_PIN_8

and uses it here:

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART3)
  {
  /* USER CODE BEGIN USART3_MspInit 0 */

  /* USER CODE END USART3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART3_CLK_ENABLE();

    __HAL_RCC_GPIOD_CLK_ENABLE();
    /**USART3 GPIO Configuration
    PD8     ------> USART3_TX
    PD9     ------> USART3_RX
    */
    GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin;      /* HERE! */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* USART3 DMA Init */
    /* USART3_TX Init */
    hdma_usart3_tx.Instance = DMA1_Stream3;
    hdma_usart3_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart3_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart3_tx.Init.Mode = DMA_NORMAL;
    hdma_usart3_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart3_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(huart,hdmatx,hdma_usart3_tx);

    /* USART3 interrupt Init */
    HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART3_IRQn);
  /* USER CODE BEGIN USART3_MspInit 1 */

  /* USER CODE END USART3_MspInit 1 */
  }

}

 

At least I found some clashing of using resources.
Can that be resolved by mapping one or the other to a different MCU resource?
(I don't know, if the wiring on the STM32F767ZI board offers that?!)
Or can USB disk usage and output to serial console not be used in parallel at all?

Pavel A.
Evangelist III

>At least I found some clashing of using resources.

Which resources?

FBerg.1
Associate III

Hi Pavel,

I am talking about both using the same GPIO_PIN_8 - for different purpose.

However, when looking at data sheet

https://www.st.com/resource/en/datasheet/stm32f777bi.pdf

I wonder, if the Initialization for the USB Interface using

 

#define MCO1_PIN              GPIO_PIN_8

 

for

 

    /* Configure the MCO1 pin in alternate function mode */
    GPIO_InitStruct.Pin = MCO1_PIN;               /* HERE! */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
    HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);

 

is correct?

Because the serial console uses the same GPIO_PIN_8

 

#define STLK_RX_Pin GPIO_PIN_8

 

for

 

    GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin;      /* HERE! */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

 

which refers to https://www.st.com/resource/en/datasheet/stm32f777bi.pdf, page #91, Port B, PB11 for AF7.
But on page #91 there is no entry for AF0 (what the USB interface is using.

The MCO1 as AF0 (for the USB interface) is defined on another page #89, but for Port A, PA8.

So a different port, and a different pin.

How can both use #define for GPIO_PIN_8?

GPIO_PIN_8 - on which port ? A, B, C, ... ? every port has a pin no. 8 , yes even more, like pin no. 7 or 9 ...

RTFM .

... at least, a little bit. ok ?

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

Thanks @AScha.3

I was wrong, thinking "GPIO_PIN_8" is using a global enumeration for all GPIO pins.

So my talking about a conflict between USB interface and serial console  because of

 

#define MCO1_PIN              GPIO_PIN_8

 

vs

#define STLK_RX_Pin GPIO_PIN_8

is obsolete.

That's why@Pavel A. asked "Which resource?". But i didn't get it from that.

Thanks!

FBerg.1
Associate III

With that I could debug better, and found out, that within USB_Process(...) for the case HOST_IDLE

  switch (phost->gState)
  {
    case HOST_IDLE :

      if ((phost->device.is_connected) != 0U)
      {
        USBH_UsrLog("USB Device Connected");

        /* Wait for 200 ms after connection */
        phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT;
        USBH_Delay(200U);
        (void)USBH_LL_ResetPort(phost);

        /* Make sure to start with Default address */
        phost->device.address = USBH_ADDRESS_DEFAULT;
        phost->Timeout = 0U;

#if (USBH_USE_OS == 1U)
        phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
        (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
        (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, 0U);
#endif
#endif
      }
      break;

the "USBH_Delay(200u)" is hanging.
USBH_Delay(...) is just a wrapper for HAL_Delay(...). And it's hanging here:

Program received signal SIGINT, Interrupt.
WWDG_IRQHandler () at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/SW4STM32/startup_stm32f767xx.s:110
110       b  Infinite_Loop
bt
#0  WWDG_IRQHandler () at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/SW4STM32/startup_stm32f767xx.s:110
#1  <signal handler called>
#2  HAL_GetTick () at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.c:303
#3  0x08000f84 in HAL_Delay (Delay=Delay@entry=200) at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.c:370
#4  0x08000e00 in USBH_Delay (Delay=Delay@entry=200) at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/Src/usbh_conf.c:451
#5  0x08006032 in USBH_Process (phost=phost@entry=0x20002a54 <hUSBHost>) at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c:499
#6  0x08000a10 in main () at /home/frank/STM32CubeIDE/workspace_1.16.0/FatFs_USBDisk/Src/main.c:164

A default IRQ handler - which uses an endless loop - is in use.
This

1) blocks the main routine (and what it calls)
2) does not increment the uwTick used by HAL_GetTick()

So my use of the serial console broke the interrupt handler, which is used by the USB.

Interestingly, it's not the setup for the serial console, that breaks the interrupt handler for USB.
It's the 1st execution of
HAL_UART_Receive(...) respectively HAL_UART_Transmit_DMA(...) for the serial console, which breaks it.

See the code for merging support for serial console in the working "FatFs_USBDisk" example here: https://github.com/FBergemann/STM32-USBDiskAndConsole
It's the use of TaskConsole_Run() in https://github.com/FBergemann/STM32-USBDiskAndConsole/blob/master/Src/main.c#L161 which breaks the USB interface. ( TaskConsole_Run() is invoking HAL_UART_Receive(...) and HAL_UART_Transmit_DMA(...). Don't wonder about the strange implementation of TaskConsole_Run(). It's taken from an RTOS project, which uses a task for this: https://github.com/FBergemann/STM32-FreeRTOS-Framework)