32 Commits
sdcard ... mmc

Author SHA1 Message Date
optixx
23efb8da74 change project 2009-08-24 20:27:28 +02:00
David Voswinkel
dade0ea275 add test dir loop 2009-08-18 09:11:07 +02:00
David Voswinkel
6edd54b092 switch file id to 32bit and get sram push working 2009-08-18 08:38:48 +02:00
David Voswinkel
dc8ed94279 add dir entry debug dump 2009-08-17 22:05:05 +02:00
David Voswinkel
7046230e31 push dir entry to sram 2009-08-17 21:44:38 +02:00
David Voswinkel
ed0a95cad5 fix file_entry struct 2009-08-17 20:39:38 +02:00
David Voswinkel
31768e2a41 Merge branch 'mmc' of git@github.com:optixx/quickdev16 into mmc 2009-08-12 21:19:18 +02:00
optixx
041cf089ad add header 2009-08-12 18:04:54 +02:00
optixx
cf090451df add dir ent to sram copy 2009-08-11 15:42:14 +02:00
David Voswinkel
51876b83ad cleanup 2009-08-10 19:46:45 +02:00
David Voswinkel
8d961dc446 Merge branch 'mmc' of git@github.com:optixx/quickdev16 into mmc
Conflicts:
	avr/usbload/fat.h
	avr/usbload/file.c
	avr/usbload/testing.c
2009-08-10 19:44:15 +02:00
David Voswinkel
9859b1fbc8 cleanup types: 2009-08-10 19:34:03 +02:00
David Voswinkel
8656beb769 code cleanup 2009-08-10 19:26:01 +02:00
optixx
f1f836bdc7 disable file write function and save 4kb progmem 2009-08-10 16:29:36 +02:00
David Voswinkel
4a0740dd02 replace mmc layer with old software spi stuff 2009-08-09 14:19:32 +02:00
David Voswinkel
d095867fe4 try to use irq for CS and use dedicated SS for hardware SPI 2009-08-09 13:12:44 +02:00
David Voswinkel
2aee210d13 switch to mmc-0.5.4 2009-08-09 12:15:06 +02:00
David Voswinkel
a27521b22b first tests 2009-08-09 10:37:51 +02:00
David Voswinkel
2132b572ff add mmc layer 2009-08-08 16:43:51 +02:00
David Voswinkel
dbff180a91 get sram restore working and make the switch to quickdev loader more
mature
2009-08-08 16:04:45 +02:00
David Voswinkel
df167b285e Merge branch 'master' of git@github.com:optixx/quickdev16 2009-08-08 15:06:35 +02:00
David Voswinkel
cd7ac81a2d add debug shm 2009-08-06 22:04:08 +02:00
David Voswinkel
f7dc5b3bd8 add upload progress 2009-08-06 22:03:50 +02:00
David Voswinkel
1f68465dc6 simplify mode swicthing 2009-08-06 21:26:16 +02:00
David Voswinkel
5e5df7e275 remove obsolte slow sram functions and depending higherlevel stuff 2009-08-06 21:25:24 +02:00
David Voswinkel
ba2ac254a7 remove sram_copy and sram_set 2009-08-06 21:18:11 +02:00
David Voswinkel
1282e93334 refactor testing code 2009-08-06 21:16:58 +02:00
David Voswinkel
decb810bcc move commands to own file and remove unsed usb methods 2009-08-06 21:10:25 +02:00
David Voswinkel
b6d5d1b571 add delya/irq switch for shared mem 2009-08-06 20:44:44 +02:00
optixx
406c884cfe add addr save and restore functions 2009-08-06 12:15:04 +02:00
optixx
6ef9989320 add sharedmem read 2009-08-06 11:22:14 +02:00
optixx
97962b8e89 split shared memroy access into tx and rx section 2009-08-06 10:52:44 +02:00
27 changed files with 2597 additions and 719 deletions

View File

@@ -30,11 +30,16 @@ SIZE = avr-size
ifeq ($(DEBUG),1) ifeq ($(DEBUG),1)
LDFLAGS = -Wl,-u,vfprintf -lprintf_flt LDFLAGS = -Wl,-u,vfprintf -lprintf_flt
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o mmc.o fat.o OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \
main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o \
dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o \
command.o mmc.o fat.o file.o dir.o testing.o
else else
LDFLAGS = -Wl,-u LDFLAGS = -Wl,-u
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o \
uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o \
info.o shared_memory.o command.o
endif endif
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE) COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)

61
avr/usbload/command.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "config.h"
#include "requests.h"
#include "sram.h"
#include "info.h"
extern uint32_t req_bank_size;
void send_reset()
{
info("Reset Snes\n");
snes_reset_on();
snes_reset_lo();
_delay_ms(2);
snes_reset_hi();
snes_reset_off();
}
void send_irq()
{
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
}
void set_rom_mode()
{
if (req_bank_size == 0x8000) {
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
}

29
avr/usbload/command.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __COMMAND_H__
#define __COMMAND_H__
void send_reset();
void send_irq();
void set_rom_mode();
#endif

View File

@@ -27,8 +27,9 @@
#define DEBUG_USB_TRANS 4 #define DEBUG_USB_TRANS 4
#define DEBUG_SRAM 8 #define DEBUG_SRAM 8
#define DEBUG_SRAM_RAW 16 #define DEBUG_SRAM_RAW 16
#define DEBUG_SREG 32 #define DEBUG_FAT 32
#define DEBUG_CRC 64 #define DEBUG_CRC 64
#define DEBUG_SHM 128
#define REQ_STATUS_IDLE 0x01 #define REQ_STATUS_IDLE 0x01
#define REQ_STATUS_UPLOAD 0x02 #define REQ_STATUS_UPLOAD 0x02

View File

@@ -91,31 +91,13 @@ uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr, uint32_t
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint32_t bank_size,uint8_t *buffer)
{
uint16_t crc = 0;
uint32_t addr;
uint8_t req_bank = 0;
for (addr = bottom_addr; addr < top_addr; addr += TRANSFER_BUFFER_SIZE) {
if (addr && addr % bank_size == 0) {
debug(DEBUG_CRC,"crc_check_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
req_bank,addr,crc);
req_bank++;
crc = 0;
}
sram_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
}
}
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer) uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer)
{ {
uint16_t crc = 0; uint16_t crc = 0;
uint32_t addr; uint32_t addr;
for (addr = start_addr; addr < start_addr + size; addr += TRANSFER_BUFFER_SIZE) { for (addr = start_addr; addr < start_addr + size; addr += TRANSFER_BUFFER_SIZE) {
sram_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE); sram_bulk_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE); crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
} }
return crc; return crc;

View File

@@ -29,7 +29,6 @@
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data); uint16_t crc_xmodem_update(uint16_t crc, uint8_t data);
uint16_t do_crc(uint8_t * data,uint16_t size); uint16_t do_crc(uint8_t * data,uint16_t size);
uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size); uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size);
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint32_t bank_size,uint8_t *buffer);
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer); uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer);
uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t bank_size,uint32_t top_addr); uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t bank_size,uint32_t top_addr);

96
avr/usbload/dir.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include "dir.h"
#include "file.h"
#include "fat.h"
#include "debug.h"
#include "sram.h"
#include "config.h"
#include <string.h>
uint16_t position = 0;
extern struct File file;
void dir_entry_start(){
position = 0;
}
void dir_entry_dump(uint32_t addr, dir_ent_t* ent){
debug(DEBUG_FAT,"dir_entry_dump: addr=0x%06lx id=%li name=%s size=%li attr=%i\n", addr, ent->id, ent->file_name,
ent->file_size, ent->file_attr);
}
void dir_entry_add(uint32_t id, uint8_t* file_name,uint32_t file_size,uint8_t file_attr){
uint32_t addr;
dir_ent_t ent;
strncpy(ent.file_name,file_name,13);
ent.id = id;
ent.file_size = file_size;
ent.file_attr = file_attr;
addr = DIR_ENTRY_LOC + (position << DIR_ENTRY_SIZE_SHIFT );
sram_bulk_copy(addr, (uint8_t *) &ent, DIR_ENTRY_SIZE );
dir_entry_dump(addr, &ent);
position++;
}
void dir_entry_header(uint16_t idx, uint8_t * header){
uint32_t addr;
addr = DIR_ENTRY_LOC + ( idx << DIR_ENTRY_SIZE_SHIFT ) + DIR_ENTRY_HEADER_OFF;
sram_bulk_copy(addr, (uint8_t *) header, DIR_ENTRY_HEADER_SIZE);
}
uint32_t dir_entry_get(uint32_t idx, dir_ent_t* ent){
uint32_t addr;
addr = DIR_ENTRY_LOC + ( idx << DIR_ENTRY_SIZE_SHIFT );
sram_bulk_read_buffer( addr, (uint8_t *) ent, DIR_ENTRY_SIZE);
return addr;
}
void dir_entry_loop(){
uint8_t i;
uint8_t j;
uint32_t addr;
dir_ent_t ent;
for (i=0; i< position; i++){
addr = dir_entry_get(i,&ent);
dir_entry_dump(addr,&ent);
ffopen( ent.file_name );
if (file.length != 524288){
ffclose();
continue;
}
//ffseek(0x7fc0);
for (j=0; j< 64; j++)
printf ("0x%02x " ,ffread());
printf("\n");
ffclose();
}
}

64
avr/usbload/dir.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __DIR_H__
#define __DIR_H__
#include <stdlib.h>
#include <stdint.h>
#define DIR_ENTRY_LOC 0x010000
#define DIR_ENTRY_SIZE 64
#define DIR_ENTRY_SIZE_SHIFT 6
#define DIR_ENTRY_HEADER_SIZE 44
#define DIR_ENTRY_HEADER_OFF 20
typedef struct {
uint32_t id; // 4
uint8_t file_name[13]; // 8.3 = 12 + 1 = 13
uint32_t file_size; // 4
uint8_t file_attr; // 1
uint8_t snes_header[41]; // 41
} dir_ent_t; // 64
void dir_entry_start();
void dir_entry_add(uint32_t id, uint8_t* file_name,uint32_t file_size,uint8_t file_attr);
void dir_entry_header(uint16_t position, uint8_t * header);
/*
lo:
0x7fc0
0x7fc0 + 0x200
hi:
0xffc0
0xffc0 + 0x200
emulated reset vector MSB must be set
sei
clc
xce
*/
#endif

View File

