sd_cmd.s
来自「Atmega64单片机程序(完整工程)」· S 代码 · 共 2,336 行 · 第 1/4 页
S
2,336 行
.module SD_Cmd.c
.area text(rom, con, rel)
; rlen -> y+4
; tmp -> R12
; i -> y+0
; resp -> R10,R11
; resptype -> R12
; param -> y+18
; cmd -> R14
.even
_SD_SendCmd::
st -y,r19
st -y,r18
xcall push_gset5
mov R14,R16
sbiw R28,8
ldd R12,y+20
ldd R10,y+22
ldd R11,y+23
; /*--------------File Info-------------------------------------------------------
; ** 文 件 名: SD_Cmd.c
; ** 最后修改日期: 2008.3.28
; ** 版 本: V1.0
; ** 描 述: sd 卡驱动软件包: SD卡物理层
; **------------------------------------------------------------------------------
; ** Created by:
; ** Created date:
; *******************************************************************************/
;
; #include "SYS_Config.h"
; #include "SD_Config.h"
; #include "SD_Hal.h"
; #include "SD_CRC.h"
; #include "SD_Cmd.h"
; #include "SD_Drive.h"
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_SendCmd()
; ** 功能描述: 向卡发送命令,并取得响应
; ** 输 入: INT8U cmd : 命令字
; INT8U *param : 命令参数,长度为4字节
; INT8U resptype : 响应类型
; INT8U *resp : 响应,长度为1-5字节
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; INT8U SD_SendCmd(INT8U cmd,INT8U *param,INT8U resptype,INT8U *resp)
; {
; INT32S i,rlen ;
; INT8U tmp ;
;
; SPI_CS_Assert();
xcall _SPI_CS_Assert
;
; SPI_SendByte((cmd&0x3F)|0x40);
mov R16,R14
andi R16,63
ori R16,64
xcall _SPI_SendByte
; /* 发送命令头和命令字 send command header and word */
;
; for(i=3;i>=0;i--)
ldi R20,3
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
std z+0,R20
std z+1,R21
std z+2,R22
std z+3,R23
L2:
movw R30,R28
push R26
push R27
ldd R26,z+0
ldd R27,z+1
movw R30,R26
pop R27
pop R26
ldd R0,y+18
ldd R1,y+19
add R30,R0
adc R31,R1
ldd R16,z+0
xcall _SPI_SendByte
L3:
ldi R20,1
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
sub R2,R20
sbc R3,R21
sbc R4,R22
sbc R5,R23
movw R30,R28
std z+0,R2
std z+1,R3
std z+2,R4
std z+3,R5
ldi R20,0
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
cp R2,R20
cpc R3,R21
cpc R4,R22
cpc R5,R23
brlt X2
xjmp L2
X2:
; SPI_SendByte(param[i]);
; /* 发送参数 send parameters */
;
; #if SD_CRC_EN
; tmp=SD_GetCmdByte6((cmd&0x3F)|0x40,param);
; SPI_SendByte(tmp);
; #else
; SPI_SendByte(0x95);
ldi R16,149
xcall _SPI_SendByte
; /* CRC校验码,只用于第1个命令 CRC,only used for the first command */
; #endif
;
; rlen=0 ;
ldi R20,0
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
std z+4,R20
std z+5,R21
std z+6,R22
std z+7,R23
; /* 根据不同的命令,得到不同的响应长度 */
; switch(resptype)
mov R14,R12
clr R15
movw R24,R14
cpi R24,1
ldi R30,0
cpc R25,R30
breq L9
cpi R24,2
ldi R30,0
cpc R25,R30
breq L9
cpi R24,3
ldi R30,0
cpc R25,R30
breq L10
cpi R24,4
ldi R30,0
cpc R25,R30
breq L11
xjmp L6
X0:
; {
L9:
; case R1 :
; case R1B:rlen=1 ;break ;
ldi R20,1
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
std z+4,R20
std z+5,R21
std z+6,R22
std z+7,R23
xjmp L7
L10:
; case R2 :rlen=2 ;break ;
ldi R20,2
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
std z+4,R20
std z+5,R21
std z+6,R22
std z+7,R23
xjmp L7
L11:
; case R3 :rlen=5 ;break ;
ldi R20,5
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
std z+4,R20
std z+5,R21
std z+6,R22
std z+7,R23
xjmp L7
L6:
; default :
; SPI_SendByte(0xFF);
ldi R16,255
xcall _SPI_SendByte
; SPI_CS_Deassert();
xcall _SPI_CS_Deassert
; return SD_ERR_CMD_RESPTYPE ; // 返回命令响应类型错误
ldi R16,16
xjmp L1
X1:
; break ;
L7:
; }
;
; i=0 ;
ldi R20,0
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
std z+0,R20
std z+1,R21
std z+2,R22
std z+3,R23
L12:
; /* 等待响应,响应的开始位为0 */
; do
; {
; /* Wait for a response,a response is a start bit(zero) */
; tmp=SPI_RecByte();
xcall _SPI_RecByte
mov R12,R16
; i++;
ldi R20,1
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
add R2,R20
adc R3,R21
adc R4,R22
adc R5,R23
movw R30,R28
std z+0,R2
std z+1,R3
std z+2,R4
std z+3,R5
; }
L13:
; while(((tmp&0x80)!=0)&&(i<SD_CMD_TIMEOUT));
sbrs R12,7
rjmp L15
ldi R20,255
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
cp R2,R20
cpc R3,R21
cpc R4,R22
cpc R5,R23
brlt L12
L15:
;
; if(i>=SD_CMD_TIMEOUT)
ldi R20,255
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
cp R2,R20
cpc R3,R21
cpc R4,R22
cpc R5,R23
brlt L16
; {
; SPI_CS_Deassert();
xcall _SPI_CS_Deassert
; return SD_ERR_CMD_TIMEOUT ;
ldi R16,17
xjmp L1
L16:
; /* 返回命令超时 return response timeout of command */
; }
;
; for(i=rlen-1;i>=0;i--)
ldi R20,1
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+4
ldd R3,z+5
ldd R4,z+6
ldd R5,z+7
sub R2,R20
sbc R3,R21
sbc R4,R22
sbc R5,R23
movw R30,R28
std z+0,R2
std z+1,R3
std z+2,R4
std z+3,R5
xjmp L21
L18:
movw R30,R28
push R26
push R27
ldd R26,z+0
ldd R27,z+1
movw R30,R26
pop R27
pop R26
add R30,R10
adc R31,R11
std z+0,R12
xcall _SPI_RecByte
mov R12,R16
L19:
ldi R20,1
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
sub R2,R20
sbc R3,R21
sbc R4,R22
sbc R5,R23
movw R30,R28
std z+0,R2
std z+1,R3
std z+2,R4
std z+3,R5
L21:
ldi R20,0
ldi R21,0
ldi R22,0
ldi R23,0
movw R30,R28
ldd R2,z+0
ldd R3,z+1
ldd R4,z+2
ldd R5,z+3
cp R2,R20
cpc R3,R21
cpc R4,R22
cpc R5,R23
brlt X3
xjmp L18
X3:
; {
; resp[i]=tmp ;
; tmp=SPI_RecByte();
; /* 循环的最后发送8clock at the last recycle,clock out 8 clock */
; }
;
; SPI_CS_Deassert();
xcall _SPI_CS_Deassert
; return SD_NO_ERR ;
clr R16
L1:
adiw R28,8
xcall pop_gset5
adiw R28,2
.dbline 0 ; func end
ret
; value -> y+2
; parameter -> R20,R21
.even
_SD_PackParam::
st -y,r19
st -y,r18
xcall push_gset1
movw R20,R16
; /* 返回执行成功 return perform sucessfully */
; }
;
; /*******************************************************************************
; ** 函数名称: void SD_PackParam()
; ** 功能描述: 将32位的参数转为字节形式
; ** 输 入: INT8U *parameter: 字节参数缓冲区
; INT32U value : 32位参数
; ** 输 出: 无
; *******************************************************************************/
; void SD_PackParam(INT8U *parameter,INT32U value)
; {
; parameter[3]=(INT8U)(value>>24);
ldi R24,24
ldi R25,0
movw R30,R28
ldd R2,z+2
ldd R3,z+3
ldd R4,z+4
ldd R5,z+5
st -y,R24
movw R16,R2
movw R18,R4
xcall lsr32
movw R30,R20
std z+3,R16
; parameter[2]=(INT8U)(value>>16);
movw R30,R28
ldd R2,z+2
ldd R3,z+3
ldd R4,z+4
ldd R5,z+5
movw R2,R4
clr R4
clr R5
movw R30,R20
std z+2,R2
; parameter[1]=(INT8U)(value>>8);
ldi R24,8
ldi R25,0
movw R30,R28
ldd R2,z+2
ldd R3,z+3
ldd R4,z+4
ldd R5,z+5
st -y,R24
movw R16,R2
movw R18,R4
xcall lsr32
movw R30,R20
std z+1,R16
; parameter[0]=(INT8U)(value);
movw R30,R28
ldd R2,z+2
ldd R3,z+3
ldd R4,z+4
ldd R5,z+5
movw R30,R20
std z+0,R2
L22:
xcall pop_gset1
adiw R28,2
.dbline 0 ; func end
ret
; resp -> y+8
; param -> y+4
; ret -> R20
; parameter -> y+13
; resptype -> R22
; cmd -> R20
.even
_SD_BlockCommand::
xcall push_gset2
mov R22,R18
mov R20,R16
sbiw R28,9
; }
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_BlockCommand()
; ** 功能描述: 块命令
; ** 输 入: INT8U cmd : 命令字
; INT8U resptype : 响应类型
; INT32U parameter: 块操作参数
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; INT8U SD_BlockCommand(INT8U cmd,INT8U resptype,INT32U parameter)
; {
; INT8U param[4],resp,ret ;
;
; parameter<<=SD_BLOCKSIZE_NBITS ;
ldi R24,9
ldi R25,0
movw R30,R28
ldd R2,z+13
ldd R3,z+14
ldd R4,z+15
ldd R5,z+16
st -y,R24
movw R16,R2
movw R18,R4
xcall lsl32
movw R30,R28
std z+13,R16
std z+14,R17
std z+15,R18
std z+16,R19
; /* 调整地址:左移9位 adjust address: move 9 bits left */
;
; SD_PackParam(param,parameter);
movw R30,R28
ldd R2,z+13
ldd R3,z+14
ldd R4,z+15
ldd R5,z+16
std y+0,R4
std y+1,R5
movw R18,R2
movw R16,R28
subi R16,252 ; offset = 4
sbci R17,255
xcall _SD_PackParam
; /* 将参数转化为字节形式 change the parameter to bytes form */
;
; ret=SD_SendCmd(cmd,param,resptype,&resp);
movw R24,R28
adiw R24,8
std y+3,R25
std y+2,R24
std y+0,R22
movw R18,R28
subi R18,252 ; offset = 4
sbci R19,255
mov R16,R20
xcall _SD_SendCmd
mov R20,R16
; if(ret!=SD_NO_ERR)
tst R16
breq L24
; return ret ;
xjmp L23
L24:
; /* 结束数据传输失败 stop transmission operation fail */
;
; if(resp!=0)
ldd R2,y+8
tst R2
breq L26
; return SD_ERR_CMD_RESP ;
ldi R16,18
xjmp L23
L26:
; /* 响应错误 response is error */
;
; return SD_NO_ERR ;
clr R16
L23:
adiw R28,9
xcall pop_gset2
.dbline 0 ; func end
ret
.area lit(rom, con, rel)
L29:
.byte 0,0
.byte 0,0
.area text(rom, con, rel)
; resp -> y+8
; param -> y+4
.even
_SD_ResetSD::
sbiw R28,9
; }
;
; /*************************************************
;
; 下面为SD卡SPI命令
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_ResetSD()
; ** 功能描述: 复位SD卡
; ** 输 入: 无
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; INT8U SD_ResetSD(void)
; {
; INT8U param[4]={0,0,0,0},resp ;
ldi R24,<L29
ldi R25,>L29
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?