También pregunté esto en SE: Stack Overflow
En mi aplicación, he configurado un STM32F4, una tarjeta SD y un USB-CDC (todos con CubeMX). Utilizando una PC, envío comandos al STM32, que luego realiza tareas en la tarjeta SD.
Los comandos se manejan utilizando un "communicationBuffer" (implementado por mí) que espera los comandos a través de USB, UART, ... y establece un indicador cuando se recibe un carácter \n
. El bucle principal sondea este indicador y, si está establecido, un analizador maneja el comando. Hasta ahora, todo bien.
Cuando envío comandos a través de UART, funciona bien y puedo obtener una lista de los archivos en la tarjeta SD o realizar otro acceso a través de FatFs sin ningún problema.
El problema ocurre cuando recibo un comando a través de USB-CDC. El analizador funciona como se esperaba, pero FatFs reclama FR_NO_FILESYSTEM (13)
en f_opendir
.
También otros comandos de FatFs fallan con este código de error.
Después de un comando USB fallido, los comandos a través de UART también fallarán. Parece, como si el USB fallara de alguna manera el controlador de la tarjeta SD inicializado.
¿Alguna idea de cómo puedo resolver este comportamiento?
Implementación de mi USB:
Estoy usando CubeMX y, por lo tanto, uso la forma prescrita para inicializar la interfaz USB-CDC:
main () llama a MX_USB_DEVICE_Init(void)
.
En usbd_conf.c
tengo:
void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(pcdHandle->Instance==USB_OTG_FS)
{
/* USER CODE BEGIN USB_OTG_FS_MspInit 0 */
/* USER CODE END USB_OTG_FS_MspInit 0 */
/**USB_OTG_FS GPIO Configuration
PA11 ------> USB_OTG_FS_DM
PA12 ------> USB_OTG_FS_DP
*/
GPIO_InitStruct.Pin = OTG_FS_DM_Pin|OTG_FS_DP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(OTG_FS_IRQn, 7, 1);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
/* USER CODE BEGIN USB_OTG_FS_MspInit 1 */
/* USER CODE END USB_OTG_FS_MspInit 1 */
}
}
y el proceso de recepción se implementa en usbd_cdc_if.c
de la siguiente manera:
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
mRootObject->mUsbBuffer->fillBuffer(Buf, *Len);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
/* USER CODE END 6 */
}
fillBuffer
se implementa de la siguiente manera (uso la misma implementación para UART y transferencia USB, con instancias separadas para las interfaces respectivas. mBuf
es una variable de instancia de tipo std::vector<char>
):
void commBuf::fillBuffer(uint8_t *buf, size_t len)
{
// Check if last fill has timed out
if(SystemTime::getMS() - lastActionTime > timeout) {
mBuf.clear();
}
lastActionTime = SystemTime::getMS();
// Fill new content
mBuf.insert(mBuf.end(), buf, buf + len);
uint32_t done = 0;
while(!done) {
for(auto i = mBuf.end() - len, ee = mBuf.end(); i != ee; ++i) {
if(*i == '\n') {
newCommand = true;
myCommand = std::string((char*) &mBuf[0],i - mBuf.begin() + 1);
mBuf.erase(mBuf.begin(), mBuf.begin() + (i - mBuf.begin() + 1));
break;
}
}
done = 1;
}
}