Merge pull request #1939 from bthebaudeau/re-mote-sd-fat

Add global SD/MMC and FAT support, with RE-Mote as an example
This commit is contained in:
Antonio Lignan 2016-12-10 18:32:39 +01:00 committed by GitHub
commit bd3f8fa3c5
44 changed files with 39692 additions and 98 deletions

View file

@ -100,6 +100,20 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin);
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK) \ #define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK) \
do { REG((PORT_BASE) + GPIO_DIR) |= (PIN_MASK); } while(0) do { REG((PORT_BASE) + GPIO_DIR) |= (PIN_MASK); } while(0)
/** \brief Return whether pins with PIN_MASK of port with PORT_BASE are set to
* output.
* \param PORT_BASE GPIO Port register offset
* \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80
* \return The direction of the pins specified by PIN_MASK
*
* This macro will \e not return 0 or 1. Instead, it will return the directions
* of the pins specified by PIN_MASK ORed together. Thus, if 0xC3
* (0x80 | 0x40 | 0x02 | 0x01) is passed as the PIN_MASK and pins 7 and 0 are
* set to output, the macro will return 0x81.
*/
#define GPIO_IS_OUTPUT(PORT_BASE, PIN_MASK) \
(REG((PORT_BASE) + GPIO_DIR) & (PIN_MASK))
/** \brief Set pins with PIN_MASK of port with PORT_BASE high. /** \brief Set pins with PIN_MASK of port with PORT_BASE high.
* \param PORT_BASE GPIO Port register offset * \param PORT_BASE GPIO Port register offset
* \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80

View file

@ -40,6 +40,7 @@
#include "contiki.h" #include "contiki.h"
#include "reg.h" #include "reg.h"
#include "spi-arch.h" #include "spi-arch.h"
#include "sys/cc.h"
#include "dev/ioc.h" #include "dev/ioc.h"
#include "dev/sys-ctrl.h" #include "dev/sys-ctrl.h"
#include "dev/spi.h" #include "dev/spi.h"
@ -155,7 +156,12 @@
#if (SPI1_CPRS_CPSDVSR & 1) == 1 || SPI1_CPRS_CPSDVSR < 2 || SPI1_CPRS_CPSDVSR > 254 #if (SPI1_CPRS_CPSDVSR & 1) == 1 || SPI1_CPRS_CPSDVSR < 2 || SPI1_CPRS_CPSDVSR > 254
#error SPI1_CPRS_CPSDVSR must be an even number between 2 and 254 #error SPI1_CPRS_CPSDVSR must be an even number between 2 and 254
#endif #endif
/*---------------------------------------------------------------------------*/
/*
* Clock source from which the baud clock is determined for the SSI, according
* to SSI_CC.CS.
*/
#define SSI_SYS_CLOCK SYS_CTRL_SYS_CLOCK
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
typedef struct { typedef struct {
int8_t port; int8_t port;
@ -314,6 +320,37 @@ spix_set_mode(uint8_t spi,
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
spix_set_clock_freq(uint8_t spi, uint32_t freq)
{
const spi_regs_t *regs;
uint64_t div;
uint32_t scr;
if(spi >= SSI_INSTANCE_COUNT) {
return;
}
regs = &spi_regs[spi];
/* Disable the SSI peripheral to configure it */
REG(regs->base + SSI_CR1) = 0;
/* Configure the SSI serial clock rate */
if(!freq) {
scr = 255;
} else {
div = (uint64_t)regs->ssi_cprs_cpsdvsr * freq;
scr = (SSI_SYS_CLOCK + div - 1) / div;
scr = MIN(MAX(scr, 1), 256) - 1;
}
REG(regs->base + SSI_CR0) = (REG(regs->base + SSI_CR0) & ~SSI_CR0_SCR_M) |
scr << SSI_CR0_SCR_S;
/* Re-enable the SSI */
REG(regs->base + SSI_CR1) |= SSI_CR1_SSE;
}
/*---------------------------------------------------------------------------*/
void
spix_cs_init(uint8_t port, uint8_t pin) spix_cs_init(uint8_t port, uint8_t pin)
{ {
GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port),

View file

@ -57,6 +57,8 @@
*/ */
#define SSI0_BASE 0x40008000 /**< Base address for SSI0 */ #define SSI0_BASE 0x40008000 /**< Base address for SSI0 */
#define SSI1_BASE 0x40009000 /**< Base address for SSI1 */ #define SSI1_BASE 0x40009000 /**< Base address for SSI1 */
/** Base address of the \c dev instance of the SSI */
#define SSI_BASE(dev) (SSI0_BASE + (dev) * (SSI1_BASE - SSI0_BASE))
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name SSI register offsets /** \name SSI register offsets

View file

@ -109,17 +109,17 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* New API macros */ /* New API macros */
#define SPIX_WAITFORTxREADY(spi) do { \ #define SPIX_WAITFORTxREADY(spi) do { \
while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_TNF)) ; \ while(!(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_TNF)) ; \
} while(0) } while(0)
#define SPIX_BUF(spi) REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_DR) #define SPIX_BUF(spi) REG(SSI_BASE(spi) + SSI_DR)
#define SPIX_WAITFOREOTx(spi) do { \ #define SPIX_WAITFOREOTx(spi) do { \
while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_BSY) ; \ while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_BSY) ; \
} while(0) } while(0)
#define SPIX_WAITFOREORx(spi) do { \ #define SPIX_WAITFOREORx(spi) do { \
while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE)) ; \ while(!(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE)) ; \
} while(0) } while(0)
#define SPIX_FLUSH(spi) do { \ #define SPIX_FLUSH(spi) do { \
while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE) { \ while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE) { \
SPIX_BUF(spi); \ SPIX_BUF(spi); \
} \ } \
} while(0) } while(0)
@ -197,6 +197,14 @@ void spix_set_mode(uint8_t spi, uint32_t frame_format,
uint32_t clock_polarity, uint32_t clock_phase, uint32_t clock_polarity, uint32_t clock_phase,
uint32_t data_size); uint32_t data_size);
/**
* \brief Sets the SPI clock frequency of the given SSI instance.
*
* \param spi SSI instance
* \param freq Frequency (Hz)
*/
void spix_set_clock_freq(uint8_t spi, uint32_t freq);
/** /**
* \brief Configure a GPIO to be the chip select pin. * \brief Configure a GPIO to be the chip select pin.
* *

98
dev/disk/disk.h Normal file
View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup dev
* @{
*
* \defgroup disk Disk device drivers
*
* Documentation for all the disk device drivers.
* @{
*
* \file
* Header file defining the disk device driver API.
*/
#ifndef DISK_H_
#define DISK_H_
#include <stdint.h>
/** Disk status flags. */
typedef enum {
DISK_STATUS_INIT = 0x01, /**< Device initialized and ready to work */
DISK_STATUS_DISK = 0x02, /**< Medium present in the drive */
DISK_STATUS_WRITABLE = 0x04 /**< Writable medium */
} disk_status_t;
/** Generic disk I/O control commands. */
typedef enum {
DISK_IOCTL_CTRL_SYNC, /**< Synchronize the cached writes to persistent storage */
DISK_IOCTL_GET_SECTOR_COUNT, /**< Get the sector count through the \c uint32_t pointed to by \c buff */
DISK_IOCTL_GET_SECTOR_SIZE, /**< Get the sector size through the \c uint16_t pointed to by \c buff */
DISK_IOCTL_GET_BLOCK_SIZE, /**< Get the erase block size (in sectors) through the \c uint32_t pointed to by \c buff */
DISK_IOCTL_CTRL_TRIM /**< Trim the sector range within the \c uint32_t boundaries pointed to by \c buff */
} disk_ioctl_t;
/** Disk access result codes. */
typedef enum {
DISK_RESULT_OK, /**< Success */
DISK_RESULT_IO_ERROR, /**< Unrecoverable I/O error */
DISK_RESULT_WR_PROTECTED, /**< Write-protected medium */
DISK_RESULT_NO_INIT, /**< Device not initialized */
DISK_RESULT_INVALID_ARG /**< Invalid argument */
} disk_result_t;
/** Disk driver API structure. */
struct disk_driver {
/** Get device status. */
disk_status_t (*status)(uint8_t dev);
/** Initialize device. */
disk_status_t (*initialize)(uint8_t dev);
/** Read sector(s). */
disk_result_t (*read)(uint8_t dev, void *buff, uint32_t sector,
uint32_t count);
/** Write sector(s). */
disk_result_t (*write)(uint8_t dev, const void *buff, uint32_t sector,
uint32_t count);
/** Control device-specific features. */
disk_result_t (*ioctl)(uint8_t dev, uint8_t cmd, void *buff);
};
#endif /* DISK_H_ */
/**
* @}
* @}
*/

98
dev/disk/mmc/mmc-arch.h Normal file
View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup mmc
* @{
*
* \defgroup mmc-arch SD/MMC architecture-specific definitions
*
* SD/MMC device driver architecture-specific definitions.
* @{
*
* \file
* Header file for the SD/MMC device driver architecture-specific definitions.
*/
#ifndef MMC_ARCH_H_
#define MMC_ARCH_H_
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
/** \brief Callback of the SD/MMC driver to call when the card-detection signal
* changes.
* \param dev Device
* \param cd Whether a card is detected
* \note Using this function is not mandatory. This only allows to detect a card
* replacement between two successive calls to the SD/MMC driver API.
*/
void mmc_arch_cd_changed_callback(uint8_t dev, bool cd);
/** \brief Gets the state of the card-detection signal.
* \param dev Device
* \return Whether a card is detected
*/
bool mmc_arch_get_cd(uint8_t dev);
/** \brief Gets the state of the write-protection signal.
* \param dev Device
* \return Whether the card is write-protected
*/
bool mmc_arch_get_wp(uint8_t dev);
/** \brief Sets the SPI /CS signal as indicated.
* \param dev Device
* \param sel Whether to assert /CS
*/
void mmc_arch_spi_select(uint8_t dev, bool sel);
/** \brief Sets the SPI clock frequency.
* \param dev Device
* \param freq Frequency (Hz)
*/
void mmc_arch_spi_set_clock_freq(uint8_t dev, uint32_t freq);
/** \brief Performs an SPI transfer.
* \param dev Device
* \param tx_buf Pointer to the transmission buffer, or \c NULL
* \param tx_cnt Number of bytes to transmit, or \c 0
* \param rx_buf Pointer to the reception buffer, or \c NULL
* \param rx_cnt Number of bytes to receive, or \c 0
*/
void mmc_arch_spi_xfer(uint8_t dev, const void *tx_buf, size_t tx_cnt,
void *rx_buf, size_t rx_cnt);
#endif /* MMC_ARCH_H_ */
/**
* @}
* @}
*/

608
dev/disk/mmc/mmc.c Normal file
View file

@ -0,0 +1,608 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Based on the FatFs Module STM32 Sample Project,
* Copyright (c) 2014, ChaN
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup mmc
* @{
*
* \file
* Implementation of the SD/MMC device driver.
*/
#include <stddef.h>
#include <stdint.h>
#include "contiki.h"
#include "sys/clock.h"
#include "sys/rtimer.h"
#include "dev/watchdog.h"
#include "mmc-arch.h"
#include "mmc.h"
/* Data read/write block length */
#define BLOCK_LEN 512
/*
* Logical sector size exposed to the disk API, not to be confused with the SDSC
* sector size, which is the size of an erasable sector
*/
#define SECTOR_SIZE BLOCK_LEN
/* Clock frequency in card identification mode: fOD <= 400 kHz */
#define CLOCK_FREQ_CARD_ID_MODE 400000
/*
* Clock frequency in data transfer mode: fPP <= 20 MHz, limited by the
* backward-compatible MMC interface timings
*/
#define CLOCK_FREQ_DATA_XFER_MODE 20000000
/* SPI-mode command list */
#define CMD0 0 /* GO_IDLE_STATE */
#define CMD1 1 /* SEND_OP_COND */
#define CMD8 8 /* SEND_IF_COND */
#define CMD8_VHS_2_7_3_6 0x1
#define CMD8_ARG(vhs, check_pattern) ((vhs) << 8 | (check_pattern))
#define CMD8_ECHO_MASK 0x00000fff
#define CMD9 9 /* SEND_CSD */
#define CMD10 10 /* SEND_CID */
#define CMD12 12 /* STOP_TRANSMISSION */
#define CMD13 13 /* SEND_STATUS */
#define CMD16 16 /* SET_BLOCKLEN */
#define CMD17 17 /* READ_SINGLE_BLOCK */
#define CMD18 18 /* READ_MULTIPLE_BLOCK */
#define CMD23 23 /* SET_BLOCK_COUNT */
#define CMD24 24 /* WRITE_BLOCK */
#define CMD25 25 /* WRITE_MULTIPLE_BLOCK */
#define CMD32 32 /* ERASE_WR_BLK_START */
#define CMD33 33 /* ERASE_WR_BLK_END */
#define CMD38 38 /* ERASE */
#define CMD55 55 /* APP_CMD */
#define CMD58 58 /* READ_OCR */
#define ACMD 0x80 /* Application-specific command */
#define ACMD13 (ACMD | 13) /* SD_STATUS */
#define ACMD23 (ACMD | 23) /* SET_WR_BLK_ERASE_COUNT */
#define ACMD41 (ACMD | 41) /* SD_APP_OP_COND */
#define ACMD41_HCS (1 << 30)
#define CMD_TX 0x40 /* Command transmission bit */
#define R1_MSB 0x00
#define R1_SUCCESS 0x00
#define R1_IDLE_STATE (1 << 0)
#define R1_ERASE_RESET (1 << 1)
#define R1_ILLEGAL_COMMAND (1 << 2)
#define R1_COM_CRC_ERROR (1 << 3)
#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
#define R1_ADDRESS_ERROR (1 << 5)
#define R1_PARAMETER_ERROR (1 << 6)
#define TOK_DATA_RESP_MASK 0x1f
#define TOK_DATA_RESP_ACCEPTED 0x05
#define TOK_DATA_RESP_CRC_ERROR 0x0b
#define TOK_DATA_RESP_WR_ERROR 0x0d
#define TOK_RD_SINGLE_WR_START_BLOCK 0xfe
#define TOK_MULTI_WR_START_BLOCK 0xfc
#define TOK_MULTI_WR_STOP_TRAN 0xfd
/* The SD Status is one data block of 512 bits. */
#define SD_STATUS_SIZE (512 / 8)
#define SD_STATUS_AU_SIZE(sd_status) ((sd_status)[10] >> 4)
#define OCR_CCS (1 << 30)
#define CSD_SIZE 16
#define CSD_STRUCTURE(csd) ((csd)[0] >> 6)
#define CSD_STRUCTURE_SD_V1_0 0
#define CSD_STRUCTURE_SD_V2_0 1
#define CSD_SD_V1_0_READ_BL_LEN(csd) ((csd)[5] & 0x0f)
#define CSD_SD_V1_0_BLOCK_LEN(csd) (1ull << CSD_SD_V1_0_READ_BL_LEN(csd))
#define CSD_SD_V1_0_C_SIZE(csd) \
(((csd)[6] & 0x03) << 10 | (csd)[7] << 2 | (csd)[8] >> 6)
#define CSD_SD_V1_0_C_SIZE_MULT(csd) \
(((csd)[9] & 0x03) << 1 | (csd)[10] >> 7)
#define CSD_SD_V1_0_MULT(csd) \
(1 << (CSD_SD_V1_0_C_SIZE_MULT(csd) + 2))
#define CSD_SD_V1_0_BLOCKNR(csd) \
(((uint32_t)CSD_SD_V1_0_C_SIZE(csd) + 1) * CSD_SD_V1_0_MULT(csd))
#define CSD_SD_V1_0_CAPACITY(csd) \
(CSD_SD_V1_0_BLOCKNR(csd) * CSD_SD_V1_0_BLOCK_LEN(csd))
#define CSD_SD_V1_0_SECTOR_SIZE(csd) \
(((csd)[10] & 0x3f) << 1 | (csd)[11] >> 7)
#define CSD_SD_V1_0_WRITE_BL_LEN(csd) \
(((csd)[12] & 0x03) << 2 | (csd)[13] >> 6)
#define CSD_SD_V2_0_C_SIZE(csd) \
(((csd)[7] & 0x3f) << 16 | (csd)[8] << 8 | (csd)[9])
#define CSD_SD_V2_0_CAPACITY(csd) \
(((uint64_t)CSD_SD_V2_0_C_SIZE(csd) + 1) << 19)
#define CSD_MMC_ERASE_GRP_SIZE(csd) (((csd)[10] & 0x7c) >> 2)
#define CSD_MMC_ERASE_GRP_MULT(csd) \
(((csd)[10] & 0x03) << 3 | (csd)[11] >> 5)
#define CSD_MMC_WRITE_BL_LEN(csd) \
(((csd)[12] & 0x03) << 2 | (csd)[13] >> 6)
typedef enum {
CARD_TYPE_MMC = 0x01, /* MMC v3 */
CARD_TYPE_SD1 = 0x02, /* SD v1 */
CARD_TYPE_SD2 = 0x04, /* SD v2 */
CARD_TYPE_SD = CARD_TYPE_SD1 | CARD_TYPE_SD2, /* SD */
CARD_TYPE_BLOCK = 0x08 /* Block addressing */
} card_type_t;
static struct mmc_priv {
uint8_t status;
uint8_t card_type;
} mmc_priv[MMC_CONF_DEV_COUNT];
/*----------------------------------------------------------------------------*/
static uint8_t
mmc_spi_xchg(uint8_t dev, uint8_t tx_byte)
{
uint8_t rx_byte;
mmc_arch_spi_xfer(dev, &tx_byte, 1, &rx_byte, 1);
return rx_byte;
}
/*----------------------------------------------------------------------------*/
static void
mmc_spi_tx(uint8_t dev, const void *buf, size_t cnt)
{
mmc_arch_spi_xfer(dev, buf, cnt, NULL, 0);
}
/*----------------------------------------------------------------------------*/
static void
mmc_spi_rx(uint8_t dev, void *buf, size_t cnt)
{
mmc_arch_spi_xfer(dev, NULL, 0, buf, cnt);
}
/*----------------------------------------------------------------------------*/
static bool
mmc_wait_ready(uint8_t dev, uint16_t timeout_ms)
{
rtimer_clock_t timeout_end =
RTIMER_NOW() + ((uint32_t)timeout_ms * RTIMER_SECOND + 999) / 1000;
uint8_t rx_byte;
do {
rx_byte = mmc_spi_xchg(dev, 0xff);
watchdog_periodic();
} while(rx_byte != 0xff && RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end));
return rx_byte == 0xff;
}
/*----------------------------------------------------------------------------*/
static bool
mmc_select(uint8_t dev, bool sel)
{
mmc_arch_spi_select(dev, sel);
mmc_spi_xchg(dev, 0xff); /* Dummy clock (force D0) */
if(sel && !mmc_wait_ready(dev, 500)) {
mmc_select(dev, false);
return false;
}
return true;
}
/*----------------------------------------------------------------------------*/
static uint8_t
mmc_send_cmd(uint8_t dev, uint8_t cmd, uint32_t arg)
{
uint8_t resp, n;
/* Send a CMD55 prior to a ACMD<n>. */
if(cmd & ACMD) {
cmd &= ~ACMD;
resp = mmc_send_cmd(dev, CMD55, 0);
if(resp != R1_SUCCESS && resp != R1_IDLE_STATE) {
return resp;
}
}
/*
* Select the card and wait for ready, except to stop a multiple-block read.
*/
if(cmd != CMD12) {
mmc_select(dev, false);
if(!mmc_select(dev, true)) {
return 0xff;
}
}
/* Send the command packet. */
mmc_spi_xchg(dev, CMD_TX | cmd); /* Start & tx bits, cmd index */
mmc_spi_xchg(dev, arg >> 24); /* Argument[31..24] */
mmc_spi_xchg(dev, arg >> 16); /* Argument[23..16] */
mmc_spi_xchg(dev, arg >> 8); /* Argument[15..8] */
mmc_spi_xchg(dev, arg); /* Argument[7..0] */
switch(cmd) {
case CMD0:
n = 0x95; /* CMD0(0) CRC7, end bit */
break;
case CMD8:
n = 0x87; /* CMD8(0x1aa) CRC7, end bit */
break;
default:
n = 0x01; /* Dummy CRC7, end bit */
break;
}
mmc_spi_xchg(dev, n);
/* Receive the command response. */
if(cmd == CMD12) {
mmc_spi_xchg(dev, 0xff); /* Discard following byte if CMD12. */
}
/* Wait for the response (max. 10 bytes). */
n = 10;
do {
resp = mmc_spi_xchg(dev, 0xff);
} while((resp & 0x80) != R1_MSB && --n);
return resp;
}
/*----------------------------------------------------------------------------*/
static bool
mmc_tx_block(uint8_t dev, const void *buf, uint8_t token)
{
uint8_t resp;
if(!mmc_wait_ready(dev, 500)) {
return false;
}
mmc_spi_xchg(dev, token);
if(token != TOK_MULTI_WR_STOP_TRAN) {
mmc_spi_tx(dev, buf, BLOCK_LEN);
mmc_spi_xchg(dev, 0xff); /* Dummy CRC */
mmc_spi_xchg(dev, 0xff);
resp = mmc_spi_xchg(dev, 0xff);
if((resp & TOK_DATA_RESP_MASK) != TOK_DATA_RESP_ACCEPTED) {
return false;
}
}
return true;
}
/*----------------------------------------------------------------------------*/
static bool
mmc_rx(uint8_t dev, void *buf, size_t cnt)
{
rtimer_clock_t timeout_end =
RTIMER_NOW() + (200ul * RTIMER_SECOND + 999) / 1000;
uint8_t token;
do {
token = mmc_spi_xchg(dev, 0xff);
watchdog_periodic();
} while(token == 0xff && RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end));
if(token != TOK_RD_SINGLE_WR_START_BLOCK) {
return false;
}
mmc_spi_rx(dev, buf, cnt);
mmc_spi_xchg(dev, 0xff); /* Discard CRC. */
mmc_spi_xchg(dev, 0xff);
return true;
}
/*----------------------------------------------------------------------------*/
void
mmc_arch_cd_changed_callback(uint8_t dev, bool cd)
{
uint8_t status;
if(dev >= MMC_CONF_DEV_COUNT) {
return;
}
if(cd) {
status = DISK_STATUS_DISK;
if(!mmc_arch_get_wp(dev)) {
status |= DISK_STATUS_WRITABLE;
}
} else {
status = 0;
}
mmc_priv[dev].status = status;
}
/*----------------------------------------------------------------------------*/
static disk_status_t
mmc_status(uint8_t dev)
{
bool cd;
struct mmc_priv *priv;
if(dev >= MMC_CONF_DEV_COUNT) {
return DISK_RESULT_INVALID_ARG;
}
cd = mmc_arch_get_cd(dev);
priv = &mmc_priv[dev];
if(cd == !(priv->status & DISK_STATUS_DISK)) {
mmc_arch_cd_changed_callback(dev, cd);
}
return priv->status;
}
/*----------------------------------------------------------------------------*/
static disk_status_t
mmc_initialize(uint8_t dev)
{
disk_status_t status;
uint8_t n, cmd;
card_type_t card_type;
rtimer_clock_t timeout_end;
uint32_t arg, resp, ocr;
struct mmc_priv *priv;
if(dev >= MMC_CONF_DEV_COUNT) {
return DISK_RESULT_INVALID_ARG;
}
status = mmc_status(dev);
if(!(status & DISK_STATUS_DISK)) {
return status;
}
mmc_arch_spi_select(dev, false);
clock_delay_usec(10000);
mmc_arch_spi_set_clock_freq(dev, CLOCK_FREQ_CARD_ID_MODE);
for(n = 10; n; n--) {
mmc_spi_xchg(dev, 0xff); /* Generate 80 dummy clock cycles. */
}
card_type = 0;
if(mmc_send_cmd(dev, CMD0, 0) == R1_IDLE_STATE) {
timeout_end = RTIMER_NOW() + RTIMER_SECOND;
arg = CMD8_ARG(CMD8_VHS_2_7_3_6, 0xaa); /* Arbitrary check pattern */
if(mmc_send_cmd(dev, CMD8, arg) == R1_IDLE_STATE) { /* SD v2? */
resp = 0;
for(n = 4; n; n--) {
resp = resp << 8 | mmc_spi_xchg(dev, 0xff);
}
/* Does the card support 2.7 V - 3.6 V? */
if((arg & CMD8_ECHO_MASK) == (resp & CMD8_ECHO_MASK)) {
/* Wait for end of initialization. */
while(RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) &&
mmc_send_cmd(dev, ACMD41, ACMD41_HCS) != R1_SUCCESS) {
watchdog_periodic();
}
if(RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) &&
mmc_send_cmd(dev, CMD58, 0) == R1_SUCCESS) { /* Read OCR. */
ocr = 0;
for(n = 4; n; n--) {
ocr = ocr << 8 | mmc_spi_xchg(dev, 0xff);
}
card_type = CARD_TYPE_SD2;
if(ocr & OCR_CCS) {
card_type |= CARD_TYPE_BLOCK;
}
}
}
} else { /* Not SD v2 */
resp = mmc_send_cmd(dev, ACMD41, 0);
if(resp == R1_SUCCESS || resp == R1_IDLE_STATE) { /* SD v1 or MMC? */
card_type = CARD_TYPE_SD1;
cmd = ACMD41;
} else {
card_type = CARD_TYPE_MMC;
cmd = CMD1;
}
/* Wait for end of initialization. */
while(RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) &&
mmc_send_cmd(dev, cmd, 0) != R1_SUCCESS) {
watchdog_periodic();
}
/* Set block length. */
if(!RTIMER_CLOCK_LT(RTIMER_NOW(), timeout_end) ||
mmc_send_cmd(dev, CMD16, BLOCK_LEN) != R1_SUCCESS) {
card_type = 0;
}
}
}
priv = &mmc_priv[dev];
priv->card_type = card_type;
mmc_select(dev, false);
status = priv->status;
if(status & DISK_STATUS_DISK && card_type) { /* OK */
mmc_arch_spi_set_clock_freq(dev, CLOCK_FREQ_DATA_XFER_MODE);
status |= DISK_STATUS_INIT;
} else { /* Failed */
status &= ~DISK_STATUS_INIT;
}
priv->status = status;
return status;
}
/*----------------------------------------------------------------------------*/
static disk_result_t
mmc_read(uint8_t dev, void *buff, uint32_t sector, uint32_t count)
{
if(dev >= MMC_CONF_DEV_COUNT || !count) {
return DISK_RESULT_INVALID_ARG;
}
if(!(mmc_status(dev) & DISK_STATUS_INIT)) {
return DISK_RESULT_NO_INIT;
}
if(!(mmc_priv[dev].card_type & CARD_TYPE_BLOCK)) {
sector *= SECTOR_SIZE;
}
if(count == 1) {
if(mmc_send_cmd(dev, CMD17, sector) == R1_SUCCESS &&
mmc_rx(dev, buff, SECTOR_SIZE)) {
count = 0;
}
} else if(mmc_send_cmd(dev, CMD18, sector) == R1_SUCCESS) {
do {
if(!mmc_rx(dev, buff, SECTOR_SIZE)) {
break;
}
buff = (uint8_t *)buff + SECTOR_SIZE;
watchdog_periodic();
} while(--count);
mmc_send_cmd(dev, CMD12, 0); /* Stop transmission. */
}
mmc_select(dev, false);
return count ? DISK_RESULT_IO_ERROR : DISK_RESULT_OK;
}
/*----------------------------------------------------------------------------*/
static disk_result_t
mmc_write(uint8_t dev, const void *buff, uint32_t sector, uint32_t count)
{
disk_status_t status;
card_type_t card_type;
if(dev >= MMC_CONF_DEV_COUNT || !count) {
return DISK_RESULT_INVALID_ARG;
}
status = mmc_status(dev);
if(!(status & DISK_STATUS_INIT)) {
return DISK_RESULT_NO_INIT;
}
if(!(status & DISK_STATUS_WRITABLE)) {
return DISK_RESULT_WR_PROTECTED;
}
card_type = mmc_priv[dev].card_type;
if(!(card_type & CARD_TYPE_BLOCK)) {
sector *= SECTOR_SIZE;
}
if(count == 1) {
if(mmc_send_cmd(dev, CMD24, sector) == R1_SUCCESS &&
mmc_tx_block(dev, buff, TOK_RD_SINGLE_WR_START_BLOCK)) {
count = 0;
}
} else {
if(card_type & CARD_TYPE_SD) {
mmc_send_cmd(dev, ACMD23, count);
}
if(mmc_send_cmd(dev, CMD25, sector) == R1_SUCCESS) {
do {
if(!mmc_tx_block(dev, buff, TOK_MULTI_WR_START_BLOCK)) {
break;
}
buff = (uint8_t *)buff + BLOCK_LEN;
watchdog_periodic();
} while(--count);
if(!mmc_tx_block(dev, NULL, TOK_MULTI_WR_STOP_TRAN)) {
count = 1;
}
}
}
mmc_select(dev, false);
return count ? DISK_RESULT_IO_ERROR : DISK_RESULT_OK;
}
/*----------------------------------------------------------------------------*/
static disk_result_t
mmc_ioctl(uint8_t dev, uint8_t cmd, void *buff)
{
card_type_t card_type;
disk_result_t res;
uint8_t csd[CSD_SIZE], sd_status[SD_STATUS_SIZE], au_size;
uint64_t capacity;
uint32_t block_size;
static const uint8_t AU_TO_BLOCK_SIZE[] = {12, 16, 24, 32, 64};
if(dev >= MMC_CONF_DEV_COUNT) {
return DISK_RESULT_INVALID_ARG;
}
if(!(mmc_status(dev) & DISK_STATUS_INIT)) {
return DISK_RESULT_NO_INIT;
}
card_type = mmc_priv[dev].card_type;
res = DISK_RESULT_IO_ERROR;
switch(cmd) {
case DISK_IOCTL_CTRL_SYNC:
if(mmc_select(dev, true)) {
res = DISK_RESULT_OK;
}
break;
case DISK_IOCTL_GET_SECTOR_COUNT:
if(mmc_send_cmd(dev, CMD9, 0) == R1_SUCCESS && mmc_rx(dev, csd, CSD_SIZE)) {
capacity = CSD_STRUCTURE(csd) == CSD_STRUCTURE_SD_V2_0 ?
CSD_SD_V2_0_CAPACITY(csd) : CSD_SD_V1_0_CAPACITY(csd);
*(uint32_t *)buff = capacity / SECTOR_SIZE;
res = DISK_RESULT_OK;
}
break;
case DISK_IOCTL_GET_SECTOR_SIZE:
*(uint16_t *)buff = SECTOR_SIZE;
res = DISK_RESULT_OK;
break;
case DISK_IOCTL_GET_BLOCK_SIZE:
if(card_type & CARD_TYPE_SD2) {
if(mmc_send_cmd(dev, ACMD13, 0) == R1_SUCCESS) { /* Read SD status. */
mmc_spi_xchg(dev, 0xff);
if(mmc_rx(dev, sd_status, SD_STATUS_SIZE)) {
au_size = SD_STATUS_AU_SIZE(sd_status);
if(au_size) {
block_size = au_size <= 0xa ? 8192ull << au_size :
(uint32_t)AU_TO_BLOCK_SIZE[au_size - 0xb] << 20;
*(uint32_t *)buff = block_size / SECTOR_SIZE;
res = DISK_RESULT_OK;
}
}
}
} else if(mmc_send_cmd(dev, CMD9, 0) == R1_SUCCESS &&
mmc_rx(dev, csd, CSD_SIZE)) {
if(card_type & CARD_TYPE_SD1) {
block_size = (uint32_t)(CSD_SD_V1_0_SECTOR_SIZE(csd) + 1) <<
CSD_SD_V1_0_WRITE_BL_LEN(csd);
} else { /* MMC */
block_size = (uint32_t)(CSD_MMC_ERASE_GRP_SIZE(csd) + 1) *
(CSD_MMC_ERASE_GRP_MULT(csd) + 1) <<
CSD_MMC_WRITE_BL_LEN(csd);
}
*(uint32_t *)buff = block_size / SECTOR_SIZE;
res = DISK_RESULT_OK;
}
break;
default:
res = DISK_RESULT_INVALID_ARG;
break;
}
mmc_select(dev, false);
return res;
}
/*----------------------------------------------------------------------------*/
const struct disk_driver mmc_driver = {
.status = mmc_status,
.initialize = mmc_initialize,
.read = mmc_read,
.write = mmc_write,
.ioctl = mmc_ioctl
};
/*----------------------------------------------------------------------------*/
/** @} */

61
dev/disk/mmc/mmc.h Normal file
View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup disk
* @{
*
* \defgroup mmc SD/MMC
*
* SD/MMC device driver.
* @{
*
* \file
* Header file for the SD/MMC device driver.
*/
#ifndef MMC_H_
#define MMC_H_
#include "contiki-conf.h"
#include "../disk.h"
#ifndef MMC_CONF_DEV_COUNT
/** Number of SD/MMC devices. */
#define MMC_CONF_DEV_COUNT 1
#endif
extern const struct disk_driver mmc_driver;
#endif /* MMC_H_ */
/**
* @}
* @}
*/

12
examples/fat/Makefile Normal file
View file

@ -0,0 +1,12 @@
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
CONTIKI = ../..
all: example-fat
CONTIKI_WITH_RIME = 1
ifeq ($(TARGET), zoul)
BOARD ?= remote-revb
endif
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1,2 @@
TARGET = zoul
BOARD ?= remote-revb

6
examples/fat/README.md Normal file
View file

@ -0,0 +1,6 @@
FAT File System Example
=======================
Supported Hardware (tested or known to work)
--------------------------------------------
* Zoul: RE-Mote revision B

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
/**
* \file
* Example demonstrating how to use the FAT file system.
*/
/*---------------------------------------------------------------------------*/
#include <stdio.h>
#include "contiki.h"
#include "ff.h"
/*---------------------------------------------------------------------------*/
PROCESS(example_fat_process, "FAT example");
AUTOSTART_PROCESSES(&example_fat_process);
/*---------------------------------------------------------------------------*/
#define TEST_FILENAME "test.txt"
#define TEST_LINE "Hello world!"
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_fat_process, ev, data)
{
static FATFS FatFs; /* Work area (file system object) for logical drive */
FIL fil; /* File object */
char line[82]; /* Line buffer */
FRESULT fr; /* FatFs return code */
PROCESS_BEGIN();
printf("FAT example\n");
/* Register work area to the default drive */
f_mount(&FatFs, "", 0);
printf("Writing \"%s\" to \"%s\"\n", TEST_LINE, TEST_FILENAME);
/* Create the test file */
fr = f_open(&fil, TEST_FILENAME, FA_WRITE | FA_CREATE_ALWAYS);
if(fr) {
printf("f_open() error: %d\n", fr);
PROCESS_EXIT();
}
/* Write the test line */
f_printf(&fil, "%s\n", TEST_LINE);
/* Close the file */
f_close(&fil);
printf("Reading back \"%s\":\n\n", TEST_FILENAME);
/* Open the test file */
fr = f_open(&fil, TEST_FILENAME, FA_READ);
if(fr) {
printf("f_open() error: %d\n", fr);
PROCESS_EXIT();
}
/* Read all the lines and display them */
while(f_gets(line, sizeof(line), &fil)) {
printf(line);
}
/* Close the file */
f_close(&fil);
printf("\nDone\n");
PROCESS_END();
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/*---------------------------------------------------------------------------*/
#if CONTIKI_TARGET_ZOUL
#define RTC_CONF_INIT 1
#define RTC_CONF_SET_FROM_SYS 1
#endif
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View file

@ -4,9 +4,6 @@ CONTIKI_PROJECT = test-power-mgmt
BOARD ?= remote-revb BOARD ?= remote-revb
# Works in Linux and probably on OSX too (RTCC example)
CFLAGS = -DDATE="\"`date +"%02u %02d %02m %02y %02H %02M %02S"`\""
all: $(CONTIKI_PROJECT) all: $(CONTIKI_PROJECT)
CONTIKI = ../../../.. CONTIKI = ../../../..

View file

@ -46,6 +46,9 @@
#define BROADCAST_CHANNEL 129 #define BROADCAST_CHANNEL 129
#define NETSTACK_CONF_RDC nullrdc_driver #define NETSTACK_CONF_RDC nullrdc_driver
#define RTC_CONF_INIT 1
#define RTC_CONF_SET_FROM_SYS 1
#endif /* PROJECT_CONF_H_ */ #endif /* PROJECT_CONF_H_ */
/** /**

View file

@ -59,10 +59,6 @@ static struct etimer et;
/* RE-Mote revision B, low-power PIC version */ /* RE-Mote revision B, low-power PIC version */
#define PM_EXPECTED_VERSION 0x20 #define PM_EXPECTED_VERSION 0x20
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#ifndef DATE
#define DATE "Unknown"
#endif
/*---------------------------------------------------------------------------*/
#define TEST_LEDS_FAIL leds_off(LEDS_ALL); \ #define TEST_LEDS_FAIL leds_off(LEDS_ALL); \
leds_on(LEDS_RED); \ leds_on(LEDS_RED); \
PROCESS_EXIT(); PROCESS_EXIT();
@ -80,7 +76,6 @@ PROCESS_THREAD(test_remote_pm, ev, data)
static uint8_t aux; static uint8_t aux;
static uint16_t voltage; static uint16_t voltage;
static uint32_t cycles; static uint32_t cycles;
static char *next;
PROCESS_BEGIN(); PROCESS_BEGIN();
@ -162,37 +157,12 @@ PROCESS_THREAD(test_remote_pm, ev, data)
/* Configure the RTCC to schedule a "hard" restart of the shutdown mode, /* Configure the RTCC to schedule a "hard" restart of the shutdown mode,
* waking up from a RTCC interrupt to the low-power PIC * waking up from a RTCC interrupt to the low-power PIC
*/ */
printf("PM: System date: %s\n", DATE); printf("PM\n");
if(strcmp("Unknown", DATE) == 0) {
printf("PM: could not retrieve date from system\n");
TEST_LEDS_FAIL;
}
/* Configure RTC and return structure with all parameters */
rtcc_init();
/* Configure the RTC with the current values */
simple_td->weekdays = (uint8_t)strtol(DATE, &next, 10);
simple_td->day = (uint8_t)strtol(next, &next, 10);
simple_td->months = (uint8_t)strtol(next, &next, 10);
simple_td->years = (uint8_t)strtol(next, &next, 10);
simple_td->hours = (uint8_t)strtol(next, &next, 10);
simple_td->minutes = (uint8_t)strtol(next, &next, 10);
simple_td->seconds = (uint8_t)strtol(next, NULL, 10);
simple_td->miliseconds = 0;
simple_td->mode = RTCC_24H_MODE;
simple_td->century = RTCC_CENTURY_20XX;
if(rtcc_set_time_date(simple_td) == AB08_ERROR) {
printf("PM: Time and date configuration failed\n");
TEST_LEDS_FAIL;
} else {
if(rtcc_get_time_date(simple_td) == AB08_ERROR) { if(rtcc_get_time_date(simple_td) == AB08_ERROR) {
printf("PM: Couldn't read time and date\n"); printf("PM: Couldn't read time and date\n");
TEST_LEDS_FAIL; TEST_LEDS_FAIL;
} }
}
printf("PM: Configured time: "); printf("PM: Configured time: ");
rtcc_print(RTCC_PRINT_DATE_DEC); rtcc_print(RTCC_PRINT_DATE_DEC);

View file

@ -3,9 +3,6 @@ CONTIKI_PROJECT = test-rtcc
TARGET = zoul TARGET = zoul
# Works in Linux and probably on OSX too (RTCC example)
CFLAGS = -DDATE="\"`date +"%02u %02d %02m %02y %02H %02M %02S"`\""
all: $(CONTIKI_PROJECT) all: $(CONTIKI_PROJECT)
CONTIKI = ../../../.. CONTIKI = ../../../..

View file

@ -47,6 +47,9 @@
#define NETSTACK_CONF_RDC nullrdc_driver #define NETSTACK_CONF_RDC nullrdc_driver
#define RTC_CONF_INIT 1
#define RTC_CONF_SET_FROM_SYS 1
#endif /* PROJECT_CONF_H_ */ #endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**

View file

@ -55,10 +55,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#ifndef DATE
#define DATE "Unknown"
#endif
/*---------------------------------------------------------------------------*/
#define LOOP_PERIOD 60L #define LOOP_PERIOD 60L
#define LOOP_INTERVAL (CLOCK_SECOND * LOOP_PERIOD) #define LOOP_INTERVAL (CLOCK_SECOND * LOOP_PERIOD)
#define TEST_ALARM_SECOND 15 #define TEST_ALARM_SECOND 15
@ -109,58 +105,13 @@ rtcc_interrupt_callback(uint8_t value)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
PROCESS_THREAD(test_remote_rtcc_process, ev, data) PROCESS_THREAD(test_remote_rtcc_process, ev, data)
{ {
static char *next;
PROCESS_BEGIN(); PROCESS_BEGIN();
/* Alternatively for test only, undefine DATE and define on your own as printf("RE-Mote RTC test\n");
* #define DATE "07 06 12 15 16 00 00"
* Also note that if you restart the node at a given time, it will use the
* already defined DATE, so if you want to update the device date/time you
* need to reflash the node
*/
/* Get the system date in the following format: wd dd mm yy hh mm ss */
printf("RE-Mote RTC test, system date: %s\n", DATE);
/* Sanity check */
if(strcmp("Unknown", DATE) == 0) {
printf("Fail: could not retrieve date from system\n");
PROCESS_EXIT();
}
/* Configure RTC and return structure with all parameters */
rtcc_init();
/* Map interrupt callback handler */ /* Map interrupt callback handler */
RTCC_REGISTER_INT1(rtcc_interrupt_callback); RTCC_REGISTER_INT1(rtcc_interrupt_callback);
/* Configure the RTC with the current values */
simple_td->weekdays = (uint8_t)strtol(DATE, &next, 10);
simple_td->day = (uint8_t)strtol(next, &next, 10);
simple_td->months = (uint8_t)strtol(next, &next, 10);
simple_td->years = (uint8_t)strtol(next, &next, 10);
simple_td->hours = (uint8_t)strtol(next, &next, 10);
simple_td->minutes = (uint8_t)strtol(next, &next, 10);
simple_td->seconds = (uint8_t)strtol(next, NULL, 10);
/* Don't care about the milliseconds... */
simple_td->miliseconds = 0;
/* This example relies on 24h mode */
simple_td->mode = RTCC_24H_MODE;
/* And to simplify the configuration, it relies it will be executed in the
* present century
*/
simple_td->century = RTCC_CENTURY_20XX;
/* Set the time and date */
if(rtcc_set_time_date(simple_td) == AB08_ERROR) {
printf("Fail: Time and date not configured\n");
PROCESS_EXIT();
}
/* Wait a bit */ /* Wait a bit */
etimer_set(&et, (CLOCK_SECOND * 2)); etimer_set(&et, (CLOCK_SECOND * 2));
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));

279
lib/fs/fat/00history.txt Normal file
View file

@ -0,0 +1,279 @@
----------------------------------------------------------------------------
Revision history of FatFs module
----------------------------------------------------------------------------
R0.00 (February 26, 2006)
Prototype.
R0.01 (April 29, 2006)
The first release.
R0.02 (June 01, 2006)
Added FAT12 support.
Removed unbuffered mode.
Fixed a problem on small (<32M) partition.
R0.02a (June 10, 2006)
Added a configuration option (_FS_MINIMUM).
R0.03 (September 22, 2006)
Added f_rename().
Changed option _FS_MINIMUM to _FS_MINIMIZE.
R0.03a (December 11, 2006)
Improved cluster scan algorithm to write files fast.
Fixed f_mkdir() creates incorrect directory on FAT32.
R0.04 (February 04, 2007)
Added f_mkfs().
Supported multiple drive system.
Changed some interfaces for multiple drive system.
Changed f_mountdrv() to f_mount().
R0.04a (April 01, 2007)
Supported multiple partitions on a physical drive.
Added a capability of extending file size to f_lseek().
Added minimization level 3.
Fixed an endian sensitive code in f_mkfs().
R0.04b (May 05, 2007)
Added a configuration option _USE_NTFLAG.
Added FSINFO support.
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (<= csize) collapses the file object.
R0.05 (August 25, 2007)
Changed arguments of f_read(), f_write() and f_mkfs().
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
Fixed f_mkdir() on FAT32 creates incorrect directory.
R0.05a (February 03, 2008)
Added f_truncate() and f_utime().
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read() can be mistruncated.
Fixed cached sector is not flushed when create and close without write.
R0.06 (April 01, 2008)
Added fputc(), fputs(), fprintf() and fgets().
Improved performance of f_lseek() on moving to the same or following cluster.
R0.07 (April 01, 2009)
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
Added long file name feature. (_USE_LFN)
Added multiple code page feature. (_CODE_PAGE)
Added re-entrancy for multitask operation. (_FS_REENTRANT)
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
R0.07a (April 14, 2009)
Septemberarated out OS dependent code on reentrant cfg.
Added multiple sector size feature.
R0.07c (June 21, 2009)
Fixed f_unlink() can return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added relative path feature.
Added f_chdir() and f_chdrive().
Added proper case conversion to extended character.
R0.07e (November 03, 2009)
Septemberarated out configuration options from ff.h to ffconf.h.
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
Fixed name matching error on the 13 character boundary.
Added a configuration option, _LFN_UNICODE.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
R0.08 (May 15, 2010)
Added a memory configuration option. (_USE_LFN = 3)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed .fname in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
R0.08a (August 16, 2010)
Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed f_mkfs() creates wrong FAT32 volume.
R0.08b (January 15, 2011)
Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path name.
R0.09 (September 06, 2011)
f_mkfs() supports multiple partition to complete the multiple partition feature.
Added f_fdisk().
R0.09a (August 27, 2012)
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
R0.09b (January 24, 2013)
Added f_setlabel() and f_getlabel().
R0.10 (October 02, 2013)
Added selection of character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
Added forced mount feature with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
R0.10a (January 15, 2014)
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added a configuration option of minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
Fixed f_close() invalidates the file object without volume lock.
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
R0.10b (May 19, 2014)
Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
R0.10c (November 09, 2014)
Added a configuration option for the platforms without RTC. (_FS_NORTC)
Changed option name _USE_ERASE to _USE_TRIM.
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
R0.11 (February 09, 2015)
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
R0.11a (September 05, 2015)
Fixed wrong media change can lead a deadlock at thread-safe configuration.
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
Fixed errors in the case conversion teble of Unicode (cc*.c).
R0.12 (April 12, 2016)
Added support for exFAT file system. (_FS_EXFAT)
Added f_expand(). (_USE_EXPAND)
Changed some members in FINFO structure and behavior of f_readdir().
Added an option _USE_CHMOD.
Removed an option _WORD_ACCESS.
Fixed errors in the case conversion table of Unicode (cc*.c).
R0.12a (July 10, 2016)
Added support for creating exFAT volume with some changes of f_mkfs().
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
f_forward() is available regardless of _FS_TINY.
Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
Fixed wrong memory read in create_name(). (appeared at R0.12)
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
R0.12b (September 04, 2016)
Improved f_rename() to be able to rename objects with the same name but case.
Fixed an error in the case conversion teble of code page 866. (ff.c)
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)

4
lib/fs/fat/README.md Normal file
View file

@ -0,0 +1,4 @@
FatFs - Generic FAT File System Module
======================================
See the documentation on the [official FatFs Module website](http://elm-chan.org/fsw/ff/00index_e.html).

80
lib/fs/fat/diskio.h Normal file
View file

@ -0,0 +1,80 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

6042
lib/fs/fat/ff.c Normal file

File diff suppressed because it is too large Load diff

366
lib/fs/fat/ff.h Normal file
View file

@ -0,0 +1,366 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12b /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2016, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 68020 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode (UTF-16) string */
#if _USE_LFN == 0
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if _FS_EXFAT
#if _USE_LFN == 0
#error LFN must be enabled when enable exFAT
#endif
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* File system type (0:N/A) */
BYTE drv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _USE_LFN != 0
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if _FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if _FS_RPATH != 0
DWORD cdir; /* Current directory start cluster (0:root) */
#if _FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (_FDID) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if _FS_EXFAT
DWORD n_cont; /* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0) */
#endif
#if _FS_LOCK != 0
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;
/* File object structure (FIL) */
typedef struct {
_FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fprt is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
_FDID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if _USE_LFN != 0
TCHAR altname[13]; /* Altenative file name */
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

38
lib/fs/fat/integer.h Normal file
View file

@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for C89 compatibility) */
typedef unsigned long long QWORD;
#endif
#endif

152
lib/fs/fat/option/syscall.c Normal file
View file

@ -0,0 +1,152 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include <stdlib.h>
#include "../ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol]; /* uITRON (give a static sync object) */
// ret = 1; /* The initial value of the semaphore must be 1. */
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
// ret = (int)(*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// vSemaphoreDelete(sobj); /* FreeRTOS */
// ret = 1;
return ret;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
// xSemaphoreGive(sobj); /* FreeRTOS */
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
free(mblock); /* Discard the memory block with POSIX API */
}
#endif

View file

@ -0,0 +1,17 @@
#include "../ff.h"
#if _USE_LFN != 0
#if _CODE_PAGE == 932 /* Japanese Shift_JIS */
#include "unicode/cc932.c"
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
#include "unicode/cc936.c"
#elif _CODE_PAGE == 949 /* Korean */
#include "unicode/cc949.c"
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
#include "unicode/cc950.c"
#else /* Single Byte Character-Set */
#include "unicode/ccsbcs.c"
#endif
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,388 @@
/*------------------------------------------------------------------------*/
/* Unicode - Local code bidirectional converter (C)ChaN, 2015 */
/* (SBCS code pages) */
/*------------------------------------------------------------------------*/
/* 437 U.S.
/ 720 Arabic
/ 737 Greek
/ 771 KBL
/ 775 Baltic
/ 850 Latin 1
/ 852 Latin 2
/ 855 Cyrillic
/ 857 Turkish
/ 860 Portuguese
/ 861 Icelandic
/ 862 Hebrew
/ 863 Canadian French
/ 864 Arabic
/ 865 Nordic
/ 866 Russian
/ 869 Greek 2
*/
#include "../../ff.h"
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 771
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 860
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 861
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 863
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 864
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F,
0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9,
0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
};
#elif _CODE_PAGE == 865
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 869
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3,
0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580,
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
};
#endif
#if !_TBLDEF || !_USE_LFN
#error This file is not needed at current configuration. Remove from the project.
#endif
WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR chr, /* Character code to be converted */
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
)
{
WCHAR c;
if (chr < 0x80) { /* ASCII */
c = chr;
} else {
if (dir) { /* OEM code to Unicode */
c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80];
} else { /* Unicode to OEM code */
for (c = 0; c < 0x80; c++) {
if (chr == Tbl[c]) break;
}
c = (c + 0x80) & 0xFF;
}
}
return c;
}
WCHAR ff_wtoupper ( /* Returns upper converted character */
WCHAR chr /* Unicode character to be upper converted (BMP only) */
)
{
/* Compressed upper conversion table */
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
/* Basic Latin */
0x0061,0x031A,
/* Latin-1 Supplement */
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
/* Latin Extended-A */
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
/* Latin Extended-B */
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
/* IPA Extensions */
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
/* Greek, Coptic */
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
/* Cyrillic */
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
/* Armenian */
0x0561,0x0426,
0x0000
};
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
/* Phonetic Extensions */
0x1D7D,0x0001,0x2C63,
/* Latin Extended Additional */
0x1E00,0x0196, 0x1EA0,0x015A,
/* Greek Extended */
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF2,0x0001,0x1FFC,
/* Letterlike Symbols */
0x214E,0x0001,0x2132,
/* Number forms */
0x2170,0x0210, 0x2184,0x0001,0x2183,
/* Enclosed Alphanumerics */
0x24D0,0x051A, 0x2C30,0x042F,
/* Latin Extended-C */
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
/* Coptic */
0x2C80,0x0164,
/* Georgian Supplement */
0x2D00,0x0826,
/* Full-width */
0xFF41,0x031A,
0x0000
};
const WCHAR *p;
WCHAR bc, nc, cmd;
p = chr < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get block base */
if (!bc || chr < bc) break;
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (chr < bc + nc) { /* In the block? */
switch (cmd) {
case 0: chr = p[chr - bc]; break; /* Table conversion */
case 1: chr -= (chr - bc) & 1; break; /* Case pairs */
case 2: chr -= 16; break; /* Shift -16 */
case 3: chr -= 32; break; /* Shift -32 */
case 4: chr -= 48; break; /* Shift -48 */
case 5: chr -= 26; break; /* Shift -26 */
case 6: chr += 8; break; /* Shift +8 */
case 7: chr -= 80; break; /* Shift -80 */
case 8: chr -= 0x1C60; break; /* Shift -0x1C60 */
}
break;
}
if (!cmd) p += nc;
}
return chr;
}

