Line 1... |
Line 1... |
/*!
|
/*!
|
ZTEX Firmware Kit for EZ-USB Microcontrollers
|
ZTEX Firmware Kit for EZ-USB FX2 Microcontrollers
|
Copyright (C) 2009-2010 ZTEX e.K.
|
Copyright (C) 2009-2011 ZTEX GmbH.
|
http://www.ztex.de
|
http://www.ztex.de
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License version 3 as
|
it under the terms of the GNU General Public License version 3 as
|
published by the Free Software Foundation.
|
published by the Free Software Foundation.
|
Line 15... |
Line 15... |
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, see http://www.gnu.org/licenses/.
|
along with this program; if not, see http://www.gnu.org/licenses/.
|
!*/
|
!*/
|
|
|
/*
|
/*
|
SPI mode of MMC / *SD Cards
|
Support for SD cards in SPI mode.
|
|
This module is not MMC compatible anymore since multi block read/write commands are used.
|
*/
|
*/
|
|
|
#ifeq[MMC_PORT][E]
|
#ifeq[MMC_PORT][E]
|
#define[MMC_bmMODE]
|
#define[MMC_bmMODE]
|
#elifeq[MMC_PORT][A]
|
#elifeq[MMC_PORT][A]
|
Line 80... |
Line 81... |
#endif
|
#endif
|
|
|
// may be redefined if the first sectors are reserved (e.g. for a FPGA bitstream)
|
// may be redefined if the first sectors are reserved (e.g. for a FPGA bitstream)
|
#define[FLASH_FIRST_FREE_SECTOR][0]
|
#define[FLASH_FIRST_FREE_SECTOR][0]
|
|
|
xdata BYTE flash_enabled; // 0 1: enabled, 0:disabled
|
__xdata BYTE flash_enabled; // 0 1: enabled, 0:disabled
|
xdata WORD flash_sector_size; // 1 sector size
|
__xdata WORD flash_sector_size; // 1 sector size
|
xdata DWORD flash_sectors; // 3 number of sectors
|
__xdata DWORD flash_sectors; // 3 number of sectors
|
xdata BYTE flash_ec; // 7 error code
|
__xdata BYTE flash_ec; // 7 error code
|
|
|
xdata BYTE mmc_last_cmd; // 0
|
__xdata BYTE mmc_last_cmd; // 0
|
xdata BYTE mmc_response; // 1
|
__xdata BYTE mmc_response; // 1
|
xdata BYTE mmc_version; // 2
|
__xdata BYTE mmc_version; // 2
|
xdata BYTE mmc_buffer[16]; // 3
|
__xdata BYTE mmc_buffer[16]; // 3
|
|
|
|
__xdata BYTE mmc_ep0_wait;
|
|
|
#define[FLASH_EC_CMD_ERROR][1]
|
#define[FLASH_EC_CMD_ERROR][1]
|
#define[FLASH_EC_TIMEOUT][2]
|
#define[FLASH_EC_TIMEOUT][2]
|
#define[FLASH_EC_BUSY][3]
|
#define[FLASH_EC_BUSY][3]
|
#define[FLASH_EC_PENDING][4]
|
#define[FLASH_EC_PENDING][4]
|
Line 104... |
Line 107... |
***** mmc_clocks ****************************************************
|
***** mmc_clocks ****************************************************
|
********************************************************************* */
|
********************************************************************* */
|
// perform c (256 if c=0) clocks
|
// perform c (256 if c=0) clocks
|
void mmc_clocks (BYTE c) {
|
void mmc_clocks (BYTE c) {
|
c; // this avoids stupid warnings
|
c; // this avoids stupid warnings
|
_asm
|
__asm
|
mov r2,dpl
|
mov r2,dpl
|
#ifdef[MMC_bmMODE]
|
#ifdef[MMC_bmMODE]
|
mov a,_MMC_IO
|
mov a,_MMC_IO
|
anl a, #(~MMC_bmCLK)
|
anl a, #(~MMC_bmCLK)
|
mov r3, a
|
mov r3, a
|
Line 123... |
Line 126... |
setb _MMC_CLK
|
setb _MMC_CLK
|
nop
|
nop
|
clr _MMC_CLK
|
clr _MMC_CLK
|
#endif
|
#endif
|
djnz r2,010014$
|
djnz r2,010014$
|
_endasm;
|
__endasm;
|
}
|
}
|
|
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_read_byte ***********************************************
|
***** flash_read_byte ***********************************************
|
********************************************************************* */
|
********************************************************************* */
|
// read a single byte from the flash
|
// read a single byte from the flash
|
BYTE flash_read_byte() { // uses r2,r3,r4
|
BYTE flash_read_byte() { // uses r2,r3,r4
|
_asm
|
__asm
|
#ifdef[MMC_bmMODE]
|
#ifdef[MMC_bmMODE]
|
// 8 - 1 + 8*13 + 1 + 6 = 118 clocks
|
// 8 - 1 + 8*13 + 1 + 6 = 118 clocks
|
mov a,_MMC_IO
|
mov a,_MMC_IO
|
anl a, #(~MMC_bmCLK)
|
anl a, #(~MMC_bmCLK)
|
mov r2, a
|
mov r2, a
|
Line 256... |
Line 259... |
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
#endif
|
#endif
|
mov dpl,a
|
mov dpl,a
|
ret
|
ret
|
_endasm;
|
__endasm;
|
return 0; // never ever called (just to avoid warnings)
|
return 0; // never ever called (just to avoid warnings)
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_read ****************************************************
|
***** flash_read ****************************************************
|
********************************************************************* */
|
********************************************************************* */
|
// read len (256 if len=0) bytes from the flash to the buffer
|
// read len (256 if len=0) bytes from the flash to the buffer
|
void flash_read(__xdata BYTE *buf, BYTE len) {
|
void flash_read(__xdata BYTE *buf, BYTE len) {
|
*buf; // this avoids stupid warnings
|
*buf; // this avoids stupid warnings
|
len; // this too
|
len; // this too
|
_asm // *buf is in dptr, len is in _flash_read_PARM_2
|
__asm // *buf is in dptr, len is in _flash_read_PARM_2
|
mov r2,_flash_read_PARM_2
|
mov r2,_flash_read_PARM_2
|
#ifdef[MMC_bmMODE]
|
#ifdef[MMC_bmMODE]
|
mov a,_MMC_IO
|
mov a,_MMC_IO
|
anl a, #(~MMC_bmCLK)
|
anl a, #(~MMC_bmCLK)
|
mov r5, a
|
mov r5, a
|
Line 394... |
Line 397... |
clr _MMC_CLK
|
clr _MMC_CLK
|
#endif
|
#endif
|
movx @dptr,a
|
movx @dptr,a
|
inc dptr
|
inc dptr
|
djnz r2,010012$
|
djnz r2,010012$
|
_endasm;
|
__endasm;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_write_byte **********************************************
|
***** flash_write_byte **********************************************
|
********************************************************************* */
|
********************************************************************* */
|
// send one bytes from buffer buf to the card
|
// send one bytes from buffer buf to the card
|
void flash_write_byte (BYTE b) { // b is in dpl
|
void flash_write_byte (BYTE b) { // b is in dpl
|
b; // this avoids stupid warnings
|
b; // this avoids stupid warnings
|
_asm
|
__asm
|
#ifdef[MMC_bmMODE]
|
#ifdef[MMC_bmMODE]
|
// up to 7 + 8*12 + 6 = 109 clocks
|
// up to 7 + 8*12 + 6 = 109 clocks
|
mov a,_MMC_IO
|
mov a,_MMC_IO
|
anl a, #(255 - MMC_bmCLK - MMC_bmDI )
|
anl a, #(255 - MMC_bmCLK - MMC_bmDI )
|
mov r3, a
|
mov r3, a
|
Line 513... |
Line 516... |
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
nop
|
nop
|
clr _MMC_CLK
|
clr _MMC_CLK
|
#endif
|
#endif
|
_endasm;
|
__endasm;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_write ***************************************************
|
***** flash_write ***************************************************
|
********************************************************************* */
|
********************************************************************* */
|
// write len (256 id len=0) bytes from the buffer to the flash
|
// write len (256 id len=0) bytes from the buffer to the flash
|
void flash_write(__xdata BYTE *buf, BYTE len) {
|
void flash_write(__xdata BYTE *buf, BYTE len) {
|
*buf; // this avoids stupid warnings
|
*buf; // this avoids stupid warnings
|
len; // this too
|
len; // this too
|
_asm // *buf is in dptr, len is in _flash_read_PARM_2
|
__asm // *buf is in dptr, len is in _flash_read_PARM_2
|
mov r2,_flash_read_PARM_2
|
mov r2,_flash_read_PARM_2
|
#ifdef[MMC_bmMODE]
|
#ifdef[MMC_bmMODE]
|
// 7 + len*(2 + 8*12 + 7 ) + 6 = 13 + len*105 clocks
|
// 7 + len*(2 + 8*12 + 7 ) + 6 = 13 + len*105 clocks
|
mov a,_MMC_IO
|
mov a,_MMC_IO
|
anl a, #(255 - MMC_bmCLK - MMC_bmDI )
|
anl a, #(255 - MMC_bmCLK - MMC_bmDI )
|
Line 641... |
Line 644... |
inc dptr
|
inc dptr
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
djnz r2,010013$
|
djnz r2,010013$
|
#endif
|
#endif
|
_endasm;
|
__endasm;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** mmc_wait_busy *************************************************
|
***** mmc_wait_busy *************************************************
|
********************************************************************* */
|
********************************************************************* */
|
BYTE mmc_wait_busy () {
|
BYTE mmc_wait_busy () {
|
WORD i;
|
WORD i;
|
flash_ec = FLASH_EC_BUSY;
|
flash_ec = FLASH_EC_BUSY;
|
MMC_IO |= MMC_bmDI; // avoids that in-data is interpreted as command
|
MMC_IO |= MMC_bmDI; // avoids that in-data is interpreted as command
|
for (i=0; (flash_read_byte()!=255) && i<65535; i++ ) ;
|
for (i=0; (flash_read_byte()!=255) && i<65535; i++ ) ;
|
|
// for (i=0; (flash_read_byte()==0) && i<65535; i++ ) ;
|
if ( MMC__IO_DO & MMC_bmDO ) {
|
if ( MMC__IO_DO & MMC_bmDO ) {
|
flash_ec = 0;
|
flash_ec = 0;
|
return 0;
|
return 0;
|
}
|
}
|
return 1;
|
return 1;
|
Line 691... |
Line 695... |
***** mmc_read_response *********************************************
|
***** mmc_read_response *********************************************
|
********************************************************************* */
|
********************************************************************* */
|
// read the first response byte
|
// read the first response byte
|
BYTE mmc_read_response() {
|
BYTE mmc_read_response() {
|
MMC_IO |= MMC_bmDI; // avoids that in-data is interpreted as command
|
MMC_IO |= MMC_bmDI; // avoids that in-data is interpreted as command
|
_asm
|
__asm
|
mov r2,#0x255
|
mov r2,#0x255
|
010010$:
|
010010$:
|
lcall _flash_read_byte
|
lcall _flash_read_byte
|
mov a,dpl
|
mov a,dpl
|
jnb acc.7,010011$
|
jnb acc.7,010011$
|
Line 704... |
Line 708... |
010011$:
|
010011$:
|
mov dptr,#_mmc_response
|
mov dptr,#_mmc_response
|
movx @dptr,a
|
movx @dptr,a
|
mov dpl,a
|
mov dpl,a
|
ret
|
ret
|
_endasm;
|
__endasm;
|
return 0; // never ever called, just to avoid stupid warnings
|
return 0; // never ever called, just to avoid stupid warnings
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
|
***** mmc_send_cmd **************************************************
|
|
********************************************************************* */
|
|
// send a command
|
|
#define[mmc_send_cmd(][,$1.$2.$3.$4,$5);][{ // send a command, argument=0
|
|
mmc_clocks(8); // 8 dummy clocks
|
|
mmc_last_cmd = $0;
|
|
mmc_buffer[0] = 64 | ($0 & 127);
|
|
mmc_buffer[1] = $1;
|
|
mmc_buffer[2] = $2;
|
|
mmc_buffer[3] = $3;
|
|
mmc_buffer[4] = $4;
|
|
mmc_buffer[5] = $5 | 1;
|
|
flash_write(mmc_buffer,6);
|
|
mmc_read_response();
|
|
}]
|
|
|
|
/* *********************************************************************
|
***** mmc_wait_start ************************************************
|
***** mmc_wait_start ************************************************
|
********************************************************************* */
|
********************************************************************* */
|
/*
|
/*
|
wait for the start byte
|
wait for the start byte
|
returns 1 on error
|
returns 1 on error
|
Line 730... |
Line 751... |
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_read_init ***********************************************
|
***** flash_read_init ***********************************************
|
********************************************************************* */
|
********************************************************************* */
|
/*
|
/*
|
Start the initialization sequence for reading sector s-
|
Start the initialization sequence for reading sector s.
|
The whole sector must be read.
|
The whole sector must be read.
|
returns an error code (FLASH_EC_*). 0 means no error.
|
returns an error code (FLASH_EC_*). 0 means no error.
|
*/
|
*/
|
BYTE flash_read_init(DWORD s) {
|
BYTE flash_read_init(DWORD s) {
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
Line 743... |
Line 764... |
if ( mmc_select() ) { // select the card
|
if ( mmc_select() ) { // select the card
|
mmc_deselect();
|
mmc_deselect();
|
return FLASH_EC_BUSY;
|
return FLASH_EC_BUSY;
|
}
|
}
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_last_cmd = 17;
|
mmc_last_cmd = 18;
|
mmc_buffer[0] = 17 | 64;
|
mmc_buffer[0] = 18 | 64;
|
if ( mmc_version == 0 ) {
|
if ( mmc_version == 0 ) {
|
s = s << 1;
|
s = s << 1;
|
mmc_buffer[1] = s >> 16;
|
mmc_buffer[1] = s >> 16;
|
mmc_buffer[2] = s >> 8;
|
mmc_buffer[2] = s >> 8;
|
mmc_buffer[3] = s;
|
mmc_buffer[3] = s;
|
Line 774... |
Line 795... |
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
|
***** flash_read_next ***********************************************
|
|
********************************************************************* */
|
|
/*
|
|
Initialization sequence for reading the next sector.
|
|
The whole sector must be read.
|
|
returns an error code (FLASH_EC_*). 0 means no error.
|
|
*/
|
|
BYTE flash_read_next() {
|
|
mmc_clocks(16); // 16 CRC clocks
|
|
if ( mmc_wait_start() ) { // wait for the start byte
|
|
mmc_deselect();
|
|
return FLASH_EC_TIMEOUT;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* *********************************************************************
|
***** flash_read_finish *********************************************
|
***** flash_read_finish *********************************************
|
********************************************************************* */
|
********************************************************************* */
|
/*
|
/*
|
Reads n dummy bytes (the whole sector has to be read out)
|
Reads n dummy bytes (the whole sector has to be read out)
|
and runs the finalization sequence for a sector read.
|
and runs the finalization sequence for a sector read.
|
Line 786... |
Line 824... |
while ( n > 32 ) {
|
while ( n > 32 ) {
|
mmc_clocks(0); // 256 clocks = 32 dummy bytes
|
mmc_clocks(0); // 256 clocks = 32 dummy bytes
|
n-=32;
|
n-=32;
|
}
|
}
|
mmc_clocks(n << 3);
|
mmc_clocks(n << 3);
|
mmc_clocks(24); // 16 CRC + 8 dummy clocks
|
mmc_clocks(16); // 16 CRC clocks
|
|
mmc_send_cmd(12, 0.0.0.0, 0); // stop transmission command, errors are ignored
|
|
// mmc_wait_busy(); // not required here
|
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_deselect();
|
mmc_deselect();
|
}
|
}
|
|
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_write_init **********************************************
|
***** flash_write_init **********************************************
|
********************************************************************* */
|
********************************************************************* */
|
/*
|
/*
|
Start the initialization sequence for writing sector s
|
Start the initialization sequence for writing sector s
|
The whole sectir must be written.
|
The whole sector must be written.
|
returns an error code (FLASH_EC_*). 0 means no error.
|
returns an error code (FLASH_EC_*). 0 means no error.
|
*/
|
*/
|
BYTE flash_write_init(DWORD s) {
|
BYTE flash_write_init(DWORD s) {
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
return FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
return FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
Line 808... |
Line 849... |
if ( mmc_select() ) { // select the card
|
if ( mmc_select() ) { // select the card
|
mmc_deselect();
|
mmc_deselect();
|
return FLASH_EC_BUSY;
|
return FLASH_EC_BUSY;
|
}
|
}
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_last_cmd = 24;
|
mmc_last_cmd = 25;
|
mmc_buffer[0] = 24 | 64;
|
mmc_buffer[0] = 25 | 64;
|
if ( mmc_version == 0 ) {
|
if ( mmc_version == 0 ) {
|
s = s << 1;
|
s = s << 1;
|
mmc_buffer[1] = s >> 16;
|
mmc_buffer[1] = s >> 16;
|
mmc_buffer[2] = s >> 8;
|
mmc_buffer[2] = s >> 8;
|
mmc_buffer[3] = s;
|
mmc_buffer[3] = s;
|
Line 831... |
Line 872... |
if ( mmc_response != 0 ) {
|
if ( mmc_response != 0 ) {
|
mmc_deselect();
|
mmc_deselect();
|
return FLASH_EC_CMD_ERROR;
|
return FLASH_EC_CMD_ERROR;
|
}
|
}
|
|
|
MMC_IO |= MMC_bmDI; // send one dummy byte plus the start byte 0xfe
|
MMC_IO |= MMC_bmDI;
|
mmc_clocks(15);
|
mmc_clocks(8); // send one dummy byte
|
MMC_IO &= ~MMC_bmDI;
|
flash_write_byte( 0xfc ); // send the start byte
|
MMC_IO |= MMC_bmCLK;
|
|
MMC_IO &= ~MMC_bmCLK;
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_write_finish ********************************************
|
***** flash_write_finish_sector *************************************
|
********************************************************************* */
|
********************************************************************* */
|
/*
|
/*
|
Writes n dummy bytes (the whole sector has to be written)
|
Writes the rest of the sector (n dummy bytes + CRC, the whole sector has to be written)
|
and runs the finalization sequence for a sector write
|
but do not write the finalization procedure. This is done by flash_write_finish
|
returns an error code (FLASH_EC_*). 0 means no error.
|
or flash_write_next, i.e. these functions must be called after flash_write_finish_sector.
|
|
|
|
Between flash_write_finish / flash_write_next and flash_write_finish_sector some code
|
|
may be executed because flash_write_finish / flash_write_next start with
|
|
mmc_wauit_busy().
|
|
|
|
Returns an error code (FLASH_EC_*). 0 means no error.
|
*/
|
*/
|
BYTE flash_write_finish(WORD n) {
|
BYTE flash_write_finish_sector (WORD n) {
|
BYTE b;
|
|
MMC_IO &= ~MMC_bmDI; // value of the dummy data is 0
|
MMC_IO &= ~MMC_bmDI; // value of the dummy data is 0
|
while ( n > 32 ) {
|
while ( n > 32 ) {
|
mmc_clocks(0); // 256 clocks = 32 dummy bytes
|
mmc_clocks(0); // 256 clocks = 32 dummy bytes
|
n-=32;
|
n-=32;
|
}
|
}
|
mmc_clocks(n << 3);
|
mmc_clocks(n << 3);
|
|
|
MMC_IO |= MMC_bmDI;
|
MMC_IO |= MMC_bmDI;
|
mmc_clocks(16); // 16 CRC clocks
|
mmc_clocks(16); // 16 CRC clocks
|
b = flash_read_byte() & 7;
|
|
// mmc_wait_busy(); // not required here, programming continues if card is deslected
|
if ( (flash_read_byte() & 0xf) != 5 ) { // data response: last four bits must be 5
|
|
flash_ec = FLASH_EC_WRITE_ERROR;
|
|
mmc_send_cmd(12, 0.0.0.0, 0); // stop transmission command, errors are ignored
|
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_deselect();
|
mmc_deselect();
|
if ( b != 5 ) { // data response, last three bits must be 5
|
|
return FLASH_EC_WRITE_ERROR;
|
return FLASH_EC_WRITE_ERROR;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** mmc_send_cmd **************************************************
|
***** flash_write_finish ********************************************
|
********************************************************************* */
|
********************************************************************* */
|
// send a command
|
/*
|
#define[mmc_send_cmd(][,$1.$2.$3.$4,$5);][{ // send a command, argument=0
|
Stops the write transimssion, see flash_write_finish1.
|
|
*/
|
|
void flash_write_finish () {
|
|
mmc_wait_busy();
|
|
flash_write_byte( 0xfd ); // send the stop byte
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_last_cmd = $0;
|
mmc_deselect();
|
mmc_buffer[0] = 64 | ($0 & 127);
|
}
|
mmc_buffer[1] = $1;
|
|
mmc_buffer[2] = $2;
|
/* *********************************************************************
|
mmc_buffer[3] = $3;
|
***** flash_write_next **********************************************
|
mmc_buffer[4] = $4;
|
********************************************************************* */
|
mmc_buffer[5] = $5 | 1;
|
/*
|
flash_write(mmc_buffer,6);
|
Prepare the nexte sector for write transimssion, see flash_write_finish1.
|
mmc_read_response();
|
*/
|
}]
|
void flash_write_next () {
|
|
mmc_wait_busy();
|
|
flash_write_byte( 0xfc ); // send the stop byte
|
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** flash_init ****************************************************
|
***** flash_init ****************************************************
|
********************************************************************* */
|
********************************************************************* */
|
// init the card
|
// init the card
|
Line 907... |
Line 960... |
mmc_select(); // select te card
|
mmc_select(); // select te card
|
flash_ec = FLASH_EC_BUSY;
|
flash_ec = FLASH_EC_BUSY;
|
|
|
mmc_send_cmd(0, 0.0.0.0, 0x95); // send reset command
|
mmc_send_cmd(0, 0.0.0.0, 0x95); // send reset command
|
if ( mmc_response & ~1 ) { // check for errors
|
if ( mmc_response & ~1 ) { // check for errors
|
|
wait(50);
|
|
mmc_send_cmd(0, 0.0.0.0, 0x95); // 2nd try
|
|
if ( mmc_response & ~1 ) // check for errors
|
goto mmc_init_cmd_err;
|
goto mmc_init_cmd_err;
|
}
|
}
|
|
|
// send cmd8, valid ? 2.0 mode : 1.xx mode
|
// send cmd8, valid ? 2.0 mode : 1.xx mode
|
mmc_send_cmd(8, 0.0.1.0xaa, 0x87);
|
mmc_send_cmd(8, 0.0.1.0xaa, 0x87);
|
Line 1003... |
Line 1059... |
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** EP0 vendor request 0x41 ***************************************
|
***** EP0 vendor request 0x41 ***************************************
|
********************************************************************* */
|
********************************************************************* */
|
void mmc_read_ep0 () {
|
void mmc_read_ep0 () {
|
|
if ( mmc_ep0_wait ) {
|
|
mmc_ep0_wait = 0;
|
|
if ( mmc_wait_start() ) { // wait for the start byte of the next block
|
|
flash_ec = FLASH_EC_TIMEOUT;
|
|
mmc_send_cmd(12, 0.0.0.0, 0); // stop transmission command
|
|
mmc_clocks(8); // 8 dummy clocks
|
|
mmc_deselect();
|
|
return;
|
|
}
|
|
}
|
|
|
flash_read(EP0BUF, ep0_payload_transfer);
|
flash_read(EP0BUF, ep0_payload_transfer);
|
if ( ep0_payload_remaining == 0 ) {
|
if ( ep0_payload_remaining == 0 ) {
|
mmc_clocks(24); // 16 CRC + 8 dummy clocks
|
mmc_clocks(16); // 16 CRC clocks
|
|
mmc_send_cmd(12, 0.0.0.0, 0); // stop transmission command, errors are ignored
|
|
// mmc_wait_busy(); // not required here
|
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_deselect();
|
mmc_deselect();
|
}
|
}
|
|
else if ( (ep0_payload_remaining & 511) == 0 ) {
|
|
mmc_clocks(16); // 16 CRC clocks
|
|
mmc_ep0_wait = 1;
|
|
}
|
}
|
}
|
|
|
ADD_EP0_VENDOR_REQUEST((0x41,, // read (exactly) one sector
|
ADD_EP0_VENDOR_REQUEST((0x41,, // read integer number of sectotrs
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
flash_ec = FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
flash_ec = FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
if ( mmc_select() ) { // select the card
|
if ( mmc_select() ) { // select the card
|
mmc_deselect();
|
mmc_deselect();
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_last_cmd = 17;
|
mmc_last_cmd = 18;
|
mmc_buffer[0] = 17 | 64;
|
mmc_buffer[0] = 18 | 64;
|
if ( mmc_version == 0 ) {
|
if ( mmc_version == 0 ) {
|
_asm
|
__asm
|
clr c
|
clr c
|
mov dptr,#(_SETUPDAT + 2)
|
mov dptr,#(_SETUPDAT + 2)
|
movx a,@dptr
|
movx a,@dptr
|
mov dptr,#(_mmc_buffer + 3)
|
mov dptr,#(_mmc_buffer + 3)
|
rlc a
|
rlc a
|
Line 1042... |
Line 1116... |
mov dptr,#(_SETUPDAT + 4)
|
mov dptr,#(_SETUPDAT + 4)
|
movx a,@dptr
|
movx a,@dptr
|
mov dptr,#(_mmc_buffer + 1)
|
mov dptr,#(_mmc_buffer + 1)
|
rlc a
|
rlc a
|
movx @dptr,a
|
movx @dptr,a
|
_endasm;
|
__endasm;
|
mmc_buffer[4] = 0;
|
mmc_buffer[4] = 0;
|
}
|
}
|
else {
|
else {
|
mmc_buffer[1] = SETUPDAT[5];
|
mmc_buffer[1] = SETUPDAT[5];
|
mmc_buffer[2] = SETUPDAT[4];
|
mmc_buffer[2] = SETUPDAT[4];
|
Line 1060... |
Line 1134... |
flash_ec = FLASH_EC_CMD_ERROR;
|
flash_ec = FLASH_EC_CMD_ERROR;
|
mmc_deselect();
|
mmc_deselect();
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
|
|
if ( mmc_wait_start() ) { // wait for the start byte
|
mmc_ep0_wait = 1;
|
flash_ec = FLASH_EC_TIMEOUT;
|
mmc_read_ep0();
|
mmc_deselect();
|
if ( flash_ec != 0 ) {
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
|
|
mmc_read_ep0();
|
|
EP0BCH = 0;
|
EP0BCH = 0;
|
EP0BCL = ep0_payload_transfer;
|
EP0BCL = ep0_payload_transfer;
|
,,
|
,,
|
if ( ep0_payload_transfer != 0 ) {
|
if ( ep0_payload_transfer != 0 ) {
|
|
flash_ec = 0;
|
mmc_read_ep0();
|
mmc_read_ep0();
|
|
if ( flash_ec != 0 ) {
|
|
EP0_STALL;
|
|
}
|
}
|
}
|
EP0BCH = 0;
|
EP0BCH = 0;
|
EP0BCL = ep0_payload_transfer;
|
EP0BCL = ep0_payload_transfer;
|
));;
|
));;
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** EP0 vendor command 0x42 ***************************************
|
***** EP0 vendor command 0x42 ***************************************
|
********************************************************************* */
|
********************************************************************* */
|
void mmc_send_ep0 () {
|
void mmc_send_ep0 () {
|
|
if ( mmc_ep0_wait ) {
|
|
mmc_ep0_wait = 0;
|
|
mmc_wait_busy();
|
|
flash_write_byte( 0xfc ); // send the start byte of the next data block
|
|
}
|
|
|
flash_write(EP0BUF, ep0_payload_transfer);
|
flash_write(EP0BUF, ep0_payload_transfer);
|
if ( ep0_payload_remaining == 0 ) {
|
if ( (ep0_payload_remaining & 511) == 0 ) {
|
MMC_IO |= MMC_bmDI;
|
MMC_IO |= MMC_bmDI;
|
mmc_clocks(16); // 16 CRC clocks
|
mmc_clocks(16); // 16 CRC clocks
|
if ( (flash_read_byte() & 7) != 5 ) { // data response, last three bits must be 5
|
|
|
if ( (flash_read_byte() & 0xf) != 5 ) { // data response: last four bits must be 5
|
flash_ec = FLASH_EC_WRITE_ERROR;
|
flash_ec = FLASH_EC_WRITE_ERROR;
|
|
mmc_send_cmd(12, 0.0.0.0, 0); // stop transmission command, errors are ignored
|
|
mmc_clocks(8); // 8 dummy clocks
|
|
mmc_deselect();
|
}
|
}
|
// mmc_wait_busy(); // not required here, programming continues if card is deselected
|
|
|
if ( ep0_payload_remaining != 0 ) {
|
|
mmc_ep0_wait = 1;
|
|
}
|
|
else {
|
|
mmc_wait_busy();
|
|
flash_write_byte( 0xfd ); // send the stop byte
|
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_deselect();
|
mmc_deselect();
|
}
|
}
|
}
|
}
|
|
}
|
|
|
ADD_EP0_VENDOR_COMMAND((0x42,, // write (exactly!) one sector
|
ADD_EP0_VENDOR_COMMAND((0x42,, // write integer number of sectors
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
if ( (MMC_IO & MMC_bmCS) == 0 ) {
|
flash_ec = FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
flash_ec = FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
if ( mmc_select() ) { // select the card
|
if ( mmc_select() ) { // select the card
|
mmc_deselect();
|
mmc_deselect();
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_clocks(8); // 8 dummy clocks
|
mmc_last_cmd = 24;
|
mmc_last_cmd = 25;
|
mmc_buffer[0] = 24 | 64;
|
mmc_buffer[0] = 25 | 64;
|
if ( mmc_version == 0 ) {
|
if ( mmc_version == 0 ) {
|
_asm
|
__asm
|
clr c
|
clr c
|
mov dptr,#(_SETUPDAT + 2)
|
mov dptr,#(_SETUPDAT + 2)
|
movx a,@dptr
|
movx a,@dptr
|
mov dptr,#(_mmc_buffer + 3)
|
mov dptr,#(_mmc_buffer + 3)
|
rlc a
|
rlc a
|
Line 1125... |
Line 1219... |
mov dptr,#(_SETUPDAT + 4)
|
mov dptr,#(_SETUPDAT + 4)
|
movx a,@dptr
|
movx a,@dptr
|
mov dptr,#(_mmc_buffer + 1)
|
mov dptr,#(_mmc_buffer + 1)
|
rlc a
|
rlc a
|
movx @dptr,a
|
movx @dptr,a
|
_endasm;
|
__endasm;
|
mmc_buffer[4] = 0;
|
mmc_buffer[4] = 0;
|
}
|
}
|
else {
|
else {
|
mmc_buffer[1] = SETUPDAT[5];
|
mmc_buffer[1] = SETUPDAT[5];
|
mmc_buffer[2] = SETUPDAT[4];
|
mmc_buffer[2] = SETUPDAT[4];
|
Line 1144... |
Line 1238... |
flash_ec = FLASH_EC_CMD_ERROR;
|
flash_ec = FLASH_EC_CMD_ERROR;
|
mmc_deselect();
|
mmc_deselect();
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
|
|
MMC_IO |= MMC_bmDI; // send one dummy byte plus the start byte 0xfe
|
MMC_IO |= MMC_bmDI;
|
mmc_clocks(15);
|
mmc_clocks(8); // send one dummy byte
|
MMC_IO &= ~MMC_bmDI;
|
flash_write_byte( 0xfc ); // send the start byte
|
MMC_IO |= MMC_bmCLK;
|
mmc_ep0_wait = 0;
|
MMC_IO &= ~MMC_bmCLK;
|
|
,,
|
,,
|
if ( ep0_payload_transfer != 0 ) {
|
if ( ep0_payload_transfer != 0 ) {
|
flash_ec = 0;
|
flash_ec = 0;
|
mmc_send_ep0();
|
mmc_send_ep0();
|
if ( flash_ec != 0 ) {
|
if ( flash_ec != 0 ) {
|