2024-07-12 09:34 AM
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?
2024-07-12 12:18 PM
>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.
2024-07-12 11:20 PM
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?
2024-07-13 02:44 PM
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.
2024-07-17 04:16 AM
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?
2024-07-17 05:42 AM
>At least I found some clashing of using resources.
Which resources?
2024-07-18 10:56 PM
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?
2024-07-18 11:43 PM
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 ?
2024-07-19 12:05 AM
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!
2024-07-20 05:14 AM
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)