Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac85195bb8 |
@@ -30,16 +30,11 @@ 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 \
|
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 huffman-decode.o rle.c loader.o info.o shared_memory.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 testing.o rtc.o mmc.o ff.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 \
|
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
|
||||||
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)
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* =====================================================================================
|
|
||||||
*
|
|
||||||
* ________ .__ __ ________ ____ ________
|
|
||||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
|
||||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
|
||||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
|
||||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
|
||||||
* \__> \/ \/ \/ \/ \/
|
|
||||||
*
|
|
||||||
* 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,7 +29,6 @@
|
|||||||
#define DEBUG_SRAM_RAW 16
|
#define DEBUG_SRAM_RAW 16
|
||||||
#define DEBUG_SREG 32
|
#define DEBUG_SREG 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
|
||||||
|
|||||||
@@ -91,13 +91,31 @@ 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_bulk_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
|
sram_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;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
/*-----------------------------------------------------------------------
|
|
||||||
/ Low level disk interface modlue include file R0.05 (C)ChaN, 2007
|
|
||||||
/-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _DISKIO
|
|
||||||
|
|
||||||
#define _READONLY 0 /* 1: Read-only mode */
|
|
||||||
#define _USE_IOCTL 1
|
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
|
||||||
typedef BYTE DSTATUS;
|
|
||||||
|
|
||||||
/* Results of Disk Functions */
|
|
||||||
typedef enum {
|
|
||||||
RES_OK = 0, /* 0: Successful */
|
|
||||||
RES_ERROR, /* 1: R/W Error */
|
|
||||||
RES_WRPRT, /* 2: Write Protected */
|
|
||||||
RES_NOTRDY, /* 3: Not Ready */
|
|
||||||
RES_PARERR /* 4: Invalid Parameter */
|
|
||||||
} DRESULT;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------*/
|
|
||||||
/* Prototypes for disk control functions */
|
|
||||||
|
|
||||||
DSTATUS disk_initialize (BYTE);
|
|
||||||
DSTATUS disk_status (BYTE);
|
|
||||||
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
|
||||||
#if _READONLY == 0
|
|
||||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
|
||||||
#endif
|
|
||||||
DRESULT disk_ioctl (BYTE, BYTE, void*);
|
|
||||||
void disk_timerproc (void);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Disk Status Bits (DSTATUS) */
|
|
||||||
|
|
||||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
|
||||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
|
||||||
#define STA_PROTECT 0x04 /* Write protected */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Command code for disk_ioctrl() */
|
|
||||||
|
|
||||||
/* Generic command */
|
|
||||||
#define CTRL_SYNC 0 /* Mandatory for write functions */
|
|
||||||
#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
|
|
||||||
#define GET_SECTOR_SIZE 2
|
|
||||||
#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
|
|
||||||
#define CTRL_POWER 4
|
|
||||||
#define CTRL_LOCK 5
|
|
||||||
#define CTRL_EJECT 6
|
|
||||||
/* MMC/SDC command */
|
|
||||||
#define MMC_GET_TYPE 10
|
|
||||||
#define MMC_GET_CSD 11
|
|
||||||
#define MMC_GET_CID 12
|
|
||||||
#define MMC_GET_OCR 13
|
|
||||||
#define MMC_GET_SDSTAT 14
|
|
||||||
/* ATA/CF command */
|
|
||||||
#define ATA_GET_REV 20
|
|
||||||
#define ATA_GET_MODEL 21
|
|
||||||
#define ATA_GET_SN 22
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Card type flags (CardType) */
|
|
||||||
#define CT_MMC 0x01
|
|
||||||
#define CT_SD1 0x02
|
|
||||||
#define CT_SD2 0x04
|
|
||||||
#define CT_SDC (CT_SD1|CT_SD2)
|
|
||||||
#define CT_BLOCK 0x08
|
|
||||||
|
|
||||||
|
|
||||||
#define _DISKIO
|
|
||||||
#endif
|
|
||||||
2936
avr/usbload/ff.c
2936
avr/usbload/ff.c
File diff suppressed because it is too large
Load Diff
547
avr/usbload/ff.h
547
avr/usbload/ff.h
@@ -1,547 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ FatFs - FAT file system module include file R0.07a (C)ChaN, 2009
|
|
||||||
/----------------------------------------------------------------------------/
|
|
||||||
/ FatFs module is an open source software to implement FAT file system to
|
|
||||||
/ small embedded systems. This is a free software and is opened for education,
|
|
||||||
/ research and commercial developments under license policy of following trems.
|
|
||||||
/
|
|
||||||
/ Copyright (C) 2009, ChaN, all right reserved.
|
|
||||||
/
|
|
||||||
/ * The FatFs module is a free software and there is NO WARRANTY.
|
|
||||||
/ * No restriction on use. You can use, modify and redistribute it for
|
|
||||||
/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
|
|
||||||
/ * Redistributions of source code must retain the above copyright notice.
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ FatFs Configuration Options
|
|
||||||
/
|
|
||||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
|
||||||
/ the configuration options.
|
|
||||||
/
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
#ifndef _FATFS
|
|
||||||
#define _FATFS
|
|
||||||
|
|
||||||
#define _WORD_ACCESS 1
|
|
||||||
/* The _WORD_ACCESS option defines which access method is used to the word
|
|
||||||
/ data in the FAT structure.
|
|
||||||
/
|
|
||||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
|
||||||
/ 1: Word access. Do not choose this unless following condition is met.
|
|
||||||
/
|
|
||||||
/ When the byte order on the memory is big-endian or address miss-aligned
|
|
||||||
/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
|
|
||||||
/ If it is not the case, the value can also be set to 1 to improve the
|
|
||||||
/ performance and code efficiency. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _FS_READONLY 0
|
|
||||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
|
||||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
|
||||||
/ f_truncate and useless f_getfree. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _FS_MINIMIZE 0
|
|
||||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
|
||||||
/
|
|
||||||
/ 0: Full function.
|
|
||||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
|
||||||
/ are removed.
|
|
||||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
|
||||||
/ 3: f_lseek is removed in addition to level 2. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _FS_TINY 1
|
|
||||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
|
||||||
/ object instead of the sector buffer in the individual file object for file
|
|
||||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_STRFUNC 0
|
|
||||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_MKFS 1
|
|
||||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_FORWARD 0
|
|
||||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _DRIVES 2
|
|
||||||
/* Number of volumes (logical drives) to be used. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _MAX_SS 512
|
|
||||||
/* Maximum sector size to be handled. (512/1024/2048/4096) */
|
|
||||||
/* 512 for memroy card and hard disk, 1024 for floppy disk, 2048 for MO disk */
|
|
||||||
|
|
||||||
|
|
||||||
#define _MULTI_PARTITION 0
|
|
||||||
/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
|
|
||||||
/ drive number and can mount only first primaly partition. When it is set to 1,
|
|
||||||
/ each volume is tied to the partitions listed in Drives[]. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _CODE_PAGE 437
|
|
||||||
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
|
||||||
/ When it is non LFN configuration, there is no difference between SBCS code
|
|
||||||
/ pages. When LFN is enabled, the code page must always be set correctly.
|
|
||||||
/ 437 - U.S.
|
|
||||||
/ 720 - Arabic
|
|
||||||
/ 737 - Greek
|
|
||||||
/ 775 - Baltic
|
|
||||||
/ 850 - Multilingual Latin 1
|
|
||||||
/ 852 - Latin 2
|
|
||||||
/ 855 - Cyrillic
|
|
||||||
/ 857 - Turkish
|
|
||||||
/ 858 - Multilingual Latin 1 + Euro
|
|
||||||
/ 862 - Hebrew
|
|
||||||
/ 866 - Russian
|
|
||||||
/ 874 - Thai
|
|
||||||
/ 932 - Japanese Shift-JIS (DBCS)
|
|
||||||
/ 936 - Simplified Chinese GBK (DBCS)
|
|
||||||
/ 949 - Korean (DBCS)
|
|
||||||
/ 950 - Traditional Chinese Big5 (DBCS)
|
|
||||||
/ 1258 - Vietnam
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_LFN 0
|
|
||||||
#define _MAX_LFN 255 /* Maximum LFN length to handle (max:255) */
|
|
||||||
/* The _USE_LFN option switches the LFN support.
|
|
||||||
/
|
|
||||||
/ 0: Disable LFN.
|
|
||||||
/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
|
|
||||||
/ 2: Enable LFN with dynamic working buffer on the caller's STACK.
|
|
||||||
/
|
|
||||||
/ The working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN,
|
|
||||||
/ a Unicode - OEM code conversion function ff_convert() must be added to
|
|
||||||
/ the project. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _FS_REENTRANT 0
|
|
||||||
#define _TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
|
||||||
#define _SYNC_t HANDLE /* Type of sync object used on the OS. */
|
|
||||||
/* e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
|
||||||
/* To make the FatFs module re-entrant, set _FS_REENTRANT to 1 and add user
|
|
||||||
/ provided synchronization handlers, ff_req_grant, ff_rel_grant,
|
|
||||||
/ ff_del_syncobj and ff_cre_syncobj function to the project. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of configuration options. Do not change followings without care. */
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Definitions corresponds to multiple sector size */
|
|
||||||
|
|
||||||
#if _MAX_SS == 512
|
|
||||||
#define SS(fs) 512
|
|
||||||
#else
|
|
||||||
#if _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096
|
|
||||||
#define SS(fs) ((fs)->s_size)
|
|
||||||
#else
|
|
||||||
#error Sector size must be 512, 1024, 2048 or 4096.
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File system object structure */
|
|
||||||
|
|
||||||
typedef struct _FATFS {
|
|
||||||
BYTE fs_type; /* FAT sub type */
|
|
||||||
BYTE drive; /* Physical drive number */
|
|
||||||
BYTE csize; /* Number of sectors per cluster */
|
|
||||||
BYTE n_fats; /* Number of FAT copies */
|
|
||||||
BYTE wflag; /* win[] dirty flag (1:must be written back) */
|
|
||||||
BYTE pad1;
|
|
||||||
WORD id; /* File system mount ID */
|
|
||||||
WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
|
|
||||||
#if _FS_REENTRANT
|
|
||||||
_SYNC_t sobj; /* Identifier of sync object */
|
|
||||||
#endif
|
|
||||||
#if _MAX_SS != 512U
|
|
||||||
WORD s_size; /* Sector size */
|
|
||||||
#endif
|
|
||||||
#if !_FS_READONLY
|
|
||||||
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
|
|
||||||
BYTE pad2;
|
|
||||||
DWORD last_clust; /* Last allocated cluster */
|
|
||||||
DWORD free_clust; /* Number of free clusters */
|
|
||||||
DWORD fsi_sector; /* fsinfo sector */
|
|
||||||
#endif
|
|
||||||
DWORD sects_fat; /* Sectors per fat */
|
|
||||||
DWORD max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
|
|
||||||
DWORD fatbase; /* FAT start sector */
|
|
||||||
DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */
|
|
||||||
DWORD database; /* Data start sector */
|
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
|
||||||
BYTE win[_MAX_SS];/* Disk access window for Directory/FAT */
|
|
||||||
} FATFS;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Directory object structure */
|
|
||||||
|
|
||||||
typedef struct _DIR {
|
|
||||||
WORD id; /* Owner file system mount ID */
|
|
||||||
WORD index; /* Current index number */
|
|
||||||
FATFS* fs; /* Pointer to the owner file system object */
|
|
||||||
DWORD sclust; /* Table start cluster (0:Static table) */
|
|
||||||
DWORD clust; /* Current cluster */
|
|
||||||
DWORD sect; /* Current sector */
|
|
||||||
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
|
||||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
|
||||||
#if _USE_LFN
|
|
||||||
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
|
||||||
WORD lfn_idx; /* Last matched LFN index (0xFFFF:No LFN) */
|
|
||||||
#endif
|
|
||||||
} DIR;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File object structure */
|
|
||||||
|
|
||||||
typedef struct _FIL {
|
|
||||||
FATFS* fs; /* Pointer to the owner file system object */
|
|
||||||
WORD id; /* Owner file system mount ID */
|
|
||||||
BYTE flag; /* File status flags */
|
|
||||||
BYTE csect; /* Sector address in the cluster */
|
|
||||||
DWORD fptr; /* File R/W pointer */
|
|
||||||
DWORD fsize; /* File size */
|
|
||||||
DWORD org_clust; /* File start cluster */
|
|
||||||
DWORD curr_clust; /* Current cluster */
|
|
||||||
DWORD dsect; /* Current data sector */
|
|
||||||
#if !_FS_READONLY
|
|
||||||
DWORD dir_sect; /* Sector containing the directory entry */
|
|
||||||
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
|
||||||
#endif
|
|
||||||
#if !_FS_TINY
|
|
||||||
BYTE buf[_MAX_SS];/* File R/W buffer */
|
|
||||||
#endif
|
|
||||||
} FIL;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File status structure */
|
|
||||||
|
|
||||||
typedef struct _FILINFO {
|
|
||||||
DWORD fsize; /* File size */
|
|
||||||
WORD fdate; /* Last modified date */
|
|
||||||
WORD ftime; /* Last modified time */
|
|
||||||
BYTE fattrib; /* Attribute */
|
|
||||||
char fname[13]; /* Short file name (8.3 format) */
|
|
||||||
#if _USE_LFN
|
|
||||||
char *lfname; /* Pointer to the LFN buffer */
|
|
||||||
int lfsize; /* Size of LFN buffer [bytes] */
|
|
||||||
#endif
|
|
||||||
} FILINFO;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* DBCS code ranges */
|
|
||||||
|
|
||||||
#if _CODE_PAGE == 932 /* CP932 (Japanese Shift-JIS) */
|
|
||||||
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
|
|
||||||
#define _DF1E 0x9F /* DBC 1st byte range 1 end */
|
|
||||||
#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
|
|
||||||
#define _DF2E 0xFC /* DBC 1st byte range 2 end */
|
|
||||||
#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
|
|
||||||
#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
|
|
||||||
#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
|
|
||||||
#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
|
|
||||||
|
|
||||||
#elif _CODE_PAGE == 936 /* CP936 (Simplified Chinese GBK) */
|
|
||||||
#define _DF1S 0x81
|
|
||||||
#define _DF1E 0xFE
|
|
||||||
#define _DS1S 0x40
|
|
||||||
#define _DS1E 0x7E
|
|
||||||
#define _DS2S 0x80
|
|
||||||
#define _DS2E 0xFE
|
|
||||||
|
|
||||||
#elif _CODE_PAGE == 949 /* CP949 (Korean) */
|
|
||||||
#define _DF1S 0x81
|
|
||||||
#define _DF1E 0xFE
|
|
||||||
#define _DS1S 0x41
|
|
||||||
#define _DS1E 0x5A
|
|
||||||
#define _DS2S 0x61
|
|
||||||
#define _DS2E 0x7A
|
|
||||||
#define _DS3S 0x81
|
|
||||||
#define _DS3E 0xFE
|
|
||||||
|
|
||||||
#elif _CODE_PAGE == 950 /* CP950 (Traditional Chinese Big5) */
|
|
||||||
#define _DF1S 0x81
|
|
||||||
#define _DF1E 0xFE
|
|
||||||
#define _DS1S 0x40
|
|
||||||
#define _DS1E 0x7E
|
|
||||||
#define _DS2S 0xA1
|
|
||||||
#define _DS2E 0xFE
|
|
||||||
|
|
||||||
#else /* SBCS code pages */
|
|
||||||
#define _DF1S 0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Character code support macros */
|
|
||||||
|
|
||||||
#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
|
|
||||||
#define IsLower(c) (((c)>='a')&&((c)<='z'))
|
|
||||||
#define IsDigit(c) (((c)>='0')&&((c)<='9'))
|
|
||||||
|
|
||||||
#if _DF1S /* DBCS configuration */
|
|
||||||
|
|
||||||
#if _DF2S /* Two 1st byte areas */
|
|
||||||
#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
|
|
||||||
#else /* One 1st byte area */
|
|
||||||
#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _DS3S /* Three 2nd byte areas */
|
|
||||||
#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
|
|
||||||
#else /* Two 2nd byte areas */
|
|
||||||
#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* SBCS configuration */
|
|
||||||
|
|
||||||
#define IsDBCS1(c) 0
|
|
||||||
#define IsDBCS2(c) 0
|
|
||||||
|
|
||||||
#endif /* _DF1S */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Definitions corresponds to multi partition */
|
|
||||||
|
|
||||||
#if _MULTI_PARTITION /* Multiple partition configuration */
|
|
||||||
|
|
||||||
typedef struct _PARTITION {
|
|
||||||
BYTE pd; /* Physical drive# */
|
|
||||||
BYTE pt; /* Partition # (0-3) */
|
|
||||||
} PARTITION;
|
|
||||||
|
|
||||||
extern
|
|
||||||
const PARTITION Drives[]; /* Logical drive# to physical location conversion table */
|
|
||||||
#define LD2PD(drv) (Drives[drv].pd) /* Get physical drive# */
|
|
||||||
#define LD2PT(drv) (Drives[drv].pt) /* Get partition# */
|
|
||||||
|
|
||||||
#else /* Single partition configuration */
|
|
||||||
|
|
||||||
#define LD2PD(drv) (drv) /* Physical drive# is equal to the logical drive# */
|
|
||||||
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File function return code (FRESULT) */
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FR_OK = 0, /* 0 */
|
|
||||||
FR_DISK_ERR, /* 1 */
|
|
||||||
FR_INT_ERR, /* 2 */
|
|
||||||
FR_NOT_READY, /* 3 */
|
|
||||||
FR_NO_FILE, /* 4 */
|
|
||||||
FR_NO_PATH, /* 5 */
|
|
||||||
FR_INVALID_NAME, /* 6 */
|
|
||||||
FR_DENIED, /* 7 */
|
|
||||||
FR_EXIST, /* 8 */
|
|
||||||
FR_INVALID_OBJECT, /* 9 */
|
|
||||||
FR_WRITE_PROTECTED, /* 10 */
|
|
||||||
FR_INVALID_DRIVE, /* 11 */
|
|
||||||
FR_NOT_ENABLED, /* 12 */
|
|
||||||
FR_NO_FILESYSTEM, /* 13 */
|
|
||||||
FR_MKFS_ABORTED, /* 14 */
|
|
||||||
FR_TIMEOUT /* 15 */
|
|
||||||
} FRESULT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
|
||||||
/* FatFs module application interface */
|
|
||||||
|
|
||||||
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
|
||||||
FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */
|
|
||||||
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
|
|
||||||
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
|
|
||||||
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
|
|
||||||
FRESULT f_close (FIL*); /* Close an open file object */
|
|
||||||
FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */
|
|
||||||
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
|
||||||
FRESULT f_stat (const char*, FILINFO*); /* Get file status */
|
|
||||||
FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
|
|
||||||
FRESULT f_truncate (FIL*); /* Truncate file */
|
|
||||||
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
|
|
||||||
FRESULT f_unlink (const char*); /* Delete an existing file or directory */
|
|
||||||
FRESULT f_mkdir (const char*); /* Create a new directory */
|
|
||||||
FRESULT f_chmod (const char*, BYTE, BYTE); /* Change attriburte of the file/dir */
|
|
||||||
FRESULT f_utime (const char*, const FILINFO*); /* Change timestamp of the file/dir */
|
|
||||||
FRESULT f_rename (const char*, const char*); /* Rename/Move a file or directory */
|
|
||||||
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
|
|
||||||
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
|
|
||||||
|
|
||||||
#if _USE_STRFUNC
|
|
||||||
int f_putc (int, FIL*); /* Put a character to the file */
|
|
||||||
int f_puts (const char*, FIL*); /* Put a string to the file */
|
|
||||||
int f_printf (FIL*, const char*, ...); /* Put a formatted string to the file */
|
|
||||||
char* f_gets (char*, int, FIL*); /* Get a string from the file */
|
|
||||||
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
|
|
||||||
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
|
|
||||||
#ifndef EOF
|
|
||||||
#define EOF -1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
|
||||||
/* User defined functions */
|
|
||||||
|
|
||||||
/* Real time clock */
|
|
||||||
#if !_FS_READONLY
|
|
||||||
DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
|
|
||||||
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Unicode - OEM code conversion */
|
|
||||||
#if _USE_LFN
|
|
||||||
WCHAR ff_convert (WCHAR, UINT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Sync functions */
|
|
||||||
#if _FS_REENTRANT
|
|
||||||
BOOL ff_cre_syncobj(BYTE, _SYNC_t*);
|
|
||||||
BOOL ff_del_syncobj(_SYNC_t);
|
|
||||||
BOOL ff_req_grant(_SYNC_t);
|
|
||||||
void ff_rel_grant(_SYNC_t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
|
||||||
/* Flags and offset address */
|
|
||||||
|
|
||||||
|
|
||||||
/* File access control and file status flags (FIL.flag) */
|
|
||||||
|
|
||||||
#define FA_READ 0x01
|
|
||||||
#define FA_OPEN_EXISTING 0x00
|
|
||||||
#if _FS_READONLY == 0
|
|
||||||
#define FA_WRITE 0x02
|
|
||||||
#define FA_CREATE_NEW 0x04
|
|
||||||
#define FA_CREATE_ALWAYS 0x08
|
|
||||||
#define FA_OPEN_ALWAYS 0x10
|
|
||||||
#define FA__WRITTEN 0x20
|
|
||||||
#define FA__DIRTY 0x40
|
|
||||||
#endif
|
|
||||||
#define FA__ERROR 0x80
|
|
||||||
|
|
||||||
|
|
||||||
/* FAT sub type (FATFS.fs_type) */
|
|
||||||
|
|
||||||
#define FS_FAT12 1
|
|
||||||
#define FS_FAT16 2
|
|
||||||
#define FS_FAT32 3
|
|
||||||
|
|
||||||
|
|
||||||
/* File attribute bits for directory entry */
|
|
||||||
|
|
||||||
#define AM_RDO 0x01 /* Read only */
|
|
||||||
#define AM_HID 0x02 /* Hidden */
|
|
||||||
#define AM_SYS 0x04 /* System */
|
|
||||||
#define AM_VOL 0x08 /* Volume label */
|
|
||||||
#define AM_LFN 0x0F /* LFN entry */
|
|
||||||
#define AM_DIR 0x10 /* Directory */
|
|
||||||
#define AM_ARC 0x20 /* Archive */
|
|
||||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
|
||||||
|
|
||||||
|
|
||||||
/* FatFs refers the members in the FAT structures with byte offset instead
|
|
||||||
/ of structure member because there are incompatibility of the packing option
|
|
||||||
/ between various compilers. */
|
|
||||||
|
|
||||||
#define BS_jmpBoot 0
|
|
||||||
#define BS_OEMName 3
|
|
||||||
#define BPB_BytsPerSec 11
|
|
||||||
#define BPB_SecPerClus 13
|
|
||||||
#define BPB_RsvdSecCnt 14
|
|
||||||
#define BPB_NumFATs 16
|
|
||||||
#define BPB_RootEntCnt 17
|
|
||||||
#define BPB_TotSec16 19
|
|
||||||
#define BPB_Media 21
|
|
||||||
#define BPB_FATSz16 22
|
|
||||||
#define BPB_SecPerTrk 24
|
|
||||||
#define BPB_NumHeads 26
|
|
||||||
#define BPB_HiddSec 28
|
|
||||||
#define BPB_TotSec32 32
|
|
||||||
#define BS_55AA 510
|
|
||||||
|
|
||||||
#define BS_DrvNum 36
|
|
||||||
#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 BS_DrvNum32 64
|
|
||||||
#define BS_BootSig32 66
|
|
||||||
#define BS_VolID32 67
|
|
||||||
#define BS_VolLab32 71
|
|
||||||
#define BS_FilSysType32 82
|
|
||||||
|
|
||||||
#define FSI_LeadSig 0
|
|
||||||
#define FSI_StrucSig 484
|
|
||||||
#define FSI_Free_Count 488
|
|
||||||
#define FSI_Nxt_Free 492
|
|
||||||
|
|
||||||
#define MBR_Table 446
|
|
||||||
|
|
||||||
#define DIR_Name 0
|
|
||||||
#define DIR_Attr 11
|
|
||||||
#define DIR_NTres 12
|
|
||||||
#define DIR_CrtTime 14
|
|
||||||
#define DIR_CrtDate 16
|
|
||||||
#define DIR_FstClusHI 20
|
|
||||||
#define DIR_WrtTime 22
|
|
||||||
#define DIR_WrtDate 24
|
|
||||||
#define DIR_FstClusLO 26
|
|
||||||
#define DIR_FileSize 28
|
|
||||||
#define LDIR_Ord 0
|
|
||||||
#define LDIR_Attr 11
|
|
||||||
#define LDIR_Type 12
|
|
||||||
#define LDIR_Chksum 13
|
|
||||||
#define LDIR_FstClusLO 26
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------*/
|
|
||||||
/* Multi-byte word access macros */
|
|
||||||
|
|
||||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
|
||||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
|
||||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
|
||||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
|
||||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
|
||||||
#else /* Use byte-by-byte access to the FAT structure */
|
|
||||||
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
|
||||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
|
|
||||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
|
|
||||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _FATFS */
|
|
||||||
267
avr/usbload/huffman-decode.c
Normal file
267
avr/usbload/huffman-decode.c
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* =====================================================================================
|
||||||
|
*
|
||||||
|
* ________ .__ __ ________ ____ ________
|
||||||
|
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||||
|
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||||
|
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||||
|
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||||
|
* \__> \/ \/ \/ \/ \/
|
||||||
|
*
|
||||||
|
* www.optixx.org
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Version: 1.0
|
||||||
|
* Created: 07/21/2009 03:32:16 PM
|
||||||
|
*
|
||||||
|
* =====================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "huffman-decode.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "info.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#undef DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define V_NODE (-2)
|
||||||
|
#define V_EOF (-1)
|
||||||
|
|
||||||
|
#define PREFIX_SIZE_B 32
|
||||||
|
|
||||||
|
#define ALLOC_ERROR {}
|
||||||
|
|
||||||
|
#undef BLOCK_ALLOC
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int16_t value;
|
||||||
|
void* left;
|
||||||
|
void* right;
|
||||||
|
} node_t;
|
||||||
|
|
||||||
|
#if HUFFMAN_USE_ADDR_16
|
||||||
|
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint16_t)){
|
||||||
|
#else
|
||||||
|
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint32_t)){
|
||||||
|
#endif
|
||||||
|
ctx->tree = NULL;
|
||||||
|
ctx->addr = 0;
|
||||||
|
ctx->read_byte = rb_func;
|
||||||
|
ctx->rbuffer_index = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HUFFMAN_USE_ADDR_16
|
||||||
|
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx, uint16_t addr){
|
||||||
|
#else
|
||||||
|
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx, uint32_t addr){
|
||||||
|
#endif
|
||||||
|
ctx->addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void prefix_increment(uint8_t* prefix){
|
||||||
|
uint8_t i;
|
||||||
|
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||||
|
prefix[i] += 1;
|
||||||
|
if(prefix[i]!=0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void prefix_shiftleft(uint8_t* prefix){
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t c[2]={0,0};
|
||||||
|
uint8_t ci=0;
|
||||||
|
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||||
|
c[ci] = (prefix[i])>>7;
|
||||||
|
prefix[i]<<=1;
|
||||||
|
ci ^= 1;
|
||||||
|
prefix[i]|=c[ci];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_last_to_eof(node_t* start){
|
||||||
|
node_t* current = start;
|
||||||
|
while(current->value==V_NODE){
|
||||||
|
current=current->right;
|
||||||
|
}
|
||||||
|
current->value=V_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
void print_tree(node_t* node){
|
||||||
|
if(node->value==V_NODE){
|
||||||
|
info("\n%p --> node->left=%p node->right=%p",node,node->left, node->right);
|
||||||
|
print_tree(node->left);
|
||||||
|
print_tree(node->right);
|
||||||
|
}else{
|
||||||
|
info("\n%p => %i",node,node->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t build_tree(huffman_dec_ctx_t* ctx){
|
||||||
|
uint16_t treesize;
|
||||||
|
uint16_t treeindex=1;
|
||||||
|
int8_t i,t;
|
||||||
|
if(ctx->read_byte(ctx->addr++)!=0xC0)
|
||||||
|
return 1;
|
||||||
|
if(((treesize=ctx->read_byte(ctx->addr++))&0xFE)!=0xDE)
|
||||||
|
return 1;
|
||||||
|
treesize = (treesize&1)<<8;
|
||||||
|
treesize += ctx->read_byte(ctx->addr++);
|
||||||
|
if(treesize>0x1ff)
|
||||||
|
return 2;
|
||||||
|
#if BLOCK_ALLOC
|
||||||
|
ctx->tree = malloc((2*treesize-1) * sizeof(node_t));
|
||||||
|
#else
|
||||||
|
ctx->tree = malloc(sizeof(node_t));
|
||||||
|
#endif
|
||||||
|
((node_t*)(ctx->tree))->value = V_NODE;
|
||||||
|
uint16_t depth=0;
|
||||||
|
uint16_t count=0;
|
||||||
|
uint16_t v;
|
||||||
|
uint8_t prefix[PREFIX_SIZE_B];
|
||||||
|
uint8_t cdepth=0;
|
||||||
|
node_t* current=ctx->tree;
|
||||||
|
current->value = V_NODE;
|
||||||
|
memset(prefix, 0, PREFIX_SIZE_B);
|
||||||
|
do{
|
||||||
|
while(count==0){
|
||||||
|
depth++;
|
||||||
|
count= ctx->read_byte(ctx->addr++);
|
||||||
|
if(count==255)
|
||||||
|
count += ctx->read_byte(ctx->addr++);
|
||||||
|
}
|
||||||
|
v = ctx->read_byte(ctx->addr++);
|
||||||
|
if(v>0xff)
|
||||||
|
return 3;
|
||||||
|
--count;
|
||||||
|
for(;cdepth<depth;++cdepth){
|
||||||
|
prefix_shiftleft(prefix);
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
printf("\n value %x => ",v);
|
||||||
|
#endif
|
||||||
|
current=ctx->tree;
|
||||||
|
for(i=depth-1; i>=0; --i){
|
||||||
|
t=(prefix[i/8])&(1<<(i%8));
|
||||||
|
if(t==0){
|
||||||
|
#if DEBUG
|
||||||
|
printf("0");
|
||||||
|
#endif
|
||||||
|
if(current->left==NULL){
|
||||||
|
#if BLOCK_ALLOC
|
||||||
|
current->left=&(((node_t*)(ctx->tree))[treeindex++]);
|
||||||
|
#else
|
||||||
|
current->left=malloc(sizeof(node_t));
|
||||||
|
#endif
|
||||||
|
((node_t*)(current->left))->value = V_NODE;
|
||||||
|
}
|
||||||
|
current = current->left;
|
||||||
|
} else {
|
||||||
|
#if DEBUG
|
||||||
|
printf("1");
|
||||||
|
#endif
|
||||||
|
if(current->right==NULL){
|
||||||
|
#if BLOCK_ALLOC
|
||||||
|
current->right=&(((node_t*)(ctx->tree))[treeindex++]);
|
||||||
|
#else
|
||||||
|
current->right=malloc( sizeof(node_t));
|
||||||
|
#endif
|
||||||
|
((node_t*)(current->right))->value=V_NODE;
|
||||||
|
}
|
||||||
|
current = current->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if !BLOCK_ALLOC
|
||||||
|
if(current==NULL)
|
||||||
|
ALLOC_ERROR
|
||||||
|
#endif
|
||||||
|
current->value=v;
|
||||||
|
prefix_increment(prefix);
|
||||||
|
}while(!(prefix[depth/8]&(1<<(depth%8))));
|
||||||
|
#if DEBUG
|
||||||
|
print_tree(ctx->tree);
|
||||||
|
#endif
|
||||||
|
set_last_to_eof(ctx->tree);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_tree(node_t* node){
|
||||||
|
#if !BLOCK_ALLOC
|
||||||
|
if(node->value==V_NODE){
|
||||||
|
free_tree(node->left);
|
||||||
|
free_tree(node->right);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
free(node);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t read_bit(huffman_dec_ctx_t* ctx){
|
||||||
|
uint16_t x;
|
||||||
|
uint8_t t;
|
||||||
|
if(ctx->rbuffer_index==8){
|
||||||
|
x=ctx->read_byte(ctx->addr);
|
||||||
|
ctx->addr++;
|
||||||
|
if(t>0xff)
|
||||||
|
return 0xFF;
|
||||||
|
ctx->rbuffer = (uint8_t)x;
|
||||||
|
ctx->rbuffer_index=0;
|
||||||
|
}
|
||||||
|
t=(ctx->rbuffer)>>7;
|
||||||
|
ctx->rbuffer<<=1;
|
||||||
|
ctx->rbuffer_index++;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t huffman_dec_byte(huffman_dec_ctx_t* ctx){
|
||||||
|
node_t* current=ctx->tree;
|
||||||
|
uint8_t t;
|
||||||
|
if(current==NULL){
|
||||||
|
#if DEBUG
|
||||||
|
printf("\nbuild tree");
|
||||||
|
#endif
|
||||||
|
t=build_tree(ctx);
|
||||||
|
if(t!=0){
|
||||||
|
#if DEBUG
|
||||||
|
printf("\n!!! building tree failed !!!\r\n");
|
||||||
|
#endif
|
||||||
|
return 0xFFFF;
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
printf("\ntree build successful");
|
||||||
|
#endif
|
||||||
|
current=ctx->tree;
|
||||||
|
}
|
||||||
|
while(current->value==V_NODE){
|
||||||
|
t=read_bit(ctx);
|
||||||
|
if(t==0xFF)
|
||||||
|
goto eof_detected;
|
||||||
|
if(t==0){
|
||||||
|
current=current->left;
|
||||||
|
} else {
|
||||||
|
current=current->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(current->value!=V_EOF){
|
||||||
|
return current->value;
|
||||||
|
}
|
||||||
|
eof_detected:
|
||||||
|
free_tree(ctx->tree);
|
||||||
|
ctx->tree = NULL;
|
||||||
|
return 0xFFFF;
|
||||||
|
}
|
||||||
@@ -13,17 +13,39 @@
|
|||||||
*
|
*
|
||||||
* Version: 1.0
|
* Version: 1.0
|
||||||
* Created: 07/21/2009 03:32:16 PM
|
* Created: 07/21/2009 03:32:16 PM
|
||||||
* Author: david@optixx.org
|
|
||||||
*
|
*
|
||||||
* =====================================================================================
|
* =====================================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef AVR_HUFFMAN_DECODE_H_
|
||||||
|
#define AVR_HUFFMAN_DECODE_H_
|
||||||
|
|
||||||
#ifndef __COMMAND_H__
|
#include <stdint.h>
|
||||||
#define __COMMAND_H__
|
|
||||||
|
|
||||||
void send_reset();
|
#define HUFFMAN_USE_ADDR_16 1
|
||||||
void send_irq();
|
|
||||||
void set_rom_mode();
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* tree;
|
||||||
|
uint8_t rbuffer;
|
||||||
|
uint8_t rbuffer_index;
|
||||||
|
#if HUFFMAN_USE_ADDR_16
|
||||||
|
uint16_t(*read_byte)(uint16_t addr);
|
||||||
|
uint16_t addr;
|
||||||
|
#else
|
||||||
|
uint16_t(*read_byte)(uint32_t addr);
|
||||||
|
uint32_t addr;
|
||||||
#endif
|
#endif
|
||||||
|
} huffman_dec_ctx_t;
|
||||||
|
|
||||||
|
#if HUFFMAN_USE_ADDR_16
|
||||||
|
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint16_t));
|
||||||
|
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx,uint16_t addr);
|
||||||
|
#else
|
||||||
|
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint32_t));
|
||||||
|
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx,uint32_t addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t huffman_dec_byte(huffman_dec_ctx_t* ctx);
|
||||||
|
|
||||||
|
#endif /* AVR_HUFFMAN_DECODE_H_ */
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*-------------------------------------------*/
|
|
||||||
/* Integer type definitions for FatFs module */
|
|
||||||
/*-------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _INTEGER
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* These types must be 16-bit, 32-bit or larger integer */
|
|
||||||
typedef int INT;
|
|
||||||
typedef unsigned int UINT;
|
|
||||||
|
|
||||||
/* These types must be 8-bit integer */
|
|
||||||
typedef signed char CHAR;
|
|
||||||
typedef unsigned char UCHAR;
|
|
||||||
typedef unsigned char BYTE;
|
|
||||||
|
|
||||||
/* These types must be 16-bit integer */
|
|
||||||
typedef short SHORT;
|
|
||||||
typedef unsigned short USHORT;
|
|
||||||
typedef unsigned short WORD;
|
|
||||||
typedef unsigned short WCHAR;
|
|
||||||
|
|
||||||
/* These types must be 32-bit integer */
|
|
||||||
typedef long LONG;
|
|
||||||
typedef unsigned long ULONG;
|
|
||||||
typedef unsigned long DWORD;
|
|
||||||
|
|
||||||
/* Boolean type */
|
|
||||||
typedef enum { FALSE = 0, TRUE } BOOL;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _INTEGER
|
|
||||||
#endif
|
|
||||||
3654
avr/usbload/loader.c
3654
avr/usbload/loader.c
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,8 @@
|
|||||||
#ifndef __FIFO_H__
|
#ifndef __FIFO_H__
|
||||||
#define __FIFO_H__
|
#define __FIFO_H__
|
||||||
|
|
||||||
#define ROM_BUFFER_SIZE 31091
|
#define ROM_BUFFER_SIZE 27288
|
||||||
#define ROM_HUFFMAN_SIZE 0
|
#define ROM_HUFFMAN_SIZE 27288
|
||||||
#define ROM_RLE_SIZE 31091
|
#define ROM_RLE_SIZE 30344
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,16 +21,17 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h> /* for sei() */
|
||||||
#include <util/delay.h>
|
#include <util/delay.h> /* for _delay_ms() */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h> /* required by usbdrv.h */
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
|
|
||||||
#include "usbdrv.h"
|
#include "usbdrv.h"
|
||||||
#include "oddebug.h"
|
#include "oddebug.h" /* This is also an example for using debug
|
||||||
|
* macros */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "requests.h"
|
#include "requests.h" /* The custom request numbers we use */
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "sram.h"
|
#include "sram.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@@ -40,18 +41,16 @@
|
|||||||
#include "usb_bulk.h"
|
#include "usb_bulk.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
|
#include "huffman-decode.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 "testing.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 );
|
||||||
|
|
||||||
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,8 +59,6 @@ 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;
|
||||||
@@ -79,28 +76,88 @@ 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 (rq->bRequest == USB_BULK_UPLOAD_INIT) {
|
if (req_state != REQ_STATUS_IDLE){
|
||||||
|
debug(DEBUG_USB,"USB_UPLOAD_INIT: ERROR state is not REQ_STATUS_IDLE\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
req_bank = 0;
|
req_bank = 0;
|
||||||
rx_remaining = 0;
|
rx_remaining = 0;
|
||||||
debug(DEBUG_USB, "USB_BULK_UPLOAD_INIT: %i %i\n", rq->wValue.word,
|
req_bank_size = (uint32_t)1 << rq->wValue.word;
|
||||||
rq->wIndex.word);
|
|
||||||
req_bank_size = (uint32_t) (1L << rq->wValue.word);
|
|
||||||
req_bank_cnt = rq->wIndex.word;
|
|
||||||
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,
|
crc = 0;
|
||||||
"USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n",
|
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;
|
||||||
|
rx_remaining = 0;
|
||||||
|
debug(DEBUG_USB,"USB_BULK_UPLOAD_INIT: %i %i\n",rq->wValue.word, rq->wIndex.word);
|
||||||
|
req_bank_size = (uint32_t)(1L << rq->wValue.word);
|
||||||
|
req_bank_cnt = rq->wIndex.word;
|
||||||
|
req_addr_end = (uint32_t)req_bank_size * req_bank_cnt;
|
||||||
|
|
||||||
|
sync_errors = 0;
|
||||||
|
debug(DEBUG_USB,"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_write(SHARED_MEM_TX_CMD_BANK_COUNT, req_bank_cnt);
|
shared_memory_put(SHARED_MEM_CMD_BANK_COUNT,req_bank_cnt);
|
||||||
if (req_addr == 0x000000) {
|
if (req_addr == 0x000000){
|
||||||
timer_start();
|
timer_start();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_BULK_UPLOAD_ADDR) {
|
} else if (rq->bRequest == USB_BULK_UPLOAD_ADDR) {
|
||||||
@@ -111,19 +168,16 @@ 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,"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
|
||||||
"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
|
req_bank, req_addr,timer_stop());
|
||||||
req_bank, req_addr, timer_stop());
|
#else
|
||||||
#else
|
debug(DEBUG_USB,"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n",
|
||||||
debug(DEBUG_USB,
|
req_bank, req_addr,timer_stop_int());
|
||||||
"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n",
|
#endif
|
||||||
req_bank, req_addr, timer_stop_int());
|
|
||||||
#endif
|
|
||||||
req_bank++;
|
req_bank++;
|
||||||
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_bank);
|
shared_memory_put(SHARED_MEM_CMD_UPLOAD_PROGESS,req_bank);
|
||||||
sram_bulk_write_start(req_addr);
|
sram_bulk_write_start(req_addr);
|
||||||
timer_start();
|
timer_start();
|
||||||
|
|
||||||
@@ -132,7 +186,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
|||||||
}
|
}
|
||||||
ret_len = USB_MAX_TRANS;
|
ret_len = USB_MAX_TRANS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_BULK_UPLOAD_NEXT) {
|
} else if (rq->bRequest == USB_BULK_UPLOAD_NEXT) {
|
||||||
@@ -142,91 +196,75 @@ 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,"USB_BULK_UPLOAD_NEXT: bank=0x%02x addr=0x%08lx crc=%04x\n",
|
||||||
"USB_BULK_UPLOAD_NEXT: 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));
|
||||||
req_bank, req_addr, crc_check_bulk_memory(req_addr - 0x1000,
|
|
||||||
req_addr,
|
|
||||||
req_bank_size));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
sram_bulk_write_start(req_addr);
|
sram_bulk_write_start(req_addr);
|
||||||
#endif
|
#endif
|
||||||
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,"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
|
||||||
"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
|
req_bank, req_addr,timer_stop());
|
||||||
req_bank, req_addr, timer_stop());
|
#else
|
||||||
#else
|
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n",
|
||||||
debug(DEBUG_USB,
|
req_bank, req_addr,timer_stop_int());
|
||||||
"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n",
|
#endif
|
||||||
req_bank, req_addr, timer_stop_int());
|
|
||||||
#endif
|
|
||||||
req_bank++;
|
req_bank++;
|
||||||
timer_start();
|
timer_start();
|
||||||
shared_memory_write(SHARED_MEM_TX_CMD_BANK_CURRENT, req_bank);
|
shared_memory_put(SHARED_MEM_CMD_BANK_CURRENT,req_bank);
|
||||||
sram_bulk_write_start(req_addr);
|
sram_bulk_write_start(req_addr);
|
||||||
|
|
||||||
}
|
}
|
||||||
ret_len = USB_MAX_TRANS;
|
ret_len = USB_MAX_TRANS;
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_BULK_UPLOAD_END) {
|
} else if (rq->bRequest == USB_BULK_UPLOAD_END) {
|
||||||
if (req_state != REQ_STATUS_BULK_UPLOAD) {
|
if (req_state != REQ_STATUS_BULK_UPLOAD){
|
||||||
debug(DEBUG_USB,
|
debug(DEBUG_USB,"USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n");
|
||||||
"USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
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_write(SHARED_MEM_TX_CMD_UPLOAD_END, 0);
|
shared_memory_put(SHARED_MEM_CMD_UPLOAD_END,0);
|
||||||
ret_len = 0;
|
ret_len = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_CRC) {
|
} else if (rq->bRequest == USB_CRC) {
|
||||||
req_addr = rq->wValue.word;
|
req_addr = rq->wValue.word;
|
||||||
req_addr = req_addr << 16;
|
req_addr = req_addr << 16;
|
||||||
req_addr = req_addr | rq->wIndex.word;
|
req_addr = req_addr | rq->wIndex.word;
|
||||||
debug(DEBUG_USB, "USB_CRC: addr=0x%08lx \n", req_addr);
|
debug(DEBUG_USB,"USB_CRC: addr=0x%08lx \n", req_addr);
|
||||||
crc_check_bulk_memory(0x000000, req_addr, req_bank_size);
|
crc_check_bulk_memory(0x000000, req_addr, req_bank_size);
|
||||||
ret_len = 0;
|
ret_len = 0;
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_MODE_SNES) {
|
} else if (rq->bRequest == USB_MODE_SNES) {
|
||||||
req_state = REQ_STATUS_SNES;
|
req_state = REQ_STATUS_SNES;
|
||||||
debug(DEBUG_USB, "USB_MODE_SNES:\n");
|
debug(DEBUG_USB,"USB_MODE_SNES:\n");
|
||||||
ret_len = 0;
|
ret_len = 0;
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_MODE_AVR) {
|
} else if (rq->bRequest == USB_MODE_AVR) {
|
||||||
req_state = REQ_STATUS_AVR;
|
req_state = REQ_STATUS_AVR;
|
||||||
debug(DEBUG_USB, "USB_MODE_AVR:\n");
|
debug(DEBUG_USB,"USB_MODE_AVR:\n");
|
||||||
ret_len = 0;
|
ret_len = 0;
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
} else if (rq->bRequest == USB_AVR_RESET) {
|
} else if (rq->bRequest == USB_AVR_RESET) {
|
||||||
debug(DEBUG_USB, "USB_AVR_RESET:\n");
|
debug(DEBUG_USB,"USB_AVR_RESET:\n");
|
||||||
soft_reset();
|
soft_reset();
|
||||||
ret_len = 0;
|
ret_len = 0;
|
||||||
/*
|
/*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -235,13 +273,12 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
|||||||
req_addr = rq->wValue.word;
|
req_addr = rq->wValue.word;
|
||||||
req_addr = req_addr << 16;
|
req_addr = req_addr << 16;
|
||||||
req_addr = req_addr | rq->wIndex.word;
|
req_addr = req_addr | rq->wIndex.word;
|
||||||
debug(DEBUG_USB, "USB_CRC_ADDR: addr=0x%lx size=%i\n", req_addr,
|
debug(DEBUG_USB,"USB_CRC_ADDR: addr=0x%lx size=%i\n", req_addr,
|
||||||
rq->wLength.word);
|
rq->wLength.word);
|
||||||
req_size = rq->wLength.word;
|
req_size = rq->wLength.word;
|
||||||
req_size = req_size << 2;
|
req_size = req_size << 2;
|
||||||
tx_remaining = 2;
|
tx_remaining = 2;
|
||||||
debug(DEBUG_USB, "USB_CRC_ADDR: addr=0x%lx size=%li\n", req_addr,
|
debug(DEBUG_USB,"USB_CRC_ADDR: addr=0x%lx size=%li\n", req_addr, req_size);
|
||||||
req_size);
|
|
||||||
|
|
||||||
crc = crc_check_memory_range(req_addr, req_size, read_buffer);
|
crc = crc_check_memory_range(req_addr, req_size, read_buffer);
|
||||||
tx_buffer[0] = crc & 0xff;
|
tx_buffer[0] = crc & 0xff;
|
||||||
@@ -251,7 +288,8 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
|||||||
}
|
}
|
||||||
|
|
||||||
usbMsgPtr = data_buffer;
|
usbMsgPtr = data_buffer;
|
||||||
return ret_len; /* default for not implemented requests: return no data back to host */
|
return ret_len; /* default for not implemented requests: return
|
||||||
|
* no data back to host */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -259,9 +297,132 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
|||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void test_read_write(){
|
||||||
|
|
||||||
void usb_connect()
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t read_byte_pgm(uint16_t addr){
|
||||||
|
return pgm_read_byte((PGM_VOID_P)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decompress_huffman(PGM_VOID_P addr, uint16_t(*fp)(uint16_t)){
|
||||||
|
uint16_t c;
|
||||||
|
uint32_t i = 0;
|
||||||
|
huffman_dec_ctx_t ctx;
|
||||||
|
info("ok1\n");
|
||||||
|
huffman_dec_init(&ctx, fp);
|
||||||
|
info("ok2\n");
|
||||||
|
huffman_dec_set_addr(&ctx, (uint16_t)addr);
|
||||||
|
info("ok3\n");
|
||||||
|
while(1){
|
||||||
|
info("ok4\n");
|
||||||
|
i++;
|
||||||
|
c=huffman_dec_byte(&ctx);
|
||||||
|
if (i%1024==0)
|
||||||
|
info(".");
|
||||||
|
if(c>0xff){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c&=0xff;
|
||||||
|
sram_bulk_write(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(){
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
info("USB init\n");
|
info("USB init\n");
|
||||||
usbDeviceDisconnect(); /* enforce re-enumeration, do this while */
|
usbDeviceDisconnect(); /* enforce re-enumeration, do this while */
|
||||||
@@ -280,8 +441,7 @@ void usb_connect()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void boot_startup_rom()
|
void boot_startup_rom(){
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
info("Activate AVR bus\n");
|
info("Activate AVR bus\n");
|
||||||
@@ -294,7 +454,13 @@ void boot_startup_rom()
|
|||||||
snes_lorom();
|
snes_lorom();
|
||||||
info("Set Snes lowrom \n");
|
info("Set Snes lowrom \n");
|
||||||
|
|
||||||
rle_decode(&_rom, ROM_BUFFER_SIZE, 0x000000);
|
|
||||||
|
info("Huffman decompress to 0x010000\n",(void*)_rom);
|
||||||
|
sram_bulk_write_start(0x010000);
|
||||||
|
decompress_huffman(&_rom,read_byte_pgm);
|
||||||
|
sram_bulk_write_end();
|
||||||
|
info("RLE decompress to 0x000000\n",(void*)_rom);
|
||||||
|
rle_decode_sram(0x010000, ROM_RLE_SIZE, 0x000000);
|
||||||
dump_memory(0x10000 - 0x100, 0x10000);
|
dump_memory(0x10000 - 0x100, 0x10000);
|
||||||
|
|
||||||
snes_reset_hi();
|
snes_reset_hi();
|
||||||
@@ -315,7 +481,7 @@ void boot_startup_rom()
|
|||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
i = 20;
|
i = 20;
|
||||||
info("Wait");
|
info("Wait");
|
||||||
while (--i) {
|
while (--i){
|
||||||
_delay_ms(500);
|
_delay_ms(500);
|
||||||
info(".");
|
info(".");
|
||||||
}
|
}
|
||||||
@@ -323,7 +489,6 @@ void boot_startup_rom()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -337,7 +502,7 @@ int main(void)
|
|||||||
test_read_write();
|
test_read_write();
|
||||||
test_bulk_read_write();
|
test_bulk_read_write();
|
||||||
test_crc();
|
test_crc();
|
||||||
while (1);
|
while(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
info("Boot startup rom\n");
|
info("Boot startup rom\n");
|
||||||
@@ -346,7 +511,7 @@ int main(void)
|
|||||||
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");
|
||||||
@@ -358,11 +523,16 @@ int main(void)
|
|||||||
snes_wr_disable();
|
snes_wr_disable();
|
||||||
sei();
|
sei();
|
||||||
info("USB poll\n");
|
info("USB poll\n");
|
||||||
while (req_state != REQ_STATUS_SNES) {
|
while (req_state != REQ_STATUS_SNES){
|
||||||
usbPoll();
|
usbPoll();
|
||||||
}
|
}
|
||||||
shared_memory_write(SHARED_MEM_TX_CMD_TERMINATE, 0);
|
shared_memory_put(SHARED_MEM_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");
|
||||||
@@ -373,7 +543,8 @@ int main(void)
|
|||||||
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
|
||||||
@@ -383,7 +554,7 @@ int main(void)
|
|||||||
while (--i) {
|
while (--i) {
|
||||||
_delay_ms(100);
|
_delay_ms(100);
|
||||||
}
|
}
|
||||||
info("Send IRQ %i\n", ++irq_count);
|
info("Send IRQ %i\n",++irq_count);
|
||||||
send_irq();
|
send_irq();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -397,7 +568,7 @@ int main(void)
|
|||||||
info("Wait to switch to snes mode %i\n", i);
|
info("Wait to switch to snes mode %i\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req_bank_size == 0x8000) {
|
if (req_bank_size == 0x8000){
|
||||||
snes_lorom();
|
snes_lorom();
|
||||||
info("Set Snes lowrom \n");
|
info("Set Snes lowrom \n");
|
||||||
} else {
|
} else {
|
||||||
@@ -408,10 +579,11 @@ int main(void)
|
|||||||
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");
|
||||||
info("Read 0x3000=%c\n", c);
|
info("Read 0x3000=%c\n",c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,600 +0,0 @@
|
|||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* MMC/SDSC/SDHC (in SPI mode) control module (C)ChaN, 2007 */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros */
|
|
||||||
/* are platform dependent. */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include "diskio.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Definitions for MMC/SDC command */
|
|
||||||
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
|
|
||||||
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
|
|
||||||
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
|
|
||||||
#define CMD8 (0x40+8) /* SEND_IF_COND */
|
|
||||||
#define CMD9 (0x40+9) /* SEND_CSD */
|
|
||||||
#define CMD10 (0x40+10) /* SEND_CID */
|
|
||||||
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
|
|
||||||
#define ACMD13 (0xC0+13) /* SD_STATUS (SDC) */
|
|
||||||
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
|
|
||||||
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
|
|
||||||
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
|
|
||||||
#define CMD23 (0x40+23) /* SET_BLOCK_COUNT (MMC) */
|
|
||||||
#define ACMD23 (0xC0+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
|
|
||||||
#define CMD24 (0x40+24) /* WRITE_BLOCK */
|
|
||||||
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
|
|
||||||
#define CMD55 (0x40+55) /* APP_CMD */
|
|
||||||
#define CMD58 (0x40+58) /* READ_OCR */
|
|
||||||
|
|
||||||
|
|
||||||
/* Port Controls (Platform dependent) */
|
|
||||||
#define SELECT() PORTB &= ~1 /* MMC CS = L */
|
|
||||||
#define DESELECT() PORTB |= 1 /* MMC CS = H */
|
|
||||||
|
|
||||||
#define SOCKPORT PINB /* Socket contact port */
|
|
||||||
#define SOCKWP 0x20 /* Write protect switch (PB5) */
|
|
||||||
#define SOCKINS 0x10 /* Card detect switch (PB4) */
|
|
||||||
|
|
||||||
#define FCLK_SLOW() /* Set slow clock (100k-400k) */
|
|
||||||
#define FCLK_FAST() /* Set fast clock (depends on the CSD) */
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Module Private Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static volatile
|
|
||||||
DSTATUS Stat = STA_NOINIT; /* Disk status */
|
|
||||||
|
|
||||||
static volatile
|
|
||||||
BYTE Timer1, Timer2; /* 100Hz decrement timer */
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE CardType; /* Card type flags */
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Transmit a byte to MMC via SPI (Platform dependent) */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define xmit_spi(dat) SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Receive a byte from MMC via SPI (Platform dependent) */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE rcvr_spi (void)
|
|
||||||
{
|
|
||||||
SPDR = 0xFF;
|
|
||||||
loop_until_bit_is_set(SPSR, SPIF);
|
|
||||||
return SPDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Alternative macro to receive data fast */
|
|
||||||
#define rcvr_spi_m(dst) SPDR=0xFF; loop_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Wait for card ready */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE wait_ready (void)
|
|
||||||
{
|
|
||||||
BYTE res;
|
|
||||||
|
|
||||||
|
|
||||||
Timer2 = 50; /* Wait for ready in timeout of 500ms */
|
|
||||||
rcvr_spi();
|
|
||||||
do
|
|
||||||
res = rcvr_spi();
|
|
||||||
while ((res != 0xFF) && Timer2);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Deselect the card and release SPI bus */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
void release_spi (void)
|
|
||||||
{
|
|
||||||
DESELECT();
|
|
||||||
rcvr_spi();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Power Control (Platform dependent) */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* When the target system does not support socket power control, there */
|
|
||||||
/* is nothing to do in these functions and chk_power always returns 1. */
|
|
||||||
|
|
||||||
static
|
|
||||||
void power_on (void)
|
|
||||||
{
|
|
||||||
PORTE &= ~0x80; /* Socket power ON */
|
|
||||||
for (Timer1 = 3; Timer1; ); /* Wait for 30ms */
|
|
||||||
PORTB = 0b10110101; /* Enable drivers */
|
|
||||||
DDRB = 0b11000111;
|
|
||||||
SPCR = 0b01010000; /* Initialize SPI port (Mode 0) */
|
|
||||||
SPSR = 0b00000001;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void power_off (void)
|
|
||||||
{
|
|
||||||
SELECT(); /* Wait for card ready */
|
|
||||||
wait_ready();
|
|
||||||
release_spi();
|
|
||||||
|
|
||||||
SPCR = 0; /* Disable SPI function */
|
|
||||||
DDRB = 0b11000000; /* Disable drivers */
|
|
||||||
PORTB = 0b10110000;
|
|
||||||
PORTE |= 0x80; /* Socket power OFF */
|
|
||||||
Stat |= STA_NOINIT; /* Set STA_NOINIT */
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int chk_power(void) /* Socket power state: 0=off, 1=on */
|
|
||||||
{
|
|
||||||
return (PORTE & 0x80) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Receive a data packet from MMC */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL rcvr_datablock (
|
|
||||||
BYTE *buff, /* Data buffer to store received data */
|
|
||||||
UINT btr /* Byte count (must be multiple of 4) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BYTE token;
|
|
||||||
|
|
||||||
|
|
||||||
Timer1 = 10;
|
|
||||||
do { /* Wait for data packet in timeout of 100ms */
|
|
||||||
token = rcvr_spi();
|
|
||||||
} while ((token == 0xFF) && Timer1);
|
|
||||||
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
|
|
||||||
|
|
||||||
do { /* Receive the data block into buffer */
|
|
||||||
rcvr_spi_m(buff++);
|
|
||||||
rcvr_spi_m(buff++);
|
|
||||||
rcvr_spi_m(buff++);
|
|
||||||
rcvr_spi_m(buff++);
|
|
||||||
} while (btr -= 4);
|
|
||||||
rcvr_spi(); /* Discard CRC */
|
|
||||||
rcvr_spi();
|
|
||||||
|
|
||||||
return TRUE; /* Return with success */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Send a data packet to MMC */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if _READONLY == 0
|
|
||||||
static
|
|
||||||
BOOL xmit_datablock (
|
|
||||||
const BYTE *buff, /* 512 byte data block to be transmitted */
|
|
||||||
BYTE token /* Data/Stop token */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BYTE resp, wc;
|
|
||||||
|
|
||||||
|
|
||||||
if (wait_ready() != 0xFF) return FALSE;
|
|
||||||
|
|
||||||
xmit_spi(token); /* Xmit data token */
|
|
||||||
if (token != 0xFD) { /* Is data token */
|
|
||||||
wc = 0;
|
|
||||||
do { /* Xmit the 512 byte data block to MMC */
|
|
||||||
xmit_spi(*buff++);
|
|
||||||
xmit_spi(*buff++);
|
|
||||||
} while (--wc);
|
|
||||||
xmit_spi(0xFF); /* CRC (Dummy) */
|
|
||||||
xmit_spi(0xFF);
|
|
||||||
resp = rcvr_spi(); /* Reveive data response */
|
|
||||||
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif /* _READONLY */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Send a command packet to MMC */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE send_cmd (
|
|
||||||
BYTE cmd, /* Command byte */
|
|
||||||
DWORD arg /* Argument */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BYTE n, res;
|
|
||||||
|
|
||||||
|
|
||||||
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
|
||||||
cmd &= 0x7F;
|
|
||||||
res = send_cmd(CMD55, 0);
|
|
||||||
if (res > 1) return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the card and wait for ready */
|
|
||||||
DESELECT();
|
|
||||||
SELECT();
|
|
||||||
if (wait_ready() != 0xFF) return 0xFF;
|
|
||||||
|
|
||||||
/* Send command packet */
|
|
||||||
xmit_spi(cmd); /* Start + Command index */
|
|
||||||
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
|
|
||||||
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
|
|
||||||
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
|
|
||||||
xmit_spi((BYTE)arg); /* Argument[7..0] */
|
|
||||||
n = 0x01; /* Dummy CRC + Stop */
|
|
||||||
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
|
|
||||||
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
|
||||||
xmit_spi(n);
|
|
||||||
|
|
||||||
/* Receive command response */
|
|
||||||
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
|
|
||||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
|
||||||
do
|
|
||||||
res = rcvr_spi();
|
|
||||||
while ((res & 0x80) && --n);
|
|
||||||
|
|
||||||
return res; /* Return with the response value */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Public Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Initialize Disk Drive */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DSTATUS disk_initialize (
|
|
||||||
BYTE drv /* Physical drive nmuber (0) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BYTE n, cmd, ty, ocr[4];
|
|
||||||
|
|
||||||
|
|
||||||
if (drv) return STA_NOINIT; /* Supports only single drive */
|
|
||||||
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
|
|
||||||
|
|
||||||
power_on(); /* Force socket power on */
|
|
||||||
FCLK_SLOW();
|
|
||||||
for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
|
|
||||||
|
|
||||||
ty = 0;
|
|
||||||
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
|
|
||||||
Timer1 = 100; /* Initialization timeout of 1000 msec */
|
|
||||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDHC */
|
|
||||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */
|
|
||||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
|
||||||
while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
|
|
||||||
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
|
|
||||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
|
||||||
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* SDSC or MMC */
|
|
||||||
if (send_cmd(ACMD41, 0) <= 1) {
|
|
||||||
ty = CT_SD1; cmd = ACMD41; /* SDSC */
|
|
||||||
} else {
|
|
||||||
ty = CT_MMC; cmd = CMD1; /* MMC */
|
|
||||||
}
|
|
||||||
while (Timer1 && send_cmd(cmd, 0)); /* Wait for leaving idle state */
|
|
||||||
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
|
|
||||||
ty = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CardType = ty;
|
|
||||||
release_spi();
|
|
||||||
|
|
||||||
if (ty) { /* Initialization succeded */
|
|
||||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
|
||||||
FCLK_FAST();
|
|
||||||
} else { /* Initialization failed */
|
|
||||||
power_off();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Get Disk Status */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DSTATUS disk_status (
|
|
||||||
BYTE drv /* Physical drive nmuber (0) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (drv) return STA_NOINIT; /* Supports only single drive */
|
|
||||||
return Stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Read Sector(s) */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DRESULT disk_read (
|
|
||||||
BYTE drv, /* Physical drive nmuber (0) */
|
|
||||||
BYTE *buff, /* Pointer to the data buffer to store read data */
|
|
||||||
DWORD sector, /* Start sector number (LBA) */
|
|
||||||
BYTE count /* Sector count (1..255) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (drv || !count) return RES_PARERR;
|
|
||||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
|
||||||
|
|
||||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
|
||||||
|
|
||||||
if (count == 1) { /* Single block read */
|
|
||||||
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
|
|
||||||
&& rcvr_datablock(buff, 512))
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
else { /* Multiple block read */
|
|
||||||
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
|
|
||||||
do {
|
|
||||||
if (!rcvr_datablock(buff, 512)) break;
|
|
||||||
buff += 512;
|
|
||||||
} while (--count);
|
|
||||||
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
release_spi();
|
|
||||||
|
|
||||||
return count ? RES_ERROR : RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Write Sector(s) */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if _READONLY == 0
|
|
||||||
DRESULT disk_write (
|
|
||||||
BYTE drv, /* Physical drive nmuber (0) */
|
|
||||||
const BYTE *buff, /* Pointer to the data to be written */
|
|
||||||
DWORD sector, /* Start sector number (LBA) */
|
|
||||||
BYTE count /* Sector count (1..255) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (drv || !count) return RES_PARERR;
|
|
||||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
|
||||||
if (Stat & STA_PROTECT) return RES_WRPRT;
|
|
||||||
|
|
||||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
|
||||||
|
|
||||||
if (count == 1) { /* Single block write */
|
|
||||||
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
|
|
||||||
&& xmit_datablock(buff, 0xFE))
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
else { /* Multiple block write */
|
|
||||||
if (CardType & CT_SDC) send_cmd(ACMD23, count);
|
|
||||||
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
|
|
||||||
do {
|
|
||||||
if (!xmit_datablock(buff, 0xFC)) break;
|
|
||||||
buff += 512;
|
|
||||||
} while (--count);
|
|
||||||
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
|
|
||||||
count = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
release_spi();
|
|
||||||
|
|
||||||
return count ? RES_ERROR : RES_OK;
|
|
||||||
}
|
|
||||||
#endif /* _READONLY == 0 */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Miscellaneous Functions */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if _USE_IOCTL != 0
|
|
||||||
DRESULT disk_ioctl (
|
|
||||||
BYTE drv, /* Physical drive nmuber (0) */
|
|
||||||
BYTE ctrl, /* Control code */
|
|
||||||
void *buff /* Buffer to send/receive control data */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
BYTE n, csd[16], *ptr = buff;
|
|
||||||
WORD csize;
|
|
||||||
|
|
||||||
|
|
||||||
if (drv) return RES_PARERR;
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
|
|
||||||
if (ctrl == CTRL_POWER) {
|
|
||||||
switch (*ptr) {
|
|
||||||
case 0: /* Sub control code == 0 (POWER_OFF) */
|
|
||||||
if (chk_power())
|
|
||||||
power_off(); /* Power off */
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
case 1: /* Sub control code == 1 (POWER_ON) */
|
|
||||||
power_on(); /* Power on */
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
case 2: /* Sub control code == 2 (POWER_GET) */
|
|
||||||
*(ptr+1) = (BYTE)chk_power();
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
res = RES_PARERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (Stat & STA_NOINIT) return RES_NOTRDY;
|
|
||||||
|
|
||||||
switch (ctrl) {
|
|
||||||
case CTRL_SYNC : /* Make sure that no pending write process */
|
|
||||||
SELECT();
|
|
||||||
if (wait_ready() == 0xFF)
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
|
||||||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
|
|
||||||
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
|
|
||||||
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
|
|
||||||
*(DWORD*)buff = (DWORD)csize << 10;
|
|
||||||
} else { /* SDC ver 1.XX or MMC*/
|
|
||||||
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
|
|
||||||
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
|
|
||||||
*(DWORD*)buff = (DWORD)csize << (n - 9);
|
|
||||||
}
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
|
|
||||||
*(WORD*)buff = 512;
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
|
|
||||||
if (CardType & CT_SD2) { /* SDC ver 2.00 */
|
|
||||||
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
|
|
||||||
rcvr_spi();
|
|
||||||
if (rcvr_datablock(csd, 16)) { /* Read partial block */
|
|
||||||
for (n = 64 - 16; n; n--) rcvr_spi(); /* Purge trailing data */
|
|
||||||
*(DWORD*)buff = 16UL << (csd[10] >> 4);
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* SDC ver 1.XX or MMC */
|
|
||||||
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
|
|
||||||
if (CardType & CT_SD1) { /* SDC ver 1.XX */
|
|
||||||
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
|
|
||||||
} else { /* MMC */
|
|
||||||
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
|
|
||||||
}
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_TYPE : /* Get card type flags (1 byte) */
|
|
||||||
*ptr = CardType;
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
|
|
||||||
if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
|
|
||||||
&& rcvr_datablock(ptr, 16))
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
|
|
||||||
if (send_cmd(CMD10, 0) == 0 /* READ_CID */
|
|
||||||
&& rcvr_datablock(ptr, 16))
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
|
|
||||||
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
|
|
||||||
for (n = 4; n; n--) *ptr++ = rcvr_spi();
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_SDSTAT : /* Receive SD statsu as a data block (64 bytes) */
|
|
||||||
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
|
|
||||||
rcvr_spi();
|
|
||||||
if (rcvr_datablock(ptr, 64))
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
res = RES_PARERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
release_spi();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif /* _USE_IOCTL != 0 */
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Device Timer Interrupt Procedure (Platform dependent) */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* This function must be called in period of 10ms */
|
|
||||||
|
|
||||||
void disk_timerproc (void)
|
|
||||||
{
|
|
||||||
static BYTE pv;
|
|
||||||
BYTE n, s;
|
|
||||||
|
|
||||||
|
|
||||||
n = Timer1; /* 100Hz decrement timer */
|
|
||||||
if (n) Timer1 = --n;
|
|
||||||
n = Timer2;
|
|
||||||
if (n) Timer2 = --n;
|
|
||||||
|
|
||||||
n = pv;
|
|
||||||
pv = SOCKPORT & (SOCKWP | SOCKINS); /* Sample socket switch */
|
|
||||||
|
|
||||||
if (n == pv) { /* Have contacts stabled? */
|
|
||||||
s = Stat;
|
|
||||||
|
|
||||||
if (pv & SOCKWP) /* WP is H (write protected) */
|
|
||||||
s |= STA_PROTECT;
|
|
||||||
else /* WP is L (write enabled) */
|
|
||||||
s &= ~STA_PROTECT;
|
|
||||||
|
|
||||||
if (pv & SOCKINS) /* INS = H (Socket empty) */
|
|
||||||
s |= (STA_NODISK | STA_NOINIT);
|
|
||||||
else /* INS = L (Card inserted) */
|
|
||||||
s &= ~STA_NODISK;
|
|
||||||
|
|
||||||
Stat = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -22,9 +22,9 @@
|
|||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h> /* required by usbdrv.h */
|
||||||
#include <util/delay.h>
|
#include <util/delay.h> /* for _delay_ms() */
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h> /* for sei() */
|
||||||
|
|
||||||
#include "sram.h"
|
#include "sram.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@@ -36,7 +36,7 @@ uint8_t rle_decode(PGM_VOID_P in_addr, int32_t in_len, uint32_t out_addr)
|
|||||||
{
|
{
|
||||||
uint8_t in_byte, in_repeat, last_byte;
|
uint8_t in_byte, in_repeat, last_byte;
|
||||||
uint32_t out_len, out_len_left;
|
uint32_t out_len, out_len_left;
|
||||||
info("RLE decode len=%li addr=0x%08lx\n", in_len, out_addr);
|
info("RLE decode len=%li addr=0x%08lx\n",in_len,out_addr);
|
||||||
last_byte = 0;
|
last_byte = 0;
|
||||||
|
|
||||||
out_len_left = out_len;
|
out_len_left = out_len;
|
||||||
@@ -71,29 +71,23 @@ uint8_t rle_decode(PGM_VOID_P in_addr, int32_t in_len, uint32_t out_addr)
|
|||||||
OUTBYTE(in_byte);
|
OUTBYTE(in_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (in_len > 0) {
|
while( in_len > 0 ) {
|
||||||
INBYTE(in_byte);
|
INBYTE(in_byte);
|
||||||
if (in_len % 1024 == 0)
|
if (in_len%1024==0)
|
||||||
info(".");
|
info(".");
|
||||||
if (in_byte == RUNCHAR) {
|
if (in_byte == RUNCHAR) {
|
||||||
INBYTE(in_repeat);
|
INBYTE(in_repeat);
|
||||||
if (in_repeat == 0) {
|
if ( in_repeat == 0 ) {
|
||||||
/*
|
/* Just an escaped RUNCHAR value */
|
||||||
* Just an escaped RUNCHAR value
|
|
||||||
*/
|
|
||||||
OUTBYTE(RUNCHAR);
|
OUTBYTE(RUNCHAR);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/* Pick up value and output a sequence of it */
|
||||||
* Pick up value and output a sequence of it
|
in_byte = last_byte; //;out_data[-1];
|
||||||
*/
|
while ( --in_repeat > 0 )
|
||||||
in_byte = last_byte; // ;out_data[-1];
|
|
||||||
while (--in_repeat > 0)
|
|
||||||
OUTBYTE(in_byte);
|
OUTBYTE(in_byte);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/* Normal byte */
|
||||||
* Normal byte
|
|
||||||
*/
|
|
||||||
OUTBYTE(in_byte);
|
OUTBYTE(in_byte);
|
||||||
}
|
}
|
||||||
last_byte = in_byte;
|
last_byte = in_byte;
|
||||||
@@ -101,3 +95,63 @@ uint8_t rle_decode(PGM_VOID_P in_addr, int32_t in_len, uint32_t out_addr)
|
|||||||
sram_bulk_write_end();
|
sram_bulk_write_end();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t rle_decode_sram(uint32_t in_addr, int32_t in_len, uint32_t out_addr)
|
||||||
|
{
|
||||||
|
uint8_t in_byte, in_repeat, last_byte;
|
||||||
|
uint32_t out_len, out_len_left;
|
||||||
|
info("RLE decode len=%li addr=0x%08lx\n",in_len,out_addr);
|
||||||
|
last_byte = 0;
|
||||||
|
out_len_left = out_len;
|
||||||
|
#define INBYTE(b) \
|
||||||
|
do { \
|
||||||
|
if ( --in_len < 0 ) { \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
b = sram_read(in_addr);\
|
||||||
|
in_addr++;\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define OUTBYTE(b) \
|
||||||
|
do { \
|
||||||
|
sram_write(out_addr,b);\
|
||||||
|
out_addr++;\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
INBYTE(in_byte);
|
||||||
|
|
||||||
|
if (in_byte == RUNCHAR) {
|
||||||
|
INBYTE(in_repeat);
|
||||||
|
if (in_repeat != 0) {
|
||||||
|
info("Orphaned RLE code at start\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
OUTBYTE(RUNCHAR);
|
||||||
|
} else {
|
||||||
|
OUTBYTE(in_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
while( in_len > 0 ) {
|
||||||
|
INBYTE(in_byte);
|
||||||
|
if (in_len%1024==0)
|
||||||
|
info(".");
|
||||||
|
if (in_byte == RUNCHAR) {
|
||||||
|
INBYTE(in_repeat);
|
||||||
|
if ( in_repeat == 0 ) {
|
||||||
|
/* Just an escaped RUNCHAR value */
|
||||||
|
OUTBYTE(RUNCHAR);
|
||||||
|
} else {
|
||||||
|
/* Pick up value and output a sequence of it */
|
||||||
|
in_byte = last_byte; //;out_data[-1];
|
||||||
|
while ( --in_repeat > 0 )
|
||||||
|
OUTBYTE(in_byte);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Normal byte */
|
||||||
|
OUTBYTE(in_byte);
|
||||||
|
}
|
||||||
|
last_byte = in_byte;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,11 +18,12 @@
|
|||||||
* =====================================================================================
|
* =====================================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RLE_H__
|
#ifndef __RLE_H__
|
||||||
#define __RLE_H__
|
#define __RLE_H__
|
||||||
|
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
uint8_t rle_decode(PGM_VOID_P in_addr, uint32_t in_len, uint32_t out_addr);
|
uint8_t rle_decode(PGM_VOID_P in_addr,uint32_t in_len, uint32_t out_addr);
|
||||||
|
uint8_t rle_decode_sram(uint32_t in_addr, int32_t in_len, uint32_t out_addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
/* RTC controls */
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include "rtc.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL rtc_gettime (RTC *rtc)
|
|
||||||
{
|
|
||||||
BYTE buf[8];
|
|
||||||
|
|
||||||
|
|
||||||
rtc->sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 7) * 10;
|
|
||||||
rtc->min = (buf[1] & 0x0F) + (buf[1] >> 4) * 10;
|
|
||||||
rtc->hour = (buf[2] & 0x0F) + ((buf[2] >> 4) & 3) * 10;
|
|
||||||
rtc->wday = (buf[2] & 0x07);
|
|
||||||
rtc->mday = (buf[4] & 0x0F) + ((buf[4] >> 4) & 3) * 10;
|
|
||||||
rtc->month = (buf[5] & 0x0F) + ((buf[5] >> 4) & 1) * 10;
|
|
||||||
rtc->year = 2000 + (buf[6] & 0x0F) + (buf[6] >> 4) * 10;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL rtc_settime (const RTC *rtc)
|
|
||||||
{
|
|
||||||
|
|
||||||
BYTE buf[8];
|
|
||||||
|
|
||||||
|
|
||||||
buf[0] = rtc->sec / 10 * 16 + rtc->sec % 10;
|
|
||||||
buf[1] = rtc->min / 10 * 16 + rtc->min % 10;
|
|
||||||
buf[2] = rtc->hour / 10 * 16 + rtc->hour % 10;
|
|
||||||
buf[3] = rtc->wday & 7;
|
|
||||||
buf[4] = rtc->mday / 10 * 16 + rtc->mday % 10;
|
|
||||||
buf[5] = rtc->month / 10 * 16 + rtc->month % 10;
|
|
||||||
buf[6] = (rtc->year - 2000) / 10 * 16 + (rtc->year - 2000) % 10;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#include "integer.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
WORD year; /* 2000..2099 */
|
|
||||||
BYTE month; /* 1..12 */
|
|
||||||
BYTE mday; /* 1.. 31 */
|
|
||||||
BYTE wday; /* 1..7 */
|
|
||||||
BYTE hour; /* 0..23 */
|
|
||||||
BYTE min; /* 0..59 */
|
|
||||||
BYTE sec; /* 0..59 */
|
|
||||||
} RTC;
|
|
||||||
|
|
||||||
BOOL rtc_gettime (RTC*); /* Get time */
|
|
||||||
BOOL rtc_settime (const RTC*); /* Set time */
|
|
||||||
|
|
||||||
@@ -38,113 +38,55 @@ uint8_t scratchpad_state;
|
|||||||
uint8_t scratchpad_cmd;
|
uint8_t scratchpad_cmd;
|
||||||
uint8_t scratchpad_payload;
|
uint8_t scratchpad_payload;
|
||||||
|
|
||||||
void shared_memory_scratchpad_tx_save()
|
void shared_memory_scratchpad_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_tx_restore()
|
void shared_memory_scratchpad_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);
|
||||||
irq_addr_hi = sram_read(SHARED_IRQ_LOC_HI);
|
irq_addr_hi = sram_read(SHARED_IRQ_LOC_HI);
|
||||||
sram_write(SHARED_IRQ_HANDLER_LO, 0);
|
sram_write(SHARED_IRQ_HANDLER_LO, 0);
|
||||||
sram_write(SHARED_IRQ_HANDLER_HI, 0);
|
sram_write(SHARED_IRQ_HANDLER_HI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shared_memory_irq_restore()
|
void shared_memory_irq_restore(){
|
||||||
{
|
|
||||||
sram_write(SHARED_IRQ_LOC_LO, irq_addr_lo);
|
sram_write(SHARED_IRQ_LOC_LO, irq_addr_lo);
|
||||||
sram_write(SHARED_IRQ_LOC_HI, irq_addr_hi);
|
sram_write(SHARED_IRQ_LOC_HI, irq_addr_hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shared_memory_write(uint8_t cmd, uint8_t value)
|
void shared_memory_put(uint8_t cmd, uint8_t value){
|
||||||
{
|
|
||||||
|
|
||||||
debug(DEBUG_SHM,"shared_memory_write: 0x%04x=0x%02x 0x%04x=0x%02x \n",
|
info("Write shared memory 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_tx_save();
|
shared_memory_scratchpad_save();
|
||||||
shared_memory_irq_hook();
|
shared_memory_irq_hook();
|
||||||
|
|
||||||
sram_write(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_SNES_ACK);
|
sram_write(SHARED_MEM_LOC_STATE,SHARED_MEM_SNES_ACK);
|
||||||
sram_write(SHARED_MEM_TX_LOC_CMD, cmd);
|
sram_write(SHARED_MEM_LOC_CMD,cmd);
|
||||||
sram_write(SHARED_MEM_TX_LOC_PAYLOAD, value);
|
sram_write(SHARED_MEM_LOC_PAYLOAD,value);
|
||||||
|
|
||||||
snes_hirom();
|
snes_hirom();
|
||||||
|
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_off();
|
||||||
snes_lorom();
|
snes_lorom();
|
||||||
|
snes_wr_disable();
|
||||||
|
|
||||||
shared_memory_scratchpad_tx_restore();
|
shared_memory_scratchpad_restore();
|
||||||
shared_memory_irq_restore();
|
shared_memory_irq_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*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_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();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,42 +22,30 @@
|
|||||||
#define __SHARED_MEMORY_H__
|
#define __SHARED_MEMORY_H__
|
||||||
|
|
||||||
|
|
||||||
#define SHARED_MEM_SWITCH_IRQ 0
|
#define SHARED_MEM_SNES_ACK 0xa5
|
||||||
#define SHARED_MEM_SWITCH_DELAY 20
|
#define SHARED_MEM_SNES_RTS 0x5a
|
||||||
|
|
||||||
#define SHARED_MEM_TX_SNES_ACK 0xa5
|
|
||||||
#define SHARED_MEM_TX_SNES_RTS 0x5a
|
|
||||||
|
|
||||||
#define SHARED_MEM_TX_CMD_BANK_COUNT 0x00
|
#define SHARED_MEM_CMD_BANK_COUNT 0
|
||||||
#define SHARED_MEM_TX_CMD_BANK_CURRENT 0x01
|
#define SHARED_MEM_CMD_BANK_CURRENT 1
|
||||||
|
|
||||||
#define SHARED_MEM_TX_CMD_UPLOAD_START 0x03
|
#define SHARED_MEM_CMD_UPLOAD_START 3
|
||||||
#define SHARED_MEM_TX_CMD_UPLOAD_END 0x04
|
#define SHARED_MEM_CMD_UPLOAD_END 4
|
||||||
#define SHARED_MEM_TX_CMD_UPLOAD_PROGESS 0x05
|
#define SHARED_MEM_CMD_UPLOAD_PROGESS 5
|
||||||
#define SHARED_MEM_TX_CMD_TERMINATE 0x06
|
#define SHARED_MEM_CMD_TERMINATE 6
|
||||||
|
|
||||||
#define SHARED_MEM_TX_LOC_STATE 0x000000
|
|
||||||
#define SHARED_MEM_TX_LOC_CMD 0x000001
|
|
||||||
#define SHARED_MEM_TX_LOC_PAYLOAD 0x000002
|
|
||||||
|
|
||||||
#define SHARED_MEM_RX_AVR_ACK 0xa5
|
#define SHARED_MEM_LOC_STATE 0x000000
|
||||||
#define SHARED_MEM_RX_AVR_RTS 0x5a
|
#define SHARED_MEM_LOC_CMD 0x000001
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
#define SHARED_IRQ_HANDLER_LO 0x00
|
#define SHARED_IRQ_HANDLER_LO 0x00
|
||||||
#define SHARED_IRQ_HANDLER_HI 0x10
|
#define SHARED_IRQ_HANDLER_HI 0x10
|
||||||
|
|
||||||
void shared_memory_write(uint8_t cmd, uint8_t value);
|
void shared_memory_put(uint8_t cmd, uint8_t value);
|
||||||
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -309,3 +309,48 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,9 @@ 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);
|
||||||
|
|||||||
@@ -1,264 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* =====================================================================================
|
|
||||||
*
|
|
||||||
* ________ .__ __ ________ ____ ________
|
|
||||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
|
||||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
|
||||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
|
||||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
|
||||||
* \__> \/ \/ \/ \/ \/
|
|
||||||
*
|
|
||||||
* www.optixx.org
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Version: 1.0
|
|
||||||
* Created: 07/21/2009 03:32:16 PM
|
|
||||||
* Author: david@optixx.org
|
|
||||||
*
|
|
||||||
* =====================================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <util/delay.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <avr/eeprom.h>
|
|
||||||
|
|
||||||
#include "usbdrv.h"
|
|
||||||
#include "oddebug.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "requests.h"
|
|
||||||
#include "uart.h"
|
|
||||||
#include "sram.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "info.h"
|
|
||||||
#include "dump.h"
|
|
||||||
#include "crc.h"
|
|
||||||
#include "usb_bulk.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "watchdog.h"
|
|
||||||
#include "rle.h"
|
|
||||||
#include "loader.h"
|
|
||||||
#include "command.h"
|
|
||||||
#include "shared_memory.h"
|
|
||||||
#include "testing.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
/* FAT file system sample project for FatFs R0.06 (C)ChaN, 2008 */
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "ff.h"
|
|
||||||
#include "diskio.h"
|
|
||||||
#include "rtc.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DWORD acc_size; /* Work register for fs command */
|
|
||||||
WORD acc_files, acc_dirs;
|
|
||||||
FILINFO finfo;
|
|
||||||
|
|
||||||
|
|
||||||
FATFS fatfs[2]; /* File system object for each logical drive */
|
|
||||||
BYTE Buff[1024]; /* Working buffer */
|
|
||||||
|
|
||||||
volatile WORD Timer; /* 100Hz increment timer */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if _MULTI_PARTITION != 0
|
|
||||||
const PARTITION Drives[] = { {0,0}, {0,1} };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
ISR(TIMER2_COMP_vect)
|
|
||||||
{
|
|
||||||
Timer++;
|
|
||||||
disk_timerproc();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
DWORD get_fattime ()
|
|
||||||
{
|
|
||||||
RTC rtc;
|
|
||||||
|
|
||||||
|
|
||||||
//rtc_gettime(&rtc);
|
|
||||||
|
|
||||||
return ((DWORD)(rtc.year - 1980) << 25)
|
|
||||||
| ((DWORD)rtc.month << 21)
|
|
||||||
| ((DWORD)rtc.mday << 16)
|
|
||||||
| ((DWORD)rtc.hour << 11)
|
|
||||||
| ((DWORD)rtc.min << 5)
|
|
||||||
| ((DWORD)rtc.sec >> 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
FRESULT scan_files (char* path)
|
|
||||||
{
|
|
||||||
DIR dirs;
|
|
||||||
FRESULT res;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((res = f_opendir(&dirs, path)) == FR_OK) {
|
|
||||||
i = strlen(path);
|
|
||||||
while (((res = f_readdir(&dirs, &finfo)) == FR_OK) && finfo.fname[0]) {
|
|
||||||
if (finfo.fattrib & AM_DIR) {
|
|
||||||
acc_dirs++;
|
|
||||||
*(path+i) = '/'; strcpy(path+i+1, &finfo.fname[0]);
|
|
||||||
res = scan_files(path);
|
|
||||||
*(path+i) = '\0';
|
|
||||||
if (res != FR_OK) break;
|
|
||||||
} else {
|
|
||||||
acc_files++;
|
|
||||||
acc_size += finfo.fsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void put_rc (FRESULT rc)
|
|
||||||
{
|
|
||||||
const prog_char *p;
|
|
||||||
static const prog_char str[] =
|
|
||||||
"OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0"
|
|
||||||
"INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0" "WRITE_PROTECTED\0"
|
|
||||||
"INVALID_DRIVE\0" "NOT_ENABLED\0" "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0";
|
|
||||||
FRESULT i;
|
|
||||||
|
|
||||||
for (p = str, i = 0; i != rc && pgm_read_byte_near(p); i++) {
|
|
||||||
while(pgm_read_byte_near(p++));
|
|
||||||
}
|
|
||||||
printf("rc=%u FR_%s\n", (WORD)rc, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void test_sdcard (void)
|
|
||||||
{
|
|
||||||
char *ptr, *ptr2;
|
|
||||||
DWORD p1, p2, p3;
|
|
||||||
BYTE res, b1;
|
|
||||||
WORD w1;
|
|
||||||
UINT s1, s2, cnt;
|
|
||||||
DWORD ofs, sect = 0;
|
|
||||||
RTC rtc;
|
|
||||||
FATFS *fs;
|
|
||||||
DIR dir; /* Directory object */
|
|
||||||
FIL file1, file2; /* File object */
|
|
||||||
|
|
||||||
|
|
||||||
printf("Try to init disk\n");
|
|
||||||
put_rc(f_mount((BYTE) 0, &fatfs[0]));
|
|
||||||
res = f_getfree("", &p2, &fs);
|
|
||||||
if (res)
|
|
||||||
put_rc(res);
|
|
||||||
|
|
||||||
printf( "FAT TYPE = %u\nBYTES/CLUSTER = %lu\nNUMBER OF FATS = %u\n"
|
|
||||||
"ROOT DIR ENTRIES = %u\nSECTORS/FAT = %lu\nNUMBER OF CLUSTERS = %lu\n"
|
|
||||||
"FAT START = %lu\nDIR START LBA,CLUSTER = %lu\nDATA START LBA = %lu\n",
|
|
||||||
(WORD) fs->fs_type, (DWORD) fs->csize * 512,
|
|
||||||
(WORD) fs->n_fats, fs->n_rootdir, (DWORD) fs->sects_fat,
|
|
||||||
(DWORD) fs->max_clust - 2, fs->fatbase, fs->dirbase, fs->database);
|
|
||||||
acc_size = acc_files = acc_dirs = 0;
|
|
||||||
|
|
||||||
printf("scan files\n");
|
|
||||||
res = scan_files("");
|
|
||||||
if (res)
|
|
||||||
put_rc(res);
|
|
||||||
printf("%u FILES, %lu BYTES\n%u FOLDERS\n"
|
|
||||||
"%lu KB TOTAK DISK SPACE\n%lu KB AVAILABLE\n", acc_files,
|
|
||||||
acc_size, acc_dirs, (fs->max_clust - 2) * (fs->csize / 2),
|
|
||||||
p2 * (fs->csize / 2));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* =====================================================================================
|
|
||||||
*
|
|
||||||
* ________ .__ __ ________ ____ ________
|
|
||||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
|
||||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
|
||||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
|
||||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
|
||||||
* \__> \/ \/ \/ \/ \/
|
|
||||||
*
|
|
||||||
* 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();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -37,4 +37,3 @@ static int uart_stream(char c, FILE *stream);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,16 @@ 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_BULK_UPLOAD) {
|
if (req_state == REQ_STATUS_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",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ import time
|
|||||||
|
|
||||||
|
|
||||||
LEN = 2**16
|
LEN = 2**16
|
||||||
huffman = False
|
|
||||||
TARGET="/Users/david/Devel/arch/avr/code/quickdev16/avr/usbload"
|
TARGET="/Users/david/Devel/arch/avr/code/quickdev16/avr/usbload"
|
||||||
HUFFMAN_ENCODER="/Users/david/Devel/arch/avr/code/quickdev16/tools/huffman/huffman-encode"
|
HUFFMAN_ENCODER="/Users/david/Devel/arch/avr/code/quickdev16/tools/huffman/huffman-encode"
|
||||||
data = open(sys.argv[1],"r").read()
|
data = open(sys.argv[1],"r").read()
|
||||||
@@ -15,21 +15,19 @@ print "Use %i bytes" % (len(data))
|
|||||||
data = binascii.rlecode_hqx(data)
|
data = binascii.rlecode_hqx(data)
|
||||||
print "RLE crunch (%i) bytes" % (len(data))
|
print "RLE crunch (%i) bytes" % (len(data))
|
||||||
|
|
||||||
|
binfile = open("/tmp/loader.rle","w")
|
||||||
|
binfile.write(data)
|
||||||
|
binfile.close()
|
||||||
rle_size = len(data)
|
rle_size = len(data)
|
||||||
huffman_size = 0
|
|
||||||
|
|
||||||
if huffman == True:
|
cmd = "%s /tmp/loader.rle" % HUFFMAN_ENCODER
|
||||||
binfile = open("/tmp/loader.rle","w")
|
os.system(cmd)
|
||||||
binfile.write(data)
|
data = open("/tmp/loader.rle.hfm","r").read()
|
||||||
binfile.close()
|
print "HUFFMAN crunch (%i) bytes" % (len(data))
|
||||||
|
huffman_size = len(data)
|
||||||
|
|
||||||
cmd = "%s /tmp/loader.rle" % HUFFMAN_ENCODER
|
os.unlink("/tmp/loader.rle")
|
||||||
os.system(cmd)
|
os.unlink("/tmp/loader.rle.hfm")
|
||||||
data = open("/tmp/loader.rle.hfm","r").read()
|
|
||||||
print "HUFFMAN crunch (%i) bytes" % (len(data))
|
|
||||||
huffman_size = len(data)
|
|
||||||
os.unlink("/tmp/loader.rle")
|
|
||||||
os.unlink("/tmp/loader.rle.hfm")
|
|
||||||
|
|
||||||
cfile = open("/tmp/loader.c","w")
|
cfile = open("/tmp/loader.c","w")
|
||||||
hfile = open("/tmp/loader.h","w")
|
hfile = open("/tmp/loader.h","w")
|
||||||
|
|||||||
Reference in New Issue
Block a user