mirror of
git://projects.qi-hardware.com/antorcha.git
synced 2024-11-25 06:11:53 +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
|
||||
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
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