@@ -1,192 +1,668 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "fat.h" #include "fat.h"
#include "file.h"
#include "mmc.h"
#include "config.h"
uint8_t cluster_size; struct Fat fat; // wichtige daten/variablen der fat
uint16_t fat_offset; struct File file; // wichtige dateibezogene daten/variablen
uint16_t cluster_offset;
uint16_t volume_boot_record_addr;
void fat_init(uint8_t * Buffer)
#if (WRITE==1)
// ***************************************************************************************************************
// schreibt sektor nummer:sec auf die karte (puffer:sector) !!
// setzt bufferFlag=0 da puffer nicht dirty sein kann nach schreiben !
// ***************************************************************************************************************
uint8_t fat_writeSector(uint32_t sec)
{ {
struct BootSec *bootp;
mmc_read_sector(MASTER_BOOT_RECORD, Buffer);
if (Buffer[510] == 0x55 && Buffer[511] == 0xAA) {
FAT_DEBUG("MBR Signatur found!\r\n");
}
else { fat.bufferDirty = 0; // buffer kann nicht dirty sein weil wird geschrieben
FAT_DEBUG("MBR Signatur not found!\r\n"); return (mmc_write_sector(sec, fat.sector)); // schreiben von sektor puffer
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;
mmc_read_sector(MASTER_BOOT_RECORD, Buffer);
}
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);
} }
uint16_t fat_root_dir_addr(uint8_t * Buffer) #endif
// ***************************************************************************************************************
// umrechnung cluster auf 1.sektor des clusters (möglicherweise mehrere sektoren/cluster) !
// ***************************************************************************************************************
uint32_t fat_clustToSec(uint32_t clust)
{ {
struct BootSec *bootp;
uint16_t FirstRootDirSecNum;
return (fat.dataDirSec + 2 + ((clust - 2) * fat.secPerClust)); // errechnet den 1. sektor der sektoren des clusters
}
mmc_read_sector(volume_boot_record_addr, Buffer); // ***************************************************************************************************************
bootp = (struct BootSec *) Buffer; // umrechnung sektor auf cluster (nicht die position im cluster selber!!)
// ***************************************************************************************************************
uint32_t fat_secToClust(uint32_t sec)
{
return ((sec - fat.dataDirSec - 2 + 2 * fat.secPerClust) / fat.secPerClust); // umkerhrfunktion von fat_clustToSec
FirstRootDirSecNum = (bootp->BPB_RsvdSecCnt +
(bootp->BPB_NumFATs * bootp->BPB_FATSz16));
FirstRootDirSecNum += volume_boot_record_addr;
return (FirstRootDirSecNum);
} }
uint16_t fat_read_dir_ent(uint16_t dir_cluster, // ***************************************************************************************************************
uint8_t Entry_Count, // läd sektor:sec auf puffer:sector zum bearbeiten im ram !
uint32_t * Size, // setzt currentSectorNr auf richtigen wert (also den sektor der gepuffert ist). es wird geprüft
uint8_t * Dir_Attrib, uint8_t * Buffer) // ob der gepufferte sektor geändert wurde, wenn ja muss erst geschrieben werden, um diese daten nicht zu verlieren !
{ // ***************************************************************************************************************
uint8_t *pointer; uint8_t fat_loadSector(uint32_t sec)
uint16_t TMP_Entry_Count = 0;
uint32_t Block = 0;
struct DirEntry *dir;
uint16_t blk;
uint16_t a;
uint8_t b;
pointer = Buffer;
if (dir_cluster == 0) {
Block = fat_root_dir_addr(Buffer);
}
else {
fat_load(dir_cluster, &Block, Buffer);
Block = ((Block - 2) * cluster_size) + cluster_offset;
}
for (blk = Block;; blk++) {
mmc_read_sector(blk, Buffer);
for (a = 0; a < BlockSize; a = a + 32) {
dir = (struct DirEntry *) &Buffer[a];
if (dir->DIR_Name[0] == 0) {
return (0xFFFF);
}
if ((dir->DIR_Attr != ATTR_LONG_NAME) &&
(dir->DIR_Name[0] != DIR_ENTRY_IS_FREE)) {
if (TMP_Entry_Count == Entry_Count) {
for (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;
*Size = dir->DIR_FileSize;
dir_cluster = dir->DIR_FstClusLO;
return (dir_cluster);
}
TMP_Entry_Count++;
}
}
}
return (0xFFFF);
}
void fat_load(uint16_t Cluster, uint32_t * Block, uint8_t * TMP_Buffer)
{
uint16_t FAT_Block_Store = 0;
uint16_t FAT_Byte_Addresse;
uint16_t FAT_Block_Addresse;
uint16_t a;
for (a = 0;; a++) {
if (a == *Block) {
*Block = (0x0000FFFF & Cluster);
return;
}
if (Cluster == 0xFFFF) {
break;
}
FAT_Byte_Addresse = (Cluster * 2) % BlockSize;
FAT_Block_Addresse =
((Cluster * 2) / BlockSize) + volume_boot_record_addr + fat_offset;
if (FAT_Block_Addresse != FAT_Block_Store) {
FAT_Block_Store = FAT_Block_Addresse;
mmc_read_sector(FAT_Block_Addresse, TMP_Buffer);
}
Cluster =
(TMP_Buffer[FAT_Byte_Addresse + 1] << 8) +
TMP_Buffer[FAT_Byte_Addresse];
}
return;
}
void fat_read_file(uint16_t Cluster, uint8_t * Buffer, uint32_t BlockCount)
{ {
uint32_t Block = (BlockCount / cluster_size); if (sec != fat.currentSectorNr) { // nachladen nötig
fat_load(Cluster, &Block, Buffer); #if (WRITE==1)
Block = ((Block - 2) * cluster_size) + cluster_offset; if (fat.bufferDirty == 1)
Block += (BlockCount % cluster_size); fat_writeSector(fat.currentSectorNr); // puffer diry, also vorher schreiben
mmc_read_sector(Block, Buffer); #endif
return; mmc_read_sector(sec, fat.sector); // neuen sektor laden
} fat.currentSectorNr = sec; // aktualisiert sektor nummer (nummer des gepufferten sektors)
void fat_write_file(uint16_t cluster, uint8_t * buffer, uint32_t blockCount)
{
uint8_t tmp_buffer[513];
uint32_t block = (blockCount / cluster_size);
fat_load(cluster, &block, tmp_buffer);
block = ((block - 2) * cluster_size) + cluster_offset;
block += (blockCount % cluster_size);
mmc_write_sector(block, buffer);
return;
}
uint8_t fat_search_file(uint8_t * File_Name,
uint16_t * Cluster,
uint32_t * Size, uint8_t * Dir_Attrib, uint8_t * Buffer)
{
uint16_t Dir_Cluster_Store = *Cluster;
uint8_t a;
for (a = 0; a < 100; a++) {
*Cluster =
fat_read_dir_ent(Dir_Cluster_Store, a, Size, Dir_Attrib, Buffer);
if (*Cluster == 0xffff) {
return (0); return (0);
} }
if (strcasecmp((char *) File_Name, (char *) Buffer) == 0) {
else
return (0); // alles ok, daten sind schon da (sec==fat.currentSectorNr)
return (1); // fehler
}
// datei lesen funktionen:
// fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir -> fat_loadFileDataFromDir -> fat_cd
// "daten chain"
// ***************************************************************************************************************
// läd die reihe:row des gepufferten sektors auf das struct:file. dort stehen dann
// alle wichgigen daten wie: 1.cluster,länge bei dateien, name des eintrags, reihen nummer (im sektor), attribut use...
// ***************************************************************************************************************
uint8_t fat_loadRowOfSector(uint16_t row)
{
uint8_t i;
row = row << 5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 usw).
void *vsector; // void, damit man schoen umbiegen kann :)
for (i = 0; i < 11; i++)
file.name[i] = fat.sector[row + i]; // datei name, ersten 10 bytes vom 32 byte eintrag.
file.attrib = fat.sector[row + 11]; // datei attribut, byte 11.
vsector = &fat.sector[row + 26]; // low word von fist.cluster
file.firstCluster = *(uint16_t *) vsector;
vsector = &fat.sector[row + 20]; // high word von first.cluster
file.firstCluster |= (*(uint16_t *) vsector) << 16;
vsector = &fat.sector[row + 28]; // 4 byte von file.length
file.length = *(uint32_t *) vsector;
return (0);
}
// ***************************************************************************************************************
// geht reihen weise durch sektoren des clusters mit dem startsektor:sec, und sucht nach der datei mit dem
// namen:name. es werden die einzelnen sektoren nachgeladen auf puffer:sector vor dem bearbeiten.
// wird die datei in dem cluster gefunden ist return 0 , sonst return1.
// ***************************************************************************************************************
uint8_t fat_loadFileDataFromCluster(uint32_t sec, char name[])
{
uint8_t r;
uint8_t s = 0;
do { // sektoren des clusters prüfen
r = 0; // neuer sektor, dann reihen von 0 an.
mmc_read_sector(sec + s, fat.sector); // läd den sektor sec auf den puffer fat.sector
fat.currentSectorNr = sec + s; // setzen des aktuellen sektors
do { // reihen des sektors prüfen
fat_loadRowOfSector(r); // zeile 0-15 auf struct file laden
if (file.name[0] == 0) { // wenn man auf erste 0 stößt müsste der rest auch leer sein!
file.row = r; // zeile sichern.
return (1); return (1);
} }
if (0 == strncmp((char *) file.name, name, 10)) { // zeile r ist gesuchte
file.row = r; // zeile sichern.
return (0);
} }
return (2); r++;
} while (r < 16); // zählt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors)
s++;
} while (s < fat.secPerClust); // geht durch sektoren des clusters
return (1); // fehler (datei nicht gefunden, oder fehler beim lesen)
} }
// ***************************************************************************************************************
// wenn dir == 0 dann wird das root direktory durchsucht, wenn nicht wird der ordner cluster-chain gefolgt, um
// die datei zu finden. es wird das komplette directory in dem man sich befindet durchsucht.
// bei fat16 wird der rootDir berreich durchsucht, bei fat32 die cluster chain des rootDir.
// ***************************************************************************************************************
uint8_t fat_loadFileDataFromDir(char name[])
{
uint16_t s;
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
if (0 == fat_loadFileDataFromCluster(fat.rootDir + s, name))
return (0); // sucht die datei, wenn da, läd daten (1.cluster usw)
}
}
else {
uint32_t i;
if (fat.dir == 0 && fat.fatType == 32)
i = fat.rootDir; // IM ROOTDIR. fat32
else
i = fat.dir; // NICHT ROOTDIR
while (!((i == 0xfffffff && fat.fatType == 32) || (i == 0xffff && fat.fatType == 16))) { // prüft ob weitere sektoren zum
// lesen da sind (fat32||fat16)
if (0 == fat_loadFileDataFromCluster(fat_clustToSec(i), name))
return (0); // lät die daten der datei auf struct:file. datei gefunden (umrechnung auf absoluten sektor)
i = fat_getNextCluster(i); // liest nächsten cluster des dir-eintrags (unterverzeichniss größer 16 einträge)
}
}
return (1); // datei/verzeichniss nicht gefunden
}
#if (SMALL_FILE_SYSTEM==0)
// ***************************************************************************************************************
// start immer im root Dir. start in root dir (dir==0).
// es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/anhängen ist (außer root, da startet mann)!
// ***************************************************************************************************************
uint8_t fat_cd(char name[])
{
if (name[0] == 0) { // ZUM ROOTDIR FAT16/32
fat.dir = 0; // root dir
return (0);
}
if (0 == fat_loadFileDataFromDir(name)) { // NICHT ROOTDIR (fat16/32)
fat.dir = file.firstCluster; // zeigt auf 1.cluster des dir (fat16/32)
return (0);
}
return (1); // dir nicht gewechselt (nicht da?) !!
}
#endif
#if (WRITE==1)
// datei anlegen funktionen :
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im cluster mit dem startsektor:secStart.
// wird dort kein freier eintrag gefunden ist return (1).
// wird ein freier eintrag gefunden, ist die position der freien reihe auf file.row abzulesen und return (0).
// der sektor mit der freien reihe ist auf dem puffer:sector gepuffert.
// ****************************************************************************************************************
uint8_t fat_getFreeRowOfCluster(unsigned long secStart)
{
uint16_t b; // zum durchgenen der sektor bytes
uint8_t s = 0; // sektoren des clusters.
do {
file.row = 0; // neuer sektor(oder 1.sektor), reihen von vorne.
if (0 == fat_loadSector(secStart + s)) { // laed sektor auf puffer fat.sector
for (b = 0; b < 512; b = b + 32) { // zaehlt durch zeilen (0-15).
if (fat.sector[b] == 0x00 || fat.sector[b] == 0xE5)
return (0); // prueft auf freihen eintrag (leer oder geloescht == OK!).
file.row++; // zählt reihe hoch (nächste reihe im sektor).
}
}
s++; // sektoren des clusters ++ weil einen geprüft.
} while (s < fat.secPerClust); // geht die sektoren des clusters durch (moeglicherweise auch nur 1. sektor).
return (1); // nicht gefunden in diesem cluster (== nicht OK!).
}
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im directory mit dem startcluster:dir.
// geht die cluster chain des direktories durch. dabei werden auch alle sektoren der cluster geprüft.
// wird dort kein freier eintrag gefunden, wird ein neuer leerer cluster gesucht, verkettet und der
// 1. sektor des freien clusters geladen. die reihe wird auf den ersten eintrag gesetzt, da frei.
// anhand der reihe kann man nun den direktory eintrag vornehmen, und auf die karte schreiben.
// ****************************************************************************************************************
void fat_getFreeRowOfDir(uint32_t dir)
{
uint32_t start = dir;
// solange bis ende cluster chain.
while (!
((dir == 0xfffffff && fat.fatType == 32)
|| (dir == 0xffff && fat.fatType == 16))) {
if (0 == fat_getFreeRowOfCluster(fat_clustToSec(dir)))
return; // freien eintrag in clustern, des dir gefunden !!
start = dir;
dir = fat_getNextCluster(dir);
} // wenn aus schleife raus, kein freier eintrag da -> neuer cluster nötig.
dir = fat_secToClust(fat.startSectors); // dir ist jetzt neuer cluster zum verketten !
fat_setCluster(start, dir); // cluster-chain mit neuem cluster verketten
fat_setCluster(dir, 0x0fffffff); // cluster-chain ende markieren
// es muessen neue gesucht werden, weil der bekannte aus file.c ja grade verkettet wurden. datei eintrag passte nicht mehr ins dir...
fat_getFreeClustersInRow(2); // neue freie cluster suchen, für datei.
file.firstCluster = fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster = fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat.currentSectorNr = fat_clustToSec(dir); // setzen des richtigen sektors, also auf den 1. der neu verketteten
uint16_t j = 511;
do {
fat.sector[j] = 0x00; // schreibt puffer fat.sector voll mit 0x00==leer
} while (j--);
uint8_t i = 1; // ab 1 weil der 1.sektor des clusters eh noch beschrieben wird...
do {
fat_writeSector(fat.currentSectorNr + i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls,
i++;
} while (i < fat.secPerClust);
file.row = 0; // erste reihe frei, weil grad neuen cluster verkettet !
}
// ***************************************************************************************************************
// erstellt 32 byte eintrag einer datei, oder verzeichnisses im puffer:sector.
// erstellt eintrag in reihe:row, mit namen:name usw... !!
// muss noch auf die karte geschrieben werden ! nicht optimiert auf geschwindigkeit.
// ***************************************************************************************************************
void fat_makeRowDataEntry(uint16_t row, char name[], uint8_t attrib,
uint32_t cluster, uint32_t length)
{
fat.bufferDirty = 1; // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
row = row << 5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile
// 15=480)
uint8_t i; // byte zähler in reihe von sektor (32byte eintrag)
uint8_t *bytesOfSec = &fat.sector[row]; // zeiger auf sector bytes
void *vsector;
for (i = 0; i < 11; i++)
*bytesOfSec++ = name[i]; // namen schreiben
*bytesOfSec++ = attrib; // attrib schreiben
vsector = &fat.sector[row + 12];
*(uint32_t *) vsector++ = 0x01010101; // unnoetige felder beschreiben
*(uint32_t *) vsector = 0x01010101;
vsector = &fat.sector[row + 20];
*(uint16_t *) vsector = (cluster & 0xffff0000) >> 16; // low word von cluster
vsector = &fat.sector[row + 22];
*(uint32_t *) vsector = 0x01010101; // unnoetige felder beschreiben
vsector = &fat.sector[row + 26];
*(uint16_t *) vsector = (cluster & 0x0000ffff); // high word von cluster
vsector = &fat.sector[row + 28];
*(uint32_t *) vsector = length; // laenge
}
// ***************************************************************************************************************
// macht den datei eintrag im jetzigen verzeichniss (fat.dir).
// file.row enthält die reihen nummer des leeren eintrags, der vorher gesucht wurde, auf puffer:sector ist der gewünschte
// sektor gepuffert. für fat16 im root dir muss andere funktion genutzt werden, als fat_getFreeRowOfDir (durchsucht nur dirs).
// fat.rootDir enthält bei fat32 den start cluster des directory, bei fat16 den 1. sektor des rootDir bereichs!
// ***************************************************************************************************************
void fat_makeFileEntry(char name[], uint8_t attrib,
uint32_t length)
{
uint16_t s; // zähler für root dir sektoren fat16
if (fat.dir == 0 && fat.fatType == 32)
fat_getFreeRowOfDir(fat.rootDir); // IM ROOT DIR (fat32)
else if (fat.dir == 0 && fat.fatType == 16) { // IM ROOT DIR (fat16)
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
if (0 == fat_getFreeRowOfCluster(fat.rootDir + s))
break; // geht durch sektoren des root dir.
}
}
else
fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR fat32/fat16
fat_makeRowDataEntry(file.row, name, attrib, file.firstCluster, length); // schreibt file eintrag auf puffer
fat_writeSector(fat.currentSectorNr); // schreibt puffer auf karte
}
#endif
// fat funktionen:
// ***************************************************************************************************************
// sucht nötige folge Cluster aus der fat !
// erster daten cluster = 2, ende einer cluster chain 0xFFFF (fat16) oder 0xFFFFFFF, 0xFFFFFF8 (fat32),
// stelle des clusters in der fat, hat als wert, den nächsten cluster. (1:1 gemapt)!
// ***************************************************************************************************************
uint32_t fat_getNextCluster(uint32_t oneCluster)
{
// FAT 16**************FAT 16
if (fat.fatType == 16) {
uint32_t i = oneCluster >> 8;; // (i=oneCluster/256)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
uint32_t j = (oneCluster << 1) - (i << 9); // (j=(oneCluster-256*i)*2 == 2*oneCluster-512*i)errechnet das low byte von
// oneCluster
if (0 == fat_loadSector(i + fat.fatSec)) { // ob neu laden nötig, wird von fat_loadSector geprüft
void *bytesOfSec = &fat.sector[j]; // zeiger auf puffer
return *(uint16_t *) bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
}
}
// FAT 32**************FAT 32
else {
uint32_t i = oneCluster >> 7; // (i=oneCluster/128)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
uint32_t j = (oneCluster << 2) - (i << 9); // (j=(oneCluster-128*i)*4 == oneCluster*4-512*i)errechnet das low byte von
// oneCluster
if (0 == fat_loadSector(i + fat.fatSec)) { // ob neu laden nötig wird von fat_loadSector geprüft
void *bytesOfSec = &fat.sector[j]; // zeiger auf puffer
return *(uint32_t *) bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
}
}
return (0);
}
// ***************************************************************************************************************
// sucht verkettete cluster einer datei, die in einer reihe liegen. worst case: nur ein cluster.
// sieht in der fat ab dem cluster offsetCluster nach. sucht die anzahl von MAX_CLUSTERS_IN_ROW,
// am stück,falls möglich. prüft ob der cluster neben offsetCluster dazu gehört...
// setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
// ***************************************************************************************************************
void fat_getFatChainClustersInRow(uint32_t offsetCluster)
{
uint16_t i = 0;
fat.startSectors = fat_clustToSec(offsetCluster); // setzen des 1. sektors der datei
fat.endSectors = fat.startSectors;
do {
if ((offsetCluster + 1 + i) == fat_getNextCluster(offsetCluster + i))
fat.endSectors += fat.secPerClust; // zählen der zusammenhängenden sektoren
else {
file.lastCluster = offsetCluster + i; // cluster daneben gehört nicht dazu, somit ist offset+i der letzte bekannte
break;
}
} while (i++ < MAX_CLUSTERS_IN_ROW);
fat.endSectors += fat.secPerClust - 1;
}
#if (WRITE==1)
// ***************************************************************************************************************
// sucht freie zusammenhängende cluster aus der fat. maximal MAX_CLUSTERS_IN_ROW am stück.
// erst wir der erste frei cluster gesucht, ab offsetCluster(iklusive) und dann wird geschaut, ob der
// daneben auch frei ist. setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
// ***************************************************************************************************************
void fat_getFreeClustersInRow(uint32_t offsetCluster)
{
uint16_t i = 1; // variable für anzahl der zu suchenden sektoren
while (fat_getNextCluster(offsetCluster))
offsetCluster++; // suche des 1. freien clusters
fat.startSectors = fat_clustToSec(offsetCluster); // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren)
fat.endSectors = fat.startSectors;
do { // suche der nächsten freien
if (0 == fat_getNextCluster(offsetCluster + i))
fat.endSectors += fat.secPerClust; // zählen der zusammenhängenden sektoren
else
break; // cluster daneben ist nicht frei
} while (i++ < MAX_CLUSTERS_IN_ROW);
fat.endSectors += fat.secPerClust - 1; // -1 weil der erste sektor schon mit zählt z.b. [95,98] = 4 sektoren
}
// ***************************************************************************************************************
// verkettet ab startCluster bis einschließlich endCluster. verkettet auch den letzten bekannten mit den neu übergebenen !
// es ist wegen der fragmentierung der fat nötig, sich den letzten bekannten cluster zu merken,
// damit man bei weiteren cluster in einer reihe die alten cluster noch dazu verketten kann (so sind lücken im verketten möglich).
// ***************************************************************************************************************
void fat_setClusterChain(uint32_t startCluster,
uint16_t endCluster)
{
fat_setCluster(file.lastCluster, startCluster); // ende der chain setzen, bzw verketten der ketten
while (startCluster != endCluster) {
startCluster++;
fat_setCluster(startCluster - 1, startCluster); // verketten der cluster der neuen kette
}
fat_setCluster(startCluster, 0xfffffff); // ende der chain setzen
file.lastCluster = endCluster; // ende cluster der kette updaten
fat_writeSector(fat.currentSectorNr); // schreiben des fat sektors auf die karte
}
// ***************************************************************************************************************
// setzt den cluster inhalt. errechnet den sektor der fat in dem cluster ist, errechnet das low byte von
// cluster und setzt dann byteweise den inhalt:content.
// prüft ob buffer dirty (zu setztender cluster nicht in jetzt gepuffertem).
// prüfung erfolgt in fat_loadSector, dann wird alter vorher geschrieben, sonst gehen dort daten verloren !!
// ***************************************************************************************************************
void fat_setCluster(uint32_t cluster, uint32_t content)
{
// FAT 16**************FAT 16
if (fat.fatType == 16) {
uint32_t i = cluster >> 8; // (i=cluster/256)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
uint32_t j = (cluster << 1) - (i << 9); // (j=(cluster-256*i)*2 == 2*cluster-512*i)errechnet das low byte von
// cluster
if (0 == fat_loadSector(i + fat.fatSec)) { // neu laden (fat_loadSector prüft ob schon gepuffert)
void *bytesOfSec = &fat.sector[j]; // init des zeigers auf unterste adresse
*(uint16_t *) bytesOfSec = content; // weil ram auch little endian geht das so :)
fat.bufferDirty = 1; // zeigt an, dass im aktuellen sector geschrieben wurde
}
}
// FAT 32**************FAT 32
else {
uint32_t i = cluster >> 7; // (i=cluster/128)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
uint32_t j = (cluster << 2) - (i << 9); // (j=(cluster-128*i)*4 == cluster*4-512*i)errechnet das low byte von
// cluster
if (0 == fat_loadSector(i + fat.fatSec)) { // neu laden (fat_loadSector prüft ob schon gepuffert)
void *bytesOfSec = &fat.sector[j]; // init des zeigers auf unterste adresse
*(uint32_t *) bytesOfSec = content; // weil ram auch little endian geht das so :)
fat.bufferDirty = 1; // zeigt an, dass im aktuellen sector geschrieben wurde
}
}
}
// ***************************************************************************************************************
// löscht cluster chain, beginnend ab dem startCluster.
// sucht cluster, setzt inhalt usw.. abschließend noch den cluster-chain ende markierten cluster löschen.
// ***************************************************************************************************************
void fat_delClusterChain(uint32_t startCluster)
{
uint32_t nextCluster = startCluster; // tmp variable, wegen verketteter cluster..
do {
startCluster = nextCluster;
nextCluster = fat_getNextCluster(startCluster);
fat_setCluster(startCluster, 0x00000000);
} while (!
((nextCluster == 0xfffffff && fat.fatType == 32)
|| (nextCluster == 0xffff && fat.fatType == 16)));
fat_writeSector(fat.currentSectorNr);
}
#endif
// ***************************************************************************************************************
// Initialisiert die Fat(16/32) daten, wie: root directory sektor, daten sektor, fat sektor...
// siehe auch Fatgen103.pdf. ist NICHT auf performance optimiert!
// byte/sector, byte/cluster, anzahl der fats, sector/fat ... (halt alle wichtigen daten zum lesen ders datei systems!)
// *****************************************************************<**********************************************
uint8_t fat_loadFatData(uint32_t sec)
{
// offset,size
uint16_t rootEntCnt; // 17,2 größe die eine fat belegt
uint16_t fatSz16; // 22,2 sectors occupied by one fat16
uint32_t fatSz32; // 36,4 sectors occupied by one fat32
void *vsector;
if (0 == mmc_read_sector(sec, fat.sector)) { // lesen von fat sector und bestimmen der wichtigen berreiche
fat.bufferDirty = 0; // init wert des flags
fat.secPerClust = fat.sector[13]; // fat.secPerClust, 13 only (power of 2)
vsector = &fat.sector[14];
fat.fatSec = *(uint16_t *) vsector;
vsector = &fat.sector[17];
rootEntCnt = *(uint16_t *) vsector;
vsector = &fat.sector[22];
fatSz16 = *(uint16_t *) vsector;
fat.rootDir = (((rootEntCnt << 5) + 512) / 512) - 1; // ist 0 bei fat 32, sonst der root dir sektor
if (fat.rootDir == 0) { // FAT32 spezifisch (die prüfung so, ist nicht spezifikation konform !).
vsector = &fat.sector[36];
fatSz32 = *(uint32_t *) vsector;
vsector = &fat.sector[44];
fat.rootDir = *(uint32_t *) vsector;
fat.dataDirSec = fat.fatSec + (fatSz32 * fat.sector[16]); // data sector (beginnt mit cluster 2)
fat.fatType = 32; // fat typ
}
else { // FAT16 spezifisch
fat.dataDirSec = fat.fatSec + (fatSz16 * fat.sector[16]) + fat.rootDir; // data sektor (beginnt mit cluster 2)
fat.rootDir = fat.dataDirSec - fat.rootDir; // root dir sektor, da nicht im datenbereich (cluster)
fat.rootDir += sec; // addiert den startsektor auf "
fat.fatType = 16; // fat typ
}
fat.fatSec += sec; // addiert den startsektor auf
fat.dataDirSec += sec; // addiert den startsektor auf (umrechnung von absolut auf real)
fat.dataDirSec -= 2; // zeigt auf 1. cluster
fat.dir = 0; // dir auf '0'==root dir, sonst 1.Cluster des dir
return (0);
}
return (1); // sector nicht gelesen, fat nicht initialisiert!!
}
// ************************************************************************************************<<***************
// int fat sucht den 1. cluster des dateisystems (fat16/32) auch VBR genannt,
// ************************************************************************************************<<***************
uint8_t fat_initfat(void)
{
uint32_t secOfFirstPartition = 0; // ist 1. sektor der 1. partition aus dem MBR
if (0 == mmc_read_sector(0, fat.sector)) {
void *vsector = &fat.sector[454]; // startsektor bestimmen
secOfFirstPartition = *(uint32_t *) vsector;
// prüfung ob man schon im VBR gelesen hat (0x6964654d = "Medi")
if (secOfFirstPartition == 0x6964654d)
return fat_loadFatData(0); // ist superfloppy
else {
return fat_loadFatData(secOfFirstPartition);
} // ist partitioniert...
}
return (1);
}
#if (SMALL_FILE_SYSTEM==0)
// *****************************************************************************************************************
// bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann.
// wandelt z.b. "t.txt" -> "T TXT" oder "main.c" in "MAIN C " => also immer 8.3 und upper case letter
// VORSICHT es werden keine Prüfungen gemacht !
// *****************************************************************************************************************
char *fat_str(char *str)
{
uint8_t i;
uint8_t j = 0;
uint8_t c;
char tmp[12]; // tmp string zum einfacheren umwandeln
strcpy(tmp, str);
for (i = 0; i < 11; i++)
str[i] = ' '; // als vorbereitung alles mit leerzeichen füllen
str[11] = '\0';
i = 0;
do {
c = toupper(tmp[j]);
if (c == '\0')
return str;
if (c != '.')
str[i] = c;
else
i = 7;
i++;
j++;
} while (i < 12);
return str;
}
#endif

