o add mmc poc

This commit is contained in:
david 2009-02-12 23:14:24 +01:00
parent fce86ed33e
commit 1a59fe0036
9 changed files with 1702 additions and 0 deletions

446
poc/poc_mmc/Makefile Normal file
View File

@ -0,0 +1,446 @@
# Hey Emacs, this is a -*- makefile -*-
#
# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al.
# Released to the Public Domain
# Please read the make user manual!
#
# Additional material for this makefile was submitted by:
# Tim Henigan
# Peter Fleury
# Reiner Patommel
# Sander Pool
# Frederik Rouleau
# Markus Pfaff
#
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
#
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
# 4.07 or greater).
#
# make program = Download the hex file to the device, using avrdude. Please
# customize the avrdude settings below first!
#
# make filename.s = Just compile filename.c into the assembler code only
#
# To rebuild project do "make clean" then "make all".
#
# mth 2004/09
# Differences from WinAVR 20040720 sample:
# - DEPFLAGS according to Eric Weddingtion's fix (avrfreaks/gcc-forum)
# - F_OSC Define in CFLAGS and AFLAGS
# MCU name
MCU = atmega8
# Main Oscillator Frequency
# This is only used to define F_OSC in all assembler and c-sources.
F_OSC = 8000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = main
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c uart.c fat.c mmc.c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
#DEBUG = stabs
#DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS =
# Place -I options here
CINCS =
# Compiler flags.
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -DF_OSC=$(F_OSC)
CFLAGS += -DF_CPU=8000000UL
#CFLAGS += -DF_CPU=3686400UL
# Assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
ASFLAGS += -DF_OSC=$(F_OSC)
#Additional libraries.
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
PRINTF_LIB =
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
SCANF_LIB =
MATH_LIB = -lm
# External memory options
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
# Programming support using avrdude. Settings and variables.
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500v2
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = /dev/ttyUSB0 # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#
# Mega8 set to internal 4mhz
# avrdude -p atmega8 -P /dev/ttyUSB0 -c stk500v2 -U lfuse:w:0xe3:m
#
# ---------------------------------------------------------------------------
# Define directories, if needed.
DIRAVR = c:/winavr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Compiler flags to generate dependency files.
### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter finished end
build: elf hex eep lss sym
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
finished:
@echo $(MSG_ERRORS_NONE)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
flash_avrdude: flash
flash: $(TARGET).hex $(TARGET).eep
sudo $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
flash_uisp:
sudo uisp -dprog=avr910 -dpart=ATmega8 -dserial=/dev/ttyUSB0 --verify --erase -v --upload if=$(TARGET).hex
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list finished end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) .dep/*
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program

316
poc/poc_mmc/fat.c Normal file
View File

@ -0,0 +1,316 @@
/*#######################################################################################
FAT for AVR (MMC/SD)
Copyright (C) 2004 Ulrich Radig
Bei Fragen und Verbesserungen wendet euch per EMail an
mail@ulrichradig.de
oder im Forum meiner Web Page : www.ulrichradig.de
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
GNU General Public License, wie von der Free Software Foundation veröffentlicht,
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
(nach Ihrer Option) jeder späteren Version.
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
Programm erhalten haben.
Falls nicht, schreiben Sie an die Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#######################################################################################*/
#include "fat.h"
unsigned char cluster_size;
unsigned int fat_offset;
unsigned int cluster_offset;
unsigned int volume_boot_record_addr;
//############################################################################
//Auslesen Cluster Size der MMC/SD Karte und Speichern der größe ins EEprom
//Auslesen Cluster Offset der MMC/SD Karte und Speichern der größe ins EEprom
void fat_init (uint8_t *Buffer)
//############################################################################
{
struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
// unsigned char Buffer[BlockSize];
//volume_boot_record_addr = fat_addr (Buffer);
mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record
if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
{
FAT_DEBUG("MBR Signatur found!\r\n");
}
else
{
FAT_DEBUG("MBR Signatur not found!\r\n");
while(1);
}
volume_boot_record_addr = Buffer[VBR_ADDR] + (Buffer[VBR_ADDR+1] << 8);
mmc_read_sector (volume_boot_record_addr,Buffer);
if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
{
FAT_DEBUG("VBR Signatur found!\r\n");
}
else
{
FAT_DEBUG("VBR Signatur not found!\r\n");
volume_boot_record_addr = MASTER_BOOT_RECORD;//<- added by Hennie
mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record
}
bootp=(struct BootSec *)Buffer;
cluster_size = bootp->BPB_SecPerClus;
fat_offset = bootp->BPB_RsvdSecCnt;
cluster_offset = ((bootp->BPB_BytesPerSec * 32)/BlockSize);
cluster_offset += fat_root_dir_addr(Buffer);
}
//############################################################################
//Auslesen der Adresse des First Root Directory von Volume Boot Record
unsigned int fat_root_dir_addr (unsigned char *Buffer)
//############################################################################
{
struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
unsigned int FirstRootDirSecNum;
//auslesen des Volume Boot Record von der MMC/SD Karte
mmc_read_sector (volume_boot_record_addr,Buffer);
bootp=(struct BootSec *)Buffer;
//berechnet den ersten Sector des Root Directory
FirstRootDirSecNum = ( bootp->BPB_RsvdSecCnt +
(bootp->BPB_NumFATs * bootp->BPB_FATSz16));
FirstRootDirSecNum+= volume_boot_record_addr;
return(FirstRootDirSecNum);
}
//############################################################################
// Ausgabe des angegebenen Directory Eintrag in Entry_Count
// ist kein Eintrag vorhanden, ist der Eintrag im
// Rückgabe Cluster 0xFFFF. Es wird immer nur ein Eintrag ausgegeben
// um Speicherplatz zu sparen um es auch für kleine Atmels zu benutzen
unsigned int fat_read_dir_ent (unsigned int dir_cluster, //Angabe Dir Cluster
unsigned char Entry_Count, //Angabe welcher Direintrag
unsigned long *Size, //Rückgabe der File Größe
unsigned char *Dir_Attrib, //Rückgabe des Dir Attributs
unsigned char *Buffer) //Working Buffer
//############################################################################
{
unsigned char *pointer;
unsigned int TMP_Entry_Count = 0;
unsigned long Block = 0;
struct DirEntry *dir; //Zeiger auf einen Verzeichniseintrag
pointer = Buffer;
if (dir_cluster == 0)
{
Block = fat_root_dir_addr(Buffer);
}
else
{
//Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
//Berechnung welcher Cluster zu laden ist
//Auslesen der FAT - Tabelle
fat_load (dir_cluster,&Block,Buffer);
Block = ((Block-2) * cluster_size) + cluster_offset;
}
//auslesen des gesamten Root Directory
for (unsigned int blk = Block;;blk++)
{
mmc_read_sector (blk,Buffer); //Lesen eines Blocks des Root Directory
for (unsigned int a=0;a<BlockSize; a = a + 32)
{
dir=(struct DirEntry *)&Buffer[a]; //Zeiger auf aktuellen Verzeichniseintrag holen
if (dir->DIR_Name[0] == 0) //Kein weiterer Eintrag wenn erstes Zeichen des Namens 0 ist
{
return (0xFFFF);
}
//Prüfen ob es ein 8.3 Eintrag ist
//Das ist der Fall wenn es sich nicht um einen Eintrag für lange Dateinamen
//oder um einen als gelöscht markierten Eintrag handelt.
if ((dir->DIR_Attr != ATTR_LONG_NAME) &&
(dir->DIR_Name[0] != DIR_ENTRY_IS_FREE))
{
//Ist es der gewünschte Verzeichniseintrag
if (TMP_Entry_Count == Entry_Count)
{
//Speichern des Verzeichnis Eintrages in den Rückgabe Buffer
for(unsigned char b=0;b<11;b++)
{
if (dir->DIR_Name[b] != SPACE)
{
if (b == 8)
{
*pointer++= '.';
}
*pointer++=dir->DIR_Name[b];
}
}
*pointer++='\0';
*Dir_Attrib = dir->DIR_Attr;
//Speichern der Filegröße
*Size=dir->DIR_FileSize;
//Speichern des Clusters des Verzeichniseintrages
dir_cluster = dir->DIR_FstClusLO;
//Eintrag gefunden Rücksprung mit Cluster File Start
return(dir_cluster);
}
TMP_Entry_Count++;
}
}
}
return (0xFFFF); //Kein Eintrag mehr gefunden Rücksprung mit 0xFFFF
}
//############################################################################
// Auslesen der Cluster für ein File aus der FAT
// in den Buffer(512Byte). Bei einer 128MB MMC/SD
// Karte ist die Cluster größe normalerweise 16KB groß
// das bedeutet das File kann max. 4MByte groß sein.
// Bei größeren Files muß der Buffer größer definiert
// werden! (Ready)
// Cluster = Start Clusterangabe aus dem Directory
void fat_load ( unsigned int Cluster, //Angabe Startcluster
unsigned long *Block,
unsigned char *TMP_Buffer) //Workingbuffer
//############################################################################
{
//Zum Überprüfen ob der FAT Block schon geladen wurde
unsigned int FAT_Block_Store = 0;
//Byte Adresse innerhalb des Fat Blocks
unsigned int FAT_Byte_Addresse;
//FAT Block Adresse
unsigned int FAT_Block_Addresse;
//Berechnung für den ersten FAT Block (FAT Start Addresse)
for (unsigned int a = 0;;a++)
{
if (a == *Block)
{
*Block = (0x0000FFFF & Cluster);
return;
}
if (Cluster == 0xFFFF)
{
break; //Ist das Ende des Files erreicht Schleife beenden
}
//Berechnung des Bytes innerhalb des FAT Block´s
FAT_Byte_Addresse = (Cluster*2) % BlockSize;
//Berechnung des Blocks der gelesen werden muß
FAT_Block_Addresse = ((Cluster*2) / BlockSize) +
volume_boot_record_addr + fat_offset;
//Lesen des FAT Blocks
//Überprüfung ob dieser Block schon gelesen wurde
if (FAT_Block_Addresse != FAT_Block_Store)
{
FAT_Block_Store = FAT_Block_Addresse;
//Lesen des FAT Blocks
mmc_read_sector (FAT_Block_Addresse,TMP_Buffer);
}
//Lesen der nächsten Clusternummer
Cluster = (TMP_Buffer[FAT_Byte_Addresse + 1] << 8) +
TMP_Buffer[FAT_Byte_Addresse];
}
return;
}
//############################################################################
//Lesen eines 512Bytes Blocks von einem File
void fat_read_file (unsigned int Cluster,//Angabe des Startclusters vom File
unsigned char *Buffer, //Workingbuffer
unsigned long BlockCount) //Angabe welcher Bock vom File geladen
//werden soll a 512 Bytes
//############################################################################
{
//Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
//Berechnung welcher Cluster zu laden ist
unsigned long Block = (BlockCount/cluster_size);
//Auslesen der FAT - Tabelle
fat_load (Cluster,&Block,Buffer);
Block = ((Block-2) * cluster_size) + cluster_offset;
//Berechnung des Blocks innerhalb des Cluster
Block += (BlockCount % cluster_size);
//Read Data Block from Device
mmc_read_sector (Block,Buffer);
return;
}
//############################################################################
//Lesen eines 512Bytes Blocks von einem File
void fat_write_file (unsigned int cluster,//Angabe des Startclusters vom File
unsigned char *buffer, //Workingbuffer
unsigned long blockCount) //Angabe welcher Bock vom File gespeichert
//werden soll a 512 Bytes
//############################################################################
{
//Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
//Berechnung welcher Cluster zu speichern ist
unsigned char tmp_buffer[513];
unsigned long block = (blockCount/cluster_size);
//Auslesen der FAT - Tabelle
fat_load (cluster,&block,tmp_buffer);
block = ((block-2) * cluster_size) + cluster_offset;
//Berechnung des Blocks innerhalb des Cluster
block += (blockCount % cluster_size);
//Write Data Block to Device
mmc_write_sector (block,buffer);
return;
}
//####################################################################################
//Sucht ein File im Directory
unsigned char fat_search_file (unsigned char *File_Name, //Name des zu suchenden Files
unsigned int *Cluster, //Angabe Dir Cluster welches
//durchsucht werden soll
//und Rückgabe des clusters
//vom File welches gefunden
//wurde
unsigned long *Size, //Rückgabe der File Größe
unsigned char *Dir_Attrib,//Rückgabe des Dir Attributs
unsigned char *Buffer) //Working Buffer
//####################################################################################
{
unsigned int Dir_Cluster_Store = *Cluster;
for (unsigned char a = 0;a < 100;a++)
{
*Cluster = fat_read_dir_ent(Dir_Cluster_Store,a,Size,Dir_Attrib,Buffer);
if (*Cluster == 0xffff)
{
return(0); //File not Found
}
if(strcasecmp((char *)File_Name,(char *)Buffer) == 0)
{
return(1); //File Found
}
}
return(2); //Error
}

