sdmmc driver update, added support for reliance edge fs

git-svn-id: https://svn.code.sf.net/p/chibios/svn2/trunk@11551 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
areviu 2018-02-26 19:06:49 +00:00
parent 70fb3b4056
commit 0c51b431f2
41 changed files with 2364 additions and 219 deletions

View File

@ -53,6 +53,7 @@ uint32_t SdmmcGetMaxFreq(SdmmcDriver *drv)
rate /= 2ul; rate /= 2ul;
} }
TRACE_DEBUG_1("SdmmcGetMaxFreq rate %d\r\n",rate);
return rate * 1000ul; return rate * 1000ul;
} }
@ -98,7 +99,7 @@ void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData)
uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry) uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
{ {
uint64_t mem_size; uint64_t mem_size;
//uint32_t freq; uint32_t freq;
uint32_t drv_err, status; uint32_t drv_err, status;
uint8_t error; uint8_t error;
bool flag; bool flag;
@ -260,14 +261,16 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
: (uint32_t)mem_size; : (uint32_t)mem_size;
} }
//TO BE DONE
#if 0
/* Automatically select the max device clock frequency */ /* Automatically select the max device clock frequency */
/* Calculate transfer speed */ /* Calculate transfer speed */
freq = SdmmcGetMaxFreq(drv); freq = SdmmcGetMaxFreq(drv);
#ifndef SDMMC_TRIM_SDIO #ifndef SDMMC_TRIM_SDIO
if (drv->card.bCardType & CARD_TYPE_bmSDIO) if (drv->card.bCardType & CARD_TYPE_bmSDIO) {
freq = min_u32(freq, SdioGetMaxFreq(drv)); freq = min_u32(freq, SdioGetMaxFreq(drv));
TRACE_INFO_1("selecting sdio freq%d\r\n",freq);
}
#endif #endif
error = HwSetClock(drv, &freq); error = HwSetClock(drv, &freq);
drv->card.dwCurrSpeed = 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)); TRACE_ERROR_1("error clk %s\n\r", SD_StringifyRetCode(error));
return error; return error;
} }
#endif
/* Check device status and eat past exceptions, which would otherwise /* Check device status and eat past exceptions, which would otherwise
* prevent upcoming data transaction routines from reliably checking * prevent upcoming data transaction routines from reliably checking
* fresh exceptions. */ * fresh exceptions. */

View File