View File

@@ -1,103 +1,78 @@
/*
*/
#ifndef _FAT_H_ #ifndef _FAT_H
#define _FAT_H_
#include <string.h>
#include "mmc.h"
#include "uart.h"
#define FAT_DEBUG uart_puts #define _FAT_H
// **************************************************************************************************************************
// WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität !
// die fat nicht fragmentiert ist !
#define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung !
#define WRITE 0 // wenn 1 dann ist write an, wenn 0 dann read only !
#define OVER_WRITE 0 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben !
#define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
// 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!"
// 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain"
// **************************************************************************************************************************
// funktionen
extern uint32_t fat_clustToSec(uint32_t); // rechnet cluster zu 1. sektor des clusters um
extern uint32_t fat_secToClust(uint32_t sec); // rechnet sektor zu cluster um!
extern uint32_t fat_getNextCluster(uint32_t oneCluster); // fat auf nächsten, verketteten cluster durchsuchen
extern uint8_t fat_initfat(void); // initalisierung (durchsucht MBR oder nicht)
extern uint8_t fat_writeSector(uint32_t sec); // schreibt sektor auf karte
extern void fat_setCluster(uint32_t cluster, uint32_t content); // setzt cluster inhalt in der fat
extern void fat_delClusterChain(uint32_t startCluster); // löscht cluster-chain in der fat
extern void fat_getFreeRowOfDir(uint32_t dir); // durchsucht directory nach feiem eintrag
extern void fat_makeFileEntry(char name[], uint8_t attrib,
uint32_t length);
extern uint8_t fat_loadSector(uint32_t sec); // läd übergebenen absoluten sektor
extern uint8_t fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory
extern uint8_t fat_cd(char *); // wechselt directory (start im rootDir)
extern uint8_t fat_loadFatData(uint32_t); // läd fat daten
extern uint8_t fat_getFreeRowOfCluster(unsigned long secStart); // durchsucht cluster nach freiem eintrag
extern void fat_getFreeClustersInRow(uint32_t offsetCluster); // sucht zusammenhängende freie cluster aus der fat
extern void fat_getFatChainClustersInRow(uint32_t offsetCluster); // sucht fat-chain cluster die zusammenhängen
extern void fat_makeRowDataEntry(uint16_t row, char name[],
uint8_t attrib,
uint32_t cluster,
uint32_t length);
extern uint8_t fat_loadRowOfSector(uint16_t); // läd reihe des geladen sektors auf struct:file
extern uint8_t fat_loadFileDataFromCluster(uint32_t sec, char name[]); // durchsucht die reihen des geladenen sektors
extern void fat_setClusterChain(uint32_t newOffsetCluster,
uint16_t length);
extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht !
// **************************************************************************************************************************
// variablen
extern uint16_t fat_root_dir_addr(uint8_t *); extern struct Fat { // fat daten (1.cluster, root-dir, dir usw.)
extern uint16_t fat_read_dir_ent(uint16_t, uint8_t, uint8_t sector[512]; // der puffer für sektoren !
uint32_t *, uint8_t *, uint8_t *); uint8_t bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird
extern void fat_load(uint16_t, uint32_t *, uint8_t *); uint32_t currentSectorNr; // aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder
extern void fat_read_file(uint16_t, uint8_t *, uint32_t); // bei fat operationen im gleichen sektor
extern void fat_write_file(uint16_t, uint8_t *, uint32_t); uint32_t dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root)
extern void fat_init(uint8_t * Buffer); uint32_t rootDir; // Sektor(f16)/Cluster(f32) nr root directory
extern uint8_t fat_search_file(uint8_t *, uint16_t *, uint32_t dataDirSec; // Sektor nr data area
uint32_t *, uint8_t *, uint8_t *); uint32_t fatSec; // Sektor nr fat area
uint32_t startSectors; // der erste sektor in einer reihe (freie oder verkettete)
uint32_t endSectors;
uint8_t secPerClust; // anzahl der sektoren pro cluster
uint8_t fatType; // fat16 oder fat32 (16 oder 32)
} fat;
extern struct File { // datei infos
#define BlockSize 512 uint16_t cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors
uint8_t name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS uint8_t weil E5)
uint8_t attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag
#define MASTER_BOOT_RECORD 0 uint8_t row; // reihe im sektor in der die datei infos stehen (reihe 0-15)
uint32_t firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte)
uint32_t length; // 28,4 datei Länge (4-byte)
#define VBR_ADDR 0x1C6 uint32_t lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette
uint32_t seek; // schreib position in der datei
} file;
#define SPACE 0x20
#define DIR_ENTRY_IS_FREE 0xE5
#define FIRST_LONG_ENTRY 0x01
#define SECOND_LONG_ENTRY 0x42
#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 {
uint8_t BS_jmpBoot[3];
uint8_t BS_OEMName[8];
uint16_t BPB_BytesPerSec;
uint8_t BPB_SecPerClus;
uint16_t BPB_RsvdSecCnt;
uint8_t BPB_NumFATs;
uint16_t BPB_RootEntCnt;
uint16_t BPB_TotSec16;
uint8_t BPB_Media;
uint16_t BPB_FATSz16;
uint16_t BPB_SecPerTrk;
uint16_t BPB_NumHeads;
uint32_t BPB_HiddSec;
uint32_t BPB_TotSec32;
};
#define BS_DRVNUM 36
#define BS_RESERVED1 37
#define BS_BOOTSIG 38
#define BS_VOLID 39
#define BS_VOLLAB 43
#define BS_FILSYSTYPE 54
#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
struct DirEntry {
uint8_t DIR_Name[11];
uint8_t DIR_Attr;
uint8_t DIR_NTRes;
uint8_t DIR_CrtTimeTenth;
uint16_t DIR_CrtTime;
uint16_t DIR_CrtDate;
uint16_t DIR_LastAccDate;
uint16_t DIR_FstClusHI;
uint16_t DIR_WrtTime;
uint16_t DIR_WrtDate;
uint16_t DIR_FstClusLO;
uint32_t DIR_FileSize;
};
#endif #endif