109
poc/poc_mmc/fat.h Normal file
View File

@ -0,0 +1,109 @@
/*#######################################################################################
Connect ARM to MMC/SD
Copyright (C) 2004 Ulrich Radig
#######################################################################################*/
#ifndef _FAT_H_
#define _FAT_H_
#include <string.h>
#include "mmc.h"
#include "uart.h"
#define FAT_DEBUG uart_puts
//#define FAT_DEBUG(...)
//Prototypes
extern unsigned int fat_root_dir_addr (unsigned char *);
extern unsigned int fat_read_dir_ent (unsigned int,unsigned char,unsigned long*,unsigned char *,unsigned char *);
extern void fat_load (unsigned int,unsigned long *,unsigned char *);
extern void fat_read_file (unsigned int,unsigned char *,unsigned long);
extern void fat_write_file (unsigned int,unsigned char *,unsigned long);
extern void fat_init (uint8_t *Buffer);
extern unsigned char fat_search_file (unsigned char *,unsigned int *,unsigned long *,unsigned char *,unsigned char *);
//Block Size in Bytes
#define BlockSize 512
//Master Boot Record
#define MASTER_BOOT_RECORD 0
//Volume Boot Record location in Master Boot Record
#define VBR_ADDR 0x1C6
//define ASCII
#define SPACE 0x20
#define DIR_ENTRY_IS_FREE 0xE5
#define FIRST_LONG_ENTRY 0x01
#define SECOND_LONG_ENTRY 0x42
//define DIR_Attr
#define ATTR_LONG_NAME 0x0F
#define ATTR_READ_ONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOLUME_ID 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
struct BootSec
{
unsigned char BS_jmpBoot[3];
unsigned char BS_OEMName[8];
unsigned int BPB_BytesPerSec; //2 bytes
unsigned char BPB_SecPerClus;
unsigned int BPB_RsvdSecCnt; //2 bytes
unsigned char BPB_NumFATs;
unsigned int BPB_RootEntCnt; //2 bytes
unsigned int BPB_TotSec16; //2 bytes
unsigned char BPB_Media;
unsigned int BPB_FATSz16; //2 bytes
unsigned int BPB_SecPerTrk; //2 bytes
unsigned int BPB_NumHeads; //2 bytes
unsigned long BPB_HiddSec; //4 bytes
unsigned long BPB_TotSec32; //4 bytes
};
//FAT12 and FAT16 Structure Starting at Offset 36
#define BS_DRVNUM 36
#define BS_RESERVED1 37
#define BS_BOOTSIG 38
#define BS_VOLID 39
#define BS_VOLLAB 43
#define BS_FILSYSTYPE 54
//FAT32 Structure Starting at Offset 36
#define BPB_FATSZ32 36
#define BPB_EXTFLAGS 40
#define BPB_FSVER 42
#define BPB_ROOTCLUS 44
#define BPB_FSINFO 48
#define BPB_BKBOOTSEC 50
#define BPB_RESERVED 52
#define FAT32_BS_DRVNUM 64
#define FAT32_BS_RESERVED1 65
#define FAT32_BS_BOOTSIG 66
#define FAT32_BS_VOLID 67
#define FAT32_BS_VOLLAB 71
#define FAT32_BS_FILSYSTYPE 82
//End of Boot Sctor and BPB Structure
struct DirEntry {
unsigned char DIR_Name[11]; //8 chars filename
unsigned char DIR_Attr; //file attributes RSHA, Longname, Drive Label, Directory
unsigned char DIR_NTRes; //set to zero
unsigned char DIR_CrtTimeTenth; //creation time part in milliseconds
unsigned int DIR_CrtTime; //creation time
unsigned int DIR_CrtDate; //creation date
unsigned int DIR_LastAccDate; //last access date
unsigned int DIR_FstClusHI; //first cluster high word
unsigned int DIR_WrtTime; //last write time
unsigned int DIR_WrtDate; //last write date
unsigned int DIR_FstClusLO; //first cluster low word
unsigned long DIR_FileSize;
};
#endif //_FAT_H_