View file

@ -18,6 +18,9 @@ endif
PYTHON = python PYTHON = python
BSL_FLAGS += -e -w -v BSL_FLAGS += -e -w -v
# Works in Linux and probably on OSX too (RTCC example)
CFLAGS += -DDATE="\"`date +"%02u %02d %02m %02y %02H %02M %02S"`\""
### Configure the build for the board and pull in board-specific sources ### Configure the build for the board and pull in board-specific sources
CONTIKI_TARGET_DIRS += . dev CONTIKI_TARGET_DIRS += . dev
CONTIKI_TARGET_DIRS += . $(BOARD) CONTIKI_TARGET_DIRS += . $(BOARD)

View file

@ -60,6 +60,7 @@ In terms of hardware support, the following drivers have been implemented for th
* Built-in core temperature and battery sensor. * Built-in core temperature and battery sensor.
* CC1200 sub-1GHz radio interface. * CC1200 sub-1GHz radio interface.
* Real Time Clock Calendar (on the RE-Mote platform). * Real Time Clock Calendar (on the RE-Mote platform).
* SD
There is a Zoul powering the RE-Mote and Firefly platforms, check out its specific README files for more information about on-board features. There is a Zoul powering the RE-Mote and Firefly platforms, check out its specific README files for more information about on-board features.