525
avr/usbload/file.c Normal file
View File

@@ -0,0 +1,525 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mmc.h"
#include "fat.h"
#include "file.h"
#include "dir.h"
#include "config.h"
// *******************************************************************************************************************************
// 2 möglichkeiten beim öffnen, datei existiert(return 1) oder muss angelegt werden(return 2)
// zuerst wird geprüft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geöffnet wird oder angelegt.
// -beim offnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
// den puffer fat.sector geladen. jetzt kann man ffread lesen...
// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefüllt.
// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprüft ob genügend platz im aktuellen verzeichniss existiert.
// möglicherweise wird der 1. cluster der datei nochmal geändert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
//*******************************************************************************************************************************
unsigned char ffopen(char name[]){
unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct
if( file_flag==0 ){ /** Datei existiert, anlegen nicht nötig! **/
fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen.
fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector.
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
return 1;
}
#if (WRITE==1) // anlegen ist schreiben !
else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2.
strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben.
file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster=file.firstCluster;//fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !!
file.length=0; // damit da nix drin steht ^^
fat_makeFileEntry((char *)file.name,file.attrib,0); // DATEI ANLEGEN auf karte
fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors
return 2;
}
#endif
}
//*******************************************************************************************************************************
// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. es gibt 2 möglichkeiten :
// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
// 2. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der aktuelle sektor geschrieben werden.
// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
// und die neue datei länge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
// *******************************************************************************************************************************
uint8_t ffclose(void)
{
#if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
if (file.length < (file.seek + file.cntOfBytes))
fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/
else if (fat.bufferDirty == 1)
fat_writeSector(fat.currentSectorNr); /** 2.) nicht über alte datei länge hinaus **/
#endif
file.cntOfBytes = 0; // init werte der nötigen zähler
file.seek = 0;
return (0);
}
// *******************************************************************************************************************************
// updatet datei eintrag auf der karte und verkettet die dazugehörigen fat cluster.
// füllt den aktuell beschriebenen sektor mit 0x00, da sonst die datei nicht richtig angezeigt wird.
// darf nur während schreibe operationen aufgerufen werden !
// *******************************************************************************************************************************
#if (WRITE==1)
void fileUpdate(void){
unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife...
while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen
fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00
comp_cntOfBytes++;
}
char name[13]; // zum sichern des dateinamens
unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert !
strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert !
fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file!
fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer
fat_writeSector(fat.currentSectorNr);
}
#endif
// *******************************************************************************************************************************
// offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht
// ist, dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
// die "vorgesucht" wurden, müssen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
// *******************************************************************************************************************************
void ffseek(unsigned long int offset){
#if (WRITE==1)
#if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !!
if( file.seek > file.length ) fileUpdate(); // fat verketten und datei update auf der karte !
#endif
#endif
fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus !
unsigned long int sec=fat.startSectors; // sektor variable zum durchgehen durch die sektoren
file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
while(offset>=512){ /** suchen des sektors in dem offset ist **/
sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden
offset-=512; // ein sektor weniger in dem das byte sein kann
file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt
if ( sec > fat.endSectors ){ // es müssen mehr sektoren der datei gesucht werden
fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // nachladen von clustern in der chain
sec=fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
}
}
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat_loadSector(sec); // sektor mit offset byte laden
file.cntOfBytes = offset; // setzen des lese zählers
}
#if (SMALL_FILE_SYSTEM==0)
// *******************************************************************************************************************************
// wechselt verzeichniss. start immer im root Dir.
// MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
// *******************************************************************************************************************************
uint8_t ffcd(char name[])
{
return (fat_cd(name));
}
// *******************************************************************************************************************************
// zeigt reihen eines clusters an, wird für ffls benötigt !
// es wird ab dem start sektor start_sec, der dazugehörige cluster angezeigt. geprüft wird ob es ein richtiger
// eintrag in der reihe ist (nicht gelöscht, nicht frei usw). die sektoren des clusters werden nachgeladen.
// die dateien werden mit namen und datei größe angezeigt.
// *******************************************************************************************************************************
void lsRowsOfClust(uint32_t start_sec)
{
uint8_t row; // reihen
uint8_t sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.name[0] != 0xE5 && file.name[0] != 0x00)) {
if (file.attrib == 0x20)
printf("Name: %s Size:%li\n", file.name, file.length);
if (file.attrib == 0x10)
printf("Dir: %s\n", file.name);
}
}
} while (++sec < fat.secPerClust);
}
void ffls(void)
{
uint32_t clust; // cluster
uint16_t s; // fat16 root dir sektoren
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
lsRowsOfClust(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
printf("Fat16\n");
} else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
printf("Fat32\n");
}
}
void lsRowsOfClust_smc(uint32_t start_sec)
{
uint8_t row; // reihen
uint8_t sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.name[0] != 0xE5 && file.name[0] != 0x00)) {
if (file.attrib == 0x20)
dir_entry_add(file.firstCluster, file.name, file.length ,file.attrib);
}
}
} while (++sec < fat.secPerClust);
}
void ffls_smc(void)
{
uint32_t clust; // cluster
uint16_t s; // fat16 root dir sektoren
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
lsRowsOfClust_smc(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
printf("Fat16\n");
} else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
lsRowsOfClust_smc(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
printf("Fat32\n");
}
}
// *******************************************************************************************************************************
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
// *******************************************************************************************************************************
uint8_t ffcdLower(void)
{
if (fat.dir == 0)
return (1); // im root dir, man kann nicht höher !
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
fat.dir = file.firstCluster; // dir setzen
return (0);
}
#ifndef __AVR_ATmega8__
// *******************************************************************************************************************************
// erstellt einen dir eintrag im aktuellen verzeichniss.
// prüft ob es den den dir-namen schon gibt, dann wird nichts angelegt.
// wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
// dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
// ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
// *******************************************************************************************************************************
#if (WRITE==1)
void ffmkdir(char name[]){
unsigned char i;
unsigned int j;
if(0==fat_loadFileDataFromDir(name))return ; // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
// cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
fat_getFreeClustersInRow(2); // holt neue freie cluster, ab cluster 2 ...
fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
file.firstCluster=fat_secToClust(fat.startSectors); // dammit fat_makeFileEntry den cluster richtig setzen kann
fat_makeFileEntry(name,0x10,0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
// aufbereiten des puffers
j=511;
do{
fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
}while(j--);
// aufbereiten des clusters
for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
fat_writeSector(fat.startSectors+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
}
// aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
fat_makeRowDataEntry(0,". ",0x10,file.firstCluster,0); // macht "." eintrag des dirs
fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
fat_writeSector(fat_clustToSec(file.firstCluster)); // schreibt einträge auf karte !
}
#endif //WRITE
#endif // ffmkdir wegen atmega8
#endif
#if (WRITE==1)
// *******************************************************************************************************************************
// löscht datei/ordner aus aktuellem verzeichniss, wenn es die datei gibt.
// löscht dateien und ordner rekursiv !
// *******************************************************************************************************************************
uint8_t ffrm(char name[])
{
if (0 == fat_loadFileDataFromDir(name)) { // datei oder ordner ist vorhanden, nur dann lösch operation
if (file.attrib != 0x10) { // ist datei.
fat.sector[file.row << 5] = 0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt)
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor ?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht.
}
fat.bufferDirty = 1; // eintrag in puffer gemacht.
if (0 == fat_getNextCluster(file.firstCluster))
return (0); // 1.cluster ist leer ?!?
fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat.
return (0);
}
// TODO noch nicht optimal. zu viele schreib vorgänge beim löschen von datei einträgen. max bis zu 16/sektor !
else { // ist ordner, dann rekursiv löschen !!
#ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität....
uint32_t parent;
uint32_t own;
uint32_t clustsOfDir; // um durch die cluster chain eines dirs zu gehen.
uint8_t cntSecOfClust = 0;
uint8_t i = 0;
fat.sector[file.row << 5] = 0xE5; // löscht dir eintrag
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor (langer datei eintrag)?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht
}
fat.bufferDirty = 1; // puffer eintrag gemacht
parent = fat.dir; // der ordner in dem der zu löschende ordner ist.
own = file.firstCluster; // der 1. cluster des ordners der zu löschen ist.
clustsOfDir = file.firstCluster; // die "cluster" des zu löschenden ordners
do { // geht durch cluster des dirs
fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden
do { // geht durch sektoren des clusters
do { // geht durch reihen des sektors
fat_loadRowOfSector(i);
if (file.attrib != 0x10 && file.attrib != 0x00 && file.name[0] != 0xE5) { // ist kein ordner,noch nicht
// gelöscht, kein freier eintrag
fat.sector[i << 5] = 0xE5; // erster eintrag der reihe als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
if (file.attrib == 0x20) { // ist datei!
fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // sektor neu laden, weil löschen der
// chain, den puffer nutzt.
}
}
if (file.attrib == 0x10 && file.name[0] == '.') { // "." oder ".." eintrag erkannt, löschen !
fat.sector[i << 5] = 0xE5; // eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
}
if (file.attrib == 0x10 && file.name[0] != '.' && file.name[0] != 0xE5 && file.name[0] != 0) { // ordner erkannt !
fat.sector[i << 5] = 0xE5; // dir eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden
clustsOfDir = file.firstCluster; // eigenes dir ist file.firstCluster
own = file.firstCluster; // eigener start cluster/dir
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
if (file.name[0] == 0x00) { // ende des dirs erreicht, wenn nicht voll !!
if (parent == fat.dir) { // erfolgreich alles gelöscht
fat_delClusterChain(own); // cluster chain des ordners löschen
return (0);
}
fat_delClusterChain(own); // cluster chain des ordners löschen
clustsOfDir = parent; // parent ist jetzt wieder arbeisverzeichniss.
own = parent; // arbeitsverzeichniss setzten
fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
i++;
} while (i < 16); // geht durch reihen des sektors.
i = 0; // neuer sektor -> reihen von vorne.
cntSecOfClust++;
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // läd sektoren des clusters nach
} while (cntSecOfClust < fat.secPerClust); // geht durch sektoren des clusters.
cntSecOfClust = 0; // neuer cluster -> sektoren von vorne.
clustsOfDir = fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain.
} while (!((clustsOfDir == 0xfffffff && fat.fatType == 32) || (clustsOfDir == 0xffff && fat.fatType == 16))); // geht
// durch
// cluster
// des
// dirs.
fat_delClusterChain(own); // hier landet man, wenn der ordner voll war (auf cluster "ebene")!!
#endif
}
}
return (1); // fehler, nicht gefunden?
}
#endif
// *******************************************************************************************************************************
// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genügend verkettete
// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
// *******************************************************************************************************************************
inline uint8_t ffread(void)
{
if (file.cntOfBytes == 512) { /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/
file.cntOfBytes = 0; // byte zähler zurück setzen
if (fat.currentSectorNr == fat.endSectors) { /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/
fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust(fat.endSectors))); // nachladen von clustern in der chain
fat.currentSectorNr = fat.startSectors - 1; // setzen des nächsten sektors um weiter lesen zu können..
}
fat_loadSector(fat.currentSectorNr + 1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/
}
return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! )
}
#if (WRITE==1)
#if (OVER_WRITE==0) // nicht überschreibende write funktion
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten
// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// *******************************************************************************************************************************
inline void ffwrite(uint8_t c)
{
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben **/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen
fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
}
}
#endif
#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende
// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten einer
// kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// es ist beim überschreiben nötig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an
// geschwindigkeit.
// *******************************************************************************************************************************
inline void ffwrite(uint8_t c)
{
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers.
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben**/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben.
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
if (file.seek > file.length) { // außerhalb der datei !!
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen.
fat_getFreeClustersInRow(file.lastCluster); // neue leere sektoren benötigt, also suchen.
} else {
fat_getFatChainClustersInRow(fat_getNextCluster(file.lastCluster)); // noch innerhalb der datei, deshlab verkettete
// suchen.
}
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
mmc_read_sector(fat.currentSectorNr, fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden...
}
}
#endif
// *******************************************************************************************************************************
// schreibt string auf karte, siehe ffwrite()
// *******************************************************************************************************************************
inline void ffwrites(const char *s)
{
while (*s)
ffwrite(*s++);
}
#endif