228
poc/poc_mmc/main.c Normal file
View File

@ -0,0 +1,228 @@
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "uart.h"
#include "mmc.h"
#include "fat.h"
//SREG defines
#define S_MOSI PB3
#define S_MISO PB4
#define S_SCK PB5
#define S_LATCH PB2
//DEBUG defines
#define D_LED0 PC5
//SRAM defines
#define R_WR PB6
#define R_RD PB7
#define R_DATA PORTD
#define R_DIR DDRD
void SPI_MasterInit(void)
{
/* Set MOSI and SCK output, all others input */
DDRB |= ((1<<S_MOSI) | (1<<S_SCK) | (1<<S_LATCH));
DDRB &= ~(1<<S_MISO);
PORTB |= (1<<S_MISO);
/* Enable SPI, Master*/
SPCR = ((1<<SPE) | (1<<MSTR));
}
void SPI_MasterTransmit(unsigned char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)));
}
uint8_t SRAM_Read(uint32_t addr)
{
uint8_t byte;
DDRD=0x00;
PORTD=0xff;
PORTB |= (1<<R_RD);
PORTB |= (1<<R_WR);
SPI_MasterTransmit((uint8_t)(addr>>16));
SPI_MasterTransmit((uint8_t)(addr>>8));
SPI_MasterTransmit((uint8_t)(addr>>0));
PORTB |= (1<<S_LATCH);
PORTB &= ~(1<<S_LATCH);
PORTB &= ~(1<<R_RD);
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
byte = PIND;
PORTB |= (1<<R_RD);
DDRD=0x00;
PORTD=0x00;
return byte;
}
void SRAM_Write(uint32_t addr, uint8_t data)
{
DDRD=0xff;
PORTB |= (1<<R_RD);
PORTB |= (1<<R_WR);
SPI_MasterTransmit((uint8_t)(addr>>16));
SPI_MasterTransmit((uint8_t)(addr>>8));
SPI_MasterTransmit((uint8_t)(addr>>0));
PORTB |= (1<<S_LATCH);
PORTB &= ~(1<<S_LATCH);
PORTB &= ~(1<<R_WR);
PORTD=data;
PORTB |= (1<<R_WR);
DDRD=0x00;
PORTD=0x00;
}
int main(void)
{
uint8_t read, buf[10], i=0;
uint8_t Buffer[512];
uint16_t Clustervar;
uint8_t Dir_Attrib = 0;
uint32_t Size = 0;
DDRD=0x00;
PORTD=0x00;
DDRB |= ((1<<R_WR) | (1<<R_RD));
PORTB |= (1<<R_RD);
PORTB |= (1<<R_WR);
DDRC |= (1<<D_LED0);
uart_init();
SPI_MasterInit();
uart_puts("\n\r\n\rSPI_init!\n\r");
SRAM_Write(0x00000000,0x23);
SRAM_Write(0x00000001,0x42);
SRAM_Write(0x00000003,0xee);
//Initialisierung der MMC/SD-Karte ANFANG:
while ( mmc_init() !=0) //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
{
uart_puts("** Keine MMC/SD Karte gefunden!! **\n\r");
}
uart_puts("Karte gefunden!!\n\r");
fat_init(Buffer); //laden Cluster OFFSET und Size
//Initialisierung der MMC/SD-Karte ENDE!
mmc_read_csd (Buffer);
for (uint16_t tmp = 0;tmp<16;tmp++)
{
itoa(Buffer[tmp],buf,16);
uart_puts(buf);
}
Clustervar = 0;//suche im Root Verzeichnis
if (fat_search_file((unsigned char *)"rom.txt",&Clustervar,&Size,&Dir_Attrib,Buffer) == 1)
{
uart_puts("\r\n\r\n");
uart_puts("rom.txt:print and write to RAM:\r\n");
//Lese File und gibt es auf der seriellen Schnittstelle aus und schreibt es ins RAM
for (uint8_t b = 0;b<1;b++)
{
fat_read_file (Clustervar,Buffer,b);
for (uint8_t a = 0;a<50;a++)
{
SRAM_Write(0x00023420+a,Buffer[a]);
uart_putc(Buffer[a]);
}
}
}
for (uint8_t b=0;b<1;b++)
{
for(uint8_t a=0; a<50;a++)
{
uart_puts("\r\nRead RAM Addr 0x");
ltoa(0x00023420+a,buf,16);
uart_puts(buf);
uart_puts(": ");
uart_putc(SRAM_Read(0x00023420+a));
}
}
uart_puts("\r\n\r\n");
while(1){
i++;
uart_puts("\r\nDump RAM Addr 0x00000-0x00004: ");
read = SRAM_Read(0x00000000);
itoa(read,buf,16);
uart_puts(buf);
uart_putc(0x20);
read = SRAM_Read(0x00000001);
itoa(read,buf,16);
uart_puts(buf);
uart_putc(0x20);
read = SRAM_Read(0x00000002);
itoa(read,buf,16);
uart_puts(buf);
uart_putc(0x20);
read = SRAM_Read(0x00000003);
itoa(read,buf,16);
uart_puts(buf);
uart_putc(0x20);
read = SRAM_Read(0x00000004);
itoa(read,buf,16);
uart_puts(buf);
uart_putc(0x20);
if(i==2){
uart_puts("\r\nWriting 0xBE,0xEF to 0x00002-0x00003..");
SRAM_Write(0x00000002,0xBE);
SRAM_Write(0x00000003,0xEF);
}
if(i==3){
while(1);
}
}
return(0);
}

