Продолжим тему программирования обмена данными по шине USB.
Причём поработаем мы с аппаратной шиной USB HS контроллера, скорость которой в 40 раз больше, чем скорость шины USB FS, и составляет 480 мегабит в секунду.
На данный урок меня сподвигла не только высокая скорость обмена, но также и то, что мы, используя протокол HTTP и разрабатывая сервер по данному протоколу, пользуемся виртуальной файловой системой, что накладывает определённые рамки на разработку программ, обусловленные тем, что мы занимаем место во FLASH-памяти контроллера, а также ограничены тем, что память данная не резиновая и поэтому не можем хранить внушительные объёмы данных на нашем сервере. И это ещё не всё. Со времён моих уроков по шине USB прошло очень много времени и поменялась не только библиотека HAL, но ещё и коренным образом поменялась и библиотека FATFS, без которой, как мы все понимаем, практически невозможно организовать хранение данных на сервере в упорядоченном виде.
В качестве подопытной платы мы будем использовать полюбившуюся многим плату STM32F746G-DISCOVERY, с которой мы уже очень много времени успешно и плодотворно работаем, и, надеюсь, ещё много будем работать для того, чтобы средства её оплаты были потрачены недаром. Данная плата в нашем случае хороша не только тем, что на ней установлен мощный микроконтроллер STM32F746NG и удобный дисплей для вывода оперативной информации, но и тем, что на её борту также присутствует микросхема USB3320C-EZK, преобразующая параллельный интерфейс USB HS ULPI в последовательный USB HS PHY, очень хорошо понятный нашей повседневной шине USB, которую мы постоянно используем. А как мы знаем, контроллер не имеет аппаратной шины USB HS PHY ввиду того, что в силу своих аппаратных характеристик он не может разогнаться до скорости передачи данных 480 Mbps. Если вдруг у вас под рукой не окажется подобной платы, то есть и альтернативные способы использования данной шины путём подсоединения к отладочной плате, не имеющей микросхемы-преобразователя, модуля с подобной микросхемой. Для подключения можно воспользоваться схемой подключения данной микросхемы в плате STM32F746G-DISCOVERY
В качестве устройства, которое мы будем подключать по шине USB HS PHY мы возьмём обычный чистый отформатированный в системе FAT32 FLASH-накопитель USB на 8 гигабайт и подключим его с помощью OTG-кабеля USB следующим образом
Как и в предыдущих занятиях по шине USB, мы не будем вдаваться в её аппаратную организацию в контроллере, так как она отнюдь непростая, поэтому поручим эту прерогативу библиотеке HAL и будем пользоваться её функционалом. А если уж что-то не заладится, то тогда и посмотрим Reference Manual.
Поэтому сразу приступим к проекту.
Так как нам пригодится дисплей для вывода некоторой оперативной информации, мы не будем создавать проект с нуля. а воспользуемся одним из наших предыдущих проектов, например, проектом урока 70 по выводу текста на дисплей с именем LTDC_TEXT и назовём его по наименованию урока — USB_HS_HOST_MSC_STANDALONE.
Прежде чем открывать проект в Cube MX, удалим из папки Src все файлы, которые писали не мы, а именно bsp_driver_sd.c, fatfs.c, stm32f7xx_hal_msp.c, stm32f7xx_it.c и system_stm32f7xx.c.
Аналогичным образом из папки Inc удалим файлы main.h, bsp_driver_sd.h, fatfs.h, ffconf.h, stm32f7xx_hal_conf.h и stm32f7xx_it.h.
Делается это в целях избежания ошибок при генерации кода, так как со времён урока 70 прошло очень немало времени и все библиотеки изменились коренным образом.
Откроем проект в проектогенераторе Cube MX, согласимся с миграцией в новую версию и сначала отключим библиотеку FATFS
Затем отключим SDMMC
Отключим RNG
В настройках FMC добавим ещё 2 банка
Включим USB OTG HS
Контакт ULPI DIR переопределим на ножку PC2
Включим USART1, так как основную информацию о ходе нашей программы мы будем всё же получать через данную шину и отображать её в терминальной программе на ПК
Здесь также переопределяем контакт TX на ножку PA9
Включим также USB Host
Также произведём его некоторые настройки
Включим FATFS
Изменим и здесь определённые настройки, так как мы будем работать с длинными именами
Ещё внесём некоторые изменения в настройки CORTEX_M7 в связи с тем, что мы добавили ещё 2 банка SDRAM
Сохраним настройки, сгенерируем проект для System Workbench, несмотря на предупреждение Cub MX по USB_HOST, и откроем его там. Установим уровень оптимизации в 1, а также уберём при наличии отладочные настройки.
Удалим весь код из пользовательской части бесконечного цикла функции main().
Удалим вот эту глобальную переменную структуры
FATFS SDFatFs; /* File system object for SD card logical drive */
Вместо неё добавим указатель на другую структуру
1 2 |
#define LCD_FRAME_BUFFER SDRAM_DEVICE_ADDR FATFS *fs; |
Также удалим данный глобальный массив
extern char SD_Path[4]; /* SD logical drive path */
А в этом массиве уменьшим количество элементов
uint8_t sect[512];
Вот это также удалим
uint32_t bytesread = 0;
uint8_t* bmp1;
uint8_t* dma2d_in1;
uint8_t* dma2d_in2;
А в данном массиве количество элементов добавим
char str1[60];
Функцию OpenBMP удалим вместе с телом.
Вот этот код из функции main() также удалим
/* USER CODE BEGIN 1 */
uint16_t i,j;
bmp1 = (uint8_t *) 0xC00FF000;
//Для файла bmp выделим на всякий случай место как под 32-битный,
//так как хоть рисунок максимум 24-битный, но в файле также
//присутствует служебная информация
dma2d_in1 = (uint8_t *) 0xC017E800;
dma2d_in2 = (uint8_t *) 0xC01FE000;
/* USER CODE END 1 */
И вот это тоже удалим
if(f_mount(&SDFatFs, (TCHAR const*)SD_Path, 0) != FR_OK)
{
TFT_FillScreen(0xFF00FF00); //в случае неудачи окрасим экран в красный цвет
Error_Handler();
}
//Копируем содержимое файла последнего рисунка в область памяти bmp1
OpenBMP((uint8_t *)bmp1,«image01.bmp»);
//Подготовим рисунок во втором входном буфере видеоускорителя DMA2D
TFT_DrawBitmapToMem(0,0,(uint8_t *)bmp1,(uint8_t *)dma2d_in2);
Зададим шрифт
1 2 3 |
TFT_FillScreen(LCD_COLOR_BLACK); TFT_SetFont(&Font24); TFT_SetTextColor(LCD_COLOR_LIGHTGREEN); |
Экспортируем глобальную переменную состояния программы
1 2 |
#define LCD_FRAME_BUFFER SDRAM_DEVICE_ADDR extern ApplicationTypeDef Appli_state; |
Добавим перечисление и создадим неоптимизируемую переменную его типа для хранения состояния программы, но уже нашего — пользовательского
1 2 3 4 5 6 7 8 9 |
FIL MyFile; /* File object */ typedef enum { MSC_APP_START = 0, MSC_APP_FILE_OPERATIONS, MSC_APP_END, MSC_APP_IDLE, } MSC_APP_State; __IO MSC_APP_State state; |
Также создадим глобальный массив для хранения имени файла
1 2 |
__IO MSC_APP_State state; char fn[30] = {0}; |
В функции main() произведём начальную настройку состояния программы, а также зададим первоначальное имя файла
1 2 3 |
TFT_SetTextColor(LCD_COLOR_LIGHTGREEN); strcpy(fn,"USBHost.txt"); state = MSC_APP_IDLE; |
Также напишем шапку на экране дисплея и после этого изменим цвет текста
1 2 3 |
TFT_SetTextColor(LCD_COLOR_LIGHTGREEN); TFT_DisplayString(0, 10, (uint8_t *)"USB HS HOST MSC STANDALONE", CENTER_MODE); TFT_SetTextColor(LCD_COLOR_LIGHTBLUE); |
Добавим пока пустотелую функцию обработки состояний программы
1 2 3 4 |
/* USER CODE BEGIN 0 */ void ApplicationProcess(void) { } |
Вызовем её в бесконечном цикле функции main()
1 2 |
/* USER CODE BEGIN 3 */ ApplicationProcess(); |
Перейдём в файл usb_host.c и подключим там библиотеку FATFS
1 2 |
/* USER CODE BEGIN Includes */ #include "fatfs.h" |
Также подключим там массив пути и переменную структуры для файловой системы
1 2 3 4 |
/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ extern char USBHPath[4]; extern FATFS USBHFatFS; |
В функции USBH_UserProcess вставим данный код в следующий кейс, чтобы при отсоединении устройства у нас отмонтировалась файловая система
1 2 3 4 |
case HOST_USER_DISCONNECTION: Appli_state = APPLICATION_DISCONNECT; f_mount(NULL, "", 0); FATFS_UnLinkDriver(USBHPath); |
И, наоборот в следующем кейсе мы её примонтируем
1 2 3 |
case HOST_USER_CONNECTION: FATFS_LinkDriver(&USBH_Driver, USBHPath); f_mount(&USBHFatFS, (TCHAR const*) USBHPath, 0); |
Вернёмся в main.c и в функции обработаем условие отключения
1 2 3 4 5 6 7 8 9 10 11 |
void ApplicationProcess(void) { if (Appli_state == APPLICATION_DISCONNECT) { TFT_DisplayString(10, 40, (uint8_t *)"Stop ", LEFT_MODE); sprintf(str1,"USB-Drive is unmounted\r\n"); HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000); Appli_state = APPLICATION_IDLE; state = MSC_APP_IDLE; } } |
В этой же функции выше добавим оператор вариантов для состояния нашей программы и обработаем некоторые из них
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void ApplicationProcess(void) { switch (state) { case MSC_APP_IDLE: state = MSC_APP_START; break; case MSC_APP_START: if (Appli_state == APPLICATION_READY) { state = MSC_APP_FILE_OPERATIONS; TFT_DisplayString(10, 40, (uint8_t *)"Start", LEFT_MODE); } break; case MSC_APP_END: break; default: break; } |
Теперь мы можем собрать код, прошить контроллер и посмотреть, примонтировался ли у нас FLASH-накопитель.
При удачном исходе мы должны получить вот такой результат
Выше добавим ещё одну функцию для работы с файловой системой, в качестве входного аргумента которой будет имя первоначального файла
1 2 3 4 5 |
//-------------------------------------------------------------- void App_File_Operations(char* fname) { } //-------------------------------------------------------------- |
В функции ApplicationProcess обработаем ещё один вариант в котором и вызовем вышедобавленную функцию
1 2 3 4 5 6 7 8 |
case MSC_APP_FILE_OPERATIONS: if (Appli_state == APPLICATION_READY) { App_File_Operations(fn); state = MSC_APP_END; } break; case MSC_APP_END: |
В следующей части урока мы попробуем записать и прочитать файлы, а также получить определённую информацию о файловой системе средствами FATFS.
Предыдущий урок Программирование МК STM32 Следующая часть
Отладочную плату можно приобрести здесь 32F746G-DISCOVERY
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий