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 + -
显示快捷键?