@ -644,8 +644,8 @@ uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStat
pCmd->pResp = pStatus; pCmd->pResp = pStatus;
drv->timeout_elapsed = -1; drv->timeout_elapsed = -1;
/* Send command */ /* Send command */
bRc = sdmmcSendCmd(drv); bRc = sdmmcSendCmd(drv);
return bRc; return bRc;
} }
@ -680,8 +680,8 @@ uint8_t Cmd24(SdmmcDriver *drv,
pCmd->wNbBlocks = 1; pCmd->wNbBlocks = 1;
pCmd->pData = pData; pCmd->pData = pData;
drv->timeout_elapsed = -1; drv->timeout_elapsed = -1;
/* Send command */ /* Send command */
bRc = sdmmcSendCmd(drv); bRc = sdmmcSendCmd(drv);
return bRc; return bRc;
} }
@ -719,8 +719,8 @@ uint8_t Cmd25(SdmmcDriver *drv,
pCmd->pData = pData; pCmd->pData = pData;
drv->timeout_elapsed = -1; drv->timeout_elapsed = -1;
/* Send command */ /* Send command */
bRc = sdmmcSendCmd(drv); bRc = sdmmcSendCmd(drv);
if (bRc == SDMMC_CHANGED) if (bRc == SDMMC_CHANGED)
*nbBlock = pCmd->wNbBlocks; *nbBlock = pCmd->wNbBlocks;
return bRc; return bRc;

View File

@ -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 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 sdmmc_build_dma_table( SdmmcDriver *driver );
static uint8_t unplug_device(SdmmcDriver *driver); static uint8_t unplug_device(SdmmcDriver *driver);
static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verify); 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) { if (driver->config->slot_id == SDMMC_SLOT0) {
driver->regs = SDMMC0; driver->regs = SDMMC0;
pmcEnableSDMMC0() pmcEnableSDMMC0();
;
} else if (driver->config->slot_id == SDMMC_SLOT1) { } else if (driver->config->slot_id == SDMMC_SLOT1) {
driver->regs = SDMMC1; driver->regs = SDMMC1;
pmcEnableSDMMC1() pmcEnableSDMMC1();
;
} }
switch (driver->config->slot_id) { switch (driver->config->slot_id) {
@ -704,12 +702,14 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
bool use_prog_mode = false; bool use_prog_mode = false;
freq = min_u32(freq, 120000000ul); freq = min_u32(freq, 120000000ul);
#ifndef NDEBUG
//if (!(regs->SDMMC_PCR & SDMMC_PCR_SDBPWR)) if (!(regs->SDMMC_PCR & SDMMC_PCR_SDBPWR)) {
// trace_error("Bus is off\n\r"); TRACE_ERROR("Bus is off\n\r");
//if (regs->SDMMC_HC2R & SDMMC_HC2R_PVALEN) }
// trace_error("Preset values enabled though not implemented\n\r"); if (regs->SDMMC_HC2R & SDMMC_HC2R_PVALEN) {
#endif TRACE_ERROR("Preset values enabled though not implemented\n\r");
}
/* In the Divided Clock Mode scenario, compute the divider */ /* In the Divided Clock Mode scenario, compute the divider */
base_freq = (regs->SDMMC_CA0R & SDMMC_CA0R_BASECLKF_Msk) >> SDMMC_CA0R_BASECLKF_Pos; base_freq = (regs->SDMMC_CA0R & SDMMC_CA0R_BASECLKF_Msk) >> SDMMC_CA0R_BASECLKF_Pos;
base_freq *= 1000000UL; base_freq *= 1000000UL;
@ -732,10 +732,10 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
* is 32 whereas the real value is 40.5 */ * is 32 whereas the real value is 40.5 */
mult_freq = (regs->SDMMC_CA1R & SDMMC_CA1R_CLKMULT_Msk) >> SDMMC_CA1R_CLKMULT_Pos; mult_freq = (regs->SDMMC_CA1R & SDMMC_CA1R_CLKMULT_Msk) >> SDMMC_CA1R_CLKMULT_Pos;
if (mult_freq != 0) if (mult_freq != 0)
#if 1 #if 0
mult_freq = base_freq * (mult_freq + 1); mult_freq = base_freq * (mult_freq + 1);
#else #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 #endif
if (mult_freq != 0) { if (mult_freq != 0) {
/* DIV = FMULTCLK / FSDCLK - 1 */ /* DIV = FMULTCLK / FSDCLK - 1 */
@ -761,6 +761,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
shval = regs->SDMMC_CCR & ~SDMMC_CCR_SDCLKEN; shval = regs->SDMMC_CCR & ~SDMMC_CCR_SDCLKEN;
regs->SDMMC_CCR = shval; regs->SDMMC_CCR = shval;
driver->dev_freq = new_freq; driver->dev_freq = new_freq;
use_prog_mode = false; //no generated clock
/* Select the clock mode */ /* Select the clock mode */
if (use_prog_mode) if (use_prog_mode)
shval |= SDMMC_CCR_CLKGSEL; shval |= SDMMC_CCR_CLKGSEL;
@ -1220,7 +1221,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
sdmmc_set_device_clock(driver, driver->control_param); 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 if (driver->dev_freq > 95000000ul
&& (driver->tim_mode == SDMMC_TIM_MMC_HS200 && (driver->tim_mode == SDMMC_TIM_MMC_HS200
|| driver->tim_mode == SDMMC_TIM_SD_SDR104 || 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); //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)) && !(caps & SDMMC_CA0R_V18VSUP))
return SDMMC_PARAM; return SDMMC_PARAM;
#ifndef NDEBUG #if 0
/* FIXME The datasheet is unclear about CCR:DIV restriction when the MMC /* FIXME The datasheet is unclear about CCR:DIV restriction when the MMC
* timing mode is High Speed DDR */ * timing mode is High Speed DDR */
if ((mode == SDMMC_TIM_MMC_HS_SDR || mode == SDMMC_TIM_MMC_HS_DDR if ((mode == SDMMC_TIM_MMC_HS_SDR || mode == SDMMC_TIM_MMC_HS_DDR
|| mode == SDMMC_TIM_SD_HS) && !(regs->SDMMC_CCR || mode == SDMMC_TIM_SD_HS) && !(regs->SDMMC_CCR
& (SDMMC_CCR_USDCLKFSEL_Msk | SDMMC_CCR_SDCLKFSEL_Msk))) { & (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; return SDMMC_STATE;
} }
#endif #endif
@ -1724,11 +1725,13 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif
goto End; goto End;
toggle_sig_lvl = pcr_prv & SDMMC_PCR_SDBPWR toggle_sig_lvl = pcr_prv & SDMMC_PCR_SDBPWR
&& (pcr ^ pcr_prv) & SDMMC_PCR_SDBVSEL_Msk; && (pcr ^ pcr_prv) & SDMMC_PCR_SDBVSEL_Msk;
//if (!(pcr_prv & SDMMC_PCR_SDBPWR)) if (!(pcr_prv & SDMMC_PCR_SDBPWR)) {
// trace_debug("Power the device on\n\r"); TRACE_DEBUG("Power the device on\n\r");
//else if (toggle_sig_lvl) }
// trace_debug("Signaling level going %s\n\r", else if (toggle_sig_lvl) {
// hc2r & SDMMC_HC2R_VS18EN ? "low" : "high"); TRACE_DEBUG_1("Signaling level going %s\n\r",
hc2r & SDMMC_HC2R_VS18EN ? "low" : "high");
}
if (verify && toggle_sig_lvl && hc2r & SDMMC_HC2R_VS18EN) { if (verify && toggle_sig_lvl && hc2r & SDMMC_HC2R_VS18EN) {
/* Expect this call to follow the VOLTAGE_SWITCH command; /* Expect this call to follow the VOLTAGE_SWITCH command;
* allow 2 device clock periods before the device pulls the CMD * 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) if (!dev_clk_on)
regs->SDMMC_CCR &= ~SDMMC_CCR_SDCLKEN; 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) regs->SDMMC_CALCR = (regs->SDMMC_CALCR & ~SDMMC_CALCR_ALWYSON)
| (low_sig ? SDMMC_CALCR_ALWYSON : 0); | (low_sig ? SDMMC_CALCR_ALWYSON : 0);

View File

@ -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 SdMmcIdentify(SdmmcDriver *drv);
extern uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry); extern uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry);
extern void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData); extern void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData);
extern bool sdmmc_is_busy(SdmmcDriver *driver);
#endif /* CH_SDMMC_DEVICE_H_ */ #endif /* CH_SDMMC_DEVICE_H_ */

View File

@ -41,7 +41,8 @@
#include "hal.h" #include "hal.h"
#if (HAL_USE_SDMMC == TRUE) #if (HAL_USE_SDMMC == TRUE)
#include "sama_sdmmc_lld.h"
#if SDMMC_USE_FF_LIB == 1
#include "ccportab.h" #include "ccportab.h"
#include "ffconf.h" #include "ffconf.h"
#include "diskio.h" #include "diskio.h"
@ -309,4 +310,5 @@ DRESULT disk_ioctl(BYTE slot, BYTE cmd, void* buff)
return res; return res;
} }
#endif #endif
#endif

View File

@ -155,7 +155,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
if (error) if (error)
return error; return error;
//else //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), /* SEND_CSD (CMD9) to obtain the Card Specific Data (CSD register),
* e.g. block length, card storage capacity, etc... */ * e.g. block length, card storage capacity, etc... */
@ -211,9 +211,8 @@ uint8_t MmcInit(SdmmcDriver *driver)
sw_arg.value = 0xf; sw_arg.value = 0xf;
error = MmcCmd6(driver, &sw_arg, &status); error = MmcCmd6(driver, &sw_arg, &status);
if (error) { if (error) {
TRACE_1("Pwr class %s\n\r", TRACE_DEBUG_1("Pwr class %s\n\r",SD_StringifyRetCode(error));
SD_StringifyRetCode(error)); }
}
} }
} }
@ -274,8 +273,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
&& tim_mode == SDMMC_TIM_MMC_HS_DDR) && tim_mode == SDMMC_TIM_MMC_HS_DDR)
driver->card.bSpeedMode = tim_mode; driver->card.bSpeedMode = tim_mode;
else if (error) { else if (error) {
TRACE_ERROR_1("Width/DDR %s\n\r", TRACE_ERROR_1("Width/DDR %s\n\r",SD_StringifyRetCode(error));
SD_StringifyRetCode(error));
return error; return error;
} }
} }

