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:
parent
ff85359a85
commit
22fbb4f11c
Binary file not shown.
|
|
@ -110,7 +110,7 @@ OUTPUT_FILE_DEP:= ./makedep.mk
|
||||||
./%.o: .././%.c
|
./%.o: .././%.c
|
||||||
@echo Building file: $<
|
@echo Building file: $<
|
||||||
@echo Invoking: AVR/GNU C Compiler : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
|
@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: $<
|
@echo Finished building: $<
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ all: $(OUTPUT_FILE_PATH) $(ADDITIONAL_DEPENDENCIES)
|
||||||
$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP)
|
$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP)
|
||||||
@echo Building target: $@
|
@echo Building target: $@
|
||||||
@echo Invoking: AVR/GNU Linker : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
|
@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: $@
|
@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" -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
|
"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
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||||
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||||
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
|
<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.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
||||||
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
||||||
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
<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.WarningsAsErrors>True</avrgcc.compiler.warnings.WarningsAsErrors>
|
||||||
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
|
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
|
||||||
<avrgcc.compiler.warnings.PedanticWarningsAsErrors>True</avrgcc.compiler.warnings.PedanticWarningsAsErrors>
|
<avrgcc.compiler.warnings.PedanticWarningsAsErrors>True</avrgcc.compiler.warnings.PedanticWarningsAsErrors>
|
||||||
|
<avrgcc.compiler.miscellaneous.DoNotDeleteTemporaryFiles>True</avrgcc.compiler.miscellaneous.DoNotDeleteTemporaryFiles>
|
||||||
<avrgcc.linker.libraries.Libraries>
|
<avrgcc.linker.libraries.Libraries>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>m</Value>
|
<Value>m</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcc.linker.libraries.Libraries>
|
</avrgcc.linker.libraries.Libraries>
|
||||||
|
<avrgcc.linker.optimization.GarbageCollectUnusedSections>True</avrgcc.linker.optimization.GarbageCollectUnusedSections>
|
||||||
|
<avrgcc.linker.optimization.RelaxBranches>True</avrgcc.linker.optimization.RelaxBranches>
|
||||||
</AvrGcc>
|
</AvrGcc>
|
||||||
</ToolchainSettings>
|
</ToolchainSettings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -82,6 +86,9 @@
|
||||||
<Compile Include="mmc.h">
|
<Compile Include="mmc.h">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="sd.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="uart.c">
|
<Compile Include="uart.c">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* P8000 WDC Emulator
|
* 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
|
#define F_CPU 18432000UL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* P8000 Interface
|
||||||
|
*/
|
||||||
|
|
||||||
#define PORT_DATA PORTA
|
#define PORT_DATA PORTA
|
||||||
#define PIN_DATA PINA
|
#define PIN_DATA PINA
|
||||||
#define DDR_DATA DDRA
|
#define DDR_DATA DDRA
|
||||||
|
|
@ -28,4 +32,20 @@
|
||||||
#define PIN_INFO_TR PINC6
|
#define PIN_INFO_TR PINC6
|
||||||
#define PIN_INFO_RST PINC7
|
#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_ */
|
#endif /* CONFIG_H_ */
|
||||||
|
|
@ -1,34 +1,43 @@
|
||||||
/*#######################################################################################
|
/*
|
||||||
Connect AVR to MMC/SD
|
* P8000 WDC Emulator
|
||||||
|
*
|
||||||
Copyright (C) 2004 Ulrich Radig
|
* $Id: wdc_drv_mmc.c,v 1.4 2012/06/05 18:21:48 olivleh1 Exp $
|
||||||
|
*
|
||||||
Bei Fragen und Verbesserungen wendet euch per EMail an
|
*/
|
||||||
|
|
||||||
mail@ulrichradig.de
|
|
||||||
|
|
||||||
oder im Forum meiner Web Page : www.ulrichradig.de
|
|
||||||
|
|
||||||
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
|
|
||||||
GNU General Public License, wie von der Free Software Foundation veröffentlicht,
|
|
||||||
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
|
|
||||||
(nach Ihrer Option) jeder späteren Version.
|
|
||||||
|
|
||||||
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
|
|
||||||
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
|
||||||
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
|
||||||
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
|
||||||
|
|
||||||
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
|
||||||
Programm erhalten haben.
|
|
||||||
Falls nicht, schreiben Sie an die Free Software Foundation,
|
|
||||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
#######################################################################################*/
|
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "config.h"
|
||||||
#include "mmc.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
|
#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,
|
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
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
|
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CRC7_POLY 0x09
|
const uint8_t crc7_table[256] = {
|
||||||
unsigned char CRC_7Bit ( unsigned char *pData, unsigned int uiLen )
|
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 )
|
||||||
{
|
{
|
||||||
|
uint8_t crc = 0x00;
|
||||||
unsigned int i, c, bit;
|
while ( len-- )
|
||||||
unsigned int crc = 0;
|
crc = crc7_table[ ( crc << 1 ) ^ *buffer++];
|
||||||
|
return crc;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( i = 0; i < 7; i++ ) {
|
|
||||||
|
|
||||||
if ( crc & 0x40 ) {
|
|
||||||
crc = ( crc << 1 ) ^ CRC7_POLY;
|
|
||||||
} else
|
|
||||||
crc <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ( crc & 0x7F );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t crc16 ( const uint8_t *buffer, uint16_t len )
|
||||||
unsigned short CRC_16Bit ( unsigned char *pData, unsigned int uiLen )
|
|
||||||
{
|
{
|
||||||
unsigned short usCRC;
|
uint16_t crc = 0x0000;
|
||||||
|
while ( len-- ) {
|
||||||
//Init CRC register to zero (Required by SD card)
|
crc = ( crc << 8 ) ^ crc16_table[ ( crc >> 8 ) ^ *buffer++];
|
||||||
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++];
|
|
||||||
}
|
}
|
||||||
|
return crc;
|
||||||
return usCRC;
|
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
//last bit enables or disables CRC mode
|
||||||
//tail bit of uiCRC sets or clears CRC mode
|
cmd[4] = on_off & 0x01;
|
||||||
ucSDSetCRC[4] = uiCRC & 0x01;
|
|
||||||
|
|
||||||
if ( mmc_write_command ( ucSDSetCRC ) != 0 ) {
|
if ( mmc_cmd ( cmd ) != 0 ) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//############################################################################
|
|
||||||
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
|
|
||||||
uint8_t mmc_init ()
|
uint8_t mmc_init ()
|
||||||
//############################################################################
|
|
||||||
{
|
{
|
||||||
uint8_t Timeout = 0;
|
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
|
DDR_MMC &= ~ ( 1 << PIN_MMC_MISO );
|
||||||
MMC_Direction_REG |= ( 1 << SPI_Clock ); //Setzen von Pin MMC_Clock auf Output
|
DDR_MMC |= ( 1 << PIN_MMC_SCK );
|
||||||
MMC_Direction_REG |= ( 1 << SPI_DO ); //Setzen von Pin MMC_DO auf Output
|
DDR_MMC |= ( 1 << PIN_MMC_MOSI );
|
||||||
MMC_Direction_REG |= ( 1 << MMC_Chip_Select ); //Setzen von Pin MMC_Chip_Select auf Output
|
DDR_MMC |= ( 1 << PIN_MMC_CS );
|
||||||
MMC_Write |= ( 1 << MMC_Chip_Select ); //Setzt den Pin MMC_Chip_Select auf High Pegel
|
|
||||||
|
MMC_Enable();
|
||||||
|
|
||||||
for ( uint8_t a = 0; a < 200; a++ ) {
|
for ( uint8_t a = 0; a < 200; a++ ) {
|
||||||
nop();
|
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
|
SPCR = ( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR0 ) | ( 1 << SPR1 ); //Enable SPI, SPI in Master Mode
|
||||||
SPSR = ( 0 << SPI2X );
|
SPSR = ( 0 << SPI2X );
|
||||||
#endif
|
|
||||||
|
|
||||||
//Initialisiere MMC/SD-Karte in den SPI-Mode
|
for ( uint8_t b = 0; b < 0x0f; b++ ) {
|
||||||
for ( uint8_t b = 0; b < 0x0f; b++ ) { //Sendet min 74+ Clocks an die MMC/SD-Karte
|
send_dummy_byte();
|
||||||
mmc_write_byte ( 0xff );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sendet Commando CMD0 an MMC/SD-Karte
|
/*
|
||||||
uint8_t CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
|
* send CMD0
|
||||||
while ( mmc_write_command ( CMD ) != 1 ) {
|
*/
|
||||||
|
uint8_t cmd[] = {CMD0, 0x00, 0x00, 0x00, 0x00, 0x95};
|
||||||
|
while ( mmc_cmd ( cmd ) != 1 ) {
|
||||||
if ( Timeout++ > 200 ) {
|
if ( Timeout++ > 200 ) {
|
||||||
MMC_Disable();
|
MMC_Disable();
|
||||||
return ( 1 ); //Abbruch bei Commando1 (Return Code1)
|
return ( 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Sendet Commando CMD1 an MMC/SD-Karte
|
|
||||||
|
/*
|
||||||
|
* send CMD1
|
||||||
|
*/
|
||||||
Timeout = 0;
|
Timeout = 0;
|
||||||
CMD[0] = 0x41;//Commando 1
|
cmd[0] = CMD1;
|
||||||
CMD[5] = 0xFF;
|
cmd[5] = 0xFF;
|
||||||
while ( mmc_write_command ( CMD ) != 0 ) {
|
while ( mmc_cmd ( cmd ) != 0 ) {
|
||||||
if ( Timeout++ > 400 ) {
|
if ( Timeout++ > 400 ) {
|
||||||
MMC_Disable();
|
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 ) );
|
SPCR &= ~ ( ( 1 << SPR0 ) | ( 1 << SPR1 ) );
|
||||||
SPSR = SPSR | ( 1 << SPI2X );
|
SPSR = SPSR | ( 1 << SPI2X );
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
SDSetCRC ( 1 );
|
SDSetCRC ( 1 );
|
||||||
#else
|
|
||||||
SDSetCRC ( 0 );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
|
||||||
MMC_Disable();
|
MMC_Disable();
|
||||||
return ( 0 );
|
return ( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//############################################################################
|
uint8_t mmc_cmd ( uint8_t *cmd )
|
||||||
//Sendet ein Commando an die MMC/SD-Karte
|
|
||||||
uint8_t mmc_write_command ( uint8_t *cmd )
|
|
||||||
//############################################################################
|
|
||||||
{
|
{
|
||||||
uint8_t tmp = 0xff;
|
uint8_t tmp = 0x80;
|
||||||
uint8_t Timeout = 0;
|
uint8_t i = 10;
|
||||||
|
uint8_t cmd0 = cmd[0];
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
unsigned char ucCRC;
|
|
||||||
|
|
||||||
//Calculate CRC and framing bits
|
//Calculate CRC and framing bits
|
||||||
cmd [0] = ( cmd[0] | ( 1 << 6 ) ) & 0x7F;
|
cmd[0] = ( cmd[0] | ( 1 << 6 ) ) & 0x7F;
|
||||||
ucCRC = CRC_7Bit ( cmd, 5 ) << 1;
|
cmd[5] = crc7 ( cmd, 5 ) << 1;
|
||||||
cmd[5] = ucCRC;
|
|
||||||
#endif
|
#endif
|
||||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
|
||||||
MMC_Disable();
|
|
||||||
|
|
||||||
//sendet 8 Clock Impulse
|
// send command
|
||||||
mmc_write_byte ( 0xFF );
|
for ( uint8_t a = 0; a < 0x06; a++ ) {
|
||||||
|
xmit_byte ( *cmd++ );
|
||||||
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
|
wait_till_send_done();
|
||||||
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++ );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wartet auf ein gültige Antwort von der MMC/SD-Karte
|
if ( cmd0 == ( CMD12 ) ) recv_byte();
|
||||||
while ( tmp == 0xff ) {
|
|
||||||
tmp = mmc_read_byte();
|
do {
|
||||||
if ( Timeout++ > 500 ) {
|
send_dummy_byte();
|
||||||
break; //Abbruch da die MMC/SD-Karte nicht Antwortet
|
tmp = recv_byte();
|
||||||
}
|
} while ( ( tmp & 0x80 ) && --i );
|
||||||
}
|
|
||||||
return ( tmp );
|
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 mmc_write_sector ( uint32_t addr, uint8_t *Buffer )
|
||||||
//############################################################################
|
|
||||||
{
|
{
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
|
uint8_t cmd[] = {CMD24, 0x00, 0x00, 0x00, 0x00, 0xFF};
|
||||||
uint8_t cmd[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
|
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
unsigned int uiCheckSum;
|
uint16_t crc;
|
||||||
|
uint8_t crcl, crch;
|
||||||
#endif
|
#endif
|
||||||
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
|
||||||
addr wird von Blocks zu Bytes umgerechnet danach werden
|
MMC_Enable();
|
||||||
diese in das Commando eingefügt*/
|
|
||||||
|
// convert blocks to bytes
|
||||||
addr = addr << 9; //addr = addr * 512
|
addr = addr << 9; //addr = addr * 512
|
||||||
|
|
||||||
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
|
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
|
||||||
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
|
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
|
||||||
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
|
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 ) {
|
if ( tmp != 0 ) {
|
||||||
|
MMC_Disable();
|
||||||
return ( tmp );
|
return ( tmp );
|
||||||
}
|
}
|
||||||
|
|
||||||
SPDR = 0xFE; //Sendet Startbyte
|
//send Startbyte
|
||||||
|
xmit_byte ( SB_START );
|
||||||
|
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
uiCheckSum = CRC_16Bit ( Buffer, 512 );
|
crc = crc16 ( Buffer, 512 );
|
||||||
|
crch = crc >> 8;
|
||||||
|
crcl = crc & 0xff;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
|
//write a single block
|
||||||
for ( uint16_t a = 0; a < 512; a++ ) {
|
for ( uint16_t a = 0; a < 512; a++ ) {
|
||||||
uint8_t data = *Buffer;
|
uint8_t data = *Buffer;
|
||||||
Buffer++;
|
Buffer++;
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
wait_till_send_done();
|
||||||
SPDR = data; //Sendet ein Byte
|
xmit_byte ( data );
|
||||||
}
|
}
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
wait_till_send_done();
|
||||||
|
|
||||||
//CRC-Byte schreiben
|
//handle CRC
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
SPDR = uiCheckSum >> 8;
|
xmit_byte ( crch );
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
wait_till_send_done();
|
||||||
SPDR = uiCheckSum & 0xFF;
|
xmit_byte ( crcl );
|
||||||
|
wait_till_send_done();
|
||||||
#else
|
#else
|
||||||
SPDR = 0xFF;
|
send_dummy_byte();
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
send_dummy_byte();
|
||||||
SPDR = 0xFF;
|
|
||||||
#endif
|
#endif
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
|
||||||
|
|
||||||
//Fehler beim schreiben? (Data Response XXX00101 = OK)
|
//check for errors
|
||||||
SPDR = 0xff;
|
send_dummy_byte();
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
|
if ( ( recv_byte() & 0x1F ) != 0x05 ) {
|
||||||
if ( ( SPDR & 0x1F ) != 0x05 ) return ( 0x02 );
|
MMC_Disable();
|
||||||
|
return ( 2 );
|
||||||
//Wartet auf MMC/SD-Karte Bussy
|
|
||||||
while ( 1 ) {
|
|
||||||
SPDR = 0xff;
|
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
|
|
||||||
if ( SPDR == 0xff )
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
wait_till_card_ready();
|
||||||
|
|
||||||
MMC_Disable();
|
MMC_Disable();
|
||||||
|
|
||||||
return ( 0 );
|
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 )
|
uint8_t mmc_read_block ( uint8_t *cmd, uint8_t *Buffer, uint16_t Bytes )
|
||||||
//############################################################################
|
|
||||||
{
|
{
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
#endif
|
#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 );
|
return ( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
|
//wait for startbyte
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
SPDR = 0xff;
|
send_dummy_byte();
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
|
if ( recv_byte() == SB_START )
|
||||||
if ( SPDR == 0xfe )
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPDR = 0xff;
|
//read first byte
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
send_dummy_byte();
|
||||||
*Buffer = SPDR;
|
*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++ ) {
|
for ( uint16_t a = 0; a < Bytes - 1; a++ ) {
|
||||||
SPDR = 0xff;
|
xmit_byte ( 0xff ); // send dummy byte
|
||||||
Buffer++;
|
Buffer++;
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
wait_till_send_done();
|
||||||
*Buffer = SPDR;
|
*Buffer = recv_byte();
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer = Buffer - ( Bytes - 1 );
|
Buffer = Buffer - ( Bytes - 1 );
|
||||||
|
|
||||||
//CRC-Byte auslesen
|
//handle CRC
|
||||||
#ifdef SPI_CRC
|
#ifdef SPI_CRC
|
||||||
SPDR = 0xff;
|
send_dummy_byte();
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
crc = recv_byte() << 8;
|
||||||
crc = SPDR << 8;
|
send_dummy_byte();
|
||||||
SPDR = 0xff;
|
crc |= recv_byte();
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
|
||||||
crc |= SPDR;
|
|
||||||
|
|
||||||
if ( crc != CRC_16Bit ( Buffer, Bytes ) ) {
|
if ( crc != crc16 ( Buffer, Bytes ) ) {
|
||||||
MMC_Disable();
|
MMC_Disable();
|
||||||
return ( 1 );
|
return ( 1 );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
SPDR = 0xff;
|
send_dummy_byte();
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
send_dummy_byte();
|
||||||
SPDR;
|
|
||||||
SPDR = 0xff;
|
|
||||||
while ( ! ( SPSR & ( 1 << SPIF ) ) );
|
|
||||||
SPDR;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
|
||||||
MMC_Disable();
|
MMC_Disable();
|
||||||
|
|
||||||
return ( 0 );
|
return ( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//############################################################################
|
|
||||||
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
|
|
||||||
uint8_t mmc_read_sector ( uint32_t addr, uint8_t *Buffer )
|
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};
|
* send CMD17
|
||||||
|
*/
|
||||||
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
uint8_t cmd[] = {CMD17, 0x00, 0x00, 0x00, 0x00, 0xFF};
|
||||||
addr wird von Blocks zu Bytes umgerechnet danach werden
|
|
||||||
diese in das Commando eingefügt*/
|
|
||||||
|
|
||||||
|
// convert blocks to bytes
|
||||||
addr = addr << 9; //addr = addr * 512
|
addr = addr << 9; //addr = addr * 512
|
||||||
|
|
||||||
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
|
cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
|
||||||
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
|
cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
|
||||||
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
|
cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
|
||||||
|
|
@ -442,24 +367,221 @@ uint8_t mmc_read_sector ( uint32_t addr, uint8_t *Buffer )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//############################################################################
|
uint8_t mmc_read_multiblock ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks )
|
||||||
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
|
||||||
uint8_t mmc_read_cid ( uint8_t *Buffer )
|
|
||||||
//############################################################################
|
|
||||||
{
|
{
|
||||||
//Commando zum lesen des CID Registers
|
uint8_t resp;
|
||||||
uint8_t cmd[] = {0x4A, 0x00, 0x00, 0x00, 0x00, 0xFF};
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 )
|
||||||
//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 resp;
|
||||||
uint8_t cmd[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
|
uint8_t cmd[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF };
|
||||||
|
#ifdef SPI_CRC
|
||||||
|
uint16_t crc;
|
||||||
|
uint8_t crcl, crch;
|
||||||
|
#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;
|
||||||
|
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 );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_
|
extern uint8_t mmc_init ();
|
||||||
#define _MMC_H_
|
|
||||||
|
|
||||||
#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
|
extern uint8_t mmc_read_multiblock ( uint32_t addr, uint8_t *Buffer, uint8_t numblocks );
|
||||||
//#define SPI_Mode 0
|
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 );
|
||||||
#define SPI_CRC 1
|
|
||||||
|
|
||||||
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
|
#endif /* MMC_H_ */
|
||||||
#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_
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* P8000 WDC Emulator
|
* 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 "mmc.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
extern uint8_t par_table[200];
|
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] ) );
|
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;
|
uint8_t errorcode;
|
||||||
|
|
||||||
errorcode = mmc_write_sector ( addr, sector );
|
errorcode = mmc_write_sector ( addr, sector );
|
||||||
if ( errorcode ) {
|
if ( errorcode ) {
|
||||||
uart_puts_p ( PSTR ( " write error at address: " ) );
|
uart_puts_p ( PSTR ( " write error at address: " ) );
|
||||||
uart_putw_dec ( addr );
|
uart_putdw_dec ( addr );
|
||||||
uart_puts_p ( PSTR ( " / errorcode is: " ) );
|
uart_puts_p ( PSTR ( " / errorcode is: " ) );
|
||||||
uart_putc_hex ( errorcode );
|
uart_putc_hex ( errorcode );
|
||||||
uart_putc ( '\n' );
|
uart_putc ( '\n' );
|
||||||
|
|
@ -52,14 +53,47 @@ uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector )
|
||||||
return 0;
|
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;
|
uint8_t errorcode;
|
||||||
|
|
||||||
errorcode = mmc_read_sector ( addr, sector );
|
errorcode = mmc_read_sector ( addr, sector );
|
||||||
if ( errorcode ) {
|
if ( errorcode ) {
|
||||||
uart_puts_p ( PSTR ( " read error at address: " ) );
|
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_puts_p ( PSTR ( " / errorcode is: " ) );
|
||||||
uart_putc_hex ( errorcode );
|
uart_putc_hex ( errorcode );
|
||||||
uart_putc ( '\n' );
|
uart_putc ( '\n' );
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* P8000 WDC Emulator
|
* 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_
|
#ifndef WDC_IF_SDCARD_H_
|
||||||
#define WDC_IF_SDCARD_H_
|
#define WDC_IF_SDCARD_H_
|
||||||
|
|
||||||
uint8_t wdc_init_sdcard();
|
extern uint8_t wdc_init_sdcard();
|
||||||
uint32_t wdc_sector2sdblock ( uint16_t req_cylinder, uint8_t req_head, uint8_t req_sector );
|
extern uint32_t wdc_sector2sdblock ( uint16_t req_cylinder, uint8_t req_head, uint8_t req_sector );
|
||||||
uint32_t wdc_p8kblock2sdblock ( uint32_t blockno );
|
extern uint32_t wdc_p8kblock2sdblock ( uint32_t blockno );
|
||||||
uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector );
|
extern uint8_t wdc_write_sector ( uint32_t addr, uint8_t *sector );
|
||||||
uint8_t wdc_read_sector ( uint16_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_ */
|
#endif /* WDC_IF_SDCARD_H_ */
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* P8000 WDC Emulator
|
* 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_STAT_ERROR ((1 << PIN_INFO_STATUS0) | (1 << PIN_INFO_STATUS1) | (1 << PIN_INFO_STATUS2)) /* 0x07 */
|
||||||
#define INFO_TR (1 << PIN_INFO_TR) /* 0x40 */
|
#define INFO_TR (1 << PIN_INFO_TR) /* 0x40 */
|
||||||
|
|
||||||
void wdc_init_ports();
|
extern void wdc_init_ports();
|
||||||
void wdc_wait_for_reset();
|
extern void wdc_wait_for_reset();
|
||||||
void wdc_receive_cmd ( uint8_t *buffer, uint16_t count );
|
extern void wdc_receive_cmd ( uint8_t *buffer, uint16_t count );
|
||||||
void wdc_receive_data ( uint8_t *buffer, uint16_t count );
|
extern void wdc_receive_data ( uint8_t *buffer, uint16_t count );
|
||||||
void wdc_send_data ( uint8_t *buffer, uint16_t count );
|
extern void wdc_send_data ( uint8_t *buffer, uint16_t count );
|
||||||
void wdc_send_error();
|
extern void wdc_send_error();
|
||||||
|
|
||||||
#endif /* WDC_IF_PIO_H_ */
|
#endif /* WDC_IF_PIO_H_ */
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* P8000 WDC Emulator
|
* 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)
|
* TODO: - Different Errorcodes in the MMC layer (use defines)
|
||||||
* - errorchecking in several places
|
* - errorchecking in several places
|
||||||
|
|
@ -44,6 +44,7 @@ ISR ( TIMER0_OVF_vect )
|
||||||
int __attribute__ ( ( OS_main ) )
|
int __attribute__ ( ( OS_main ) )
|
||||||
main ( void )
|
main ( void )
|
||||||
{
|
{
|
||||||
|
#ifndef MEASURE_SDCARD_TIME
|
||||||
uint16_t cmd_counter = 9;
|
uint16_t cmd_counter = 9;
|
||||||
uint16_t data_counter;
|
uint16_t data_counter;
|
||||||
uint32_t blockno;
|
uint32_t blockno;
|
||||||
|
|
@ -52,14 +53,14 @@ main ( void )
|
||||||
uint8_t cmd_buffer[9];
|
uint8_t cmd_buffer[9];
|
||||||
uint8_t i8;
|
uint8_t i8;
|
||||||
uint16_t i16;
|
uint16_t i16;
|
||||||
|
#endif
|
||||||
atmega_setup();
|
atmega_setup();
|
||||||
|
|
||||||
uart_puts_p ( PSTR ( "P8000 WDC Emulator 0.01\n" ) );
|
uart_puts_p ( PSTR ( "P8000 WDC Emulator 0.01\n" ) );
|
||||||
|
|
||||||
#ifdef MEASURE_SDCARD_TIME
|
#ifdef MEASURE_SDCARD_TIME
|
||||||
measure_performance();
|
measure_performance();
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
/* load Parameter Table into RAM if valid */
|
/* load Parameter Table into RAM if valid */
|
||||||
blockno = 0;
|
blockno = 0;
|
||||||
|
|
@ -84,9 +85,12 @@ main ( void )
|
||||||
, cmd_counter
|
, cmd_counter
|
||||||
);
|
);
|
||||||
|
|
||||||
#if DEBUG == 2
|
#if DEBUG >= 2
|
||||||
|
#if DEBUG >= 3
|
||||||
uart_puts_p ( PSTR ( " CMD:" ) );
|
uart_puts_p ( PSTR ( " CMD:" ) );
|
||||||
|
#endif
|
||||||
uart_putc_hex ( cmd_buffer[0] );
|
uart_putc_hex ( cmd_buffer[0] );
|
||||||
|
#if DEBUG >= 3
|
||||||
uart_putc_hex ( cmd_buffer[1] );
|
uart_putc_hex ( cmd_buffer[1] );
|
||||||
uart_putc_hex ( cmd_buffer[2] );
|
uart_putc_hex ( cmd_buffer[2] );
|
||||||
uart_putc_hex ( cmd_buffer[3] );
|
uart_putc_hex ( cmd_buffer[3] );
|
||||||
|
|
@ -96,6 +100,7 @@ main ( void )
|
||||||
uart_putc_hex ( cmd_buffer[7] );
|
uart_putc_hex ( cmd_buffer[7] );
|
||||||
uart_putc_hex ( cmd_buffer[8] );
|
uart_putc_hex ( cmd_buffer[8] );
|
||||||
uart_putc ( '\n' );
|
uart_putc ( '\n' );
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch ( cmd_buffer[0] ) {
|
switch ( cmd_buffer[0] ) {
|
||||||
|
|
@ -107,11 +112,19 @@ main ( void )
|
||||||
, data_counter
|
, data_counter
|
||||||
);
|
);
|
||||||
errorcode = 1;
|
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 ) {
|
for ( i16 = 0; i16 < data_counter; i16 += 512 ) {
|
||||||
errorcode = wdc_write_sector ( blockno, &data_buffer[i16] );
|
errorcode = wdc_write_sector ( blockno, &data_buffer[i16] );
|
||||||
if ( errorcode ) break;
|
if ( errorcode ) break;
|
||||||
blockno++;
|
blockno++;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if ( errorcode )
|
if ( errorcode )
|
||||||
wdc_send_error();
|
wdc_send_error();
|
||||||
break;
|
break;
|
||||||
|
|
@ -120,12 +133,21 @@ main ( void )
|
||||||
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
|
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] );
|
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;
|
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 ) {
|
for ( i16 = 0; i16 < data_counter; i16 += 512 ) {
|
||||||
errorcode = wdc_read_sector ( blockno, &data_buffer[i16] );
|
errorcode = wdc_read_sector ( blockno, &data_buffer[i16] );
|
||||||
if ( errorcode ) break;
|
if ( errorcode ) break;
|
||||||
blockno++;
|
blockno++;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if ( errorcode )
|
if ( errorcode )
|
||||||
wdc_send_error();
|
wdc_send_error();
|
||||||
wdc_send_data ( data_buffer
|
wdc_send_data ( data_buffer
|
||||||
|
|
@ -311,7 +333,7 @@ main ( void )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,38 +354,85 @@ void atmega_setup ( void )
|
||||||
void measure_performance()
|
void measure_performance()
|
||||||
{
|
{
|
||||||
uint32_t starttime;
|
uint32_t starttime;
|
||||||
uint8_t *data_buffer;
|
uint8_t data_buffer[4096];
|
||||||
uint32_t blockno;
|
uint32_t blockno=0;
|
||||||
|
uint8_t numblocks=4;
|
||||||
|
uint8_t i8, errorcode;
|
||||||
|
uint8_t nr_of_tests=5;
|
||||||
|
|
||||||
|
#define BLOCKNO 300000
|
||||||
sei();
|
sei();
|
||||||
TIMSK0 |= ( 0x01 << TOIE0 );
|
TIMSK0 |= ( 0x01 << TOIE0 );
|
||||||
TCCR0B = ( 1 << CS01 ); // Prescaler 8
|
TCCR0B = ( 1 << CS01 ); // Prescaler 8
|
||||||
TCNT0 = 0x00;
|
TCNT0 = 0x00;
|
||||||
|
|
||||||
uart_putdw_dec ( overflow );
|
uart_puts_p ( PSTR ( "Performance Measurement. Displayed are the Timer-Overflows." ) );uart_putc ( '\n' );
|
||||||
data_buffer = malloc ( 512 * sizeof ( *data_buffer ) );
|
uart_puts_p ( PSTR ( "Timer is initialized with a Prescaler 8" ) );uart_putc ( '\n' );
|
||||||
uart_putc ( 'w' );
|
|
||||||
uart_putc ( '\n' );
|
uart_puts_p ( PSTR ( "Test Read 5000 512B-Blocks with Multiblock-Read (4KB Blocksize):" ) );uart_putc ( '\n' );
|
||||||
for ( i8 = 0; i8 < 5; i8++ ) {
|
|
||||||
for ( blockno = 200000, starttime = overflow; blockno < 205000; blockno++ ) {
|
for ( i8 = 0; i8 < nr_of_tests; i8++ ) {
|
||||||
errorcode = wdc_write_sector ( blockno, data_buffer );
|
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_putdw_dec ( overflow - starttime );
|
||||||
uart_putc ( '\n' );
|
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' );
|
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 );
|
errorcode = wdc_read_sector ( blockno, data_buffer );
|
||||||
|
if(errorcode) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(errorcode)
|
||||||
|
break;
|
||||||
uart_putdw_dec ( overflow - starttime );
|
uart_putdw_dec ( overflow - starttime );
|
||||||
uart_putc ( '\n' );
|
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
|
#endif
|
||||||
Loading…
Reference in New Issue