From bae22ff5bf8185b7ed2b6d26fb0d8f2c42253cfb Mon Sep 17 00:00:00 2001 From: areviu Date: Thu, 11 Jan 2018 21:41:51 +0000 Subject: [PATCH] update SDMMC driver and added test hal project git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11264 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c | 22 +- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h | 3 +- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c | 229 ++++++- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h | 68 +- .../ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c | 102 +-- .../ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h | 9 - os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c | 307 +++++++++ os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c | 8 +- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c | 3 +- .../ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h | 2 + os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c | 408 +++++++++++- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h | 13 +- os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c | 3 + .../ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h | 75 ++- os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk | 5 +- .../ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h | 7 + .../ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c | 80 +-- .../ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h | 12 +- os/hal/ports/SAMA/SAMA5D2x/platform.mk | 1 + testhal/ATSAMA5D2/SDMMC/.cproject | 58 ++ testhal/ATSAMA5D2/SDMMC/.project | 91 +++ testhal/ATSAMA5D2/SDMMC/Makefile | 256 ++++++++ testhal/ATSAMA5D2/SDMMC/chconf.h | 615 ++++++++++++++++++ .../debug/SAMA5D2-SDMMC (Load and Run).launch | 55 ++ .../debug/SAMA5D2-SDMMC (bootstrap).launch | 55 ++ testhal/ATSAMA5D2/SDMMC/halconf.h | 437 +++++++++++++ testhal/ATSAMA5D2/SDMMC/main.c | 188 ++++++ testhal/ATSAMA5D2/SDMMC/mcuconf.h | 137 ++++ testhal/ATSAMA5D2/SDMMC/readme.txt | 13 + 29 files changed, 3107 insertions(+), 155 deletions(-) create mode 100644 os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c create mode 100644 testhal/ATSAMA5D2/SDMMC/.cproject create mode 100644 testhal/ATSAMA5D2/SDMMC/.project create mode 100644 testhal/ATSAMA5D2/SDMMC/Makefile create mode 100644 testhal/ATSAMA5D2/SDMMC/chconf.h create mode 100644 testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch create mode 100644 testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch create mode 100644 testhal/ATSAMA5D2/SDMMC/halconf.h create mode 100644 testhal/ATSAMA5D2/SDMMC/main.c create mode 100644 testhal/ATSAMA5D2/SDMMC/mcuconf.h create mode 100644 testhal/ATSAMA5D2/SDMMC/readme.txt diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c index 04f2a619e..c47c520af 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c @@ -95,7 +95,8 @@ void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData) uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) { uint64_t mem_size; - uint32_t freq, drv_err, status; + //uint32_t freq; + uint32_t drv_err, status; uint8_t error; bool flag; sSdCard *pSd = &drv->card; @@ -153,7 +154,7 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) if (error) return error; else { - TRACE_1("RCA=%u\n\r",drv->card.wAddress ); + TRACE_DEBUG_1("RCA=%u\n\r",drv->card.wAddress ); } /* SEND_CSD (CMD9) to obtain the Card Specific Data (CSD register), @@ -250,12 +251,14 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) } else { drv->card.wBlockSize = 512; - mem_size = SD_CSD_TOTAL_SIZE(pSd); + mem_size = SD_CSD_TOTAL_SIZE(pSd->CSD); drv->card.dwNbBlocks = (uint32_t)(mem_size >> 9); drv->card.dwTotalSize = mem_size >> 32 ? 0xFFFFFFFF : (uint32_t)mem_size; } +//TO BE DONE +#if 0 /* Automatically select the max device clock frequency */ /* Calculate transfer speed */ freq = SdmmcGetMaxFreq(drv); @@ -266,10 +269,10 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) error = HwSetClock(drv, &freq); drv->card.dwCurrSpeed = freq; if (error != SDMMC_OK && error != SDMMC_CHANGED) { - TRACE_1("clk %s\n\r", SD_StringifyRetCode(error)); + TRACE_ERROR_1("clk %s\n\r", SD_StringifyRetCode(error)); return error; } - +#endif /* Check device status and eat past exceptions, which would otherwise * prevent upcoming data transaction routines from reliably checking * fresh exceptions. */ @@ -277,8 +280,11 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) if (error) return error; status = status & ~STATUS_STATE & ~STATUS_READY_FOR_DATA & ~STATUS_APP_CMD; - //if (status) - // trace_warning("st %lx\n\r", status); + + //warning + if (status) { + TRACE_WARNING_1("st %lx\n\r", status); + } return SDMMC_OK; } @@ -457,7 +463,7 @@ uint8_t SdMmcSelect(SdmmcDriver *drv, uint16_t address, uint8_t statCheck) if (currState == targetState) return 0; if (currState != srcState) { - TRACE_1("st %lx\n\r", currState); + TRACE_ERROR_1("st %lx\n\r", currState); return SDMMC_ERR; } break; diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h index 8b03a8bb8..f675996e4 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.h @@ -171,8 +171,7 @@ extern const uint16_t sdmmcTransUnits[8]; extern const uint8_t sdTransMultipliers[16]; extern const uint8_t mmcTransMultipliers[16]; extern void SdParamReset(sSdCard * pSd); -extern uint32_t SdmmcDecodeTransSpeed(uint32_t code, - const uint16_t * unitCodes, const uint8_t * multiCodes); +extern uint32_t SdmmcDecodeTransSpeed(uint32_t code,const uint16_t * unitCodes, const uint8_t * multiCodes); diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c index 246a9f1ab..2a9b8a529 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c @@ -186,7 +186,7 @@ uint8_t Cmd1(SdmmcDriver *drv, bool * hc) ocr & SD_OCR_VDD_34_35 ? 'X' : '.', ocr & SD_OCR_VDD_35_36 ? 'X' : '.'); #endif - TRACE_1("Device access 0x%lx\n\r", ocr >> 29 & 0x3ul); + TRACE_INFO_1("Device access 0x%lx\n\r", ocr >> 29 & 0x3ul); *hc = (ocr & MMC_OCR_ACCESS_MODE) == MMC_OCR_ACCESS_SECTOR? true : false; @@ -414,6 +414,30 @@ uint8_t Cmd11(SdmmcDriver *drv, uint32_t * pStatus) return bRc; } +/** + * Forces the card to stop transmission + * \param pSd Pointer to a SD card driver instance. + * \param pStatus Pointer to a status variable. + */ +uint8_t Cmd12(SdmmcDriver *drv, uint32_t * pStatus) +{ + sSdmmcCommand *pCmd = &drv->cmd; + uint8_t bRc; + + _ResetCmd(pCmd); + + /* Fill command */ + pCmd->bCmd = 12; + pCmd->cmdOp.wVal = SDMMC_CMD_CSTOP | SDMMC_CMD_bmBUSY; + pCmd->pResp = pStatus; + + drv->timeout_elapsed = -1; + /* Send command */ + bRc = sdmmcSendCmd(drv); + return bRc; +} + + /** * Addressed card sends its status register. * Returns the command transfer result (see SendMciCommand). @@ -466,6 +490,47 @@ uint8_t Cmd14(SdmmcDriver *drv, uint8_t * pData, uint8_t len, uint32_t * pStatus bRc = sdmmcSendCmd(drv); return bRc; } + +/** + * Continously transfers datablocks from card to host until interrupted by a + * STOP_TRANSMISSION command. + * \param pSd Pointer to a SD card driver instance. + * \param nbBlocks Number of blocks to send. + * \param pData Pointer to the buffer to be filled. + * The buffer shall follow the peripheral and DMA alignment requirements. + * \param address Data Address on SD/MMC card. + * \param pStatus Pointer to the response status. + * \param fCallback Pointer to optional callback invoked on command end. + * NULL: Function return until command finished. + * Pointer: Return immediately and invoke callback at end. + * Callback argument is fixed to a pointer to sSdCard instance. + */ +uint8_t Cmd18(SdmmcDriver *drv, + uint16_t * nbBlock, + uint8_t * pData, + uint32_t address, uint32_t * pStatus) +{ + sSdmmcCommand *pCmd = &drv->cmd; + uint8_t bRc; + + _ResetCmd(pCmd); + + /* Fill command */ + pCmd->cmdOp.wVal = SDMMC_CMD_CDATARX(1); + pCmd->bCmd = 18; + pCmd->dwArg = address; + pCmd->pResp = pStatus; + pCmd->wBlockSize = drv->card.wCurrBlockLen; + pCmd->wNbBlocks = *nbBlock; + pCmd->pData = pData; + drv->timeout_elapsed = -1; + /* Send command */ + bRc = sdmmcSendCmd(drv); + if (bRc == SDMMC_CHANGED) + *nbBlock = pCmd->wNbBlocks; + return bRc; +} + /** * A host sends the bus test data pattern to a card. * \param drv Pointer to \ref SdmmcDriver instance. @@ -513,6 +578,152 @@ uint8_t Cmd16(SdmmcDriver *drv, uint16_t blkLen) return bRc; } + +/** + * Read single block command + * \param pSd Pointer to a SD card driver instance. + * \param pData Pointer to the buffer to be filled. + * The buffer shall follow the peripheral and DMA alignment requirements. + * \param address Data Address on SD/MMC card. + * \param pStatus Pointer response buffer as status return. + * \param fCallback Pointer to optional callback invoked on command end. + * NULL: Function return until command finished. + * Pointer: Return immediately and invoke callback at end. + * Callback argument is fixed to a pointer to sSdCard instance. + */ +uint8_t Cmd17(SdmmcDriver *drv, + uint8_t * pData, + uint32_t address, uint32_t * pStatus) +{ + sSdmmcCommand *pCmd = &drv->cmd; + uint8_t bRc; + + _ResetCmd(pCmd); + + /* Fill command */ + pCmd->cmdOp.wVal = SDMMC_CMD_CDATARX(1); + pCmd->bCmd = 17; + pCmd->dwArg = address; + pCmd->pResp = pStatus; + pCmd->wBlockSize =drv->card.wCurrBlockLen; + pCmd->wNbBlocks = 1; + pCmd->pData = pData; + + + drv->timeout_elapsed = -1; + /* Send command */ + bRc = sdmmcSendCmd(drv); + return bRc; +} + + +/** + * Defines the number of blocks (read/write) and the reliable writer parameter + * (write) for a block read or write command + * data (CSD) on the CMD line. + * Returns the command transfer result (see SendMciCommand). + * \param pSd Pointer to a SD card driver instance. + * \param write Write Request parameter. + * \param blocks number of blocks. + */ +uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStatus) +{ + sSdmmcCommand *pCmd = &drv->cmd; + uint8_t bRc; + + _ResetCmd(pCmd); + + /* Fill command */ + pCmd->cmdOp.wVal = SDMMC_CMD_CNODATA(1); + pCmd->bCmd = 23; + pCmd->wNbBlocks = 0; + pCmd->dwArg = write << 31 | blocks; + pCmd->pResp = pStatus; + + drv->timeout_elapsed = -1; + /* Send command */ + bRc = sdmmcSendCmd(drv); + return bRc; +} + +/** + * Write single block command + * \param pSd Pointer to a SD card driver instance. + * \param blockSize Block size (shall be set to 512 in case of high capacity). + * \param pData Pointer to the buffer to be filled. + * The buffer shall follow the peripheral and DMA alignment requirements. + * \param address Data Address on SD/MMC card. + * \param pStatus Pointer to response buffer as status. + * \param fCallback Pointer to optional callback invoked on command end. + * NULL: Function return until command finished. + * Pointer: Return immediately and invoke callback at end. + * Callback argument is fixed to a pointer to sSdCard instance. + */ +uint8_t Cmd24(SdmmcDriver *drv, + uint8_t * pData, + uint32_t address, uint32_t * pStatus) +{ + sSdmmcCommand *pCmd = &drv->cmd; + uint8_t bRc; + + _ResetCmd(pCmd); + + /* Fill command */ + pCmd->cmdOp.wVal = SDMMC_CMD_CDATATX(1); + pCmd->bCmd = 24; + pCmd->dwArg = address; + pCmd->pResp = pStatus; + pCmd->wBlockSize =drv->card.wCurrBlockLen; + pCmd->wNbBlocks = 1; + pCmd->pData = pData; + drv->timeout_elapsed = -1; + /* Send command */ + bRc = sdmmcSendCmd(drv); + return bRc; +} + +/** + * Write multiple block command + * \param pSd Pointer to a SD card driver instance. + * \param blockSize Block size (shall be set to 512 in case of high capacity). + * \param nbBlock Number of blocks to send. + * \param pData Pointer to the buffer to be filled. + * The buffer shall follow the peripheral and DMA alignment requirements. + * \param address Data Address on SD/MMC card. + * \param pStatus Pointer to the response buffer as status. + * \param fCallback Pointer to optional callback invoked on command end. + * NULL: Function return until command finished. + * Pointer: Return immediately and invoke callback at end. + * Callback argument is fixed to a pointer to sSdCard instance. + */ +uint8_t Cmd25(SdmmcDriver *drv, + uint16_t * nbBlock, + uint8_t * pData, + uint32_t address, uint32_t * pStatus) +{ + sSdmmcCommand *pCmd = &drv->cmd; + uint8_t bRc; + + _ResetCmd(pCmd); + + /* Fill command */ + pCmd->cmdOp.wVal = SDMMC_CMD_CDATATX(1); + pCmd->bCmd = 25; + pCmd->dwArg = address; + pCmd->pResp = pStatus; + pCmd->wBlockSize =drv->card.wCurrBlockLen; + pCmd->wNbBlocks = *nbBlock; + pCmd->pData = pData; + + drv->timeout_elapsed = -1; + /* Send command */ + bRc = sdmmcSendCmd(drv); + if (bRc == SDMMC_CHANGED) + *nbBlock = pCmd->wNbBlocks; + return bRc; +} + + /** * SDIO IO_RW_DIRECT command, response R5. * \return the command transfer result (see SendMciCommand). @@ -588,7 +799,7 @@ uint8_t Acmd6(SdmmcDriver *drv, uint8_t busWidth) sSdmmcCommand *pCmd = &drv->cmd; uint8_t error; - TRACE_1("Acmd%u\n\r", 6); + TRACE_INFO_1("Acmd%u\n\r", 6); error = Cmd55(drv, drv->card.wAddress); @@ -603,7 +814,7 @@ uint8_t Acmd6(SdmmcDriver *drv, uint8_t busWidth) } else { if (error) { - TRACE_2("Acmd%u %s\n\r", 6, SD_StringifyRetCode(error)); + TRACE_ERROR_2("Acmd%u %s\n\r", 6, SD_StringifyRetCode(error)); } } return error; @@ -626,7 +837,7 @@ uint8_t Acmd13(SdmmcDriver *drv, uint8_t * pSSR, uint32_t * pResp) //assert(pSd); - TRACE_1("Acmd%u\n\r", 13); + TRACE_INFO_1("Acmd%u\n\r", 13); error = Cmd55(drv, drv->card.wAddress); @@ -647,7 +858,7 @@ uint8_t Acmd13(SdmmcDriver *drv, uint8_t * pSSR, uint32_t * pResp) } else { if (error) { - TRACE_2("Acmd%u %s\n\r", 13, SD_StringifyRetCode(error)); + TRACE_ERROR_2("Acmd%u %s\n\r", 13, SD_StringifyRetCode(error)); } } return error; @@ -713,7 +924,7 @@ uint8_t Acmd41(SdmmcDriver *drv, bool * low_sig_lvl, bool * hc) /* Supply voltage range is incompatible */ rc = SDMMC_BUSY; if (rc != SDMMC_OK) { - TRACE_2("Acmd%u %s\n\r", 41, SD_StringifyRetCode(rc)); + TRACE_ERROR_2("Acmd%u %s\n\r", 41, SD_StringifyRetCode(rc)); } else { #if 0 @@ -761,7 +972,7 @@ uint8_t Acmd51(SdmmcDriver *drv, uint8_t * pSCR, uint32_t * pResp) uint8_t error; - TRACE_1("Acmd%u\n\r", 51); + TRACE_INFO_1("Acmd%u\n\r", 51); error = Cmd55(drv, drv->card.wAddress); @@ -783,7 +994,7 @@ uint8_t Acmd51(SdmmcDriver *drv, uint8_t * pSCR, uint32_t * pResp) } else { if (error) { - TRACE_2("Acmd%u %s\n\r", 51, SD_StringifyRetCode(error)); + TRACE_ERROR_2("Acmd%u %s\n\r", 51, SD_StringifyRetCode(error)); } } return error; @@ -833,7 +1044,7 @@ uint8_t MmcCmd6(SdmmcDriver *drv, const void *pSwitchArg, uint32_t * pResp) bRc = sdmmcSendCmd(drv); if (!bRc && pResp && *pResp & STATUS_MMC_SWITCH) { - TRACE_1("st %lx\n\r", *pResp); + TRACE_INFO_1("st %lx\n\r", *pResp); } return bRc; } diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h index 014986e22..6de912fe8 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.h @@ -103,6 +103,60 @@ typedef struct _SdioCmd52Arg { #define STATUS_ADDRESS_MISALIGN (1UL << 30) #define STATUS_ADDR_OUT_OR_RANGE (1UL << 31) +#define STATUS_STOP ((uint32_t)( STATUS_CARD_IS_LOCKED \ + | STATUS_COM_CRC_ERROR \ + | STATUS_ILLEGAL_COMMAND \ + | STATUS_CC_ERROR \ + | STATUS_ERROR \ + | STATUS_STATE \ + | STATUS_READY_FOR_DATA )) + +#define STATUS_WRITE ((uint32_t)( STATUS_ADDR_OUT_OR_RANGE \ + | STATUS_ADDRESS_MISALIGN \ + | STATUS_BLOCK_LEN_ERROR \ + | STATUS_WP_VIOLATION \ + | STATUS_CARD_IS_LOCKED \ + | STATUS_COM_CRC_ERROR \ + | STATUS_ILLEGAL_COMMAND \ + | STATUS_CC_ERROR \ + | STATUS_ERROR \ + | STATUS_ERASE_RESET \ + | STATUS_STATE \ + | STATUS_READY_FOR_DATA )) + +#define STATUS_READ ((uint32_t)( STATUS_ADDR_OUT_OR_RANGE \ + | STATUS_ADDRESS_MISALIGN \ + | STATUS_BLOCK_LEN_ERROR \ + | STATUS_CARD_IS_LOCKED \ + | STATUS_COM_CRC_ERROR \ + | STATUS_ILLEGAL_COMMAND \ + | STATUS_CARD_ECC_FAILED \ + | STATUS_CC_ERROR \ + | STATUS_ERROR \ + | STATUS_ERASE_RESET \ + | STATUS_STATE \ + | STATUS_READY_FOR_DATA )) + +#define STATUS_SD_SWITCH ((uint32_t)( STATUS_ADDR_OUT_OR_RANGE \ + | STATUS_CARD_IS_LOCKED \ + | STATUS_COM_CRC_ERROR \ + | STATUS_ILLEGAL_COMMAND \ + | STATUS_CARD_ECC_FAILED \ + | STATUS_CC_ERROR \ + | STATUS_ERROR \ + | STATUS_UNERRUN \ + | STATUS_OVERRUN \ + /*| STATUS_STATE*/)) + +#define STATUS_MMC_SWITCH ((uint32_t)( STATUS_CARD_IS_LOCKED \ + | STATUS_COM_CRC_ERROR \ + | STATUS_ILLEGAL_COMMAND \ + | STATUS_CC_ERROR \ + | STATUS_ERROR \ + | STATUS_ERASE_RESET \ + /*| STATUS_STATE*/ \ + /*| STATUS_READY_FOR_DATA*/ \ + | STATUS_SWITCH_ERROR )) #define SD_OCR_S18A (1ul << 24) /**< Switching to 1.8V signaling level Accepted */ #define SDIO_OCR_MP (0x1ul << 27) /**< SDIO: Memory present */ @@ -190,12 +244,24 @@ extern uint8_t Cmd5(SdmmcDriver *drv, uint32_t * pIo); extern uint8_t Cmd7(SdmmcDriver *drv, uint16_t address); extern uint8_t Cmd9(SdmmcDriver *drv); extern uint8_t Cmd11(SdmmcDriver *drv, uint32_t * pStatus); +extern uint8_t Cmd12(SdmmcDriver *drv, uint32_t * pStatus); extern uint8_t Cmd13(SdmmcDriver *drv, uint32_t * pStatus); extern uint8_t Cmd14(SdmmcDriver *drv, uint8_t * pData, uint8_t len, uint32_t * pStatus); extern uint8_t Cmd16(SdmmcDriver *drv, uint16_t blkLen); +extern uint8_t Cmd17(SdmmcDriver *drv, + uint8_t * pData, + uint32_t address, uint32_t * pStatus); +extern uint8_t Cmd18(SdmmcDriver *drv,uint16_t * nbBlock,uint8_t * pData,uint32_t address, uint32_t * pStatus); extern uint8_t Cmd19(SdmmcDriver *drv, uint8_t * pData, uint8_t len, uint32_t * pStatus); - +extern uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStatus); +extern uint8_t Cmd24(SdmmcDriver *drv, + uint8_t * pData, + uint32_t address, uint32_t * pStatus); +extern uint8_t Cmd25(SdmmcDriver *drv, + uint16_t * nbBlock, + uint8_t * pData, + uint32_t address, uint32_t * pStatus); extern uint8_t Cmd52(SdmmcDriver *drv,uint8_t wrFlag,uint8_t funcNb, uint8_t rdAfterWr, uint32_t addr, uint32_t * pIoData); extern uint8_t Cmd55(SdmmcDriver *drv, uint16_t cardAddr); diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c index ca28cc051..8c05bf133 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c @@ -66,13 +66,13 @@ uint8_t sdmmc_device_lowlevelcfg(SdmmcDriver *driver) pmc_set_main_oscillator_freq(BOARD_MAIN_CLOCK_EXT_OSC); - TRACE_1("Processor clock: %u MHz\r\n", ((unsigned)(pmc_get_processor_clock() / 1000000) )); - TRACE_1("Master clock: %u MHz\r\n", ((unsigned)(pmc_get_master_clock() / 1000000)) ); - + TRACE_INFO_1("Processor clock: %u MHz\r\n", ((unsigned)(pmc_get_processor_clock() / 1000000) )); + TRACE_INFO_1("Master clock: %u MHz\r\n", ((unsigned)(pmc_get_master_clock() / 1000000)) ); +#if SDMMC_USE_TC == 1 driver->tctimer_id = get_tc_id_from_addr(driver->config->tctimer,driver->config->tc_chan); pmc_configure_peripheral(driver->tctimer_id, NULL, true); - +#endif if (driver->config->slot_id == SDMMC_SLOT0) { @@ -180,18 +180,17 @@ uint8_t sdmmc_device_lowlevelcfg(SdmmcDriver *driver) if (res) { //check res res = IS_CACHE_ALIGNED(driver->config->data_buf); - TRACE_2("check data buf %d %08x\r\n", res, driver->config->data_buf); + TRACE_DEBUG_2("check data buf %d %08x\r\n", res, driver->config->data_buf); res &= IS_CACHE_ALIGNED(driver->config->data_buf_size); - TRACE_2("check data_buf_size %d %08x\r\n", res, + TRACE_DEBUG_2("check data_buf_size %d %08x\r\n", res, driver->config->data_buf_size); res &= IS_CACHE_ALIGNED(driver->card.EXT); - TRACE_2("check libExt %d %08x\r\n", res, driver->card.EXT); + TRACE_DEBUG_2("check libExt %d %08x\r\n", res, driver->card.EXT); //res &= IS_CACHE_ALIGNED(sizeof(driver->card.EXT)); //TRACE_2("check size libExt %d %08x\r\n",rc,sizeof(driver->card.EXT)); if (!res) { - TRACE( - "WARNING: buffers are not aligned on data cache lines. Please fix this before enabling DMA.\n\r"); + TRACE_WARNING("WARNING: buffers are not aligned on data cache lines. Please fix this before enabling DMA.\n\r"); driver->use_polling = true; } else { driver->use_polling = false; @@ -217,13 +216,11 @@ bool sdmmc_device_initialize(SdmmcDriver *driver) driver->blk_size = (val <= 0x2 ? (512 << val) : 512); //Configure the TC Timer - +#if SDMMC_USE_TC == 1 pmc_configure_peripheral(driver->tctimer_id, NULL, true); - tc_configure(driver->config->tctimer, driver->config->tc_chan, TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_CPCDIS | TC_CMR_BURST_NONE | TC_CMR_TCCLKS_TIMER_CLOCK2); - driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_EMR |= TC_EMR_NODIVCLK; - +#endif /* Perform the initial I/O calibration sequence, manually. * Allow tSTARTUP = 2 usec for the analog circuitry to start up. * CNTVAL = fHCLOCK / (4 * (1 / tSTARTUP)) */ @@ -257,7 +254,7 @@ bool sdmmc_device_initialize(SdmmcDriver *driver) driver->regs->SDMMC_TCR = (driver->regs->SDMMC_TCR & ~SDMMC_TCR_DTCVAL_Msk) | SDMMC_TCR_DTCVAL(exp); - TRACE_1("Set DAT line timeout to %lu ms\n\r", (10UL << (exp + 13UL))/ (base_freq / 100UL)); + TRACE_DEBUG_1("Set DAT line timeout to %lu ms\n\r", (10UL << (exp + 13UL))/ (base_freq / 100UL)); /* Reset the peripheral. This will reset almost all registers. * It doesn't affect I/O calibration however. */ @@ -334,7 +331,7 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv) if (drv->state != MCID_IDLE ) return SDMMC_STATE; - do { + Retry: /* After power-on or CMD0, all cards? * CMD lines are in input mode, waiting for start bit of the next command. * The cards are initialized with a default relative card address @@ -343,7 +340,7 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv) error = SdMmcIdentify(drv); if (error) { - TRACE_1("Identify %s\n\r", SD_StringifyRetCode(error)); + TRACE_ERROR_1("Identify %s\n\r", SD_StringifyRetCode(error)); return error; } @@ -366,12 +363,10 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv) if (!error) { drv->card.bSpeedMode = SDMMC_TIM_SD_SDR12; - //goto Retry; + goto Retry; } } } - - #ifndef SDMMC_TRIM_SDIO else if (drv->card.bCardType & CARD_TYPE_bmSDIO) error = SdioInit(drv); @@ -381,15 +376,14 @@ uint8_t sdmmc_device_identify(SdmmcDriver *drv) error = MmcInit(drv); #endif else { - TRACE_1("Identify %s\n\r", "failed"); + TRACE_ERROR_1("Identify %s\n\r", "failed"); return SDMMC_NOT_INITIALIZED; } if (error) { - TRACE_1("Init %s\n\r", SD_StringifyRetCode(error)); + TRACE_ERROR_1("Init %s\n\r", SD_StringifyRetCode(error)); return error; } - } while (retry==1); drv->card.bStatus = SDMMC_OK; @@ -428,21 +422,32 @@ void sdmmc_device_deInit(SdmmcDriver *drv) Fetch: /* Fetch normal events */ events = regs->SDMMC_NISTR; +#if SDMMC_USE_TC == 1 if (driver->use_polling) { - if (driver->expect_auto_end - + if ( + driver->expect_auto_end && !(driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_SR & TC_SR_CLKSTA) - ) events |= SDMMC_NISTR_CUSTOM_EVT; + + } else { if (driver->expect_auto_end) { while (driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_SR & TC_SR_CLKSTA); - events |= SDMMC_NISTR_CUSTOM_EVT; } } +#else + + if (driver->expect_auto_end) + { + while ( chSysIsCounterWithinX(chSysGetRealtimeCounterX(),driver->start_cycles ,driver->start_cycles+driver->timeout_cycles) ); + events |= SDMMC_NISTR_CUSTOM_EVT; + } + + +#endif if (!events) return; //TRACE_1("events %08x\n\r",events); @@ -661,9 +666,9 @@ void sdmmc_device_deInit(SdmmcDriver *drv) * Counter for this purpose. */ if (has_data && (cmd->bCmd == 18 || cmd->bCmd == 25) && !driver->use_set_blk_cnt) { - +#if SDMMC_USE_TC == 1 driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; - +#endif driver->expect_auto_end = true; //#ifndef NDEBUG // if (!set->cmd_line_released) @@ -734,10 +739,12 @@ void sdmmc_device_deInit(SdmmcDriver *drv) && cmd->dwArg & 1ul << 31 && !cmd->cmdOp.bmBits.checkBsy)) { /* Currently in the function switching period, wait for the * delay preconfigured in sdmmc_send_command(). */ - +#if SDMMC_USE_TC == 1 driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; while (driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_SR & TC_SR_CLKSTA) ; - +#else + while ( chSysIsCounterWithinX(chSysGetRealtimeCounterX(),driver->start_cycles ,driver->start_cycles+driver->timeout_cycles) ); +#endif } /* Release this command */ @@ -878,14 +885,16 @@ void sdmmc_device_deInit(SdmmcDriver *drv) uint32_t eister; uint32_t mask; uint32_t len; +#if SDMMC_USE_TC == 1 uint32_t cycles; +#endif uint16_t cr; uint16_t tmr; uint8_t mc1r; uint8_t rc = SDMMC_OK; - //TRACE_1("[command] start %d\r\n",driver->cmd.bCmd); + TRACE_DEBUG_1("[command] start %d\r\n",driver->cmd.bCmd); if (driver->state == MCID_OFF) return SDMMC_STATE; @@ -962,7 +971,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) driver->dat_lines_released = false; driver->expect_auto_end = false; driver->cmd.bStatus = rc; - //TRACE_1("command set status %d\r\n",driver->cmd.bStatus); + TRACE_DEBUG_1("command set status %d\r\n",driver->cmd.bStatus); tmr = (regs->SDMMC_TMR & ~SDMMC_TMR_MSBSEL & ~SDMMC_TMR_DTDSEL & ~SDMMC_TMR_ACMDEN_Msk & ~SDMMC_TMR_BCEN & ~SDMMC_TMR_DMAEN) @@ -1101,12 +1110,16 @@ void sdmmc_device_deInit(SdmmcDriver *drv) * bits, hence 48 device clock cycles. * The sum of the above timings is the maximum time CMD12 will * take to complete. */ - +#if SDMMC_USE_TC == 1 cycles = pmc_get_peripheral_clock(driver->tctimer_id) / (driver->dev_freq / (2ul + 64ul + 48ul)); - //TRACE_1("[command] has_data wait %d cycles\r\n",cycles); + TRACE_DEBUG_1("[command] has_data wait %d cycles\r\n",cycles); /* The Timer operates with RC >= 1 */ driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_RC = max_u32(cycles, 1); +#else + driver->timeout_cycles = 2+64+48; + driver->start_cycles = chSysGetRealtimeCounterX(); +#endif } /* With SD devices, the 8-cycle function switching period will apply, @@ -1114,18 +1127,21 @@ void sdmmc_device_deInit(SdmmcDriver *drv) * Note that MMC devices don't require this fixed delay, but regarding * GO_IDLE_STATE we have no mean to filter the MMC requests out. */ else if (wait_switch) { - +#if SDMMC_USE_TC == 1 cycles = pmc_get_peripheral_clock(driver->tctimer_id) / (driver->dev_freq / 8ul); - //TRACE_1("[command] wait_switch %d cycles\r\n",cycles); + TRACE_DEBUG_1("[command] wait_switch %d cycles\r\n",cycles); driver->config->tctimer->TC_CHANNEL[driver->config->tc_chan].TC_RC = max_u32(cycles, 1); - +#else + driver->timeout_ticks = 8; + driver->start_cycles = chSysGetRealtimeCounterX(); +#endif } if (!driver->use_polling) { regs->SDMMC_NISIER |= SDMMC_NISIER_BRDRDY | SDMMC_NISIER_BWRRDY | SDMMC_NISIER_TRFC | SDMMC_NISIER_CMDC | SDMMC_NISIER_CINT; regs->SDMMC_EISIER = eister; } - //TRACE_1("[command] finish %d OK\r\n",driver->cmd.bCmd); + TRACE_DEBUG_1("[command] finish %d OK\r\n",driver->cmd.bCmd); return SDMMC_OK; } @@ -1150,7 +1166,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) //#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG if (bCtl != SDMMC_IOCTL_BUSY_CHECK && bCtl != SDMMC_IOCTL_GET_DEVICE) { - TRACE_2("SDMMC_IOCTL_%s(%lu)\n\r", SD_StringifyIOCtrl(bCtl),driver->control_param ); + TRACE_DEBUG_2("SDMMC_IOCTL_%s(%lu)\n\r", SD_StringifyIOCtrl(bCtl),driver->control_param ); } //#endif @@ -1217,7 +1233,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) if (driver->control_param > 0xff) return SDMMC_PARAM; rc = sdmmc_set_bus_width(driver, driver->control_param); - TRACE_1("Using a %u-bit data bus\n\r", sdmmc_get_bus_width(driver)); + TRACE_DEBUG_1("Using a %u-bit data bus\n\r", sdmmc_get_bus_width(driver)); break; case SDMMC_IOCTL_GET_HSMODE: @@ -1283,7 +1299,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) sdmmc_set_device_clock(driver, driver->control_param); - TRACE_1("Clocking the device at %lu Hz\n\r", driver->dev_freq); + TRACE_DEBUG_1("Clocking the device at %lu Hz\n\r", driver->dev_freq); if (driver->dev_freq > 95000000ul && (driver->tim_mode == SDMMC_TIM_MMC_HS200 || driver->tim_mode == SDMMC_TIM_SD_SDR104 @@ -1345,7 +1361,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) //#if TRACE_LEVEL >= TRACE_LEVEL_ERROR if (rc != SDMMC_OK && rc != SDMMC_CHANGED && bCtl != SDMMC_IOCTL_BUSY_CHECK) { - TRACE_2("SDMMC_IOCTL_%s ended with %s\n\r",SD_StringifyIOCtrl(bCtl), SD_StringifyRetCode(rc)); + TRACE_ERROR_2("SDMMC_IOCTL_%s ended with %s\n\r",SD_StringifyIOCtrl(bCtl), SD_StringifyRetCode(rc)); } //#endif return rc; @@ -1988,7 +2004,7 @@ static uint8_t sdmmc_set_bus_width(SdmmcDriver *driver, uint8_t bits) *pIoValClk = drv->control_param; - TRACE_1("Device clk %lu kHz\n\r", drv->control_param / 1000UL); + TRACE_DEBUG_1("Device clk %lu kHz\n\r", drv->control_param / 1000UL); } return rc; } diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h index ebe0da07d..340feb172 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h @@ -350,15 +350,6 @@ or not by mechanical write protect switch */ -#define STATUS_MMC_SWITCH ((uint32_t)( STATUS_CARD_IS_LOCKED \ - | STATUS_COM_CRC_ERROR \ - | STATUS_ILLEGAL_COMMAND \ - | STATUS_CC_ERROR \ - | STATUS_ERROR \ - | STATUS_ERASE_RESET \ - /*| STATUS_STATE*/ \ - /*| STATUS_READY_FOR_DATA*/ \ - | STATUS_SWITCH_ERROR )) #define t_usleep(d,t) sdmmc_device_sleep(d,t,2) #define t_msleep(d,t) sdmmc_device_sleep(d,t,1) diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c new file mode 100644 index 000000000..49b667bd7 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c @@ -0,0 +1,307 @@ +/* ---------------------------------------------------------------------------- + * SAM Software Package License + * ---------------------------------------------------------------------------- + * Copyright (c) 2015, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------------------- + * This file is based on the template source file named diskio.c, + * part of the FatFs Module R0.10b: + * Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 + * If a working storage control module is available, it should be + * attached to the FatFs via a glue function rather than modifying it. + * This is an example of glue functions to attach various existing + * storage control modules to the FatFs module with a defined API. + * ---------------------------------------------------------------------------- + */ + +#include "hal.h" +#include "ccportab.h" +#include "ffconf.h" +#include "diskio.h" + +#include +#include "sama_sdmmc_lld.h" +#include "ch_sdmmc_device.h" +#include "ch_sdmmc_sd.h" +#include "ch_sdmmc_sdio.h" +#include "ch_sdmmc_trace.h" +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** + * \brief Access the SD/MMC Library instances owned by the application. + * Used upon calls from the FatFs Module. + * + * Shall be implemented by the application. + */ +extern bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) ; + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initialize a Drive. + * \param slot Physical drive number (0..). + * \return Drive status flags; STA_NOINIT if the specified drive does not exist. + */ +DSTATUS disk_initialize(BYTE slot) +{ + SdmmcDriver *sdmmcp = NULL; + uint8_t rc; + + if (!sdmmcGetInstance(slot, &sdmmcp)) + return STA_NOINIT; + + + rc = SD_GetStatus(sdmmcp); + + if (rc == SDMMC_NOT_SUPPORTED) + return STA_NODISK | STA_NOINIT; +#if 0 + if (sdmmcp->state != MCID_IDLE ) + sdmmc_device_deInit(sdmmcp); + + /* FIXME a delay with the bus held off may be required by the device */ + rc = sdmmc_device_start(sdmmcp); + + if (rc == SDMMC_OK) { + rc = sdmmc_device_identify(sdmmcp); + } +#endif + + return rc == SDMMC_OK ? 0 : STA_NOINIT; +} + +/** + * \brief Get Drive Status. + * \param slot Physical drive number (0..). + * \return Drive status flags; STA_NODISK if there is currently no device in + * the specified slot. + */ +DSTATUS disk_status(BYTE slot) +{ + SdmmcDriver *sdmmcp = NULL; + uint8_t rc; + + if (!sdmmcGetInstance(slot, &sdmmcp)) + return STA_NODISK | STA_NOINIT; + + rc = SD_GetStatus(sdmmcp); + + if (rc == SDMMC_NOT_SUPPORTED) + return STA_NODISK | STA_NOINIT; + else if (rc != SDMMC_OK) + return STA_NOINIT; + /* Well, no restriction on this drive */ + return 0; +} + +/** + * \brief Read Sector(s). + * \param slot Physical drive number (0..). + * \param buff Data buffer to store read data. + * \param sector Sector address in LBA. + * \param count Number of sectors to read. + * \return Result code; RES_OK if successful. + */ +DRESULT disk_read(BYTE slot, BYTE* buff, DWORD sector, UINT count) +{ + SdmmcDriver *sdmmcp = NULL; + DRESULT res; + uint32_t blk_size, addr = sector, len = count; + uint8_t rc; + + if (!sdmmcGetInstance(slot, &sdmmcp)) + return RES_PARERR; + + blk_size = sdmmcp->card.wBlockSize; + + if (blk_size == 0) + return RES_NOTRDY; + + if (blk_size < FF_MIN_SS) { + if (FF_MIN_SS % blk_size) + return RES_PARERR; + addr = sector * (FF_MIN_SS / blk_size); + len = count * (FF_MIN_SS / blk_size); + } + + if (count <= 1) + rc = SD_ReadBlocks(sdmmcp, addr, buff, len); + else + rc = SD_Read(sdmmcp, addr, buff, len); + + if (rc == SDMMC_OK || rc == SDMMC_CHANGED) + res = RES_OK; + else if (rc == SDMMC_ERR_IO || rc == SDMMC_ERR_RESP || rc == SDMMC_ERR) + res = RES_ERROR; + else if (rc == SDMMC_NO_RESPONSE || rc == SDMMC_BUSY + || rc == SDMMC_NOT_INITIALIZED || rc == SDMMC_LOCKED + || rc == SDMMC_STATE || rc == SDMMC_USER_CANCEL) + res = RES_NOTRDY; + else if (rc == SDMMC_PARAM || rc == SDMMC_NOT_SUPPORTED) + res = RES_PARERR; + else + res = RES_ERROR; + + return res; +} + +#if !FF_FS_READONLY +/** + * \brief Write Sector(s). + * + * \param slot Physical drive number (0..). + * \param buff Data to be written. + * \param sector Sector address in LBA. + * \param count Number of sectors to write. + * \return Result code; RES_OK if successful. + * + * \note The FatFs module will issue multiple sector transfer request + * (count > 1) to the disk I/O layer. The disk function should process + * the multiple sector transfer properly. Do not translate it into + * multiple single sector transfers to the media, or the data read/write + * performance may be drastically decreased. + */ +DRESULT disk_write(BYTE slot, const BYTE* buff, DWORD sector, UINT count) +{ + SdmmcDriver *sdmmcp = NULL; + DRESULT res; + uint32_t blk_size, addr = sector, len = count; + uint8_t rc; + + if (!sdmmcGetInstance(slot, &sdmmcp)) + return RES_PARERR; + + blk_size = sdmmcp->card.wBlockSize; + + if (blk_size < FF_MIN_SS) { + if (FF_MIN_SS % blk_size) + return RES_PARERR; + addr = sector * (FF_MIN_SS / blk_size); + len = count * (FF_MIN_SS / blk_size); + } + if (count <= 1) + rc = SD_WriteBlocks(sdmmcp, addr, buff, len); + else + rc = SD_Write(sdmmcp, addr, buff, len); + + if (rc == SDMMC_OK || rc == SDMMC_CHANGED) + res = RES_OK; + else if (rc == SDMMC_ERR_IO || rc == SDMMC_ERR_RESP || rc == SDMMC_ERR) + res = RES_ERROR; + else if (rc == SDMMC_NO_RESPONSE || rc == SDMMC_BUSY + || rc == SDMMC_NOT_INITIALIZED || rc == SDMMC_LOCKED + || rc == SDMMC_STATE || rc == SDMMC_USER_CANCEL) + res = RES_NOTRDY; + else if (rc == SDMMC_PARAM || rc == SDMMC_NOT_SUPPORTED) + res = RES_PARERR; + else + res = RES_ERROR; + return res; +} +#endif /* _FS_READONLY */ + +/** + * \brief Miscellaneous Functions. + * \param slot Physical drive number (0..). + * \param cmd Control code. + * \param buff Buffer to send/receive control data. + * \return Result code; RES_OK if successful. + */ +DRESULT disk_ioctl(BYTE slot, BYTE cmd, void* buff) +{ + SdmmcDriver *sdmmcp = NULL; + DRESULT res; + DWORD *param_u32 = (DWORD *)buff; + WORD *param_u16 = (WORD *)buff; + uint32_t blk_size, blk_count; + + if (!sdmmcGetInstance(slot, &sdmmcp)) + return RES_PARERR; + + switch (cmd) + { + case CTRL_SYNC: + /* SD/MMC devices do not seem to cache data beyond completion + * of the write commands. Note that if _FS_READONLY is enabled, + * this command is not needed. */ + res = RES_OK; + break; + + case GET_SECTOR_COUNT: + if (!buff) + return RES_PARERR; + blk_size = sdmmcp->card.wBlockSize; + blk_count = sdmmcp->card.dwNbBlocks; + + if (blk_size < FF_MIN_SS) + { + if (FF_MIN_SS % blk_size) + return RES_PARERR; + *param_u32 = blk_count / (FF_MIN_SS / blk_size); + } + else + *param_u32 = blk_count; + res = RES_OK; + break; + + case GET_SECTOR_SIZE: + /* Note that if _MAX_SS equals _MIN_SS i.e. the drive does not + * have to support several sector sizes, this command is not + * needed. */ + if (!buff) + return RES_PARERR; + blk_size = sdmmcp->card.wBlockSize; + *param_u16 = blk_size >= FF_MIN_SS ? blk_size : FF_MIN_SS; + res = RES_OK; + break; + + case GET_BLOCK_SIZE: + if (!buff) + return RES_PARERR; + /* On SD/MMC devices, erase block size is the same as write + * block size. + * Hence, erasing as little as one sector is allowed. */ + *param_u32 = 1; + res = RES_OK; + break; + + case CTRL_TRIM: + /* This TRIM-like command is not implemented. + * It would be required if _USE_TRIM was enabled. */ + res = RES_PARERR; + break; + + default: + res = RES_PARERR; + break; + } + return res; +} diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c index a6206854e..601c95f2a 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c @@ -238,7 +238,7 @@ uint8_t MmcInit(SdmmcDriver *driver) error = error == SDMMC_CHANGED ? SDMMC_OK : error; } if (error != SDMMC_OK) { - TRACE_1("HS %s\n\r", SD_StringifyRetCode(error)); + TRACE_ERROR_1("HS %s\n\r", SD_StringifyRetCode(error)); return error; } } @@ -271,7 +271,7 @@ uint8_t MmcInit(SdmmcDriver *driver) && tim_mode == SDMMC_TIM_MMC_HS_DDR) driver->card.bSpeedMode = tim_mode; else if (error) { - TRACE_1("Width/DDR %s\n\r", + TRACE_ERROR_1("Width/DDR %s\n\r", SD_StringifyRetCode(error)); return error; } @@ -306,7 +306,7 @@ uint8_t MmcInit(SdmmcDriver *driver) error = error == SDMMC_CHANGED ? SDMMC_OK : error; } if (error != SDMMC_OK) { - TRACE_1("HS200 %s\n\r", SD_StringifyRetCode(error)); + TRACE_ERROR_1("HS200 %s\n\r", SD_StringifyRetCode(error)); return error; } } @@ -367,7 +367,7 @@ uint8_t MmcInit(SdmmcDriver *driver) return error; status = status & ~STATUS_STATE & ~STATUS_READY_FOR_DATA & ~STATUS_APP_CMD; if (status) { - TRACE_1("st %lx\n\r", status); + TRACE_WARNING_1("st %lx\n\r", status); } return SDMMC_OK; diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c index 2f866296a..8a75a8656 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c @@ -3,7 +3,6 @@ #include "ch_sdmmc_pmc.h" - struct _pmc_main_osc { uint32_t rc_freq; uint32_t crystal_freq; @@ -828,3 +827,5 @@ void pmc_disable_internal_osc(void) #endif } + + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h index 34a137b91..ae05cee2f 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sama5d2.h @@ -8,6 +8,8 @@ #define SB1_SIZE 64 #define SB2_SIZE 8 +#define SDMMC_BUFFER_SIZE (EXT_SIZE + SSR_SIZE + SCR_SIZE + SB1_SIZE + SB2_SIZE) + /** Frequency of the board main clock oscillator */ #define BOARD_MAIN_CLOCK_EXT_OSC 12000000 #define MAIN_CLOCK_INT_OSC 12000000 diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c index 2f5e80a09..6363a0fac 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c @@ -6,7 +6,10 @@ #include "ch_sdmmc_sd.h" #include "ch_sdmmc_sdio.h" - +static uint8_t PerformSingleTransfer(SdmmcDriver *driver,uint32_t address, uint8_t * pData, uint8_t isRead); +static uint8_t MoveToTransferState(SdmmcDriver *driver,uint32_t address,uint16_t * nbBlocks, uint8_t * pData, uint8_t isRead); +static uint8_t _StopCmd(SdmmcDriver *driver); +static uint8_t _WaitUntilReady(SdmmcDriver *driver, uint32_t last_dev_status); static uint8_t SdGetTimingFunction(uint8_t mode); static void SdSelectSlowerTiming(bool high_sig, uint8_t * mode); @@ -78,6 +81,154 @@ const char * SD_StringifyIOCtrl(uint32_t dwCtrl) } #endif + +/** + * Read Blocks of data in a buffer pointed by pData. The buffer size must be at + * least 512 byte long. This function checks the SD card status register and + * address the card if required before sending the read command. + * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code". + * \param pSd Pointer to a SD card driver instance. + * \param address Address of the block to read. + * \param pData Data buffer whose size is at least the block size. It shall + * follow the peripheral and DMA alignment requirements. + * \param length Number of blocks to be read. + * \param pCallback Pointer to callback function that invoked when read done. + * 0 to start a blocked read. + * \param pArgs Pointer to callback function arguments. + */ +uint8_t SD_Read(SdmmcDriver *driver,uint32_t address,void *pData, uint32_t length) +{ + uint8_t *out = NULL; + uint32_t remaining, blk_no; + uint16_t limited; + uint8_t error = SDMMC_OK; + + + for (blk_no = address, remaining = length, out = (uint8_t *)pData; + remaining != 0 && error == SDMMC_OK; + blk_no += limited, remaining -= limited, + out += (uint32_t)limited * (uint32_t)driver->card.wCurrBlockLen) + { + limited = (uint16_t)min_u32(remaining, 65535); + error = MoveToTransferState(driver, blk_no, &limited, out, 1); + } + //debug + TRACE_DEBUG_3("SDrd(%lu,%lu) %s\n\r", address, length, SD_StringifyRetCode(error)); + return error; +} + +/** + * Write Blocks of data in a buffer pointed by pData. The buffer size must be at + * least 512 byte long. This function checks the SD card status register and + * address the card if required before sending the read command. + * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code". + * \param pSd Pointer to a SD card driver instance. + * \param address Address of the block to write. + * \param pData Data buffer whose size is at least the block size. It shall + * follow the peripheral and DMA alignment requirements. + * \param length Number of blocks to be write. + * \param pCallback Pointer to callback function that invoked when write done. + * 0 to start a blocked write. + * \param pArgs Pointer to callback function arguments. + */ +uint8_t SD_Write(SdmmcDriver *driver,uint32_t address,const void *pData,uint32_t length) +{ + uint8_t *in = NULL; + uint32_t remaining, blk_no; + uint16_t limited; + uint8_t error = SDMMC_OK; + +// assert(pSd != NULL); +// assert(pData != NULL); + + for (blk_no = address, remaining = length, in = (uint8_t *)pData; + remaining != 0 && error == SDMMC_OK; + blk_no += limited, remaining -= limited, + in += (uint32_t)limited * (uint32_t)driver->card.wCurrBlockLen) { + limited = (uint16_t)min_u32(remaining, 65535); + error = MoveToTransferState(driver, blk_no, &limited, in, 0); + } + //debug + TRACE_DEBUG_3("SDwr(%lu,%lu) %s\n\r", address, length, SD_StringifyRetCode(error)); + return error; +} + +/** + * Read Blocks of data in a buffer pointed by pData. The buffer size must be at + * least 512 byte long. This function checks the SD card status register and + * address the card if required before sending the read command. + * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code". + * \param pSd Pointer to a SD card driver instance. + * \param address Address of the block to read. + * \param nbBlocks Number of blocks to be read. + * \param pData Data buffer whose size is at least the block size. It shall + * follow the peripheral and DMA alignment requirements. + */ +uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks) +{ + uint8_t error = 0; + uint8_t *pBytes = (uint8_t *) pData; + + + //debug + TRACE_DEBUG_2("RdBlks(%lu,%lu)\n\r", address, nbBlocks); + + while (nbBlocks--) { + error = PerformSingleTransfer(driver, address, pBytes, 1); + if (error) + break; + address += 1; + pBytes = &pBytes[512]; + } + return error; +} + +/** + * Write Block of data pointed by pData. The buffer size must be at + * least 512 byte long. This function checks the SD card status register and + * address the card if required before sending the read command. + * \return 0 if successful; otherwise returns an \ref sdmmc_rc "error code". + * \param pSd Pointer to a SD card driver instance. + * \param address Address of block to write. + * \param nbBlocks Number of blocks to be read + * \param pData Data buffer whose size is at least the block size. It shall + * follow the peripheral and DMA alignment requirements. + */ +uint8_t SD_WriteBlocks(SdmmcDriver *driver, uint32_t address, const void *pData, uint32_t nbBlocks) +{ + uint8_t error = 0; + uint8_t *pB = (uint8_t *) pData; + + + //debug + TRACE_DEBUG_2("WrBlks(%lu,%lu)\n\r", address, nbBlocks); + + while (nbBlocks--) { + error = PerformSingleTransfer(driver, address, pB, 0); + if (error) + break; + address += 1; + pB = &pB[512]; + } + return error; +} + +uint8_t SD_GetStatus(SdmmcDriver *driver) +{ + uint32_t rc; + + const sSdCard * pSd = &driver->card; + + driver->control_param = 0; + + rc = sdmmc_device_control(driver,SDMMC_IOCTL_GET_DEVICE); + + if (rc != SDMMC_OK || !driver->control_param) + return SDMMC_NOT_SUPPORTED; + + return pSd->bStatus == SDMMC_NOT_SUPPORTED ? SDMMC_ERR : pSd->bStatus; +} + uint8_t SdDecideBuswidth(SdmmcDriver *drv) { uint8_t error, busWidth = 1; @@ -155,7 +306,7 @@ uint8_t SdEnableHighSpeed(SdmmcDriver *drv) return SDMMC_ERR; sfs_v1 = SD_SWITCH_ST_DATA_STRUCT_VER(drv->card.sandbox1) >= 0x01; mode_mask = SD_SWITCH_ST_FUN_GRP1_INFO(drv->card.sandbox1); - TRACE_1("Device timing functions: 0x%04x\n\r", mode_mask); + TRACE_DEBUG_1("Device timing functions: 0x%04x\n\r", mode_mask); if (has_io && mode == SDMMC_TIM_SD_HS && !(mode_mask & 1 << SD_SWITCH_ST_ACC_HS)) return SDMMC_NOT_SUPPORTED; @@ -181,7 +332,7 @@ uint8_t SdEnableHighSpeed(SdmmcDriver *drv) return SDMMC_STATE; /* Check the electrical power requirements of this device */ val = SD_SWITCH_ST_FUN_GRP4_INFO(drv->card.sandbox1); - TRACE_2("Device pwr & strength functions: 0x%04x & 0x%04x\n\r", val, + TRACE_DEBUG_2("Device pwr & strength functions: 0x%04x & 0x%04x\n\r", val, SD_SWITCH_ST_FUN_GRP3_INFO(drv->card.sandbox1)); if (!(val & 1 << SD_SWITCH_ST_MAX_PWR_1_44W)) pwr_func = SD_SWITCH_ST_MAX_PWR_0_72W; @@ -192,7 +343,7 @@ uint8_t SdEnableHighSpeed(SdmmcDriver *drv) if (error || status & STATUS_SWITCH_ERROR) return SDMMC_ERR; val = SD_SWITCH_ST_MAX_CURR_CONSUMPTION(drv->card.sandbox1); - TRACE_1("Device max current: %u mA\n\r", val); + TRACE_DEBUG_1("Device max current: %u mA\n\r", val); if (val == 0 || val > (1440 * 10) / 36) SdSelectSlowerTiming(drv->card.bCardSigLevel != 0, &mode); else if (sfs_v1) { @@ -257,7 +408,7 @@ Switch: val = SD_SWITCH_ST_FUN_GRP4_RC(drv->card.sandbox1); if (val != pwr_func) { - TRACE_1("Device power limit 0x%x\n\r", val); + TRACE_DEBUG_1("Device power limit 0x%x\n\r", val); } Apply: @@ -280,7 +431,7 @@ void SdGetExtInformation(SdmmcDriver *drv) if (error == SDMMC_OK) { card_status &= ~STATUS_READY_FOR_DATA; if (card_status != (STATUS_APP_CMD | STATUS_TRAN)) { - TRACE_1("SCR st %lx\n\r", card_status); + TRACE_DEBUG_1("SCR st %lx\n\r", card_status); } } @@ -289,7 +440,7 @@ void SdGetExtInformation(SdmmcDriver *drv) if (error == SDMMC_OK) { card_status &= ~STATUS_READY_FOR_DATA; if (card_status != (STATUS_APP_CMD | STATUS_TRAN)) { - TRACE_1("SSR st %lx\n\r", card_status); + TRACE_DEBUG_1("SSR st %lx\n\r", card_status); } } } @@ -529,10 +680,10 @@ void SD_DumpStatus(const sSdCard *pSd) strcat(mode, "104"); } - TRACE_4("%s, %u-bit data, in %s mode at %lu kHz\n\r", text, pSd->bBusMode, mode, (pSd->dwCurrSpeed / 1000UL) ); + TRACE_DEBUG_4("%s, %u-bit data, in %s mode at %lu kHz\n\r", text, pSd->bBusMode, mode, (pSd->dwCurrSpeed / 1000UL) ); if (pSd->bCardType & CARD_TYPE_bmSDMMC) { - TRACE_3("Device memory size: %lu MiB, %lu * %uB\n\r", SD_GetTotalSizeKB(pSd) / 1024ul, pSd->dwNbBlocks,pSd->wBlockSize); + TRACE_DEBUG_3("Device memory size: %lu MiB, %lu * %uB\n\r", SD_GetTotalSizeKB(pSd) / 1024ul, pSd->dwNbBlocks,pSd->wBlockSize); } @@ -779,3 +930,242 @@ void SD_DumpExtCSD(const uint8_t *pExtCSD) _PrintField("ER_GRP_DEF 0x%X\r\n", MMC_EXT_ERASE_GROUP_DEF(pExtCSD)); } + + +/** + * Transfer a single data block. + * The device shall be in its Transfer State already. + * \param pSd Pointer to a SD card driver instance. + * \param address Address of the block to transfer. + * \param pData Data buffer, whose size is at least one block size. + * \param isRead Either 1 to read data from the device or 0 to write data. + * \return a \ref sdmmc_rc result code. + */ +static uint8_t PerformSingleTransfer(SdmmcDriver *driver,uint32_t address, uint8_t * pData, uint8_t isRead) +{ + uint8_t result = SDMMC_OK, error; + uint32_t sdmmc_address, status; + + /* Convert block address into device-expected unit */ + if (driver->card.bCardType & CARD_TYPE_bmHC) + sdmmc_address = address; + else if (address <= 0xfffffffful / driver->card.wCurrBlockLen) + sdmmc_address = address * driver->card.wCurrBlockLen; + else + return SDMMC_PARAM; + + if (isRead) + /* Read a single data block */ + error = Cmd17(driver, pData, sdmmc_address, &status); + else + /* Write a single data block */ + error = Cmd24(driver, pData, sdmmc_address, &status); + + if (!error) { + status = status & (isRead ? STATUS_READ : STATUS_WRITE) + & ~STATUS_READY_FOR_DATA & ~STATUS_STATE; + if (status) { + //error + TRACE_1("st %lx\n\r", status); + error = SDMMC_ERR; + } + } + if (error) { + //error + TRACE_ERROR_3("Cmd%u(0x%lx) %s\n\r", isRead ? 17 : 24,sdmmc_address, SD_StringifyRetCode(error)); + result = error; + error = Cmd13(driver, &status); + if (error) { + driver->card.bStatus = error; + return result; + } + error = _WaitUntilReady(driver, status); + if (error) { + driver->card.bStatus = error; + return result; + } + } + return result; +} + +/** + * Move SD card to transfer state. The buffer size must be at + * least 512 byte long. This function checks the SD card status register and + * address the card if required before sending the transfer command. + * Returns 0 if successful; otherwise returns an code describing the error. + * \param pSd Pointer to a SD card driver instance. + * \param address Address of the block to transfer. + * \param nbBlocks Pointer to count of blocks to transfer. Pointer to 0 + * for infinite transfer. Upon return, points to the count of blocks actually + * transferred. + * \param pData Data buffer whose size is at least the block size. + * \param isRead 1 for read data and 0 for write data. + */ +static uint8_t MoveToTransferState(SdmmcDriver *driver,uint32_t address,uint16_t * nbBlocks, uint8_t * pData, uint8_t isRead) +{ + uint8_t result = SDMMC_OK, error; + uint32_t sdmmc_address, state, status; + + /* Convert block address into device-expected unit */ + if (driver->card.bCardType & CARD_TYPE_bmHC) + sdmmc_address = address; + else if (address <= 0xfffffffful / driver->card.wCurrBlockLen) + sdmmc_address = address * driver->card.wCurrBlockLen; + else + return SDMMC_PARAM; + + if (driver->card.bSetBlkCnt) { + error = Cmd23(driver, 0, *nbBlocks, &status); + if (error) + return error; + } + + if (isRead) + /* Move to Receiving data state */ + error = Cmd18(driver, nbBlocks, pData, sdmmc_address, &status); + else + /* Move to Sending data state */ + error = Cmd25(driver, nbBlocks, pData, sdmmc_address, &status); + + if (error == SDMMC_CHANGED) + error = SDMMC_OK; + + if (!error) { + status = status & (isRead ? STATUS_READ : STATUS_WRITE) + & ~STATUS_READY_FOR_DATA & ~STATUS_STATE; + + if (driver->card.bStopMultXfer) + error = _StopCmd(driver); + + if (status) { + //error + TRACE_DEBUG_1("st %lx\n\r", status); + /* TODO ignore STATUS_ADDR_OUT_OR_RANGE if the read + * operation is for the last block of memory area. */ + error = SDMMC_ERR; + } + /* FIXME when not using the STOP_TRANSMISSION command (using the + * SET_BLOCK_COUNT command instead), we should issue the + * SEND_STATUS command, eat and handle any Execution Mode + * exception. */ + } + if (error) { + //error + TRACE_ERROR_4("Cmd%u(0x%lx, %u) %s\n\r", isRead ? 18 : 25,sdmmc_address, *nbBlocks, SD_StringifyRetCode(error)); + result = error; + error = Cmd13(driver, &status); + + if (error) { + driver->card.bStatus = error; + return result; + } + + state = status & STATUS_STATE; + + if (state == STATUS_DATA || state == STATUS_RCV) { + + error = Cmd12(driver, &status); + + if (error == SDMMC_OK) { + //info + TRACE_INFO_1("st %lx\n\r", status); + + if (status & (STATUS_ERASE_SEQ_ERROR + | STATUS_ERASE_PARAM | STATUS_UN_LOCK_FAILED + | STATUS_ILLEGAL_COMMAND + | STATUS_CIDCSD_OVERWRITE + | STATUS_ERASE_RESET | STATUS_SWITCH_ERROR)) + result = SDMMC_STATE; + else if (status & (STATUS_COM_CRC_ERROR + | STATUS_CARD_ECC_FAILED | STATUS_ERROR)) + result = SDMMC_ERR_IO; + else if (status & (STATUS_ADDR_OUT_OR_RANGE + | STATUS_ADDRESS_MISALIGN + | STATUS_BLOCK_LEN_ERROR + | STATUS_WP_VIOLATION + | STATUS_WP_ERASE_SKIP)) + result = SDMMC_PARAM; + else if (status & STATUS_CC_ERROR) + result = SDMMC_ERR; + } + else if (error == SDMMC_NO_RESPONSE) + error = Cmd13(driver, &status); + if (error) { + driver->card.bStatus = error; + return result; + } + } + error = _WaitUntilReady(driver, status); + + if (error) { + driver->card.bStatus = error; + return result; + } + } + return result; +} + +/** + * Stop TX/RX + */ +static uint8_t _StopCmd(SdmmcDriver *driver) +{ + uint32_t status, state = STATUS_RCV; + uint32_t i; + uint8_t err, count; + /* When stopping a write operation, allow retrying several times */ + for (i = 0; i < 9 && state == STATUS_RCV; i++) { + err = Cmd12(driver, &status); + if (err) + return err; + /* TODO handle any exception, raised in status; report that + * the data transfer has failed. */ + + /* Wait until ready. Allow 30 ms. */ + for (count = 0; count < 6; count++) { + /* Wait for about 5 ms - which equals 5 system ticks */ + t_msleep(driver,5); + err = Cmd13(driver, &status); + if (err) + return err; + state = status & STATUS_STATE; + + /* Invalid state */ + if (state == STATUS_IDLE || state == STATUS_READY + || state == STATUS_IDENT || state == STATUS_STBY + || state == STATUS_DIS) + return SDMMC_NOT_INITIALIZED; + + /* Ready? */ + if ((status & STATUS_READY_FOR_DATA) == + STATUS_READY_FOR_DATA && state == STATUS_TRAN) + return SDMMC_OK; + } + } + return SDMMC_STATE; +} + +static uint8_t _WaitUntilReady(SdmmcDriver *driver, uint32_t last_dev_status) +{ + uint32_t state, status = last_dev_status; + uint8_t err, count; + + for (count = 0; count < 51; count++) { + state = status & STATUS_STATE; + if (state == STATUS_TRAN && status & STATUS_READY_FOR_DATA) + return SDMMC_OK; + /* Sending-data and Receive-data states may be encountered + * temporarily further to single-block data transfers. */ + /* FIXME state 15 "reserved for I/O mode" may be allowed */ + if (state != STATUS_TRAN && state != STATUS_PRG + && state != STATUS_DATA && state != STATUS_RCV) + return SDMMC_NOT_INITIALIZED; + /* Wait for about 10 ms - which equals 10 system ticks */ + t_msleep(driver,10); + err = Cmd13(driver, &status); + if (err) + return err; + } + return SDMMC_BUSY; +} + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h index d08778219..7708a88f1 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h @@ -75,10 +75,6 @@ #define SD_SWITCH_ST_FUN_GRP_FUN_BUSY(funNdx) (1 << (funNdx)) /** @}*/ - - - - /** We support 2.7 ~ 3.3V cards */ #define SD_HOST_VOLTAGE_RANGE (SD_OCR_VDD_27_28 +\ SD_OCR_VDD_28_29 +\ @@ -91,6 +87,10 @@ SD_OCR_VDD_35_36 ) + +/** @}*/ + +extern uint8_t SD_GetStatus(SdmmcDriver *driver); extern uint8_t SdDecideBuswidth(SdmmcDriver *drv); extern uint8_t SdEnableHighSpeed(SdmmcDriver *drv); extern uint32_t SD_GetField(const uint8_t *reg, uint16_t reg_len, uint16_t field_start, @@ -107,5 +107,10 @@ extern void SD_DumpSSR(const uint8_t *pSSR); extern const char * SD_StringifyRetCode(uint32_t dwRCode); extern const char * SD_StringifyIOCtrl(uint32_t dwCtrl); +extern uint8_t SD_Read(SdmmcDriver *driver,uint32_t address,void *pData, uint32_t length); +extern uint8_t SD_Write(SdmmcDriver *driver,uint32_t address,const void *pData,uint32_t length); +extern uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks); +extern uint8_t SD_WriteBlocks(SdmmcDriver *driver, uint32_t address, const void *pData, uint32_t nbBlocks); +extern uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks); #endif /* CH_SDMMC_SD_H_ */ diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c index b8898acb5..9b66742c7 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c @@ -3,6 +3,8 @@ #include "ch_sdmmc_pmc.h" #include "ch_sdmmc_tc.h" +#if SDMMC_USE_TC == 1 + /*------------------------------------------------------------------------------ * Global functions *------------------------------------------------------------------------------*/ @@ -249,3 +251,4 @@ uint32_t tc_get_cv(Tc* tc, uint32_t channel) return ch->TC_CV; } +#endif diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h index 1bb9ad15f..20ea20f50 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_trace.h @@ -23,7 +23,80 @@ extern BaseSequentialStream * ts; #define TRACE_4(s,v1,v2,v3,v4) #define TRACE_5(s,v1,v2,v3,v4,v5) #define TRACE_6(s,v1,v2,v3,v4,v5,v6) -#define TRACE_LEV_1(s,v1) +#endif + +#if SAMA_SDMMC_TRACE_LEVEL >= 1 +#define TRACE_INFO(s) TRACE(s) +#define TRACE_INFO_1(s,v1) TRACE_1(s,v1) +#define TRACE_INFO_2(s,v1,v2) TRACE_2(s,v1,v2) +#define TRACE_INFO_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3) +#define TRACE_INFO_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4) +#define TRACE_INFO_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5) +#define TRACE_INFO_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6) +#else +#define TRACE_INFO(s) +#define TRACE_INFO_1(s,v1) +#define TRACE_INFO_2(s,v1,v2) +#define TRACE_INFO_3(s,v1,v2,v3) +#define TRACE_INFO_4(s,v1,v2,v3,v4) +#define TRACE_INFO_5(s,v1,v2,v3,v4,v5) +#define TRACE_INFO_6(s,v1,v2,v3,v4,v5,v6) +#endif + + +#if SAMA_SDMMC_TRACE_LEVEL >= 2 +#define TRACE_WARNING(s) TRACE(s) +#define TRACE_WARNING_1(s,v1) TRACE_1(s,v1) +#define TRACE_WARNING_2(s,v1,v2) TRACE_2(s,v1,v2) +#define TRACE_WARNING_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3) +#define TRACE_WARNING_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4) +#define TRACE_WARNING_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5) +#define TRACE_WARNING_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6) +#else +#define TRACE_WARNING(s) +#define TRACE_WARNING_1(s,v1) +#define TRACE_WARNING_2(s,v1,v2) +#define TRACE_WARNING_3(s,v1,v2,v3) +#define TRACE_WARNING_4(s,v1,v2,v3,v4) +#define TRACE_WARNING_5(s,v1,v2,v3,v4,v5) +#define TRACE_WARNING_6(s,v1,v2,v3,v4,v5,v6) +#endif + + +#if SAMA_SDMMC_TRACE_LEVEL >= 3 +#define TRACE_ERROR(s) TRACE(s) +#define TRACE_ERROR_1(s,v1) TRACE_1(s,v1) +#define TRACE_ERROR_2(s,v1,v2) TRACE_2(s,v1,v2) +#define TRACE_ERROR_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3) +#define TRACE_ERROR_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4) +#define TRACE_ERROR_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5) +#define TRACE_ERROR_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6) +#else +#define TRACE_ERROR(s) +#define TRACE_ERROR_1(s,v1) +#define TRACE_ERROR_2(s,v1,v2) +#define TRACE_ERROR_3(s,v1,v2,v3) +#define TRACE_ERROR_4(s,v1,v2,v3,v4) +#define TRACE_ERROR_5(s,v1,v2,v3,v4,v5) +#define TRACE_ERROR_6(s,v1,v2,v3,v4,v5,v6) +#endif + +#if SAMA_SDMMC_TRACE_LEVEL >= 4 +#define TRACE_DEBUG(s) TRACE(s) +#define TRACE_DEBUG_1(s,v1) TRACE_1(s,v1) +#define TRACE_DEBUG_2(s,v1,v2) TRACE_2(s,v1,v2) +#define TRACE_DEBUG_3(s,v1,v2,v3) TRACE_3(s,v1,v2,v3) +#define TRACE_DEBUG_4(s,v1,v2,v3,v4) TRACE_4(s,v1,v2,v3,v4) +#define TRACE_DEBUG_5(s,v1,v2,v3,v4,v5) TRACE_5(s,v1,v2,v3,v4,v5) +#define TRACE_DEBUG_6(s,v1,v2,v3,v4,v5,v6) TRACE_6(s,v1,v2,v3,v4,v5,v6) +#else +#define TRACE_DEBUG(s) +#define TRACE_DEBUG_1(s,v1) +#define TRACE_DEBUG_2(s,v1,v2) +#define TRACE_DEBUG_3(s,v1,v2,v3) +#define TRACE_DEBUG_4(s,v1,v2,v3,v4) +#define TRACE_DEBUG_5(s,v1,v2,v3,v4,v5) +#define TRACE_DEBUG_6(s,v1,v2,v3,v4,v5,v6) #endif diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk index ae2e9f16a..13494bdc2 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk @@ -1,12 +1,13 @@ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sdio.c \ - $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_tc.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c \ - $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_pmc.c PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1 diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h index 560fcb1c7..0fb377549 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h @@ -14,12 +14,19 @@ typedef FATFS CH_SDMMC_FAT; #define SAMA_SDMMC_TRACE 0 #endif +#ifndef SAMA_SDMMC_TRACE_LEVEL +#define SAMA_SDMMC_TRACE_LEVEL 0 +#endif /** Default block size for SD/MMC access */ #ifndef SDMMC_BLOCK_SIZE #define SDMMC_BLOCK_SIZE 512 #endif +#ifndef SDMMC_USE_TC +#define SDMMC_USE_TC 0 +#endif + #endif //SAMA_SDMMC_CONF_H diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c index 105e18036..7aed656dc 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c @@ -23,7 +23,7 @@ */ #include "hal.h" - +#include "ccportab.h" #if (HAL_USE_SDMMC == TRUE) || defined(__DOXYGEN__) #include #include "sama_sdmmc_lld.h" @@ -129,11 +129,9 @@ void sdmmcStart(SdmmcDriver *sdmmcp, const SamaSDMMCConfig *config) } - TRACE_LEV_1("[%s] Cannot init board for MMC\r\n","ERROR"); + TRACE_ERROR("Cannot init board for MMC\r\n"); sdmmcp->state = MCID_INIT_ERROR; - - } /** @@ -177,7 +175,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp) uint8_t bRc; if (sdmmcp->cmd.bCmd != 55) { - TRACE_2("Cmd%u(%lx)\n\r", sdmmcp->cmd.bCmd, sdmmcp->cmd.dwArg); + TRACE_INFO_2("Cmd%u(%lx)\n\r", sdmmcp->cmd.bCmd, sdmmcp->cmd.dwArg); } bRc = sdmmc_device_command(sdmmcp); @@ -198,6 +196,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp) sdmmcp->control_param = 1; sdmmcp->timeout_elapsed = 0; + sdmmcp->timeout_ticks = 30*1000; sdmmc_device_startTimeCount(sdmmcp); do @@ -221,18 +220,17 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp) } bRc = sdmmcp->cmd.bStatus; - //TRACE_1("post cmd bRc = %d\r\n",bRc); + if (bRc == SDMMC_CHANGED) { - //TRACE_2("Changed Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc)); + TRACE_DEBUG_2("Changed Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc)); } else if (bRc != SDMMC_OK) { - //TRACE_2("OK Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc)); + TRACE_DEBUG_2("OK Cmd%u %s\n\r", sdmmcp->cmd.bCmd,SD_StringifyRetCode(bRc)); } else if (sdmmcp->cmd.cmdOp.bmBits.respType == 1 && sdmmcp->cmd.pResp) { - //TRACE_2("Resp Cmd%u st %lx\n\r", sdmmcp->cmd.bCmd, *sdmmcp->cmd.pResp); + TRACE_DEBUG_2("Resp Cmd%u st %lx\n\r", sdmmcp->cmd.bCmd, *sdmmcp->cmd.pResp); } - //TRACE_1("[ret sending cmd] %d\r\n",bRc); return bRc; } @@ -252,14 +250,14 @@ bool sdmmcOpenDevice(SdmmcDriver *sdmmcp) rc = sdmmc_device_start(sdmmcp); if (rc != SDMMC_OK) { - TRACE_1("SD/MMC device initialization failed: %d\n\r", rc); + TRACE_INFO_1("SD/MMC device initialization failed: %d\n\r", rc); return false; } - if (sdmmc_device_identify(sdmmcp) == SDMMC_OK) { + if (sdmmc_device_identify(sdmmcp) != SDMMC_OK) { return false; } - TRACE("SD/MMC device initialization successful\n\r"); + TRACE_INFO("SD/MMC device initialization successful\n\r"); return true; } @@ -272,13 +270,13 @@ bool sdmmcCloseDevice(SdmmcDriver *sdmmcp) bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp) { sSdCard *pSd =&sdmmcp->card; - TRACE("Show Device Info:\n\r"); + TRACE_INFO("Show Device Info:\n\r"); #ifndef SDMMC_TRIM_INFO const uint8_t card_type = sdmmcp->card.bCardType; - TRACE_1("Card Type: %d\n\r", card_type); + TRACE_INFO_1("Card Type: %d\n\r", card_type); #endif - TRACE("Dumping Status ... \n\r"); + TRACE_INFO("Dumping Status ... \n\r"); SD_DumpStatus(pSd); #ifndef SDMMC_TRIM_INFO if (card_type & CARD_TYPE_bmSDMMC) @@ -304,58 +302,24 @@ bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp) bool sdmmcMountVolume(SdmmcDriver *sdmmcp, CH_SDMMC_FAT *fs) { -#if 0 - //TODO to be done - const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; - DIR dir = { .sect = 0 }; - FILINFO fno = { 0 }; FRESULT res; - bool is_dir, rc = true; + const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; (void)sdmmcp; memset(fs, 0, sizeof(CH_SDMMC_FAT)); res = f_mount(fs, drive_path, 1); if (res != FR_OK) { - TRACE_1("Failed to mount FAT file system, error %d\n\r", res); + TRACE_INFO_1("Failed to mount FAT file system, error %d\n\r", res); return false; } - res = f_opendir(&dir, drive_path); - if (res != FR_OK) { - TRACE_1("Failed to change to root directory, error %d\n\r", res); - return false; - } TRACE("Listing the files present in the root directory:\n\r"); - for (;;) { - res = f_readdir(&dir, &fno); - if (res != FR_OK) { - TRACE_1("Error (%d) while listing files\n\r", res); - rc = false; - break; - } - if (fno.fname[0] == '\0') - break; - is_dir = fno.fattrib & AM_DIR ? true : false; - TRACE_3(" %s%s%c\n\r", is_dir ? "[" : "", fno.fname,is_dir ? ']' : ' '); - } - res = f_closedir(&dir); - if (res != FR_OK) { - TRACE_1("Failed to close directory, error %d\n\r", res); - rc = false; - } - return rc; -#else - (void)sdmmcp; - (void)fs; - return 0; -#endif + return true; } bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp) { - #if 0 - //TODO to be done const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; FRESULT res; bool rc = true; @@ -365,13 +329,15 @@ bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp) rc = false; return rc; -#else - (void)sdmmcp; - return 0; -#endif } +bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) +{ + (void)index; + (void)sdmmcp; + return false; +} #endif /* HAL_USE_SDMMC == TRUE */ diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h index 9b672c642..7093dd9b3 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h @@ -78,21 +78,18 @@ typedef struct { struct _pmc_periph_cfg pmccfg; bool use_fastest_clock; - +#if SDMMC_USE_TC == 1 Tc * tctimer; - uint8_t tc_chan; +#endif uint8_t * bp; uint8_t * data_buf; uint32_t data_buf_size; - - uint32_t * dma_table; uint32_t dma_table_size; - } SamaSDMMCConfig; @@ -132,6 +129,11 @@ struct SamaSDMMCDriver uint32_t timeout_ticks; int8_t timeout_elapsed; systime_t time,now; +#if SDMMC_USE_TC == 0 + rtcnt_t timeout_cycles; + rtcnt_t start_cycles; +#endif + }; typedef sSdCard sdmmclib; typedef struct SamaSDMMCDriver SdmmcDriver; diff --git a/os/hal/ports/SAMA/SAMA5D2x/platform.mk b/os/hal/ports/SAMA/SAMA5D2x/platform.mk index 3f8b171ed..2c1f6e15b 100644 --- a/os/hal/ports/SAMA/SAMA5D2x/platform.mk +++ b/os/hal/ports/SAMA/SAMA5D2x/platform.mk @@ -33,6 +33,7 @@ include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SPIv1/driver.mk include $(CHIBIOS)/os/hal/ports/SAMA/LLD/RTCv1/driver.mk include $(CHIBIOS)/os/hal/ports/SAMA/LLD/USARTv1/driver.mk include $(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk # Shared variables ALLCSRC += $(PLATFORMSRC) diff --git a/testhal/ATSAMA5D2/SDMMC/.cproject b/testhal/ATSAMA5D2/SDMMC/.cproject new file mode 100644 index 000000000..1c30c8b9b --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/.cproject @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testhal/ATSAMA5D2/SDMMC/.project b/testhal/ATSAMA5D2/SDMMC/.project new file mode 100644 index 000000000..fc56de69d --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/.project @@ -0,0 +1,91 @@ + + + SAMA5D2-SDMMC + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -j1 + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + + + + board + 2 + CHIBIOS/os/hal/boards/ATSAMA5D2_XULT + + + os + 2 + CHIBIOS/os + + + diff --git a/testhal/ATSAMA5D2/SDMMC/Makefile b/testhal/ATSAMA5D2/SDMMC/Makefile new file mode 100644 index 000000000..42697581f --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/Makefile @@ -0,0 +1,256 @@ +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -Og -ggdb -fomit-frame-pointer -falign-functions=16 +endif + +# C specific options here (added to USE_OPT). +ifeq ($(USE_COPT),) + USE_COPT = +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -fno-rtti +endif + +# Enable this if you want the linker to remove unused code and data +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# Linker extra options here. +ifeq ($(USE_LDOPT),) + USE_LDOPT = +endif + +# Enable this if you want link time optimizations (LTO) +ifeq ($(USE_LTO),) + USE_LTO = yes +endif + +# If enabled, this option allows to compile the application in THUMB mode. +ifeq ($(USE_THUMB),) + USE_THUMB = no +endif + +# Enable this if you want to see the full log while compiling. +ifeq ($(USE_VERBOSE_COMPILE),) + USE_VERBOSE_COMPILE = no +endif + +# If enabled, this option makes the build process faster by not compiling +# modules not used in the current configuration. +ifeq ($(USE_SMART_BUILD),) + USE_SMART_BUILD = yes +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Stack size to be allocated to the ARM System/User stack. This +# stack is the stack used by the main() thread. +ifeq ($(USE_SYSTEM_STACKSIZE),) + USE_SYSTEM_STACKSIZE = 0x400 +endif + +# Stack size to the allocated to the ARM IRQ stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_EXCEPTIONS_STACKSIZE),) + USE_IRQ_STACKSIZE = 0x400 +endif + +# Stack size to the allocated to the ARM FIQ stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_FIQ_STACKSIZE),) + USE_FIQ_STACKSIZE = 64 +endif + +# Stack size to the allocated to the ARM Supervisor stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_SUPERVISOR_STACKSIZE),) + USE_SUPERVISOR_STACKSIZE = 8 +endif + +# Stack size to the allocated to the ARM Undefined stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_UND_STACKSIZE),) + USE_UND_STACKSIZE = 8 +endif + +# Stack size to the allocated to the ARM Abort stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_ABT_STACKSIZE),) + USE_ABT_STACKSIZE = 8 +endif + +# Enables the use of FPU. +ifeq ($(USE_FPU),) + USE_FPU = no +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define project name here +PROJECT = ch + +# Imported source files and paths +CHIBIOS = ../../.. +# Startup files. +include $(CHIBIOS)/os/common/startup/ARMCAx-TZ/compilers/GCC/mk/startup_sama5d2.mk +# HAL-OSAL files (optional). +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/platform.mk +include $(CHIBIOS)/os/hal/boards/ATSAMA5D2_XULT/board.mk +include $(CHIBIOS)/os/hal/osal/rt/osal.mk +# RTOS files (optional). +include $(CHIBIOS)/os/rt/rt.mk +include $(CHIBIOS)/os/common/ports/ARMCAx-TZ/compilers/GCC/mk/port_generic.mk +# Other files (optional). +#include $(CHIBIOS)/test/lib/test.mk +#include $(CHIBIOS)/test/rt/rt_test.mk +#include $(CHIBIOS)/test/oslib/oslib_test.mk +include $(CHIBIOS)/os/various/fatfs_bindings/fatfs.mk +include $(CHIBIOS)/os/hal/lib/streams/streams.mk +# Define linker script file here +LDSCRIPT= $(STARTUPLD)/SAMA5D2.ld + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(STARTUPSRC) \ + $(KERNSRC) \ + $(PORTSRC) \ + $(OSALSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + $(TESTSRC) $(STREAMSSRC) \ + main.c + +CSRC += $(CHIBIOS)/os/various/syscalls.c +CSRC += $(CHIBIOS)/os/various/fatfs_bindings/fatfs_syscall.c +CSRC += $(CHIBIOS)/ext/fatfs/src/ff.c +CSRC += $(CHIBIOS)/ext/fatfs/src/ffunicode.c +# C++ sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CPPSRC = + +# C sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACSRC = + +# C++ sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACPPSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCPPSRC = + +# List ASM source files here +ASMSRC = +ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) + +INCDIR = $(CHIBIOS)/os/license \ + $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ + $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ + $(CHIBIOS)/os/various $(STREAMSINC) + +INCDIR += $(FATFSINC) +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +MCU = cortex-a5 + +#TRGT = arm-elf- +TRGT = arm-none-eabi- +CC = $(TRGT)gcc +CPPC = $(TRGT)g++ +# Enable loading with g++ only if you need C++ runtime support. +# NOTE: You can use C++ even without C++ support if you are careful. C++ +# runtime support makes code size explode. +LD = $(TRGT)gcc +#LD = $(TRGT)g++ +CP = $(TRGT)objcopy +AS = $(TRGT)gcc -x assembler-with-cpp +AR = $(TRGT)ar +OD = $(TRGT)objdump +SZ = $(TRGT)size +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +# ARM-specific options here +AOPT = + +# THUMB-specific options here +TOPT = -mthumb -DTHUMB + +# Define C warning options here +CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra -Wundef + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = -DCH_CFG_USE_MMU -DPLATFORM_SDMMC_USE_SDMMC1=1 + +# Define ASM defines here +UADEFS = -DCH_CFG_USE_MMU + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = + +# +# End of user defines +############################################################################## + +RULESPATH = $(CHIBIOS)/os/common/startup/ARMCAx-TZ/compilers/GCC +include $(RULESPATH)/rules.mk + +############################################################################## +# MISRA check rule, requires PCLint and the setup files, not provided. +# +misra: + @lint-nt -v -w3 $(DEFS) pclint/co-gcc.lnt pclint/au-misra3.lnt pclint/waivers.lnt $(IINCDIR) $(CSRC) &> misra.txt diff --git a/testhal/ATSAMA5D2/SDMMC/chconf.h b/testhal/ATSAMA5D2/SDMMC/chconf.h new file mode 100644 index 000000000..f61dc3f3e --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/chconf.h @@ -0,0 +1,615 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_5_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 0 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY TRUE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +/** + * @brief Trust zone configuration. + * @details If enabled the kernel is configured for the secure world + * and can access specific devices. + */ +#define CH_CFG_SEC_WORLD TRUE + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch new file mode 100644 index 000000000..e68b5ed9a --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch new file mode 100644 index 000000000..7a1b87b82 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testhal/ATSAMA5D2/SDMMC/halconf.h b/testhal/ATSAMA5D2/SDMMC/halconf.h new file mode 100644 index 000000000..b534118ae --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/halconf.h @@ -0,0 +1,437 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the QSPI subsystem. + */ +#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__) +#define HAL_USE_QSPI FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/testhal/ATSAMA5D2/SDMMC/main.c b/testhal/ATSAMA5D2/SDMMC/main.c new file mode 100644 index 000000000..ee87869b8 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/main.c @@ -0,0 +1,188 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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 +#include "ch.h" +#include "hal.h" +#include "sama_sdmmc_lld.h" +#include "chprintf.h" + + +#define BLOCK_CNT_MAX 32u +#define DMADL_CNT_MAX 64u +#define BLOCK_CNT 3u + + +CACHE_ALIGNED uint8_t data_buf[BLOCK_CNT_MAX * 512ul]; + +CACHE_ALIGNED static uint32_t dma_table[DMADL_CNT_MAX * SDMMC_DMADL_SIZE]; + +CACHE_ALIGNED uint8_t sdmmcbuffer[ROUND_UP_MULT(EXT_SIZE + SSR_SIZE + SCR_SIZE + SB1_SIZE + SB2_SIZE, L1_CACHE_BYTES)]; + +static FATFS fs_header; +//static FIL f_header; + +BaseSequentialStream * ts; + +static const SerialConfig sdcfg = { 115200, 0,UART_MR_PAR_NO }; + +/* + * LED blinker thread, times are in milliseconds. + */ +static THD_WORKING_AREA(waThread1, 512); +static THD_FUNCTION(Thread1, arg) { + + (void) arg; + chRegSetThreadName("blinker"); + + while (true) { + palToggleLine(LINE_LED_BLUE); + chThdSleepMilliseconds(500); + } +} + +//for emmc +#define CFG_FASTEST { \ + PMC_PCR_GCKCSS_UPLL_CLK, \ + 1, \ + } + +#define CFG_SDMMC { \ + PMC_PCR_GCKCSS_PLLA_CLK, \ + 1, \ + } + +static const SamaSDMMCConfig sdmmc_slot1_cfg = { + SDMMC_SLOT1, + { CFG_SDMMC }, + false, +#if SDMMC_USE_TC == 1 + TC0, + 0, +#endif + sdmmcbuffer, + data_buf, + sizeof(data_buf), + dma_table, + DMADL_CNT_MAX +}; + +void getdir(SdmmcDriver *sdmmcp); +/* + * Application entry point. + */ +int main(void) { + + /* + * System initializations. + * - HAL initialization, this also initializes the configured device drivers + * and performs the board-specific initializations. + * - Kernel initialization, the main() function becomes a thread and the + * RTOS is active. + */ + halInit(); + chSysInit(); + + /* + * Activates the serial driver 0 using the driver default configuration. + */ + sdStart(&SD1, &sdcfg); + + /* Redirecting UART0 RX on PD2 and UART0 TX on PD3. */ + palSetGroupMode(PIOD, PAL_PORT_BIT(2) | PAL_PORT_BIT(3), 0U, + PAL_SAMA_FUNC_PERIPH_A | PAL_MODE_SECURE); + + ts = (BaseSequentialStream *) &SD1; + + sdmmcInit(); + + sdmmcStart(&SDMMCD1, &sdmmc_slot1_cfg); + + if (SDMMCD1.state != MCID_INIT_ERROR) { + + chprintf(ts,"starting MMC Demo\n\r"); + + if (sdmmcOpenDevice(&SDMMCD1)) { + + //sdmmcShowDeviceInfo(&SDMMCD1); + if ( sdmmcMountVolume(&SDMMCD1,&fs_header) ) { + chprintf(ts,"reading files:\n\r"); + getdir(&SDMMCD1); + } + sdmmcCloseDevice(&SDMMCD1); + } + + + } else { + chprintf(ts,"error,stopping MMC\n\r"); + sdmmcStop(&SDMMCD1); + } + + /* + * Creates the blinker thread. + */ + chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); + + /* + * Normal main() thread activity, in this demo it does nothing except + * sleeping in a loop and check the button state. + */ + while (true) { + chThdSleepMilliseconds(500); + } +} + + +bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) +{ + if (index == SDMMCD1.config->slot_id) { + *sdmmcp = &SDMMCD1; + return true; + } + return false; +} + +void getdir(SdmmcDriver *sdmmcp) +{ + const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; + DIR dir = { .sect = 0 }; + FILINFO fno = { 0 }; + FRESULT res; + bool is_dir; + + res = f_opendir(&dir, drive_path); + if (res != FR_OK) { + chprintf(ts,"Failed to open dir, error %d\n\r", res); + return; + } + chprintf(ts,"files in the root directory:\n\r"); + for (;;) { + res = f_readdir(&dir, &fno); + if (res != FR_OK) { + chprintf(ts,"cannot read dir, error (%d)\n\r", res); + break; + } + if (fno.fname[0] == '\0') + break; + is_dir = fno.fattrib & AM_DIR ? true : false; + chprintf(ts," %s%s%c\n\r", is_dir ? "[" : "", fno.fname, + is_dir ? ']' : ' '); + } + + res = f_closedir(&dir); +} + + + diff --git a/testhal/ATSAMA5D2/SDMMC/mcuconf.h b/testhal/ATSAMA5D2/SDMMC/mcuconf.h new file mode 100644 index 000000000..0c7f64108 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/mcuconf.h @@ -0,0 +1,137 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define SAMA5D2x_MCUCONF + +/* + * HAL driver system settings. + */ +#define SAMA_HAL_IS_SECURE TRUE +#define SAMA_NO_INIT FALSE +#define SAMA_MOSCRC_ENABLED FALSE +#define SAMA_MOSCXT_ENABLED TRUE +#define SAMA_MOSC_SEL SAMA_MOSC_MOSCXT +#define SAMA_OSC_SEL SAMA_OSC_OSCXT +#define SAMA_MCK_SEL SAMA_MCK_PLLA_CLK +#define SAMA_MCK_PRES_VALUE 1 +#define SAMA_MCK_MDIV_VALUE 3 +#define SAMA_PLLA_MUL_VALUE 83 +#define SAMA_PLLADIV2_EN TRUE +#define SAMA_H64MX_H32MX_RATIO 2 + +/* + * SPI driver system settings. + */ +#define SAMA_SPI_USE_SPI0 FALSE +#define SAMA_SPI_USE_SPI1 FALSE +#define SAMA_SPI_USE_FLEXCOM0 FALSE +#define SAMA_SPI_USE_FLEXCOM1 FALSE +#define SAMA_SPI_USE_FLEXCOM2 FALSE +#define SAMA_SPI_USE_FLEXCOM3 FALSE +#define SAMA_SPI_USE_FLEXCOM4 FALSE +#define SAMA_SPI_SPI0_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_SPI1_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_FLEXCOM0_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_FLEXCOM1_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_FLEXCOM2_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_FLEXCOM3_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_FLEXCOM4_DMA_IRQ_PRIORITY 4 +#define SAMA_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * SERIAL driver system settings. + */ +#define SAMA_SERIAL_USE_UART0 FALSE +#define SAMA_SERIAL_USE_UART1 TRUE +#define SAMA_SERIAL_USE_UART2 FALSE +#define SAMA_SERIAL_USE_UART3 FALSE +#define SAMA_SERIAL_USE_UART4 FALSE +#define SAMA_SERIAL_USE_UART5 FALSE +#define SAMA_SERIAL_USE_FLEXCOM0 FALSE +#define SAMA_SERIAL_USE_FLEXCOM1 FALSE +#define SAMA_SERIAL_USE_FLEXCOM2 FALSE +#define SAMA_SERIAL_USE_FLEXCOM3 FALSE +#define SAMA_SERIAL_USE_FLEXCOM4 FALSE +#define SAMA_SERIAL_UART0_IRQ_PRIORITY 4 +#define SAMA_SERIAL_UART1_IRQ_PRIORITY 4 +#define SAMA_SERIAL_UART2_IRQ_PRIORITY 4 +#define SAMA_SERIAL_UART3_IRQ_PRIORITY 4 +#define SAMA_SERIAL_UART4_IRQ_PRIORITY 4 +#define SAMA_SERIAL_FLEXCOM0_IRQ_PRIORITY 4 +#define SAMA_SERIAL_FLEXCOM1_IRQ_PRIORITY 4 +#define SAMA_SERIAL_FLEXCOM2_IRQ_PRIORITY 4 +#define SAMA_SERIAL_FLEXCOM3_IRQ_PRIORITY 4 +#define SAMA_SERIAL_FLEXCOM4_IRQ_PRIORITY 4 + +/* + * SECUMOD + */ +#define HAL_USE_SECUMOD TRUE + +/* + * TC driver system settings. + */ +#define HAL_USE_TC FALSE +#define SAMA_USE_TC0 FALSE +#define SAMA_USE_TC1 FALSE +#define SAMA_TC0_IRQ_PRIORITY 2 +#define SAMA_TC1_IRQ_PRIORITY 2 + + +/* + * SDMMC driver system settings. + */ +#define HAL_USE_SDMMC TRUE + +/* + * UART driver system settings. + */ +#define SAMA_UART_USE_UART0 FALSE +#define SAMA_UART_USE_UART1 FALSE +#define SAMA_UART_USE_UART2 FALSE +#define SAMA_UART_USE_UART3 FALSE +#define SAMA_UART_USE_UART4 FALSE +#define SAMA_UART_USE_FLEXCOM0 FALSE +#define SAMA_UART_USE_FLEXCOM1 FALSE +#define SAMA_UART_USE_FLEXCOM2 FALSE +#define SAMA_UART_USE_FLEXCOM3 FALSE +#define SAMA_UART_USE_FLEXCOM4 FALSE +#define SAMA_UART_UART0_IRQ_PRIORITY 4 +#define SAMA_UART_UART1_IRQ_PRIORITY 4 +#define SAMA_UART_UART2_IRQ_PRIORITY 4 +#define SAMA_UART_UART3_IRQ_PRIORITY 4 +#define SAMA_UART_UART4_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM0_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM1_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM2_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM3_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM4_IRQ_PRIORITY 4 +#define SAMA_UART_UART0_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_UART1_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_UART2_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_UART3_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_UART4_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM0_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM1_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM2_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM3_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_FLEXCOM4_DMA_IRQ_PRIORITY 4 +#define SAMA_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +#endif /* MCUCONF_H */ diff --git a/testhal/ATSAMA5D2/SDMMC/readme.txt b/testhal/ATSAMA5D2/SDMMC/readme.txt new file mode 100644 index 000000000..cc6e568f6 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/readme.txt @@ -0,0 +1,13 @@ +***************************************************************************** +** ChibiOS/RT port for ARM-A5. ** +***************************************************************************** + +** TARGET ** + +The demo targets a generic ARM Cortex-A5 device without HAL support. + +** The Demo ** + +** Build Procedure ** + +** Notes **