298
poc/poc_mmc/mmc.c Normal file
View File

@ -0,0 +1,298 @@
/*#######################################################################################
Connect AVR to MMC/SD
Copyright (C) 2004 Ulrich Radig
Bei Fragen und Verbesserungen wendet euch per EMail an
mail@ulrichradig.de
oder im Forum meiner Web Page : www.ulrichradig.de
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
GNU General Public License, wie von der Free Software Foundation veröffentlicht,
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
(nach Ihrer Option) jeder späteren Version.
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
Programm erhalten haben.
Falls nicht, schreiben Sie an die Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#######################################################################################*/
#include "mmc.h"
#include <util/delay.h>
//############################################################################
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
unsigned char mmc_init ()
//############################################################################
{
unsigned int Timeout = 0,i;
//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
DDRC |= ( (1<<MMC_DO) | (1<<MMC_CS) | (1<<MMC_CLK) );
DDRC &= ~(1<<MMC_DI);
PORTC |= ( (1<<MMC_DO) | (1<<MMC_DI) | (1<<MMC_CS) );
//Wartet eine kurze Zeit
_delay_ms(10);
//Initialisiere MMC/SD-Karte in den SPI-Mode
for(i=0; i<250; i++)
{
PORTC ^= (1<<MMC_CLK);
_delay_us(4);
}
PORTC &= ~(1<<MMC_CLK);
_delay_us(10);
PORTC &= ~(1<<MMC_CS);
_delay_us(3);
//Sendet Commando CMD0 an MMC/SD-Karte
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
while(mmc_write_command (CMD) !=1)
{
if (Timeout++ > 20)
{
MMC_Disable();
return(1); //Abbruch bei Commando1 (Return Code1)
}
}
//Sendet Commando CMD1 an MMC/SD-Karte
Timeout = 0;
CMD[0] = 0x41;//Commando 1
CMD[5] = 0xFF;
while( mmc_write_command (CMD) !=0)
{
if (Timeout++ > 800)
{
MMC_Disable();
return(9); //Abbruch bei Commando2 (Return Code2)
}
}
return(0);
}
//############################################################################
//Sendet ein Commando an die MMC/SD-Karte
unsigned char mmc_write_command (unsigned char *cmd)
//############################################################################
{
unsigned char tmp = 0xff;
unsigned int Timeout = 0;
//sendet 6 Byte Commando
for (unsigned char a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
{
mmc_write_byte(*cmd++);
}
//Wartet auf ein gültige Antwort von der MMC/SD-Karte
while (tmp == 0xff)
{
tmp = mmc_read_byte();
if (Timeout++ > 50)
{
break; //Abbruch da die MMC/SD-Karte nicht Antwortet
}
}
return(tmp);
}
//############################################################################
//Routine zum Empfangen eines Bytes von der MMC-Karte
unsigned char mmc_read_byte (void)
//############################################################################
{
uint8_t Byte=0,j;
for(j=0; j<8; j++){
Byte = (Byte<<1);
PORTC |= (1<<MMC_CLK);
_delay_us(4);
if(PINC & (1<<MMC_DI)){
Byte |= 1;
}
else{
Byte &= ~1;
}
PORTC &= ~(1<<MMC_CLK);
_delay_us(4);
}
return (Byte);
}
//############################################################################
//Routine zum Senden eines Bytes zur MMC-Karte
void mmc_write_byte (unsigned char Byte)
//############################################################################
{
uint8_t i;
for(i=0; i<8; i++){
if(Byte & 0x80){
PORTC |= (1<<MMC_DO);
}
else{
PORTC &= ~(1<<MMC_DO);
}
Byte = (Byte<<1);
PORTC |= (1<<MMC_CLK);
_delay_us(4);
PORTC &= ~(1<<MMC_CLK);
_delay_us(4);
}
PORTC |= (1<<MMC_DO);
}
//############################################################################
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
//############################################################################
{
unsigned char tmp;
//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingefügt*/
addr = addr << 9; //addr = addr * 512
cmd[1] = ((addr & 0xFF000000) >>24 );
cmd[2] = ((addr & 0x00FF0000) >>16 );
cmd[3] = ((addr & 0x0000FF00) >>8 );
//Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
tmp = mmc_write_command (cmd);
if (tmp != 0)
{
return(tmp);
}
//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
for (unsigned char a=0;a<100;a++)
{
mmc_read_byte();
}
//Sendet Start Byte an MMC/SD-Karte
mmc_write_byte(0xFE);
//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
for (unsigned int a=0;a<512;a++)
{
mmc_write_byte(*Buffer++);
}
//CRC-Byte schreiben
mmc_write_byte(0xFF); //Schreibt Dummy CRC
mmc_write_byte(0xFF); //CRC Code wird nicht benutzt
//Fehler beim schreiben? (Data Response XXX00101 = OK)
if((mmc_read_byte()&0x1F) != 0x05) return(1);
//Wartet auf MMC/SD-Karte Bussy
while (mmc_read_byte() != 0xff){};
return(0);
}
//############################################################################
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes)
//############################################################################
{
//Sendet Commando cmd an MMC/SD-Karte
if (mmc_write_command (cmd) != 0)
{
return;
}
//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
while (mmc_read_byte() != 0xfe){};
//Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
for (unsigned int a=0;a<Bytes;a++)
{
*Buffer++ = mmc_read_byte();
}
//CRC-Byte auslesen
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
return;
}
//############################################################################
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
//############################################################################
{
//Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingefügt*/
addr = addr << 9; //addr = addr * 512
cmd[1] = ((addr & 0xFF000000) >>24 );
cmd[2] = ((addr & 0x00FF0000) >>16 );
cmd[3] = ((addr & 0x0000FF00) >>8 );
mmc_read_block(cmd,Buffer,512);
return(0);
}
//############################################################################
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
unsigned char mmc_read_cid (unsigned char *Buffer)
//############################################################################
{
//Commando zum lesen des CID Registers
unsigned char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
mmc_read_block(cmd,Buffer,16);
return(0);
}
//############################################################################
//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
unsigned char mmc_read_csd (unsigned char *Buffer)
//############################################################################
{
//Commando zum lesen des CSD Registers
unsigned char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
mmc_read_block(cmd,Buffer,16);
return(0);
}