33
avr/usbload/file.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef _FILE_H
#define _FILE_H
// **************************************************************************************************************************
// funktionen
extern inline uint8_t ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen)
extern inline void ffwrite(uint8_t c); // schreibt ein byte in die geöffnete datei
extern inline void ffwrites(const char *s); // schreibt string auf karte
extern uint8_t ffopen(char name[]); // kann immer nur 1 datei bearbeiten.
extern uint8_t ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird.
extern void ffseek(uint32_t offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei.
extern uint8_t ffcd(char name[]); // wechselt direktory
extern void ffls(void); // zeigt direktory inhalt an
extern void ffls_smc(void); // zeigt direktory inhalt an
extern uint8_t ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory)
extern uint8_t ffrm(char name[]); // löscht datei aus aktuellem verzeichniss.
extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an.
void lsRowsOfClust(uint32_t start_sec); // zeigt reihen eines clusters an, ab start_sec
void fileUpdate(void); // updatet datei eintrag auf karte
// **************************************************************************************************************************//
// #######################################################################################################################
#endif

12
avr/usbload/hardware.h Executable file
View File

@@ -0,0 +1,12 @@
#ifndef _HARDWARE_H
/*
hier sind die beiden hardware abhängigen bibliotheken zu includen !
welchen umfang diese haben müssen (an funktionen), muss man in den bibliotheken nachsehen.
*/
#define _HARDWARE_H
#include "uart.h"
#include "mmc.h"
#endif

View File

@@ -1,6 +1,6 @@
/* /*
File: main.smc File: main.smc
Time: Thu, 06 Aug 2009 08:37:50 Time: Sun, 09 Aug 2009 11:41:19
*/ */
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <loader.h> #include <loader.h>

View File

