1
0
mirror of git://projects.qi-hardware.com/antorcha.git synced 2024-12-22 18:34:14 +02:00

tornado/fw/: add MMC driver (WIP, based on Mass Storage for V-USB by "lleeloo")

This commit is contained in:
Werner Almesberger 2012-12-04 10:52:15 -03:00
parent f3c22bc6ab
commit a1c7a948d2
5 changed files with 329 additions and 1 deletions

View File

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

55
tornado/fw/mmc-hw.c Normal file
View File

@ -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 <stdint.h>
#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;
}

27
tornado/fw/mmc-hw.h Normal file
View File

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

211
tornado/fw/mmc.c Normal file
View File

@ -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 <stdbool.h>
#include <stdint.h>
#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;
}

35
tornado/fw/mmc.h Normal file
View File

@ -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 <stdbool.h>
#include <stdint.h>
#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 */