View File

@ -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

View File

@ -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_ */

View File

@ -479,6 +479,29 @@ void SdParamReset(sSdCard * pSd)
memset(pSd->SCR, 0, SCR_SIZE); 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;
}
/** /**

View File

@ -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_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_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_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks);
extern uint8_t SD_GetWpStatus(SdmmcDriver *driver);
#endif /* CH_SDMMC_SD_H_ */ #endif /* CH_SDMMC_SD_H_ */

View File

@ -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_mmc.c \
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.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/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 $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c
PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1 PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1

View File

@ -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 <redfs.h>
#if REDCONF_ASSERTS == 1
#include <redosdeviations.h>
/** @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

View File

@ -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 <redfs.h>
#include <redvolume.h>
#include <redosdeviations.h>
#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

View File

@ -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 <redfs.h>
/** @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

View File

@ -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 <redfs.h>
#include <redosdeviations.h>
#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

View File

@ -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 <redfs.h>
#if REDCONF_OUTPUT == 1
#include <redosdeviations.h>
/** @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

View File

@ -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 <redfs.h>
#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1)
#include <redosdeviations.h>
/** @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

View File

@ -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 <stdio.h>
#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

View File

@ -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

View File

@ -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 <apptypes.h>
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 <stdbool.h>
/* Defines uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t,
int64_t, and uintptr_t.
*/
//#include <stdint.h>
#endif

