/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012,2013 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. ChibiOS/RT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "ch.h" #include "hal.h" #include "shell.h" #include "chprintf.h" #include "ff.h" #define SDC_DATA_DESTRUCTIVE_TEST FALSE #define SDC_BURST_SIZE 8 /* how many sectors reads at once */ static uint8_t outbuf[MMCSD_BLOCK_SIZE * SDC_BURST_SIZE + 1]; static uint8_t inbuf[MMCSD_BLOCK_SIZE * SDC_BURST_SIZE + 1]; /* FS object.*/ static FATFS SDC_FS; /* FS mounted and ready.*/ static bool_t fs_ready = FALSE; /** * @brief Parody of UNIX badblocks program. * * @param[in] start first block to check * @param[in] end last block to check * @param[in] blockatonce number of blocks to check at once * @param[in] pattern check pattern * * @return The operation status. * @retval SDC_SUCCESS operation succeeded, the requested blocks have been * read. * @retval SDC_FAILED operation failed, the state of the buffer is uncertain. */ bool_t badblocks(uint32_t start, uint32_t end, uint32_t blockatonce, uint8_t pattern){ uint32_t position = 0; uint32_t i = 0; chDbgCheck(blockatonce <= SDC_BURST_SIZE, "badblocks"); /* fill control buffer */ for (i=0; i < MMCSD_BLOCK_SIZE * blockatonce; i++) outbuf[i] = pattern; /* fill SD card with pattern. */ position = start; while (position < end){ if (sdcWrite(&SDCD1, position, outbuf, blockatonce)) goto ERROR; position += blockatonce; } /* read and compare. */ position = start; while (position < end){ if (sdcRead(&SDCD1, position, inbuf, blockatonce)) goto ERROR; if (memcmp(inbuf, outbuf, blockatonce * MMCSD_BLOCK_SIZE) != 0) goto ERROR; position += blockatonce; } return FALSE; ERROR: return TRUE; } /** * */ void fillbuffer(uint8_t pattern, uint8_t *b){ uint32_t i = 0; for (i=0; i < MMCSD_BLOCK_SIZE * SDC_BURST_SIZE; i++) b[i] = pattern; } /** * */ void fillbuffers(uint8_t pattern){ fillbuffer(pattern, inbuf); fillbuffer(pattern, outbuf); } /** * */ bool_t sdc_lld_is_write_protected(SDCDriver *sdcp) { (void)sdcp; return FALSE; } /** * */ bool_t sdc_lld_is_card_inserted(SDCDriver *sdcp) { (void)sdcp; return !palReadPad(GPIOE, GPIOE_SDIO_DETECT); } /** * */ void cmd_sdiotest(BaseSequentialStream *chp, int argc, char *argv[]){ (void)argc; (void)argv; uint32_t i = 0; chprintf(chp, "Trying to connect SDIO... "); chThdSleepMilliseconds(100); if (!sdcConnect(&SDCD1)) { chprintf(chp, "OK\r\n"); chprintf(chp, "*** Card CSD content is: "); chprintf(chp, "%X %X %X %X \r\n", (&SDCD1)->csd[3], (&SDCD1)->csd[2], (&SDCD1)->csd[1], (&SDCD1)->csd[0]); chprintf(chp, "Single aligned read..."); chThdSleepMilliseconds(100); if (sdcRead(&SDCD1, 0, inbuf, 1)) chSysHalt(); chprintf(chp, " OK\r\n"); chThdSleepMilliseconds(100); chprintf(chp, "Single unaligned read..."); chThdSleepMilliseconds(100); if (sdcRead(&SDCD1, 0, inbuf + 1, 1)) chSysHalt(); if (sdcRead(&SDCD1, 0, inbuf + 2, 1)) chSysHalt(); if (sdcRead(&SDCD1, 0, inbuf + 3, 1)) chSysHalt(); chprintf(chp, " OK\r\n"); chThdSleepMilliseconds(100); chprintf(chp, "Multiple aligned reads..."); chThdSleepMilliseconds(100); fillbuffers(0x55); /* fill reference buffer from SD card */ if (sdcRead(&SDCD1, 0, inbuf, SDC_BURST_SIZE)) chSysHalt(); for (i=0; i<1000; i++){ if (sdcRead(&SDCD1, 0, outbuf, SDC_BURST_SIZE)) chSysHalt(); if (memcmp(inbuf, outbuf, SDC_BURST_SIZE * MMCSD_BLOCK_SIZE) != 0) chSysHalt(); } chprintf(chp, " OK\r\n"); chThdSleepMilliseconds(100); chprintf(chp, "Multiple unaligned reads..."); chThdSleepMilliseconds(100); fillbuffers(0x55); /* fill reference buffer from SD card */ if (sdcRead(&SDCD1, 0, inbuf + 1, SDC_BURST_SIZE)) chSysHalt(); for (i=0; i<1000; i++){ if (sdcRead(&SDCD1, 0, outbuf + 1, SDC_BURST_SIZE)) chSysHalt(); if (memcmp(inbuf, outbuf, SDC_BURST_SIZE * MMCSD_BLOCK_SIZE) != 0) chSysHalt(); } chprintf(chp, " OK\r\n"); chThdSleepMilliseconds(100); #if SDC_DATA_DESTRUCTIVE_TEST chprintf(chp, "Single aligned write..."); chThdSleepMilliseconds(100); fillbuffer(0xAA, inbuf); if (sdcWrite(&SDCD1, 0, inbuf, 1)) chSysHalt(); fillbuffer(0, outbuf); if (sdcRead(&SDCD1, 0, outbuf, 1)) chSysHalt(); if (memcmp(inbuf, outbuf, MMCSD_BLOCK_SIZE) != 0) chSysHalt(); chprintf(chp, " OK\r\n"); chprintf(chp, "Single unaligned write..."); chThdSleepMilliseconds(100); fillbuffer(0xFF, inbuf); if (sdcWrite(&SDCD1, 0, inbuf+1, 1)) chSysHalt(); fillbuffer(0, outbuf); if (sdcRead(&SDCD1, 0, outbuf+1, 1)) chSysHalt(); if (memcmp(inbuf+1, outbuf+1, MMCSD_BLOCK_SIZE) != 0) chSysHalt(); chprintf(chp, " OK\r\n"); chprintf(chp, "Running badblocks at 0x10000 offset..."); chThdSleepMilliseconds(100); if(badblocks(0x10000, 0x11000, SDC_BURST_SIZE, 0xAA)) chSysHalt(); chprintf(chp, " OK\r\n"); #endif /* !SDC_DATA_DESTRUCTIVE_TEST */ /** * Now perform some FS tests. */ FRESULT err; uint32_t clusters; FATFS *fsp; FIL FileObject; uint32_t bytes_written; uint32_t bytes_read; FILINFO filinfo; uint8_t teststring[] = {"This is test file\r\n"}; chprintf(chp, "Register working area for filesystem... "); chThdSleepMilliseconds(100); err = f_mount(0, &SDC_FS); if (err != FR_OK){ chSysHalt(); } else{ fs_ready = TRUE; chprintf(chp, "OK\r\n"); } #if SDC_DATA_DESTRUCTIVE_TEST chprintf(chp, "Formatting... "); chThdSleepMilliseconds(100); err = f_mkfs (0,0,0); if (err != FR_OK){ chSysHalt(); } else{ chprintf(chp, "OK\r\n"); } #endif /* SDC_DATA_DESTRUCTIVE_TEST */ chprintf(chp, "Mount filesystem... "); chThdSleepMilliseconds(100); err = f_getfree("/", &clusters, &fsp); if (err != FR_OK) { chSysHalt(); } chprintf(chp, "OK\r\n"); chprintf(chp, "FS: %lu free clusters, %lu sectors per cluster, %lu bytes free\r\n", clusters, (uint32_t)SDC_FS.csize, clusters * (uint32_t)SDC_FS.csize * (uint32_t)MMCSD_BLOCK_SIZE); chprintf(chp, "Create file \"chtest.txt\"... "); chThdSleepMilliseconds(100); err = f_open(&FileObject, "0:chtest.txt", FA_WRITE | FA_OPEN_ALWAYS); if (err != FR_OK) { chSysHalt(); } chprintf(chp, "OK\r\n"); chprintf(chp, "Write some data in it... "); chThdSleepMilliseconds(100); err = f_write(&FileObject, teststring, sizeof(teststring), (void *)&bytes_written); if (err != FR_OK) { chSysHalt(); } else chprintf(chp, "OK\r\n"); chprintf(chp, "Close file \"chtest.txt\"... "); err = f_close(&FileObject); if (err != FR_OK) { chSysHalt(); } else chprintf(chp, "OK\r\n"); chprintf(chp, "Check file size \"chtest.txt\"... "); err = f_stat("0:chtest.txt", &filinfo); chThdSleepMilliseconds(100); if (err != FR_OK) { chSysHalt(); } else{ if (filinfo.fsize == sizeof(teststring)) chprintf(chp, "OK\r\n"); else chSysHalt(); } chprintf(chp, "Check file content \"chtest.txt\"... "); err = f_open(&FileObject, "0:chtest.txt", FA_READ | FA_OPEN_EXISTING); chThdSleepMilliseconds(100); if (err != FR_OK) { chSysHalt(); } uint8_t buf[sizeof(teststring)]; err = f_read(&FileObject, buf, sizeof(teststring), (void *)&bytes_read); if (err != FR_OK) { chSysHalt(); } else{ if (memcmp(teststring, buf, sizeof(teststring)) != 0){ chSysHalt(); } else{ chprintf(chp, "OK\r\n"); } } chprintf(chp, "Umount filesystem... "); f_mount(0, NULL); chprintf(chp, "OK\r\n"); chprintf(chp, "Disconnecting from SDIO..."); chThdSleepMilliseconds(100); if (sdcDisconnect(&SDCD1)) chSysHalt(); chprintf(chp, " OK\r\n"); chprintf(chp, "------------------------------------------------------\r\n"); chprintf(chp, "All tests passed successfully.\r\n"); chThdSleepMilliseconds(100); } else{ chSysHalt(); } } /* * SDIO configuration. */ static const SDCConfig sdccfg = { 0 }; /** * */ static SerialConfig ser_cfg = { 115200, 0, 0, 0, }; static const ShellCommand commands[] = { {"sdiotest", cmd_sdiotest}, {NULL, NULL} }; static const ShellConfig shell_cfg1 = { (BaseSequentialStream *)&SD2, commands }; /* * Application entry point. */ int main(void) { halInit(); chSysInit(); /* start debugging serial link */ sdStart(&SD2, &ser_cfg); shellInit(); static WORKING_AREA(waShell, 2048); shellCreateStatic(&shell_cfg1, waShell, sizeof(waShell), NORMALPRIO); /* * Initializes the SDIO drivers. */ sdcStart(&SDCD1, &sdccfg); /* * Normal main() thread activity. * Blinking signaling about successful passing. */ while (TRUE) { palTogglePad(GPIOB, GPIOB_LED_R); chThdSleepMilliseconds(100); } }