diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c index 8145de2b1..a337ee6d7 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c @@ -53,6 +53,7 @@ uint32_t SdmmcGetMaxFreq(SdmmcDriver *drv) rate /= 2ul; } + TRACE_DEBUG_1("SdmmcGetMaxFreq rate %d\r\n",rate); return rate * 1000ul; } @@ -98,7 +99,7 @@ void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData) uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) { uint64_t mem_size; - //uint32_t freq; + uint32_t freq; uint32_t drv_err, status; uint8_t error; bool flag; @@ -260,14 +261,16 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) : (uint32_t)mem_size; } -//TO BE DONE -#if 0 + /* Automatically select the max device clock frequency */ /* Calculate transfer speed */ freq = SdmmcGetMaxFreq(drv); + #ifndef SDMMC_TRIM_SDIO - if (drv->card.bCardType & CARD_TYPE_bmSDIO) + if (drv->card.bCardType & CARD_TYPE_bmSDIO) { freq = min_u32(freq, SdioGetMaxFreq(drv)); + TRACE_INFO_1("selecting sdio freq%d\r\n",freq); + } #endif error = HwSetClock(drv, &freq); drv->card.dwCurrSpeed = freq; @@ -275,7 +278,7 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) TRACE_ERROR_1("error 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. */ 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 cfe49ebea..4323b5876 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_cmds.c @@ -644,8 +644,8 @@ uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStat pCmd->pResp = pStatus; drv->timeout_elapsed = -1; - /* Send command */ - bRc = sdmmcSendCmd(drv); + /* Send command */ + bRc = sdmmcSendCmd(drv); return bRc; } @@ -680,8 +680,8 @@ uint8_t Cmd24(SdmmcDriver *drv, pCmd->wNbBlocks = 1; pCmd->pData = pData; drv->timeout_elapsed = -1; - /* Send command */ - bRc = sdmmcSendCmd(drv); + /* Send command */ + bRc = sdmmcSendCmd(drv); return bRc; } @@ -719,8 +719,8 @@ uint8_t Cmd25(SdmmcDriver *drv, pCmd->pData = pData; drv->timeout_elapsed = -1; - /* Send command */ - bRc = sdmmcSendCmd(drv); + /* Send command */ + bRc = sdmmcSendCmd(drv); if (bRc == SDMMC_CHANGED) *nbBlock = pCmd->wNbBlocks; return bRc; 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 3f1ad6852..194655c76 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.c @@ -53,7 +53,7 @@ static uint8_t HwReset(SdmmcDriver *driver); static void sdmmc_get_response(SdmmcDriver *driver, sSdmmcCommand *cmd, bool complete, uint32_t *out); -static bool sdmmc_is_busy(SdmmcDriver *driver); + static uint8_t sdmmc_build_dma_table( SdmmcDriver *driver ); static uint8_t unplug_device(SdmmcDriver *driver); static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verify); @@ -70,12 +70,10 @@ uint8_t sdmmc_device_lowlevelcfg(SdmmcDriver *driver) if (driver->config->slot_id == SDMMC_SLOT0) { driver->regs = SDMMC0; - pmcEnableSDMMC0() - ; + pmcEnableSDMMC0(); } else if (driver->config->slot_id == SDMMC_SLOT1) { driver->regs = SDMMC1; - pmcEnableSDMMC1() - ; + pmcEnableSDMMC1(); } switch (driver->config->slot_id) { @@ -704,12 +702,14 @@ void sdmmc_device_deInit(SdmmcDriver *drv) bool use_prog_mode = false; freq = min_u32(freq, 120000000ul); - #ifndef NDEBUG - //if (!(regs->SDMMC_PCR & SDMMC_PCR_SDBPWR)) - // trace_error("Bus is off\n\r"); - //if (regs->SDMMC_HC2R & SDMMC_HC2R_PVALEN) - // trace_error("Preset values enabled though not implemented\n\r"); - #endif + + if (!(regs->SDMMC_PCR & SDMMC_PCR_SDBPWR)) { + TRACE_ERROR("Bus is off\n\r"); + } + if (regs->SDMMC_HC2R & SDMMC_HC2R_PVALEN) { + TRACE_ERROR("Preset values enabled though not implemented\n\r"); + } + /* In the Divided Clock Mode scenario, compute the divider */ base_freq = (regs->SDMMC_CA0R & SDMMC_CA0R_BASECLKF_Msk) >> SDMMC_CA0R_BASECLKF_Pos; base_freq *= 1000000UL; @@ -732,10 +732,10 @@ void sdmmc_device_deInit(SdmmcDriver *drv) * is 32 whereas the real value is 40.5 */ mult_freq = (regs->SDMMC_CA1R & SDMMC_CA1R_CLKMULT_Msk) >> SDMMC_CA1R_CLKMULT_Pos; if (mult_freq != 0) - #if 1 + #if 0 mult_freq = base_freq * (mult_freq + 1); #else - mult_freq = pmc_get_gck_clock(ID_SDMMC0+driver->config->slot_id); + mult_freq = SAMA_MCK ;// pmc_get_gck_clock(ID_SDMMC0+driver->config->slot_id); #endif if (mult_freq != 0) { /* DIV = FMULTCLK / FSDCLK - 1 */ @@ -761,6 +761,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) shval = regs->SDMMC_CCR & ~SDMMC_CCR_SDCLKEN; regs->SDMMC_CCR = shval; driver->dev_freq = new_freq; + use_prog_mode = false; //no generated clock /* Select the clock mode */ if (use_prog_mode) shval |= SDMMC_CCR_CLKGSEL; @@ -1220,7 +1221,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) sdmmc_set_device_clock(driver, driver->control_param); - TRACE_DEBUG_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 @@ -1495,7 +1496,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv) } } -static bool sdmmc_is_busy(SdmmcDriver *driver) +bool sdmmc_is_busy(SdmmcDriver *driver) { //osalDbgCheck(driver->state != MCID_OFF); @@ -1660,13 +1661,13 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif && !(caps & SDMMC_CA0R_V18VSUP)) return SDMMC_PARAM; -#ifndef NDEBUG +#if 0 /* FIXME The datasheet is unclear about CCR:DIV restriction when the MMC * timing mode is High Speed DDR */ if ((mode == SDMMC_TIM_MMC_HS_SDR || mode == SDMMC_TIM_MMC_HS_DDR || mode == SDMMC_TIM_SD_HS) && !(regs->SDMMC_CCR & (SDMMC_CCR_USDCLKFSEL_Msk | SDMMC_CCR_SDCLKFSEL_Msk))) { - //trace_error("Incompatible with the current clock config\n\r"); + TRACE_ERROR("Incompatible with the current clock config\n\r"); return SDMMC_STATE; } #endif @@ -1724,11 +1725,13 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif goto End; toggle_sig_lvl = pcr_prv & SDMMC_PCR_SDBPWR && (pcr ^ pcr_prv) & SDMMC_PCR_SDBVSEL_Msk; - //if (!(pcr_prv & SDMMC_PCR_SDBPWR)) - // trace_debug("Power the device on\n\r"); - //else if (toggle_sig_lvl) - // trace_debug("Signaling level going %s\n\r", - // hc2r & SDMMC_HC2R_VS18EN ? "low" : "high"); + if (!(pcr_prv & SDMMC_PCR_SDBPWR)) { + TRACE_DEBUG("Power the device on\n\r"); + } + else if (toggle_sig_lvl) { + TRACE_DEBUG_1("Signaling level going %s\n\r", + hc2r & SDMMC_HC2R_VS18EN ? "low" : "high"); + } if (verify && toggle_sig_lvl && hc2r & SDMMC_HC2R_VS18EN) { /* Expect this call to follow the VOLTAGE_SWITCH command; * allow 2 device clock periods before the device pulls the CMD @@ -1787,7 +1790,7 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif if (!dev_clk_on) regs->SDMMC_CCR &= ~SDMMC_CCR_SDCLKEN; } - //trace_debug("Using timing mode 0x%02x\n\r", mode); + TRACE_DEBUG_1("Using timing mode 0x%02x\n\r", mode); regs->SDMMC_CALCR = (regs->SDMMC_CALCR & ~SDMMC_CALCR_ALWYSON) | (low_sig ? SDMMC_CALCR_ALWYSON : 0); 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 340feb172..d9c789a20 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_device.h @@ -379,5 +379,6 @@ extern uint8_t SdMmcSelect(SdmmcDriver *drv, uint16_t address, uint8_t statCheck extern uint8_t SdMmcIdentify(SdmmcDriver *drv); extern uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry); extern void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData); +extern bool sdmmc_is_busy(SdmmcDriver *driver); #endif /* CH_SDMMC_DEVICE_H_ */ diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c index 7d764886d..d4e98b885 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c @@ -41,7 +41,8 @@ #include "hal.h" #if (HAL_USE_SDMMC == TRUE) - +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_FF_LIB == 1 #include "ccportab.h" #include "ffconf.h" #include "diskio.h" @@ -309,4 +310,5 @@ DRESULT disk_ioctl(BYTE slot, BYTE cmd, void* buff) return res; } #endif +#endif 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 99ad68962..5ddbdaed9 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c @@ -155,7 +155,7 @@ uint8_t MmcInit(SdmmcDriver *driver) if (error) return error; //else - TRACE_1("RCA=%u\n\r", driver->card.wAddress); + TRACE_DEBUG_1("RCA=%u\n\r", driver->card.wAddress); /* SEND_CSD (CMD9) to obtain the Card Specific Data (CSD register), * e.g. block length, card storage capacity, etc... */ @@ -211,9 +211,8 @@ uint8_t MmcInit(SdmmcDriver *driver) sw_arg.value = 0xf; error = MmcCmd6(driver, &sw_arg, &status); if (error) { - TRACE_1("Pwr class %s\n\r", - SD_StringifyRetCode(error)); - } + TRACE_DEBUG_1("Pwr class %s\n\r",SD_StringifyRetCode(error)); + } } } @@ -274,8 +273,7 @@ uint8_t MmcInit(SdmmcDriver *driver) && tim_mode == SDMMC_TIM_MMC_HS_DDR) driver->card.bSpeedMode = tim_mode; else if (error) { - TRACE_ERROR_1("Width/DDR %s\n\r", - SD_StringifyRetCode(error)); + TRACE_ERROR_1("Width/DDR %s\n\r",SD_StringifyRetCode(error)); return error; } } diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.c new file mode 100644 index 000000000..82dd5e920 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.c @@ -0,0 +1,64 @@ +#include "hal.h" + +#if (HAL_USE_SDMMC == TRUE) + +#include "sama_sdmmc_lld.h" + +#include "ch_sdmmc_device.h" +#include "ch_sdmmc_cmds.h" +#include "ch_sdmmc_sdio.h" +#include "ch_sdmmc_sd.h" +#include "ch_sdmmc_mmc.h" + +#include "ch_sdmmc_reledge.h" + +eSDMMC_RC sd_mmc_test_unit_ready( SdmmcDriver *sdmmcp) +{ + + uint32_t rc; + + if (sdmmc_is_busy(sdmmcp)) + return SDMMC_BUSY; + + rc = SD_GetStatus(sdmmcp); + + if (rc != SDMMC_OK) + { + return rc; + } + + + if ( !(sdmmcp->card.bCardType == CARD_UNKNOWN) ) { + return SDMMC_OK; + } + // It is not a memory card + return SDMMC_ERR; + +} + +bool sd_mmc_is_write_protected(SdmmcDriver *sdmmcp) +{ + uint32_t rc; + + rc = SD_GetWpStatus(sdmmcp); + + return (rc == SDMMC_LOCKED); +} + + + +eSDMMC_RC sd_mmc_read_capacity(SdmmcDriver *sdmmcp, uint32_t *nb_sector) +{ + // Return last sector address (-1) + *nb_sector = sdmmcp->card.dwNbBlocks - 1; + + return sd_mmc_test_unit_ready(sdmmcp); +} + + + + + +#endif + + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.h b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.h new file mode 100644 index 000000000..04ed471cf --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.h @@ -0,0 +1,14 @@ + +#ifndef CH_SDMMC_RELEDGE_H_ +#define CH_SDMMC_RELEDGE_H_ + + + + +extern eSDMMC_RC sd_mmc_test_unit_ready( SdmmcDriver *sdmmcp); +extern bool sd_mmc_is_write_protected(SdmmcDriver *sdmmcp); +extern eSDMMC_RC sd_mmc_read_capacity(SdmmcDriver *sdmmcp, uint32_t *nb_sector); + + + +#endif /* CH_SDMMC_RELEDGE_H_ */ 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 a27d0b819..ed2286bbc 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c @@ -479,6 +479,29 @@ void SdParamReset(sSdCard * pSd) memset(pSd->SCR, 0, SCR_SIZE); } +/** + * Query whether the card is writeprotected or not by mechanical + write protect switch. + * \param pSd Pointer to \ref sSdCard instance. + * \return an \ref sdmmc_rc "error code", as follows: + * - SDMMC_LOCKED if the device has been mechanical write protected. + * - SDMMC_OK if the card is not write-protected. + */ +uint8_t SD_GetWpStatus(SdmmcDriver *driver) +{ + uint32_t rc; + + driver->control_param = 0; + + rc = sdmmc_device_control(driver,SDMMC_IOCTL_GET_WP); + + if (rc != SDMMC_OK) + return SDMMC_NOT_SUPPORTED; + if (!driver->control_param) + return SDMMC_LOCKED; + else + return SDMMC_OK; +} /** 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 7708a88f1..b9d6a6ccc 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.h @@ -112,5 +112,6 @@ extern uint8_t SD_Write(SdmmcDriver *driver,uint32_t address,const void *pData,u 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); +extern uint8_t SD_GetWpStatus(SdmmcDriver *driver); #endif /* CH_SDMMC_SD_H_ */ diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk index 5b31411d5..06bb80865 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/driver.mk @@ -5,6 +5,13 @@ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.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/osassert.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osoutput.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osclock.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osbdev.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osmutex.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ostask.c \ + $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.c \ $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1 diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/osassert.c b/os/hal/ports/SAMA/LLD/SDMMCv1/osassert.c new file mode 100644 index 000000000..c4cc20497 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/osassert.c @@ -0,0 +1,62 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Implements assertion handling. +*/ +#include "hal.h" +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 +#include + +#if REDCONF_ASSERTS == 1 + +#include + + +/** @brief Invoke the native assertion handler. + + @param pszFileName Null-terminated string containing the name of the file + where the assertion fired. + @param ulLineNum Line number in @p pszFileName where the assertion + fired. +*/ +void RedOsAssertFail( + const char *pszFileName, + uint32_t ulLineNum) +{ + #if REDCONF_OUTPUT == 1 + IGNORE_ERRORS(PRINT_ASSERT(pszFileName, ulLineNum)); + #endif + + while(true) + { + } +} + +#endif + +#endif +#endif diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/osbdev.c b/os/hal/ports/SAMA/LLD/SDMMCv1/osbdev.c new file mode 100644 index 000000000..645201521 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/osbdev.c @@ -0,0 +1,515 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Implements block device I/O. +*/ +#include "hal.h" + +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 + +#include "sama_sdmmc_lld.h" +#include "ch_sdmmc_device.h" +#include "ch_sdmmc_cmds.h" +#include "ch_sdmmc_sdio.h" +#include "ch_sdmmc_sd.h" +#include "ch_sdmmc_mmc.h" +#include "ch_sdmmc_reledge.h" + +#include +#include +#include + +#if REDCONF_API_POSIX == 0 +#error "REDCONF_API_POSIX should be 1" +#endif + +#if REDCONF_API_FSE == 1 +#error "REDCONF_API_FSE not supported, should be 0" +#endif + + +/* sd_mmc_mem_2_ram_multi() and sd_mmc_ram_2_mem_multi() use an unsigned + 16-bit value to specify the sector count, so no transfer can be larger + than UINT16_MAX sectors. +*/ +#define MAX_SECTOR_TRANSFER UINT16_MAX + + +/** @brief Initialize a disk. + + @param bVolNum The volume number of the volume whose block device is being + initialized. + @param mode The open mode, indicating the type of access required. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. + @retval -RED_EIO A disk I/O error occurred. + @retval -RED_EROFS The device is read-only media and write access was + requested. +*/ +static REDSTATUS DiskOpen( + uint8_t bVolNum, + BDEVOPENMODE mode) +{ + REDSTATUS ret = 0; + uint32_t ulTries; + + + eSDMMC_RC cs; + + SdmmcDriver *sdmmcp = NULL; + + + if (!sdmmcGetInstance(bVolNum, &sdmmcp)) + return RED_EINVAL; + + /* Note: Assuming the volume number is the same as the SD card slot. The + ASF SD/MMC driver supports two SD slots. This implementation will need + to be modified if multiple volumes share a single SD card. + */ + + /* The first time the disk is opened, the SD card can take a while to get + ready, in which time sd_mmc_test_unit_ready() returns either CTRL_BUSY + or CTRL_NO_PRESENT. Try numerous times, waiting half a second after + each failure. Empirically, this has been observed to succeed on the + second try, so trying 10x more than that provides a margin of error. + */ + for(ulTries = 0U; ulTries < 20U; ulTries++) + { + cs = sd_mmc_test_unit_ready(sdmmcp); + + if((cs != SDMMC_OK) && (cs != SDMMC_BUSY)) + { + break; + } + + // t_msleep(sdmmcp,500); + } + + if(cs == SDMMC_OK) + { + #if REDCONF_READ_ONLY == 0 + if(mode != BDEV_O_RDONLY) + { + if(sd_mmc_is_write_protected(sdmmcp)) + { + ret = -RED_EROFS; + } + } + + if(ret == 0) + #endif + { + uint32_t ulSectorLast; + + IGNORE_ERRORS(sd_mmc_read_capacity(sdmmcp, &ulSectorLast)); + + /* The ASF SD/MMC driver only supports 512-byte sectors. + */ + if( (gaRedVolConf[bVolNum].ulSectorSize != 512U) + || (((uint64_t)ulSectorLast + 1U) < gaRedVolConf[bVolNum].ullSectorCount)) + { + ret = -RED_EINVAL; + } + } + } + else + { + ret = -RED_EIO; + } + + return ret; +} + + +/** @brief Uninitialize a disk. + + @param bVolNum The volume number of the volume whose block device is being + uninitialized. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +static REDSTATUS DiskClose( + uint8_t bVolNum) +{ + (void)bVolNum; + return 0; +} + + +/** @brief Read sectors from a disk. + + @param bVolNum The volume number of the volume whose block device + is being read from. + @param ullSectorStart The starting sector number. + @param ulSectorCount The number of sectors to read. + @param pBuffer The buffer into which to read the sector data. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +static REDSTATUS DiskRead( + uint8_t bVolNum, + uint64_t ullSectorStart, + uint32_t ulSectorCount, + void *pBuffer) +{ + REDSTATUS ret = 0; + uint8_t *pbBuffer = CAST_VOID_PTR_TO_UINT8_PTR(pBuffer); + + SdmmcDriver *sdmmcp = NULL; + eSDMMC_RC cs; + + if (!sdmmcGetInstance(bVolNum, &sdmmcp)) + return RED_EINVAL; + + cs = SD_ReadBlocks(sdmmcp, ullSectorStart, pbBuffer,ulSectorCount); + + if(cs != SDMMC_OK) + { + ret = -RED_EIO; + } + + + return ret; +} + + +#if REDCONF_READ_ONLY == 0 + +/** @brief Write sectors to a disk. + + @param bVolNum The volume number of the volume whose block device + is being written to. + @param ullSectorStart The starting sector number. + @param ulSectorCount The number of sectors to write. + @param pBuffer The buffer from which to write the sector data. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +static REDSTATUS DiskWrite( + uint8_t bVolNum, + uint64_t ullSectorStart, + uint32_t ulSectorCount, + const void *pBuffer) +{ + REDSTATUS ret = 0; + const uint8_t *pbBuffer = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pBuffer); + + SdmmcDriver *sdmmcp = NULL; + eSDMMC_RC cs; + + if (!sdmmcGetInstance(bVolNum, &sdmmcp)) + return RED_EINVAL; + + + cs = SD_WriteBlocks(sdmmcp, ullSectorStart, pbBuffer, ulSectorCount); + if(cs != SDMMC_OK) + { + ret = -RED_EIO; + } + + + return ret; +} + + +/** @brief Flush any caches beneath the file system. + + @param bVolNum The volume number of the volume whose block device is being + flushed. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +static REDSTATUS DiskFlush( + uint8_t bVolNum) +{ + REDSTATUS ret; + + eSDMMC_RC cs; + + SdmmcDriver *sdmmcp = NULL; + + + if (!sdmmcGetInstance(bVolNum, &sdmmcp)) + return RED_EINVAL; + + /* The ASF SD/MMC driver appears to write sectors synchronously, so it + should be fine to do nothing and return success. However, Atmel's + implementation of the FatFs diskio.c file does the equivalent of the + below when the disk is flushed. Just in case this is important for some + non-obvious reason, do the same. + */ + cs = sd_mmc_test_unit_ready(sdmmcp); + if(cs == SDMMC_OK) + { + ret = 0; + } + else + { + ret = -RED_EIO; + } + + return ret; +} + + +#if REDCONF_DISCARDS == 1 +/** @brief Discard sectors on a disk. + + @param bVolNum The volume number of the volume whose block device + is being accessed. + @param ullSectorStart The starting sector number. + @param ullSectorCount The number of sectors to discard. +*/ +static void DiskDiscard( + uint8_t bVolNum, + uint64_t ullSectorStart, + uint64_t ullSectorCount) +{ +#error "this SD/MMC driver does not support discards." +} +#endif /* REDCONF_DISCARDS == 1 */ + +#endif /* REDCONF_READ_ONLY == 0 */ + +/** @brief Initialize a block device. + + This function is called when the file system needs access to a block + device. + + Upon successful return, the block device should be fully initialized and + ready to service read/write/flush/close requests. + + The behavior of calling this function on a block device which is already + open is undefined. + + @param bVolNum The volume number of the volume whose block device is being + initialized. + @param mode The open mode, indicating the type of access required. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. + @retval -RED_EINVAL @p bVolNum is an invalid volume number. + @retval -RED_EIO A disk I/O error occurred. +*/ +REDSTATUS RedOsBDevOpen( + uint8_t bVolNum, + BDEVOPENMODE mode) +{ + REDSTATUS ret; + + if(bVolNum >= REDCONF_VOLUME_COUNT) + { + ret = -RED_EINVAL; + } + else + { + ret = DiskOpen(bVolNum, mode); + } + + return ret; +} + + +/** @brief Uninitialize a block device. + + This function is called when the file system no longer needs access to a + block device. If any resource were allocated by RedOsBDevOpen() to service + block device requests, they should be freed at this time. + + Upon successful return, the block device must be in such a state that it + can be opened again. + + The behavior of calling this function on a block device which is already + closed is undefined. + + @param bVolNum The volume number of the volume whose block device is being + uninitialized. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. + @retval -RED_EINVAL @p bVolNum is an invalid volume number. +*/ +REDSTATUS RedOsBDevClose( + uint8_t bVolNum) +{ + REDSTATUS ret; + + if(bVolNum >= REDCONF_VOLUME_COUNT) + { + ret = -RED_EINVAL; + } + else + { + ret = DiskClose(bVolNum); + } + + return ret; +} + + +/** @brief Read sectors from a physical block device. + + The behavior of calling this function is undefined if the block device is + closed or if it was opened with ::BDEV_O_WRONLY. + + @param bVolNum The volume number of the volume whose block device + is being read from. + @param ullSectorStart The starting sector number. + @param ulSectorCount The number of sectors to read. + @param pBuffer The buffer into which to read the sector data. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. + @retval -RED_EINVAL @p bVolNum is an invalid volume number, @p pBuffer is + `NULL`, or @p ullStartSector and/or @p ulSectorCount + refer to an invalid range of sectors. + @retval -RED_EIO A disk I/O error occurred. +*/ +REDSTATUS RedOsBDevRead( + uint8_t bVolNum, + uint64_t ullSectorStart, + uint32_t ulSectorCount, + void *pBuffer) +{ + REDSTATUS ret = 0; + + if( (bVolNum >= REDCONF_VOLUME_COUNT) + || (ullSectorStart >= gaRedVolConf[bVolNum].ullSectorCount) + || ((gaRedVolConf[bVolNum].ullSectorCount - ullSectorStart) < ulSectorCount) + || (pBuffer == NULL)) + { + ret = -RED_EINVAL; + } + else + { + ret = DiskRead(bVolNum, ullSectorStart, ulSectorCount, pBuffer); + } + + return ret; +} + + +#if REDCONF_READ_ONLY == 0 + +/** @brief Write sectors to a physical block device. + + The behavior of calling this function is undefined if the block device is + closed or if it was opened with ::BDEV_O_RDONLY. + + @param bVolNum The volume number of the volume whose block device + is being written to. + @param ullSectorStart The starting sector number. + @param ulSectorCount The number of sectors to write. + @param pBuffer The buffer from which to write the sector data. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. + @retval -RED_EINVAL @p bVolNum is an invalid volume number, @p pBuffer is + `NULL`, or @p ullStartSector and/or @p ulSectorCount + refer to an invalid range of sectors. + @retval -RED_EIO A disk I/O error occurred. +*/ +REDSTATUS RedOsBDevWrite( + uint8_t bVolNum, + uint64_t ullSectorStart, + uint32_t ulSectorCount, + const void *pBuffer) +{ + REDSTATUS ret = 0; + + if( (bVolNum >= REDCONF_VOLUME_COUNT) + || (ullSectorStart >= gaRedVolConf[bVolNum].ullSectorCount) + || ((gaRedVolConf[bVolNum].ullSectorCount - ullSectorStart) < ulSectorCount) + || (pBuffer == NULL)) + { + ret = -RED_EINVAL; + } + else + { + ret = DiskWrite(bVolNum, ullSectorStart, ulSectorCount, pBuffer); + } + + return ret; +} + + +/** @brief Flush any caches beneath the file system. + + This function must synchronously flush all software and hardware caches + beneath the file system, ensuring that all sectors written previously are + committed to permanent storage. + + If the environment has no caching beneath the file system, the + implementation of this function can do nothing and return success. + + The behavior of calling this function is undefined if the block device is + closed or if it was opened with ::BDEV_O_RDONLY. + + @param bVolNum The volume number of the volume whose block device is being + flushed. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. + @retval -RED_EINVAL @p bVolNum is an invalid volume number. + @retval -RED_EIO A disk I/O error occurred. +*/ +REDSTATUS RedOsBDevFlush( + uint8_t bVolNum) +{ + REDSTATUS ret; + + if(bVolNum >= REDCONF_VOLUME_COUNT) + { + ret = -RED_EINVAL; + } + else + { + ret = DiskFlush(bVolNum); + } + + return ret; +} + +#endif /* REDCONF_READ_ONLY == 0 */ +#endif + +#endif diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/osclock.c b/os/hal/ports/SAMA/LLD/SDMMCv1/osclock.c new file mode 100644 index 000000000..e140e6e28 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/osclock.c @@ -0,0 +1,85 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Implements real-time clock functions. +*/ +#include "hal.h" +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 +#include + + +/** @brief Initialize the real time clock. + + The behavior of calling this function when the RTC is already initialized + is undefined. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +REDSTATUS RedOsClockInit(void) +{ + return 0; +} + + +/** @brief Uninitialize the real time clock. + + The behavior of calling this function when the RTC is not initialized is + undefined. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +REDSTATUS RedOsClockUninit(void) +{ + return 0; +} + + +/** @brief Get the date/time. + + The behavior of calling this function when the RTC is not initialized is + undefined. + + @return The number of seconds since January 1, 1970 excluding leap seconds + (in other words, standard Unix time). If the resolution or epoch + of the RTC is different than this, the implementation must convert + it to the expected representation. +*/ +uint32_t RedOsClockGetTime(void) +{ + /* FreeRTOS does not provide an RTC abstraction since most of the systems + it targets have no RTC hardware. If your hardware includes an RTC that + you would like to use, this function must be customized. + */ + return 0; +} +#endif +#endif + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/osmutex.c b/os/hal/ports/SAMA/LLD/SDMMCv1/osmutex.c new file mode 100644 index 000000000..b921a8aa9 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/osmutex.c @@ -0,0 +1,108 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Implements a synchronization object to provide mutual exclusion. +*/ +#include "ch.h" +#include "hal.h" +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 +#include +#include + +#if REDCONF_TASK_COUNT > 1U + + +static semaphore_t red_sem; + + +/** @brief Initialize the mutex. + + After initialization, the mutex is in the released state. + + The behavior of calling this function when the mutex is still initialized + is undefined. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +REDSTATUS RedOsMutexInit(void) +{ + chSemObjectInit(&red_sem, 1); + + return 0; +} + + +/** @brief Uninitialize the mutex. + + The behavior of calling this function when the mutex is not initialized is + undefined; likewise, the behavior of uninitializing the mutex when it is + in the acquired state is undefined. + + @return A negated ::REDSTATUS code indicating the operation result. + + @retval 0 Operation was successful. +*/ +REDSTATUS RedOsMutexUninit(void) +{ + chSemReset(&red_sem, 0); + + return 0; +} + + +/** @brief Acquire the mutex. + + The behavior of calling this function when the mutex is not initialized is + undefined; likewise, the behavior of recursively acquiring the mutex is + undefined. +*/ +void RedOsMutexAcquire(void) +{ + chSemWaitTimeout(&red_sem, TIME_INFINITE); +} + + +/** @brief Release the mutex. + + The behavior is undefined in the following cases: + + - Releasing the mutex when the mutex is not initialized. + - Releasing the mutex when it is not in the acquired state. + - Releasing the mutex from a task or thread other than the one which + acquired the mutex. +*/ +void RedOsMutexRelease(void) +{ + chSemSignal(&red_sem); +} + +#endif +#endif +#endif + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/osoutput.c b/os/hal/ports/SAMA/LLD/SDMMCv1/osoutput.c new file mode 100644 index 000000000..bff230522 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/osoutput.c @@ -0,0 +1,76 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Implements outputting a character string. +*/ +#include "hal.h" +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 +#include + +#if REDCONF_OUTPUT == 1 + +#include + + +/** @brief Write a string to a user-visible output location. + + Write a null-terminated string to the serial port, console, terminal, or + other display device, such that the text is visible to the user. + + @param pszString A null-terminated string. +*/ +void RedOsOutputString( + const char *pszString) +{ + if(pszString == NULL) + { + REDERROR(); + } + else + { + uint32_t ulIdx = 0U; + + while(pszString[ulIdx] != '\0') + { + OUTPUT_CHARACTER(pszString[ulIdx]); + + /* Serial output often requires a \r to print newlines correctly. + */ + if(pszString[ulIdx] == '\n') + { + OUTPUT_CHARACTER('\r'); + } + + ulIdx++; + } + } +} + +#endif + +#endif +#endif diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ostask.c b/os/hal/ports/SAMA/LLD/SDMMCv1/ostask.c new file mode 100644 index 000000000..f06f00f22 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/ostask.c @@ -0,0 +1,68 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Implements task functions. +*/ +#include "ch.h" +#include "hal.h" +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 +#include + +#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1) + +#include + + +/** @brief Get the current task ID. + + This task ID must be unique for all tasks using the file system. + + @return The task ID. Must not be 0. +*/ +uint32_t RedOsTaskId(void) +{ + /* Simply casting the xTaskGetCurrentTaskHandle() return value results in + warnings from some compilers, so use variables. + */ + thread_t* t= chThdGetSelfX(); + uintptr_t taskptr = CAST_TASK_PTR_TO_UINTPTR(t); + uint32_t ulTaskPtr = (uint32_t)taskptr; + + /* Assert no information was lost casting from uintptr_t to uint32_t. + */ + REDASSERT(ulTaskPtr == taskptr); + + /* NULL is a valid task handle in FreeRTOS, so add one to all task IDs. + */ + REDASSERT((ulTaskPtr + 1U) != 0U); + return ulTaskPtr + 1U; +} + +#endif + +#endif +#endif diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/redosdeviations.h b/os/hal/ports/SAMA/LLD/SDMMCv1/redosdeviations.h new file mode 100644 index 000000000..b00fc4184 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/redosdeviations.h @@ -0,0 +1,245 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Macros to encapsulate MISRA C:2012 deviations in OS-specific code. +*/ +#ifndef REDOSDEVIATIONS_H +#define REDOSDEVIATIONS_H + + +#if REDCONF_OUTPUT == 1 +/* Needed for PRINT_ASSERT() and OUTPUT_CHARACTER(). +*/ +#include +#endif + + +#if (REDCONF_ASSERTS == 1) && (REDCONF_OUTPUT == 1) +/** @brief Print a formatted message for an assertion. + + Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required). Using + printf() is the most convenient way to output this information; and the risk + of "unspecified, undefined and implementation-defined" behavior causing + problems (as cited in the rationale for the rule) is small. The driver does + not depend on this string being outputted correctly. Furthermore, use of + printf() disappears when either asserts or output are disabled. + + As Rule 21.6 is required, a separate deviation record is required. +*/ +#define PRINT_ASSERT(file, line) \ + printf("Assertion failed in \"%s\" at line %u\n\r", ((file) == NULL) ? "" : (file), (unsigned)(line)) +#endif + + +/** @brief Cast a value to unsigned long. + + Usages of this macro deviate from MISRA C:2012 Directive 4.6. This macro is + used in two places to cast a uint64_t value (used by the block device + abstraction for sector numbers) to unsigned long, since third-party code + which is not under the control of this project uses unsigned long for sector + numbers. The cast is guaranteed to not lose any information, since when the + disk is opened the sector count is verified to be less than or equal to an + unsigned long value. The text of the directive mentions that "it might be + desirable not to apply this guideline when interfacing with ... code outside + the project's control", which describes the situation for this deviation. + + As Directive 4.6 is advisory, a deviation record is not required. This + notice is the only record of the deviation. +*/ +#define CAST_ULONG(ull) ((unsigned long)(ull)) + + +/** @brief Cast a const-qualified pointer to a pointer which is *not* + const-qualified. + + Usages of this macro deviate from MISRA C:2012 Rule 11.8. This macro is + used in exactly one place in order to cope with a poorly designed + third-party interface. Reliance Edge, at every level of the stack, uses + const-qualified pointers for buffers used in write operations, since the + data is read from the buffer, and the buffer does not need to be modified + (consistent with Rule 8.13). One of the third-party block device interfaces + that Reliance Edge interfaces with does not follow this convention: it uses + an unqualified pointer for the buffer parameter of its sector write + function. This forces the need for the cast to avoid warnings. The + implementation of the sector write function is provided by the user, so it + is to be hoped that the buffer is not actually modified. + + As Rule 11.8 is required, a separate deviation record is required. +*/ +#define CAST_AWAY_CONST(type, ptr) ((type *)(ptr)) + + +/** @brief Allocate zero-initialized (cleared) memory. + + All usages of this macro deviate from MISRA C:2012 Directive 4.12 (required) + and Rule 21.3 (required). In the context of the single place it is actually + used, this macro also deviates from Rule 22.1 (required). + + This macro is used in the FreeRTOS block device code in order to allocate a + RAM disk, when that implementation of the block device is selected. The + primary rationale for all these deviations is that a) the RAM disk cannot be + allocated statically (since the volume information is stored in a + structure), and b) the RAM disk is primarily intended as a temporary testing + tool for users who want to try out Reliance Edge before the real storage + media is available. In most real systems, Reliance Edge is used with + non-volatile storage like SD/MMC or eMMC, not with RAM disks. + + Rule 22.1 states that all resources which are allocated must also be + explicitly freed. The RAM disk is allocated and never freed, deviating from + that rule. This is done because the data in the RAM disk is emulating a + non-volatile storage medium, and thus needs to persist even after the block + device is closed, to allow the file system to be ormatted and then mounted, + or unmounted and remounted in the course of a test. Thus the memory will + remain allocated until the target device is rebooted. This is assumed to be + acceptable for the primary purpose of the RAM disk, which is preliminary + testing. + + As Directive 4.12, Rule 21.3, and Rule 22.1 are all required, separate + deviation records are required. +*/ +#define ALLOCATE_CLEARED_MEMORY(nelem, elsize) calloc(nelem, elsize) + + +#if REDCONF_OUTPUT == 1 +/** @brief Output a character to a serial port or other display device. + + Usages of this macro deviate from MISRA C:2012 Rule 21.6 (required). + FreeRTOS does not include a standard method of printing characters, so + putchar() is the most convenient and portable way to accomplish the task. + The risk of "unspecified, undefined and implementation-defined" behavior + causing problems (as cited in the rationale for the rule) is small. The + driver does not depend on the character being outputted correctly. + Furthermore, use of putchar() disappears when output is disabled. + + As Rule 21.6 is required, a separate deviation record is required. +*/ +#define OUTPUT_CHARACTER(ch) (void)putchar(ch) +#endif + + +#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1) +/** @brief Cast a TaskHandle_t (a pointer type) to uintptr_t. + + Usage of this macro deivate from MISRA-C:2012 Rule 11.4 (advisory). This + macro is used for the FreeRTOS version of RedOsTaskId(). Some RTOSes + natively use an integer for task IDs; others use pointers. RedOsTaskId() + uses integers, FreeRTOS uses pointers; to reconcile this difference, the + pointer must be cast to integer. This is fairly safe, since the resulting + integer is never cast back to a pointer; and although the integer + representation of a pointer is implementation-defined, the representation is + irrelevant provided that unique pointers are converted to unique integers. + + As Rule 11.4 is advisory, a deviation record is not required. This notice + is the only record of the deviation. +*/ +#define CAST_TASK_PTR_TO_UINTPTR(taskptr) ((uintptr_t)(taskptr)) +#endif + + +/** @brief Ignore the return value of a function (cast to void) + + Usages of this macro deviate from MISRA C:2012 Directive 4.7, which states + that error information must be checked immediately after a function returns + potential error information. + + If asserts and output are enabled, then this macro is used to document that + the return value of printf() is ignored. A failure of printf() does not + impact the filesystem core, nor is there anything the filesystem can do to + respond to such an error (especially since it occurs within an assert). + Thus, the most reasonable action is to ignore the error. + + In the STM32 SDIO block device implementation, errors are also ignored in an + IRQ interrupt handler. This is the most reasonable action to take for two + reasons: (a) it would be dangerous to spend processor time responding to the + error inside the IRQ handler; (b) it has been verified that the same error + is propegated to the DiskRead/Write method, which does return the error to + the core. + + In the Atmel SD/MMC block device implementation, error information from + sd_mmc_read_capacity() is ignored. This is a reasonable action because all + of the possible error conditions were eliminated by a previous check. + sd_mmc_read_capacity() fails under the same conditions as + sd_mmc_test_unit_ready(), which was checked ealier in the same function. + + In the mutex module, error information returned from the mutex release + function is ignored when asserts are disabled. This is a reasonable action + because the mutex release function (xSemaphoreGive) is documented only to + fail if the mutex was not obtained correctly, which can be demonstrably + avoided. + + As Directive 4.7 is required, a separate deviation record is required. +*/ +#define IGNORE_ERRORS(fn) ((void) (fn)) + + +/** @brief Determine whether a pointer is aligned on a 32-bit boundary. + + This is used to determine whether a data buffer meets the requirements of + the underlying block device implementation. When transferring data via + DMA (Direct Memory Access) on an STM32 device, the data buffer must be cast + as a uint32 pointer, and unexpected behavior may occur if the buffer is not + aligned correctly. + + There is no way to perform this check without deviating from MISRA C rules + against casting pointers to integer types. Usage of this macro deviates + from MISRA C:2012 Rule 11.4 (advisory). The main rationale the rule cites + against converting pointers to integers is that the chosen integer type may + not be able to represent the pointer; this is a non-issue here since we use + uintptr_t. The text says the rule still applies when using uintptr_t due to + concern about unaligned pointers, but that is not an issue here since the + integer value of the pointer is not saved and not converted back into a + pointer and dereferenced. The result of casting a pointer to a sufficiently + large integer is implementation-defined, but macros similar to this one have + been used by Datalight for a long time in a wide variety of environments and + they have always worked as expected. + + This deviation only occurs when using the STM32 SDIO block device + implementation. + + As Rule 11.4 is advisory, a deviation record is not required. This notice + is the only record of deviation. +*/ +#define IS_UINT32_ALIGNED_PTR(ptr) (((uintptr_t)(ptr) & (sizeof(uint32_t) - 1U)) == 0U) + + +/** @brief Cast a 32-bit aligned void pointer to a uint32 pointer. + + Usages of this macro deviate from MISRA C:2012 Rule 11.5 (advisory). A + cast from a void pointer to an object pointer is discouraged because of + potential alignment issues. However, this macro is only used to cast + pointers that have already been tested to be 32-bit aligned, so the + operation will be safe. + + This deviation only occurs when using the STM32 SDIO block device + implementation. + + As rule 11.5 is advisory, a deviation record is not required. This notice + is the only record of the deviation. +*/ +#define CAST_UINT32_PTR(ptr) ((uint32_t *) (ptr)) + + +#endif + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/redostypes.h b/os/hal/ports/SAMA/LLD/SDMMCv1/redostypes.h new file mode 100644 index 000000000..687b2d167 --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/redostypes.h @@ -0,0 +1,42 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Defines OS-specific types for use in common code. +*/ +#ifndef REDOSTYPES_H +#define REDOSTYPES_H + + +/** @brief Implementation-defined timestamp type. + + This can be an integer, a structure, or a pointer: anything that is + convenient for the implementation. Since the underlying type is not fixed, + common code should treat this as an opaque type. +*/ +typedef uint32_t REDTIMESTAMP; + + +#endif + diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/redtypes.h b/os/hal/ports/SAMA/LLD/SDMMCv1/redtypes.h new file mode 100644 index 000000000..bb5606eef --- /dev/null +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/redtypes.h @@ -0,0 +1,98 @@ +/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <---- + + Copyright (c) 2014-2017 Datalight, Inc. + All Rights Reserved Worldwide. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; use version 2 of the License. + + This program is distributed in the hope that it will be useful, + but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* Businesses and individuals that for commercial or other reasons cannot + comply with the terms of the GPLv2 license may obtain a commercial license + before incorporating Reliance Edge into proprietary software for + distribution in any form. Visit http://www.datalight.com/reliance-edge for + more information. +*/ +/** @file + @brief Defines basic types used by Reliance Edge. + + The following types *must* be defined by this header, either directly (using + typedef) or indirectly (by including other headers, such as the C99 headers + stdint.h and stdbool.h): + + - bool: Boolean type, capable of storing true (1) or false (0) + - uint8_t: Unsigned 8-bit integer + - int8_t: Signed 8-bit integer + - uint16_t: Unsigned 16-bit integer + - int16_t: Signed 16-bit integer + - uint32_t: Unsigned 32-bit integer + - int32_t: Signed 32-bit integer + - uint64_t: Unsigned 64-bit integer + - int64_t: Signed 64-bit integer + - uintptr_t: Unsigned integer capable of storing a pointer, preferably the + same size as pointers themselves. + + These types deliberately use the same names as the standard C99 types, so + that if the C99 headers stdint.h and stdbool.h are available, they may be + included here. + + If the user application defines similar types, those may be reused. For + example, suppose there is an application header apptypes.h which defines + types with a similar purpose but different names. That header could be + reused to define the types Reliance Edge needs: + + ~~~{.c} + #include + + typedef BOOL bool; + typedef BYTE uint8_t; + typedef INT8 int8_t; + // And so on... + ~~~ + + If there are neither C99 headers nor suitable types in application headers, + this header should be populated with typedefs that define the required types + in terms of the standard C types. This requires knowledge of the size of + the C types on the target hardware (e.g., how big is an "int" or a pointer). + Below is an example which assumes the target has 8-bit chars, 16-bit shorts, + 32-bit ints, 32-bit pointers, and 64-bit long longs: + + ~~~{.c} + typedef int bool; + typedef unsigned char uint8_t; + typedef signed char int8_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned long long uint64_t; + typedef long long int64_t; + typedef uint32_t uintptr_t; + ~~~ +*/ +#ifndef REDTYPES_H +#define REDTYPES_H + +#include "hal.h" + +/* Defines bool. +*/ +//#include + +/* Defines uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, + int64_t, and uintptr_t. +*/ +//#include + + +#endif + 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 72314ba1a..74dde4632 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_conf.h @@ -3,19 +3,19 @@ #include "ch_sdmmc_sama5d2.h" -#include "ff.h" -typedef FATFS CH_SDMMC_FAT; + + #ifndef SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY #define SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY 4 #endif #ifndef SAMA_SDMMC_TRACE -#define SAMA_SDMMC_TRACE 0 +#define SAMA_SDMMC_TRACE 0 #endif #ifndef SAMA_SDMMC_TRACE_LEVEL -#define SAMA_SDMMC_TRACE_LEVEL 0 +#define SAMA_SDMMC_TRACE_LEVEL 5 #endif /** Default block size for SD/MMC access */ @@ -24,6 +24,13 @@ typedef FATFS CH_SDMMC_FAT; #endif +#ifndef SDMMC_USE_FF_LIB +#define SDMMC_USE_FF_LIB 1 +#endif + +#ifndef SDMMC_USE_RELEDGE_LIB +#define SDMMC_USE_RELEDGE_LIB 1 +#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 dadca65b7..6aa83624b 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c @@ -87,9 +87,6 @@ OSAL_IRQ_HANDLER(SAMA_SDMMCD1_HANDLER) { void sdmmcInit(void) { #if PLATFORM_SDMMC_USE_SDMMC1 == TRUE -#if SAMA_HAL_IS_SECURE - mtxConfigPeriphSecurity(MATRIX0, ID_SDMMC1, SECURE_PER); -#endif /* SAMA_HAL_IS_SECURE */ /* Driver initialization.*/ sdmmcObjectInit(&SDMMCD1); #endif @@ -110,6 +107,10 @@ void sdmmcStart(SdmmcDriver *sdmmcp, const SamaSDMMCConfig *config) sdmmcp->config = config; +#if SAMA_HAL_IS_SECURE + mtxConfigPeriphSecurity(MATRIX0, (ID_SDMMC0 + sdmmcp->config->slot_id) , SECURE_PER); +#endif /* SAMA_HAL_IS_SECURE */ + sdmmcp->card.EXT = sdmmcp->config->bp; sdmmcp->card.SSR = &sdmmcp->config->bp[EXT_SIZE]; sdmmcp->card.SCR = &sdmmcp->config->bp[EXT_SIZE + SSR_SIZE]; @@ -307,37 +308,6 @@ bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp) return true; } -bool sdmmcMountVolume(SdmmcDriver *sdmmcp, CH_SDMMC_FAT *fs) -{ - FRESULT res; - 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_INFO_1("Failed to mount FAT file system, error %d\n\r", res); - return false; - } - - return true; -} - - - -bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp) -{ - const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; - FRESULT res; - bool rc = true; - - res = f_mount(NULL, drive_path, 0); - if (res != FR_OK) - rc = false; - - return rc; - -} bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) { 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 c87c90525..a340f7786 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h +++ b/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.h @@ -127,7 +127,7 @@ struct SamaSDMMCDriver }; -typedef sSdCard sdmmclib; + typedef struct SamaSDMMCDriver SdmmcDriver; /*===========================================================================*/ @@ -154,8 +154,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp); bool sdmmcOpenDevice(SdmmcDriver *sdmmcp); bool sdmmcCloseDevice(SdmmcDriver *sdmmcp); bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp); -bool sdmmcMountVolume(SdmmcDriver *sdmmcp,CH_SDMMC_FAT *fs); -bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp); +bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) ; #ifdef __cplusplus } diff --git a/os/various/reledge_bindings/readme.txt b/os/various/reledge_bindings/readme.txt new file mode 100644 index 000000000..4489695c1 --- /dev/null +++ b/os/various/reledge_bindings/readme.txt @@ -0,0 +1,12 @@ +This directory contains the ChibiOS/RT "official" bindings with the RelianceEdge +library by Datalight : https://github.com/datalightinc/reliance-edge + +In order to use Reliance Edge within ChibiOS/RT project: +1. unzip Reliance Edge under reliance-edge +2. include $(CHIBIOS)/os/various/reledge_bindings/reledge.mk in your makefile. +3. Add $(RELEDGESRC) to $(CSRC) +4. Add $(RELEDGEINC) to $(INCDIR) + +Note: +1. These files modified for use with version 2.2 of reliance edge + diff --git a/os/various/reledge_bindings/reledge.mk b/os/various/reledge_bindings/reledge.mk new file mode 100644 index 000000000..c85b7f659 --- /dev/null +++ b/os/various/reledge_bindings/reledge.mk @@ -0,0 +1,30 @@ +# RELIANCE EDGE files. + +RELEDGESRC= \ + $(CHIBIOS)/ext/reliance-edge/core/driver/blockio.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/buffer.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/core.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/dir.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/format.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/imap.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/imapextern.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/imapinline.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/inode.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/inodedata.c \ + $(CHIBIOS)/ext/reliance-edge/core/driver/volume.c \ + $(CHIBIOS)/ext/reliance-edge/fse/fse.c \ + $(CHIBIOS)/ext/reliance-edge/posix/path.c \ + $(CHIBIOS)/ext/reliance-edge/posix/posix.c \ + $(CHIBIOS)/ext/reliance-edge/util/bitmap.c \ + $(CHIBIOS)/ext/reliance-edge/util/crc.c \ + $(CHIBIOS)/ext/reliance-edge/util/memory.c \ + $(CHIBIOS)/ext/reliance-edge/util/namelen.c \ + $(CHIBIOS)/ext/reliance-edge/util/sign.c \ + $(CHIBIOS)/ext/reliance-edge/util/string.c + +RELEDGEINC = $(CHIBIOS)/ext/reliance-edge/include \ + $(CHIBIOS)/ext/reliance-edge/core/include + +# Shared variables +ALLCSRC += $(RELEDGESRC) +ALLINC += $(RELEDGEINC) \ No newline at end of file diff --git a/testhal/ATSAMA5D2/SDMMC/.cproject b/testhal/ATSAMA5D2/SDMMC/.cproject index 1c30c8b9b..e9cbdc182 100644 --- a/testhal/ATSAMA5D2/SDMMC/.cproject +++ b/testhal/ATSAMA5D2/SDMMC/.cproject @@ -32,7 +32,8 @@ - + + @@ -55,4 +56,10 @@ + + + + + + diff --git a/testhal/ATSAMA5D2/SDMMC/.project b/testhal/ATSAMA5D2/SDMMC/.project index fc56de69d..0a941555e 100644 --- a/testhal/ATSAMA5D2/SDMMC/.project +++ b/testhal/ATSAMA5D2/SDMMC/.project @@ -87,5 +87,10 @@ 2 CHIBIOS/os + + reliance-edge + 2 + $%7BPARENT-3-PROJECT_LOC%7D/ext/reliance-edge + diff --git a/testhal/ATSAMA5D2/SDMMC/Makefile b/testhal/ATSAMA5D2/SDMMC/Makefile index 42697581f..c9dc8bec4 100644 --- a/testhal/ATSAMA5D2/SDMMC/Makefile +++ b/testhal/ATSAMA5D2/SDMMC/Makefile @@ -121,15 +121,12 @@ 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/reledge_bindings/reledge.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 - +#LDSCRIPT= $(STARTUPLD)/SAMA5D2.ld +LDSCRIPT= $(STARTUPLD)/SAMA5D2ddr.ld # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(STARTUPSRC) \ @@ -140,7 +137,7 @@ CSRC = $(STARTUPSRC) \ $(PLATFORMSRC) \ $(BOARDSRC) \ $(TESTSRC) $(STREAMSSRC) \ - main.c + main.c fat32test.c reledgetest.c redconf.c $(RELEDGESRC) CSRC += $(CHIBIOS)/os/various/syscalls.c CSRC += $(CHIBIOS)/os/various/fatfs_bindings/fatfs_syscall.c @@ -177,9 +174,8 @@ ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) INCDIR = $(CHIBIOS)/os/license \ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ - $(CHIBIOS)/os/various $(STREAMSINC) + $(CHIBIOS)/os/various $(STREAMSINC) $(FATFSINC) $(RELEDGEINC) -INCDIR += $(FATFSINC) # # Project, sources and paths ############################################################################## @@ -228,10 +224,10 @@ CPPWARN = -Wall -Wextra -Wundef # # List all user C define here, like -D_DEBUG=1 -UDEFS = -DCH_CFG_USE_MMU -DPLATFORM_SDMMC_USE_SDMMC1=1 +UDEFS = -DPLATFORM_SDMMC_USE_SDMMC1=1 # Define ASM defines here -UADEFS = -DCH_CFG_USE_MMU +UADEFS = # List all user directories here UINCDIR = diff --git a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (DDRAM).launch b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (DDRAM).launch new file mode 100644 index 000000000..48a548c60 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (DDRAM).launch @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch index e68b5ed9a..4d7c946f4 100644 --- a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch +++ b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (Load and Run).launch @@ -17,7 +17,7 @@ - + diff --git a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch index 7a1b87b82..33bb28a80 100644 --- a/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch +++ b/testhal/ATSAMA5D2/SDMMC/debug/SAMA5D2-SDMMC (bootstrap).launch @@ -6,7 +6,7 @@ - + diff --git a/testhal/ATSAMA5D2/SDMMC/fat32test.c b/testhal/ATSAMA5D2/SDMMC/fat32test.c new file mode 100644 index 000000000..83a199add --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/fat32test.c @@ -0,0 +1,287 @@ +/* + ChibiOS - Copyright (C) 2006..2018 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 "ff.h" +#include "sama_sdmmc_lld.h" +#include "chprintf.h" + + +extern BaseSequentialStream * ts; + + + +#if FF_MULTI_PARTITION == 1 +#define DEMO_VOLUMES 2 + +PARTITION VolToPart[] = { + {1, 1}, /* "0:" ==> Physical drive 1, 1st partition */ + {1, 2}, /* "1:" ==> Physical drive 1, 2nd partition */ +}; + +const TCHAR volume_paths[DEMO_VOLUMES][3] = +{ + { '0', ':', '\0' }, + { '1', ':', '\0' } +}; + +const TCHAR volume_labels[DEMO_VOLUMES][13] = +{ + { '0', ':','C','H','I','B','I','V','O','L','_','1','\0' }, + { '1', ':','C','H','I','B','I','V','O','L','_','2','\0' } +}; + +//two partition: 20% of total size the first, 80% the second +//using a number > 100 means sector count +const DWORD plist[] = { 50, 50, 0, 0 }; + + +#else +#define DEMO_VOLUMES 1 +const TCHAR volume_paths[DEMO_VOLUMES][3] = +{ + { '0', ':', '\0' } +}; + +const TCHAR volume_labels[DEMO_VOLUMES][13] = +{ + { '0', ':','C','H','I','B','I','V','O','L','_','1','\0' } +}; + +#endif + + + + +static FATFS fs_header; +static FIL f_header; +const char test_file_path[] = "test.txt"; + +//Welcome to Chibios! +const uint8_t buffer[19]={ 0x57,0x65,0x6C,0x63,0x6F, + 0x6D,0x65,0x20,0x74,0x6F, + 0x20,0x43,0x68,0x69,0x62, + 0x69,0x4F,0x53,0x21 +}; + +static void getdir(uint8_t vi); +static void writefile(uint8_t vi); +static void readfile(uint8_t vi); +static bool format(void); +static bool mountVolume(uint8_t vi, FATFS *fs); +static bool unmountVolume(uint8_t vi); + +extern CACHE_ALIGNED uint8_t data_buf[]; + +void fat32test_demo(void) +{ + uint8_t i; + chprintf(ts,"Init FAT32 FS\r\n" ); + if ( format() ) { + + for (i=0;in_fatent - 2) * fs->csize; + fre_sect = fre_clust * fs->csize; + + chprintf(ts,"%10lu KiB total drive space.\r\n%10lu KiB available.\r\n",tot_sect / 2, fre_sect / 2); + } + + } + + return true; +} + + +static bool unmountVolume(uint8_t vi) +{ + FRESULT res; + bool rc = true; + + res = f_mount(NULL, volume_paths[vi], 0); + if (res != FR_OK) + rc = false; + + return rc; + +} + + +static bool format(void) +{ + uint8_t i; + + FRESULT res = FR_OK; + + + +#if FF_MULTI_PARTITION == 1 + chprintf(ts, "fdisk ... \n\r"); + res = f_fdisk(0, plist, data_buf); +#endif + + if (res == FR_OK) { + + for (i = 0; i < DEMO_VOLUMES; i++) { + chprintf(ts, "Creating fat32 volume %s\n\r", volume_paths[i]); + + res = f_mkfs(volume_paths[i], FM_FAT32, 0, data_buf,FF_MAX_SS); + + if (res == FR_OK) { + chprintf(ts, "format OK\r\n"); + + } else { + chprintf(ts, "failed creating volume %s error %d\n\r", volume_paths[i],res); + return false; + } + + } + } + return true; +} diff --git a/testhal/ATSAMA5D2/SDMMC/fat32test.h b/testhal/ATSAMA5D2/SDMMC/fat32test.h new file mode 100644 index 000000000..a9d0a2c66 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/fat32test.h @@ -0,0 +1,10 @@ +#ifndef FAT32TEST_H_ +#define FAT32TEST_H_ + + + + +extern void fat32test_demo(void); + + +#endif /* FAT32TEST_H_ */ diff --git a/os/hal/ports/SAMA/LLD/SDMMCv1/ffconf.h b/testhal/ATSAMA5D2/SDMMC/ffconf.h similarity index 98% rename from os/hal/ports/SAMA/LLD/SDMMCv1/ffconf.h rename to testhal/ATSAMA5D2/SDMMC/ffconf.h index 3937ff27e..18a902237 100644 --- a/os/hal/ports/SAMA/LLD/SDMMCv1/ffconf.h +++ b/testhal/ATSAMA5D2/SDMMC/ffconf.h @@ -1,5 +1,6 @@ /* CHIBIOS FIX */ #include "ch.h" +#include "sama_sdmmc_conf.h" /*---------------------------------------------------------------------------/ / FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016 /---------------------------------------------------------------------------*/ @@ -41,7 +42,7 @@ / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ -#define FF_USE_MKFS 0 +#define FF_USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ @@ -58,7 +59,7 @@ / (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */ -#define FF_USE_LABEL 0 +#define FF_USE_LABEL 1 /* This option switches volume label functions, f_getlabel() and f_setlabel(). / (0:Disable or 1:Enable) */ @@ -163,7 +164,7 @@ / the drive ID strings are: A-Z and 0-9. */ -#define FF_MULTI_PARTITION 0 +#define FF_MULTI_PARTITION 1 /* This option switches support of multi-partition on a physical drive. / By default (0), each logical drive number is bound to the same physical drive / number and only an FAT volume found on the physical drive will be mounted. @@ -172,8 +173,8 @@ / funciton will be available. */ -#define FF_MIN_SS 512 -#define FF_MAX_SS 512 +#define FF_MIN_SS SDMMC_BLOCK_SIZE +#define FF_MAX_SS SDMMC_BLOCK_SIZE /* These options configure the range of sector size to be supported. (512, 1024, / 2048 or 4096) Always set both 512 for most systems, all type of memory cards and / harddisk. But a larger value may be required for on-board flash memory and some @@ -221,7 +222,7 @@ #define FF_FS_NORTC 1 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2016 +#define FF_NORTC_YEAR 2018 /* The option _FS_NORTC switches timestamp functiton. If the system does not have / any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable / the timestamp function. All objects modified by FatFs will have a fixed timestamp diff --git a/testhal/ATSAMA5D2/SDMMC/main.c b/testhal/ATSAMA5D2/SDMMC/main.c index 551b4dd65..b424ce152 100644 --- a/testhal/ATSAMA5D2/SDMMC/main.c +++ b/testhal/ATSAMA5D2/SDMMC/main.c @@ -18,7 +18,15 @@ #include "hal.h" #include "sama_sdmmc_lld.h" #include "chprintf.h" +#include "fat32test.h" +#include "reledgetest.h" +//----------- DEMO CONFIGURATION ------------------------ +//0 (SLOT0) or 1 (SLOT1) +#define DEMO_SLOT 0 +//1 for FFLib, 0 for Reliance +#define DEMO_FAT 1 +//---------------------------------------------------------- #define BLOCK_CNT_MAX 32u #define DMADL_CNT_MAX 64u @@ -26,16 +34,13 @@ -const char test_file_path[] = "test.txt"; - 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(SDMMC_BUFFER_SIZE, L1_CACHE_BYTES)]; -static FATFS fs_header; -static FIL f_header; + BaseSequentialStream * ts; @@ -56,9 +61,17 @@ static THD_FUNCTION(Thread1, arg) { } } - - -static const SamaSDMMCConfig sdmmc_slot1_cfg = { +#if DEMO_SLOT == 0 +static const SamaSDMMCConfig sdmmc_cfg = { + SDMMC_SLOT0, + sdmmcbuffer, + data_buf, + sizeof(data_buf), + dma_table, + DMADL_CNT_MAX +}; +#else +static const SamaSDMMCConfig sdmmc_cfg = { SDMMC_SLOT1, sdmmcbuffer, data_buf, @@ -66,10 +79,8 @@ static const SamaSDMMCConfig sdmmc_slot1_cfg = { dma_table, DMADL_CNT_MAX }; +#endif -void getdir(SdmmcDriver *sdmmcp); -void writefile(SdmmcDriver *sdmmcp); -void readfile(SdmmcDriver *sdmmcp); /* * Application entry point. */ @@ -98,23 +109,26 @@ int main(void) { sdmmcInit(); - sdmmcStart(&SDMMCD1, &sdmmc_slot1_cfg); + sdmmcStart(&SDMMCD1, &sdmmc_cfg); if (SDMMCD1.state != MCID_INIT_ERROR) { - chprintf(ts,"starting MMC Demo\n\r"); + chprintf(ts,"starting MMC Demo with slot %d\n\r",SDMMCD1.config->slot_id); if (sdmmcOpenDevice(&SDMMCD1)) { - //sdmmcShowDeviceInfo(&SDMMCD1); - if ( sdmmcMountVolume(&SDMMCD1,&fs_header) ) { - writefile(&SDMMCD1); - chprintf(ts,"reading dir:\n\r"); - getdir(&SDMMCD1); - readfile(&SDMMCD1); +#if DEMO_FAT == 1 + fat32test_demo(); +#else + relianceedge_demo(); +#endif + if (SDMMCD1.config->slot_id == SDMMC_SLOT1) + { + chprintf(ts,"remove card to finish demo\n\r"); + sdmmcCloseDevice(&SDMMCD1); } - sdmmcCloseDevice(&SDMMCD1); + } @@ -140,106 +154,13 @@ int main(void) { bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) { - if (index == SDMMCD1.config->slot_id) { - *sdmmcp = &SDMMCD1; - return true; - } - return false; -} + (void)index; -void writefile(SdmmcDriver *sdmmcp) -{ - const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; - TCHAR file_path[sizeof(drive_path) + sizeof(test_file_path)]; - FRESULT res; - UINT len; - uint8_t buffer[]={ 0x57,0x65,0x6C,0x63,0x6F, - 0x6D,0x65,0x20,0x74,0x6F, - 0x20,0x43,0x68,0x69,0x62, - 0x69,0x4F,0x53,0x21}; + *sdmmcp = &SDMMCD1; - - strcpy(file_path, drive_path); - strcat(file_path, test_file_path); - - chprintf(ts,"Creating new file ... "); - res = f_open(&f_header, file_path, FA_WRITE | FA_CREATE_ALWAYS); - if (res == FR_OK) { - chprintf(ts,"OK\r\n"); - res = f_write(&f_header, buffer, 19, &len); - if (res == FR_OK) { - chprintf(ts,"written %d bytes\n\r", len); - } - } - else - { - chprintf(ts,"Failed error %d\n\r", res); - } - f_close(&f_header); - -} - -void readfile(SdmmcDriver *sdmmcp) -{ - const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' }; - TCHAR file_path[sizeof(drive_path) + sizeof(test_file_path)]; - FRESULT res; - UINT len; - uint8_t buffer[19]; - UINT i; - - strcpy(file_path, drive_path); - strcat(file_path, test_file_path); - - chprintf(ts,"Reading back the new file ... "); - res = f_open(&f_header, file_path, FA_OPEN_EXISTING | FA_READ); - if (res == FR_OK) { - chprintf(ts,"OK\r\n"); - res = f_read(&f_header, buffer, 19, &len); - if (res == FR_OK) { - chprintf(ts,"read %d bytes\n\r", len); - for (i=0;iconfig->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); + return true; } + diff --git a/testhal/ATSAMA5D2/SDMMC/mcuconf.h b/testhal/ATSAMA5D2/SDMMC/mcuconf.h index d1e0fe8d6..5e2eeefe3 100644 --- a/testhal/ATSAMA5D2/SDMMC/mcuconf.h +++ b/testhal/ATSAMA5D2/SDMMC/mcuconf.h @@ -23,7 +23,7 @@ * HAL driver system settings. */ #define SAMA_HAL_IS_SECURE TRUE -#define SAMA_NO_INIT FALSE +#define SAMA_NO_INIT TRUE #define SAMA_MOSCRC_ENABLED FALSE #define SAMA_MOSCXT_ENABLED TRUE #define SAMA_MOSC_SEL SAMA_MOSC_MOSCXT diff --git a/testhal/ATSAMA5D2/SDMMC/readme.txt b/testhal/ATSAMA5D2/SDMMC/readme.txt index cc6e568f6..49423b98c 100644 --- a/testhal/ATSAMA5D2/SDMMC/readme.txt +++ b/testhal/ATSAMA5D2/SDMMC/readme.txt @@ -7,6 +7,7 @@ The demo targets a generic ARM Cortex-A5 device without HAL support. ** The Demo ** +Testing FF and Reliance Edge Libraries ** Build Procedure ** diff --git a/testhal/ATSAMA5D2/SDMMC/redconf.c b/testhal/ATSAMA5D2/SDMMC/redconf.c new file mode 100644 index 000000000..7c0647332 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/redconf.c @@ -0,0 +1,36 @@ +/* THIS FILE WAS GENERATED BY THE DATALIGHT RELIANCE EDGE CONFIGURATION + UTILITY. DO NOT MODIFY. + + Generated by configuration utility version 2.02 +*/ +/** @file +*/ + +#include "hal.h" + +#if (HAL_USE_SDMMC == TRUE) +#include "sama_sdmmc_lld.h" +#if SDMMC_USE_RELEDGE_LIB == 1 +#include +#include +#include +#include +#include + + +const VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT] = +{ + { + SDMMC_BLOCK_SIZE, //ulSectorSize + 1048576U, //ullSectorCount + 0U, //ullSectorOffset + false, //fAtomicSectorWrite + 1024U, //ulInodeCount + 2U, //bBlockIoRetries + "CHIBIVOL" + } +}; + +#endif +#endif + diff --git a/testhal/ATSAMA5D2/SDMMC/redconf.h b/testhal/ATSAMA5D2/SDMMC/redconf.h new file mode 100644 index 000000000..ab51742f4 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/redconf.h @@ -0,0 +1,114 @@ +/* THIS FILE WAS GENERATED BY THE DATALIGHT RELIANCE EDGE CONFIGURATION + UTILITY. DO NOT MODIFY. + + Generated by configuration utility version 2.02 +*/ +/** @file +*/ +#ifndef REDCONF_H +#define REDCONF_H + + +#include + +#define REDCONF_READ_ONLY 0 + +#define REDCONF_API_POSIX 1 + +#define REDCONF_API_FSE 0 + +#define REDCONF_API_POSIX_FORMAT 1 + +#define REDCONF_API_POSIX_LINK 1 + +#define REDCONF_API_POSIX_UNLINK 1 + +#define REDCONF_API_POSIX_MKDIR 1 + +#define REDCONF_API_POSIX_RMDIR 1 + +#define REDCONF_API_POSIX_RENAME 1 + +#define REDCONF_RENAME_ATOMIC 1 + +#define REDCONF_API_POSIX_FTRUNCATE 1 + +#define REDCONF_API_POSIX_READDIR 1 + +#define REDCONF_API_POSIX_CWD 0 + +#define REDCONF_NAME_MAX 12U + +#define REDCONF_PATH_SEPARATOR '/' + +#define REDCONF_TASK_COUNT 10U + +#define REDCONF_HANDLE_COUNT 10U + +#define REDCONF_API_FSE_FORMAT 0 + +#define REDCONF_API_FSE_TRUNCATE 0 + +#define REDCONF_API_FSE_TRANSMASKGET 0 + +#define REDCONF_API_FSE_TRANSMASKSET 0 + +#define REDCONF_OUTPUT 1 + +#define REDCONF_ASSERTS 1 + +#define REDCONF_BLOCK_SIZE 512U + +#define REDCONF_VOLUME_COUNT 1U + +#define REDCONF_ENDIAN_BIG 0 + +#define REDCONF_ALIGNMENT_SIZE 4U + +#define REDCONF_CRC_ALGORITHM CRC_SLICEBY8 + +#define REDCONF_INODE_BLOCKS 1 + +#define REDCONF_INODE_TIMESTAMPS 1 + +#define REDCONF_ATIME 0 + +#define REDCONF_DIRECT_POINTERS 4U + +#define REDCONF_INDIRECT_POINTERS 32U + +#define REDCONF_BUFFER_COUNT 12U + +#define RedMemCpyUnchecked memcpy + +#define RedMemMoveUnchecked memmove + +#define RedMemSetUnchecked memset + +#define RedMemCmpUnchecked memcmp + +#define RedStrLenUnchecked strlen + +#define RedStrCmpUnchecked strcmp + +#define RedStrNCmpUnchecked strncmp + +#define RedStrNCpyUnchecked strncpy + +#define REDCONF_TRANSACT_DEFAULT (( RED_TRANSACT_CREAT | RED_TRANSACT_MKDIR | RED_TRANSACT_RENAME | RED_TRANSACT_LINK | RED_TRANSACT_UNLINK | RED_TRANSACT_FSYNC | RED_TRANSACT_CLOSE | RED_TRANSACT_VOLFULL | RED_TRANSACT_UMOUNT ) & RED_TRANSACT_MASK) + +#define REDCONF_IMAP_INLINE 0 + +#define REDCONF_IMAP_EXTERNAL 1 + +#define REDCONF_DISCARDS 0 + +#define REDCONF_IMAGE_BUILDER 0 + +#define REDCONF_CHECKER 0 + +#define RED_CONFIG_UTILITY_VERSION 0x2000200U + +#define RED_CONFIG_MINCOMPAT_VER 0x1000200U + +#endif diff --git a/testhal/ATSAMA5D2/SDMMC/reledgetest.c b/testhal/ATSAMA5D2/SDMMC/reledgetest.c new file mode 100644 index 000000000..a741ff83c --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/reledgetest.c @@ -0,0 +1,268 @@ +/* + ChibiOS - Copyright (C) 2006..2018 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 +#include "ch.h" +#include "hal.h" +#include "sama_sdmmc_lld.h" + +#if SDMMC_USE_RELEDGE_LIB == 1 +#include "chprintf.h" +#include +#include +#include +#include +#include +#include +#include + +static int32_t format(uint8_t volnum); +static void readfiles(void); +static void writefiles(uint8_t volnum); + +#define fsRAM_BUFFER_SIZE 30 +static char cRAMBuffer[ fsRAM_BUFFER_SIZE ]; + +static const char *pcDirectory1 = "/DIR1", *pcDirectory2 = "/DIR1/DIR2"; +extern BaseSequentialStream * ts; +extern const VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT]; + +void relianceedge_demo(void) +{ + int32_t ret; + int volnum = 0; + const char *pszVolume = gaRedVolConf[volnum].pszPathPrefix; + + chprintf(ts,"Init Reliance Edge FS\r\n" ); + ret = red_init(); + + chprintf(ts,"Start formatting fs ... " ); + ret = format(volnum); + + if ( ret == 0 ) + { + chprintf(ts,"OK , mounting volume .." ); + + ret = red_mount(pszVolume); + if ( ret == 0 ) + { + chprintf(ts,"OK\r\n writing files ..\r\n" ); + writefiles(volnum); + chprintf(ts,"OK\r\n reading files ..\r\n" ); + readfiles(); + } + } + else + { + chprintf(ts,"FAILED! \r\n" ); + } +} + + + +static void writefiles(uint8_t volnum) +{ + uint32_t i, j; + char path[ 64 ]; + const uint32_t filen = 5; + + uint32_t ulEventMask; + int32_t written, filedescr, status; + int iByte; + + const char *pszVolume = gaRedVolConf[volnum].pszPathPrefix; + /* Save the current transaction point settings. */ + status = red_gettransmask( pszVolume, &ulEventMask ); + osalDbgCheck( status == 0 ); + + /* Disable automatic transaction points so that all of the files can be + created in one atomic operation. */ + status = red_settransmask( pszVolume, RED_TRANSACT_MANUAL ); + osalDbgCheck( status == 0 ); + + /* Create filen files. Each created file will be + ( i * fsRAM_BUFFER_SIZE ) bytes in length, and filled + with a different repeating character. */ + for( i = 1; i <= filen; i++ ) + { + /* Generate a file name. */ + sprintf( path, "/root%03d.txt", (int)i ); + + /* Print out the file name and the directory into which the file is + being written. */ + chprintf(ts,"Creating file %s\r\n", path ); + + /* Open the file, creating the file if it does not already exist. */ + filedescr = red_open( path, RED_O_CREAT|RED_O_TRUNC|RED_O_WRONLY ); + osalDbgCheck( filedescr != -1 ); + + /* Fill the RAM buffer with data that will be written to the file. This + is just a repeating ascii character that indicates the file number. */ + memset( cRAMBuffer, ( int ) ( '0' + i ), fsRAM_BUFFER_SIZE ); + + /* Write the RAM buffer to the opened file a number of times. The + number of times the RAM buffer is written to the file depends on the + file number, so the length of each created file will be different. */ + for( j = 0; j < i; j++ ) + { + written = red_write( filedescr, cRAMBuffer, fsRAM_BUFFER_SIZE ); + osalDbgCheck( written == fsRAM_BUFFER_SIZE ); + } + + /* Close the file so another file can be created. */ + status = red_close( filedescr ); + osalDbgCheck( status == 0 ); + } + + /* Commit a transaction point, atomically adding the set of files to the + transacted state. */ + status = red_transact( pszVolume ); + osalDbgCheck( status == 0 ); + + /* Create a sub directory. */ + chprintf(ts,"Creating directory %s\r\n", pcDirectory1 ); + + status = red_mkdir( pcDirectory1 ); + osalDbgCheck( status == 0 ); + + /* Create a subdirectory in the new directory. */ + chprintf(ts, "Creating directory %s\r\n", pcDirectory2 ); + + status = red_mkdir( pcDirectory2 ); + osalDbgCheck( status == 0 ); + + /* Generate the file name. */ + sprintf( path, "%s/file.txt", pcDirectory2 ); + + /* Print out the file name and the directory into which the file is being + written. */ + chprintf(ts, "Writing file %s\r\n", path ); + + filedescr = red_open( path, RED_O_CREAT|RED_O_TRUNC|RED_O_WRONLY ); + + /* Write the file. It is filled with incrementing ascii characters starting + from '0'. */ + for( iByte = 0; iByte < fsRAM_BUFFER_SIZE; iByte++ ) + { + cRAMBuffer[ iByte ] = ( char ) ( ( int ) '0' + iByte ); + } + + written = red_write( filedescr, cRAMBuffer, fsRAM_BUFFER_SIZE ); + osalDbgCheck( written == fsRAM_BUFFER_SIZE ); + + /* Finished so close the file. */ + status = red_close( filedescr ); + osalDbgCheck( status == 0 ); + + /* Commit a transaction point, atomically adding the set of files and + directories to the transacted state. */ + status = red_transact( pszVolume ); + osalDbgCheck( status == 0 ); + + /* Restore previous transaction point settings. */ + status = red_settransmask( pszVolume, ulEventMask ); + osalDbgCheck( status == 0 ); +} + +static void readfiles(void) +{ + uint32_t i, j; + char path[ 64 ]; + const uint32_t filen = 5; + long lChar; + int32_t lBytesRead, filedescr, status; + int iByte; + + + /* Read back the files that were created by prvCreateDemoFiles(). */ + for( i = 1; i <= filen; i++ ) + { + /* Generate the file name. */ + sprintf( path, "/root%03d.txt",(int) i ); + + /* Print out the file name and the directory from which the file is + being read. */ + chprintf(ts,"Reading file %s\r\n", path ); + + /* Open the file for reading. */ + filedescr = red_open( path, RED_O_RDONLY ); + osalDbgCheck( filedescr != -1 ); + + /* Read the file into the RAM buffer, checking the file contents are as + expected. The size of the file depends on the file number. */ + for( j = 0; j < i; j++ ) + { + /* Start with the RAM buffer clear. */ + memset( cRAMBuffer, 0x00, fsRAM_BUFFER_SIZE ); + + lBytesRead = red_read( filedescr, cRAMBuffer, fsRAM_BUFFER_SIZE ); + osalDbgCheck( lBytesRead == fsRAM_BUFFER_SIZE ); + + /* Check the RAM buffer is filled with the expected data. Each + file contains a different repeating ascii character that indicates + the number of the file. */ + for( lChar = 0; lChar < fsRAM_BUFFER_SIZE; lChar++ ) + { + osalDbgCheck( cRAMBuffer[ lChar ] == ( '0' + ( char ) i ) ); + } + } + + /* Close the file. */ + status = red_close( filedescr ); + osalDbgCheck( status == 0 ); + } + + /* Generate the file name. */ + sprintf( path, "%s/file.txt", pcDirectory2 ); + + /* Print out the file name and the directory from which the file is being + read. */ + chprintf(ts, "Reading file %s\r\n", path ); + + /* This time the file is opened for reading. */ + filedescr = red_open( path, RED_O_RDONLY ); + osalDbgCheck( filedescr != -1 ); + + /* Read the file. */ + lBytesRead = red_read( filedescr, cRAMBuffer, fsRAM_BUFFER_SIZE ); + osalDbgCheck( lBytesRead == fsRAM_BUFFER_SIZE ); + + /* Verify the file 1 byte at a time. */ + for( iByte = 0; iByte < fsRAM_BUFFER_SIZE; iByte++ ) + { + osalDbgCheck( cRAMBuffer[ iByte ] == ( char ) ( ( int ) '0' + iByte ) ); + } + + /* Finished so close the file. */ + status = red_close( filedescr ); + osalDbgCheck( status == 0 ); + +} + + +static int32_t format(uint8_t volnum) +{ + int32_t ret=-1; +#if REDCONF_API_POSIX_FORMAT == 1 + const char *pszVolume = gaRedVolConf[volnum].pszPathPrefix; + ret = red_format(pszVolume); + +#endif + return ret; +} + +#endif + diff --git a/testhal/ATSAMA5D2/SDMMC/reledgetest.h b/testhal/ATSAMA5D2/SDMMC/reledgetest.h new file mode 100644 index 000000000..1e5ee7cc8 --- /dev/null +++ b/testhal/ATSAMA5D2/SDMMC/reledgetest.h @@ -0,0 +1,8 @@ +#ifndef RELEDGETEST_H_ +#define RELEDGETEST_H_ + + + +extern void relianceedge_demo(void); + +#endif /* RELEDGETEST_H_ */