View File

@ -3,19 +3,19 @@
#include "ch_sdmmc_sama5d2.h" #include "ch_sdmmc_sama5d2.h"
#include "ff.h"
typedef FATFS CH_SDMMC_FAT;
#ifndef SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY #ifndef SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY
#define SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY 4 #define SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY 4
#endif #endif
#ifndef SAMA_SDMMC_TRACE #ifndef SAMA_SDMMC_TRACE
#define SAMA_SDMMC_TRACE 0 #define SAMA_SDMMC_TRACE 0
#endif #endif
#ifndef SAMA_SDMMC_TRACE_LEVEL #ifndef SAMA_SDMMC_TRACE_LEVEL
#define SAMA_SDMMC_TRACE_LEVEL 0 #define SAMA_SDMMC_TRACE_LEVEL 5
#endif #endif
/** Default block size for SD/MMC access */ /** Default block size for SD/MMC access */
@ -24,6 +24,13 @@ typedef FATFS CH_SDMMC_FAT;
#endif #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 #endif //SAMA_SDMMC_CONF_H

View File

@ -87,9 +87,6 @@ OSAL_IRQ_HANDLER(SAMA_SDMMCD1_HANDLER) {
void sdmmcInit(void) void sdmmcInit(void)
{ {
#if PLATFORM_SDMMC_USE_SDMMC1 == TRUE #if PLATFORM_SDMMC_USE_SDMMC1 == TRUE
#if SAMA_HAL_IS_SECURE
mtxConfigPeriphSecurity(MATRIX0, ID_SDMMC1, SECURE_PER);
#endif /* SAMA_HAL_IS_SECURE */
/* Driver initialization.*/ /* Driver initialization.*/
sdmmcObjectInit(&SDMMCD1); sdmmcObjectInit(&SDMMCD1);
#endif #endif
@ -110,6 +107,10 @@ void sdmmcStart(SdmmcDriver *sdmmcp, const SamaSDMMCConfig *config)
sdmmcp->config = 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.EXT = sdmmcp->config->bp;
sdmmcp->card.SSR = &sdmmcp->config->bp[EXT_SIZE]; sdmmcp->card.SSR = &sdmmcp->config->bp[EXT_SIZE];
sdmmcp->card.SCR = &sdmmcp->config->bp[EXT_SIZE + SSR_SIZE]; sdmmcp->card.SCR = &sdmmcp->config->bp[EXT_SIZE + SSR_SIZE];
@ -307,37 +308,6 @@ bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp)
return true; 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) bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)
{ {

View File

@ -127,7 +127,7 @@ struct SamaSDMMCDriver
}; };
typedef sSdCard sdmmclib;
typedef struct SamaSDMMCDriver SdmmcDriver; typedef struct SamaSDMMCDriver SdmmcDriver;
/*===========================================================================*/ /*===========================================================================*/
@ -154,8 +154,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp);
bool sdmmcOpenDevice(SdmmcDriver *sdmmcp); bool sdmmcOpenDevice(SdmmcDriver *sdmmcp);
bool sdmmcCloseDevice(SdmmcDriver *sdmmcp); bool sdmmcCloseDevice(SdmmcDriver *sdmmcp);
bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp); bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp);
bool sdmmcMountVolume(SdmmcDriver *sdmmcp,CH_SDMMC_FAT *fs); bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) ;
bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -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

