complete overhaul and reimplementation of the MMC Code

Implement Checksumming
Implement Multiblock-Operation
Also increase performance by reducing function calls for SPI handling
This commit is contained in:
Oliver Lehmann 2012-06-05 18:21:48 +00:00
parent ff85359a85
commit 22fbb4f11c
10 changed files with 597 additions and 371 deletions

View File

@ -110,7 +110,7 @@ OUTPUT_FILE_DEP:= ./makedep.mk
./%.o: .././%.c
@echo Building file: $<
@echo Invoking: AVR/GNU C Compiler : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
$(QUOTE)C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe$(QUOTE) -funsigned-char -funsigned-bitfields -O1 -fpack-struct -fshort-enums -Wall -Wundef -Werror -pedantic -pedantic-errors -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -mmcu=atmega1284p -o"$@" "$<"
$(QUOTE)C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe$(QUOTE) -funsigned-char -funsigned-bitfields -O1 -ffunction-sections -fpack-struct -fshort-enums -Wall -Wundef -Werror -pedantic -pedantic-errors -c -std=gnu99 -save-temps -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -mmcu=atmega1284p -o"$@" "$<"
@echo Finished building: $<
@ -138,7 +138,7 @@ all: $(OUTPUT_FILE_PATH) $(ADDITIONAL_DEPENDENCIES)
$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP)
@echo Building target: $@
@echo Invoking: AVR/GNU Linker : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
$(QUOTE)C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe$(QUOTE) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -Wl,-Map="P8000_WDC_Emulator.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -mmcu=atmega1284p
$(QUOTE)C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe$(QUOTE) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -Wl,-Map="P8000_WDC_Emulator.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mrelax -mmcu=atmega1284p
@echo Finished building target: $@
"C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature "P8000_WDC_Emulator.elf" "P8000_WDC_Emulator.hex"
"C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-objcopy.exe" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "P8000_WDC_Emulator.elf" "P8000_WDC_Emulator.eep" || exit 0

View File

@ -51,6 +51,7 @@
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</avrgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
@ -58,11 +59,14 @@
<avrgcc.compiler.warnings.WarningsAsErrors>True</avrgcc.compiler.warnings.WarningsAsErrors>
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
<avrgcc.compiler.warnings.PedanticWarningsAsErrors>True</avrgcc.compiler.warnings.PedanticWarningsAsErrors>
<avrgcc.compiler.miscellaneous.DoNotDeleteTemporaryFiles>True</avrgcc.compiler.miscellaneous.DoNotDeleteTemporaryFiles>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>m</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.linker.optimization.GarbageCollectUnusedSections>True</avrgcc.linker.optimization.GarbageCollectUnusedSections>
<avrgcc.linker.optimization.RelaxBranches>True</avrgcc.linker.optimization.RelaxBranches>
</AvrGcc>
</ToolchainSettings>
</PropertyGroup>
@ -82,6 +86,9 @@
<Compile Include="mmc.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="sd.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="uart.c">
<SubType>compile</SubType>
</Compile>

View File

@ -1,7 +1,7 @@
/*
* P8000 WDC Emulator
*
* $Id: wdc_config.h,v 1.4 2012/05/30 20:07:10 olivleh1 Exp $
* $Id: wdc_config.h,v 1.5 2012/06/05 18:21:48 olivleh1 Exp $
*
*/
@ -11,6 +11,10 @@
#define F_CPU 18432000UL
/*
* P8000 Interface
*/
#define PORT_DATA PORTA
#define PIN_DATA PINA
#define DDR_DATA DDRA
@ -28,4 +32,20 @@
#define PIN_INFO_TR PINC6
#define PIN_INFO_RST PINC7
/*
* SD-Card Interface
*/
#define PORT_MMC PORTB
#define PIN_MMC PINB
#define DDR_MMC DDRB
#define PIN_MMC_CS PINB4 //AVR Port where the MMC Card /CS signal is connected to
#define PIN_MMC_MOSI PINB5 //AVR Port: MOSI / MMC Card: Data-In
#define PIN_MMC_MISO PINB6 //AVR Port: MISO / MMC Card: Data-Out
#define PIN_MMC_SCK PINB7 //AVR Port: SCk / MMC Card: CLK
//maximum performance with both turned off
//#define MMC_PRESET_MULTIBLOCKCOUNT 1
//#define SPI_CRC 1
#endif /* CONFIG_H_ */

View File

