From 771feb098db86458340ab2665dfb23bef970ace6 Mon Sep 17 00:00:00 2001 From: Fabien Poussin Date: Mon, 15 Feb 2016 23:34:25 +0100 Subject: USB-Host: Initial commit --- testhal/STM32/STM32F4xx/USB_HOST/main.c | 488 ++++++++++++++++++++++++++++++++ 1 file changed, 488 insertions(+) create mode 100644 testhal/STM32/STM32F4xx/USB_HOST/main.c (limited to 'testhal/STM32/STM32F4xx/USB_HOST/main.c') diff --git a/testhal/STM32/STM32F4xx/USB_HOST/main.c b/testhal/STM32/STM32F4xx/USB_HOST/main.c new file mode 100644 index 0000000..bfb318f --- /dev/null +++ b/testhal/STM32/STM32F4xx/USB_HOST/main.c @@ -0,0 +1,488 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "ch.h" +#include "hal.h" +#include "ff.h" +#include "usbh.h" +#include + + + +#if HAL_USBH_USE_FTDI +#include "usbh/dev/ftdi.h" +#include "test.h" +#include "shell.h" +#include "chprintf.h" + +static THD_WORKING_AREA(waTestFTDI, 1024); + +#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048) +#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256) + +static uint8_t buf[] = + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + +static void cmd_mem(BaseSequentialStream *chp, int argc, char *argv[]) { + size_t n, size; + + (void)argv; + if (argc > 0) { + chprintf(chp, "Usage: mem\r\n"); + return; + } + n = chHeapStatus(NULL, &size); + chprintf(chp, "core free memory : %u bytes\r\n", chCoreGetStatusX()); + chprintf(chp, "heap fragments : %u\r\n", n); + chprintf(chp, "heap free total : %u bytes\r\n", size); +} + +static void cmd_threads(BaseSequentialStream *chp, int argc, char *argv[]) { + static const char *states[] = {CH_STATE_NAMES}; + thread_t *tp; + + (void)argv; + if (argc > 0) { + chprintf(chp, "Usage: threads\r\n"); + return; + } + chprintf(chp, " addr stack prio refs state\r\n"); + tp = chRegFirstThread(); + do { + chprintf(chp, "%08lx %08lx %4lu %4lu %9s\r\n", + (uint32_t)tp, (uint32_t)tp->p_ctx.r13, + (uint32_t)tp->p_prio, (uint32_t)(tp->p_refs - 1), + states[tp->p_state]); + tp = chRegNextThread(tp); + } while (tp != NULL); +} + +static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) { + thread_t *tp; + + (void)argv; + if (argc > 0) { + chprintf(chp, "Usage: test\r\n"); + return; + } + tp = chThdCreateFromHeap(NULL, TEST_WA_SIZE, chThdGetPriorityX(), + TestThread, chp); + if (tp == NULL) { + chprintf(chp, "out of memory\r\n"); + return; + } + chThdWait(tp); +} + +static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) { + + (void)argv; + if (argc > 0) { + chprintf(chp, "Usage: write\r\n"); + return; + } + + while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) != Q_TIMEOUT) { + //flush + } + + while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) { + chSequentialStreamWrite(&FTDIPD[0], buf, sizeof buf - 1); + } + chprintf(chp, "\r\n\nstopped\r\n"); +} + +static const ShellCommand commands[] = { + {"mem", cmd_mem}, + {"threads", cmd_threads}, + {"test", cmd_test}, + {"write", cmd_write}, + {NULL, NULL} +}; + +static const ShellConfig shell_cfg1 = { + (BaseSequentialStream *)&FTDIPD[0], + commands +}; + +static void ThreadTestFTDI(void *p) { + (void)p; + USBHFTDIPortDriver *const ftdipp = &FTDIPD[0]; + + shellInit(); + +start: + while (ftdipp->state != USBHFTDIP_STATE_ACTIVE) { + chThdSleepMilliseconds(100); + } + + usbDbgPuts("FTDI: Connected"); + + USBHFTDIPortConfig config = { + 115200, + USBHFTDI_FRAMING_DATABITS_8 | USBHFTDI_FRAMING_PARITY_NONE | USBHFTDI_FRAMING_STOP_BITS_1, + USBHFTDI_HANDSHAKE_NONE, + 0, + 0 + }; + + usbhftdipStart(ftdipp, &config); + + //loopback + if (0) { + for(;;) { + msg_t m = chSequentialStreamGet(ftdipp); + if (m < MSG_OK) { + usbDbgPuts("FTDI: Disconnected"); + goto start; + } + chSequentialStreamPut(ftdipp, (uint8_t)m); + if (m == 'q') + break; + } + } + + //shell test + if (1) { + thread_t *shelltp = NULL; + for(;;) { + if (ftdipp->state != USBHFTDIP_STATE_READY) + goto start; + if (!shelltp) { + shelltp = shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO); + } else if (chThdTerminatedX(shelltp)) { + chThdRelease(shelltp); + if (ftdipp->state != USBHFTDIP_STATE_READY) + goto start; + break; + } + chThdSleepMilliseconds(100); + } + } + + //FTDI uart RX to debug TX bridge + if (0) { + for(;;) { + msg_t m = chSequentialStreamGet(ftdipp); + if (m < MSG_OK) { + usbDbgPuts("FTDI: Disconnected"); + goto start; + } + sdPut(&USBH_DEBUG_SD, (uint8_t)m); + if (m == 'q') + break; + } + } + + //write speed test + if (1) { + usbhftdipStop(ftdipp); + config.speed = 3000000; + usbhftdipStart(ftdipp, &config); + + systime_t st, et; + int i; + for (i = 0; i < 5; i++) { + uint32_t bytes = config.speed / 10; + uint32_t times = bytes / 1024; + st = chVTGetSystemTimeX(); + while (times--) { + if (chSequentialStreamWrite(ftdipp, buf, 1024) < 1024) { + usbDbgPuts("FTDI: Disconnected"); + goto start; + } + bytes -= 1024; + } + if (bytes) { + if (chSequentialStreamWrite(ftdipp, buf, bytes) < bytes) { + usbDbgPuts("FTDI: Disconnected"); + goto start; + } + } + et = chVTGetSystemTimeX(); + usbDbgPrintf("\tRate=%uB/s", (config.speed * 100) / (et - st)); + } + } + + //single character write test (tests the timer) + if (0) { + for (;;) { + if (chSequentialStreamPut(ftdipp, 'A') != MSG_OK) { + usbDbgPuts("FTDI: Disconnected"); + goto start; + } + chThdSleepMilliseconds(100); + } + } + + usbhftdipStop(ftdipp); + + usbDbgPuts("FTDI: Tests done, restarting in 3s"); + chThdSleepMilliseconds(3000); + + goto start; +} +#endif + + + +#if HAL_USBH_USE_MSD +#include "usbh/dev/msd.h" +#include "ff.h" + +static FATFS MSDLUN0FS; +static uint8_t fbuff[10240]; +static FIL file; + +static FRESULT scan_files(BaseSequentialStream *chp, char *path) { + FRESULT res; + FILINFO fno; + DIR dir; + int i; + char *fn; + +#if _USE_LFN + fno.lfname = 0; + fno.lfsize = 0; +#endif + res = f_opendir(&dir, path); + if (res == FR_OK) { + i = strlen(path); + for (;;) { + res = f_readdir(&dir, &fno); + if (res != FR_OK || fno.fname[0] == 0) + break; + if (fno.fname[0] == '.') + continue; + fn = fno.fname; + if (fno.fattrib & AM_DIR) { + path[i++] = '/'; + strcpy(&path[i], fn); + res = scan_files(chp, path); + if (res != FR_OK) + break; + path[--i] = 0; + } else { + usbDbgPrintf("FS: %s/%s", path, fn); + } + } + } + return res; +} +static THD_WORKING_AREA(waTestMSD, 1024); +static void ThreadTestMSD(void *p) { + (void)p; + + FATFS *fsp; + uint32_t clusters; + FRESULT res; + BaseSequentialStream * const chp = (BaseSequentialStream *)&USBH_DEBUG_SD; + blkstate_t state; + systime_t st, et; + uint32_t j; + +start: + for(;;) { + chThdSleepMilliseconds(100); + + chSysLock(); + state = blkGetDriverState(&MSBLKD[0]); + chSysUnlock(); + if (state != BLK_READY) + continue; + + //raw read test + if (1) { +#define RAW_READ_SZ_MB 1 +#define NBLOCKS (sizeof(fbuff) / 512) +#define NITERATIONS ((RAW_READ_SZ_MB * 1024UL * 1024UL) / sizeof(fbuff)) + uint32_t start = 0; + chThdSetPriority(HIGHPRIO); + usbDbgPrintf("BLK: Raw read test (%dMB, %dB blocks)", RAW_READ_SZ_MB, sizeof(fbuff)); + st = chVTGetSystemTime(); + for (j = 0; j < NITERATIONS; j++) { + blkRead(&MSBLKD[0], start, fbuff, NBLOCKS); + start += NBLOCKS; + } + et = chVTGetSystemTime(); + usbDbgPrintf("BLK: Raw read in %d ms, %dkB/s", + et - st, + (RAW_READ_SZ_MB * 1024UL * 1000) / (et - st)); + chThdSetPriority(NORMALPRIO); + } + + usbDbgPuts("FS: Block driver ready, try mount..."); + + res = f_mount(&MSDLUN0FS, "0:", 1); + if (res != FR_OK) { + usbDbgPuts("FS: Can't mount. Check file system."); + continue; + } + usbDbgPuts("FS: Mounted."); + + res = f_getfree("0:", &clusters, &fsp); + if (res != FR_OK) { + usbDbgPuts("FS: f_getfree() failed"); + continue; + } + + usbDbgPrintf("FS: %lu free clusters, %lu sectors per cluster, %lu bytes free", + clusters, (uint32_t)MSDLUN0FS.csize, + clusters * (uint32_t)MSDLUN0FS.csize * MSBLKD[0].info.blk_size); + + break; + } + + //FATFS test + if (1) { + UINT bw; + const uint8_t *src; + const uint8_t *const start = (uint8_t *)0x08000000; + const uint8_t *const top = (uint8_t *)0x08020000; + + //write test + if (1) { + usbDbgPuts("FS: Write test (create file /test.dat, 1MB)"); + f_open(&file, "/test.dat", FA_CREATE_ALWAYS | FA_WRITE); + src = start; + st = chVTGetSystemTime(); + for (j = 0; j < 2048; j++) { + if (f_write(&file, src, 512, &bw) != FR_OK) + goto start; + src += bw; + if (src >= top) + src = start; + } + et = chVTGetSystemTime(); + usbDbgPrintf("FS: Written 1MB in %d ms, %dkB/s", + et - st, + (1024UL*1000) / (et - st)); + f_close(&file); + } + + //read test + if (1) { + usbDbgPuts("FS: Read test (read file /test.dat, 1MB, compare)"); + f_open(&file, "/test.dat", FA_READ); + src = start; + st = chVTGetSystemTime(); + for (j = 0; j < 2048; j++) { + if (f_read(&file, fbuff, 512, &bw) != FR_OK) + goto start; + if (memcmp(src, fbuff, bw)) { + usbDbgPrintf("Compare error @%08x", (uint32_t)src); + goto start; + } + src += bw; + if (src >= top) + src = start; + } + et = chVTGetSystemTime(); + usbDbgPrintf("FS: Read 1MB in %d ms, %dkB/s", + et - st, + (1024UL*1000) / (et - st)); + f_close(&file); + } + + //scan files test + if (1) { + usbDbgPuts("FS: Scan files test"); + fbuff[0] = 0; + scan_files(chp, (char *)fbuff); + } + } + + usbDbgPuts("FS: Tests done, restarting in 3s"); + chThdSleepMilliseconds(3000); + + goto start; + +} +#endif + + + + + + +int main(void) { + + halInit(); + usbhInit(); + chSysInit(); + + //PA2(TX) and PA3(RX) are routed to USART2 + sdStart(&SD2, NULL); + palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7)); + palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7)); + +#if STM32_USBH_USE_OTG1 + //VBUS - configured in board.h + //USB_FS - configured in board.h +#endif + +#if STM32_USBH_USE_OTG2 + //USB_HS + //TODO: Initialize Pads +#endif + +#if HAL_USBH_USE_MSD + usbhmsdObjectInit(&USBHMSD[0]); + usbhmsdLUNObjectInit(&MSBLKD[0]); + chThdCreateStatic(waTestMSD, sizeof(waTestMSD), NORMALPRIO, ThreadTestMSD, 0); +#endif +#if HAL_USBH_USE_FTDI + usbhftdiObjectInit(&USBHFTDID[0]); + usbhftdipObjectInit(&FTDIPD[0]); + chThdCreateStatic(waTestFTDI, sizeof(waTestFTDI), NORMALPRIO, ThreadTestFTDI, 0); +#endif + + //turn on USB power + palClearPad(GPIOC, GPIOC_OTG_FS_POWER_ON); + + //start +#if STM32_USBH_USE_OTG1 + usbhStart(&USBHD1); +#endif +#if STM32_USBH_USE_OTG2 + usbhStart(&USBHD2); +#endif + + for(;;) { +#if STM32_USBH_USE_OTG1 + usbhMainLoop(&USBHD1); +#endif +#if STM32_USBH_USE_OTG2 + usbhMainLoop(&USBHD2); +#endif + chThdSleepMilliseconds(100); + } +} -- cgit v1.2.3