mirror of
git://projects.qi-hardware.com/antorcha.git
synced 2024-11-22 11:56:14 +02:00
tornado/fw/: add MMC driver (WIP, based on Mass Storage for V-USB by "lleeloo")
This commit is contained in:
parent
f3c22bc6ab
commit
a1c7a948d2
@ -31,7 +31,7 @@ OBJCOPY = $(AVR_PREFIX)objcopy
|
|||||||
#OBJDUMP = $(AVR_PREFIX)objdump
|
#OBJDUMP = $(AVR_PREFIX)objdump
|
||||||
SIZE = $(AVR_PREFIX)size
|
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)
|
BOOT_OBJS = boot.o $(COMMON_OBJS)
|
||||||
COMMON_OBJS =
|
COMMON_OBJS =
|
||||||
|
|
||||||
|
55
tornado/fw/mmc-hw.c
Normal file
55
tornado/fw/mmc-hw.c
Normal 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
27
tornado/fw/mmc-hw.h
Normal 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
211
tornado/fw/mmc.c
Normal 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
35
tornado/fw/mmc.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user