57
poc/poc_mmc/mmc.h Normal file
View File

@ -0,0 +1,57 @@
/*#######################################################################################
Connect ARM to MMC/SD
Copyright (C) 2004 Ulrich Radig
#######################################################################################*/
#ifndef _MMC_H_
#define _MMC_H_
#include <avr/io.h>
//#define SPI_Mode 1 //1 = Hardware SPI | 0 = Software SPI
#define SPI_Mode 0
#define MMC_Write PORTC //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_Read PINC
#define MMC_Direction_REG DDRC
#if defined (__AVR_ATmega8__)
#define MMC_CS PC0
#define MMC_DO PC1
#define MMC_DI PC2
#define MMC_CLK PC3
#define SPI_SS 4 //Nicht Benutz muß aber definiert werden
#endif
//Prototypes
extern unsigned char mmc_read_byte(void);
extern void mmc_write_byte(unsigned char);
extern void mmc_read_block(unsigned char *,unsigned char *,unsigned in);
extern unsigned char mmc_init(void);
extern unsigned char mmc_read_sector (unsigned long,unsigned char *);
extern unsigned char mmc_write_sector (unsigned long,unsigned char *);
extern unsigned char mmc_write_command (unsigned char *);
extern unsigned char mmc_read_csd (unsigned char *);
extern unsigned char mmc_read_cid (unsigned char *);
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
#define MMC_Disable() MMC_Write|= (1<<MMC_CS);
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
#define MMC_Enable() MMC_Write&=~(1<<MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif //_MMC_H_