View File

@ -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)

View File

@ -32,7 +32,8 @@
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<entry excluding="os/hal/ports/SAMA/LLD/SDMMCv0+" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> <entry excluding="os|os/hal/ports/SAMA/LLD/SDMMCv0+" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="os"/>
</sourceEntries> </sourceEntries>
</configuration> </configuration>
</storageModule> </storageModule>
@ -55,4 +56,10 @@
</scannerConfigBuildInfo> </scannerConfigBuildInfo>
</storageModule> </storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/SAMA5D2-SDMMC"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject> </cproject>

View File

@ -87,5 +87,10 @@
<type>2</type> <type>2</type>
<locationURI>CHIBIOS/os</locationURI> <locationURI>CHIBIOS/os</locationURI>
</link> </link>
<link>
<name>reliance-edge</name>
<type>2</type>
<locationURI>$%7BPARENT-3-PROJECT_LOC%7D/ext/reliance-edge</locationURI>
</link>
</linkedResources> </linkedResources>
</projectDescription> </projectDescription>

View File

@ -121,15 +121,12 @@ include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional). # RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCAx-TZ/compilers/GCC/mk/port_generic.mk include $(CHIBIOS)/os/common/ports/ARMCAx-TZ/compilers/GCC/mk/port_generic.mk
# Other files (optional). include $(CHIBIOS)/os/various/reledge_bindings/reledge.mk
#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/various/fatfs_bindings/fatfs.mk
include $(CHIBIOS)/os/hal/lib/streams/streams.mk include $(CHIBIOS)/os/hal/lib/streams/streams.mk
# Define linker script file here # 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 # C sources that can be compiled in ARM or THUMB mode depending on the global
# setting. # setting.
CSRC = $(STARTUPSRC) \ CSRC = $(STARTUPSRC) \
@ -140,7 +137,7 @@ CSRC = $(STARTUPSRC) \
$(PLATFORMSRC) \ $(PLATFORMSRC) \
$(BOARDSRC) \ $(BOARDSRC) \
$(TESTSRC) $(STREAMSSRC) \ $(TESTSRC) $(STREAMSSRC) \
main.c main.c fat32test.c reledgetest.c redconf.c $(RELEDGESRC)
CSRC += $(CHIBIOS)/os/various/syscalls.c CSRC += $(CHIBIOS)/os/various/syscalls.c
CSRC += $(CHIBIOS)/os/various/fatfs_bindings/fatfs_syscall.c CSRC += $(CHIBIOS)/os/various/fatfs_bindings/fatfs_syscall.c
@ -177,9 +174,8 @@ ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(CHIBIOS)/os/license \ INCDIR = $(CHIBIOS)/os/license \
$(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
$(CHIBIOS)/os/various $(STREAMSINC) $(CHIBIOS)/os/various $(STREAMSINC) $(FATFSINC) $(RELEDGEINC)
INCDIR += $(FATFSINC)
# #
# Project, sources and paths # Project, sources and paths
############################################################################## ##############################################################################
@ -228,10 +224,10 @@ CPPWARN = -Wall -Wextra -Wundef
# #
# List all user C define here, like -D_DEBUG=1 # 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 # Define ASM defines here
UADEFS = -DCH_CFG_USE_MMU UADEFS =
# List all user directories here # List all user directories here
UINCDIR = UINCDIR =

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.cdt.debug.gdbjtag.launchConfigurationType">
<stringAttribute key="bad_container_name" value="/RT-SAMA5D2-XPLAINED/debu"/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.delay" value="3"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doHalt" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="false"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="mon reg cpsr = 0xd3&#13;&#10;set *0xF8048000 = 0xA5000004&#13;&#10;set *0x00A00100 = 0&#13;&#10;set *0xF8048044 = 0x00008000&#13;&#10;mon cp15 1 0 0 0 = 0x00C50078&#13;&#10;set *0xF0014004 = 0x4&#13;&#10;set *0xF0014014 = 1&lt;&lt;13&#13;&#10;load ./bootstrap.elf&#13;&#10;&#10;mon reg pc = 0x00200000&#13;&#10;&#10;continue"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="Generic TCP/IP"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value="20100000"/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="2331"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.runCommands" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="_start"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="arm-none-eabi-gdb"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="Standard"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="arm-none-eabi-gdb"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList&gt;&lt;content id=&quot;mode-_pal_lld_setgroupmode-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;null-boardInit-(format)&quot; val=&quot;2&quot;/&gt;&lt;content id=&quot;null-sama_clock_init-(format)&quot; val=&quot;4&quot;/&gt;&lt;content id=&quot;null-_pal_lld_setgroupmode-(format)&quot; val=&quot;4&quot;/&gt;&lt;/contentList&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;globalVariableList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="SAMA5D2-SDMMC"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/SAMA5D2-SDMMC"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
<mapEntry key="[debug]" value="org.eclipse.cdt.debug.gdbjtag.core.dsfLaunchDelegate"/>
</mapAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList context=&quot;reserved-for-future-use&quot;/&gt;&#13;&#10;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

View File

@ -17,7 +17,7 @@
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="true"/> <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/> <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/> <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="_start"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/> <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>

View File

@ -6,7 +6,7 @@
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="false"/> <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="false"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="mon reg cpsr = 0xd3&#13;&#10;set *0xF8048000 = 0xA5000004&#13;&#10;set *0x00A00100 = 0&#13;&#10;set *0xF8048044 = 0x00008000&#13;&#10;mon cp15 1 0 0 0 = 0x00C50078&#13;&#10;set *0xF0014004 = 0x4&#13;&#10;set *0xF0014014 = 1&lt;&lt;13&#13;&#10;load ./bootstrap.elf&#13;&#10;mon reg pc = 0x00200000&#13;&#10;continue"/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="mon reg cpsr = 0xd3&#13;&#10;set *0xF8048000 = 0xA5000004&#13;&#10;set *0x00A00100 = 0&#13;&#10;set *0xF8048044 = 0x00008000&#13;&#10;mon cp15 1 0 0 0 = 0x00C50078&#13;&#10;set *0xF0014004 = 0x4&#13;&#10;set *0xF0014014 = 1&lt;&lt;13&#13;&#10;load ./bootstrap.elf&#13;&#10;&#10;mon reg pc = 0x00200000&#13;&#10;&#10;continue"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="Generic TCP/IP"/> <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="Generic TCP/IP"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/> <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>

View File

@ -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 <string.h>
#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;i<DEMO_VOLUMES;i++) {
if ( mountVolume(i,&fs_header) ) {
writefile(i);
chprintf(ts,"reading dir:\n\r");
getdir(i);
readfile(i);
unmountVolume(i);
}
}
}
}
static void writefile(uint8_t vi)
{
TCHAR file_path[sizeof(volume_paths[vi]) + sizeof(test_file_path)];
FRESULT res;
UINT len;
strcpy(file_path, volume_paths[vi]);
strcat(file_path, test_file_path);
chprintf(ts,"Creating new file ... %s ",file_path);
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,"error %d \n\r", res);
}
}
else
{
chprintf(ts,"Failed error %d\n\r", res);
}
f_close(&f_header);
}
static void readfile(uint8_t vi)
{
TCHAR file_path[sizeof(volume_paths[vi]) + sizeof(test_file_path)];
FRESULT res;
UINT len;
uint8_t buffer[19];
UINT i;
strcpy(file_path, volume_paths[vi]);
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;i<len;i++) {
chprintf(ts,"%c", buffer[i]);
}
chprintf(ts,"\r\n");
}
}
else
{
chprintf(ts,"Failed error %d\n\r", res);
}
f_close(&f_header);
}
static void getdir(uint8_t vi)
{
DIR dir = { .sect = 0 };
FILINFO fno = { 0 };
FRESULT res;
bool is_dir;
res = f_opendir(&dir, volume_paths[vi]);
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);
}
static bool mountVolume(uint8_t vi, FATFS *fs)
{
FRESULT res;
DWORD fre_clust, fre_sect, tot_sect;
memset(fs, 0, sizeof(FATFS));
res = f_mount(fs, volume_paths[vi], 1);
if (res != FR_OK) {
chprintf(ts,"Failed to mount FAT file system, error %d\n\r", res);
return false;
}
else
{
chprintf(ts, "setting label %s",volume_labels[vi]);
res = f_setlabel(volume_labels[vi]);
if (res == FR_OK) {
chprintf(ts, " OK\r\n");
}
else
{
chprintf(ts, " FAILED err %d\r\n",res);
return false;
}
res = f_getfree(volume_paths[vi], &fre_clust, &fs);
if (res == FR_OK) {
//Get total sectors and free sectors
tot_sect = (fs->n_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;
}

View File

@ -0,0 +1,10 @@
#ifndef FAT32TEST_H_
#define FAT32TEST_H_
extern void fat32test_demo(void);
#endif /* FAT32TEST_H_ */

View File

@ -1,5 +1,6 @@
/* CHIBIOS FIX */ /* CHIBIOS FIX */
#include "ch.h" #include "ch.h"
#include "sama_sdmmc_conf.h"
/*---------------------------------------------------------------------------/ /*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016 / 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) */ / 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) */ /* 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. */ / (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(). /* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */ / (0:Disable or 1:Enable) */
@ -163,7 +164,7 @@
/ the drive ID strings are: A-Z and 0-9. */ / 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. /* 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 / 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. / number and only an FAT volume found on the physical drive will be mounted.
@ -172,8 +173,8 @@
/ funciton will be available. */ / funciton will be available. */
#define FF_MIN_SS 512 #define FF_MIN_SS SDMMC_BLOCK_SIZE
#define FF_MAX_SS 512 #define FF_MAX_SS SDMMC_BLOCK_SIZE
/* These options configure the range of sector size to be supported. (512, 1024, /* 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 / 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 / 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_FS_NORTC 1
#define FF_NORTC_MON 1 #define FF_NORTC_MON 1
#define FF_NORTC_MDAY 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 /* 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 / 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 / the timestamp function. All objects modified by FatFs will have a fixed timestamp

View File

@ -18,7 +18,15 @@
#include "hal.h" #include "hal.h"
#include "sama_sdmmc_lld.h" #include "sama_sdmmc_lld.h"
#include "chprintf.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 BLOCK_CNT_MAX 32u
#define DMADL_CNT_MAX 64u #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 uint8_t data_buf[BLOCK_CNT_MAX * 512ul];
CACHE_ALIGNED static uint32_t dma_table[DMADL_CNT_MAX * SDMMC_DMADL_SIZE]; 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)]; CACHE_ALIGNED uint8_t sdmmcbuffer[ROUND_UP_MULT(SDMMC_BUFFER_SIZE, L1_CACHE_BYTES)];
static FATFS fs_header;
static FIL f_header;
BaseSequentialStream * ts; BaseSequentialStream * ts;
@ -56,9 +61,17 @@ static THD_FUNCTION(Thread1, arg) {
} }
} }
#if DEMO_SLOT == 0
static const SamaSDMMCConfig sdmmc_cfg = {
static const SamaSDMMCConfig sdmmc_slot1_cfg = { SDMMC_SLOT0,
sdmmcbuffer,
data_buf,
sizeof(data_buf),
dma_table,
DMADL_CNT_MAX
};
#else
static const SamaSDMMCConfig sdmmc_cfg = {
SDMMC_SLOT1, SDMMC_SLOT1,
sdmmcbuffer, sdmmcbuffer,
data_buf, data_buf,
@ -66,10 +79,8 @@ static const SamaSDMMCConfig sdmmc_slot1_cfg = {
dma_table, dma_table,
DMADL_CNT_MAX DMADL_CNT_MAX
}; };
#endif
void getdir(SdmmcDriver *sdmmcp);
void writefile(SdmmcDriver *sdmmcp);
void readfile(SdmmcDriver *sdmmcp);
/* /*
* Application entry point. * Application entry point.
*/ */
@ -98,23 +109,26 @@ int main(void) {
sdmmcInit(); sdmmcInit();
sdmmcStart(&SDMMCD1, &sdmmc_slot1_cfg); sdmmcStart(&SDMMCD1, &sdmmc_cfg);
if (SDMMCD1.state != MCID_INIT_ERROR) { 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)) { if (sdmmcOpenDevice(&SDMMCD1)) {
//sdmmcShowDeviceInfo(&SDMMCD1); #if DEMO_FAT == 1
if ( sdmmcMountVolume(&SDMMCD1,&fs_header) ) { fat32test_demo();
writefile(&SDMMCD1); #else
chprintf(ts,"reading dir:\n\r"); relianceedge_demo();
getdir(&SDMMCD1); #endif
readfile(&SDMMCD1);
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) bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)
{ {
if (index == SDMMCD1.config->slot_id) { (void)index;
*sdmmcp = &SDMMCD1;
return true;
}
return false;
}
void writefile(SdmmcDriver *sdmmcp) *sdmmcp = &SDMMCD1;
{
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};
return true;
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;i<len;i++) {
chprintf(ts,"%c", buffer[i]);
}
}
}
else
{
chprintf(ts,"Failed error %d\n\r", res);
}
f_close(&f_header);
}
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);
} }