@@ -21,16 +21,16 @@
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> /* for sei() */ #include <avr/interrupt.h>
#include <util/delay.h> /* for _delay_ms() */ #include <util/delay.h>
#include <stdlib.h> #include <stdlib.h>
#include <avr/pgmspace.h> /* required by usbdrv.h */ #include <avr/pgmspace.h>
#include <avr/eeprom.h> #include <avr/eeprom.h>
#include "usbdrv.h" #include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug macros */ #include "oddebug.h"
#include "config.h" #include "config.h"
#include "requests.h" /* The custom request numbers we use */ #include "requests.h"
#include "uart.h" #include "uart.h"
#include "sram.h" #include "sram.h"
#include "debug.h" #include "debug.h"
@@ -42,16 +42,16 @@
#include "watchdog.h" #include "watchdog.h"
#include "rle.h" #include "rle.h"
#include "loader.h" #include "loader.h"
#include "command.h"
#include "shared_memory.h" #include "shared_memory.h"
#include "mmc.h" #include "testing.h"
#include "fat.h"
extern const char _rom[] PROGMEM; extern const char _rom[] PROGMEM;
extern FILE uart_stdout; extern FILE uart_stdout;
uint8_t debug_level = (DEBUG | DEBUG_USB | DEBUG_CRC); uint8_t debug_level = (DEBUG | DEBUG_USB | DEBUG_CRC | DEBUG_FAT);
uint8_t read_buffer[TRANSFER_BUFFER_SIZE]; uint8_t read_buffer[TRANSFER_BUFFER_SIZE];
uint32_t req_addr = 0; uint32_t req_addr = 0;
@@ -60,6 +60,8 @@ uint32_t req_size;
uint8_t req_bank; uint8_t req_bank;
uint32_t req_bank_size; uint32_t req_bank_size;
uint16_t req_bank_cnt; uint16_t req_bank_cnt;
uint8_t req_percent;
uint8_t req_percent_last;
uint8_t req_state = REQ_STATUS_IDLE; uint8_t req_state = REQ_STATUS_IDLE;
uint8_t rx_remaining = 0; uint8_t rx_remaining = 0;
uint8_t tx_remaining = 0; uint8_t tx_remaining = 0;
@@ -77,76 +79,8 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
usbRequest_t *rq = (void *) data; usbRequest_t *rq = (void *) data;
uint8_t ret_len = 0; uint8_t ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
if (rq->bRequest == USB_UPLOAD_INIT) {
if (req_state != REQ_STATUS_IDLE) { if (rq->bRequest == USB_BULK_UPLOAD_INIT) {
debug(DEBUG_USB,
"USB_UPLOAD_INIT: ERROR state is not REQ_STATUS_IDLE\n");
return 0;
}
req_bank = 0;
rx_remaining = 0;
req_bank_size = (uint32_t) 1 << rq->wValue.word;
sync_errors = 0;
crc = 0;
debug(DEBUG_USB, "USB_UPLOAD_INIT: bank_size=0x%08lx\n", req_bank_size);
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_UPLOAD_ADDR) {
req_state = REQ_STATUS_UPLOAD;
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
if (rx_remaining) {
sync_errors++;
debug
(DEBUG_USB,
"USB_UPLOAD_ADDR: Out of sync addr=0x%lx remain=%i packet=%i sync_error=%i\n",
req_addr, rx_remaining, rq->wLength.word, sync_errors);
ret_len = 0;
}
rx_remaining = rq->wLength.word;
ret_len = USB_MAX_TRANS;
if (req_addr && (req_addr % 0x1000) == 0) {
debug(DEBUG_USB,
"USB_UPLOAD_ADDR: bank=0x%02x addr=0x%08lx crc=%04x\n",
req_bank, req_addr, crc_check_bulk_memory(req_addr - 0x1000,
req_addr,
req_bank_size));
}
if (req_addr && req_addr % req_bank_size == 0) {
debug(DEBUG_USB, "USB_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx\n",
req_bank, req_addr);
req_bank++;
// shared_memory_put(SHARED_MEM_CMD_UPLOAD_PROGESS,req_bank);
}
ret_len = USB_MAX_TRANS;
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_DOWNLOAD_INIT) {
debug(DEBUG_USB, "USB_DOWNLOAD_INIT\n");
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_DOWNLOAD_ADDR) {
debug(DEBUG_USB, "USB_DOWNLOAD_ADDR\n");
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_INIT) {
req_bank = 0; req_bank = 0;
rx_remaining = 0; rx_remaining = 0;
@@ -155,13 +89,14 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_bank_size = (uint32_t) (1L << rq->wValue.word); req_bank_size = (uint32_t) (1L << rq->wValue.word);
req_bank_cnt = rq->wIndex.word; req_bank_cnt = rq->wIndex.word;
req_addr_end = (uint32_t) req_bank_size *req_bank_cnt; req_addr_end = (uint32_t) req_bank_size *req_bank_cnt;
req_percent = 0;
req_percent_last = 0;
sync_errors = 0; sync_errors = 0;
debug(DEBUG_USB, debug(DEBUG_USB,
"USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n", "USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n",
req_bank_size, req_bank_cnt, req_addr_end); req_bank_size, req_bank_cnt, req_addr_end);
shared_memory_put(SHARED_MEM_CMD_BANK_COUNT, req_bank_cnt); shared_memory_write(SHARED_MEM_TX_CMD_BANK_COUNT, req_bank_cnt);
if (req_addr == 0x000000) { if (req_addr == 0x000000) {
timer_start(); timer_start();
} }
@@ -176,6 +111,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_addr = req_addr | rq->wIndex.word; req_addr = req_addr | rq->wIndex.word;
rx_remaining = rq->wLength.word; rx_remaining = rq->wLength.word;
if (req_addr && req_addr % req_bank_size == 0) { if (req_addr && req_addr % req_bank_size == 0) {
#ifdef FLT_DEBUG #ifdef FLT_DEBUG
debug(DEBUG_USB, debug(DEBUG_USB,
@@ -187,7 +123,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_bank, req_addr, timer_stop_int()); req_bank, req_addr, timer_stop_int());
#endif #endif
req_bank++; req_bank++;
shared_memory_put(SHARED_MEM_CMD_UPLOAD_PROGESS, req_bank); shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_bank);
sram_bulk_write_start(req_addr); sram_bulk_write_start(req_addr);
timer_start(); timer_start();
@@ -206,6 +142,16 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_addr = req_addr << 16; req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word; req_addr = req_addr | rq->wIndex.word;
rx_remaining = rq->wLength.word; rx_remaining = rq->wLength.word;
req_percent = (uint32_t)( 100 * req_addr ) / req_addr_end;
if (req_percent!=req_percent_last){
//debug(DEBUG_USB,
// "USB_BULK_UPLOAD_ADDR: precent=%i\n", req_percent);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_percent);
sram_bulk_write_start(req_addr);
}
req_percent_last = req_percent;
#if 0 #if 0
if (req_addr && (req_addr % 0x1000) == 0) { if (req_addr && (req_addr % 0x1000) == 0) {
debug(DEBUG_USB, debug(DEBUG_USB,
@@ -229,7 +175,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
#endif #endif
req_bank++; req_bank++;
timer_start(); timer_start();
shared_memory_put(SHARED_MEM_CMD_BANK_CURRENT, req_bank); shared_memory_write(SHARED_MEM_TX_CMD_BANK_CURRENT, req_bank);
sram_bulk_write_start(req_addr); sram_bulk_write_start(req_addr);
} }
@@ -246,7 +192,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
debug(DEBUG_USB, "USB_BULK_UPLOAD_END:\n"); debug(DEBUG_USB, "USB_BULK_UPLOAD_END:\n");
req_state = REQ_STATUS_IDLE; req_state = REQ_STATUS_IDLE;
sram_bulk_write_end(); sram_bulk_write_end();
shared_memory_put(SHARED_MEM_CMD_UPLOAD_END, 0); shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_END, 0);
ret_len = 0; ret_len = 0;
/* /*
@@ -312,174 +258,6 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
/* /*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#define ENABLE_TEST
#ifdef ENABLE_TEST
uint8_t buffer[512];
void test_sdcard(){
uint16_t fat_cluster = 0;
uint8_t fat_attrib = 0;
uint32_t fat_size = 0;
uint32_t rom_addr = 0;
uint8_t bank_cnt = 0;
uint16_t crc = 0;
uint16_t block_cnt;
uint16_t clustervar;
uint8_t dir_attrib = 0;
uint32_t file_size = 0;
uint8_t i = 0;
#define FILENAME "mrdo.smc" //failed
#define ROMSIZE 2 // 4 == 4mbit == 512kb
#define BUFFER_SIZE 512
#define BLOCKS (ROMSIZE << 8)
while ( mmc_init() !=0) {
info("No sdcard...\n");
}
info("MMC Init done\n");
fat_init(read_buffer);
info("FAT Init done.\n");
info("\r\nDirectory\r\n");
for (i = 1;i < 240;i++){
clustervar = fat_read_dir_ent(0,i,&file_size,&dir_attrib,buffer);
if (clustervar == 0xffff){
break;
}
info("Cluster = %4x DirA = %2x FileName = %s size=%li\n",clustervar,dir_attrib,buffer,file_size);
}
info("Look for %s\n",FILENAME);
if (fat_search_file((uint8_t*)FILENAME,
&fat_cluster,
&fat_size,
&fat_attrib,
read_buffer) == 1) {
for (block_cnt=0; block_cnt<BLOCKS; block_cnt++) {
fat_read_file (fat_cluster,read_buffer,block_cnt);
if (block_cnt && block_cnt % 64 == 0){
printf("Write Ram Bank: 0x%x Addr: 0x%lx Block: %x CRC: %x\n",bank_cnt,rom_addr,block_cnt,crc);
bank_cnt++;
crc = 0;
}
}
printf("Write Ram Bank: 0x%x Addr: 0x%lx Block: %x CRC: %x\n",bank_cnt,rom_addr,block_cnt,crc);
printf("Done\n");
}
}
void test_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 1;
while (addr++ <= 0x0000ff) {
sram_write(addr, i++);
}
addr = 0x000000;
while (addr++ <= 0x0000ff) {
info("read addr=0x%08lx %x\n", addr, sram_read(addr));
}
}
void test_bulk_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 0;
sram_bulk_write_start(addr);
while (addr++ <= 0x8000) {
sram_bulk_write(i++);
sram_bulk_write_next();
}
sram_bulk_write_end();
addr = 0x000000;
sram_bulk_read_start(addr);
while (addr <= 0x8000) {
info("addr=0x%08lx %x\n", addr, sram_bulk_read());
sram_bulk_read_next();
addr++;
}
sram_bulk_read_end();
}
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr)
{
uint32_t addr = 0;
uint8_t c;
sram_bulk_read_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
c = sram_bulk_read();
if (c != 0xff)
info("addr=0x%08lx c=0x%x\n", addr, c);
sram_bulk_read_next();
}
sram_bulk_read_end();
}
void test_crc()
{
info("test_crc: clear\n");
avr_bus_active();
sram_bulk_set(0x000000, 0x10000, 0xff);
info("test_crc: crc\n");
crc_check_bulk_memory(0x000000, 0x10000, 0x8000);
info("test_crc: check\n");
test_non_zero_memory(0x000000, 0x10000);
}
#endif
void send_reset()
{
info("Reset Snes\n");
snes_reset_on();
snes_reset_lo();
_delay_ms(2);
snes_reset_hi();
snes_reset_off();
}
void send_irq()
{
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
}
void set_rom_mode()
{
if (req_bank_size == 0x8000) {
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
}
void usb_connect() void usb_connect()
@@ -505,21 +283,15 @@ void usb_connect()
void boot_startup_rom() void boot_startup_rom()
{ {
info("Activate AVR bus\n"); info("Activate AVR bus\n");
avr_bus_active(); avr_bus_active();
info("IRQ off\n"); info("IRQ off\n");
snes_irq_lo(); snes_irq_lo();
snes_irq_off(); snes_irq_off();
snes_lorom(); snes_lorom();
info("Set Snes lowrom \n"); info("Set Snes lowrom \n");
rle_decode(&_rom, ROM_BUFFER_SIZE, 0x000000); rle_decode(&_rom, ROM_BUFFER_SIZE, 0x000000);
dump_memory(0x10000 - 0x100, 0x10000); dump_memory(0x10000 - 0x100, 0x10000);
snes_reset_hi(); snes_reset_hi();
snes_reset_off(); snes_reset_off();
snes_irq_lo(); snes_irq_lo();
@@ -530,46 +302,46 @@ void boot_startup_rom()
info("Disable snes WR\n"); info("Disable snes WR\n");
snes_bus_active(); snes_bus_active();
info("Activate Snes bus\n"); info("Activate Snes bus\n");
_delay_ms(100); _delay_ms(20);
info("Reset Snes\n");
send_reset(); send_reset();
_delay_ms(100); _delay_ms(200);
#if 0
uint8_t i = 0;
i = 20;
info("Wait");
while (--i) {
_delay_ms(500);
info(".");
}
info("\n");
#endif
} }
int main(void) int main(void)
{ {
uart_init(); uart_init();
stdout = &uart_stdout; stdout = &uart_stdout;
info("Sytem start\n"); info("Sytem start\n");
system_init(); system_init();
test_sdcard();
#if 0
test_read_write(); #if 1
test_bulk_read_write(); avr_bus_active();
test_crc(); info("Activate AVR bus\n");
while (1); info("IRQ off\n");
snes_irq_lo();
snes_irq_off();
info("Set Snes lowrom\n");
snes_lorom();
info("Disable snes WR\n");
snes_wr_disable();
test_sdcard();
#endif #endif
info("Boot startup rom\n"); info("Boot startup rom\n");
boot_startup_rom(); boot_startup_rom();
usbInit(); usbInit();
usb_connect(); usb_connect();
while (1) { while (1) {
avr_bus_active(); avr_bus_active();
info("Activate AVR bus\n"); info("Activate AVR bus\n");
info("IRQ off\n"); info("IRQ off\n");
@@ -584,25 +356,18 @@ int main(void)
while (req_state != REQ_STATUS_SNES) { while (req_state != REQ_STATUS_SNES) {
usbPoll(); usbPoll();
} }
shared_memory_put(SHARED_MEM_CMD_TERMINATE, 0); shared_memory_write(SHARED_MEM_TX_CMD_TERMINATE, 0);
info("USB poll done\n"); info("USB poll done\n");
snes_reset_hi();
snes_reset_off();
snes_irq_lo();
snes_irq_off();
info("IRQ off\n");
set_rom_mode(); set_rom_mode();
snes_wr_disable(); snes_wr_disable();
info("Disable snes WR\n"); info("Disable snes WR\n");
snes_bus_active(); snes_bus_active();
info("Activate Snes bus\n"); info("Activate Snes bus\n");
_delay_ms(100); _delay_ms(100);
info("Reset Snes\n");
send_reset(); send_reset();
info("Poll\n"); info("Poll\n");
while (req_state != REQ_STATUS_AVR) { while (req_state != REQ_STATUS_AVR) {
usbPoll(); usbPoll();
#ifdef DO_IRQ #ifdef DO_IRQ
@@ -640,6 +405,8 @@ int main(void)
info("Read 0x3000=%c\n", c); info("Read 0x3000=%c\n", c);
#endif #endif
} }
info("Boot startup rom\n");
boot_startup_rom();
} }
return 0; return 0;

View File

@@ -1,6 +1,33 @@
#include "mmc.h" /*
* ####################################################################################### 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 <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#include "mmc.h"
uint8_t mmc_init() uint8_t mmc_init()
{ {
uint16_t Timeout = 0, i; uint16_t Timeout = 0, i;
@@ -36,7 +63,6 @@ uint8_t mmc_init()
} }
return (0); return (0);
} }
uint8_t mmc_write_command(uint8_t * cmd) uint8_t mmc_write_command(uint8_t * cmd)
{ {
uint8_t tmp = 0xff; uint8_t tmp = 0xff;

View File

@@ -1,8 +1,15 @@
#ifndef _MMC_H_ /*
#define _MMC_H_ * ####################################################################################### Connect ARM to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig #######################################################################################
*/
#include <avr/io.h>
#ifndef _MMC_H
#define _MMC_H
#define SPI_Mode 0 // 1 = Hardware SPI | 0 = Software SPI
#define MMC_WRITE PORTB #define MMC_WRITE PORTB
#define MMC_READ PINB #define MMC_READ PINB
@@ -12,18 +19,26 @@
#define MMC_DO PB6 #define MMC_DO PB6
#define MMC_DI PB5 #define MMC_DI PB5
#define MMC_CLK PB7 #define MMC_CLK PB7
#define MMC_WRITE PORTB // Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_READ PINB
#define MMC_REG DDRB
extern uint8_t mmc_read_byte(void); extern uint8_t mmc_read_byte(void);
extern void mmc_write_byte(uint8_t); extern void mmc_write_byte(uint8_t);
extern void mmc_read_block(uint8_t *, uint8_t *, unsigned in); extern void mmc_read_block(uint8_t *, uint8_t *, unsigned in);
extern uint8_t mmc_init(void); extern uint8_t mmc_init(void);
extern uint8_t mmc_read_sector(uint32_t, uint8_t *); extern uint8_t mmc_read_sector(unsigned long, uint8_t *);
extern uint8_t mmc_write_sector(uint32_t, uint8_t *); extern uint8_t mmc_write_sector(unsigned long, uint8_t *);
extern uint8_t mmc_write_command(uint8_t *); extern uint8_t mmc_write_command(uint8_t *);
extern uint8_t mmc_read_csd(uint8_t *);
extern uint8_t mmc_read_cid(uint8_t *);
#define mmc_disable() MMC_WRITE|= (1<<MMC_CS); #define mmc_disable() MMC_WRITE|= (1<<MMC_CS);
#define mmc_enable() MMC_WRITE&=~(1<<MMC_CS); #define mmc_enable() MMC_WRITE&=~(1<<MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif #endif

View File

@@ -38,20 +38,21 @@ uint8_t scratchpad_state;
uint8_t scratchpad_cmd; uint8_t scratchpad_cmd;
uint8_t scratchpad_payload; uint8_t scratchpad_payload;
void shared_memory_scratchpad_save() void shared_memory_scratchpad_tx_save()
{ {
scratchpad_state = sram_read(SHARED_MEM_LOC_STATE); scratchpad_state = sram_read(SHARED_MEM_TX_LOC_STATE);
scratchpad_cmd = sram_read(SHARED_MEM_LOC_CMD); scratchpad_cmd = sram_read(SHARED_MEM_TX_LOC_CMD);
scratchpad_payload = sram_read(SHARED_MEM_LOC_PAYLOAD); scratchpad_payload = sram_read(SHARED_MEM_TX_LOC_PAYLOAD);
} }
void shared_memory_scratchpad_restore() void shared_memory_scratchpad_tx_restore()
{ {
sram_write(SHARED_MEM_LOC_STATE, scratchpad_state); sram_write(SHARED_MEM_TX_LOC_STATE, scratchpad_state);
sram_write(SHARED_MEM_LOC_CMD, scratchpad_cmd); sram_write(SHARED_MEM_TX_LOC_CMD, scratchpad_cmd);
sram_write(SHARED_MEM_LOC_PAYLOAD, scratchpad_payload); sram_write(SHARED_MEM_TX_LOC_PAYLOAD, scratchpad_payload);
} }
void shared_memory_irq_hook() void shared_memory_irq_hook()
{ {
irq_addr_lo = sram_read(SHARED_IRQ_LOC_LO); irq_addr_lo = sram_read(SHARED_IRQ_LOC_LO);
@@ -66,24 +67,33 @@ void shared_memory_irq_restore()
sram_write(SHARED_IRQ_LOC_HI, irq_addr_hi); sram_write(SHARED_IRQ_LOC_HI, irq_addr_hi);
} }
void shared_memory_put(uint8_t cmd, uint8_t value) void shared_memory_write(uint8_t cmd, uint8_t value)
{ {
info("Write shared memory 0x%04x=0x%02x 0x%04x=0x%02x \n", debug(DEBUG_SHM,"shared_memory_write: 0x%04x=0x%02x 0x%04x=0x%02x \n",
SHARED_MEM_LOC_CMD, cmd, SHARED_MEM_LOC_PAYLOAD, value); SHARED_MEM_TX_LOC_CMD, cmd, SHARED_MEM_TX_LOC_PAYLOAD, value);
shared_memory_scratchpad_save(); sram_bulk_addr_save();
shared_memory_scratchpad_tx_save();
shared_memory_irq_hook(); shared_memory_irq_hook();
sram_write(SHARED_MEM_LOC_STATE, SHARED_MEM_SNES_ACK); sram_write(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_SNES_ACK);
sram_write(SHARED_MEM_LOC_CMD, cmd); sram_write(SHARED_MEM_TX_LOC_CMD, cmd);
sram_write(SHARED_MEM_LOC_PAYLOAD, value); sram_write(SHARED_MEM_TX_LOC_PAYLOAD, value);
snes_hirom(); snes_hirom();
snes_wr_disable(); snes_wr_disable();
snes_bus_active(); snes_bus_active();
_delay_ms(50);
#if SHARED_MEM_SWITCH_IRQ
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
#else
_delay_ms(SHARED_MEM_SWITCH_DELAY);
#endif
avr_bus_active(); avr_bus_active();
snes_irq_lo(); snes_irq_lo();
@@ -91,7 +101,62 @@ void shared_memory_put(uint8_t cmd, uint8_t value)
snes_lorom(); snes_lorom();
snes_wr_disable(); snes_wr_disable();
shared_memory_scratchpad_restore(); shared_memory_scratchpad_tx_restore();
shared_memory_irq_restore(); shared_memory_irq_restore();
sram_bulk_addr_restore();
} }
void shared_memory_yield()
{
snes_hirom();
snes_wr_disable();
snes_bus_active();
_delay_ms(SHARED_MEM_SWITCH_DELAY);
avr_bus_active();
snes_lorom();
snes_wr_disable();
}
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer)
{
uint8_t state;
state = sram_read(SHARED_MEM_RX_LOC_STATE);
if (state != SHARED_MEM_RX_AVR_ACK){
return 1;
}
sram_bulk_addr_save();
*cmd = sram_read(SHARED_MEM_RX_LOC_CMD);
*len = sram_read(SHARED_MEM_RX_LOC_LEN);
debug(DEBUG_SHM,"shared_memory_read: 0x%04x=0x%02x 0x%04x=0x%02x \n",
SHARED_MEM_RX_LOC_CMD, *cmd, SHARED_MEM_RX_LOC_LEN, *len);
sram_bulk_read_buffer(SHARED_MEM_RX_LOC_PAYLOAD,buffer, *len);
sram_write(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_AVR_RTS);
snes_hirom();
snes_wr_disable();
snes_bus_active();
#if SHARED_MEM_SWITCH_IRQ
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
#else
_delay_ms(SHARED_MEM_SWITCH_DELAY);
#endif
avr_bus_active();
snes_lorom();
snes_wr_disable();
sram_bulk_addr_restore();
return 0;
}

View File

@@ -22,30 +22,45 @@
#define __SHARED_MEMORY_H__ #define __SHARED_MEMORY_H__
#define SHARED_MEM_SNES_ACK 0xa5 #define SHARED_MEM_SWITCH_IRQ 0
#define SHARED_MEM_SNES_RTS 0x5a #define SHARED_MEM_SWITCH_DELAY 20
#define SHARED_MEM_TX_SNES_ACK 0xa5
#define SHARED_MEM_TX_SNES_RTS 0x5a
#define SHARED_MEM_CMD_BANK_COUNT 0 #define SHARED_MEM_TX_CMD_BANK_COUNT 0x00
#define SHARED_MEM_CMD_BANK_CURRENT 1 #define SHARED_MEM_TX_CMD_BANK_CURRENT 0x01
#define SHARED_MEM_CMD_UPLOAD_START 3 #define SHARED_MEM_TX_CMD_UPLOAD_START 0x03
#define SHARED_MEM_CMD_UPLOAD_END 4 #define SHARED_MEM_TX_CMD_UPLOAD_END 0x04
#define SHARED_MEM_CMD_UPLOAD_PROGESS 5 #define SHARED_MEM_TX_CMD_UPLOAD_PROGESS 0x05
#define SHARED_MEM_CMD_TERMINATE 6 #define SHARED_MEM_TX_CMD_TERMINATE 0x06
#define SHARED_MEM_TX_LOC_STATE 0x000000
#define SHARED_MEM_TX_LOC_CMD 0x000001
#define SHARED_MEM_TX_LOC_PAYLOAD 0x000002
#define SHARED_MEM_LOC_STATE 0x000000 #define SHARED_MEM_RX_AVR_ACK 0xa5
#define SHARED_MEM_LOC_CMD 0x000001 #define SHARED_MEM_RX_AVR_RTS 0x5a
#define SHARED_MEM_LOC_PAYLOAD 0x000002
#define SHARED_MEM_RX_CMD_PRINFT 0x00
#define SHARED_MEM_RX_CMD_FILESEL 0x01
#define SHARED_MEM_RX_LOC_STATE 0x001000
#define SHARED_MEM_RX_LOC_CMD 0x001001
#define SHARED_MEM_RX_LOC_LEN 0x001002
#define SHARED_MEM_RX_LOC_PAYLOAD 0x001003
#define SHARED_IRQ_LOC_LO 0x00fffe #define SHARED_IRQ_LOC_LO 0x00fffe
#define SHARED_IRQ_LOC_HI 0x00ffff #define SHARED_IRQ_LOC_HI 0x00ffff
/* Use COP IRQ LOC for hooked IRQ handler */
#define SHARED_IRQ_HANDLER_LO 0x0ffe4
#define SHARED_IRQ_HANDLER_HI 0x0ffe5
#define SHARED_IRQ_HANDLER_LO 0x00
#define SHARED_IRQ_HANDLER_HI 0x10
void shared_memory_put(uint8_t cmd, uint8_t value);
void shared_memory_write(uint8_t cmd, uint8_t value);
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer);
#endif #endif

View File

@@ -22,8 +22,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> /* for _delay_ms() */ #include <util/delay.h>
#include "config.h" #include "config.h"
#include "sram.h" #include "sram.h"
@@ -31,6 +30,10 @@
#include "debug.h" #include "debug.h"
#include "info.h" #include "info.h"
uint32_t addr_current = 0;
uint32_t addr_stash = 0;
void system_init(void) void system_init(void)
{ {
/*-------------------------------------------------*/ /*-------------------------------------------------*/
@@ -93,19 +96,19 @@ void system_init(void)
void sreg_set(uint32_t addr) void sreg_set(uint32_t addr)
{ {
uint8_t i = 24; uint8_t i = 24;
debug(DEBUG_SREG,"sreg_set: addr=0x%08lx",addr); debug(DEBUG_SRAM,"sreg_set: addr=0x%08lx\n",addr);
while(i--) { while(i--) {
if ((addr & ( 1L << i))){ if ((addr & ( 1L << i))){
debug(DEBUG_SREG,"1"); debug(DEBUG_SRAM,"1");
AVR_ADDR_SER_PORT |= ( 1 << AVR_ADDR_SER_PIN); AVR_ADDR_SER_PORT |= ( 1 << AVR_ADDR_SER_PIN);
} else { } else {
AVR_ADDR_SER_PORT &= ~( 1 << AVR_ADDR_SER_PIN); AVR_ADDR_SER_PORT &= ~( 1 << AVR_ADDR_SER_PIN);
debug(DEBUG_SREG,"0"); debug(DEBUG_SRAM,"0");
} }
AVR_ADDR_SCK_PORT |= (1 << AVR_ADDR_SCK_PIN); AVR_ADDR_SCK_PORT |= (1 << AVR_ADDR_SCK_PIN);
AVR_ADDR_SCK_PORT &= ~(1 << AVR_ADDR_SCK_PIN); AVR_ADDR_SCK_PORT &= ~(1 << AVR_ADDR_SCK_PIN);
} }
debug(DEBUG_SREG,"\n"); debug(DEBUG_SRAM,"\n");
AVR_ADDR_LATCH_PORT |= (1 << AVR_ADDR_LATCH_PIN); AVR_ADDR_LATCH_PORT |= (1 << AVR_ADDR_LATCH_PIN);
AVR_ADDR_LATCH_PORT &= ~(1 << AVR_ADDR_LATCH_PIN); AVR_ADDR_LATCH_PORT &= ~(1 << AVR_ADDR_LATCH_PIN);
@@ -113,11 +116,23 @@ void sreg_set(uint32_t addr)
} }
inline void sram_bulk_addr_save()
{
addr_stash = addr_current;
}
inline void sram_bulk_addr_restore()
{
sreg_set(addr_stash);
}
void sram_bulk_read_start(uint32_t addr) void sram_bulk_read_start(uint32_t addr)
{ {
debug(DEBUG_SRAM,"sram_bulk_read_start: addr=0x%08lx\n\r", addr); debug(DEBUG_SRAM,"sram_bulk_read_start: addr=0x%08lx\n\r", addr);
addr_current = addr;
avr_data_in(); avr_data_in();
AVR_CS_PORT &= ~(1 << AVR_CS_PIN); AVR_CS_PORT &= ~(1 << AVR_CS_PIN);
@@ -138,6 +153,7 @@ void sram_bulk_read_start(uint32_t addr)
inline void sram_bulk_read_next(void) inline void sram_bulk_read_next(void)
{ {
addr_current++;
AVR_RD_PORT |= (1 << AVR_RD_PIN); AVR_RD_PORT |= (1 << AVR_RD_PIN);
counter_up(); counter_up();
AVR_RD_PORT &= ~(1 << AVR_RD_PIN); AVR_RD_PORT &= ~(1 << AVR_RD_PIN);
@@ -309,48 +325,3 @@ void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value){
sram_bulk_write_end(); sram_bulk_write_end();
} }
void sram_setr(uint32_t addr, uint32_t len,uint8_t value)
{
uint32_t i;
debug(DEBUG_SRAM,"sram_clear: addr=0x%08lx len=%li\n\r", addr,len);
for (i = addr; i < (addr + len); i++) {
if (0 == i % 0xfff)
debug(DEBUG_SRAM,"sram_clear: addr=0x%08lx\n\r", i);
sram_write(i, value);
}
}
void sram_copy(uint32_t addr, uint8_t * src, uint32_t len)
{
uint32_t i;
uint8_t *ptr = src;
debug(DEBUG_SRAM,"sram_copy: addr=0x%08lx src=0x%p len=%li\n\r", addr,src,len);
for (i = addr; i < (addr + len); i++)
sram_write(i, *ptr++);
}
void sram_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
{
uint32_t i;
uint8_t *ptr = dst;
debug(DEBUG_SRAM,"sram_read_buffer: addr=0x%08lx dst=0x%p len=%li\n\r", addr,dst,len);
for (i = addr; i < (addr + len); i++) {
*ptr = sram_read(i);
ptr++;
}
}
uint8_t sram_check(uint8_t * buffer, uint32_t len)
{
uint16_t cnt;
debug(DEBUG_SRAM,"sram_check: len=%li\n\r",len);
for (cnt = 0; cnt < len; cnt++)
if (buffer[cnt])
return 1;
return 0;
}

View File

@@ -186,9 +186,6 @@ void sreg_set(uint32_t addr);
uint8_t sram_read(uint32_t addr); uint8_t sram_read(uint32_t addr);
void sram_write(uint32_t addr, uint8_t data); void sram_write(uint32_t addr, uint8_t data);
void sram_set(uint32_t addr, uint32_t len, uint8_t value);
void sram_copy(uint32_t addr,uint8_t *src, uint32_t len);
void sram_read_buffer(uint32_t addr,uint8_t *dst, uint32_t len);
void sram_bulk_read_start(uint32_t addr); void sram_bulk_read_start(uint32_t addr);
inline void sram_bulk_read_next(void); inline void sram_bulk_read_next(void);
@@ -204,4 +201,9 @@ void sram_bulk_copy(uint32_t addr, uint8_t * src, uint32_t len);
void sram_bulk_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len); void sram_bulk_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len);
void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value); void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value);
inline void sram_bulk_addr_save();
inline void sram_bulk_addr_restore();
#endif #endif

156
avr/usbload/testing.c Normal file
View File

@@ -0,0 +1,156 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <util/delay.h>
#include "shared_memory.h"
#include "config.h"
#include "sram.h"
#include "debug.h"
#include "crc.h"
#include "config.h"
#include "info.h"
#include "mmc.h"
#include "fat.h"
#include "file.h"
#include "dir.h"
void test_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 1;
while (addr++ <= 0x0000ff) {
sram_write(addr, i++);
}
addr = 0x000000;
while (addr++ <= 0x0000ff) {
info("read addr=0x%08lx %x\n", addr, sram_read(addr));
}
}
void test_bulk_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 0;
sram_bulk_write_start(addr);
while (addr++ <= 0x8000) {
sram_bulk_write(i++);
sram_bulk_write_next();
}
sram_bulk_write_end();
addr = 0x000000;
sram_bulk_read_start(addr);
while (addr <= 0x8000) {
info("addr=0x%08lx %x\n", addr, sram_bulk_read());
sram_bulk_read_next();
addr++;
}
sram_bulk_read_end();
}
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr)
{
uint32_t addr = 0;
uint8_t c;
sram_bulk_read_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
c = sram_bulk_read();
if (c != 0xff)
info("addr=0x%08lx c=0x%x\n", addr, c);
sram_bulk_read_next();
}
sram_bulk_read_end();
}
void test_crc()
{
info("test_crc: clear\n");
avr_bus_active();
sram_bulk_set(0x000000, 0x10000, 0xff);
info("test_crc: crc\n");
crc_check_bulk_memory(0x000000, 0x10000, 0x8000);
info("test_crc: check\n");
test_non_zero_memory(0x000000, 0x10000);
}
void test_sdcard(void){
while (mmc_init() !=0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
printf("no sdcard\n");
}
if (fat_initfat()==0){
printf("fatinit ok\n");
} else {
printf("fatinit failed\n");
return;
}
printf("Root dirlist\n");
ffls_smc();
dump_memory(DIR_ENTRY_LOC , DIR_ENTRY_LOC + (64 * 2));
dir_entry_loop();
while(1);
#if (WRITE==1)
char datei[12]="test.txt"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
fat_str(datei);
ffrm( datei ); // löschen der datei/ordner falls vorhanden
printf("open %s\n",datei);
ffopen( datei );
printf("write %s\n",datei);
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
printf("close %s\n",datei);
ffclose();
printf("open %s\n",datei);
ffopen( datei );
printf("open %s\n",datei);
unsigned long int seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten !
do{
printf("%c",ffread()); // liest ein zeichen und gibt es über uart aus !
}while(--seek); // liest solange bytes da sind (von datei länge bis 0)
ffclose(); // schließt datei
#endif
}