View file

@ -573,6 +573,27 @@ typedef uint32_t rtimer_clock_t;
#endif #endif
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/**
* \name RTC
*
* @{
*/
#ifdef PLATFORM_HAS_RTC
#ifndef RTC_CONF_INIT
#define RTC_CONF_INIT 0 /**< Whether to initialize the RTC */
#endif
#ifndef RTC_CONF_SET_FROM_SYS
#define RTC_CONF_SET_FROM_SYS 0 /**< Whether to set the RTC from the build system */
#endif
#else
#undef RTC_CONF_INIT
#define RTC_CONF_INIT 0
#endif
/** @} */
/*---------------------------------------------------------------------------*/
#endif /* CONTIKI_CONF_H_ */ #endif /* CONTIKI_CONF_H_ */

View file

@ -57,6 +57,7 @@
#include "dev/cc2538-rf.h" #include "dev/cc2538-rf.h"
#include "dev/udma.h" #include "dev/udma.h"
#include "dev/crypto.h" #include "dev/crypto.h"
#include "dev/rtcc.h"
#include "usb/usb-serial.h" #include "usb/usb-serial.h"
#include "lib/random.h" #include "lib/random.h"
#include "net/netstack.h" #include "net/netstack.h"
@ -72,6 +73,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if STARTUP_CONF_VERBOSE #if STARTUP_CONF_VERBOSE
@ -109,6 +111,62 @@ fade(unsigned char l)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
rtc_init(void)
{
#if RTC_CONF_INIT
#if RTC_CONF_SET_FROM_SYS
char *next;
simple_td_map td;
#endif
/* Configure RTC and return structure with all parameters */
rtcc_init();
#if RTC_CONF_SET_FROM_SYS
#ifndef DATE
#error Could not retrieve date from system
#endif
/* Alternatively, for test only, undefine DATE and define it on your own as:
* #define DATE "07 06 12 15 16 00 00"
* Also note that if you restart the node at a given time, it will use the
* already defined DATE, so if you want to update the device date/time you
* need to reflash the node.
*/
/* Get the system date in the following format: wd dd mm yy hh mm ss */
PRINTF("Setting RTC from system date: %s\n", DATE);
/* Configure the RTC with the current values */
td.weekdays = (uint8_t)strtol(DATE, &next, 10);
td.day = (uint8_t)strtol(next, &next, 10);
td.months = (uint8_t)strtol(next, &next, 10);
td.years = (uint8_t)strtol(next, &next, 10);
td.hours = (uint8_t)strtol(next, &next, 10);
td.minutes = (uint8_t)strtol(next, &next, 10);
td.seconds = (uint8_t)strtol(next, NULL, 10);
/* Don't care about the milliseconds... */
td.miliseconds = 0;
/* This example relies on 24h mode */
td.mode = RTCC_24H_MODE;
/*
* And to simplify the configuration, it relies on the fact that it will be
* executed in the present century
*/
td.century = RTCC_CENTURY_20XX;
/* Set the time and date */
if(rtcc_set_time_date(&td) == AB08_ERROR) {
PRINTF("Failed to set time and date\n");
}
#endif
#endif
}
/*---------------------------------------------------------------------------*/
static void
set_rf_params(void) set_rf_params(void)
{ {
uint16_t short_addr; uint16_t short_addr;
@ -204,6 +262,8 @@ main(void)
crypto_disable(); crypto_disable();
#endif #endif
rtc_init();
netstack_init(); netstack_init();
set_rf_params(); set_rf_params();

View file

@ -0,0 +1,139 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup mmc-arch
* @{
*
* \file
* Implementation of the SD/MMC device driver RE-Mote-specific definitions.
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "spi-arch.h"
#include "dev/ioc.h"
#include "dev/gpio.h"
#include "dev/spi.h"
#include "mmc-arch.h"
#define USD_SEL_PORT_BASE GPIO_PORT_TO_BASE(USD_SEL_PORT)
#define USD_SEL_PIN_MASK GPIO_PIN_MASK(USD_SEL_PIN)
/*----------------------------------------------------------------------------*/
static void
mmc_arch_init(void)
{
static uint8_t init_done;
if(init_done) {
return;
}
GPIO_SET_INPUT(USD_SEL_PORT_BASE, USD_SEL_PIN_MASK);
GPIO_SOFTWARE_CONTROL(USD_SEL_PORT_BASE, USD_SEL_PIN_MASK);
ioc_set_over(USD_SEL_PORT, USD_SEL_PIN, IOC_OVERRIDE_DIS);
spix_cs_init(USD_CSN_PORT, USD_CSN_PIN);
spix_init(USD_SPI_INSTANCE);
spix_set_mode(USD_SPI_INSTANCE, SSI_CR0_FRF_MOTOROLA, 0, 0, 8);
init_done = 1;
}
/*----------------------------------------------------------------------------*/
bool
mmc_arch_get_cd(uint8_t dev)
{
mmc_arch_init();
if(GPIO_IS_OUTPUT(USD_SEL_PORT_BASE, USD_SEL_PIN_MASK)) {
/* Card previously detected and powered */
return true;
} else if(GPIO_READ_PIN(USD_SEL_PORT_BASE, USD_SEL_PIN_MASK)) {
/* Card inserted -> power it */
GPIO_SET_OUTPUT(USD_SEL_PORT_BASE, USD_SEL_PIN_MASK);
GPIO_CLR_PIN(USD_SEL_PORT_BASE, USD_SEL_PIN_MASK);
return true;
} else {
/* No card detected */
return false;
}
}
/*----------------------------------------------------------------------------*/
bool
mmc_arch_get_wp(uint8_t dev)
{
return false;
}
/*----------------------------------------------------------------------------*/
void
mmc_arch_spi_select(uint8_t dev, bool sel)
{
if(sel) {
SPIX_CS_CLR(USD_CSN_PORT, USD_CSN_PIN);
} else {
SPIX_CS_SET(USD_CSN_PORT, USD_CSN_PIN);
}
}
/*----------------------------------------------------------------------------*/
void
mmc_arch_spi_set_clock_freq(uint8_t dev, uint32_t freq)
{
spix_set_clock_freq(USD_SPI_INSTANCE, freq);
}
/*----------------------------------------------------------------------------*/
void
mmc_arch_spi_xfer(uint8_t dev, const void *tx_buf, size_t tx_cnt,
void *rx_buf, size_t rx_cnt)
{
const uint8_t *tx_buf_u8 = tx_buf;
uint8_t *rx_buf_u8 = rx_buf;
while(tx_cnt || rx_cnt) {
SPIX_WAITFORTxREADY(USD_SPI_INSTANCE);
if(tx_cnt) {
SPIX_BUF(USD_SPI_INSTANCE) = *tx_buf_u8++;
tx_cnt--;
} else {
SPIX_BUF(USD_SPI_INSTANCE) = 0;
}
SPIX_WAITFOREOTx(USD_SPI_INSTANCE);
SPIX_WAITFOREORx(USD_SPI_INSTANCE);
if(rx_cnt) {
*rx_buf_u8++ = SPIX_BUF(USD_SPI_INSTANCE);
rx_cnt--;
} else {
SPIX_BUF(USD_SPI_INSTANCE);
}
}
}
/*----------------------------------------------------------------------------*/
/** @} */

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup remote-fat
* @{
*
* \file
* Implementation of the default port of FatFs on RE-Mote.
*/
#include "diskio.h"
#include "mmc.h"
#include "rtcc.h"
/*----------------------------------------------------------------------------*/
DSTATUS __attribute__((__weak__))
disk_status(BYTE pdrv)
{
return ~mmc_driver.status(pdrv);
}
/*----------------------------------------------------------------------------*/
DSTATUS __attribute__((__weak__))
disk_initialize(BYTE pdrv)
{
return ~mmc_driver.initialize(pdrv);
}
/*----------------------------------------------------------------------------*/
DRESULT __attribute__((__weak__))
disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
return mmc_driver.read(pdrv, buff, sector, count);
}
/*----------------------------------------------------------------------------*/
DRESULT __attribute__((__weak__))
disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
return mmc_driver.write(pdrv, buff, sector, count);
}
/*----------------------------------------------------------------------------*/
DRESULT __attribute__((__weak__))
disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
return mmc_driver.ioctl(pdrv, cmd, buff);
}
/*----------------------------------------------------------------------------*/
DWORD __attribute__((__weak__))
get_fattime(void)
{
simple_td_map td;
return rtcc_get_time_date(&td) == AB08_SUCCESS ?
(2000 + td.years - 1980) << 25 | td.months << 21 | td.day << 16 |
td.hours << 11 | td.minutes << 5 | td.seconds : 0;
}
/*----------------------------------------------------------------------------*/
/** @} */

View file

@ -0,0 +1,418 @@
/*
* Copyright (c) 2016, Benoît Thébaudeau <benoit@wsystem.com>
* All rights reserved.
*
* Based on the FatFs Module,
* Copyright (c) 2016, ChaN
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup remote
* @{
*
* \defgroup remote-fat RE-Mote FatFs
*
* Default port of FatFs on RE-Mote.
* @{
*
* \file
* Header file configuring FatFs for RE-Mote.
*/
#ifndef FFCONF_H_
#define FFCONF_H_
#include "contiki-conf.h"
#define _FFCONF 68020 /**< Revision ID */
/*----------------------------------------------------------------------------*/
/** \name Function Configuration
* @{
*/
#ifndef _FS_READONLY
/** This option switches the read-only configuration
* (\c 0: read/write or \c 1: read-only).
*
* The read-only configuration removes the writing functions from the API:
* \c f_write(), \c f_sync(), \c f_unlink(), \c f_mkdir(), \c f_chmod(),
* \c f_rename(), \c f_truncate(), \c f_getfree(), and optional writing
* functions as well.
*/
#define _FS_READONLY 0
#endif
#ifndef _FS_MINIMIZE
/** This option defines the minimization level to remove some basic API
* functions.
*
* \c 0: All the basic functions are enabled.
* \c 1: \c f_stat(), \c f_getfree(), \c f_unlink(), \c f_mkdir(),
* \c f_truncate(), and \c f_rename() are removed.
* \c 2: \c f_opendir(), \c f_readdir(), and \c f_closedir() are removed in
* addition to \c 1.
* \c 3: \c f_lseek() is removed in addition to \c 2.
*/
#define _FS_MINIMIZE 0
#endif
#ifndef _USE_STRFUNC
/** This option switches the string functions: \c f_gets(), \c f_putc(),
* \c f_puts(), and \c f_printf().
*
* \c 0: Disable string functions.
* \c 1: Enable without LF-CRLF conversion.
* \c 2: Enable with LF-CRLF conversion.
*/
#define _USE_STRFUNC 1
#endif
#ifndef _USE_FIND
/** This option switches the filtered directory read functions: \c f_findfirst()
* and \c f_findnext() (\c 0: disable, \c 1: enable, \c 2: enable with matching
* \c altname[] too).
*/
#define _USE_FIND 1
#endif
#ifndef _USE_MKFS
/** This option switches the \c f_mkfs() function
* (\c 0: disable or \c 1: enable).
*/
#define _USE_MKFS 1
#endif
#ifndef _USE_FASTSEEK
/** This option switches the fast seek function
* (\c 0: disable or \c 1: enable).
*/
#define _USE_FASTSEEK 0
#endif
#ifndef _USE_EXPAND
/** This option switches the \c f_expand() function
* (\c 0: disable or \c 1: enable).
*/
#define _USE_EXPAND 0
#endif
#ifndef _USE_CHMOD
/** This option switches the attribute manipulation functions: \c f_chmod() and
* \c f_utime() (\c 0: disable or \c 1: enable). Also, \c _FS_READONLY needs to
* be \c 0 to enable this option.
*/
#define _USE_CHMOD 1
#endif
#ifndef _USE_LABEL
/** This option switches the volume label functions: \c f_getlabel() and
* \c f_setlabel() (\c 0: disable or \c 1: enable).
*/
#define _USE_LABEL 1
#endif
#ifndef _USE_FORWARD
/** This option switches the \c f_forward() function
* (\c 0: disable or \c 1: enable).
*/
#define _USE_FORWARD 0
#endif
/** @} */
/*----------------------------------------------------------------------------*/
/** \name Locale and Namespace Configuration
* @{
*/
#ifndef _CODE_PAGE
/** This option specifies the OEM code page to be used on the target system.
* Incorrect setting of the code page can cause a file open failure.
*
* \c 1 - ASCII (no extended character, non-LFN cfg. only)
* \c 437 - U.S.
* \c 720 - Arabic
* \c 737 - Greek
* \c 771 - KBL
* \c 775 - Baltic
* \c 850 - Latin 1
* \c 852 - Latin 2
* \c 855 - Cyrillic
* \c 857 - Turkish
* \c 860 - Portuguese
* \c 861 - Icelandic
* \c 862 - Hebrew
* \c 863 - Canadian French
* \c 864 - Arabic
* \c 865 - Nordic
* \c 866 - Russian
* \c 869 - Greek 2
* \c 932 - Japanese (DBCS)
* \c 936 - Simplified Chinese (DBCS)
* \c 949 - Korean (DBCS)
* \c 950 - Traditional Chinese (DBCS)
*/
#define _CODE_PAGE 437
#endif
#ifndef _USE_LFN
/** \c _USE_LFN switches the support of long file name (LFN).
*
* \c 0: Disable LFN support. \c _MAX_LFN has no effect.
* \c 1: Enable LFN with static working buffer on the BSS. Always thread-unsafe.
* \c 2: Enable LFN with dynamic working buffer on the STACK.
* \c 3: Enable LFN with dynamic working buffer on the HEAP.
*
* To enable LFN, the Unicode handling functions (<tt>option/unicode.c</tt>)
* must be added to the project. The working buffer occupies
* <tt>(_MAX_LFN + 1) * 2</tt> bytes, and 608 more bytes with exFAT enabled.
* \c _MAX_LFN can be in the range from 12 to 255. It should be set to 255 to
* support the full-featured LFN operations. When using the stack for the
* working buffer, take care of stack overflow. When using the heap memory for
* the working buffer, the memory management functions, \c ff_memalloc() and
* \c ff_memfree(), must be added to the project.
*/
#define _USE_LFN 3
#endif
#ifndef _MAX_LFN
#define _MAX_LFN 255
#endif
#ifndef _LFN_UNICODE
/** This option switches the character encoding in the API
* (\c 0: ANSI/OEM or \c 1: UTF-16).
*
* To use a Unicode string for the path name, enable LFN and set \c _LFN_UNICODE
* to \c 1.
* This option also affects the behavior of the string I/O functions.
*/
#define _LFN_UNICODE 0
#endif
#ifndef _STRF_ENCODE
/** If \c _LFN_UNICODE is set to \c 1, this option selects the character
* encoding OF THE FILE to be read/written via the string I/O functions:
* \c f_gets(), \c f_putc(), \c f_puts(), and \c f_printf().
*
* \c 0: ANSI/OEM
* \c 1: UTF-16LE
* \c 2: UTF-16BE
* \c 3: UTF-8
*
* This option has no effect if \c _LFN_UNICODE is set to \c 0.
*/
#define _STRF_ENCODE 0
#endif
#ifndef _FS_RPATH
/** This option configures the support of relative path.
*
* \c 0: Disable relative path and remove related functions.
* \c 1: Enable relative path. \c f_chdir() and \c f_chdrive() are available.
* \c 2: \c f_getcwd() is available in addition to \c 1.
*/
#define _FS_RPATH 2
#endif
/** @} */
/*----------------------------------------------------------------------------*/
/** \name Drive/Volume Configuration
* @{
*/
#ifndef _VOLUMES
/** Number of volumes (logical drives) to be used. */
#define _VOLUMES 1
#endif
#ifndef _STR_VOLUME_ID
/** \c _STR_VOLUME_ID switches the string support of volume ID.
* If \c _STR_VOLUME_ID is set to \c 1, pre-defined strings can also be used as
* drive number in the path name. \c _VOLUME_STRS defines the drive ID strings
* for each logical drive. The number of items must be equal to \c _VOLUMES.
* The valid characters for the drive ID strings are: A-Z and 0-9.
*/
#define _STR_VOLUME_ID 0
#endif
#ifndef _VOLUME_STRS
#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
#endif
#ifndef _MULTI_PARTITION
/** 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.
* When multi-partition is enabled (1), each logical drive number can be bound to
* arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
* funciton will be available.
*/
#define _MULTI_PARTITION 0
#endif
#ifndef _MIN_SS
/** These options configure the range of sector size to be supported (512, 1024,
* 2048, or 4096). Always set both to 512 for most systems, all types of memory
* cards and harddisk. But a larger value may be required for on-board flash
* memory and some types of optical media. When \c _MAX_SS is larger than
* \c _MIN_SS, FatFs is configured to variable sector size and the
* \c GET_SECTOR_SIZE command must be implemented in \c disk_ioctl().
*/
#define _MIN_SS 512
#endif
#ifndef _MAX_SS
#define _MAX_SS 512
#endif
#ifndef _USE_TRIM
/** This option switches the support of ATA-TRIM
* (\c 0: disable or \c 1: enable).
*
* To enable the Trim function, the \c CTRL_TRIM command should also be
* implemented in \c disk_ioctl().
*/
#define _USE_TRIM 0
#endif
#ifndef _FS_NOFSINFO
/** If you need to know the correct free space on the FAT32 volume, set the bit
* 0 of this option, and the \c f_getfree() function will force a full FAT scan
* on the first time after a volume mount. The bit 1 controls the use of the
* last allocated cluster number.
*
* bit 0=0: Use the free cluster count in FSINFO if available.
* bit 0=1: Do not trust the free cluster count in FSINFO.
* bit 1=0: Use the last allocated cluster number in FSINFO if available.
* bit 1=1: Do not trust the last allocated cluster number in FSINFO.
*/
#define _FS_NOFSINFO 3
#endif
/** @} */
/*----------------------------------------------------------------------------*/
/** \name System Configuration
* @{
*/
#ifndef _FS_TINY
/** This option switches the tiny buffer configuration
* (\c 0: normal or \c 1: tiny).
*
* With the tiny configuration, the size of a file object (FIL) is reduced to
* \c _MAX_SS bytes. Instead of the private sector buffer eliminated from the
* file object, a common sector buffer in the file system object (FATFS) is used
* for the file data transfer.
*/
#define _FS_TINY 0
#endif
#ifndef _FS_EXFAT
/** This option switches the support of the exFAT file system
* (\c 0: disable or \c 1: enable).
*
* With exFAT enabled, LFN also needs to be enabled (\c _USE_LFN >= 1).
* Note that enabling exFAT discards C89 compatibility.
*/
#define _FS_EXFAT 1
#endif
#ifndef _FS_NORTC
/** The option \c _FS_NORTC switches the timestamp function. If the system does
* not have any RTC function or if a valid timestamp is not needed, set
* \c _FS_NORTC to \c 1 to disable the timestamp function. All the objects
* modified by FatFs will have a fixed timestamp defined by \c _NORTC_MON,
* \c _NORTC_MDAY, and \c _NORTC_YEAR in local time.
* To enable the timestamp function (\c _FS_NORTC set to \c 0), \c get_fattime()
* needs to be added to the project to get the current time from a real-time
* clock. \c _NORTC_MON, \c _NORTC_MDAY, and \c _NORTC_YEAR have no effect.
* These options have no effect with a read-only configuration (\c _FS_READONLY
* set to \c 1).
*/
#define _FS_NORTC (!RTC_CONF_INIT)
#endif
#ifndef _NORTC_MON
#define _NORTC_MON 1
#endif
#ifndef _NORTC_MDAY
#define _NORTC_MDAY 1
#endif
#ifndef _NORTC_YEAR
#define _NORTC_YEAR 2016
#endif
#ifndef _FS_LOCK
/** The option \c _FS_LOCK switches the file lock function controlling duplicate
* file open and illegal operations on the open objects. This option must be set
* to \c 0 if \c _FS_READONLY is \c 1.
*
* \c 0: Disable the file lock function. To avoid volume corruption, the
* application program should avoid illegal open, remove, and rename on
* the open objects.
* \c >0: Enable the file lock function. The value defines how many
* files/sub-directories can be opened simultaneously under file lock
* control. Note that the file lock control is independent of
* re-entrancy.
*/
#define _FS_LOCK 0
#endif
#ifndef _FS_REENTRANT
/** The option \c _FS_REENTRANT switches the re-entrancy (thread-safe) of the
* FatFs module itself. Note that, regardless of this option, file access to
* different volumes is always re-entrant, and the volume control functions,
* \c f_mount(), \c f_mkfs(), and \c f_fdisk(), are always non-re-entrant. Only
* file/directory access to the same volume is under control of this function.
*
* \c 0: Disable re-entrancy. \c _FS_TIMEOUT and \c _SYNC_t have no effect.
* \c 1: Enable re-entrancy. The user-provided synchronization handlers,
* \c ff_req_grant(), \c ff_rel_grant(), \c ff_del_syncobj(), and
* \c ff_cre_syncobj(), must also be added to the project. Samples are
* available in <tt>option/syscall.c</tt>.
*
* \c _FS_TIMEOUT defines the timeout period in unit of time tick.
* \c _SYNC_t defines the OS-dependent sync object type, e.g. \c HANDLE, \c ID,
* \c OS_EVENT*, \c SemaphoreHandle_t, etc. A header file for the OS definitions
* needs to be included somewhere in the scope of <tt>ff.h</tt>.
*/
#define _FS_REENTRANT 0
#endif
#ifndef _FS_TIMEOUT
#define _FS_TIMEOUT 1000
#endif
#ifndef _SYNC_t
#define _SYNC_t HANDLE
#endif
/** @} */
/*----------------------------------------------------------------------------*/
#endif /* FFCONF_H_ */
/**
* @}
* @}
*/

View file

@ -1,2 +1,4 @@
MOTELIST_ZOLERTIA = remote MOTELIST_ZOLERTIA = remote
BOARD_SOURCEFILES += board.c antenna-sw.c rtcc.c power-mgmt.c leds-arch.c BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c leds-arch.c
MODULES += lib/fs/fat lib/fs/fat/option platform/zoul/fs/fat dev/disk/mmc

View file

@ -405,6 +405,7 @@
* external module, to be used with SSI1 * external module, to be used with SSI1
* @{ * @{
*/ */
#define USD_SPI_INSTANCE 1
#define USD_CLK_PORT SPI1_CLK_PORT #define USD_CLK_PORT SPI1_CLK_PORT
#define USD_CLK_PIN SPI1_CLK_PIN #define USD_CLK_PIN SPI1_CLK_PIN
#define USD_MOSI_PORT SPI1_TX_PORT #define USD_MOSI_PORT SPI1_TX_PORT
@ -454,6 +455,7 @@
* requiring to put the PIC into deep-sleep and waking up at a certain time. * requiring to put the PIC into deep-sleep and waking up at a certain time.
* @{ * @{
*/ */
#define PLATFORM_HAS_RTC 1
#define RTC_SDA_PORT I2C_SDA_PORT #define RTC_SDA_PORT I2C_SDA_PORT
#define RTC_SDA_PIN I2C_SDA_PIN #define RTC_SDA_PIN I2C_SDA_PIN
#define RTC_SCL_PORT I2C_SCL_PORT #define RTC_SCL_PORT I2C_SCL_PORT

View file

@ -1,2 +1,4 @@
MOTELIST_ZOLERTIA = remote MOTELIST_ZOLERTIA = remote
BOARD_SOURCEFILES += board.c antenna-sw.c rtcc.c leds-res-arch.c power-mgmt.c BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c leds-res-arch.c power-mgmt.c
MODULES += lib/fs/fat lib/fs/fat/option platform/zoul/fs/fat dev/disk/mmc

View file

@ -433,6 +433,7 @@
* a microSD in the slot, or when connected to disable the microSD to save power * a microSD in the slot, or when connected to disable the microSD to save power
* @{ * @{
*/ */
#define USD_SPI_INSTANCE 1
#define USD_CLK_PORT SPI1_CLK_PORT #define USD_CLK_PORT SPI1_CLK_PORT
#define USD_CLK_PIN SPI1_CLK_PIN #define USD_CLK_PIN SPI1_CLK_PIN
#define USD_MOSI_PORT SPI1_TX_PORT #define USD_MOSI_PORT SPI1_TX_PORT
@ -481,6 +482,7 @@
* *
* @{ * @{
*/ */
#define PLATFORM_HAS_RTC 1
#define RTC_SDA_PORT I2C_SDA_PORT #define RTC_SDA_PORT I2C_SDA_PORT
#define RTC_SDA_PIN I2C_SDA_PIN #define RTC_SDA_PIN I2C_SDA_PIN
#define RTC_SCL_PORT I2C_SCL_PORT #define RTC_SCL_PORT I2C_SCL_PORT

View file

@ -54,6 +54,7 @@ sensniff/ev-aducrf101mkxz \
cfs-coffee/cc2538dk \ cfs-coffee/cc2538dk \
cfs-coffee/openmote-cc2538 \ cfs-coffee/openmote-cc2538 \
cfs-coffee/zoul \ cfs-coffee/zoul \
fat/zoul:BOARD=remote-revb \
ipv6/rpl-tsch/zoul \ ipv6/rpl-tsch/zoul \
ipv6/rpl-tsch/zoul:MAKE_WITH_ORCHESTRA=1 \ ipv6/rpl-tsch/zoul:MAKE_WITH_ORCHESTRA=1 \
ipv6/rpl-tsch/zoul:MAKE_WITH_SECURITY=1 ipv6/rpl-tsch/zoul:MAKE_WITH_SECURITY=1