View File

@ -23,7 +23,7 @@
* HAL driver system settings. * HAL driver system settings.
*/ */
#define SAMA_HAL_IS_SECURE TRUE #define SAMA_HAL_IS_SECURE TRUE
#define SAMA_NO_INIT FALSE #define SAMA_NO_INIT TRUE
#define SAMA_MOSCRC_ENABLED FALSE #define SAMA_MOSCRC_ENABLED FALSE
#define SAMA_MOSCXT_ENABLED TRUE #define SAMA_MOSCXT_ENABLED TRUE
#define SAMA_MOSC_SEL SAMA_MOSC_MOSCXT #define SAMA_MOSC_SEL SAMA_MOSC_MOSCXT

View File

@ -7,6 +7,7 @@
The demo targets a generic ARM Cortex-A5 device without HAL support. The demo targets a generic ARM Cortex-A5 device without HAL support.
** The Demo ** ** The Demo **
Testing FF and Reliance Edge Libraries
** Build Procedure ** ** Build Procedure **

View File

@ -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 <redfs.h>
#include <redconf.h>
#include <redtypes.h>
#include <redmacs.h>
#include <redvolume.h>
const VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT] =
{
{
SDMMC_BLOCK_SIZE, //ulSectorSize
1048576U, //ullSectorCount
0U, //ullSectorOffset
false, //fAtomicSectorWrite
1024U, //ulInodeCount
2U, //bBlockIoRetries
"CHIBIVOL"
}
};
#endif
#endif

View File

@ -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 <string.h>
#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

View File

@ -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 <stdio.h>
#include <string.h>
#include "ch.h"
#include "hal.h"
#include "sama_sdmmc_lld.h"
#if SDMMC_USE_RELEDGE_LIB == 1
#include "chprintf.h"
#include <redfs.h>
#include <redposix.h>
#include <redfse.h>
#include <redconf.h>
#include <redtypes.h>
#include <redmacs.h>
#include <redvolume.h>
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

View File

@ -0,0 +1,8 @@
#ifndef RELEDGETEST_H_
#define RELEDGETEST_H_
extern void relianceedge_demo(void);
#endif /* RELEDGETEST_H_ */