/*!
|
/*!
|
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.
|
|
|
This program is distributed in the hope that it will be useful, but
|
This program is distributed in the hope that it will be useful, but
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
General Public License for more details.
|
General Public License for more details.
|
|
|
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]
|
#elifeq[MMC_PORT][B]
|
#elifeq[MMC_PORT][B]
|
#elifeq[MMC_PORT][C]
|
#elifeq[MMC_PORT][C]
|
#elifneq[MMC_PORT][D]
|
#elifneq[MMC_PORT][D]
|
#error[Macro `MMC_PORT' is not defined correctly. Valid values are: `A', `B', `C', `D' and `E'.]
|
#error[Macro `MMC_PORT' is not defined correctly. Valid values are: `A', `B', `C', `D' and `E'.]
|
#endif
|
#endif
|
|
|
#ifndef[ZTEX_FLASH1_H]
|
#ifndef[ZTEX_FLASH1_H]
|
#define[ZTEX_FLASH1_H]
|
#define[ZTEX_FLASH1_H]
|
|
|
#define[@CAPABILITY_FLASH;]
|
#define[@CAPABILITY_FLASH;]
|
|
|
#ifndef[MMC_PORT]
|
#ifndef[MMC_PORT]
|
#error[MMC_PORT not defined]
|
#error[MMC_PORT not defined]
|
#endif
|
#endif
|
|
|
#ifndef[MMC_BIT_CS]
|
#ifndef[MMC_BIT_CS]
|
#error[MMC_BIT_CS not defined]
|
#error[MMC_BIT_CS not defined]
|
#endif
|
#endif
|
|
|
#ifndef[MMC_BIT_DI]
|
#ifndef[MMC_BIT_DI]
|
#error[MMC_BIT_DI not defined]
|
#error[MMC_BIT_DI not defined]
|
#endif
|
#endif
|
|
|
#ifndef[MMC_BIT_DO]
|
#ifndef[MMC_BIT_DO]
|
#error[MMC_BIT_DO not defined]
|
#error[MMC_BIT_DO not defined]
|
#endif
|
#endif
|
|
|
#ifndef[MMC_BIT_CLK]
|
#ifndef[MMC_BIT_CLK]
|
#error[MMC_BIT_CLK not defined]
|
#error[MMC_BIT_CLK not defined]
|
#endif
|
#endif
|
|
|
#ifndef[MMC__PORT_DO]
|
#ifndef[MMC__PORT_DO]
|
#define[MMC__PORT_DO][MMC_PORT]
|
#define[MMC__PORT_DO][MMC_PORT]
|
#endif
|
#endif
|
|
|
#ifdef[MMC_bmMODE]
|
#ifdef[MMC_bmMODE]
|
#ifneq[MMC__PORT_DO][MMC_PORT]
|
#ifneq[MMC__PORT_DO][MMC_PORT]
|
#error[MMC__PORT_DO and MMC_PORT must be equal]
|
#error[MMC__PORT_DO and MMC_PORT must be equal]
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
#define[MMC_bmCS][bmBITMMC_BIT_CS]
|
#define[MMC_bmCS][bmBITMMC_BIT_CS]
|
#define[MMC_bmDI][bmBITMMC_BIT_DI]
|
#define[MMC_bmDI][bmBITMMC_BIT_DI]
|
#define[MMC_bmDO][bmBITMMC_BIT_DO]
|
#define[MMC_bmDO][bmBITMMC_BIT_DO]
|
#define[MMC_bmCLK][bmBITMMC_BIT_CLK]
|
#define[MMC_bmCLK][bmBITMMC_BIT_CLK]
|
|
|
#define[MMC_IO][IOMMC_PORT]
|
#define[MMC_IO][IOMMC_PORT]
|
#define[MMC__IO_DO][IOMMC__PORT_DO]
|
#define[MMC__IO_DO][IOMMC__PORT_DO]
|
|
|
#ifndef[MMC_bmMODE]
|
#ifndef[MMC_bmMODE]
|
#define[MMC_CS][IOMMC_PORTMMC_BIT_CS]
|
#define[MMC_CS][IOMMC_PORTMMC_BIT_CS]
|
#define[MMC_CLK][IOMMC_PORTMMC_BIT_CLK]
|
#define[MMC_CLK][IOMMC_PORTMMC_BIT_CLK]
|
#define[MMC_DI][IOMMC_PORTMMC_BIT_DI]
|
#define[MMC_DI][IOMMC_PORTMMC_BIT_DI]
|
#define[MMC_DO][IOMMC__PORT_DOMMC_BIT_DO]
|
#define[MMC_DO][IOMMC__PORT_DOMMC_BIT_DO]
|
#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]
|
#define[FLASH_EC_READ_ERROR][5]
|
#define[FLASH_EC_READ_ERROR][5]
|
#define[FLASH_EC_WRITE_ERROR][6]
|
#define[FLASH_EC_WRITE_ERROR][6]
|
#define[FLASH_EC_NOTSUPPORTED][7]
|
#define[FLASH_EC_NOTSUPPORTED][7]
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** 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
|
orl a, #(MMC_bmCLK)
|
orl a, #(MMC_bmCLK)
|
mov r4, a
|
mov r4, a
|
010014$:
|
010014$:
|
mov _MMC_IO,r4
|
mov _MMC_IO,r4
|
nop
|
nop
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
#else
|
#else
|
010014$:
|
010014$:
|
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
|
orl a, #(MMC_bmCLK)
|
orl a, #(MMC_bmCLK)
|
mov r3, a
|
mov r3, a
|
|
|
mov a,_MMC_IO // 7
|
mov a,_MMC_IO // 7
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 6
|
mov a,_MMC_IO // 6
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 5
|
mov a,_MMC_IO // 5
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 4
|
mov a,_MMC_IO // 4
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 3
|
mov a,_MMC_IO // 3
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 2
|
mov a,_MMC_IO // 2
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 1
|
mov a,_MMC_IO // 1
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
mov a,_MMC_IO // 0
|
mov a,_MMC_IO // 0
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
xrl a,#255
|
xrl a,#255
|
mov _MMC_IO, r2
|
mov _MMC_IO, r2
|
|
|
#else
|
#else
|
// 8*7 + 6 = 62 clocks
|
// 8*7 + 6 = 62 clocks
|
mov c,_MMC_DO // 7
|
mov c,_MMC_DO // 7
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 6
|
mov c,_MMC_DO // 6
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 5
|
mov c,_MMC_DO // 5
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 4
|
mov c,_MMC_DO // 4
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 3
|
mov c,_MMC_DO // 3
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 2
|
mov c,_MMC_DO // 2
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 1
|
mov c,_MMC_DO // 1
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 0
|
mov c,_MMC_DO // 0
|
setb _MMC_CLK
|
setb _MMC_CLK
|
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
|
orl a, #(MMC_bmCLK)
|
orl a, #(MMC_bmCLK)
|
mov r3, a
|
mov r3, a
|
|
|
010012$:
|
010012$:
|
// 8 + len*(-1 + 8*13 - 1 + 2 + 9) + 4 = 12 + len*113 clocks
|
// 8 + len*(-1 + 8*13 - 1 + 2 + 9) + 4 = 12 + len*113 clocks
|
mov a,_MMC_IO // 7
|
mov a,_MMC_IO // 7
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 6
|
mov a,_MMC_IO // 6
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 5
|
mov a,_MMC_IO // 5
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 4
|
mov a,_MMC_IO // 4
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 3
|
mov a,_MMC_IO // 3
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 2
|
mov a,_MMC_IO // 2
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 1
|
mov a,_MMC_IO // 1
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
mov r4,a
|
mov r4,a
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
|
|
mov a,_MMC_IO // 0
|
mov a,_MMC_IO // 0
|
anl a,#(MMC_bmDO)
|
anl a,#(MMC_bmDO)
|
mov _MMC_IO, r3
|
mov _MMC_IO, r3
|
subb a,#1
|
subb a,#1
|
mov a,r4
|
mov a,r4
|
rlc a
|
rlc a
|
xrl a,#255
|
xrl a,#255
|
mov _MMC_IO, r5
|
mov _MMC_IO, r5
|
#else
|
#else
|
010012$:
|
010012$:
|
// 2 + len*(8*7 + 9) + 4 = 6 + len*65 clocks
|
// 2 + len*(8*7 + 9) + 4 = 6 + len*65 clocks
|
mov c,_MMC_DO // 7
|
mov c,_MMC_DO // 7
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 6
|
mov c,_MMC_DO // 6
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 5
|
mov c,_MMC_DO // 5
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 4
|
mov c,_MMC_DO // 4
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 3
|
mov c,_MMC_DO // 3
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 2
|
mov c,_MMC_DO // 2
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 1
|
mov c,_MMC_DO // 1
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov c,_MMC_DO // 0
|
mov c,_MMC_DO // 0
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a
|
rlc a
|
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
|
mov a,dpl
|
mov a,dpl
|
|
|
rlc a // 7
|
rlc a // 7
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100157$
|
jnc 0100157$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100157$:
|
0100157$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 6
|
rlc a // 6
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100156$
|
jnc 0100156$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100156$:
|
0100156$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 5
|
rlc a // 5
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100155$
|
jnc 0100155$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100155$:
|
0100155$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 4
|
rlc a // 4
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100154$
|
jnc 0100154$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100154$:
|
0100154$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 3
|
rlc a // 3
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100153$
|
jnc 0100153$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100153$:
|
0100153$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 2
|
rlc a // 2
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100152$
|
jnc 0100152$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100152$:
|
0100152$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 1
|
rlc a // 1
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100151$
|
jnc 0100151$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100151$:
|
0100151$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 0
|
rlc a // 0
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100150$
|
jnc 0100150$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100150$:
|
0100150$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
#else
|
#else
|
// 3 + 8*7 + 4 = 63 clocks
|
// 3 + 8*7 + 4 = 63 clocks
|
mov a,dpl
|
mov a,dpl
|
rlc a // 7
|
rlc a // 7
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 6
|
rlc a // 6
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 5
|
rlc a // 5
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 4
|
rlc a // 4
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 3
|
rlc a // 3
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 2
|
rlc a // 2
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 1
|
rlc a // 1
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 0
|
rlc a // 0
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
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 )
|
mov r3, a
|
mov r3, a
|
010013$:
|
010013$:
|
movx a,@dptr
|
movx a,@dptr
|
|
|
rlc a // 7
|
rlc a // 7
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100167$
|
jnc 0100167$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100167$:
|
0100167$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 6
|
rlc a // 6
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100166$
|
jnc 0100166$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100166$:
|
0100166$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 5
|
rlc a // 5
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100165$
|
jnc 0100165$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100165$:
|
0100165$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 4
|
rlc a // 4
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100164$
|
jnc 0100164$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100164$:
|
0100164$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 3
|
rlc a // 3
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100163$
|
jnc 0100163$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100163$:
|
0100163$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 2
|
rlc a // 2
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100162$
|
jnc 0100162$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100162$:
|
0100162$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 1
|
rlc a // 1
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100161$
|
jnc 0100161$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100161$:
|
0100161$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
rlc a // 0
|
rlc a // 0
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
jnc 0100160$
|
jnc 0100160$
|
orl _MMC_IO, #(MMC_bmDI)
|
orl _MMC_IO, #(MMC_bmDI)
|
0100160$:
|
0100160$:
|
orl _MMC_IO, #(MMC_bmCLK)
|
orl _MMC_IO, #(MMC_bmCLK)
|
|
|
inc dptr
|
inc dptr
|
djnz r2,010013$
|
djnz r2,010013$
|
|
|
mov _MMC_IO,r3
|
mov _MMC_IO,r3
|
#else
|
#else
|
010013$:
|
010013$:
|
// 2 + len*(3 + 8*7 - 1 + 7 ) + 4 = 6 + len*65 clocks
|
// 2 + len*(3 + 8*7 - 1 + 7 ) + 4 = 6 + len*65 clocks
|
movx a,@dptr
|
movx a,@dptr
|
rlc a // 7
|
rlc a // 7
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 6
|
rlc a // 6
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 5
|
rlc a // 5
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 4
|
rlc a // 4
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 3
|
rlc a // 3
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 2
|
rlc a // 2
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 1
|
rlc a // 1
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
rlc a // 0
|
rlc a // 0
|
clr _MMC_CLK
|
clr _MMC_CLK
|
|
|
mov _MMC_DI,c
|
mov _MMC_DI,c
|
setb _MMC_CLK
|
setb _MMC_CLK
|
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;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** mmc_select ****************************************************
|
***** mmc_select ****************************************************
|
********************************************************************* */
|
********************************************************************* */
|
/*
|
/*
|
select the card (CS) and waits if busy
|
select the card (CS) and waits if busy
|
returns 1 if busy
|
returns 1 if busy
|
*/
|
*/
|
BYTE mmc_select() {
|
BYTE mmc_select() {
|
MMC_IO |= MMC_bmCS; // CS = 1
|
MMC_IO |= MMC_bmCS; // CS = 1
|
mmc_clocks(8); // 8 dummy clocks to finish a previous command
|
mmc_clocks(8); // 8 dummy clocks to finish a previous command
|
MMC_IO &= ~MMC_bmCS; // CS = 0
|
MMC_IO &= ~MMC_bmCS; // CS = 0
|
|
|
return mmc_wait_busy();
|
return mmc_wait_busy();
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** mmc_deselect **************************************************
|
***** mmc_deselect **************************************************
|
********************************************************************* */
|
********************************************************************* */
|
// de-select the card (CS) and waits if busy
|
// de-select the card (CS) and waits if busy
|
void mmc_deselect() {
|
void mmc_deselect() {
|
MMC_IO |= MMC_bmDI; // CS = 1
|
MMC_IO |= MMC_bmDI; // CS = 1
|
mmc_clocks(8); // 8 dummy clocks to finish a previous command
|
mmc_clocks(8); // 8 dummy clocks to finish a previous command
|
MMC_IO |= MMC_bmCS; // CS = 1
|
MMC_IO |= MMC_bmCS; // CS = 1
|
mmc_clocks(8); // 8 more dummy clocks
|
mmc_clocks(8); // 8 more dummy clocks
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** 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$
|
djnz r2, 010010$
|
djnz r2, 010010$
|
|
|
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
|
*/
|
*/
|
BYTE mmc_wait_start() {
|
BYTE mmc_wait_start() {
|
WORD to;
|
WORD to;
|
to=0;
|
to=0;
|
MMC_IO |= MMC_bmDI; // avoids that in-data is interpreted as command
|
MMC_IO |= MMC_bmDI; // avoids that in-data is interpreted as command
|
while ( flash_read_byte() != 0xfe ) { // wait for the start byte
|
while ( flash_read_byte() != 0xfe ) { // wait for the start byte
|
if ( ++to == 0 ) // 65536 * 8 clocks
|
if ( ++to == 0 ) // 65536 * 8 clocks
|
return 1;
|
return 1;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** 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 ) {
|
return FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
return FLASH_EC_PENDING; // we interrupted a pending Flash operation
|
}
|
}
|
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;
|
mmc_buffer[4] = 0;
|
mmc_buffer[4] = 0;
|
}
|
}
|
else {
|
else {
|
mmc_buffer[1] = s >> 24;
|
mmc_buffer[1] = s >> 24;
|
mmc_buffer[2] = s >> 16;
|
mmc_buffer[2] = s >> 16;
|
mmc_buffer[3] = s >> 8;
|
mmc_buffer[3] = s >> 8;
|
mmc_buffer[4] = s;
|
mmc_buffer[4] = s;
|
}
|
}
|
mmc_buffer[5] = 1;
|
mmc_buffer[5] = 1;
|
flash_write(mmc_buffer,6);
|
flash_write(mmc_buffer,6);
|
mmc_read_response();
|
mmc_read_response();
|
if ( mmc_response != 0 ) {
|
if ( mmc_response != 0 ) {
|
mmc_deselect();
|
mmc_deselect();
|
return FLASH_EC_CMD_ERROR;
|
return FLASH_EC_CMD_ERROR;
|
}
|
}
|
|
|
if ( mmc_wait_start() ) { // wait for the start byte
|
if ( mmc_wait_start() ) { // wait for the start byte
|
mmc_deselect();
|
mmc_deselect();
|
return FLASH_EC_TIMEOUT;
|
return FLASH_EC_TIMEOUT;
|
}
|
}
|
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.
|
*/
|
*/
|
void flash_read_finish(WORD n) {
|
void flash_read_finish(WORD n) {
|
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
|
}
|
}
|
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;
|
mmc_buffer[4] = 0;
|
mmc_buffer[4] = 0;
|
}
|
}
|
else {
|
else {
|
mmc_buffer[1] = s >> 24;
|
mmc_buffer[1] = s >> 24;
|
mmc_buffer[2] = s >> 16;
|
mmc_buffer[2] = s >> 16;
|
mmc_buffer[3] = s >> 8;
|
mmc_buffer[3] = s >> 8;
|
mmc_buffer[4] = s;
|
mmc_buffer[4] = s;
|
}
|
}
|
mmc_buffer[5] = 1;
|
mmc_buffer[5] = 1;
|
flash_write(mmc_buffer,6);
|
flash_write(mmc_buffer,6);
|
mmc_read_response();
|
mmc_read_response();
|
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
|
void flash_init() {
|
void flash_init() {
|
BYTE i, j, k;
|
BYTE i, j, k;
|
|
|
flash_enabled = 1;
|
flash_enabled = 1;
|
flash_sector_size = 512;
|
flash_sector_size = 512;
|
mmc_version = 0;
|
mmc_version = 0;
|
|
|
OEMMC_PORT = OEMMC_PORT | ( MMC_bmCS | MMC_bmDI | MMC_bmCLK );
|
OEMMC_PORT = OEMMC_PORT | ( MMC_bmCS | MMC_bmDI | MMC_bmCLK );
|
OEMMC__PORT_DO = OEMMC__PORT_DO & ~MMC_bmDO;
|
OEMMC__PORT_DO = OEMMC__PORT_DO & ~MMC_bmDO;
|
|
|
MMC_IO |= MMC_bmDI;
|
MMC_IO |= MMC_bmDI;
|
MMC_IO |= MMC_bmCS;
|
MMC_IO |= MMC_bmCS;
|
mmc_clocks(0); // 256 clocks
|
mmc_clocks(0); // 256 clocks
|
|
|
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);
|
if ( ( mmc_response & bmBIT2) == 0 ) {
|
if ( ( mmc_response & bmBIT2) == 0 ) {
|
if ( (mmc_response & 0xfe) != 0 )
|
if ( (mmc_response & 0xfe) != 0 )
|
goto mmc_init_cmd_err;
|
goto mmc_init_cmd_err;
|
flash_read(mmc_buffer,4);
|
flash_read(mmc_buffer,4);
|
if ( ( (mmc_buffer[2] & 15) != 1) || (mmc_buffer[3] != 0xaa ) ) {
|
if ( ( (mmc_buffer[2] & 15) != 1) || (mmc_buffer[3] != 0xaa ) ) {
|
flash_ec = FLASH_EC_NOTSUPPORTED;
|
flash_ec = FLASH_EC_NOTSUPPORTED;
|
goto mmc_init_err;
|
goto mmc_init_err;
|
}
|
}
|
mmc_version=1;
|
mmc_version=1;
|
}
|
}
|
|
|
// CMD1 is not recommended, therefore we try ACMD41 first
|
// CMD1 is not recommended, therefore we try ACMD41 first
|
k=mmc_version ? 64 : 0;
|
k=mmc_version ? 64 : 0;
|
mmc_send_cmd(55, 0.0.0.0, 0);
|
mmc_send_cmd(55, 0.0.0.0, 0);
|
if ( (mmc_response & 0xfe) == 0 )
|
if ( (mmc_response & 0xfe) == 0 )
|
mmc_send_cmd(41, k.0.0.0, 0);
|
mmc_send_cmd(41, k.0.0.0, 0);
|
j = mmc_response & 0xfe;
|
j = mmc_response & 0xfe;
|
|
|
for ( i=0; mmc_response != 0 && i<255; i++ ) { // send the init command and wait wait (up to 1s) until ready
|
for ( i=0; mmc_response != 0 && i<255; i++ ) { // send the init command and wait wait (up to 1s) until ready
|
wait(4);
|
wait(4);
|
if ( j ) {
|
if ( j ) {
|
mmc_send_cmd(1, k.0.0.0, 0xff);
|
mmc_send_cmd(1, k.0.0.0, 0xff);
|
}
|
}
|
else {
|
else {
|
mmc_send_cmd(55, 0.0.0.0, 0);
|
mmc_send_cmd(55, 0.0.0.0, 0);
|
mmc_send_cmd(41, k.0.0.0, 0);
|
mmc_send_cmd(41, k.0.0.0, 0);
|
}
|
}
|
}
|
}
|
if ( mmc_response != 0 ) { // check for errors
|
if ( mmc_response != 0 ) { // check for errors
|
goto mmc_init_cmd_err;
|
goto mmc_init_cmd_err;
|
}
|
}
|
|
|
if ( mmc_version ) {
|
if ( mmc_version ) {
|
mmc_send_cmd(58, 0.0.0.0, 0); // check the high capacity mode
|
mmc_send_cmd(58, 0.0.0.0, 0); // check the high capacity mode
|
if ( mmc_response != 0 ) // check for errors
|
if ( mmc_response != 0 ) // check for errors
|
goto mmc_init_cmd_err;
|
goto mmc_init_cmd_err;
|
flash_read(mmc_buffer,4);
|
flash_read(mmc_buffer,4);
|
if ( (mmc_buffer[0] & 64) == 0 ) // card in standard capacity mode
|
if ( (mmc_buffer[0] & 64) == 0 ) // card in standard capacity mode
|
mmc_version = 0;
|
mmc_version = 0;
|
}
|
}
|
|
|
mmc_send_cmd(9, 0.0.0.0, 0); // read the CSD
|
mmc_send_cmd(9, 0.0.0.0, 0); // read the CSD
|
if ( mmc_wait_start() ) {
|
if ( mmc_wait_start() ) {
|
flash_ec = FLASH_EC_TIMEOUT;
|
flash_ec = FLASH_EC_TIMEOUT;
|
goto mmc_init_err;
|
goto mmc_init_err;
|
}
|
}
|
flash_read(mmc_buffer,16);
|
flash_read(mmc_buffer,16);
|
mmc_clocks(16); // CRC is clocked out
|
mmc_clocks(16); // CRC is clocked out
|
|
|
mmc_buffer[0] &= 192;
|
mmc_buffer[0] &= 192;
|
if ( (mmc_buffer[0] & 192) == 0 ) {
|
if ( (mmc_buffer[0] & 192) == 0 ) {
|
i = (mmc_buffer[5] & 15) + ((mmc_buffer[10] >> 7) | ((mmc_buffer[9] & 3) << 1)) - 7;
|
i = (mmc_buffer[5] & 15) + ((mmc_buffer[10] >> 7) | ((mmc_buffer[9] & 3) << 1)) - 7;
|
flash_sectors = ((mmc_buffer[8] >> 6) | (mmc_buffer[7] << 2) | ((mmc_buffer[6] & 3) << 10)) + 1;
|
flash_sectors = ((mmc_buffer[8] >> 6) | (mmc_buffer[7] << 2) | ((mmc_buffer[6] & 3) << 10)) + 1;
|
flash_sectors = flash_sectors << i;
|
flash_sectors = flash_sectors << i;
|
}
|
}
|
else if ( (mmc_buffer[0] & 192) == 64 ) { // todo
|
else if ( (mmc_buffer[0] & 192) == 64 ) { // todo
|
flash_sectors = ( ( ((DWORD)(mmc_buffer[7] & 63) << 16) | (mmc_buffer[8] << 8) | mmc_buffer[9] ) +1 ) << 10;
|
flash_sectors = ( ( ((DWORD)(mmc_buffer[7] & 63) << 16) | (mmc_buffer[8] << 8) | mmc_buffer[9] ) +1 ) << 10;
|
}
|
}
|
else {
|
else {
|
flash_ec = FLASH_EC_NOTSUPPORTED;
|
flash_ec = FLASH_EC_NOTSUPPORTED;
|
goto mmc_init_err;
|
goto mmc_init_err;
|
}
|
}
|
|
|
flash_ec = 0;
|
flash_ec = 0;
|
mmc_deselect();
|
mmc_deselect();
|
|
|
return;
|
return;
|
|
|
mmc_init_cmd_err:
|
mmc_init_cmd_err:
|
flash_ec = FLASH_EC_CMD_ERROR;
|
flash_ec = FLASH_EC_CMD_ERROR;
|
mmc_init_err:
|
mmc_init_err:
|
flash_enabled = 0;
|
flash_enabled = 0;
|
mmc_deselect();
|
mmc_deselect();
|
}
|
}
|
|
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** EP0 vendor request 0x40 ***************************************
|
***** EP0 vendor request 0x40 ***************************************
|
********************************************************************* */
|
********************************************************************* */
|
// send mmc information structure (card size, error status, ...) to the host
|
// send mmc information structure (card size, error status, ...) to the host
|
ADD_EP0_VENDOR_REQUEST((0x40,,
|
ADD_EP0_VENDOR_REQUEST((0x40,,
|
MEM_COPY1(flash_enabled,EP0BUF,8);
|
MEM_COPY1(flash_enabled,EP0BUF,8);
|
EP0BCH = 0;
|
EP0BCH = 0;
|
EP0BCL = 8;
|
EP0BCL = 8;
|
,,
|
,,
|
));;
|
));;
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** 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
|
movx @dptr,a
|
movx @dptr,a
|
|
|
mov dptr,#(_SETUPDAT + 3)
|
mov dptr,#(_SETUPDAT + 3)
|
movx a,@dptr
|
movx a,@dptr
|
mov dptr,#(_mmc_buffer + 2)
|
mov dptr,#(_mmc_buffer + 2)
|
rlc a
|
rlc a
|
movx @dptr,a
|
movx @dptr,a
|
|
|
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];
|
mmc_buffer[3] = SETUPDAT[3];
|
mmc_buffer[3] = SETUPDAT[3];
|
mmc_buffer[4] = SETUPDAT[2];
|
mmc_buffer[4] = SETUPDAT[2];
|
}
|
}
|
mmc_buffer[5] = 1;
|
mmc_buffer[5] = 1;
|
flash_write(mmc_buffer,6);
|
flash_write(mmc_buffer,6);
|
mmc_read_response();
|
mmc_read_response();
|
if ( mmc_response != 0 ) {
|
if ( mmc_response != 0 ) {
|
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
|
movx @dptr,a
|
movx @dptr,a
|
|
|
mov dptr,#(_SETUPDAT + 3)
|
mov dptr,#(_SETUPDAT + 3)
|
movx a,@dptr
|
movx a,@dptr
|
mov dptr,#(_mmc_buffer + 2)
|
mov dptr,#(_mmc_buffer + 2)
|
rlc a
|
rlc a
|
movx @dptr,a
|
movx @dptr,a
|
|
|
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];
|
mmc_buffer[3] = SETUPDAT[3];
|
mmc_buffer[3] = SETUPDAT[3];
|
mmc_buffer[4] = SETUPDAT[2];
|
mmc_buffer[4] = SETUPDAT[2];
|
}
|
}
|
|
|
mmc_buffer[5] = 1;
|
mmc_buffer[5] = 1;
|
flash_write(mmc_buffer,6);
|
flash_write(mmc_buffer,6);
|
mmc_read_response();
|
mmc_read_response();
|
if ( mmc_response != 0 ) {
|
if ( mmc_response != 0 ) {
|
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 ) {
|
EP0_STALL;
|
EP0_STALL;
|
}
|
}
|
}
|
}
|
));;
|
));;
|
|
|
/* *********************************************************************
|
/* *********************************************************************
|
***** EP0 vendor request 0x43 ***************************************
|
***** EP0 vendor request 0x43 ***************************************
|
********************************************************************* */
|
********************************************************************* */
|
// send detailed MMC status plus debug information
|
// send detailed MMC status plus debug information
|
ADD_EP0_VENDOR_REQUEST((0x43,, // this may interrupt a pending operation
|
ADD_EP0_VENDOR_REQUEST((0x43,, // this may interrupt a pending operation
|
MEM_COPY1(flash_ec,EP0BUF+2,20);
|
MEM_COPY1(flash_ec,EP0BUF+2,20);
|
EP0BUF[22] = (MMC__IO_DO & MMC_bmDO) == 0;
|
EP0BUF[22] = (MMC__IO_DO & MMC_bmDO) == 0;
|
mmc_select();
|
mmc_select();
|
mmc_send_cmd(13, 0.0.0.0, 0);
|
mmc_send_cmd(13, 0.0.0.0, 0);
|
EP0BUF[0] = mmc_response;
|
EP0BUF[0] = mmc_response;
|
EP0BUF[1] = flash_read_byte();
|
EP0BUF[1] = flash_read_byte();
|
mmc_deselect();
|
mmc_deselect();
|
EP0BCH = 0;
|
EP0BCH = 0;
|
EP0BCL = 23;
|
EP0BCL = 23;
|
,,
|
,,
|
));;
|
));;
|
|
|
#endif /*ZTEX_FLASH1_H*/
|
#endif /*ZTEX_FLASH1_H*/
|
|
|