From a1c7a948d2518f79ce49fd2450733f5f956d9331 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Tue, 4 Dec 2012 10:52:15 -0300 Subject: [PATCH] tornado/fw/: add MMC driver (WIP, based on Mass Storage for V-USB by "lleeloo") --- tornado/fw/Makefile | 2 +- tornado/fw/mmc-hw.c | 55 ++++++++++++ tornado/fw/mmc-hw.h | 27 ++++++ tornado/fw/mmc.c | 211 ++++++++++++++++++++++++++++++++++++++++++++ tornado/fw/mmc.h | 35 ++++++++ 5 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 tornado/fw/mmc-hw.c create mode 100644 tornado/fw/mmc-hw.h create mode 100644 tornado/fw/mmc.c create mode 100644 tornado/fw/mmc.h diff --git a/tornado/fw/Makefile b/tornado/fw/Makefile index d370d1a..ca23c49 100644 --- a/tornado/fw/Makefile +++ b/tornado/fw/Makefile @@ -31,7 +31,7 @@ OBJCOPY = $(AVR_PREFIX)objcopy #OBJDUMP = $(AVR_PREFIX)objdump SIZE = $(AVR_PREFIX)size -OBJS = $(NAME).o accel.o led.o $(COMMON_OBJS) +OBJS = $(NAME).o accel.o led.o mmc.o mmc-hw.o $(COMMON_OBJS) BOOT_OBJS = boot.o $(COMMON_OBJS) COMMON_OBJS = diff --git a/tornado/fw/mmc-hw.c b/tornado/fw/mmc-hw.c new file mode 100644 index 0000000..f638942 --- /dev/null +++ b/tornado/fw/mmc-hw.c @@ -0,0 +1,55 @@ +/* + * fw/mmc-hw.c - MMC hardware interface + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include + +#include "io.h" +#include "mmc-hw.h" + + +void mmc_select(void) +{ +// CS = 0; +} + +void mmc_deselect(void) +{ +// CS = 1; +} + + +uint8_t mmc_recv(void) +{ +// MSB first + return 0; +} + + +void mmc_send(uint8_t v) +{ +// MSB first +} + + +void mmc_activate(void) +{ +// set pull-ups +// VDD = 1; +} + + +void mmc_deactivate(void) +{ +// set directions +// VDD = 0; +} diff --git a/tornado/fw/mmc-hw.h b/tornado/fw/mmc-hw.h new file mode 100644 index 0000000..06b4f33 --- /dev/null +++ b/tornado/fw/mmc-hw.h @@ -0,0 +1,27 @@ +/* + * fw/mmc-hw.h - MMC hardware interface + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef MMC_HW_H +#define MMC_HW_H + +#include + + +void mmc_select(void); +void mmc_deselect(void); +uint8_t mmc_recv(void); +void mmc_send(uint8_t v); +void mmc_activate(void); +void mmc_deactivate(void); + +#endif /* !MMC_HW_H */ diff --git a/tornado/fw/mmc.c b/tornado/fw/mmc.c new file mode 100644 index 0000000..fed6100 --- /dev/null +++ b/tornado/fw/mmc.c @@ -0,0 +1,211 @@ +/* + * fw/mmc.c - MMC card access + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* + * Heavily influenced by the MMC driver in the Mass Storage for V-USB project + * by "lleeloo": + * http://we.easyelectronics.ru/AVR/usb-fleshka-na-atmega8-i-v-usb-ot-idei-k-gotovomu-ustroystvu.html + */ + +#include +#include + +#include "mmc-hw.h" +#include "mmc.h" + + +/* Command indices */ + +enum { + MMC_GO_IDLE_STATE = 0, + MMC_SEND_OP_COND = 1, + MMC_SET_BLOCKLEN = 16, + MMC_READ_SINGLE_BLOCK = 17, + MMC_WRITE_BLOCK = 24, +}; + + +/* Start block tokens */ + +enum { + MMC_START_SINGLE_BLOCK = 0xfe, +}; + + +static void mmc_begin(void) +{ + mmc_select(); +} + + +static void mmc_end(void) +{ + mmc_send(0xff); + mmc_send(0xff); + mmc_deselect(); + mmc_send(0xff); +} + +static void mmc_command(uint8_t cmd, uint32_t arg) +{ + mmc_send(0x40 | cmd); /* start (0)+transmission(1)+cmd */ + mmc_send(arg >> 24); + mmc_send(arg >> 16); + mmc_send(arg >> 8); + mmc_send(arg); + mmc_send(0x95); /* crc7+end(1) */ +} + + +static uint8_t mmc_r1(void) +{ + uint8_t v, tries = 0xff; + + do v = mmc_read(); + while ((v & 0x80) && --tries); + return v; +} + + +static void mmc_wait(void) +{ + uint8_t v, tries = 0xff; + + do { + v = mmc_read(); + if (v == MMC_START_SINGLE_BLOCK) + return; + } + while (--tries); +} + + +bool mmc_begin_read(uint32_t sector) +{ + mmc_begin(); + mmc_command(MMC_READ_SINGLE_BLOCK, sector); + if (mmc_r1()) { + mmc_end(); + return 0; + } else { + mmc_wait(); + return 1; + } +} + + +uint8_t mmc_read(void) +{ + return mmc_recv(); +} + + +bool mmc_end_read(void) +{ + mmc_end(); + return 1; +} + + +bool mmc_begin_write(uint32_t sector) +{ + mmc_begin(); + mmc_command(MMC_WRITE_BLOCK, sector); + if (mmc_r1()) { + mmc_end(); + return 0; + } else { + mmc_send(0xff); + mmc_send(0xff); + mmc_send(MMC_START_SINGLE_BLOCK); + return 1; + } +} + + +void mmc_write(uint8_t data) +{ + mmc_send(data); +} + + +bool mmc_end_write(void) +{ + mmc_send(0xff); + mmc_send(0xff); + mmc_recv(); + while (!mmc_recv()); + mmc_end(); + return 1; +} + + +void mmc_off(void) +{ + mmc_deactivate(); +} + + +static void send_clock(void) +{ + uint8_t i; + + for (i = 0; i != 10; i++) + mmc_send(0xff); +} + + +bool mmc_init(void) +{ + uint16_t tries = 0xff; + uint8_t res; + + mmc_activate(); + send_clock(); + mmc_begin(); + + do { + mmc_command(MMC_GO_IDLE_STATE, 0); + if (mmc_r1() == 0x01) /* in idle state */ + break; + } + while (--tries); + mmc_end(); + if (!tries) + return 0; + + send_clock(); + + tries = 0x7ff; + do { + mmc_select(); + mmc_command(MMC_SEND_OP_COND, 0); + res = mmc_r1(); + mmc_deselect(); + send_clock(); + } + while (res && --tries); + + mmc_end(); + + if (res) { + mmc_deactivate(); + return 0; + } + + mmc_begin(); + mmc_command(MMC_SET_BLOCKLEN, MMC_BLOCK); + mmc_r1(); + mmc_end(); + + return 1; +} diff --git a/tornado/fw/mmc.h b/tornado/fw/mmc.h new file mode 100644 index 0000000..dd03a5d --- /dev/null +++ b/tornado/fw/mmc.h @@ -0,0 +1,35 @@ +/* + * fw/mmc.h - MMC card access + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef MMC_H +#define MMC_H + +#include +#include + + +#define MMC_BLOCK 512 + + +bool mmc_begin_read(uint32_t sector); +uint8_t mmc_read(void); +bool mmc_end_read(void); + +bool mmc_begin_write(uint32_t sector); +void mmc_write(uint8_t data); +bool mmc_end_write(void); + +void mmc_off(void); +bool mmc_init(void); + +#endif /* !MMC_H */