diff options
| -rw-r--r-- | fw/fe310/eos/Makefile | 2 | ||||
| -rw-r--r-- | fw/fe310/eos/board.h | 8 | ||||
| -rw-r--r-- | fw/fe310/eos/eos.c | 2 | ||||
| -rw-r--r-- | fw/fe310/eos/sdcard.c | 314 | ||||
| -rw-r--r-- | fw/fe310/eos/sdcard.h | 3 | ||||
| -rw-r--r-- | fw/fe310/eos/spi.c | 4 | ||||
| -rw-r--r-- | fw/fe310/eos/spi.h | 2 | ||||
| -rw-r--r-- | fw/fe310/eos/timer.c | 4 | ||||
| -rw-r--r-- | fw/fe310/eos/timer.h | 1 | 
9 files changed, 332 insertions, 8 deletions
diff --git a/fw/fe310/eos/Makefile b/fw/fe310/eos/Makefile index 0b3d6fe..66ac136 100644 --- a/fw/fe310/eos/Makefile +++ b/fw/fe310/eos/Makefile @@ -2,7 +2,7 @@ include ../common.mk  CFLAGS += -I. -I../bsp/include -I../bsp/drivers -obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o power.o i2s.o i2c.o uart.o spi.o spi_dev.o net.o wifi.o cell.o sock.o unicode.o +obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o power.o i2s.o i2c.o uart.o spi.o spi_dev.o sdcard.o net.o wifi.o cell.o sock.o unicode.o  %.o: %.c %.h diff --git a/fw/fe310/eos/board.h b/fw/fe310/eos/board.h index e663f62..1299bb6 100644 --- a/fw/fe310/eos/board.h +++ b/fw/fe310/eos/board.h @@ -1,19 +1,19 @@  #define SPI_DIV_NET             16  #define SPI_DIV_EVE             16 -#define SPI_DIV_SDC             16 +#define SPI_DIV_SDC             1024  #define SPI_DIV_CAM             16  #define SPI_CSID_NET            3  #define SPI_CSID_EVE            2 -#define SPI_CSID_SDC            0 +#define SPI_CSID_SDC            SPI_CSID_NONE  #define SPI_CSID_CAM            SPI_CSID_NONE  #define SPI_CSPIN_NET           SPI_CSPIN_NONE  #define SPI_CSPIN_EVE           SPI_CSPIN_NONE -#define SPI_CSPIN_SDC           SPI_CSPIN_NONE +#define SPI_CSPIN_SDC           2  #define SPI_CSPIN_CAM           23 -#define SPI_IOF_MASK_CS         (((uint32_t)1 << IOF_SPI1_SS0) | ((uint32_t)1 << IOF_SPI1_SS2) | ((uint32_t)1 << IOF_SPI1_SS3)) +#define SPI_IOF_MASK_CS         (((uint32_t)1 << IOF_SPI1_SS2) | ((uint32_t)1 << IOF_SPI1_SS3))  #define NET_PIN_RTS             20  #define NET_PIN_CTS             22 diff --git a/fw/fe310/eos/eos.c b/fw/fe310/eos/eos.c index aa374a0..87b414b 100644 --- a/fw/fe310/eos/eos.c +++ b/fw/fe310/eos/eos.c @@ -8,6 +8,7 @@  #include "uart.h"  #include "spi.h"  #include "spi_dev.h" +#include "sdcard.h"  #include "net.h"  #include "wifi.h"  #include "cell.h" @@ -30,6 +31,7 @@ void eos_init(void) {      eos_uart_init();      eos_spi_init();      eos_spi_dev_init(); +    eos_sdc_init();      eos_net_init();      eos_power_init();      eos_wifi_init(); diff --git a/fw/fe310/eos/sdcard.c b/fw/fe310/eos/sdcard.c new file mode 100644 index 0000000..8162a3e --- /dev/null +++ b/fw/fe310/eos/sdcard.c @@ -0,0 +1,314 @@ +#include <stdlib.h> +#include <stdint.h> + +#include "eos.h" +#include "timer.h" + +#include "spi.h" +#include "spi_dev.h" + +#include "sdcard.h" + +#define SDC_POLY_CRC7           0x09 +#define SDC_POLY_CRC16          0x1021 + +#define SDC_CMD_FLAG_CRC        0x01 +#define SDC_CMD_FLAG_NOCS       0x02 +#define SDC_CMD_FLAG_SKIP       0x08 + +#define SDC_TOKEN_START_BLK     0xfe +#define SDC_TOKEN_START_BLKM    0xfc +#define SDC_TOKEN_STOP_TRAN     0xfd + +#define SDC_R1_READY            0x00 + +#define SDC_R1_IDLE_STATE       0x01 +#define SDC_R1_ERASE_RESET      0x02 +#define SDC_R1_ILLEGAL_CMD      0x04 +#define SDC_R1_ERR_CMD_CRC      0x08 +#define SDC_R1_ERR_ERASE_SEQ    0x10 +#define SDC_R1_ERR_ADDR         0x20 +#define SDC_R1_ERR_PARAM        0x40 + +#define SDC_NCR                 10 + +#define SDC_TYPE_MMC            1 +#define SDC_TYPE_SDC1           2 +#define SDC_TYPE_SDC2           3 + +#define SDC_ERR(rv)             ((rv < 0) ? rv : EOS_ERR) + +/* CMD */ +#define GO_IDLE_STATE           0 +#define SEND_OP_COND            1 +#define SEND_IF_COND            8 +#define SET_BLOCKLEN            16 +#define APP_CMD                 55 +#define READ_OCR                58 + +/* ACMD */ +#define SD_APP_OP_COND          41 + +static uint8_t sdc_crc7(uint8_t crc, uint8_t b) { +    int i; + +    for (i=8; i--; b<<=1) { +        crc <<= 1; +        if ((b ^ crc) & 0x80) crc ^= SDC_POLY_CRC7; +    } +    return crc & 0x7f; +} + +static uint16_t sdc_crc16(uint16_t crc, uint8_t b) { +    int i; + +    crc = crc ^ ((uint16_t)b << 8); +    for (i=8; i--;) { +        if (crc & 0x8000) { +            crc = (crc << 1) ^ SDC_POLY_CRC16; +        } else { +            crc <<= 1; +        } +    } +    return crc; +} + +static uint32_t sdc_nto(uint64_t start, uint32_t timeout) { +    uint32_t d = eos_time_since(start); +    return (d > timeout) ? 0 : timeout - d; +} + +static void sdc_xchg(unsigned char *buffer, uint16_t len) { +} + +static uint8_t sdc_xchg8(uint8_t data) { +    return eos_spi_xchg8(data, 0); +} + +static uint16_t sdc_xchg16(uint16_t data) { +    return eos_spi_xchg16(data, 0); +} + +static uint32_t sdc_xchg32(uint32_t data) { +    return eos_spi_xchg32(data, 0); +} + +static void sdc_select(void) { +    eos_spi_cs_set(); +    eos_spi_xchg8(0xff, 0); +} + +static void sdc_deselect(void) { +    eos_spi_cs_clear(); +    eos_spi_xchg8(0xff, 0); +} + +static int sdc_xchg_cmd(uint8_t cmd, uint32_t arg, uint8_t flags) { +    int i; +    uint8_t ret; +    uint8_t crc = 0x7f; + +    cmd |= 0x40; +    if (flags & SDC_CMD_FLAG_CRC) { +        crc = sdc_crc7(0, cmd); +        crc = sdc_crc7(crc, arg >> 24); +        crc = sdc_crc7(crc, arg >> 16); +        crc = sdc_crc7(crc, arg >> 8); +        crc = sdc_crc7(crc, arg); +    } +    crc = (crc << 1) | 0x01; +    sdc_xchg8(cmd); +    sdc_xchg32(arg); +    sdc_xchg8(crc); +    if (flags & SDC_CMD_FLAG_SKIP) sdc_xchg8(0xff); + +    i = SDC_NCR; +    do { +        ret = sdc_xchg8(0xff); +    } while ((ret & 0x80) && --i); +    if (ret & 0x80) return EOS_ERR_BUSY; + +    return ret; +} + +static int sdc_ready(uint32_t timeout) { +    uint8_t d = 0; +    uint64_t start; + +    if (timeout == 0) return EOS_ERR_BUSY; +    start = eos_time_get_tick(); +	do { +        if (eos_time_since(start) > timeout) break; +		d = sdc_xchg8(0xff); +	} while (d != 0xff); +	if (d != 0xff) return EOS_ERR_BUSY; + +    return EOS_OK; +} + +static int sdc_block_read(uint8_t *buffer, uint16_t len, uint32_t timeout) { +    uint8_t token = 0xff; +    uint64_t start; + +    if (timeout == 0) return EOS_ERR_BUSY; +    start = eos_time_get_tick(); +	do { +        if (eos_time_since(start) > timeout) break; +		token = sdc_xchg8(0xff); +	} while (token == 0xff); +    if (token == 0xff) return EOS_ERR_BUSY; +	if (token != SDC_TOKEN_START_BLK) return EOS_ERR; + +    sdc_xchg(buffer, len); +    sdc_xchg16(0xff); /* dummy CRC */ + +    return EOS_OK; +} + +static int sdc_block_write(uint8_t token, uint8_t *buffer, uint16_t len, uint32_t timeout) { +    uint8_t d; +    int rv; + +    rv = sdc_ready(timeout); +    if (rv) return rv; + +    sdc_xchg8(token); +    if (buffer && len) { +        sdc_xchg(buffer, len); +        sdc_xchg16(0xff); /* dummy CRC */ + +        d = sdc_xchg8(0xff); /* Response */ +        if ((d & 0x1f) != 0x05) return EOS_ERR; +    } + +    return EOS_OK; +} + +static int sdc_cmd(uint8_t cmd, uint32_t arg, uint8_t flags, uint32_t timeout) { +    int do_cs = !(flags & SDC_CMD_FLAG_NOCS); +    int rv; + +    if (do_cs) sdc_select(); +    rv = sdc_ready(timeout); +    if (rv) { +        if (do_cs) sdc_deselect(); +        return rv; +    } +    rv = sdc_xchg_cmd(cmd, arg, flags); +    if (do_cs) sdc_deselect(); +    return rv; +} + +static int sdc_acmd(uint8_t cmd, uint32_t arg, uint8_t flags, uint32_t timeout) { +    int rv; +    uint64_t start; + +    if (flags & SDC_CMD_FLAG_NOCS) return EOS_ERR; + +    start = eos_time_get_tick(); +    rv = sdc_cmd(APP_CMD, 0, flags & SDC_CMD_FLAG_CRC, timeout); +    if (rv & ~SDC_R1_IDLE_STATE) return rv; + +    return sdc_cmd(cmd, arg, flags, sdc_nto(start, timeout)); +} + +static int sdc_init(uint32_t timeout, uint8_t *type, uint8_t *lba) { +    uint8_t _type, _lba; +    int rv, i; +    uint8_t ocr[4]; +    uint64_t start; + +    _type = 0; +    _lba = 0; + +    start = eos_time_get_tick(); +    sdc_select(); +	for (i=10; i--;) sdc_xchg8(0xff);     /* 80 dummy cycles */ +    rv = sdc_cmd(GO_IDLE_STATE, 0, SDC_CMD_FLAG_CRC | SDC_CMD_FLAG_NOCS, timeout); +    if (rv != SDC_R1_IDLE_STATE) return SDC_ERR(rv); +    sdc_deselect(); + +    sdc_select(); +    rv = sdc_cmd(SEND_IF_COND, 0x1aa, SDC_CMD_FLAG_CRC | SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); +    switch (rv) { +        case SDC_R1_IDLE_STATE: +    		for (i=0; i<4; i++) { +                ocr[i] = sdc_xchg8(0xff);    /* get R7 resp */ +            } +            sdc_deselect(); +    		if (ocr[2] == 0x01 && ocr[3] == 0xaa) {     /* Check voltage range: 2.7-3.6V */ +                do { +                    rv = sdc_acmd(SD_APP_OP_COND, 0x40000000, 0, sdc_nto(start, timeout)); +                } while (rv == SDC_R1_IDLE_STATE); +                if (rv != SDC_R1_READY) return SDC_ERR(rv); + +                sdc_select(); +                rv = sdc_cmd(READ_OCR, 0, SDC_CMD_FLAG_NOCS, sdc_nto(start, timeout)); +                if (rv == SDC_R1_READY) { +    				for (i=0; i<4; i++) { +                        ocr[i] = sdc_xchg8(0xff); +                    } +                    sdc_deselect(); +                } else { +                    sdc_deselect(); +                    return SDC_ERR(rv); +                } + +                _type = SDC_TYPE_SDC2; +                if (ocr[0] & 0xc0) _lba = 1; +            } +            break; + +        case SDC_R1_IDLE_STATE | SDC_R1_ILLEGAL_CMD: +            sdc_deselect(); +            rv = sdc_acmd(SD_APP_OP_COND, 0, 0, sdc_nto(start, timeout)); +            switch (rv) { +                case SDC_R1_IDLE_STATE: +                    do  { +                        rv = sdc_acmd(SD_APP_OP_COND, 0, 0, sdc_nto(start, timeout)); +                    } while (rv == SDC_R1_IDLE_STATE); +                    if (rv != SDC_R1_READY) return SDC_ERR(rv); +                case SDC_R1_READY: +                    _type = SDC_TYPE_SDC1; +                    break; + +                default: +                    do { +                        rv = sdc_cmd(SEND_OP_COND, 0, 0, sdc_nto(start, timeout)); +                    } while (rv == SDC_R1_IDLE_STATE); +                    if (rv != SDC_R1_READY) return SDC_ERR(rv); +                    _type = SDC_TYPE_MMC; +                    break; + +            } +            break; + +        default: +            sdc_deselect(); +            return SDC_ERR(rv); +    } + +    if (_type && !_lba) { +        rv = sdc_cmd(SET_BLOCKLEN, 512, 0, sdc_nto(start, timeout)); +        if (rv != SDC_R1_READY) return SDC_ERR(rv); +    } +    *type = _type; +    *lba = _lba; +    return EOS_OK; +} + +#include <stdio.h> + +void eos_sdc_init(void) { +    uint8_t type, lba; +    int rv; + +    eos_spi_select(EOS_SPI_DEV_SDC); +    rv = sdc_init(5000, &type, &lba); +    if (rv) { +        printf("SDC ERROR\n"); +    } else { +        printf("SDC OK:%d %d\n", type, lba); +    } +    eos_spi_deselect(); +} diff --git a/fw/fe310/eos/sdcard.h b/fw/fe310/eos/sdcard.h new file mode 100644 index 0000000..a0a1ae3 --- /dev/null +++ b/fw/fe310/eos/sdcard.h @@ -0,0 +1,3 @@ +#include <stdint.h> + +void eos_sdc_init(void); diff --git a/fw/fe310/eos/spi.c b/fw/fe310/eos/spi.c index 2966ab9..c5e953e 100644 --- a/fw/fe310/eos/spi.c +++ b/fw/fe310/eos/spi.c @@ -69,7 +69,7 @@ void eos_spi_init(void) {      // SPI1_REG(SPI_REG_CSDEF) = 0xFFFF;  } -void eos_spi_start(uint8_t div, uint8_t csid, uint8_t cspin, unsigned char evt) { +void eos_spi_start(uint16_t div, uint8_t csid, uint8_t cspin, unsigned char evt) {      spi_state_flags = 0;      spi_evt = evt;      SPI1_REG(SPI_REG_SCKDIV) = div; @@ -77,8 +77,8 @@ void eos_spi_start(uint8_t div, uint8_t csid, uint8_t cspin, unsigned char evt)      if (csid != SPI_CSID_NONE) {          SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;      } else { -        SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF;          spi_cspin = cspin; +        SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF;      }      eos_intr_set_handler(INT_SPI1_BASE, eos_spi_handle_xchg);  } diff --git a/fw/fe310/eos/spi.h b/fw/fe310/eos/spi.h index 1463c66..06db0d0 100644 --- a/fw/fe310/eos/spi.h +++ b/fw/fe310/eos/spi.h @@ -11,7 +11,7 @@  #define EOS_SPI_MAX_EVT         2  void eos_spi_init(void); -void eos_spi_start(uint8_t div, uint8_t csid, uint8_t cspin, unsigned char evt); +void eos_spi_start(uint16_t div, uint8_t csid, uint8_t cspin, unsigned char evt);  void eos_spi_stop(void);  void eos_spi_set_handler(unsigned char evt, eos_evt_handler_t handler); diff --git a/fw/fe310/eos/timer.c b/fw/fe310/eos/timer.c index e07b9a6..d8cf107 100644 --- a/fw/fe310/eos/timer.c +++ b/fw/fe310/eos/timer.c @@ -129,3 +129,7 @@ uint64_t eos_time_get_tick(void) {      volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);      return *mtime;  } + +uint32_t eos_time_since(uint32_t start) { +    return (eos_time_get_tick() - start) * 1000 / EOS_TIMER_RTC_FREQ; + } diff --git a/fw/fe310/eos/timer.h b/fw/fe310/eos/timer.h index 2ac53f7..99ffa7a 100644 --- a/fw/fe310/eos/timer.h +++ b/fw/fe310/eos/timer.h @@ -20,3 +20,4 @@ void eos_timer_clear(unsigned char evt);  void eos_time_sleep(uint32_t msec);  uint64_t eos_time_get_tick(void); +uint32_t eos_time_since(uint32_t start);  | 