2
poc/poc_mmc/notes Normal file
View File

@ -0,0 +1,2 @@
#uisp -dprog=avr910 -dpart=ATmega8 -dserial=/dev/ttyUSB0 --rd_fuses
#uisp -dprog=avr910 -dpart=ATmega8 -dserial=/dev/ttyUSB0 --erase --verify -v --upload if=blinky.hex

223
poc/poc_mmc/uart.c Normal file
View File

@ -0,0 +1,223 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#ifndef SIGNAL
#include <avr/signal.h>
#endif // SIGNAL
#include "uart.h"
// Folgende Zeile einkommentieren, falls FIFO verwendet werden soll
// #include "fifo.h"
#define BAUDRATE 9600
#define F_CPU 8000000
#define nop() __asm volatile ("nop")
#ifdef SUART_TXD
#define SUART_TXD_PORT PORTB
#define SUART_TXD_DDR DDRB
#define SUART_TXD_BIT PB1
static volatile uint16_t outframe;
#endif // SUART_TXD
#ifdef SUART_RXD
#define SUART_RXD_PORT PORTB
#define SUART_RXD_PIN PINB
#define SUART_RXD_DDR DDRB
#define SUART_RXD_BIT PB0
static volatile uint16_t inframe;
static volatile uint8_t inbits, received;
#ifdef _FIFO_H_
#define INBUF_SIZE 4
static uint8_t inbuf[INBUF_SIZE];
fifo_t infifo;
#else // _FIFO_H_
static volatile uint8_t indata;
#endif // _FIFO_H_
#endif // SUART_RXD
// Initialisierung für einen ATmega8
// Für andere AVR-Derivate sieht dies vermutlich anders aus:
// Registernamen ändern sich (zB TIMSK0 anstatt TIMSK, etc).
void uart_init()
{
uint8_t tifr = 0;
uint8_t sreg = SREG;
cli();
// Mode #4 für Timer1
// und volle MCU clock
// IC Noise Cancel
// IC on Falling Edge
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS10) | (0 << ICES1) | (1 << ICNC1);
// OutputCompare für gewünschte Timer1 Frequenz
OCR1A = (uint16_t) ((uint32_t) F_CPU/BAUDRATE);
#ifdef SUART_RXD
SUART_RXD_DDR &= ~(1 << SUART_RXD_BIT);
SUART_RXD_PORT |= (1 << SUART_RXD_BIT);
TIMSK |= (1 << TICIE1);
tifr |= (1 << ICF1) | (1 << OCF1B);
#else
TIMSK &= ~(1 << TICIE1);
#endif // SUART_RXD
#ifdef SUART_TXD
tifr |= (1 << OCF1A);
SUART_TXD_PORT |= (1 << SUART_TXD_BIT);
SUART_TXD_DDR |= (1 << SUART_TXD_BIT);
outframe = 0;
#endif // SUART_TXD
TIFR = tifr;
SREG = sreg;
}
#ifdef SUART_TXD
void uart_putc (uint8_t c)
{
do
{
sei(); nop(); cli(); // yield();
} while (outframe);
// frame = *.P.7.6.5.4.3.2.1.0.S S=Start(0), P=Stop(1), *=Endemarke(1)
outframe = (3 << 9) | (((uint8_t) c) << 1);
TIMSK |= (1 << OCIE1A);
TIFR = (1 << OCF1A);
sei();
}
void uart_puts (uint8_t *buf)
{
while( *buf )
uart_putc ( *buf++ );
}
#endif // SUART_TXD
#ifdef SUART_TXD
SIGNAL (SIG_OUTPUT_COMPARE1A)
{
uint16_t data = outframe;
if (data & 1) SUART_TXD_PORT |= (1 << SUART_TXD_BIT);
else SUART_TXD_PORT &= ~(1 << SUART_TXD_BIT);
if (1 == data)
{
TIMSK &= ~(1 << OCIE1A);
}
outframe = data >> 1;
}
#endif // SUART_TXD
#ifdef SUART_RXD
SIGNAL (SIG_INPUT_CAPTURE1)
{
uint16_t icr1 = ICR1;
uint16_t ocr1a = OCR1A;
// Eine halbe Bitzeit zu ICR1 addieren (modulo OCR1A) und nach OCR1B
uint16_t ocr1b = icr1 + ocr1a/2;
if (ocr1b >= ocr1a)
ocr1b -= ocr1a;
OCR1B = ocr1b;
TIFR = (1 << OCF1B);
TIMSK = (TIMSK & ~(1 << TICIE1)) | (1 << OCIE1B);
inframe = 0;
inbits = 0;
}
#endif // SUART_RXD
#ifdef SUART_RXD
SIGNAL (SIG_OUTPUT_COMPARE1B)
{
uint16_t data = inframe >> 1;
if (SUART_RXD_PIN & (1 << SUART_RXD_BIT))
data |= (1 << 9);
uint8_t bits = inbits+1;
if (10 == bits)
{
if ((data & 1) == 0)
if (data >= (1 << 9))
{
#ifdef _FIFO_H_
_inline_fifo_put (&infifo, data >> 1);
#else
indata = data >> 1;
#endif // _FIFO_H_
received = 1;
}
TIMSK = (TIMSK & ~(1 << OCIE1B)) | (1 << TICIE1);
TIFR = (1 << ICF1);
}
else
{
inbits = bits;
inframe = data;
}
}
#endif // SUART_RXD
#ifdef SUART_RXD
#ifdef _FIFO_H_
uint8_t uart_getc_wait()
{
return (int) fifo_get_wait (&infifo);
}
int uart_getc_nowait()
{
return fifo_get_nowait (&infifo);
}
#else // _FIFO_H_
uint8_t uart_getc_wait()
{
while (!received) {}
received = 0;
return (uint8_t) indata;
}
uint8_t uart_getc_nowait()
{
if (received)
{
received = 0;
return (uint8_t) indata;
}
return -1;
}
#endif // _FIFO_H_
#endif // SUART_RXD

23
poc/poc_mmc/uart.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _UART_H_
#define _UART_H_
#define SUART_TXD
#define SUART_RXD
#include <avr/io.h>
#include <stdio.h>
void uart_init();
#ifdef SUART_TXD
void uart_putc(uint8_t byte);
void uart_puts(uint8_t *buf);
#endif // SUART_RXD
#ifdef SUART_RXD
uint8_t uart_getc_wait();
uint8_t uart_getc_nowait();
#endif // SUART_RXD
#endif /* _UART_H_ */