32
avr/usbload/testing.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __TESTING_H__
#define __TESTING_H__
void test_read_write();
void test_bulk_read_write();
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr);
void test_crc();
void test_sdcard();
#endif

View File

@@ -37,3 +37,4 @@ static int uart_stream(char c, FILE *stream);
#endif #endif

View File

@@ -60,16 +60,7 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
rx_remaining, len); rx_remaining, len);
len = rx_remaining; len = rx_remaining;
} }
if (req_state == REQ_STATUS_UPLOAD) { if (req_state == REQ_STATUS_BULK_UPLOAD) {
rx_remaining -= len;
debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n",
req_addr, len, rx_remaining);
debug(DEBUG_USB_TRANS,"usbFunctionWrite %02x %02x %02x %02x %02x %02x %02x %x\n",
data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
sram_copy(req_addr, data, len);
req_addr += len;
} else if (req_state == REQ_STATUS_BULK_UPLOAD) {
rx_remaining -= len; rx_remaining -= len;
debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n", debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n",

View File

@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>currentDocument</key>
<string>avr/usbload/dir.c</string>
<key>documents</key> <key>documents</key>
<array> <array>
<dict> <dict>
@@ -19,6 +21,558 @@
<integer>271</integer> <integer>271</integer>
<key>metaData</key> <key>metaData</key>
<dict> <dict>
<key>avr/bootloader/bootloader.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>6</integer>
<key>line</key>
<integer>268</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>381</integer>
</dict>
<key>avr/bootloader/config.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>22</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/config.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>38</integer>
<key>line</key>
<integer>28</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/crc.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>53</integer>
</dict>
<key>avr/usbload/crc.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>26</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>25</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>26</integer>
</dict>
</dict>
<key>avr/usbload/dir.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>27</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>45</integer>
</dict>
<key>avr/usbload/dir.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>3</integer>
<key>line</key>
<integer>48</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>13</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>48</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>6</integer>
<key>line</key>
<integer>48</integer>
</dict>
</dict>
<key>avr/usbload/dump.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>26</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>1</integer>
</dict>
<key>avr/usbload/dump.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/fat.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>13</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>12</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>13</integer>
</dict>
</dict>
<key>avr/usbload/fat.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>15</integer>
<key>line</key>
<integer>71</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>13</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>13</integer>
<key>line</key>
<integer>71</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>25</integer>
<key>line</key>
<integer>71</integer>
</dict>
</dict>
<key>avr/usbload/fifo.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>19</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/file.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>20</integer>
<key>line</key>
<integer>33</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>1</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>16</integer>
<key>line</key>
<integer>33</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>20</integer>
<key>line</key>
<integer>33</integer>
</dict>
</dict>
<key>avr/usbload/file.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>20</integer>
<key>line</key>
<integer>20</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/main.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>320</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>313</integer>
</dict>
<key>avr/usbload/mmc.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>220</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>169</integer>
</dict>
<key>avr/usbload/mmc.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>39</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/shared_memory.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>111</integer>
</dict>
<key>avr/usbload/shared_memory.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>48</integer>
<key>line</key>
<integer>51</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>14</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>44</integer>
<key>line</key>
<integer>51</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>52</integer>
<key>line</key>
<integer>51</integer>
</dict>
</dict>
<key>avr/usbload/sram.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>299</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>273</integer>
</dict>
<key>avr/usbload/sram.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>3</integer>
<key>line</key>
<integer>200</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>158</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>71</integer>
<key>line</key>
<integer>200</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>3</integer>
<key>line</key>
<integer>200</integer>
</dict>
</dict>
<key>avr/usbload/testing.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>31</integer>
<key>line</key>
<integer>147</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>105</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>27</integer>
<key>line</key>
<integer>147</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>31</integer>
<key>line</key>
<integer>147</integer>
</dict>
</dict>
<key>avr/usbload/testing.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>poc/avr_sdcard/fat.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>38</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>poc/avr_sdcard/fat.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>4</integer>
<key>line</key>
<integer>63</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>23</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>1</integer>
<key>line</key>
<integer>63</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>9</integer>
<key>line</key>
<integer>63</integer>
</dict>
</dict>
<key>poc/avr_sdcard/main.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>12</integer>
<key>line</key>
<integer>170</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>137</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>1</integer>
<key>line</key>
<integer>170</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>20</integer>
<key>line</key>
<integer>170</integer>
</dict>
</dict>
<key>poc/avr_sdcard/main.lst</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>poc/avr_usbload/sram.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>17</integer>
<key>line</key>
<integer>5</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>snes/banktest/LoadGraphics.asm</key> <key>snes/banktest/LoadGraphics.asm</key>
<dict> <dict>
<key>caret</key> <key>caret</key>
@@ -47,7 +601,52 @@
<key>firstVisibleLine</key> <key>firstVisibleLine</key>
<integer>211</integer> <integer>211</integer>
</dict> </dict>
<key>tools/ucon64/2.0/src/console/snes.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>28</integer>
<key>line</key>
<integer>1135</integer>
</dict> </dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>1952</integer>
</dict>
</dict>
<key>openDocuments</key>
<array>
<string>avr/usbload/testing.h</string>
<string>avr/usbload/testing.c</string>
<string>avr/usbload/mmc.c</string>
<string>poc/avr_sdcard/fat.c</string>
<string>poc/avr_sdcard/fat.h</string>
<string>poc/avr_sdcard/main.lst</string>
<string>avr/bootloader/config.h</string>
<string>avr/bootloader/bootloader.c</string>
<string>avr/usbload/dir.h</string>
<string>avr/usbload/dump.h</string>
<string>avr/usbload/file.c</string>
<string>avr/usbload/fat.h</string>
<string>avr/usbload/file.h</string>
<string>avr/usbload/crc.c</string>
<string>avr/usbload/fat.c</string>
<string>avr/usbload/dir.c</string>
<string>avr/usbload/dump.c</string>
<string>avr/usbload/config.h</string>
<string>tools/ucon64/2.0/src/console/snes.c</string>
<string>poc/avr_sdcard/main.c</string>
<string>poc/avr_usbload/sram.c</string>
<string>avr/usbload/sram.h</string>
<string>avr/usbload/shared_memory.h</string>
<string>avr/usbload/shared_memory.c</string>
<string>avr/usbload/fifo.h</string>
<string>avr/usbload/main.c</string>
<string>avr/usbload/sram.c</string>
<string>avr/usbload/crc.h</string>
</array>
<key>showFileHierarchyDrawer</key> <key>showFileHierarchyDrawer</key>
<false/> <false/>
<key>showFileHierarchyPanel</key> <key>showFileHierarchyPanel</key>
@@ -66,6 +665,13 @@
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>bootloader</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>usbload</key> <key>usbload</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
@@ -75,55 +681,31 @@
</dict> </dict>
</dict> </dict>
</dict> </dict>
<key>poc</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>avr_sdcard</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
</dict>
</dict>
<key>scripts</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>snes</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>tools</key> <key>tools</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>ff</key> <key>ucon64</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>ffsample</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>avr</key> <key>2.0</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>src</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>console</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
@@ -132,12 +714,9 @@
</dict> </dict>
</dict> </dict>
</dict> </dict>
<key>huffman</key> </dict>
<dict> </dict>
<key>isExpanded</key> </dict>
<true/>
<key>subItems</key>
<dict/>
</dict> </dict>
</dict> </dict>
</dict> </dict>