Я использую STM32F407 Discovery Board
для взаимодействия с USB OTG FS
. Я использую CubeMx and Keil
для разработки.
Первым делом я включил PC0 - USB_Power (для платы обнаружения) и состояние - RESET для правильной работы USB.
Я включил PA9 - VBUS в качестве входа GPIO.
Моя система работает на частоте 168 МГц.
Использовал MAX_SS (максимальный размер сектора) - 4096 (Эта опция доступна в Cube Mx) .
Включен USB в качестве хоста и используется файловая система FATFS, предоставленная CubeMX.
Enbaled MSC (Mass Storage Class).
КОД:
#include "main.h"
#include "stm32f4xx_hal.h"
#include "fatfs.h"
#include "usb_host.h"
#define GREEN_High HAL_GPIO_WritePin(GREEN_GPIO_Port,GREEN_Pin,GPIO_PIN_SET)
#define GREEN_Low HAL_GPIO_WritePin(GREEN_GPIO_Port,GREEN_Pin,GPIO_PIN_RESET)
#define ORANGE_High HAL_GPIO_WritePin(ORANGE_GPIO_Port,ORANGE_Pin,GPIO_PIN_SET)
#define ORANGE_Low HAL_GPIO_WritePin(ORANGE_GPIO_Port,ORANGE_Pin,GPIO_PIN_RESET)
extern USBH_HandleTypeDef hUsbHostFS;
extern ApplicationTypeDef Appli_state;
FATFS USBDISKFatFs;
FIL MyFile;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void MX_USB_HOST_Process(void);
void Green_Blink(uint16_t ms);
void Orange_Blink(uint16_t ms);
void USB_Write_Demo(char* fileName);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_HOST_Init();
MX_FATFS_Init();
Green_Blink(100);
Orange_Blink(100);
while (1)
{
MX_USB_HOST_Process();
if (Appli_state == APPLICATION_START)
{
USB_Write_Demo("myCSV.csv");
}
*THIS IS THE AREA OF PROBLEM*
// else if (Appli_state == APPLICATION_IDLE)
// {
// GREEN_High;
// ORANGE_High;
// HAL_Delay(100);
// GREEN_Low;
// ORANGE_Low;
// HAL_Delay(100);
// }
}
}
void USB_Write_Demo(char *fileName)
{
FRESULT fres;
uint32_t bytesWritten;
uint8_t w_text[] = {"Hello, I, AM, STM32, Discovery\r\n"};
if (f_mount(&USBDISKFatFs,(TCHAR const*)USBHPath,0) != FR_OK)
{
Orange_Blink(1000);
Error_Handler();
}
else
{
Green_Blink(100);
if (open_append(&MyFile,fileName) != FR_OK)
{
Orange_Blink(100);
Error_Handler();
}
else
{
Green_Blink(100);
fres = f_write(&MyFile,w_text,sizeof(w_text),(void*)bytesWritten);
if (bytesWritten == 0 || fres != FR_OK)
{
Orange_Blink(100);
Error_Handler();
}
else
{
f_close(&MyFile);
Green_Blink(100);
}
}
}
}
void Green_Blink(uint16_t ms)
{
GREEN_High;
HAL_Delay(ms);
GREEN_Low;
HAL_Delay(ms);
}
void Orange_Blink(uint16_t ms)
{
ORANGE_High;
HAL_Delay(ms);
ORANGE_Low;
HAL_Delay(ms);
}
Итак, что здесь происходит: я создаю файл CSV и с каждым циклом добавляю в него новые данные. И мне это действительно удается. Я создал очень длинный (не так уж и 500 КБ) файл csv, используя этот конкретный код.
Но я обнаружил здесь аномалию, которую не могу понять.
Когда я добавляю эту часть в код, файл не создается, и на каждой итерации элемент управления достигает этой функции.
else if (Appli_state == APPLICATION_IDLE)
{
GREEN_High;
ORANGE_High;
HAL_Delay(100);
GREEN_Low;
ORANGE_Low;
HAL_Delay(100);
}
Я не могу понять, как эта функция влияет на рабочий код. Я уверен, что APPLICATION_START
и APPLICATION_IDLE
- две разные вещи. Когда я комментирую эту часть кода, все в порядке, я могу создавать файлы, пока мое хранилище не заканчивается.
Мне потребовалось несколько часов (например, 2 дня), чтобы понять, в чем проблема. Я попытался увеличить минимальный размер кучи - 0x2000 и минимальный размер стека - 0x4000 (эта опция доступна при настройке компоновщика в cubeMx. При создании файла только место, где вы указываете имя проекта, местоположение и все остальное)
Любые предложения будут полезны, так как у меня нет идей.
да, работает. но мне нужно проделать больше работы в этом разделе, поэтому будет много кода и задержек.
и какова логика удаления HAL_Delay()
, и код работает, но если я помещаю HAL_Delay()
, код не работает ??
Прочтите о параллелизме, параллельном программировании и всем остальном, что касается запуска двух заданий на одном процессоре. Ваш процессор должен обслуживать USB-запрос, но в то же время вы запрашиваете, чтобы он завис на 100 миллисекунд. Вам нужно создать два потока, один для обслуживания USB, а другой - для вашей задачи. Функцию MX_USB_HOST_Process()
необходимо вызывать чаще, чем каждые 100 мс. Функция HAL_Delay
- это просто цикл, проверяющий счетчик systick, каждые 1 мс прерываются прерыванием systick для увеличения счетчика
Хорошо, теперь я установил HAL_Dealy()
после этого вызова USB_Write_Demo("myCSV.csv")
, и я моргнул еще одним светодиодом BLUE
внутри другой части, и я обнаружил, что на определенное время Appli_state equals to APPLICATION_IDLE
, а затем все вернулось к нормальному состоянию.
Последняя вещь. Есть ли другой способ кроме RTOS. ?????
Вы можете создать две задачи (FreeRTOS) с помощью CubeMX, отделив USB-файлы от светодиодных. taskLED () и taskUSB ()
Я нашел способ справиться с этой проблемой без использования RTOS. Поскольку я никогда раньше не пробовал RTOS, было сложно завершить проект за несколько дней.
Идея проста. Нам нужно подождать, пока MX_USB_HOST_Process()
не вернет Appli_state
как Idle.
Я не беру на себя ответственность.
Вы можете проверить это ССЫЛКА НА САЙТ
поэтому я добавил новую функцию в usb_host.c
, которая перенастраивает Appli_state
uint8_t IsUSB_Busy(void)
{
return Appli_state;
}
А в main.c
я ждал, пока он не вернет что-нибудь, кроме 0. Как APPLICATION_IDLE=0
typedef enum {
APPLICATION_IDLE = 0,
APPLICATION_START,
APPLICATION_READY,
APPLICATION_DISCONNECT
}ApplicationTypeDef;
Добавлен этот фрагмент кода в основной файл, и все работает, как ожидалось
while (!IsUSB_Busy())
{
MX_USB_HOST_Process();
}
Я надеюсь, что кто-то сочтет это полезным.
И спасибо за вашу помощь.
Можете ли вы удалить
HAL_Delay()
из этого фрагмента и проверить, сохраняется ли проблема?