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:
parent
70fb3b4056
commit
0c51b431f2
|
@ -53,6 +53,7 @@ uint32_t SdmmcGetMaxFreq(SdmmcDriver *drv)
|
|||
rate /= 2ul;
|
||||
}
|
||||
|
||||
TRACE_DEBUG_1("SdmmcGetMaxFreq rate %d\r\n",rate);
|
||||
return rate * 1000ul;
|
||||
}
|
||||
|
||||
|
@ -98,7 +99,7 @@ void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData)
|
|||
uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
|
||||
{
|
||||
uint64_t mem_size;
|
||||
//uint32_t freq;
|
||||
uint32_t freq;
|
||||
uint32_t drv_err, status;
|
||||
uint8_t error;
|
||||
bool flag;
|
||||
|
@ -260,14 +261,16 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
|
|||
: (uint32_t)mem_size;
|
||||
}
|
||||
|
||||
//TO BE DONE
|
||||
#if 0
|
||||
|
||||
/* Automatically select the max device clock frequency */
|
||||
/* Calculate transfer speed */
|
||||
freq = SdmmcGetMaxFreq(drv);
|
||||
|
||||
#ifndef SDMMC_TRIM_SDIO
|
||||
if (drv->card.bCardType & CARD_TYPE_bmSDIO)
|
||||
if (drv->card.bCardType & CARD_TYPE_bmSDIO) {
|
||||
freq = min_u32(freq, SdioGetMaxFreq(drv));
|
||||
TRACE_INFO_1("selecting sdio freq%d\r\n",freq);
|
||||
}
|
||||
#endif
|
||||
error = HwSetClock(drv, &freq);
|
||||
drv->card.dwCurrSpeed = freq;
|
||||
|
@ -275,7 +278,7 @@ uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry)
|
|||
TRACE_ERROR_1("error clk %s\n\r", SD_StringifyRetCode(error));
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check device status and eat past exceptions, which would otherwise
|
||||
* prevent upcoming data transaction routines from reliably checking
|
||||
* fresh exceptions. */
|
||||
|
|
|
@ -644,8 +644,8 @@ uint8_t Cmd23(SdmmcDriver *drv, uint8_t write, uint32_t blocks, uint32_t * pStat
|
|||
pCmd->pResp = pStatus;
|
||||
|
||||
drv->timeout_elapsed = -1;
|
||||
/* Send command */
|
||||
bRc = sdmmcSendCmd(drv);
|
||||
/* Send command */
|
||||
bRc = sdmmcSendCmd(drv);
|
||||
return bRc;
|
||||
}
|
||||
|
||||
|
@ -680,8 +680,8 @@ uint8_t Cmd24(SdmmcDriver *drv,
|
|||
pCmd->wNbBlocks = 1;
|
||||
pCmd->pData = pData;
|
||||
drv->timeout_elapsed = -1;
|
||||
/* Send command */
|
||||
bRc = sdmmcSendCmd(drv);
|
||||
/* Send command */
|
||||
bRc = sdmmcSendCmd(drv);
|
||||
return bRc;
|
||||
}
|
||||
|
||||
|
@ -719,8 +719,8 @@ uint8_t Cmd25(SdmmcDriver *drv,
|
|||
pCmd->pData = pData;
|
||||
|
||||
drv->timeout_elapsed = -1;
|
||||
/* Send command */
|
||||
bRc = sdmmcSendCmd(drv);
|
||||
/* Send command */
|
||||
bRc = sdmmcSendCmd(drv);
|
||||
if (bRc == SDMMC_CHANGED)
|
||||
*nbBlock = pCmd->wNbBlocks;
|
||||
return bRc;
|
||||
|
|
|
@ -53,7 +53,7 @@ static uint8_t HwReset(SdmmcDriver *driver);
|
|||
|
||||
|
||||
static void sdmmc_get_response(SdmmcDriver *driver, sSdmmcCommand *cmd, bool complete, uint32_t *out);
|
||||
static bool sdmmc_is_busy(SdmmcDriver *driver);
|
||||
|
||||
static uint8_t sdmmc_build_dma_table( SdmmcDriver *driver );
|
||||
static uint8_t unplug_device(SdmmcDriver *driver);
|
||||
static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verify);
|
||||
|
@ -70,12 +70,10 @@ uint8_t sdmmc_device_lowlevelcfg(SdmmcDriver *driver)
|
|||
|
||||
if (driver->config->slot_id == SDMMC_SLOT0) {
|
||||
driver->regs = SDMMC0;
|
||||
pmcEnableSDMMC0()
|
||||
;
|
||||
pmcEnableSDMMC0();
|
||||
} else if (driver->config->slot_id == SDMMC_SLOT1) {
|
||||
driver->regs = SDMMC1;
|
||||
pmcEnableSDMMC1()
|
||||
;
|
||||
pmcEnableSDMMC1();
|
||||
}
|
||||
|
||||
switch (driver->config->slot_id) {
|
||||
|
@ -704,12 +702,14 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
|
|||
bool use_prog_mode = false;
|
||||
|
||||
freq = min_u32(freq, 120000000ul);
|
||||
#ifndef NDEBUG
|
||||
//if (!(regs->SDMMC_PCR & SDMMC_PCR_SDBPWR))
|
||||
// trace_error("Bus is off\n\r");
|
||||
//if (regs->SDMMC_HC2R & SDMMC_HC2R_PVALEN)
|
||||
// trace_error("Preset values enabled though not implemented\n\r");
|
||||
#endif
|
||||
|
||||
if (!(regs->SDMMC_PCR & SDMMC_PCR_SDBPWR)) {
|
||||
TRACE_ERROR("Bus is off\n\r");
|
||||
}
|
||||
if (regs->SDMMC_HC2R & SDMMC_HC2R_PVALEN) {
|
||||
TRACE_ERROR("Preset values enabled though not implemented\n\r");
|
||||
}
|
||||
|
||||
/* In the Divided Clock Mode scenario, compute the divider */
|
||||
base_freq = (regs->SDMMC_CA0R & SDMMC_CA0R_BASECLKF_Msk) >> SDMMC_CA0R_BASECLKF_Pos;
|
||||
base_freq *= 1000000UL;
|
||||
|
@ -732,10 +732,10 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
|
|||
* is 32 whereas the real value is 40.5 */
|
||||
mult_freq = (regs->SDMMC_CA1R & SDMMC_CA1R_CLKMULT_Msk) >> SDMMC_CA1R_CLKMULT_Pos;
|
||||
if (mult_freq != 0)
|
||||
#if 1
|
||||
#if 0
|
||||
mult_freq = base_freq * (mult_freq + 1);
|
||||
#else
|
||||
mult_freq = pmc_get_gck_clock(ID_SDMMC0+driver->config->slot_id);
|
||||
mult_freq = SAMA_MCK ;// pmc_get_gck_clock(ID_SDMMC0+driver->config->slot_id);
|
||||
#endif
|
||||
if (mult_freq != 0) {
|
||||
/* DIV = FMULTCLK / FSDCLK - 1 */
|
||||
|
@ -761,6 +761,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
|
|||
shval = regs->SDMMC_CCR & ~SDMMC_CCR_SDCLKEN;
|
||||
regs->SDMMC_CCR = shval;
|
||||
driver->dev_freq = new_freq;
|
||||
use_prog_mode = false; //no generated clock
|
||||
/* Select the clock mode */
|
||||
if (use_prog_mode)
|
||||
shval |= SDMMC_CCR_CLKGSEL;
|
||||
|
@ -1220,7 +1221,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
|
|||
|
||||
sdmmc_set_device_clock(driver, driver->control_param);
|
||||
|
||||
TRACE_DEBUG_1("Clocking the device at %lu Hz\n\r", driver->dev_freq);
|
||||
TRACE_DEBUG_1("Clocking the device at %lu Hz\n\r", driver->dev_freq);
|
||||
if (driver->dev_freq > 95000000ul
|
||||
&& (driver->tim_mode == SDMMC_TIM_MMC_HS200
|
||||
|| driver->tim_mode == SDMMC_TIM_SD_SDR104
|
||||
|
@ -1495,7 +1496,7 @@ void sdmmc_device_deInit(SdmmcDriver *drv)
|
|||
}
|
||||
}
|
||||
|
||||
static bool sdmmc_is_busy(SdmmcDriver *driver)
|
||||
bool sdmmc_is_busy(SdmmcDriver *driver)
|
||||
{
|
||||
//osalDbgCheck(driver->state != MCID_OFF);
|
||||
|
||||
|
@ -1660,13 +1661,13 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif
|
|||
&& !(caps & SDMMC_CA0R_V18VSUP))
|
||||
return SDMMC_PARAM;
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if 0
|
||||
/* FIXME The datasheet is unclear about CCR:DIV restriction when the MMC
|
||||
* timing mode is High Speed DDR */
|
||||
if ((mode == SDMMC_TIM_MMC_HS_SDR || mode == SDMMC_TIM_MMC_HS_DDR
|
||||
|| mode == SDMMC_TIM_SD_HS) && !(regs->SDMMC_CCR
|
||||
& (SDMMC_CCR_USDCLKFSEL_Msk | SDMMC_CCR_SDCLKFSEL_Msk))) {
|
||||
//trace_error("Incompatible with the current clock config\n\r");
|
||||
TRACE_ERROR("Incompatible with the current clock config\n\r");
|
||||
return SDMMC_STATE;
|
||||
}
|
||||
#endif
|
||||
|
@ -1724,11 +1725,13 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif
|
|||
goto End;
|
||||
toggle_sig_lvl = pcr_prv & SDMMC_PCR_SDBPWR
|
||||
&& (pcr ^ pcr_prv) & SDMMC_PCR_SDBVSEL_Msk;
|
||||
//if (!(pcr_prv & SDMMC_PCR_SDBPWR))
|
||||
// trace_debug("Power the device on\n\r");
|
||||
//else if (toggle_sig_lvl)
|
||||
// trace_debug("Signaling level going %s\n\r",
|
||||
// hc2r & SDMMC_HC2R_VS18EN ? "low" : "high");
|
||||
if (!(pcr_prv & SDMMC_PCR_SDBPWR)) {
|
||||
TRACE_DEBUG("Power the device on\n\r");
|
||||
}
|
||||
else if (toggle_sig_lvl) {
|
||||
TRACE_DEBUG_1("Signaling level going %s\n\r",
|
||||
hc2r & SDMMC_HC2R_VS18EN ? "low" : "high");
|
||||
}
|
||||
if (verify && toggle_sig_lvl && hc2r & SDMMC_HC2R_VS18EN) {
|
||||
/* Expect this call to follow the VOLTAGE_SWITCH command;
|
||||
* allow 2 device clock periods before the device pulls the CMD
|
||||
|
@ -1787,7 +1790,7 @@ static uint8_t sdmmc_set_speed_mode(SdmmcDriver *driver, uint8_t mode,bool verif
|
|||
if (!dev_clk_on)
|
||||
regs->SDMMC_CCR &= ~SDMMC_CCR_SDCLKEN;
|
||||
}
|
||||
//trace_debug("Using timing mode 0x%02x\n\r", mode);
|
||||
TRACE_DEBUG_1("Using timing mode 0x%02x\n\r", mode);
|
||||
|
||||
regs->SDMMC_CALCR = (regs->SDMMC_CALCR & ~SDMMC_CALCR_ALWYSON)
|
||||
| (low_sig ? SDMMC_CALCR_ALWYSON : 0);
|
||||
|
|
|
@ -379,5 +379,6 @@ extern uint8_t SdMmcSelect(SdmmcDriver *drv, uint16_t address, uint8_t statCheck
|
|||
extern uint8_t SdMmcIdentify(SdmmcDriver *drv);
|
||||
extern uint8_t SDMMC_Lib_SdStart(SdmmcDriver *drv, bool * retry);
|
||||
extern void SdMmcUpdateInformation(SdmmcDriver *drv, bool csd, bool extData);
|
||||
extern bool sdmmc_is_busy(SdmmcDriver *driver);
|
||||
|
||||
#endif /* CH_SDMMC_DEVICE_H_ */
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
#include "hal.h"
|
||||
|
||||
#if (HAL_USE_SDMMC == TRUE)
|
||||
|
||||
#include "sama_sdmmc_lld.h"
|
||||
#if SDMMC_USE_FF_LIB == 1
|
||||
#include "ccportab.h"
|
||||
#include "ffconf.h"
|
||||
#include "diskio.h"
|
||||
|
@ -309,4 +310,5 @@ DRESULT disk_ioctl(BYTE slot, BYTE cmd, void* buff)
|
|||
return res;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
|
|||
if (error)
|
||||
return error;
|
||||
//else
|
||||
TRACE_1("RCA=%u\n\r", driver->card.wAddress);
|
||||
TRACE_DEBUG_1("RCA=%u\n\r", driver->card.wAddress);
|
||||
|
||||
/* SEND_CSD (CMD9) to obtain the Card Specific Data (CSD register),
|
||||
* e.g. block length, card storage capacity, etc... */
|
||||
|
@ -211,9 +211,8 @@ uint8_t MmcInit(SdmmcDriver *driver)
|
|||
sw_arg.value = 0xf;
|
||||
error = MmcCmd6(driver, &sw_arg, &status);
|
||||
if (error) {
|
||||
TRACE_1("Pwr class %s\n\r",
|
||||
SD_StringifyRetCode(error));
|
||||
}
|
||||
TRACE_DEBUG_1("Pwr class %s\n\r",SD_StringifyRetCode(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,8 +273,7 @@ uint8_t MmcInit(SdmmcDriver *driver)
|
|||
&& tim_mode == SDMMC_TIM_MMC_HS_DDR)
|
||||
driver->card.bSpeedMode = tim_mode;
|
||||
else if (error) {
|
||||
TRACE_ERROR_1("Width/DDR %s\n\r",
|
||||
SD_StringifyRetCode(error));
|
||||
TRACE_ERROR_1("Width/DDR %s\n\r",SD_StringifyRetCode(error));
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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_ */
|
|
@ -479,6 +479,29 @@ void SdParamReset(sSdCard * pSd)
|
|||
memset(pSd->SCR, 0, SCR_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query whether the card is writeprotected or not by mechanical
|
||||
write protect switch.
|
||||
* \param pSd Pointer to \ref sSdCard instance.
|
||||
* \return an \ref sdmmc_rc "error code", as follows:
|
||||
* - SDMMC_LOCKED if the device has been mechanical write protected.
|
||||
* - SDMMC_OK if the card is not write-protected.
|
||||
*/
|
||||
uint8_t SD_GetWpStatus(SdmmcDriver *driver)
|
||||
{
|
||||
uint32_t rc;
|
||||
|
||||
driver->control_param = 0;
|
||||
|
||||
rc = sdmmc_device_control(driver,SDMMC_IOCTL_GET_WP);
|
||||
|
||||
if (rc != SDMMC_OK)
|
||||
return SDMMC_NOT_SUPPORTED;
|
||||
if (!driver->control_param)
|
||||
return SDMMC_LOCKED;
|
||||
else
|
||||
return SDMMC_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,5 +112,6 @@ extern uint8_t SD_Write(SdmmcDriver *driver,uint32_t address,const void *pData,u
|
|||
extern uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks);
|
||||
extern uint8_t SD_WriteBlocks(SdmmcDriver *driver, uint32_t address, const void *pData, uint32_t nbBlocks);
|
||||
extern uint8_t SD_ReadBlocks(SdmmcDriver *driver, uint32_t address, void *pData, uint32_t nbBlocks);
|
||||
extern uint8_t SD_GetWpStatus(SdmmcDriver *driver);
|
||||
|
||||
#endif /* CH_SDMMC_SD_H_ */
|
||||
|
|
|
@ -5,6 +5,13 @@ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/sama_sdmmc_lld.c \
|
|||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_mmc.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_sd.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osassert.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osoutput.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osclock.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osbdev.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/osmutex.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ostask.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_reledge.c \
|
||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1/ch_sdmmc_ff.c
|
||||
|
||||
PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/SDMMCv1
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -3,19 +3,19 @@
|
|||
|
||||
#include "ch_sdmmc_sama5d2.h"
|
||||
|
||||
#include "ff.h"
|
||||
typedef FATFS CH_SDMMC_FAT;
|
||||
|
||||
|
||||
|
||||
#ifndef SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY
|
||||
#define SAMA_SDMMC_SDMMCDRIVER_IRQ_PRIORITY 4
|
||||
#endif
|
||||
|
||||
#ifndef SAMA_SDMMC_TRACE
|
||||
#define SAMA_SDMMC_TRACE 0
|
||||
#define SAMA_SDMMC_TRACE 0
|
||||
#endif
|
||||
|
||||
#ifndef SAMA_SDMMC_TRACE_LEVEL
|
||||
#define SAMA_SDMMC_TRACE_LEVEL 0
|
||||
#define SAMA_SDMMC_TRACE_LEVEL 5
|
||||
#endif
|
||||
|
||||
/** Default block size for SD/MMC access */
|
||||
|
@ -24,6 +24,13 @@ typedef FATFS CH_SDMMC_FAT;
|
|||
#endif
|
||||
|
||||
|
||||
#ifndef SDMMC_USE_FF_LIB
|
||||
#define SDMMC_USE_FF_LIB 1
|
||||
#endif
|
||||
|
||||
#ifndef SDMMC_USE_RELEDGE_LIB
|
||||
#define SDMMC_USE_RELEDGE_LIB 1
|
||||
#endif
|
||||
|
||||
#endif //SAMA_SDMMC_CONF_H
|
||||
|
||||
|
|
|
@ -87,9 +87,6 @@ OSAL_IRQ_HANDLER(SAMA_SDMMCD1_HANDLER) {
|
|||
void sdmmcInit(void)
|
||||
{
|
||||
#if PLATFORM_SDMMC_USE_SDMMC1 == TRUE
|
||||
#if SAMA_HAL_IS_SECURE
|
||||
mtxConfigPeriphSecurity(MATRIX0, ID_SDMMC1, SECURE_PER);
|
||||
#endif /* SAMA_HAL_IS_SECURE */
|
||||
/* Driver initialization.*/
|
||||
sdmmcObjectInit(&SDMMCD1);
|
||||
#endif
|
||||
|
@ -110,6 +107,10 @@ void sdmmcStart(SdmmcDriver *sdmmcp, const SamaSDMMCConfig *config)
|
|||
|
||||
sdmmcp->config = config;
|
||||
|
||||
#if SAMA_HAL_IS_SECURE
|
||||
mtxConfigPeriphSecurity(MATRIX0, (ID_SDMMC0 + sdmmcp->config->slot_id) , SECURE_PER);
|
||||
#endif /* SAMA_HAL_IS_SECURE */
|
||||
|
||||
sdmmcp->card.EXT = sdmmcp->config->bp;
|
||||
sdmmcp->card.SSR = &sdmmcp->config->bp[EXT_SIZE];
|
||||
sdmmcp->card.SCR = &sdmmcp->config->bp[EXT_SIZE + SSR_SIZE];
|
||||
|
@ -307,37 +308,6 @@ bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool sdmmcMountVolume(SdmmcDriver *sdmmcp, CH_SDMMC_FAT *fs)
|
||||
{
|
||||
FRESULT res;
|
||||
const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
|
||||
|
||||
(void)sdmmcp;
|
||||
memset(fs, 0, sizeof(CH_SDMMC_FAT));
|
||||
res = f_mount(fs, drive_path, 1);
|
||||
if (res != FR_OK) {
|
||||
TRACE_INFO_1("Failed to mount FAT file system, error %d\n\r", res);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp)
|
||||
{
|
||||
const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
|
||||
FRESULT res;
|
||||
bool rc = true;
|
||||
|
||||
res = f_mount(NULL, drive_path, 0);
|
||||
if (res != FR_OK)
|
||||
rc = false;
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
bool CC_WEAK sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)
|
||||
{
|
||||
|
|
|
@ -127,7 +127,7 @@ struct SamaSDMMCDriver
|
|||
|
||||
|
||||
};
|
||||
typedef sSdCard sdmmclib;
|
||||
|
||||
typedef struct SamaSDMMCDriver SdmmcDriver;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -154,8 +154,7 @@ uint8_t sdmmcSendCmd(SdmmcDriver *sdmmcp);
|
|||
bool sdmmcOpenDevice(SdmmcDriver *sdmmcp);
|
||||
bool sdmmcCloseDevice(SdmmcDriver *sdmmcp);
|
||||
bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp);
|
||||
bool sdmmcMountVolume(SdmmcDriver *sdmmcp,CH_SDMMC_FAT *fs);
|
||||
bool sdmmcUnmountVolume(SdmmcDriver *sdmmcp);
|
||||
bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp) ;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -32,7 +32,8 @@
|
|||
</toolChain>
|
||||
</folderInfo>
|
||||
<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>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
|
@ -55,4 +56,10 @@
|
|||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<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>
|
||||
|
|
|
@ -87,5 +87,10 @@
|
|||
<type>2</type>
|
||||
<locationURI>CHIBIOS/os</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>reliance-edge</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-3-PROJECT_LOC%7D/ext/reliance-edge</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
|
|
|
@ -121,15 +121,12 @@ include $(CHIBIOS)/os/hal/osal/rt/osal.mk
|
|||
# RTOS files (optional).
|
||||
include $(CHIBIOS)/os/rt/rt.mk
|
||||
include $(CHIBIOS)/os/common/ports/ARMCAx-TZ/compilers/GCC/mk/port_generic.mk
|
||||
# Other files (optional).
|
||||
#include $(CHIBIOS)/test/lib/test.mk
|
||||
#include $(CHIBIOS)/test/rt/rt_test.mk
|
||||
#include $(CHIBIOS)/test/oslib/oslib_test.mk
|
||||
include $(CHIBIOS)/os/various/reledge_bindings/reledge.mk
|
||||
include $(CHIBIOS)/os/various/fatfs_bindings/fatfs.mk
|
||||
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
|
||||
# Define linker script file here
|
||||
LDSCRIPT= $(STARTUPLD)/SAMA5D2.ld
|
||||
|
||||
#LDSCRIPT= $(STARTUPLD)/SAMA5D2.ld
|
||||
LDSCRIPT= $(STARTUPLD)/SAMA5D2ddr.ld
|
||||
# C sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
CSRC = $(STARTUPSRC) \
|
||||
|
@ -140,7 +137,7 @@ CSRC = $(STARTUPSRC) \
|
|||
$(PLATFORMSRC) \
|
||||
$(BOARDSRC) \
|
||||
$(TESTSRC) $(STREAMSSRC) \
|
||||
main.c
|
||||
main.c fat32test.c reledgetest.c redconf.c $(RELEDGESRC)
|
||||
|
||||
CSRC += $(CHIBIOS)/os/various/syscalls.c
|
||||
CSRC += $(CHIBIOS)/os/various/fatfs_bindings/fatfs_syscall.c
|
||||
|
@ -177,9 +174,8 @@ ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
|
|||
INCDIR = $(CHIBIOS)/os/license \
|
||||
$(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
|
||||
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
|
||||
$(CHIBIOS)/os/various $(STREAMSINC)
|
||||
$(CHIBIOS)/os/various $(STREAMSINC) $(FATFSINC) $(RELEDGEINC)
|
||||
|
||||
INCDIR += $(FATFSINC)
|
||||
#
|
||||
# Project, sources and paths
|
||||
##############################################################################
|
||||
|
@ -228,10 +224,10 @@ CPPWARN = -Wall -Wextra -Wundef
|
|||
#
|
||||
|
||||
# List all user C define here, like -D_DEBUG=1
|
||||
UDEFS = -DCH_CFG_USE_MMU -DPLATFORM_SDMMC_USE_SDMMC1=1
|
||||
UDEFS = -DPLATFORM_SDMMC_USE_SDMMC1=1
|
||||
|
||||
# Define ASM defines here
|
||||
UADEFS = -DCH_CFG_USE_MMU
|
||||
UADEFS =
|
||||
|
||||
# List all user directories here
|
||||
UINCDIR =
|
||||
|
|
|
@ -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 set *0xF8048000 = 0xA5000004 set *0x00A00100 = 0 set *0xF8048044 = 0x00008000 mon cp15 1 0 0 0 = 0x00C50078 set *0xF0014004 = 0x4 set *0xF0014014 = 1<<13 load ./bootstrap.elf mon reg pc = 0x00200000 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="<?xml version="1.0" encoding="UTF-8" standalone="no"?><contentList><content id="mode-_pal_lld_setgroupmode-(format)" val="4"/><content id="null-boardInit-(format)" val="2"/><content id="null-sama_clock_init-(format)" val="4"/><content id="null-_pal_lld_setgroupmode-(format)" val="4"/></contentList>"/>
|
||||
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <globalVariableList/> "/>
|
||||
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList/> "/>
|
||||
<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="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="reserved-for-future-use"/> "/>
|
||||
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
|
||||
</launchConfiguration>
|
|
@ -17,7 +17,7 @@
|
|||
<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="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.symbolsOffset" value=""/>
|
||||
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<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 set *0xF8048000 = 0xA5000004 set *0x00A00100 = 0 set *0xF8048044 = 0x00008000 mon cp15 1 0 0 0 = 0x00C50078 set *0xF0014004 = 0x4 set *0xF0014014 = 1<<13 load ./bootstrap.elf mon reg pc = 0x00200000 continue"/>
|
||||
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="mon reg cpsr = 0xd3 set *0xF8048000 = 0xA5000004 set *0x00A00100 = 0 set *0xF8048044 = 0x00008000 mon cp15 1 0 0 0 = 0x00C50078 set *0xF0014004 = 0x4 set *0xF0014014 = 1<<13 load ./bootstrap.elf mon reg pc = 0x00200000 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"/>
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef FAT32TEST_H_
|
||||
#define FAT32TEST_H_
|
||||
|
||||
|
||||
|
||||
|
||||
extern void fat32test_demo(void);
|
||||
|
||||
|
||||
#endif /* FAT32TEST_H_ */
|
|
@ -1,5 +1,6 @@
|
|||
/* CHIBIOS FIX */
|
||||
#include "ch.h"
|
||||
#include "sama_sdmmc_conf.h"
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
@ -41,7 +42,7 @@
|
|||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
|
||||
#define FF_USE_MKFS 0
|
||||
#define FF_USE_MKFS 1
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
|
@ -58,7 +59,7 @@
|
|||
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
|
||||
#define FF_USE_LABEL 0
|
||||
#define FF_USE_LABEL 1
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
|
@ -163,7 +164,7 @@
|
|||
/ the drive ID strings are: A-Z and 0-9. */
|
||||
|
||||
|
||||
#define FF_MULTI_PARTITION 0
|
||||
#define FF_MULTI_PARTITION 1
|
||||
/* This option switches support of multi-partition on a physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
|
@ -172,8 +173,8 @@
|
|||
/ funciton will be available. */
|
||||
|
||||
|
||||
#define FF_MIN_SS 512
|
||||
#define FF_MAX_SS 512
|
||||
#define FF_MIN_SS SDMMC_BLOCK_SIZE
|
||||
#define FF_MAX_SS SDMMC_BLOCK_SIZE
|
||||
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||
|
@ -221,7 +222,7 @@
|
|||
#define FF_FS_NORTC 1
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2016
|
||||
#define FF_NORTC_YEAR 2018
|
||||
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
|
||||
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
|
|
@ -18,7 +18,15 @@
|
|||
#include "hal.h"
|
||||
#include "sama_sdmmc_lld.h"
|
||||
#include "chprintf.h"
|
||||
#include "fat32test.h"
|
||||
#include "reledgetest.h"
|
||||
|
||||
//----------- DEMO CONFIGURATION ------------------------
|
||||
//0 (SLOT0) or 1 (SLOT1)
|
||||
#define DEMO_SLOT 0
|
||||
//1 for FFLib, 0 for Reliance
|
||||
#define DEMO_FAT 1
|
||||
//----------------------------------------------------------
|
||||
|
||||
#define BLOCK_CNT_MAX 32u
|
||||
#define DMADL_CNT_MAX 64u
|
||||
|
@ -26,16 +34,13 @@
|
|||
|
||||
|
||||
|
||||
const char test_file_path[] = "test.txt";
|
||||
|
||||
CACHE_ALIGNED uint8_t data_buf[BLOCK_CNT_MAX * 512ul];
|
||||
|
||||
CACHE_ALIGNED static uint32_t dma_table[DMADL_CNT_MAX * SDMMC_DMADL_SIZE];
|
||||
|
||||
CACHE_ALIGNED uint8_t sdmmcbuffer[ROUND_UP_MULT(SDMMC_BUFFER_SIZE, L1_CACHE_BYTES)];
|
||||
|
||||
static FATFS fs_header;
|
||||
static FIL f_header;
|
||||
|
||||
|
||||
BaseSequentialStream * ts;
|
||||
|
||||
|
@ -56,9 +61,17 @@ static THD_FUNCTION(Thread1, arg) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const SamaSDMMCConfig sdmmc_slot1_cfg = {
|
||||
#if DEMO_SLOT == 0
|
||||
static const SamaSDMMCConfig sdmmc_cfg = {
|
||||
SDMMC_SLOT0,
|
||||
sdmmcbuffer,
|
||||
data_buf,
|
||||
sizeof(data_buf),
|
||||
dma_table,
|
||||
DMADL_CNT_MAX
|
||||
};
|
||||
#else
|
||||
static const SamaSDMMCConfig sdmmc_cfg = {
|
||||
SDMMC_SLOT1,
|
||||
sdmmcbuffer,
|
||||
data_buf,
|
||||
|
@ -66,10 +79,8 @@ static const SamaSDMMCConfig sdmmc_slot1_cfg = {
|
|||
dma_table,
|
||||
DMADL_CNT_MAX
|
||||
};
|
||||
#endif
|
||||
|
||||
void getdir(SdmmcDriver *sdmmcp);
|
||||
void writefile(SdmmcDriver *sdmmcp);
|
||||
void readfile(SdmmcDriver *sdmmcp);
|
||||
/*
|
||||
* Application entry point.
|
||||
*/
|
||||
|
@ -98,23 +109,26 @@ int main(void) {
|
|||
|
||||
sdmmcInit();
|
||||
|
||||
sdmmcStart(&SDMMCD1, &sdmmc_slot1_cfg);
|
||||
sdmmcStart(&SDMMCD1, &sdmmc_cfg);
|
||||
|
||||
if (SDMMCD1.state != MCID_INIT_ERROR) {
|
||||
|
||||
chprintf(ts,"starting MMC Demo\n\r");
|
||||
chprintf(ts,"starting MMC Demo with slot %d\n\r",SDMMCD1.config->slot_id);
|
||||
|
||||
if (sdmmcOpenDevice(&SDMMCD1)) {
|
||||
|
||||
//sdmmcShowDeviceInfo(&SDMMCD1);
|
||||
if ( sdmmcMountVolume(&SDMMCD1,&fs_header) ) {
|
||||
writefile(&SDMMCD1);
|
||||
chprintf(ts,"reading dir:\n\r");
|
||||
getdir(&SDMMCD1);
|
||||
readfile(&SDMMCD1);
|
||||
#if DEMO_FAT == 1
|
||||
fat32test_demo();
|
||||
#else
|
||||
relianceedge_demo();
|
||||
#endif
|
||||
|
||||
if (SDMMCD1.config->slot_id == SDMMC_SLOT1)
|
||||
{
|
||||
chprintf(ts,"remove card to finish demo\n\r");
|
||||
sdmmcCloseDevice(&SDMMCD1);
|
||||
}
|
||||
sdmmcCloseDevice(&SDMMCD1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,106 +154,13 @@ int main(void) {
|
|||
|
||||
bool sdmmcGetInstance(uint8_t index, SdmmcDriver **sdmmcp)
|
||||
{
|
||||
if (index == SDMMCD1.config->slot_id) {
|
||||
*sdmmcp = &SDMMCD1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
(void)index;
|
||||
|
||||
void writefile(SdmmcDriver *sdmmcp)
|
||||
{
|
||||
const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
|
||||
TCHAR file_path[sizeof(drive_path) + sizeof(test_file_path)];
|
||||
FRESULT res;
|
||||
UINT len;
|
||||
uint8_t buffer[]={ 0x57,0x65,0x6C,0x63,0x6F,
|
||||
0x6D,0x65,0x20,0x74,0x6F,
|
||||
0x20,0x43,0x68,0x69,0x62,
|
||||
0x69,0x4F,0x53,0x21};
|
||||
*sdmmcp = &SDMMCD1;
|
||||
|
||||
|
||||
strcpy(file_path, drive_path);
|
||||
strcat(file_path, test_file_path);
|
||||
|
||||
chprintf(ts,"Creating new file ... ");
|
||||
res = f_open(&f_header, file_path, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
if (res == FR_OK) {
|
||||
chprintf(ts,"OK\r\n");
|
||||
res = f_write(&f_header, buffer, 19, &len);
|
||||
if (res == FR_OK) {
|
||||
chprintf(ts,"written %d bytes\n\r", len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chprintf(ts,"Failed error %d\n\r", res);
|
||||
}
|
||||
f_close(&f_header);
|
||||
|
||||
}
|
||||
|
||||
void readfile(SdmmcDriver *sdmmcp)
|
||||
{
|
||||
const TCHAR drive_path[] = { '0' + sdmmcp->config->slot_id, ':', '\0' };
|
||||
TCHAR file_path[sizeof(drive_path) + sizeof(test_file_path)];
|
||||
FRESULT res;
|
||||
UINT len;
|
||||
uint8_t buffer[19];
|
||||
UINT i;
|
||||
|
||||
strcpy(file_path, drive_path);
|
||||
strcat(file_path, test_file_path);
|
||||
|
||||
chprintf(ts,"Reading back the new file ... ");
|
||||
res = f_open(&f_header, file_path, FA_OPEN_EXISTING | FA_READ);
|
||||
if (res == FR_OK) {
|
||||
chprintf(ts,"OK\r\n");
|
||||
res = f_read(&f_header, buffer, 19, &len);
|
||||
if (res == FR_OK) {
|
||||
chprintf(ts,"read %d bytes\n\r", len);
|
||||
for (i=0;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);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* HAL driver system settings.
|
||||
*/
|
||||
#define SAMA_HAL_IS_SECURE TRUE
|
||||
#define SAMA_NO_INIT FALSE
|
||||
#define SAMA_NO_INIT TRUE
|
||||
#define SAMA_MOSCRC_ENABLED FALSE
|
||||
#define SAMA_MOSCXT_ENABLED TRUE
|
||||
#define SAMA_MOSC_SEL SAMA_MOSC_MOSCXT
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
The demo targets a generic ARM Cortex-A5 device without HAL support.
|
||||
|
||||
** The Demo **
|
||||
Testing FF and Reliance Edge Libraries
|
||||
|
||||
** Build Procedure **
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef RELEDGETEST_H_
|
||||
#define RELEDGETEST_H_
|
||||
|
||||
|
||||
|
||||
extern void relianceedge_demo(void);
|
||||
|
||||
#endif /* RELEDGETEST_H_ */
|
Loading…
Reference in New Issue