@ -1,34 +1,43 @@
/*#######################################################################################
Connect AVR to MMC/SD
Copyright (C) 2004 Ulrich Radig
Bei Fragen und Verbesserungen wendet euch per EMail an
mail@ulrichradig.de
oder im Forum meiner Web Page : www.ulrichradig.de
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
GNU General Public License, wie von der Free Software Foundation veröffentlicht,
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
(nach Ihrer Option) jeder späteren Version.
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
Programm erhalten haben.
Falls nicht, schreiben Sie an die Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#######################################################################################*/
/*
* P8000 WDC Emulator
*
* $Id: wdc_drv_mmc.c,v 1.4 2012/06/05 18:21:48 olivleh1 Exp $
*
*/
#include <avr/io.h>
#include "config.h"
#include "mmc.h"
#define wait_till_send_done() while ( ! ( SPSR & ( 1 << SPIF ) ) )
#define wait_till_card_ready() do { send_dummy_byte(); } while ( !recv_byte() )
#define send_dummy_byte() SPDR = 0xFF; wait_till_send_done()
#define recv_byte() SPDR
#define xmit_byte(x) SPDR = x
#define MMC_Disable() PORT_MMC|= (1<<PIN_MMC_CS);
#define MMC_Enable() PORT_MMC=~(1<<PIN_MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#define CMD0 (0x40 + 0)
#define CMD1 (0x40 + 1)
#define CMD12 (0x40 + 12)
#define CMD17 (0x40 + 17)
#define CMD18 (0x40 + 18)
#define CMD23 (0x40 + 23)
#define CMD24 (0x40 + 24)
#define CMD25 (0x40 + 25)
#define CMD55 (0x40 + 55)
#define CMD59 (0x40 + 59)
#define SB_START 0xFE
#define MB_START 0xFC
#define MB_STOP 0xFD
uint8_t mmc_read_block ( uint8_t *, uint8_t *, uint16_t );
uint8_t mmc_cmd ( uint8_t * );
#ifdef SPI_CRC
const uint16_t crc_itu_t_table[256] = {
const uint16_t crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
@ -63,377 +72,293 @@ const uint16_t crc_itu_t_table[256] = {
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
#define CRC7_POLY 0x09
unsigned char CRC_7Bit ( unsigned char *pData, unsigned int uiLen )
const uint8_t crc7_table[256] = {
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
};
uint8_t crc7 ( const uint8_t *buffer, uint8_t len )
{
unsigned int i, c, bit;
unsigned int crc = 0;
while ( uiLen-- ) {
c = ( unsigned long ) * pData++;
for ( i = 0x80; i; i >>= 1 ) {
bit = crc & 0x40;
crc <<= 1;
if ( c & i ) crc |= 1;
if ( bit ) crc ^= CRC7_POLY;
}
uint8_t crc = 0x00;
while ( len-- )
crc = crc7_table[ ( crc << 1 ) ^ *buffer++];
return crc;
}
for ( i = 0; i < 7; i++ ) {
if ( crc & 0x40 ) {
crc = ( crc << 1 ) ^ CRC7_POLY;
} else
crc <<= 1;
}
return ( crc & 0x7F );
}
unsigned short CRC_16Bit ( unsigned char *pData, unsigned int uiLen )
uint16_t crc16 ( const uint8_t *buffer, uint16_t len )
{
unsigned short usCRC;
//Init CRC register to zero (Required by SD card)
usCRC = 0x0000;
while ( uiLen-- ) {
//Do table lookup and xor result
//see "Painless guide to CRC error detection algorithms" section 10
usCRC = ( usCRC << 8 ) ^ crc_itu_t_table[ ( usCRC >> 8 ) ^ *pData++];
uint16_t crc = 0x0000;
while ( len-- ) {
crc = ( crc << 8 ) ^ crc16_table[ ( crc >> 8 ) ^ *buffer++];
}
return usCRC;
return crc;
}
#endif
unsigned int SDSetCRC ( unsigned int uiCRC )
uint8_t SDSetCRC ( uint8_t on_off )
{
unsigned char ucSDSetCRC[] = {0x3B, 0x00, 0x00, 0x00, 0x00, 0xFF};
unsigned char cmd[] = {CMD59, 0x00, 0x00, 0x00, 0x00, 0xFF};
ucSDSetCRC[0] = 0x3B;
//tail bit of uiCRC sets or clears CRC mode
ucSDSetCRC[4] = uiCRC & 0x01;
//last bit enables or disables CRC mode
cmd[4] = on_off & 0x01;
if ( mmc_write_command ( ucSDSetCRC ) != 0 ) {
if ( mmc_cmd ( cmd ) != 0 ) {
return 1;
}
return 0;
}
//############################################################################
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
uint8_t mmc_init ()
//############################################################################
{
uint8_t Timeout = 0;
//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
MMC_Direction_REG &= ~ ( 1 << SPI_DI ); //Setzen von Pin MMC_DI auf Input
MMC_Direction_REG |= ( 1 << SPI_Clock ); //Setzen von Pin MMC_Clock auf Output
MMC_Direction_REG |= ( 1 << SPI_DO ); //Setzen von Pin MMC_DO auf Output
MMC_Direction_REG |= ( 1 << MMC_Chip_Select ); //Setzen von Pin MMC_Chip_Select auf Output
MMC_Write |= ( 1 << MMC_Chip_Select ); //Setzt den Pin MMC_Chip_Select auf High Pegel
DDR_MMC &= ~ ( 1 << PIN_MMC_MISO );
DDR_MMC |= ( 1 << PIN_MMC_SCK );
DDR_MMC |= ( 1 << PIN_MMC_MOSI );
DDR_MMC |= ( 1 << PIN_MMC_CS );
MMC_Enable();
for ( uint8_t a = 0; a < 200; a++ ) {
nop();
}; //Wartet eine kurze Zeit
};
#if SPI_Mode
//Aktiviren des SPI - Bus, Clock = Idel LOW
//SPI Clock teilen durch 128
SPCR = ( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR0 ) | ( 1 << SPR1 ); //Enable SPI, SPI in Master Mode
SPSR = ( 0 << SPI2X );
#endif
//Initialisiere MMC/SD-Karte in den SPI-Mode
for ( uint8_t b = 0; b < 0x0f; b++ ) { //Sendet min 74+ Clocks an die MMC/SD-Karte
mmc_write_byte ( 0xff );
for ( uint8_t b = 0; b < 0x0f; b++ ) {
send_dummy_byte();
}
//Sendet Commando CMD0 an MMC/SD-Karte
uint8_t CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
while ( mmc_write_command ( CMD ) != 1 ) {
/*
* send CMD0
*/
uint8_t cmd[] = {CMD0, 0x00, 0x00, 0x00, 0x00, 0x95};
while ( mmc_cmd ( cmd ) != 1 ) {
if ( Timeout++ > 200 ) {
MMC_Disable();
return ( 1 ); //Abbruch bei Commando1 (Return Code1)
return ( 1 );
}
}
//Sendet Commando CMD1 an MMC/SD-Karte
/*
* send CMD1
*/
Timeout = 0;
CMD[0] = 0x41;//Commando 1
CMD[5] = 0xFF;
while ( mmc_write_command ( CMD ) != 0 ) {
cmd[0] = CMD1;
cmd[5] = 0xFF;
while ( mmc_cmd ( cmd ) != 0 ) {
if ( Timeout++ > 400 ) {
MMC_Disable();
return ( 2 ); //Abbruch bei Commando2 (Return Code2)
return ( 2 );
}
}
#if SPI_Mode
//SPI Bus auf max Geschwindigkeit
//SPI Bus to max. speed
SPCR &= ~ ( ( 1 << SPR0 ) | ( 1 << SPR1 ) );
SPSR = SPSR | ( 1 << SPI2X );
#endif
#ifdef SPI_CRC
SDSetCRC ( 1 );
#else
SDSetCRC ( 0 );
#endif
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
MMC_Disable();
return ( 0 );
}
//############################################################################
//Sendet ein Commando an die MMC/SD-Karte
uint8_t mmc_write_command ( uint8_t *cmd )
//############################################################################
uint8_t mmc_cmd ( uint8_t *cmd )
{
uint8_t tmp = 0xff;
uint8_t Timeout = 0;
uint8_t tmp = 0x80;
uint8_t i = 10;
uint8_t cmd0 = cmd[0];
#ifdef SPI_CRC
unsigned char ucCRC;
//Calculate CRC and framing bits
cmd[0] = ( cmd[0] | ( 1 << 6 ) ) & 0x7F;
ucCRC = CRC_7Bit ( cmd, 5 ) << 1;
cmd[5] = ucCRC;
cmd[5] = crc7 ( cmd, 5 ) << 1;
#endif
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
MMC_Disable();
//sendet 8 Clock Impulse
mmc_write_byte ( 0xFF );
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
MMC_Enable();
//sendet 6 Byte Commando
for ( uint8_t a = 0; a < 0x06; a++ ) { //sendet 6 Byte Commando zur MMC/SD-Karte
mmc_write_byte ( *cmd++ );
// send command
for ( uint8_t a = 0; a < 0x06; a++ ) {
xmit_byte ( *cmd++ );
wait_till_send_done();
}
//Wartet auf ein gültige Antwort von der MMC/SD-Karte
while ( tmp == 0xff ) {
tmp = mmc_read_byte();
if ( Timeout++ > 500 ) {
break; //Abbruch da die MMC/SD-Karte nicht Antwortet
}
}
if ( cmd0 == ( CMD12 ) ) recv_byte();
do {
send_dummy_byte();
tmp = recv_byte();
} while ( ( tmp & 0x80 ) && --i );
return ( tmp );
}
//############################################################################
//Routine zum Empfangen eines Bytes von der MMC-Karte
uint8_t mmc_read_byte ( void )
//############################################################################
{
uint8_t Byte = 0;
#if SPI_Mode //Routine für Hardware SPI
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
Byte = SPDR;
#else //Routine für Software SPI
for ( uint8_t a = 8; a > 0; a-- ) { //das Byte wird Bitweise nacheinander Empangen MSB First
MMC_Write &= ~ ( 1 << SPI_Clock ); //erzeugt ein Clock Impuls (Low)
if ( bit_is_set ( MMC_Read, SPI_DI ) > 0 ) { //Lesen des Pegels von MMC_DI
Byte |= ( 1 << ( a - 1 ) );
} else {
Byte &= ~ ( 1 << ( a - 1 ) );
}
MMC_Write |= ( 1 << SPI_Clock ); //setzt Clock Impuls wieder auf (High)
}
#endif
return ( Byte );
}
//############################################################################
//Routine zum Senden eines Bytes zur MMC-Karte
void mmc_write_byte ( uint8_t Byte )
//############################################################################
{
#if SPI_Mode //Routine für Hardware SPI
SPDR = Byte; //Sendet ein Byte
while ( ! ( SPSR & ( 1 << SPIF ) ) ) { //Wartet bis Byte gesendet wurde
}
#else //Routine für Software SPI
for ( uint8_t a = 8; a > 0; a-- ) { //das Byte wird Bitweise nacheinander Gesendet MSB First
if ( bit_is_set ( Byte, ( a - 1 ) ) > 0 ) { //Ist Bit a in Byte gesetzt
MMC_Write |= ( 1 << SPI_DO ); //Set Output High
} else {
MMC_Write &= ~ ( 1 << SPI_DO ); //Set Output Low
}
MMC_Write &= ~ ( 1 << SPI_Clock ); //erzeugt ein Clock Impuls (LOW)
MMC_Write |= ( 1 << SPI_Clock ); //setzt Clock Impuls wieder auf (High)
}
MMC_Write |= ( 1 << SPI_DO ); //setzt Output wieder auf High
#endif
}
//############################################################################
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
uint8_t mmc_write_sector ( uint32_t addr, uint8_t *Buffer )
//############################################################################
{
uint8_t tmp;
//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
uint8_t cmd[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
uint8_t cmd[] = {CMD24, 0x00, 0x00, 0x00, 0x00, 0xFF};
#ifdef SPI_CRC
unsigned int uiCheckSum;
uint16_t crc;
uint8_t crcl, crch;
#endif
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingefügt*/
MMC_Enable();
// convert blocks to bytes
addr = addr << 9; //addr = addr * 512
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
//Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
tmp = mmc_write_command ( cmd );
/*
* send CMD24
*/
tmp = mmc_cmd ( cmd );
if ( tmp != 0 ) {
MMC_Disable();
return ( tmp );
}
SPDR = 0xFE; //Sendet Startbyte
//send Startbyte
xmit_byte ( SB_START );
#ifdef SPI_CRC
uiCheckSum = CRC_16Bit ( Buffer, 512 );
crc = crc16 ( Buffer, 512 );
crch = crc >> 8;
crcl = crc & 0xff;
#endif
//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
//write a single block
for ( uint16_t a = 0; a < 512; a++ ) {
uint8_t data = *Buffer;
Buffer++;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
SPDR = data; //Sendet ein Byte
wait_till_send_done();
xmit_byte ( data );
}
while ( ! ( SPSR & ( 1 << SPIF ) ) );
wait_till_send_done();
//CRC-Byte schreiben
//handle CRC
#ifdef SPI_CRC
SPDR = uiCheckSum >> 8;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
SPDR = uiCheckSum & 0xFF;
xmit_byte ( crch );
wait_till_send_done();
xmit_byte ( crcl );
wait_till_send_done();
#else
SPDR = 0xFF;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
SPDR = 0xFF;
send_dummy_byte();
send_dummy_byte();
#endif
while ( ! ( SPSR & ( 1 << SPIF ) ) );
//Fehler beim schreiben? (Data Response XXX00101 = OK)
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
if ( ( SPDR & 0x1F ) != 0x05 ) return ( 0x02 );
//Wartet auf MMC/SD-Karte Bussy
while ( 1 ) {
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
if ( SPDR == 0xff )
break;
//check for errors
send_dummy_byte();
if ( ( recv_byte() & 0x1F ) != 0x05 ) {
MMC_Disable();
return ( 2 );
}
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
wait_till_card_ready();
MMC_Disable();
return ( 0 );
}
//############################################################################
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
uint8_t mmc_read_block ( uint8_t *cmd, uint8_t *Buffer, uint16_t Bytes )
//############################################################################
{
#ifdef SPI_CRC
uint16_t crc;
#endif
//Sendet Commando cmd an MMC/SD-Karte
if ( mmc_write_command ( cmd ) != 0 ) {
MMC_Enable();
//send command
if ( mmc_cmd ( cmd ) != 0 ) {
MMC_Disable();
return ( 1 );
}
//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
//wait for startbyte
while ( 1 ) {
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
if ( SPDR == 0xfe )
send_dummy_byte();
if ( recv_byte() == SB_START )
break;
}
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
*Buffer = SPDR;
//read first byte
send_dummy_byte();
*Buffer = recv_byte();
//Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
//read the remaining 511 bytes
for ( uint16_t a = 0; a < Bytes - 1; a++ ) {
SPDR = 0xff;
xmit_byte ( 0xff ); // send dummy byte
Buffer++;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
*Buffer = SPDR;
wait_till_send_done();
*Buffer = recv_byte();
}
Buffer = Buffer - ( Bytes - 1 );
//CRC-Byte auslesen
//handle CRC
#ifdef SPI_CRC
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
crc = SPDR << 8;
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
crc |= SPDR;
send_dummy_byte();
crc = recv_byte() << 8;
send_dummy_byte();
crc |= recv_byte();
if ( crc != CRC_16Bit ( Buffer, Bytes ) ) {
if ( crc != crc16 ( Buffer, Bytes ) ) {
MMC_Disable();
return ( 1 );
}
#else
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
SPDR;
SPDR = 0xff;
while ( ! ( SPSR & ( 1 << SPIF ) ) );
SPDR;
send_dummy_byte();
send_dummy_byte();
#endif
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
MMC_Disable();
return ( 0 );
}
//############################################################################
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
uint8_t mmc_read_sector ( uint32_t addr, uint8_t *Buffer )
//############################################################################
{
//Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
uint8_t cmd[] = {0x51, 0x00, 0x00, 0x00, 0x00, 0xFF};
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingefügt*/
/*
* send CMD17
*/
uint8_t cmd[] = {CMD17, 0x00, 0x00, 0x00, 0x00, 0xFF};
// convert blocks to bytes
addr = addr << 9; //addr = addr * 512
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
@ -442,24 +367,221 @@ uint8_t mmc_read_sector ( uint32_t addr, uint8_t *Buffer )
}
//############################################################################
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
uint8_t mmc_read_cid ( uint8_t *Buffer )
//############################################################################
uint8_t mmc_read_multiblock ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks )
{
//Commando zum lesen des CID Registers
uint8_t cmd[] = {0x4A, 0x00, 0x00, 0x00, 0x00, 0xFF};
uint8_t resp;
uint8_t cmd[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF };
#ifdef SPI_CRC
uint16_t crc;
#endif
return mmc_read_block ( cmd, Buffer, 16 );
MMC_Enable();
#ifdef MMC_PRESET_MULTIBLOCKCOUNT
wait_till_card_ready();
/*
* send CMD55
*/
cmd[0] = CMD55;
mmc_cmd ( cmd );
/*
* send CMD23
*/
cmd[0] = CMD23;
cmd[4] = numblocks;
mmc_cmd ( cmd );
wait_till_card_ready();
#endif
// convert blocks to bytes
addr = addr << 9; //addr = addr * 512
cmd[0] = CMD18;
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
cmd[4] = ( addr & 0x000000FF );
wait_till_card_ready();
/*
* send CMD18
*/
resp = mmc_cmd ( cmd );
if ( resp > 1 ) {
MMC_Disable();
return ( 1 );
}
//############################################################################
//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
uint8_t mmc_read_csd ( uint8_t *Buffer )
//############################################################################
{
//Commando zum lesen des CSD Registers
uint8_t cmd[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
return mmc_read_block ( cmd, Buffer, 16 );
for ( uint8_t n = numblocks; n > 0; n-- ) {
// wait for startbyte
while ( 1 ) {
send_dummy_byte();
if ( recv_byte() == SB_START )
break;
}
send_dummy_byte();
*Buffer = recv_byte();
// receive the block
for ( uint16_t a = 0; a < 512 - 1; a++ ) {
xmit_byte ( 0xff );
Buffer++;
wait_till_send_done();
*Buffer = recv_byte();
}
// handle CRC
#ifdef SPI_CRC
Buffer = Buffer - ( 512 - 1 );
send_dummy_byte();
crc = recv_byte() << 8;
send_dummy_byte();
crc |= recv_byte();
if ( crc != crc16 ( Buffer, 512 ) ) {
MMC_Disable();
return ( 1 );
}
Buffer = Buffer + 512;
#else
send_dummy_byte();
send_dummy_byte();
Buffer++;
#endif
}
wait_till_card_ready();
/*
* send CMD12
*/
cmd[0] = CMD12;
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;
resp = mmc_cmd ( cmd );
/* TODO: Apacer Card I have sends 0x7f after some reads - No idea why - CRC was correct
if ( resp > 1 ) {
MMC_Disable();
return ( 2 );
}
*/
// Pad 8
send_dummy_byte();
MMC_Disable()
return ( 0 );
}
uint8_t mmc_write_multiblock ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks )
{
uint8_t resp;
uint8_t cmd[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF };
#ifdef SPI_CRC
uint16_t crc;
uint8_t crcl, crch;
#endif
MMC_Enable();
#ifdef MMC_PRESET_MULTIBLOCKCOUNT
wait_till_card_ready();
/*
* send CMD55
*/
cmd[0] = CMD55;
mmc_cmd ( cmd );
/*
* send CMD23
*/
cmd[0] = CMD23;
cmd[4] = numblocks;
mmc_cmd ( cmd );
wait_till_card_ready();
#endif
// convert blocks to bytes
addr = addr << 9;
cmd[0] = CMD25;
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
cmd[4] = 0;
/*
* send CMD25
*/
resp = mmc_cmd ( cmd );
if ( resp > 1 ) {
MMC_Disable();
return ( 1 );
}
for ( uint8_t n = numblocks; n > 0; n-- ) {
#ifdef SPI_CRC
crc = crc16 ( Buffer, 512 );
crch = crc >> 8;
crcl = crc & 0xff;
#endif
wait_till_card_ready();
// Send multi-block start-token
xmit_byte ( MB_START );
//actually transfer the data
for ( uint16_t i = 512; i; i-- ) {
uint8_t data = *Buffer;
Buffer++;
wait_till_send_done();
xmit_byte ( data );
}
wait_till_send_done();
// handle CRC
#ifdef SPI_CRC
xmit_byte ( crch );
wait_till_send_done();
xmit_byte ( crcl );
#else
xmit_byte ( 0xff );
wait_till_send_done();
xmit_byte ( 0xff );
#endif
#ifdef MMC_PRESET_MULTIBLOCKCOUNT
// Pad 8
send_dummy_byte();
#else
wait_till_send_done();
#endif
// Get response
send_dummy_byte();
resp = recv_byte();
if ( ( resp & 0x0E ) != 4 ) {
MMC_Disable();
return ( 2 );
}
}
wait_till_card_ready();
// Send "transfer stop byte"
xmit_byte ( MB_STOP );
wait_till_send_done();
// Pad 8
send_dummy_byte();
wait_till_card_ready();
MMC_Disable();
return ( 0 );
}

View File

@ -1,50 +1,23 @@
/*#######################################################################################
Connect ARM to MMC/SD
/*
* P8000 WDC Emulator
*
* $Id: wdc_drv_mmc.h,v 1.3 2012/06/05 18:21:48 olivleh1 Exp $
*
*/
Copyright (C) 2004 Ulrich Radig
#######################################################################################*/
#ifndef MMC_H_
#define MMC_H_
#ifndef _MMC_H_
#define _MMC_H_
extern uint8_t mmc_init ();
#include <avr/io.h>
extern uint8_t mmc_read_sector ( uint32_t addr, uint8_t *Buffer );
extern uint8_t mmc_write_sector ( uint32_t addr, uint8_t *Buffer );
#define SPI_Mode 1 //1 = Hardware SPI | 0 = Software SPI
//#define SPI_Mode 0
#define SPI_CRC 1
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_Read PINB
#define MMC_Direction_REG DDRB
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
//Prototypes
extern uint8_t mmc_read_byte ( void );
extern void mmc_write_byte ( uint8_t );
extern uint8_t mmc_read_block ( uint8_t *, uint8_t *, uint16_t );
extern uint8_t mmc_init ( void );
extern uint8_t mmc_read_sector ( uint32_t, uint8_t * );
extern uint8_t mmc_write_sector ( uint32_t, uint8_t * );
extern uint8_t mmc_write_command ( uint8_t * );
extern uint8_t mmc_read_csd ( uint8_t * );
extern uint8_t mmc_read_cid ( uint8_t * );
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
#define MMC_Disable() MMC_Write|= (1<<MMC_Chip_Select);
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
#define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif //_MMC_H_
extern uint8_t mmc_read_multiblock ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks );
extern uint8_t mmc_write_multiblock_predef ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks );
extern uint8_t mmc_write_multiblock ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks );
#endif /* MMC_H_ */

View File

@ -1,10 +1,11 @@
/*
* P8000 WDC Emulator
*
* $Id: wdc_if_disk.c,v 1.4 2012/06/03 13:38:03 olivleh1 Exp $
* $Id: wdc_if_disk.c,v 1.5 2012/06/05 18:21:48 olivleh1 Exp $
*
*/
#include <stdint.h>
#include "mmc.h"
#include "uart.h"
extern uint8_t par_table[200];
@ -36,14 +37,14 @@ uint32_t wdc_p8kblock2sdblock ( uint32_t blockno )
return ( blockno + ( par_table[25] * par_table[26] ) );
}
uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector )
uint8_t wdc_write_sector ( uint32_t addr, uint8_t *sector )
{
uint8_t errorcode;
errorcode = mmc_write_sector ( addr, sector );
if ( errorcode ) {
uart_puts_p ( PSTR ( " write error at address: " ) );
uart_putw_dec ( addr );
uart_putdw_dec ( addr );
uart_puts_p ( PSTR ( " / errorcode is: " ) );
uart_putc_hex ( errorcode );
uart_putc ( '\n' );
@ -52,14 +53,47 @@ uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector )
return 0;
}
uint8_t wdc_read_sector ( uint16_t addr, uint8_t *sector )
uint8_t wdc_read_sector ( uint32_t addr, uint8_t *sector )
{
uint8_t errorcode;
errorcode = mmc_read_sector ( addr, sector );
if ( errorcode ) {
uart_puts_p ( PSTR ( " read error at address: " ) );
uart_putw_dec ( addr );
uart_putdw_dec ( addr );
uart_puts_p ( PSTR ( " / errorcode is: " ) );
uart_putc_hex ( errorcode );
uart_putc ( '\n' );
return errorcode;
} else
return 0;
}
uint8_t wdc_read_multiblock ( uint32_t addr, uint8_t *sector, uint8_t numblocks )
{
uint8_t errorcode;
errorcode = mmc_read_multiblock ( addr, sector, numblocks );
if ( errorcode ) {
uart_puts_p ( PSTR ( " read error at address: " ) );
uart_putdw_dec ( addr );
uart_puts_p ( PSTR ( " / errorcode is: " ) );
uart_putc_hex ( errorcode );
uart_putc ( '\n' );
return errorcode;
} else
return 0;
}
uint8_t wdc_write_multiblock ( uint32_t addr, uint8_t *sector, uint8_t numblocks )
{
uint8_t errorcode;
errorcode = mmc_write_multiblock ( addr, sector, numblocks );
// errorcode = mmc_write_multiblock_predef ( addr, sector, numblocks );
if ( errorcode ) {
uart_puts_p ( PSTR ( " write error at address: " ) );
uart_putdw_dec ( addr );
uart_puts_p ( PSTR ( " / errorcode is: " ) );
uart_putc_hex ( errorcode );
uart_putc ( '\n' );

View File

@ -1,17 +1,18 @@
/*
* P8000 WDC Emulator
*
* $Id: wdc_if_disk.h,v 1.3 2012/06/02 23:04:30 olivleh1 Exp $
* $Id: wdc_if_disk.h,v 1.4 2012/06/05 18:21:48 olivleh1 Exp $
*
*/
#ifndef WDC_IF_SDCARD_H_
#define WDC_IF_SDCARD_H_
uint8_t wdc_init_sdcard();
uint32_t wdc_sector2sdblock ( uint16_t req_cylinder, uint8_t req_head, uint8_t req_sector );
uint32_t wdc_p8kblock2sdblock ( uint32_t blockno );
uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector );
uint8_t wdc_read_sector ( uint16_t addr, uint8_t *sector );
extern uint8_t wdc_init_sdcard();
extern uint32_t wdc_sector2sdblock ( uint16_t req_cylinder, uint8_t req_head, uint8_t req_sector );
extern uint32_t wdc_p8kblock2sdblock ( uint32_t blockno );
extern uint8_t wdc_write_sector ( uint32_t addr, uint8_t *sector );
extern uint8_t wdc_read_sector ( uint32_t addr, uint8_t *sector );
extern uint8_t wdc_read_multiblock ( uint32_t addr, uint8_t *sector, uint8_t numblocks );
extern uint8_t wdc_write_multiblock ( uint32_t addr, uint8_t *sector, uint8_t numblocks );
#endif /* WDC_IF_SDCARD_H_ */

View File

@ -1,7 +1,7 @@
/*
* P8000 WDC Emulator
*
* $Id: wdc_if_p8000.h,v 1.4 2012/06/03 13:38:03 olivleh1 Exp $
* $Id: wdc_if_p8000.h,v 1.5 2012/06/05 18:21:48 olivleh1 Exp $
*
*/
@ -43,11 +43,11 @@
#define INFO_STAT_ERROR ((1 << PIN_INFO_STATUS0) | (1 << PIN_INFO_STATUS1) | (1 << PIN_INFO_STATUS2)) /* 0x07 */
#define INFO_TR (1 << PIN_INFO_TR) /* 0x40 */
void wdc_init_ports();
void wdc_wait_for_reset();
void wdc_receive_cmd ( uint8_t *buffer, uint16_t count );
void wdc_receive_data ( uint8_t *buffer, uint16_t count );
void wdc_send_data ( uint8_t *buffer, uint16_t count );
void wdc_send_error();
extern void wdc_init_ports();
extern void wdc_wait_for_reset();
extern void wdc_receive_cmd ( uint8_t *buffer, uint16_t count );
extern void wdc_receive_data ( uint8_t *buffer, uint16_t count );
extern void wdc_send_data ( uint8_t *buffer, uint16_t count );
extern void wdc_send_error();
#endif /* WDC_IF_PIO_H_ */

View File

@ -1,7 +1,7 @@
/*
* P8000 WDC Emulator
*
* $Id: wdc_main.c,v 1.9 2012/06/03 13:51:43 olivleh1 Exp $
* $Id: wdc_main.c,v 1.10 2012/06/05 18:21:48 olivleh1 Exp $
*
* TODO: - Different Errorcodes in the MMC layer (use defines)
* - errorchecking in several places
@ -44,6 +44,7 @@ ISR ( TIMER0_OVF_vect )
int __attribute__ ( ( OS_main ) )
main ( void )
{
#ifndef MEASURE_SDCARD_TIME
uint16_t cmd_counter = 9;
uint16_t data_counter;
uint32_t blockno;
@ -52,14 +53,14 @@ main ( void )
uint8_t cmd_buffer[9];
uint8_t i8;
uint16_t i16;
#endif
atmega_setup();
uart_puts_p ( PSTR ( "P8000 WDC Emulator 0.01\n" ) );
#ifdef MEASURE_SDCARD_TIME
measure_performance();
#endif
#else
/* load Parameter Table into RAM if valid */
blockno = 0;
@ -84,9 +85,12 @@ main ( void )
, cmd_counter
);
#if DEBUG == 2
#if DEBUG >= 2
#if DEBUG >= 3
uart_puts_p ( PSTR ( " CMD:" ) );
#endif
uart_putc_hex ( cmd_buffer[0] );
#if DEBUG >= 3
uart_putc_hex ( cmd_buffer[1] );
uart_putc_hex ( cmd_buffer[2] );
uart_putc_hex ( cmd_buffer[3] );
@ -96,6 +100,7 @@ main ( void )
uart_putc_hex ( cmd_buffer[7] );
uart_putc_hex ( cmd_buffer[8] );
uart_putc ( '\n' );
#endif
#endif
switch ( cmd_buffer[0] ) {
@ -107,11 +112,19 @@ main ( void )
, data_counter
);
errorcode = 1;
if(data_counter/512 == 1) {
errorcode = wdc_write_sector ( blockno, data_buffer);
} else {
uart_putc('#');
errorcode = wdc_write_multiblock( blockno, data_buffer, data_counter/512);
}
/* check if this really works - this must be used if the card does not support multiblock-access (there are some)
for ( i16 = 0; i16 < data_counter; i16 += 512 ) {
errorcode = wdc_write_sector ( blockno, &data_buffer[i16] );
if ( errorcode ) break;
blockno++;
}
*/
if ( errorcode )
wdc_send_error();
break;
@ -120,12 +133,21 @@ main ( void )
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
blockno = wdc_p8kblock2sdblock ( ( ( uint32_t ) cmd_buffer[5] << 24 ) | ( ( uint32_t ) cmd_buffer[4] << 16 ) | ( ( uint16_t ) cmd_buffer[3] << 8 ) | cmd_buffer[2] );
errorcode = 1;
if(data_counter/512 == 1) {
errorcode = wdc_read_sector ( blockno, data_buffer);
} else {
uart_putc('#');
errorcode = wdc_read_multiblock( blockno, data_buffer, data_counter/512);
}
/* check if this really works - this must be used if the card does not support multiblock-access (there are some)
for ( i16 = 0; i16 < data_counter; i16 += 512 ) {
errorcode = wdc_read_sector ( blockno, &data_buffer[i16] );
if ( errorcode ) break;
blockno++;
}
*/
if ( errorcode )
wdc_send_error();
wdc_send_data ( data_buffer
@ -311,7 +333,7 @@ main ( void )
break;
}
}
#endif
return 0;
}
@ -332,38 +354,85 @@ void atmega_setup ( void )
void measure_performance()
{
uint32_t starttime;
uint8_t *data_buffer;
uint32_t blockno;
uint8_t data_buffer[4096];
uint32_t blockno=0;
uint8_t numblocks=4;
uint8_t i8, errorcode;
uint8_t nr_of_tests=5;
#define BLOCKNO 300000
sei();
TIMSK0 |= ( 0x01 << TOIE0 );
TCCR0B = ( 1 << CS01 ); // Prescaler 8
TCNT0 = 0x00;
uart_putdw_dec ( overflow );
data_buffer = malloc ( 512 * sizeof ( *data_buffer ) );
uart_putc ( 'w' );
uart_putc ( '\n' );
for ( i8 = 0; i8 < 5; i8++ ) {
for ( blockno = 200000, starttime = overflow; blockno < 205000; blockno++ ) {
errorcode = wdc_write_sector ( blockno, data_buffer );
uart_puts_p ( PSTR ( "Performance Measurement. Displayed are the Timer-Overflows." ) );uart_putc ( '\n' );
uart_puts_p ( PSTR ( "Timer is initialized with a Prescaler 8" ) );uart_putc ( '\n' );
uart_puts_p ( PSTR ( "Test Read 5000 512B-Blocks with Multiblock-Read (4KB Blocksize):" ) );uart_putc ( '\n' );
for ( i8 = 0; i8 < nr_of_tests; i8++ ) {
blockno=BLOCKNO;
for ( starttime = overflow; blockno < (BLOCKNO+5000); blockno+=numblocks ) {
errorcode = wdc_read_multiblock ( blockno, data_buffer,numblocks );
if(errorcode) {
break;
}
}
if(errorcode)
break;
uart_putdw_dec ( overflow - starttime );
uart_putc ( '\n' );
}
uart_putc ( '\n' );
uart_putc ( 'r' );
uart_puts_p ( PSTR ( "Test Write 5000 512B-Blocks with Multiblock-Write (4KB Blocksize):" ) );uart_putc ( '\n' );
memset ( &data_buffer[0], 0xCC, 512*numblocks );
for ( i8 = 0; i8 < nr_of_tests; i8++ ) {
blockno=BLOCKNO;
for ( starttime = overflow; blockno < (BLOCKNO+5000); blockno+=numblocks ) {
errorcode = wdc_write_multiblock ( blockno, data_buffer,numblocks );
if(errorcode) {
break;
}
}
if(errorcode)
break;
uart_putdw_dec ( overflow - starttime );
uart_putc ( '\n' );
for ( i8 = 0; i8 < 5; i8++ ) {
for ( blockno = 200000, starttime = overflow; blockno < 205000; blockno++ ) {
}
uart_puts_p ( PSTR ( "Test Read 5000 512B-Blocks with Singleblock-Read (512B Blocksize):" ) );uart_putc ( '\n' );
for ( i8 = 0; i8 < nr_of_tests; i8++ ) {
blockno=BLOCKNO;
for ( starttime = overflow; blockno < (BLOCKNO+5000); blockno++ ) {
errorcode = wdc_read_sector ( blockno, data_buffer );
if(errorcode) {
break;
}
}
if(errorcode)
break;
uart_putdw_dec ( overflow - starttime );
uart_putc ( '\n' );
}
uart_putc ( '\n' );
free ( data_buffer );
uart_puts_p ( PSTR ( "Test Write 5000 512B-Blocks with Singleblock-Write (512B Blocksize):" ) );uart_putc ( '\n' );
memset ( &data_buffer[0], 0xCC, 512*numblocks );
for ( i8 = 0; i8 < nr_of_tests; i8++ ) {
blockno=BLOCKNO;
for ( starttime = overflow; blockno < (BLOCKNO+5000); blockno++ ) {
errorcode = wdc_write_sector ( blockno, data_buffer );
if(errorcode) {
break;
}
}
if(errorcode)
break;
uart_putdw_dec ( overflow - starttime );
uart_putc ( '\n' );
}
while(1);
}
#endif