瀏覽代碼

1.增加数据补传功能开发(RAM存储1小时)功能代码,未进行验证自测;
2.基于808透传传感器上报功能协议的合并

libo 2 年之前
父節點
當前提交
7724ade735
共有 16 個文件被更改,包括 3197 次插入0 次删除
  1. 19 0
      lib/c_template.c
  2. 23 0
      lib/c_template.h
  3. 119 0
      lib/lib_buffer.c
  4. 23 0
      lib/lib_buffer.h
  5. 117 0
      lib/lib_buffer_test.c
  6. 969 0
      obj/obj_sdmmc_sdcard.c
  7. 356 0
      obj/obj_sdmmc_sdcard.h
  8. 540 0
      obj/obj_spi_sd_stm32.c
  9. 53 0
      obj/obj_spi_sd_stm32.h
  10. 140 0
      sys/sys_api.c
  11. 83 0
      sys/sys_api.h
  12. 234 0
      sys/sys_delay.c
  13. 24 0
      sys/sys_delay.h
  14. 319 0
      sys/sys_malloc.c
  15. 115 0
      sys/sys_malloc.h
  16. 63 0
      sys/sys_type.h

+ 19 - 0
lib/c_template.c

@@ -0,0 +1,19 @@
+/*********************************************************
+//file		:hd_dev_gpio.c
+//author	:libo
+//date		:2020/05/10
+//version	:V1.0
+//brief		:GSP HARD²ãGPIO½Ó¿ÚCÎļþ
+*********************************************************/
+/* Includes-----------------------------------------------------------------------------------*/
+
+#ifdef HD_DEV_USE_ID
+/* Includes-----------------------------------------------------------------------------------*/
+
+/* Private macro------------------------------------------------------------------------------*/
+/* Private typedef----------------------------------------------------------------------------*/
+/* Private define-----------------------------------------------------------------------------*/
+/* Private variables--------------------------------------------------------------------------*/
+/* Private function prototypes----------------------------------------------------------------*/
+
+#endif    /*************HD_DEV_USE_ID*******************/

+ 23 - 0
lib/c_template.h

@@ -0,0 +1,23 @@
+/*********************************************************
+//file		:hd_dev_gpio.h
+//author	:libo
+//date		:2020/05/10
+//version	:V1.0
+//brief		:GSP HAL²ãGPIO½Ó¿ÚHÎļþ
+*********************************************************/
+#ifndef HD_DEV_ID_H
+#define HD_DEV_ID_H
+
+/* Includes----------------------------------------------------------------------------------*/
+
+/* Public macro------------------------------------------------------------------------------*/
+
+/* Public define-----------------------------------------------------------------------------*/
+
+/* Public typedef----------------------------------------------------------------------------*/
+
+/* public function---------------------------------------------------------------------------*/
+
+#endif    /*********HD_DEV_ID_H****************/
+/******************************the end of file************************************************/
+

+ 119 - 0
lib/lib_buffer.c

@@ -0,0 +1,119 @@
+#include "stdio.h"
+#include "string.h"
+#include "stdlib.h"
+#include "lib_buffer.h"
+#define validLen (Object->push_size - Object->pop_size)    //缓冲区有效长度
+
+TBufffer TBuffer_Init(TBuffferOBJ *data, void *buffer, int buff_size)
+{
+    TBufffer result = NULL;
+    if (data != NULL && buffer != NULL && buff_size > 0)
+    {
+        data->pHead = buffer;
+        data->size = buff_size;
+        data->pTail = data->pHead + buff_size;
+        data->pValid = data->pHead;
+        data->pValidTail = data->pHead;
+        data->push_size = 0;
+        data->pop_size = 0;
+        result = data;
+    }
+    return result;
+}
+
+void TBuffer_Fini(TBuffferOBJ *data)
+{
+    if (data != NULL)
+    {
+        data->pValid = data->pValidTail = data->pHead;
+        data->pop_size = data->push_size;
+    }    
+}
+
+int TBuffer_Push(TBufffer Object, const void *data, int size)
+{
+    int result = 0;
+    int _ValidLength = Object->push_size - Object->pop_size;
+    int _Size = Object->size - _ValidLength;    //实际可用 为0?
+    if (data == NULL)
+        result = -1;
+    else if (size > 0 && _Size > 0) //保留原本不能丢弃
+    {
+        if (_Size < size)
+            size = _Size;
+        result = size;
+        if (Object->pValidTail + size > Object->pTail)//写入之后超出缓冲区 分两段
+        {
+            int rest = Object->pTail - Object->pValidTail;
+            memcpy(Object->pValidTail, data, rest);
+            memcpy(Object->pHead, (char *)data + rest, size - rest);
+            Object->pValidTail = Object->pHead + size - rest;
+        }
+        else
+        {
+            memcpy(Object->pValidTail, data, size);
+            Object->pValidTail += size;
+            if (Object->pValidTail == Object->pTail)
+                Object->pValidTail = Object->pHead;
+        }
+        Object->push_size += result;
+    }
+    // printf(" push = %s\n", Object->pHead);  
+    return result;
+}
+
+int TBuffer_Peek(TBufffer Object, void *data, int size)//返回实际尺寸
+{
+    int result = 0;
+    if (data == NULL)
+        result = -1;
+    else if (size > 0 && Object->pop_size != Object->push_size)
+    {
+        int _ValidLength = Object->push_size - Object->pop_size;
+        if (size > _ValidLength)//可能会push validLen变大 导致size变大越界
+            size = _ValidLength;
+        if (Object->pValid + size > Object->pTail)//需要分成两段copy
+        {
+            int rest = Object->pTail - Object->pValid;
+            memcpy(data, Object->pValid, rest);
+            memcpy((char*)data + rest, Object->pHead, size - rest);//第二段,绕到整个存储区的开头
+        }
+        else
+        {
+            memcpy(data, Object->pValid, size);
+        }
+        result = size;
+    }
+    return result;
+}
+
+int TBuffer_Pop(TBufffer Object, void *data, int size)                                                                        
+{
+    int result = 0;
+    if (data == NULL)
+        result = -1;
+    else if (size > 0 && Object->pop_size != Object->push_size)
+    {
+        int _ValidLength = Object->push_size - Object->pop_size;
+        if (size > _ValidLength)//可能会push validLen变大 导致size变大越界
+            size = _ValidLength;
+        if (Object->pValid + size > Object->pTail)//需要分成两段copy
+        {
+            int rest = Object->pTail - Object->pValid;
+            memcpy(data, Object->pValid, rest);
+            memcpy((char*)data + rest, Object->pHead, size - rest);//第二段,绕到整个存储区的开头
+            Object->pValid = Object->pHead + size - rest;//更新已使用缓冲区的起始
+        }
+        else
+        {
+            memcpy(data, Object->pValid, size);
+            Object->pValid = Object->pValid + size;
+            if (Object->pValid == Object->pTail)
+                Object->pValid = Object->pHead;
+        }
+        result = size;
+        Object->pop_size += result;
+    }
+    // printf("pop = %s\n",(char*)data);   
+    return result;
+}

+ 23 - 0
lib/lib_buffer.h

@@ -0,0 +1,23 @@
+#ifndef __BUFFER
+#define __BUFFER
+
+
+typedef struct
+{
+    unsigned char  *pHead;//环形存储区的首地址
+    unsigned char  *pTail;//环形存储区的结尾地址   
+    unsigned char  *pValid;//已使用的缓冲区的首地址
+    unsigned char  *pValidTail;//已使用的缓冲区的尾地址
+    unsigned int pop_size;
+    unsigned int push_size;
+    unsigned int   size;
+} TBuffferOBJ;
+
+typedef TBuffferOBJ* TBufffer;
+
+TBufffer TBuffer_Init(TBuffferOBJ *data, void *buffer, int buff_size);
+void TBuffer_Fini(TBuffferOBJ *data);
+int TBuffer_Push(TBufffer Object, const void *data, int size);
+int TBuffer_Peek(TBufffer Object, void *data, int size); //返回实际尺寸
+int TBuffer_Pop(TBufffer Object, void *data, int size);
+#endif 

+ 117 - 0
lib/lib_buffer_test.c

@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "signal.h"
+#include "lib_buffer.h"
+#include "cmsis_os.h"
+//用push_count 压入
+//检查pop_count-push_count ? 
+//错误休眠
+//错误打印信息
+//数据流连续压入 不能断开
+char str[20] = {'1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','w','a','1','2','3'};
+
+bool run_over = false;
+
+void sighandler(int signum)
+{
+    run_over = true;
+}
+
+void *push(void *arg)
+{
+    int RetSize = 0;
+    int Push_Ptr = 0;
+    TBufffer tmp = (TBufffer)arg;
+    if (tmp != NULL)
+    {
+        while (!run_over)
+        {
+            RetSize = TBuffer_Push(tmp, str + Push_Ptr, sizeof(str) - Push_Ptr);
+            if (RetSize < sizeof(str) - Push_Ptr)
+            {
+                Push_Ptr += RetSize;
+                osDelay(1);   
+            }
+            else
+                Push_Ptr = 0;
+        }
+    }
+    else
+        printf("TBuffferOBJ  ERR");
+    return NULL;
+}
+
+
+void *pop(void *arg)
+{
+    char buf[10];
+    int RetSize = 0;
+    int Pop_Ptr = 0;
+    TBufffer tmp = (TBufffer)arg;
+    if (tmp != NULL)
+    {
+       while (!run_over)
+       {
+            RetSize = TBuffer_Pop(tmp, buf, sizeof(buf) - 1);//size?
+            if (RetSize == 0)   //无有效数据
+               osDelay(1);
+            else        //检查
+            {
+                // char str[20] = {'1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','w','a','1','2','3'};
+                //1.开始比较 比较完之后 Pop_Ptr指针往后移动RetSize
+                //2.需要回到模板头部时 即 RetSize > sizeof(str) - Pop_Ptr 
+                //分成两部分比较 第一部分比较 (sizeof(str) - Pop_Ptr)个长度,Pop_Ptr清零
+                //第二部分比较 RetSize - (sizeof(str) - Pop_Ptr)个长度
+                if (RetSize > sizeof(str) - Pop_Ptr)
+                {
+                    int PreSize = sizeof(str) - Pop_Ptr;
+                    if (memcmp(str + Pop_Ptr, buf, PreSize) != 0 || memcmp(str, buf + PreSize, RetSize - PreSize) != 0)//?
+                    {
+                        puts("ERR 1");
+                        run_over = true;
+                    }
+                    Pop_Ptr = RetSize - PreSize;
+                }
+                else
+                {
+                    if (memcmp(str + Pop_Ptr, buf, RetSize) != 0)
+                    {
+                        puts("ERR 2");
+                        run_over = true;
+                    }
+                    Pop_Ptr += RetSize;//到头处理
+                    if (Pop_Ptr == sizeof(str))
+                        Pop_Ptr = 0;
+                }
+            }
+        }        
+    }
+    else
+       printf("TBuffferOBJ ERR");
+    return NULL;
+}
+#if 0
+TBuffferOBJ _data;
+
+
+int main() 
+{
+     char buf[16];
+      TBufffer tmp = TBuffer_Init(&_data, buf, sizeof(buf));
+    if (tmp != NULL)
+    {
+        pthread_t th1, th2;
+        signal(SIGINT, sighandler);
+        pthread_create(&th1, NULL, push, tmp);
+        pthread_create(&th2, NULL, pop, tmp);
+        
+        pthread_join(th1, NULL);
+        pthread_join(th2, NULL);
+    }
+    else
+        printf("Failed to initialize");
+    return 0;
+}     
+#endif

+ 969 - 0
obj/obj_sdmmc_sdcard.c

@@ -0,0 +1,969 @@
+#ifdef USE_SDIO_SD
+#include "obj_sdmmc_sdcard.h"
+#include "string.h"  
+#include "usart.h"	 
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//SDMMC 驱动代码	(仅提供查询模式驱动代码)
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2018/7/31
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved		 
+//********************************************************************************
+//升级说明
+//无
+////////////////////////////////////////////////////////////////////////////////// 	 
+static u8 CardType=STD_CAPACITY_SD_CARD_V1_1;			//SD卡类型(默认为1.x卡)
+static u32 CSD_Tab[4],CID_Tab[4],RCA=0;					//SD卡CSD,CID以及相对地址(RCA)数据
+SD_CardInfo SDCardInfo;									//SD卡信息
+
+//SD_ReadDisk/SD_WriteDisk函数专用buf,当这两个函数的数据缓存区地址不是4字节对齐的时候,
+//需要用到该数组,确保数据缓存区地址是4字节对齐的.
+__align(4) u8 SDMMC_DATA_BUFFER[512];						  
+ 
+
+//初始化SD卡
+//返回值:错误代码;(0,无错误)
+SD_Error SD_Init(void)
+{
+	SD_Error errorstatus=SD_OK;	  
+	u8 clkdiv=0;
+	//SDMMC1 IO口初始化   	 
+    GPIO_InitTypeDef GPIO_Initure;
+
+    __HAL_RCC_SDMMC1_CLK_ENABLE();  //使能SDMMC1时钟
+    __HAL_RCC_GPIOC_CLK_ENABLE();   //使能GPIOC时钟
+    __HAL_RCC_GPIOD_CLK_ENABLE();   //使能GPIOD时钟
+/*    
+    //PC8,9,10,11,12
+    GPIO_Initure.Pin=GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
+    GPIO_Initure.Mode=GPIO_MODE_AF_PP;      //推挽复用
+    GPIO_Initure.Pull=GPIO_NOPULL;          //无上下拉
+    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;     //高速
+    GPIO_Initure.Alternate=GPIO_AF12_SDIO; //复用为SDIO
+    HAL_GPIO_Init(GPIOC,&GPIO_Initure);     //初始化
+    
+    //PD2
+    GPIO_Initure.Pin=GPIO_PIN_2;            
+    HAL_GPIO_Init(GPIOD,&GPIO_Initure);     //初始化
+*/
+
+		 
+		//SDIO_DAT0 							PB14
+		//RMII_TXD1&SDIO_CLK  		PB13
+		//SDIO_CMD 								PB15
+		//RMII_TXD0&SDIO_CD/DAT3 	PB12
+
+    GPIO_Initure.Pin=GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
+    GPIO_Initure.Mode=GPIO_MODE_AF_PP;      //推挽复用
+    GPIO_Initure.Pull=GPIO_NOPULL;          //无上下拉
+    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;     //高速
+    GPIO_Initure.Alternate=GPIO_AF12_SDIO; //复用为SDIO
+    HAL_GPIO_Init(GPIOC,&GPIO_Initure);     //初始化
+    
+    //SDIO-nCD	 	PD8   
+    GPIO_Initure.Pin=GPIO_PIN_8;            
+    HAL_GPIO_Init(GPIOD,&GPIO_Initure);     //初始化
+		
+ 	//SDMMC外设寄存器设置为默认值 			   
+	SDMMC1->POWER=0x00000000;
+	SDMMC1->CLKCR=0x00000000;
+	SDMMC1->ARG=0x00000000;
+	SDMMC1->CMD=0x00000000;
+	SDMMC1->DTIMER=0x00000000;
+	SDMMC1->DLEN=0x00000000;
+	SDMMC1->DCTRL=0x00000000;
+	SDMMC1->ICR=0X1FE00FFF;
+	SDMMC1->MASK=0x00000000;	  
+
+    HAL_NVIC_SetPriority(SDMMC1_IRQn,2,0);  //配置SDMMC1中断,抢占优先级2,子优先级0
+    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断
+    
+   	errorstatus=SD_PowerON();			//SD卡上电
+ 	if(errorstatus==SD_OK)errorstatus=SD_InitializeCards();			//初始化SD卡														  
+  	if(errorstatus==SD_OK)errorstatus=SD_GetCardInfo(&SDCardInfo);	//获取卡信息
+ 	if(errorstatus==SD_OK)errorstatus=SD_SelectDeselect((u32)(SDCardInfo.RCA<<16));//选中SD卡   
+   	if(errorstatus==SD_OK)errorstatus=SD_EnableWideBusOperation(1);	//4位宽度,如果是MMC卡,则不能用4位模式 
+  	if((errorstatus==SD_OK)||(MULTIMEDIA_CARD==CardType))
+	{  		    
+		if(SDCardInfo.CardType==STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==STD_CAPACITY_SD_CARD_V2_0)
+		{
+			clkdiv=SDMMC_TRANSFER_CLK_DIV+2;	//V1.1/V2.0卡,设置最高48/4=12Mhz
+		}else clkdiv=SDMMC_TRANSFER_CLK_DIV;	//SDHC等其他卡,设置最高48/2=24Mhz
+		SDMMC_Clock_Set(clkdiv);	//设置时钟频率,SDMMC时钟计算公式:SDMMC_CK时钟=SDMMCCLK/[clkdiv+2];其中,SDMMCCLK固定为48Mhz 
+  	}
+	return errorstatus;		 
+}
+//SDMMC时钟初始化设置
+//clkdiv:时钟分频系数
+//CK时钟=sdmmc_ker_ck/[2*clkdiv];(sdmmc_ker_ck钟固定为400Mhz)
+void SDMMC_Clock_Set(u16 clkdiv)
+{
+	u32 tmpreg=SDMMC1->CLKCR; 
+  	tmpreg&=0XFFFFFC00; 
+ 	tmpreg|=clkdiv;   
+	SDMMC1->CLKCR=tmpreg;
+} 
+//SDMMC发送命令函数
+//cmdindex:命令索引,低六位有效
+//waitrsp:期待的相应.00/10,无响应;01,短响应;11,长响应
+//arg:参数
+void SDMMC_Send_Cmd(u8 cmdindex,u8 waitrsp,u32 arg)
+{			
+	u32 tmpreg=0;
+	SDMMC1->ARG=arg;  
+	tmpreg|=cmdindex&0X3F;	//设置新的index			 
+	tmpreg|=(u32)waitrsp<<8;//设置新的wait rsp 
+	tmpreg|=0<<10;			//无等待
+  	tmpreg|=1<<12;			//命令通道状态机使能
+	SDMMC1->CMD=tmpreg;
+}
+//SDMMC发送数据配置函数
+//datatimeout:超时时间设置
+//datalen:传输数据长度,低25位有效,必须为块大小的整数倍
+//blksize:块大小.实际大小为:2^blksize字节
+//dir:数据传输方向:0,控制器到卡;1,卡到控制器;
+void SDMMC_Send_Data_Cfg(u32 datatimeout,u32 datalen,u8 blksize,u8 dir)
+{
+	u32 tmpreg;
+	SDMMC1->DTIMER=datatimeout;
+  	SDMMC1->DLEN=datalen&0X1FFFFFF;	//低25位有效
+	tmpreg=SDMMC1->DCTRL; 
+	tmpreg&=0xFFFFFF00;		//清除之前的设置.
+	tmpreg|=blksize<<4;		//设置块大小
+	tmpreg|=0<<2;			//块数据传输
+	tmpreg|=(dir&0X01)<<1;	//方向控制
+	tmpreg|=1<<0;			//数据传输使能,DPSM状态机
+	SDMMC1->DCTRL=tmpreg;		
+}  
+
+//卡上电
+//查询所有SDMMC接口上的卡设备,并查询其电压和配置时钟
+//返回值:错误代码;(0,无错误)
+SD_Error SD_PowerON(void)
+{
+ 	u8 i=0;
+	u32 tempreg=0;
+	SD_Error errorstatus=SD_OK;
+	u32 response=0,count=0,validvoltage=0;
+	u32 SDType=SD_STD_CAPACITY;
+	//配置CLKCR寄存器  
+	tempreg|=0<<12;				//PWRSAV=0,非省电模式 
+	tempreg|=0<<14;				//WIDBUS[1:0]=0,1位数据宽度
+	tempreg|=0<<16;				//NEGEDGE=0,SDMMCCK下降沿更改命令和数据
+	tempreg|=0<<17;				//HWFC_EN=0,关闭硬件流控制    
+	SDMMC1->CLKCR=tempreg; 
+	SDMMC_Clock_Set(SDMMC_INIT_CLK_DIV);//设置时钟频率(初始化的时候,不能超过400Khz)			 
+ 	SDMMC1->POWER=0X03;			//上电状态,开启卡时钟     
+   	for(i=0;i<74;i++)
+	{
+		SDMMC_Send_Cmd(SD_CMD_GO_IDLE_STATE,0,0);//发送CMD0进入IDLE STAGE模式命令.												  
+		errorstatus=CmdError();
+		if(errorstatus==SD_OK)break;
+ 	}
+ 	if(errorstatus)return errorstatus;//返回错误状态
+	SDMMC_Send_Cmd(SD_SDMMC_SEND_IF_COND,1,SD_CHECK_PATTERN);//发送CMD8,短响应,检查SD卡接口特性.
+ 														//arg[11:8]:01,支持电压范围,2.7~3.6V
+														//arg[7:0]:默认0XAA
+														//返回响应7
+  	errorstatus=CmdResp7Error();						//等待R7响应
+ 	if(errorstatus==SD_OK) 								//R7响应正常
+	{
+		CardType=STD_CAPACITY_SD_CARD_V2_0;				//SD 2.0卡
+		SDType=SD_HIGH_CAPACITY;			   			//高容量卡
+	}
+	SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,0);					//发送CMD55,短响应	 
+	errorstatus=CmdResp1Error(SD_CMD_APP_CMD); 		 	//等待R1响应   
+	if(errorstatus==SD_OK)//SD2.0/SD 1.1,否则为MMC卡
+	{																  
+		//SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000 
+		while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
+		{	   										   
+			SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,0);				//发送CMD55,短响应	 
+			errorstatus=CmdResp1Error(SD_CMD_APP_CMD); 	 	//等待R1响应   
+ 			if(errorstatus!=SD_OK)return errorstatus;   	//响应错误
+			SDMMC_Send_Cmd(SD_CMD_SD_APP_OP_COND,1,SD_VOLTAGE_WINDOW_SD|SDType);//发送ACMD41,短响应	 
+			errorstatus=CmdResp3Error(); 					//等待R3响应   
+ 			if(errorstatus!=SD_OK)return errorstatus;   	//响应错误  
+			response=SDMMC1->RESP1;;			   				//得到响应
+			validvoltage=(((response>>31)==1)?1:0);			//判断SD卡上电是否完成
+			count++;
+		}
+		if(count>=SD_MAX_VOLT_TRIAL)
+		{
+			errorstatus=SD_INVALID_VOLTRANGE;
+			return errorstatus;
+		}	 
+		if(response&=SD_HIGH_CAPACITY)
+		{
+			CardType=HIGH_CAPACITY_SD_CARD;
+		}
+ 	}else//MMC卡
+	{
+		//MMC卡,发送CMD1 SDMMC_SEND_OP_COND,参数为:0x80FF8000 
+		while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
+		{	   										   				   
+			SDMMC_Send_Cmd(SD_CMD_SEND_OP_COND,1,SD_VOLTAGE_WINDOW_MMC);//发送CMD1,短响应	 
+			errorstatus=CmdResp3Error(); 					//等待R3响应   
+ 			if(errorstatus!=SD_OK)return errorstatus;   	//响应错误  
+			response=SDMMC1->RESP1;;			   				//得到响应
+			validvoltage=(((response>>31)==1)?1:0);
+			count++;
+		}
+		if(count>=SD_MAX_VOLT_TRIAL)
+		{
+			errorstatus=SD_INVALID_VOLTRANGE;
+			return errorstatus;
+		}	 			    
+		CardType=MULTIMEDIA_CARD;	  
+  	}  
+  	return(errorstatus);		
+}
+//SD卡 Power OFF
+//返回值:错误代码;(0,无错误)
+SD_Error SD_PowerOFF(void)
+{
+  	SDMMC1->POWER&=~(3<<0);//SDMMC电源关闭,时钟停止	
+	return SD_OK;		  
+}   
+//初始化所有的卡,并让卡进入就绪状态
+//返回值:错误代码
+SD_Error SD_InitializeCards(void)
+{
+ 	SD_Error errorstatus=SD_OK;
+	u16 rca = 0x01;
+ 	if((SDMMC1->POWER&0X03)==0)return SD_REQUEST_NOT_APPLICABLE;//检查电源状态,确保为上电状态
+ 	if(SECURE_DIGITAL_IO_CARD!=CardType)				//非SECURE_DIGITAL_IO_CARD
+	{
+		SDMMC_Send_Cmd(SD_CMD_ALL_SEND_CID,3,0);		//发送CMD2,取得CID,长响应	 
+		errorstatus=CmdResp2Error(); 					//等待R2响应   
+		if(errorstatus!=SD_OK)return errorstatus;   	//响应错误		    
+ 		CID_Tab[0]=SDMMC1->RESP1;
+		CID_Tab[1]=SDMMC1->RESP2;
+		CID_Tab[2]=SDMMC1->RESP3;
+		CID_Tab[3]=SDMMC1->RESP4;
+	}
+	if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(SECURE_DIGITAL_IO_COMBO_CARD==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))//判断卡类型
+	{
+		SDMMC_Send_Cmd(SD_CMD_SET_REL_ADDR,1,0);			//发送CMD3,短响应 
+		errorstatus=CmdResp6Error(SD_CMD_SET_REL_ADDR,&rca);//等待R6响应 
+		if(errorstatus!=SD_OK)return errorstatus;   	//响应错误		    
+	}   
+    if (MULTIMEDIA_CARD==CardType)
+    {
+ 		SDMMC_Send_Cmd(SD_CMD_SET_REL_ADDR,1,(u32)(rca<<16));//发送CMD3,短响应 	   
+		errorstatus=CmdResp2Error(); 					//等待R2响应   
+		if(errorstatus!=SD_OK)return errorstatus;   	//响应错误	 
+    }
+	if (SECURE_DIGITAL_IO_CARD!=CardType)			//非SECURE_DIGITAL_IO_CARD
+	{
+		RCA = rca;
+		SDMMC_Send_Cmd(SD_CMD_SEND_CSD,3,(u32)(rca<<16));//发送CMD9+卡RCA,取得CSD,长响应 	   
+		errorstatus=CmdResp2Error(); 					//等待R2响应   
+		if(errorstatus!=SD_OK)return errorstatus;   	//响应错误		    
+  		CSD_Tab[0]=SDMMC1->RESP1;
+		CSD_Tab[1]=SDMMC1->RESP2;
+		CSD_Tab[2]=SDMMC1->RESP3;						
+		CSD_Tab[3]=SDMMC1->RESP4;					    
+	}
+	return SD_OK;//卡初始化成功
+} 
+//得到卡信息
+//cardinfo:卡信息存储区
+//返回值:错误状态
+SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
+{
+ 	SD_Error errorstatus=SD_OK;
+	u8 tmp=0;	   
+	cardinfo->CardType=(u8)CardType; 				//卡类型
+	cardinfo->RCA=(u16)RCA;							//卡RCA值
+	tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
+	cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6;		//CSD结构
+	cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2;	//2.0协议还没定义这部分(为保留),应该是后续协议定义的
+	cardinfo->SD_csd.Reserved1=tmp&0x03;			//2个保留位  
+	tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16);			//第1个字节
+	cardinfo->SD_csd.TAAC=tmp;				   		//数据读时间1
+	tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8);	  		//第2个字节
+	cardinfo->SD_csd.NSAC=tmp;		  				//数据读时间2
+	tmp=(u8)(CSD_Tab[0]&0x000000FF);				//第3个字节
+	cardinfo->SD_csd.MaxBusClkFrec=tmp;		  		//传输速度	   
+	tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24);			//第4个字节
+	cardinfo->SD_csd.CardComdClasses=tmp<<4;    	//卡指令类高四位
+	tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16);	 		//第5个字节
+	cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
+	cardinfo->SD_csd.RdBlockLen=tmp&0x0F;	    	//最大读取数据长度
+	tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8);			//第6个字节
+	cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7;	//允许分块读
+	cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6;	//写块错位
+	cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5;	//读块错位
+	cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
+	cardinfo->SD_csd.Reserved2=0; 					//保留
+ 	if((CardType==STD_CAPACITY_SD_CARD_V1_1)||(CardType==STD_CAPACITY_SD_CARD_V2_0)||(MULTIMEDIA_CARD==CardType))//标准1.1/2.0卡/MMC卡
+	{
+		cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10;	//C_SIZE(12位)
+	 	tmp=(u8)(CSD_Tab[1]&0x000000FF); 			//第7个字节	
+		cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
+ 		tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);		//第8个字节	
+		cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
+ 		cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
+		cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
+ 		tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);		//第9个字节	
+		cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
+		cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
+		cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
+ 		tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);	  	//第10个字节	
+		cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
+ 		cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
+		cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
+		cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
+		cardinfo->CardCapacity*=cardinfo->CardBlockSize;
+	}else if(CardType==HIGH_CAPACITY_SD_CARD)	//高容量卡
+	{
+ 		tmp=(u8)(CSD_Tab[1]&0x000000FF); 		//第7个字节	
+		cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
+ 		tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24); 	//第8个字节	
+ 		cardinfo->SD_csd.DeviceSize|=(tmp<<8);
+ 		tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);	//第9个字节	
+ 		cardinfo->SD_csd.DeviceSize|=(tmp);
+ 		tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8); 	//第10个字节	
+ 		cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
+		cardinfo->CardBlockSize=512; 			//块大小固定为512字节
+	}	  
+	cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
+	cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;	   
+	tmp=(u8)(CSD_Tab[2]&0x000000FF);			//第11个字节	
+	cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
+	cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
+ 	tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24);		//第12个字节	
+	cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
+	cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
+	cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
+	cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;	 
+	tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16);		//第13个字节
+	cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
+	cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
+	cardinfo->SD_csd.Reserved3=0;
+	cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);  
+	tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8);		//第14个字节
+	cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
+	cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
+	cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
+	cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
+	cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
+	cardinfo->SD_csd.ECC=(tmp&0x03);  
+	tmp=(u8)(CSD_Tab[3]&0x000000FF);			//第15个字节
+	cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
+	cardinfo->SD_csd.Reserved4=1;		 
+	tmp=(u8)((CID_Tab[0]&0xFF000000)>>24);		//第0个字节
+	cardinfo->SD_cid.ManufacturerID=tmp;		    
+	tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16);		//第1个字节
+	cardinfo->SD_cid.OEM_AppliID=tmp<<8;	  
+	tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8);		//第2个字节
+	cardinfo->SD_cid.OEM_AppliID|=tmp;	    
+	tmp=(u8)(CID_Tab[0]&0x000000FF);			//第3个字节	
+	cardinfo->SD_cid.ProdName1=tmp<<24;				  
+	tmp=(u8)((CID_Tab[1]&0xFF000000)>>24); 		//第4个字节
+	cardinfo->SD_cid.ProdName1|=tmp<<16;	  
+	tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16);	   	//第5个字节
+	cardinfo->SD_cid.ProdName1|=tmp<<8;		 
+	tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8);		//第6个字节
+	cardinfo->SD_cid.ProdName1|=tmp;		   
+	tmp=(u8)(CID_Tab[1]&0x000000FF);	  		//第7个字节
+	cardinfo->SD_cid.ProdName2=tmp;			  
+	tmp=(u8)((CID_Tab[2]&0xFF000000)>>24); 		//第8个字节
+	cardinfo->SD_cid.ProdRev=tmp;		 
+	tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16);		//第9个字节
+	cardinfo->SD_cid.ProdSN=tmp<<24;	   
+	tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8); 		//第10个字节
+	cardinfo->SD_cid.ProdSN|=tmp<<16;	   
+	tmp=(u8)(CID_Tab[2]&0x000000FF);   			//第11个字节
+	cardinfo->SD_cid.ProdSN|=tmp<<8;		   
+	tmp=(u8)((CID_Tab[3]&0xFF000000)>>24); 		//第12个字节
+	cardinfo->SD_cid.ProdSN|=tmp;			     
+	tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16);	 	//第13个字节
+	cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
+	cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;    
+	tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8);		//第14个字节
+	cardinfo->SD_cid.ManufactDate|=tmp;		 	  
+	tmp=(u8)(CID_Tab[3]&0x000000FF);			//第15个字节
+	cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
+	cardinfo->SD_cid.Reserved2=1;	 
+	return errorstatus;
+}
+//设置SDMMC总线宽度(MMC卡不支持4bit模式)
+//wmode:位宽模式.0,1位数据宽度;1,4位数据宽度;2,8位数据宽度
+//返回值:SD卡错误状态
+SD_Error SD_EnableWideBusOperation(u32 wmode)
+{
+  	SD_Error errorstatus=SD_OK;
+	u16 clkcr=0;
+  	if(MULTIMEDIA_CARD==CardType)return SD_UNSUPPORTED_FEATURE;//MMC卡不支持
+ 	else if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
+	{
+		if(wmode>=2)return SD_UNSUPPORTED_FEATURE;//不支持8位模式
+ 		else   
+		{
+			errorstatus=SDEnWideBus(wmode);
+ 			if(SD_OK==errorstatus)
+			{
+				clkcr=SDMMC1->CLKCR;	//读取CLKCR的值
+				clkcr&=~(3<<14);		//清除之前的位宽设置    
+				clkcr|=(u32)wmode<<14;	//1位/4位总线宽度 
+				clkcr|=0<<17;			//不开启硬件流控制
+				SDMMC1->CLKCR=clkcr;	//重新设置CLKCR值 
+			}
+		}  
+	} 
+	return errorstatus; 
+} 
+//选卡
+//发送CMD7,选择相对地址(rca)为addr的卡,取消其他卡.如果为0,则都不选择.
+//addr:卡的RCA地址
+SD_Error SD_SelectDeselect(u32 addr)
+{
+ 	SDMMC_Send_Cmd(SD_CMD_SEL_DESEL_CARD,1,addr);	//发送CMD7,选择卡,短响应	 	   
+   	return CmdResp1Error(SD_CMD_SEL_DESEL_CARD);	  
+}  
+//SD卡读取单个/多个块 
+//buf:读数据缓存区
+//addr:读取地址
+//blksize:块大小
+//nblks:要读取的块数,1,表示读取单个块
+//返回值:错误状态 
+SD_Error SD_ReadBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks)
+{
+  	SD_Error errorstatus=SD_OK; 
+   	u32 count=0;
+	u32 timeout=SDMMC_DATATIMEOUT;  
+	u32 *tempbuff=(u32*)buf;	//转换为u32指针 
+    SDMMC1->DCTRL=0x0;			//数据控制寄存器清零(关DMA)   
+	if(CardType==HIGH_CAPACITY_SD_CARD)//大容量卡
+	{
+		blksize=512;
+		addr>>=9;
+	}     
+	SDMMC_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize);			//发送CMD16+设置数据长度为blksize,短响应 	   
+	errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);			//等待R1响应   
+	if(errorstatus!=SD_OK)
+    {
+        printf("SDMMC_Send_Cmd=%d\r\n",errorstatus);
+        return errorstatus;   			//响应错误
+    }
+	SDMMC_Send_Data_Cfg(SD_DATATIMEOUT,nblks*blksize,9,1);	//nblks*blksize,块大小恒为512,卡到控制器	 
+	SDMMC1->CMD|=1<<6;										//CMDTRANS=1,产生一个数据传输命令
+	if(nblks>1)												//多块读  
+	{									    
+		SDMMC_Send_Cmd(SD_CMD_READ_MULT_BLOCK,1,addr);		//发送CMD18+从addr地址出读取数据,短响应 	   
+		errorstatus=CmdResp1Error(SD_CMD_READ_MULT_BLOCK);	//等待R1响应   
+		if(errorstatus!=SD_OK)
+		{	
+			printf("SD_CMD_READ_MULT_BLOCK Error\r\n");
+			return errorstatus;   		//响应错误	 
+		}
+	}else													//单块读
+	{ 
+		SDMMC_Send_Cmd(SD_CMD_READ_SINGLE_BLOCK,1,addr);		//发送CMD17+从addr地址出读取数据,短响应 	   
+		errorstatus=CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);//等待R1响应   
+		if(errorstatus!=SD_OK)return errorstatus;   		//响应错误	 
+	} 
+	INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDMMC读写操作!!!)
+	while(!(SDMMC1->STA&((1<<5)|(1<<1)|(1<<3)|(1<<8))))//无上溢/CRC/超时/完成(标志)
+	{
+		if(SDMMC1->STA&(1<<15))						//接收区半满,表示至少存了8个字
+		{
+			for(count=0;count<8;count++)			//循环读取数据
+			{
+				*(tempbuff+count)=SDMMC1->FIFO;
+			}
+			tempbuff+=8;	 
+			timeout=0X7FFFFF; 	//读数据溢出时间
+		}else 	//处理超时
+		{
+			if(timeout==0)return SD_DATA_TIMEOUT;
+			timeout--;
+		}
+	} 
+	SDMMC1->CMD&=~(1<<6);		//CMDTRANS=0,结束数据传输
+	INTX_ENABLE();				//开启总中断
+	if(SDMMC1->STA&(1<<3))		//数据超时错误
+	{										   
+		SDMMC1->ICR|=1<<3; 		//清错误标志
+		return SD_DATA_TIMEOUT;
+	}else if(SDMMC1->STA&(1<<1))//数据块CRC错误
+	{
+		SDMMC1->ICR|=1<<1; 		//清错误标志
+		if(nblks>1)				//针对可能出现的CRC错误,如果是多块读取,必须发送结束传输命令!
+		{
+			SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);		//发送CMD12+结束传输 	   
+			errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应   
+		}				
+		return SD_DATA_CRC_FAIL;		   
+	}else if(SDMMC1->STA&(1<<5))//接收fifo上溢错误
+	{
+		SDMMC1->ICR|=1<<5; 		//清错误标志
+		return SD_RX_OVERRUN;		 
+	}  
+	if((SDMMC1->STA&(1<<8))&&(nblks>1))//多块接收结束,发送结束指令
+	{
+		if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
+		{
+			SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);		//发送CMD12+结束传输 	   
+			errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应   
+			if(errorstatus!=SD_OK)return errorstatus;	 
+		}
+	}
+	SDMMC1->ICR=0X1FE00FFF;	 		//清除所有标记 
+	return errorstatus;
+}	
+ 		    																  
+//SD卡写单个/多个块 
+//buf:数据缓存区
+//addr:写地址
+//blksize:块大小
+//nblks:要读取的块数,1,表示读取单个块
+//返回值:错误状态												   
+SD_Error SD_WriteBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks)
+{
+	SD_Error errorstatus = SD_OK;
+	u8  cardstate=0;
+	u32 timeout=0,bytestransferred=0;
+	u32 cardstatus=0,count=0,restwords=0;
+	u32 tlen=nblks*blksize;						//总长度(字节)
+	u32*tempbuff=(u32*)buf;								 
+ 	if(buf==NULL)return SD_INVALID_PARAMETER;	//参数错误   
+  	SDMMC1->DCTRL=0x0;							//数据控制寄存器清零(关DMA)    
+ 	if(CardType==HIGH_CAPACITY_SD_CARD)			//大容量卡
+	{
+		blksize=512;
+		addr>>=9;
+	}     
+	SDMMC_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,blksize);			//发送CMD16+设置数据长度为blksize,短响应 	   
+	errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);			//等待R1响应   
+	if(errorstatus!=SD_OK)return errorstatus;   			//响应错误  
+	if(nblks>1)												//多块写
+	{									     
+		if(nblks*blksize>SD_MAX_DATA_LENGTH)return SD_INVALID_PARAMETER;   
+     	if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
+    	{
+			//提高性能
+	 	   	SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,(u32)RCA<<16);	//发送ACMD55,短响应 	   
+			errorstatus=CmdResp1Error(SD_CMD_APP_CMD);		//等待R1响应   		   
+			if(errorstatus!=SD_OK)return errorstatus;				    
+	 	   	SDMMC_Send_Cmd(SD_CMD_SET_BLOCK_COUNT,1,nblks);	//发送CMD23,设置块数量,短响应 	   
+			errorstatus=CmdResp1Error(SD_CMD_SET_BLOCK_COUNT);//等待R1响应   		   
+			if(errorstatus!=SD_OK)return errorstatus;				    
+		} 
+		SDMMC_Send_Cmd(SD_CMD_WRITE_MULT_BLOCK,1,addr);		//发送CMD25,多块写指令,短响应 	   
+		errorstatus=CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK);	//等待R1响应    
+	}else													//单块写		
+	{ 
+		SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);	//发送CMD13,查询卡的状态,短响应 	   
+		errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);		//等待R1响应   		   
+		if(errorstatus!=SD_OK)return errorstatus;
+		cardstatus=SDMMC1->RESP1;													  
+		timeout=SD_DATATIMEOUT;
+		while(((cardstatus&0x00000100)==0)&&(timeout>0)) 	//检查READY_FOR_DATA位是否置位
+		{
+			timeout--;
+			SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);//发送CMD13,查询卡的状态,短响应 	   
+			errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);	//等待R1响应   		   
+			if(errorstatus!=SD_OK)return errorstatus;				    
+			cardstatus=SDMMC1->RESP1;													  
+		}
+		if(timeout==0)return SD_ERROR;  
+		SDMMC_Send_Cmd(SD_CMD_WRITE_SINGLE_BLOCK,1,addr);	//发送CMD24,写单块指令,短响应 	   
+		errorstatus=CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK);//等待R1响应   	
+	}	   
+	if(errorstatus!=SD_OK)return errorstatus;   	   
+ 	SDMMC_Send_Data_Cfg(SD_DATATIMEOUT,nblks*blksize,9,0);	//blksize,块大小恒为512字节,控制器到卡	  
+	SDMMC1->CMD|=1<<6;										//CMDTRANS=1,产生一个数据传输命令
+	timeout=SDMMC_DATATIMEOUT; 
+	INTX_DISABLE();//关闭总中断(POLLING模式,严禁中断打断SDMMC读写操作!!!)
+	while(!(SDMMC1->STA&((1<<4)|(1<<1)|(1<<8)|(1<<3))))//下溢/CRC/数据结束/超时
+	{
+		if(SDMMC1->STA&(1<<14))							//发送区半空,表示至少存了8字(32字节)
+		{	  
+			if((tlen-bytestransferred)<SD_HALFFIFOBYTES)//不够32字节了
+			{
+				restwords=((tlen-bytestransferred)%4==0)?((tlen-bytestransferred)/4):((tlen-bytestransferred)/4+1);
+				for(count=0;count<restwords;count++,tempbuff++,bytestransferred+=4)
+				{
+					SDMMC1->FIFO=*tempbuff;
+				}
+			}else 										//发送区半空,可以发送至少8字(32字节)数据
+			{
+				for(count=0;count<SD_HALFFIFO;count++)
+				{
+					SDMMC1->FIFO=*(tempbuff+count);
+				}
+				tempbuff+=SD_HALFFIFO;
+				bytestransferred+=SD_HALFFIFOBYTES;
+			}
+			timeout=0X3FFFFFFF;		//写数据溢出时间
+		}else
+		{
+			if(timeout==0)return SD_DATA_TIMEOUT; 
+			timeout--;
+		}
+	} 
+	SDMMC1->CMD&=~(1<<6);			//CMDTRANS=0,结束数据传输
+	INTX_ENABLE();					//开启总中断
+	if(SDMMC1->STA&(1<<3))			//数据超时错误
+	{										   
+		SDMMC1->ICR|=1<<3; 			//清错误标志
+		return SD_DATA_TIMEOUT;
+	}else if(SDMMC1->STA&(1<<1))	//数据块CRC错误
+	{
+		SDMMC1->ICR|=1<<1; 			//清错误标志
+		if(nblks>1)					//针对可能出现的CRC错误,如果是多块读取,必须发送结束传输命令!
+		{
+			SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);		//发送CMD12+结束传输 	   
+			errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应   
+		}	
+		return SD_DATA_CRC_FAIL;		   
+	}else if(SDMMC1->STA&(1<<4)) 	//接收fifo下溢错误
+	{
+		SDMMC1->ICR|=1<<4; 			//清错误标志
+		return SD_TX_UNDERRUN;		 
+	}
+	if((SDMMC1->STA&(1<<8))&&(nblks>1))//多块发送结束,发送结束指令
+	{
+		if((STD_CAPACITY_SD_CARD_V1_1==CardType)||(STD_CAPACITY_SD_CARD_V2_0==CardType)||(HIGH_CAPACITY_SD_CARD==CardType))
+		{
+			SDMMC_Send_Cmd(SD_CMD_STOP_TRANSMISSION,1,0);		//发送CMD12+结束传输 	   
+			errorstatus=CmdResp1Error(SD_CMD_STOP_TRANSMISSION);//等待R1响应   
+			if(errorstatus!=SD_OK)return errorstatus;	 
+		}
+	}
+	SDMMC1->ICR=0X1FE00FFF;		//清除所有标记	  
+ 	errorstatus=IsCardProgramming(&cardstate);
+ 	while((errorstatus==SD_OK)&&((cardstate==SD_CARD_PROGRAMMING)||(cardstate==SD_CARD_RECEIVING)))
+	{
+		errorstatus=IsCardProgramming(&cardstate);
+	}   
+	return errorstatus;
+}  
+//检查CMD0的执行状态
+//返回值:sd卡错误码
+SD_Error CmdError(void)
+{
+	SD_Error errorstatus = SD_OK;
+	u32 timeout=SDMMC_CMD0TIMEOUT;	   
+	while(timeout--)
+	{
+		if(SDMMC1->STA&(1<<7))break;//命令已发送(无需响应)	 
+	}	    
+	if(timeout==0)return SD_CMD_RSP_TIMEOUT;  
+	SDMMC1->ICR=0X1FE00FFF;			//清除标记
+	return errorstatus;
+}	 
+//检查R7响应的错误状态
+//返回值:sd卡错误码
+SD_Error CmdResp7Error(void)
+{
+	SD_Error errorstatus=SD_OK;
+	u32 status;
+	u32 timeout=SDMMC_CMD0TIMEOUT;
+ 	while(timeout--)
+	{
+		status=SDMMC1->STA;
+		if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)	
+	}
+ 	if((timeout==0)||(status&(1<<2)))	//响应超时
+	{																				    
+		errorstatus=SD_CMD_RSP_TIMEOUT;	//当前卡不是2.0兼容卡,或者不支持设定的电压范围
+		SDMMC1->ICR|=1<<2;				//清除命令响应超时标志
+		return errorstatus;
+	}	 
+	if(status&1<<6)						//成功接收到响应
+	{								   
+		errorstatus=SD_OK;
+		SDMMC1->ICR|=1<<6;				//清除响应标志
+ 	}
+	return errorstatus;
+}	   
+//检查R1响应的错误状态
+//cmd:当前命令
+//返回值:sd卡错误码
+SD_Error CmdResp1Error(u8 cmd)
+{	  
+   	u32 status; 
+	while(1)
+	{
+		status=SDMMC1->STA;
+		if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)
+	} 
+	if(status&(1<<2))					//响应超时
+	{																				    
+ 		SDMMC1->ICR=1<<2;				//清除命令响应超时标志
+		SDMMC1->ICR=0X1FE00FFF;				//清除标记
+		return SD_CMD_RSP_TIMEOUT;
+	}	
+ 	if(status&(1<<0))					//CRC错误
+	{																				    
+ 		SDMMC1->ICR=1<<0;				//清除标志
+		return SD_CMD_CRC_FAIL;
+	}		
+	if(SDMMC1->RESPCMD!=cmd)return SD_ILLEGAL_CMD;//命令不匹配 
+  	SDMMC1->ICR=0X1FE00FFF;				//清除标记
+	return (SD_Error)(SDMMC1->RESP1&SD_OCR_ERRORBITS);//返回卡响应
+}
+//检查R3响应的错误状态
+//返回值:错误状态
+SD_Error CmdResp3Error(void)
+{
+	u32 status;						 
+ 	while(1)
+	{
+		status=SDMMC1->STA;
+		if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)	
+	}
+ 	if(status&(1<<2))					//响应超时
+	{											 
+		SDMMC1->ICR|=1<<2;				//清除命令响应超时标志
+		return SD_CMD_RSP_TIMEOUT;
+	}	 
+   	SDMMC1->ICR=0X1FE00FFF;				//清除标记
+ 	return SD_OK;								  
+}
+//检查R2响应的错误状态
+//返回值:错误状态
+SD_Error CmdResp2Error(void)
+{
+	SD_Error errorstatus=SD_OK;
+	u32 status;
+	u32 timeout=SDMMC_CMD0TIMEOUT;
+ 	while(timeout--)
+	{
+		status=SDMMC1->STA;
+		if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)	
+	}
+  	if((timeout==0)||(status&(1<<2)))	//响应超时
+	{																				    
+		errorstatus=SD_CMD_RSP_TIMEOUT; 
+		SDMMC1->ICR|=1<<2;				//清除命令响应超时标志
+		return errorstatus;
+	}	 
+	if(status&1<<0)						//CRC错误
+	{								   
+		errorstatus=SD_CMD_CRC_FAIL;
+		SDMMC1->ICR|=1<<0;				//清除响应标志
+ 	}
+	SDMMC1->ICR=0X1FE00FFF;				//清除标记
+ 	return errorstatus;								    		 
+} 
+//检查R6响应的错误状态
+//cmd:之前发送的命令
+//prca:卡返回的RCA地址
+//返回值:错误状态
+SD_Error CmdResp6Error(u8 cmd,u16*prca)
+{
+	SD_Error errorstatus=SD_OK;
+	u32 status;					    
+	u32 rspr1;
+ 	while(1)
+	{
+		status=SDMMC1->STA;
+		if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功)	
+	}
+	if(status&(1<<2))					//响应超时
+	{																				    
+ 		SDMMC1->ICR|=1<<2;				//清除命令响应超时标志
+		return SD_CMD_RSP_TIMEOUT;
+	}	 	 
+	if(status&1<<0)						//CRC错误
+	{								   
+		SDMMC1->ICR|=1<<0;				//清除响应标志
+ 		return SD_CMD_CRC_FAIL;
+	}
+	if(SDMMC1->RESPCMD!=cmd)			//判断是否响应cmd命令
+	{
+ 		return SD_ILLEGAL_CMD; 		
+	}	    
+	SDMMC1->ICR=0X1FE00FFF;				//清除所有标记
+	rspr1=SDMMC1->RESP1;				//得到响应 	 
+	if(SD_ALLZERO==(rspr1&(SD_R6_GENERAL_UNKNOWN_ERROR|SD_R6_ILLEGAL_CMD|SD_R6_COM_CRC_FAILED)))
+	{
+		*prca=(u16)(rspr1>>16);			//右移16位得到,rca
+		return errorstatus;
+	}
+   	if(rspr1&SD_R6_GENERAL_UNKNOWN_ERROR)return SD_GENERAL_UNKNOWN_ERROR;
+   	if(rspr1&SD_R6_ILLEGAL_CMD)return SD_ILLEGAL_CMD;
+   	if(rspr1&SD_R6_COM_CRC_FAILED)return SD_COM_CRC_FAILED;
+	return errorstatus;
+}
+
+//SDMMC使能宽总线模式
+//enx:0,不使能;1,使能;
+//返回值:错误状态
+SD_Error SDEnWideBus(u8 enx)
+{
+	SD_Error errorstatus = SD_OK;
+ 	u32 scr[2]={0,0};
+	u8 arg=0X00;
+	if(enx)arg=0X02;
+	else arg=0X00;
+ 	if(SDMMC1->RESP1&SD_CARD_LOCKED)return SD_LOCK_UNLOCK_FAILED;//SD卡处于LOCKED状态		    
+ 	errorstatus=FindSCR(RCA,scr);						//得到SCR寄存器数据
+ 	if(errorstatus!=SD_OK)return errorstatus;
+	if((scr[1]&SD_WIDE_BUS_SUPPORT)!=SD_ALLZERO)		//支持宽总线
+	{
+	 	SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,(u32)RCA<<16);	//发送CMD55+RCA,短响应											  
+	 	errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
+	 	if(errorstatus!=SD_OK)return errorstatus; 
+	 	SDMMC_Send_Cmd(SD_CMD_APP_SD_SET_BUSWIDTH,1,arg);//发送ACMD6,短响应,参数:10,4位;00,1位.											  
+		errorstatus=CmdResp1Error(SD_CMD_APP_SD_SET_BUSWIDTH);
+		return errorstatus;
+	}else return SD_REQUEST_NOT_APPLICABLE;				//不支持宽总线设置 	 
+}												   
+//检查卡是否正在执行写操作
+//pstatus:当前状态.
+//返回值:错误代码
+SD_Error IsCardProgramming(u8 *pstatus)
+{
+ 	vu32 respR1 = 0, status = 0; 
+  	SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,(u32)RCA<<16);		//发送CMD13 	   
+  	status=SDMMC1->STA;
+	while(!(status&((1<<0)|(1<<6)|(1<<2))))status=SDMMC1->STA;//等待操作完成
+   	if(status&(1<<0))			//CRC检测失败
+	{
+		SDMMC1->ICR|=1<<0;		//清除错误标记
+		return SD_CMD_CRC_FAIL;
+	}
+   	if(status&(1<<2))			//命令超时 
+	{
+		SDMMC1->ICR|=1<<2;		//清除错误标记
+		return SD_CMD_RSP_TIMEOUT;
+	}
+ 	if(SDMMC1->RESPCMD!=SD_CMD_SEND_STATUS)return SD_ILLEGAL_CMD;
+	SDMMC1->ICR=0X1FE00FFF;		//清除所有标记
+	respR1=SDMMC1->RESP1;
+	*pstatus=(u8)((respR1>>9)&0x0000000F);
+	return SD_OK;
+}
+//读取当前卡状态
+//pcardstatus:卡状态
+//返回值:错误代码
+SD_Error SD_SendStatus(uint32_t *pcardstatus)
+{
+	SD_Error errorstatus = SD_OK;
+	if(pcardstatus==NULL)
+	{
+		errorstatus=SD_INVALID_PARAMETER;
+		return errorstatus;
+	}
+ 	SDMMC_Send_Cmd(SD_CMD_SEND_STATUS,1,RCA<<16);	//发送CMD13,短响应		 
+	errorstatus=CmdResp1Error(SD_CMD_SEND_STATUS);	//查询响应状态 
+	if(errorstatus!=SD_OK)return errorstatus;
+	*pcardstatus=SDMMC1->RESP1;//读取响应值
+	return errorstatus;
+} 
+//返回SD卡的状态
+//返回值:SD卡状态
+SDCardState SD_GetState(void)
+{
+	u32 resp1=0;
+	if(SD_SendStatus(&resp1)!=SD_OK)return SD_CARD_ERROR;
+	else return (SDCardState)((resp1>>9) & 0x0F);
+}
+//查找SD卡的SCR寄存器值
+//rca:卡相对地址
+//pscr:数据缓存区(存储SCR内容)
+//返回值:错误状态		   
+SD_Error FindSCR(u16 rca,u32 *pscr)
+{  
+	SD_Error errorstatus = SD_OK;
+	u32 tempscr[2]={0,0};  
+ 	SDMMC_Send_Cmd(SD_CMD_SET_BLOCKLEN,1,8);			//发送CMD16,短响应,设置Block Size为8字节											  
+ 	errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);
+ 	if(errorstatus!=SD_OK)return errorstatus;	    
+  	SDMMC_Send_Cmd(SD_CMD_APP_CMD,1,(u32)rca<<16);	//发送CMD55,短响应 									  
+ 	errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
+ 	if(errorstatus!=SD_OK)return errorstatus;
+	SDMMC_Send_Data_Cfg(SD_DATATIMEOUT,8,3,1);		//8个字节长度,block为8字节,SD卡到SDMMC.
+   	SDMMC_Send_Cmd(SD_CMD_SD_APP_SEND_SCR,1,0);		//发送ACMD51,短响应,参数为0											  
+ 	errorstatus=CmdResp1Error(SD_CMD_SD_APP_SEND_SCR);
+ 	if(errorstatus!=SD_OK)return errorstatus;							   
+ 	while(!(SDMMC1->STA&(SDMMC_STA_RXOVERR|SDMMC_STA_DCRCFAIL|SDMMC_STA_DTIMEOUT|SDMMC_STA_DBCKEND|SDMMC_STA_DATAEND)))
+	{ 
+		if(!(SDMMC1->STA&(1<<19)))		//接收FIFO数据可用
+		{
+			tempscr[0]=SDMMC1->FIFO;	//读取FIFO内容 
+			tempscr[1]=SDMMC1->FIFO;	//读取FIFO内容 
+			break;
+		}
+	}
+ 	if(SDMMC1->STA&(1<<3))		//接收数据超时
+	{										 
+ 		SDMMC1->ICR|=1<<3;		//清除标记
+		return SD_DATA_TIMEOUT;
+	}else if(SDMMC1->STA&(1<<1))//已发送/接收的数据块CRC校验错误
+	{
+ 		SDMMC1->ICR|=1<<1;		//清除标记
+		return SD_DATA_CRC_FAIL;   
+	}else if(SDMMC1->STA&(1<<5))//接收FIFO溢出
+	{
+ 		SDMMC1->ICR|=1<<5;		//清除标记
+		return SD_RX_OVERRUN;   	   
+	} 
+   	SDMMC1->ICR=0X1FE00FFF;		//清除标记	 
+	//把数据顺序按8位为单位倒过来.   	
+	*(pscr+1)=((tempscr[0]&SD_0TO7BITS)<<24)|((tempscr[0]&SD_8TO15BITS)<<8)|((tempscr[0]&SD_16TO23BITS)>>8)|((tempscr[0]&SD_24TO31BITS)>>24);
+	*(pscr)=((tempscr[1]&SD_0TO7BITS)<<24)|((tempscr[1]&SD_8TO15BITS)<<8)|((tempscr[1]&SD_16TO23BITS)>>8)|((tempscr[1]&SD_24TO31BITS)>>24);
+ 	return errorstatus;
+}  
+//读SD卡
+//buf:读数据缓存区
+//sector:扇区地址
+//cnt:扇区个数	
+//返回值:错误状态;0,正常;其他,错误代码;				  				 
+u8 SD_ReadDisk(u8*buf,u32 sector,u32 cnt)
+{
+	u8 sta=SD_OK;
+	long long lsector=sector;
+	u32 n;
+	if(CardType!=STD_CAPACITY_SD_CARD_V1_1)lsector<<=9;
+	if((u32)buf%4!=0)
+	{
+	 	for(n=0;n<cnt;n++)
+		{
+		 	sta=SD_ReadBlocks(SDMMC_DATA_BUFFER,lsector+512*n,512,1);//单个sector的读操作
+			memcpy(buf,SDMMC_DATA_BUFFER,512);
+			buf+=512;
+		} 
+	}else sta=SD_ReadBlocks(buf,lsector,512,cnt);	//单个/多个sector   
+	return sta;
+}
+//写SD卡
+//buf:写数据缓存区
+//sector:扇区地址
+//cnt:扇区个数	
+//返回值:错误状态;0,正常;其他,错误代码;	
+u8 SD_WriteDisk(u8*buf,u32 sector,u32 cnt)
+{
+	u8 sta=SD_OK;
+	u32 n;
+	long long lsector=sector;
+	if(CardType!=STD_CAPACITY_SD_CARD_V1_1)lsector<<=9;
+	if((u32)buf%4!=0)
+	{
+	 	for(n=0;n<cnt;n++)
+		{
+			memcpy(SDMMC_DATA_BUFFER,buf,512);
+		 	sta=SD_WriteBlocks(SDMMC_DATA_BUFFER,lsector+512*n,512,1);//单个sector的写操作
+			buf+=512;
+		} 
+	}else sta=SD_WriteBlocks(buf,lsector,512,cnt);	//单个/多个sector   
+	return sta;
+}
+
+
+#endif
+
+
+
+

+ 356 - 0
obj/obj_sdmmc_sdcard.h

@@ -0,0 +1,356 @@
+#ifndef __SDMMC_SDCARD_H
+#define __SDMMC_SDCARD_H																			   
+#include "sys_type.h" 													   
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//SDMMC 驱动代码	(仅提供查询模式驱动代码)
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2018/7/31
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved		 
+//********************************************************************************
+//升级说明
+//无
+////////////////////////////////////////////////////////////////////////////////// 	 
+ 
+ 
+//用户配置区			  
+//SDMMC时钟计算公式:SDMMC_CK时钟=sdmmc_ker_ck/[2*clkdiv];其中,sdmmc_ker_ck来自pll1_q_ck,为200Mhz
+//如果出现驱动错误,请尝试将SDMMC_TRANSFER_CLK_DIV频率降低
+//#define SDMMC_INIT_CLK_DIV        0xFA		//SDMMC初始化频率,200M/(250*2)=400Khz,最大400Kh  
+#define SDMMC_TRANSFER_CLK_DIV    0x04		//SDMMC传输频率,该值太小可能会导致读写文件出错 
+										 
+//SD卡操作 各种错误枚举定义
+typedef enum
+{	 
+	//特殊错误定义 
+	SD_CMD_CRC_FAIL                    = (1),   /*!< Command response received (but CRC check failed)              */
+	SD_DATA_CRC_FAIL                   = (2),   /*!< Data block sent/received (CRC check failed)                   */
+	SD_CMD_RSP_TIMEOUT                 = (3),   /*!< Command response timeout                                      */
+	SD_DATA_TIMEOUT                    = (4),   /*!< Data timeout                                                  */
+	SD_TX_UNDERRUN                     = (5),   /*!< Transmit FIFO underrun                                        */
+	SD_RX_OVERRUN                      = (6),   /*!< Receive FIFO overrun                                          */
+	SD_START_BIT_ERR                   = (7),   /*!< Start bit not detected on all data signals in wide bus mode   */
+	SD_CMD_OUT_OF_RANGE                = (8),   /*!< Command's argument was out of range.                          */
+	SD_ADDR_MISALIGNED                 = (9),   /*!< Misaligned address                                            */
+	SD_BLOCK_LEN_ERR                   = (10),  /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
+	SD_ERASE_SEQ_ERR                   = (11),  /*!< An error in the sequence of erase command occurs.            */
+	SD_BAD_ERASE_PARAM                 = (12),  /*!< An invalid selection for erase groups                        */
+	SD_WRITE_PROT_VIOLATION            = (13),  /*!< Attempt to program a write protect block                     */
+	SD_LOCK_UNLOCK_FAILED              = (14),  /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
+	SD_COM_CRC_FAILED                  = (15),  /*!< CRC check of the previous command failed                     */
+	SD_ILLEGAL_CMD                     = (16),  /*!< Command is not legal for the card state                      */
+	SD_CARD_ECC_FAILED                 = (17),  /*!< Card internal ECC was applied but failed to correct the data */
+	SD_CC_ERROR                        = (18),  /*!< Internal card controller error                               */
+	SD_GENERAL_UNKNOWN_ERROR           = (19),  /*!< General or unknown error                                     */
+	SD_STREAM_READ_UNDERRUN            = (20),  /*!< The card could not sustain data transfer in stream read operation. */
+	SD_STREAM_WRITE_OVERRUN            = (21),  /*!< The card could not sustain data programming in stream mode   */
+	SD_CID_CSD_OVERWRITE               = (22),  /*!< CID/CSD overwrite error                                      */
+	SD_WP_ERASE_SKIP                   = (23),  /*!< Only partial address space was erased                        */
+	SD_CARD_ECC_DISABLED               = (24),  /*!< Command has been executed without using internal ECC         */
+	SD_ERASE_RESET                     = (25),  /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */
+	SD_AKE_SEQ_ERROR                   = (26),  /*!< Error in sequence of authentication.                         */
+	SD_INVALID_VOLTRANGE               = (27),
+	SD_ADDR_OUT_OF_RANGE               = (28),
+	SD_SWITCH_ERROR                    = (29),
+	SD_SDMMC_DISABLED                  = (30),
+	SD_SDMMC_FUNCTION_BUSY             = (31),
+	SD_SDMMC_FUNCTION_FAILED           = (32),
+	SD_SDMMC_UNKNOWN_FUNCTION          = (33),
+	//标准错误定义
+	SD_INTERNAL_ERROR                  = (34),
+	SD_NOT_CONFIGURED                  = (35),
+	SD_REQUEST_PENDING                 = (36),
+	SD_REQUEST_NOT_APPLICABLE          = (37),
+	SD_INVALID_PARAMETER               = (38),
+	SD_UNSUPPORTED_FEATURE             = (39),
+	SD_UNSUPPORTED_HW                  = (40),
+	SD_ERROR                           = (41),
+	SD_OK                              = (0) 
+} SD_Error;		  
+
+//SD卡CSD寄存器数据		  
+typedef struct
+{
+	u8  CSDStruct;            /*!< CSD structure */
+	u8  SysSpecVersion;       /*!< System specification version */
+	u8  Reserved1;            /*!< Reserved */
+	u8  TAAC;                 /*!< Data read access-time 1 */
+	u8  NSAC;                 /*!< Data read access-time 2 in CLK cycles */
+	u8  MaxBusClkFrec;        /*!< Max. bus clock frequency */
+	u16 CardComdClasses;      /*!< Card command classes */
+	u8  RdBlockLen;           /*!< Max. read data block length */
+	u8  PartBlockRead;        /*!< Partial blocks for read allowed */
+	u8  WrBlockMisalign;      /*!< Write block misalignment */
+	u8  RdBlockMisalign;      /*!< Read block misalignment */
+	u8  DSRImpl;              /*!< DSR implemented */
+	u8  Reserved2;            /*!< Reserved */
+	u32 DeviceSize;           /*!< Device Size */
+	u8  MaxRdCurrentVDDMin;   /*!< Max. read current @ VDD min */
+	u8  MaxRdCurrentVDDMax;   /*!< Max. read current @ VDD max */
+	u8  MaxWrCurrentVDDMin;   /*!< Max. write current @ VDD min */
+	u8  MaxWrCurrentVDDMax;   /*!< Max. write current @ VDD max */
+	u8  DeviceSizeMul;        /*!< Device size multiplier */
+	u8  EraseGrSize;          /*!< Erase group size */
+	u8  EraseGrMul;           /*!< Erase group size multiplier */
+	u8  WrProtectGrSize;      /*!< Write protect group size */
+	u8  WrProtectGrEnable;    /*!< Write protect group enable */
+	u8  ManDeflECC;           /*!< Manufacturer default ECC */
+	u8  WrSpeedFact;          /*!< Write speed factor */
+	u8  MaxWrBlockLen;        /*!< Max. write data block length */
+	u8  WriteBlockPaPartial;  /*!< Partial blocks for write allowed */
+	u8  Reserved3;            /*!< Reserded */
+	u8  ContentProtectAppli;  /*!< Content protection application */
+	u8  FileFormatGrouop;     /*!< File format group */
+	u8  CopyFlag;             /*!< Copy flag (OTP) */
+	u8  PermWrProtect;        /*!< Permanent write protection */
+	u8  TempWrProtect;        /*!< Temporary write protection */
+	u8  FileFormat;           /*!< File Format */
+	u8  ECC;                  /*!< ECC code */
+	u8  CSD_CRC;              /*!< CSD CRC */
+	u8  Reserved4;            /*!< always 1*/
+} SD_CSD;   
+
+//SD卡CID寄存器数据
+typedef struct
+{
+	u8  ManufacturerID;       /*!< ManufacturerID */
+	u16 OEM_AppliID;          /*!< OEM/Application ID */
+	u32 ProdName1;            /*!< Product Name part1 */
+	u8  ProdName2;            /*!< Product Name part2*/
+	u8  ProdRev;              /*!< Product Revision */
+	u32 ProdSN;               /*!< Product Serial Number */
+	u8  Reserved1;            /*!< Reserved1 */
+	u16 ManufactDate;         /*!< Manufacturing Date */
+	u8  CID_CRC;              /*!< CID CRC */
+	u8  Reserved2;            /*!< always 1 */
+} SD_CID;	 
+//SD卡状态
+typedef enum
+{
+	SD_CARD_READY                  = ((uint32_t)0x00000001),
+	SD_CARD_IDENTIFICATION         = ((uint32_t)0x00000002),
+	SD_CARD_STANDBY                = ((uint32_t)0x00000003),
+	SD_CARD_TRANSFER               = ((uint32_t)0x00000004),
+	SD_CARD_SENDING                = ((uint32_t)0x00000005),
+	SD_CARD_RECEIVING              = ((uint32_t)0x00000006),
+	SD_CARD_PROGRAMMING            = ((uint32_t)0x00000007),
+	SD_CARD_DISCONNECTED           = ((uint32_t)0x00000008),
+	SD_CARD_ERROR                  = ((uint32_t)0x000000FF)
+}SDCardState;
+
+//SD卡信息,包括CSD,CID等数据
+typedef struct
+{
+  SD_CSD SD_csd;
+  SD_CID SD_cid;
+  long long CardCapacity;  	//SD卡容量,单位:字节,最大支持2^64字节大小的卡.
+  u32 CardBlockSize; 		//SD卡块大小	
+  u16 RCA;					//卡相对地址
+  u8 CardType;				//卡类型
+} SD_CardInfo;
+extern SD_CardInfo SDCardInfo;//SD卡信息			 
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//SDMMC卡 指令集
+//拷贝自:stm32f7xx_hal_sd.h
+#define SD_CMD_GO_IDLE_STATE                       ((uint8_t)0U)   /*!< Resets the SD memory card.                                                               */
+#define SD_CMD_SEND_OP_COND                        ((uint8_t)1U)   /*!< Sends host capacity support information and activates the card's initialization process. */
+#define SD_CMD_ALL_SEND_CID                        ((uint8_t)2U)   /*!< Asks any card connected to the host to send the CID numbers on the CMD line.             */
+#define SD_CMD_SET_REL_ADDR                        ((uint8_t)3U)   /*!< Asks the card to publish a new relative address (RCA).                                   */
+#define SD_CMD_SET_DSR                             ((uint8_t)4U)   /*!< Programs the DSR of all cards.                                                           */
+#define SD_CMD_SDMMC_SEN_OP_COND                   ((uint8_t)5U)   /*!< Sends host capacity support information (HCS) and asks the accessed card to send its 
+                                                                       operating condition register (OCR) content in the response on the CMD line.              */
+#define SD_CMD_HS_SWITCH                           ((uint8_t)6U)   /*!< Checks switchable function (mode 0) and switch card function (mode 1).                   */
+#define SD_CMD_SEL_DESEL_CARD                      ((uint8_t)7U)   /*!< Selects the card by its own relative address and gets deselected by any other address    */
+#define SD_CMD_HS_SEND_EXT_CSD                     ((uint8_t)8U)   /*!< Sends SD Memory Card interface condition, which includes host supply voltage information 
+                                                                       and asks the card whether card supports voltage.                                         */
+#define SD_CMD_SEND_CSD                            ((uint8_t)9U)   /*!< Addressed card sends its card specific data (CSD) on the CMD line.                       */
+#define SD_CMD_SEND_CID                            ((uint8_t)10U)  /*!< Addressed card sends its card identification (CID) on the CMD line.                      */
+#define SD_CMD_READ_DAT_UNTIL_STOP                 ((uint8_t)11U)  /*!< SD card doesn't support it.                                                              */
+#define SD_CMD_STOP_TRANSMISSION                   ((uint8_t)12U)  /*!< Forces the card to stop transmission.                                                    */
+#define SD_CMD_SEND_STATUS                         ((uint8_t)13U)  /*!< Addressed card sends its status register.                                                */
+#define SD_CMD_HS_BUSTEST_READ                     ((uint8_t)14U) 
+#define SD_CMD_GO_INACTIVE_STATE                   ((uint8_t)15U)  /*!< Sends an addressed card into the inactive state.                                         */
+#define SD_CMD_SET_BLOCKLEN                        ((uint8_t)16U)  /*!< Sets the block length (in bytes for SDSC) for all following block commands 
+                                                                       (read, write, lock). Default block length is fixed to 512 Bytes. Not effective 
+                                                                       for SDHS and SDXC.                                                                       */
+#define SD_CMD_READ_SINGLE_BLOCK                   ((uint8_t)17U)  /*!< Reads single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of 
+                                                                       fixed 512 bytes in case of SDHC and SDXC.                                                */
+#define SD_CMD_READ_MULT_BLOCK                     ((uint8_t)18U)  /*!< Continuously transfers data blocks from card to host until interrupted by 
+                                                                       STOP_TRANSMISSION command.                                                               */
+#define SD_CMD_HS_BUSTEST_WRITE                    ((uint8_t)19U)  /*!< 64 bytes tuning pattern is sent for SDR50 and SDR104.                                    */
+#define SD_CMD_WRITE_DAT_UNTIL_STOP                ((uint8_t)20U)  /*!< Speed class control command.                                                             */
+#define SD_CMD_SET_BLOCK_COUNT                     ((uint8_t)23U)  /*!< Specify block count for CMD18 and CMD25.                                                 */
+#define SD_CMD_WRITE_SINGLE_BLOCK                  ((uint8_t)24U)  /*!< Writes single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of 
+                                                                       fixed 512 bytes in case of SDHC and SDXC.                                                */
+#define SD_CMD_WRITE_MULT_BLOCK                    ((uint8_t)25U)  /*!< Continuously writes blocks of data until a STOP_TRANSMISSION follows.                    */
+#define SD_CMD_PROG_CID                            ((uint8_t)26U)  /*!< Reserved for manufacturers.                                                              */
+#define SD_CMD_PROG_CSD                            ((uint8_t)27U)  /*!< Programming of the programmable bits of the CSD.                                         */
+#define SD_CMD_SET_WRITE_PROT                      ((uint8_t)28U)  /*!< Sets the write protection bit of the addressed group.                                    */
+#define SD_CMD_CLR_WRITE_PROT                      ((uint8_t)29U)  /*!< Clears the write protection bit of the addressed group.                                  */
+#define SD_CMD_SEND_WRITE_PROT                     ((uint8_t)30U)  /*!< Asks the card to send the status of the write protection bits.                           */
+#define SD_CMD_SD_ERASE_GRP_START                  ((uint8_t)32U)  /*!< Sets the address of the first write block to be erased. (For SD card only).              */
+#define SD_CMD_SD_ERASE_GRP_END                    ((uint8_t)33U)  /*!< Sets the address of the last write block of the continuous range to be erased.           */
+#define SD_CMD_ERASE_GRP_START                     ((uint8_t)35U)  /*!< Sets the address of the first write block to be erased. Reserved for each command 
+                                                                       system set by switch function command (CMD6).                                            */
+#define SD_CMD_ERASE_GRP_END                       ((uint8_t)36U)  /*!< Sets the address of the last write block of the continuous range to be erased. 
+                                                                       Reserved for each command system set by switch function command (CMD6).                  */
+#define SD_CMD_ERASE                               ((uint8_t)38U)  /*!< Reserved for SD security applications.                                                   */
+#define SD_CMD_FAST_IO                             ((uint8_t)39U)  /*!< SD card doesn't support it (Reserved).                                                   */
+#define SD_CMD_GO_IRQ_STATE                        ((uint8_t)40U)  /*!< SD card doesn't support it (Reserved).                                                   */
+#define SD_CMD_LOCK_UNLOCK                         ((uint8_t)42U)  /*!< Sets/resets the password or lock/unlock the card. The size of the data block is set by 
+                                                                       the SET_BLOCK_LEN command.                                                               */
+#define SD_CMD_APP_CMD                             ((uint8_t)55U)  /*!< Indicates to the card that the next command is an application specific command rather 
+                                                                       than a standard command.                                                                 */
+#define SD_CMD_GEN_CMD                             ((uint8_t)56U)  /*!< Used either to transfer a data block to the card or to get a data block from the card 
+                                                                       for general purpose/application specific commands.                                       */
+#define SD_CMD_NO_CMD                              ((uint8_t)64U) 
+
+/** 
+  * @brief Following commands are SD Card Specific commands.
+  *        SDMMC_APP_CMD should be sent before sending these commands. 
+  */
+#define SD_CMD_APP_SD_SET_BUSWIDTH                 ((uint8_t)6U)   /*!< (ACMD6) Defines the data bus width to be used for data transfer. The allowed data bus 
+                                                                       widths are given in SCR register.                                                          */
+#define SD_CMD_SD_APP_STATUS                       ((uint8_t)13U)  /*!< (ACMD13) Sends the SD status.                                                              */
+#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS        ((uint8_t)22U)  /*!< (ACMD22) Sends the number of the written (without errors) write blocks. Responds with 
+                                                                       32bit+CRC data block.                                                                      */
+#define SD_CMD_SD_APP_OP_COND                      ((uint8_t)41U)  /*!< (ACMD41) Sends host capacity support information (HCS) and asks the accessed card to 
+                                                                       send its operating condition register (OCR) content in the response on the CMD line.       */
+#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT          ((uint8_t)42U)  /*!< (ACMD42) Connects/Disconnects the 50 KOhm pull-up resistor on CD/DAT3 (pin 1) of the card. */
+#define SD_CMD_SD_APP_SEND_SCR                     ((uint8_t)51U)  /*!< Reads the SD Configuration Register (SCR).                                                 */
+#define SD_CMD_SDMMC_RW_DIRECT                     ((uint8_t)52U)  /*!< For SD I/O card only, reserved for security specification.                                 */
+#define SD_CMD_SDMMC_RW_EXTENDED                   ((uint8_t)53U)  /*!< For SD I/O card only, reserved for security specification.                                 */
+
+/** 
+  * @brief Following commands are SD Card Specific security commands.
+  *        SD_CMD_APP_CMD should be sent before sending these commands. 
+  */
+#define SD_CMD_SD_APP_GET_MKB                      ((uint8_t)43U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_GET_MID                      ((uint8_t)44U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_SET_CER_RN1                  ((uint8_t)45U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_GET_CER_RN2                  ((uint8_t)46U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_SET_CER_RES2                 ((uint8_t)47U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_GET_CER_RES1                 ((uint8_t)48U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK   ((uint8_t)18U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK  ((uint8_t)25U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_SECURE_ERASE                 ((uint8_t)38U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_CHANGE_SECURE_AREA           ((uint8_t)49U)  /*!< For SD card only */
+#define SD_CMD_SD_APP_SECURE_WRITE_MKB             ((uint8_t)48U)  /*!< For SD card only */
+
+//CMD8指令
+#define SD_SDMMC_SEND_IF_COND           	  ((uint32_t)SD_CMD_HS_SEND_EXT_CSD)
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//支持的SD卡定义
+#define STD_CAPACITY_SD_CARD_V1_1			((uint32_t)0x00000000U)
+#define STD_CAPACITY_SD_CARD_V2_0			((uint32_t)0x00000001U)
+#define HIGH_CAPACITY_SD_CARD					((uint32_t)0x00000002U)
+#define MULTIMEDIA_CARD								((uint32_t)0x00000003U)
+#define SECURE_DIGITAL_IO_CARD				((uint32_t)0x00000004U)
+#define HIGH_SPEED_MULTIMEDIA_CARD		((uint32_t)0x00000005U)
+#define SECURE_DIGITAL_IO_COMBO_CARD	((uint32_t)0x00000006U)
+#define HIGH_CAPACITY_MMC_CARD				((uint32_t)0x00000007U)
+
+//SDMMC相关参数定义
+#define NULL 0
+//#define SDMMC_STATIC_FLAGS				((u32)0x000205FF)
+#define SDMMC_CMD0TIMEOUT						((u32)0x00010000)	  
+//#define SDMMC_DATATIMEOUT					((u32)0xFFFFFFFF)	 
+
+//Mask for errors Card Status R1 (OCR Register)  
+#define SD_OCR_ADDR_OUT_OF_RANGE        ((u32)0x80000000)
+#define SD_OCR_ADDR_MISALIGNED          ((u32)0x40000000)
+#define SD_OCR_BLOCK_LEN_ERR            ((u32)0x20000000)
+#define SD_OCR_ERASE_SEQ_ERR            ((u32)0x10000000)
+#define SD_OCR_BAD_ERASE_PARAM          ((u32)0x08000000)
+#define SD_OCR_WRITE_PROT_VIOLATION     ((u32)0x04000000)
+#define SD_OCR_LOCK_UNLOCK_FAILED       ((u32)0x01000000)
+#define SD_OCR_COM_CRC_FAILED           ((u32)0x00800000)
+#define SD_OCR_ILLEGAL_CMD              ((u32)0x00400000)
+#define SD_OCR_CARD_ECC_FAILED          ((u32)0x00200000)
+#define SD_OCR_CC_ERROR                 ((u32)0x00100000)
+#define SD_OCR_GENERAL_UNKNOWN_ERROR    ((u32)0x00080000)
+#define SD_OCR_STREAM_READ_UNDERRUN     ((u32)0x00040000)
+#define SD_OCR_STREAM_WRITE_OVERRUN     ((u32)0x00020000)
+//#define SD_OCR_CID_CSD_OVERWRIETE       ((u32)0x00010000)
+#define SD_OCR_WP_ERASE_SKIP            ((u32)0x00008000)
+#define SD_OCR_CARD_ECC_DISABLED        ((u32)0x00004000)
+#define SD_OCR_ERASE_RESET              ((u32)0x00002000)
+#define SD_OCR_AKE_SEQ_ERROR            ((u32)0x00000008)
+#define SD_OCR_ERRORBITS                ((u32)0xFDFFE008)
+
+//Masks for R6 Response 
+#define SD_R6_GENERAL_UNKNOWN_ERROR     ((u32)0x00002000)
+#define SD_R6_ILLEGAL_CMD               ((u32)0x00004000)
+#define SD_R6_COM_CRC_FAILED            ((u32)0x00008000)
+
+#define SD_VOLTAGE_WINDOW_SD            ((u32)0x80100000)
+#define SD_HIGH_CAPACITY                ((u32)0x40000000)
+#define SD_STD_CAPACITY                 ((u32)0x00000000)
+#define SD_CHECK_PATTERN                ((u32)0x000001AA)
+#define SD_VOLTAGE_WINDOW_MMC           ((u32)0x80FF8000)
+
+#define SD_MAX_VOLT_TRIAL               ((u32)0x0000FFFF)
+#define SD_ALLZERO                      ((u32)0x00000000)
+
+#define SD_WIDE_BUS_SUPPORT             ((u32)0x00040000)
+#define SD_SINGLE_BUS_SUPPORT           ((u32)0x00010000)
+#define SD_CARD_LOCKED                  ((u32)0x02000000)
+#define SD_CARD_PROGRAMMING             ((u32)0x00000007)
+#define SD_CARD_RECEIVING               ((u32)0x00000006)
+#define SD_DATATIMEOUT                  ((u32)0xFFFFFFFF)
+#define SD_0TO7BITS                     ((u32)0x000000FF)
+#define SD_8TO15BITS                    ((u32)0x0000FF00)
+#define SD_16TO23BITS                   ((u32)0x00FF0000)
+#define SD_24TO31BITS                   ((u32)0xFF000000)
+#define SD_MAX_DATA_LENGTH              ((u32)0x01FFFFFF)
+
+#define SD_HALFFIFO                     ((u32)0x00000008)
+#define SD_HALFFIFOBYTES                ((u32)0x00000020)
+
+//Command Class Supported  
+#define SD_CCCC_LOCK_UNLOCK             ((u32)0x00000080)
+#define SD_CCCC_WRITE_PROT              ((u32)0x00000040)
+#define SD_CCCC_ERASE                   ((u32)0x00000020)
+																 
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//相关函数定义
+SD_Error SD_Init(void);
+void SDMMC_Clock_Set(u16 clkdiv);
+void SDMMC_Send_Cmd(u8 cmdindex,u8 waitrsp,u32 arg);
+void SDMMC_Send_Data_Cfg(u32 datatimeout,u32 datalen,u8 blksize,u8 dir);
+SD_Error SD_PowerON(void);    
+SD_Error SD_PowerOFF(void);
+SD_Error SD_InitializeCards(void);
+SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo);		  
+SD_Error SD_EnableWideBusOperation(u32 wmode); 
+SD_Error SD_SelectDeselect(u32 addr); 
+SD_Error SD_SendStatus(uint32_t *pcardstatus);
+SDCardState SD_GetState(void);  
+SD_Error SD_ReadBlocks(u8 *buf,long long  addr,u16 blksize,u32 nblks);   
+SD_Error SD_WriteBlocks(u8 *buf,long long addr,u16 blksize,u32 nblks); 
+SD_Error CmdError(void);  
+SD_Error CmdResp7Error(void);
+SD_Error CmdResp1Error(u8 cmd);
+SD_Error CmdResp3Error(void);
+SD_Error CmdResp2Error(void);
+SD_Error CmdResp6Error(u8 cmd,u16*prca);  
+SD_Error SDEnWideBus(u8 enx);	  
+SD_Error IsCardProgramming(u8 *pstatus); 
+SD_Error FindSCR(u16 rca,u32 *pscr);   
+
+u8 SD_ReadDisk(u8*buf,u32 sector,u32 cnt); 	//读SD卡,fatfs/usb调用
+u8 SD_WriteDisk(u8*buf,u32 sector,u32 cnt);	//写SD卡,fatfs/usb调用
+
+
+#endif 
+
+
+
+
+

+ 540 - 0
obj/obj_spi_sd_stm32.c

@@ -0,0 +1,540 @@
+/*-----------------------------------------------------------------------*/
+/* MMC/SDC (in SPI mode) control module  (C)ChaN, 2007                   */
+/*-----------------------------------------------------------------------*/
+/* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros         */
+/* are platform dependent.                                               */
+/*-----------------------------------------------------------------------*/
+#include "obj_spi_sd_stm32.h"
+
+/*--------------------------------------------------------------------------
+
+ Module Private Functions
+
+ ---------------------------------------------------------------------------*/
+ 
+extern SPI_HandleTypeDef hspi2;
+
+#define SD_SPIDriver	  hspi2 
+
+static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */
+
+static volatile BYTE Timer1, Timer2; /* 100Hz decrement timer */
+
+static BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
+
+static BYTE PowerFlag = 0; /* indicates if "power" is on */
+
+static
+void SELECT(void)
+{
+	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
+}
+
+static
+void DESELECT(void)
+{
+	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
+}
+
+static
+void xmit_spi(BYTE Data)
+{
+	while (HAL_SPI_GetState(&SD_SPIDriver) != HAL_SPI_STATE_READY);
+	HAL_SPI_Transmit(&SD_SPIDriver, &Data, 1, 5000);
+}
+
+static BYTE rcvr_spi(void)
+{
+	unsigned char Dummy, Data;
+	Dummy = 0xFF;
+	Data = 0;
+	while ((HAL_SPI_GetState(&SD_SPIDriver) != HAL_SPI_STATE_READY))
+		;
+	HAL_SPI_TransmitReceive(&SD_SPIDriver, &Dummy, &Data, 1, 5000);
+
+	return Data;
+}
+
+static
+void rcvr_spi_m(BYTE *dst) {
+	*dst = rcvr_spi();
+}
+
+/*-----------------------------------------------------------------------*/
+/* Wait for card ready                                                   */
+/*-----------------------------z------------------------------------------*/
+
+static BYTE wait_ready(void) {
+	BYTE res;
+
+	Timer2 = 50;
+	rcvr_spi();
+	do
+		res = rcvr_spi();
+	while ((res != 0xFF) && Timer2);
+
+	return res;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Power Control  (Platform dependent)                                   */
+/*-----------------------------------------------------------------------*/
+/* When the target system does not support socket power control, there   */
+/* is nothing to do in these functions and chk_power always returns 1.   */
+
+static
+void power_on(void) {
+	unsigned char i, cmd_arg[6];
+	unsigned int Count = 0x1FFF;
+
+	DESELECT();
+
+	for (i = 0; i < 10; i++)
+		xmit_spi(0xFF);
+	
+	SELECT();
+
+	cmd_arg[0] = (CMD0 | 0x40);
+	cmd_arg[1] = 0;
+	cmd_arg[2] = 0;
+	cmd_arg[3] = 0;
+	cmd_arg[4] = 0;
+	cmd_arg[5] = 0x95;
+
+	for (i = 0; i < 6; i++)
+		xmit_spi(cmd_arg[i]);
+
+	while ((rcvr_spi() != 0x01) && Count)
+		Count--;
+
+	DESELECT();
+	xmit_spi(0XFF);
+
+	PowerFlag = 1;
+}
+
+static
+void power_off(void) {
+	PowerFlag = 0;
+}
+
+static
+int chk_power(void) /* Socket power state: 0=off, 1=on */
+{
+	return PowerFlag;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Receive a data packet from MMC                                        */
+/*-----------------------------------------------------------------------*/
+
+static bool rcvr_datablock(BYTE *buff, /* Data buffer to store received data */
+UINT btr /* Byte count (must be even number) */
+) {
+	BYTE token;
+
+	Timer1 = 10;
+	do { /* Wait for data packet in timeout of 100ms */
+		token = rcvr_spi();
+	} while ((token == 0xFF) && Timer1);
+	if (token != 0xFE)
+		return FALSE; /* If not valid data token, retutn with error */
+
+	do { /* Receive the data block into buffer */
+		rcvr_spi_m(buff++);
+		rcvr_spi_m(buff++);
+	} while (btr -= 2);
+	rcvr_spi(); /* Discard CRC */
+	rcvr_spi();
+
+	return TRUE; /* Return with success */
+}
+
+/*-----------------------------------------------------------------------*/
+/* Send a data packet to MMC                                             */
+/*-----------------------------------------------------------------------*/
+
+#if _READONLY == 0
+static bool xmit_datablock(const BYTE *buff, /* 512 byte data block to be transmitted */
+BYTE token /* Data/Stop token */
+) {
+	BYTE resp, wc;
+	uint32_t i = 0;
+
+	if (wait_ready() != 0xFF)
+		return FALSE;
+
+	xmit_spi(token); /* Xmit data token */
+	if (token != 0xFD) { /* Is data token */
+		wc = 0;
+		do { /* Xmit the 512 byte data block to MMC */
+			xmit_spi(*buff++);
+			xmit_spi(*buff++);
+		} while (--wc);
+
+		rcvr_spi();
+		rcvr_spi();
+
+		while (i <= 64) {
+			resp = rcvr_spi(); /* Reveive data response */
+			if ((resp & 0x1F) == 0x05) /* If not accepted, return with error */
+				break;
+			i++;
+		}
+		while (rcvr_spi() == 0)
+			;
+	}
+	if ((resp & 0x1F) == 0x05)
+		return TRUE;
+	else
+		return FALSE;
+}
+#endif /* _READONLY */
+
+/*-----------------------------------------------------------------------*/
+/* Send a command packet to MMC                                          */
+/*-----------------------------------------------------------------------*/
+
+static BYTE send_cmd(BYTE cmd, /* Command byte */
+DWORD arg /* Argument */
+) {
+	BYTE n, res;
+
+	if (wait_ready() != 0xFF)
+		return 0xFF;
+
+	/* Send command packet */
+	xmit_spi(cmd); /* Command */
+	xmit_spi((BYTE) (arg >> 24)); /* Argument[31..24] */
+	xmit_spi((BYTE) (arg >> 16)); /* Argument[23..16] */
+	xmit_spi((BYTE) (arg >> 8)); /* Argument[15..8] */
+	xmit_spi((BYTE) arg); /* Argument[7..0] */
+	n = 0;
+	if (cmd == CMD0)
+		n = 0x95; /* CRC for CMD0(0) */
+	if (cmd == CMD8)
+		n = 0x87; /* CRC for CMD8(0x1AA) */
+	xmit_spi(n);
+
+	/* Receive command response */
+	if (cmd == CMD12)
+		rcvr_spi(); /* Skip a stuff byte when stop reading */
+	n = 10; /* Wait for a valid response in timeout of 10 attempts */
+	do
+		res = rcvr_spi();
+	while ((res & 0x80) && --n);
+
+	return res; /* Return with the response value */
+}
+
+/*--------------------------------------------------------------------------
+
+ Public Functions
+
+ ---------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------*/
+/* Initialize Disk Drive                                                 */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS SD_disk_initialize(BYTE drv /* Physical drive nmuber (0) */
+) {
+	BYTE n, ty, ocr[4];
+
+	if (drv)
+		return STA_NOINIT; /* Supports only single drive */
+	if (Stat & STA_NODISK)
+		return Stat; /* No card in the socket */
+
+	power_on(); /* Force socket power on */
+	//send_initial_clock_train();
+
+	SELECT(); /* CS = L */
+	ty = 0;
+	if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
+		Timer1 = 100; /* Initialization timeout of 1000 msec */
+		if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
+			for (n = 0; n < 4; n++)
+				ocr[n] = rcvr_spi();
+			if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
+				do {
+					if (send_cmd(CMD55, 0) <= 1
+							&& send_cmd(CMD41, 1UL << 30) == 0)
+						break; /* ACMD41 with HCS bit */
+				} while (Timer1);
+				if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
+					for (n = 0; n < 4; n++)
+						ocr[n] = rcvr_spi();
+					ty = (ocr[0] & 0x40) ? 6 : 2;
+				}
+			}
+		} else { /* SDC Ver1 or MMC */
+			ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
+			do {
+				if (ty == 2) {
+					if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0)
+						break; /* ACMD41 */
+				} else {
+					if (send_cmd(CMD1, 0) == 0)
+						break; /* CMD1 */
+				}
+			} while (Timer1);
+			if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
+				ty = 0;
+		}
+	}
+	CardType = ty;
+	DESELECT(); /* CS = H */
+	rcvr_spi(); /* Idle (Release DO) */
+
+	if (ty) /* Initialization succeded */
+		Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
+	else
+		/* Initialization failed */
+		power_off();
+
+	return Stat;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Get Disk Status                                                       */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS SD_disk_status(BYTE drv /* Physical drive nmuber (0) */
+) {
+	if (drv)
+		return STA_NOINIT; /* Supports only single drive */
+	return Stat;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Read Sector(s)                                                        */
+/*-----------------------------------------------------------------------*/
+
+DRESULT SD_disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
+	if (pdrv || !count)
+		return RES_PARERR;
+	if (Stat & STA_NOINIT)
+		return RES_NOTRDY;
+
+	if (!(CardType & 4))
+		sector *= 512; /* Convert to byte address if needed */
+
+	SELECT(); /* CS = L */
+
+	if (count == 1) { /* Single block read */
+		if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
+		&& rcvr_datablock(buff, 512))
+			count = 0;
+	} else { /* Multiple block read */
+		if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
+			do {
+				if (!rcvr_datablock(buff, 512))
+					break;
+				buff += 512;
+			} while (--count);
+			send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
+		}
+	}
+
+	DESELECT(); /* CS = H */
+	rcvr_spi(); /* Idle (Release DO) */
+
+	return count ? RES_ERROR : RES_OK;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Write Sector(s)                                                       */
+/*-----------------------------------------------------------------------*/
+
+#if _READONLY == 0
+DRESULT SD_disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
+	if (pdrv || !count)
+		return RES_PARERR;
+	if (Stat & STA_NOINIT)
+		return RES_NOTRDY;
+	if (Stat & STA_PROTECT)
+		return RES_WRPRT;
+
+	if (!(CardType & 4))
+		sector *= 512; /* Convert to byte address if needed */
+
+	SELECT(); /* CS = L */
+
+	if (count == 1) { /* Single block write */
+		if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
+		&& xmit_datablock(buff, 0xFE))
+			count = 0;
+	} else { /* Multiple block write */
+		if (CardType & 2) {
+			send_cmd(CMD55, 0);
+			send_cmd(CMD23, count); /* ACMD23 */
+		}
+		if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
+			do {
+				if (!xmit_datablock(buff, 0xFC))
+					break;
+				buff += 512;
+			} while (--count);
+			if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
+				count = 1;
+		}
+	}
+
+	DESELECT(); /* CS = H */
+	rcvr_spi(); /* Idle (Release DO) */
+
+	return count ? RES_ERROR : RES_OK;
+}
+#endif /* _READONLY */
+
+/*-----------------------------------------------------------------------*/
+/* Miscellaneous Functions                                               */
+/*-----------------------------------------------------------------------*/
+
+DRESULT SD_disk_ioctl(BYTE drv, /* Physical drive nmuber (0) */
+BYTE ctrl, /* Control code */
+void *buff /* Buffer to send/receive control data */
+) {
+	DRESULT res;
+	BYTE n, csd[16], *ptr = buff;
+	WORD csize;
+
+	if (drv)
+		return RES_PARERR;
+
+	res = RES_ERROR;
+
+	if (ctrl == CTRL_POWER) {
+		switch (*ptr) {
+		case 0: /* Sub control code == 0 (POWER_OFF) */
+			if (chk_power())
+				power_off(); /* Power off */
+			res = RES_OK;
+			break;
+		case 1: /* Sub control code == 1 (POWER_ON) */
+			power_on(); /* Power on */
+			res = RES_OK;
+			break;
+		case 2: /* Sub control code == 2 (POWER_GET) */
+			*(ptr + 1) = (BYTE) chk_power();
+			res = RES_OK;
+			break;
+		default:
+			res = RES_PARERR;
+		}
+	} else {
+		if (Stat & STA_NOINIT)
+			return RES_NOTRDY;
+
+		SELECT(); /* CS = L */
+
+		switch (ctrl) {
+		case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
+			if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
+				if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
+					csize = csd[9] + ((WORD) csd[8] << 8) + 1;
+					*(DWORD*) buff = (DWORD) csize << 10;
+				} else { /* MMC or SDC ver 1.XX */
+					n = (csd[5] & 15) + ((csd[10] & 128) >> 7)
+							+ ((csd[9] & 3) << 1) + 2;
+					csize = (csd[8] >> 6) + ((WORD) csd[7] << 2)
+							+ ((WORD) (csd[6] & 3) << 10) + 1;
+					*(DWORD*) buff = (DWORD) csize << (n - 9);
+				}
+				res = RES_OK;
+			}
+			break;
+
+		case GET_SECTOR_SIZE: /* Get sectors on the disk (WORD) */
+			*(WORD*) buff = 512;
+			res = RES_OK;
+			break;
+
+		case CTRL_SYNC: /* Make sure that data has been written */
+			if (wait_ready() == 0xFF)
+				res = RES_OK;
+			break;
+
+		case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
+			if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
+			&& rcvr_datablock(ptr, 16))
+				res = RES_OK;
+			break;
+
+		case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
+			if (send_cmd(CMD10, 0) == 0 /* READ_CID */
+			&& rcvr_datablock(ptr, 16))
+				res = RES_OK;
+			break;
+
+		case MMC_GET_OCR: /* Receive OCR as an R3 resp (4 bytes) */
+			if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
+				for (n = 0; n < 4; n++)
+					*ptr++ = rcvr_spi();
+				res = RES_OK;
+			}
+
+//        case MMC_GET_TYPE :    /* Get card type flags (1 byte) */
+//            *ptr = CardType;
+//            res = RES_OK;
+//            break;
+
+		default:
+			res = RES_PARERR;
+		}
+
+		DESELECT(); /* CS = H */
+		rcvr_spi(); /* Idle (Release DO) */
+	}
+
+	return res;
+}
+
+/*-----------------------------------------------------------------------*/
+/* Device Timer Interrupt Procedure  (Platform dependent)                */
+/*-----------------------------------------------------------------------*/
+/* This function must be called in period of 10ms                        */
+
+void disk_timerproc(void) {
+//    BYTE n, s;
+	BYTE n;
+
+	n = Timer1; /* 100Hz decrement timer */
+	if (n)
+		Timer1 = --n;
+	n = Timer2;
+	if (n)
+		Timer2 = --n;
+
+}
+
+volatile unsigned short int sdcard_timer;
+
+void inline sdcard_systick_timerproc(void) {
+	++sdcard_timer;
+	if (sdcard_timer >= 100) {
+		sdcard_timer = 0;
+		disk_timerproc();
+	}
+}
+
+/*---------------------------------------------------------*/
+/* User Provided Timer Function for FatFs module           */
+/*---------------------------------------------------------*/
+/* This is a real time clock service to be called from     */
+/* FatFs module. Any valid time must be returned even if   */
+/* the system does not support a real time clock.          */
+
+DWORD SD_get_fattime(void) {
+
+	return ((2007UL - 1980) << 25) // Year = 2007
+	| (6UL << 21) // Month = June
+			| (5UL << 16) // Day = 5
+			| (11U << 11) // Hour = 11
+			| (38U << 5) // Min = 38
+			| (0U >> 1) // Sec = 0
+	;
+
+}
+

+ 53 - 0
obj/obj_spi_sd_stm32.h

@@ -0,0 +1,53 @@
+#ifndef SD_STM32_HEADER
+#define SD_STM32_HEADER
+
+#include "main.h"
+#include "diskio.h"
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include "obj_spi_sd_stm32.h"
+
+#include "ff_gen_drv.h"
+
+
+
+#define TRUE  1
+#define FALSE 0
+//#define bool  char
+//#define BYTE  char
+
+/* Definitions for MMC/SDC command */
+#define CMD0    (0x40+0)    /* GO_IDLE_STATE */
+#define CMD1    (0x40+1)    /* SEND_OP_COND */
+#define CMD8    (0x40+8)    /* SEND_IF_COND */
+#define CMD9    (0x40+9)    /* SEND_CSD */
+#define CMD10    (0x40+10)    /* SEND_CID */
+#define CMD12    (0x40+12)    /* STOP_TRANSMISSION */
+#define CMD16    (0x40+16)    /* SET_BLOCKLEN */
+#define CMD17    (0x40+17)    /* READ_SINGLE_BLOCK */
+#define CMD18    (0x40+18)    /* READ_MULTIPLE_BLOCK */
+#define CMD23    (0x40+23)    /* SET_BLOCK_COUNT */
+#define CMD24    (0x40+24)    /* WRITE_BLOCK */
+#define CMD25    (0x40+25)    /* WRITE_MULTIPLE_BLOCK */
+#define CMD41    (0x40+41)    /* SEND_OP_COND (ACMD) */
+#define CMD55    (0x40+55)    /* APP_CMD */
+#define CMD58    (0x40+58)    /* READ_OCR */
+
+/*-----------------------------------------------------------------------*/
+/* Device Timer Interrupt Procedure  (Platform dependent)                */
+/*-----------------------------------------------------------------------*/
+/* This function must be called in period of 10ms                        */
+
+void sdcard_systick_timerproc(void);
+DSTATUS SD_disk_initialize(BYTE drv);
+DSTATUS SD_disk_status(BYTE drv);
+DRESULT SD_disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
+DRESULT SD_disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
+DRESULT SD_disk_ioctl(BYTE drv, /* Physical drive nmuber (0) */
+BYTE ctrl, /* Control code */
+void *buff /* Buffer to send/receive control data */
+);
+
+#endif
+

+ 140 - 0
sys/sys_api.c

@@ -0,0 +1,140 @@
+#include "sys_type.h"
+#include "sys_api.h"
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//系统时钟初始化	
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2017/6/8
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved
+//********************************************************************************
+//修改说明
+//无
+////////////////////////////////////////////////////////////////////////////////// 
+
+//使能CPU的L1-Cache
+void Cache_Enable(void)
+{
+    SCB_EnableICache();//使能I-Cache
+    SCB_EnableDCache();//使能D-Cache   
+	SCB->CACR|=1<<2;   //强制D-Cache透写,如不开启,实际使用中可能遇到各种问题	
+}
+
+//时钟设置函数
+//Fvco=Fs*(plln/pllm);
+//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
+//Fq=Fvco/pllq=Fs*(plln/(pllm*pllq));
+
+//Fvco:VCO频率
+//Fsys:系统时钟频率,也是PLL1的p分频输出时钟频率
+//Fq:PLL1的q分频输出时钟频率
+//Fs:PLL输入时钟频率,可以是HSI,CSI,HSE等. 
+
+//plln:PLL1倍频系数(PLL倍频),取值范围:4~512.
+//pllm:PLL1预分频系数(进PLL之前的分频),取值范围:2~63.
+//pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)
+//pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128.
+
+//CPU频率(rcc_c_ck)=sys_d1cpre_ck=400Mhz 
+//rcc_aclk=rcc_hclk3=200Mhz
+//AHB1/2/3/4(rcc_hclk1/2/3/4)=200Mhz  
+//APB1/2/3/4(rcc_pclk1/2/3/4)=100Mhz  
+//FMC时钟频率=pll2_r_ck=((25/25)*512/2)=256Mhz
+
+//外部晶振为25M的时候,推荐值:plln=160,pllm=5,pllp=2,pllq=2.
+//得到:Fvco=25*(160/5)=800Mhz
+//     Fsys=800/2=400Mhz
+//     Fq=800/2=400Mhz
+//返回值:0,成功;1,失败。
+
+#ifdef  USE_FULL_ASSERT
+//当编译提示出错的时候此函数用来报告错误的文件和所在行
+//file:指向源文件
+//line:指向在文件中的行数
+void assert_failed(uint8_t* file, uint32_t line)
+{ 
+	while (1)
+	{
+	}
+}
+#endif
+
+//判断I_Cache是否打开
+//返回值:0 关闭,1 打开
+u8 Get_ICahceSta(void)
+{
+    u8 sta;
+    sta=((SCB->CCR)>>17)&0X01;
+    return sta;
+}
+
+//判断I_Dache是否打开
+//返回值:0 关闭,1 打开
+u8 Get_DCahceSta(void)
+{
+    u8 sta;
+    sta=((SCB->CCR)>>16)&0X01;
+    return sta;
+}
+
+#if defined(__clang__) //使用V6编译器(clang)
+//THUMB指令不支持汇编内联
+//采用如下方法实现执行汇编指令WFI  
+void __attribute__((noinline)) WFI_SET(void)
+{
+    __asm__("wfi");
+}
+
+//关闭所有中断(但是不包括fault和NMI中断)   
+void __attribute__((noinline)) INTX_DISABLE(void)
+{
+    __asm__("cpsid i \t\n"
+            "bx lr");
+}
+
+//开启所有中断
+void __attribute__((noinline)) INTX_ENABLE(void)
+{
+    __asm__("cpsie i \t\n"
+            "bx lr");
+}
+
+//设置栈顶地址
+//addr:栈顶地址
+void __attribute__((noinline)) MSR_MSP(u32 addr) 
+{
+    __asm__("msr msp, r0 \t\n"
+            "bx r14");
+}
+#elif defined (__CC_ARM)    //使用V5编译器(ARMCC)
+
+//THUMB指令不支持汇编内联
+//采用如下方法实现执行汇编指令WFI  
+__asm void WFI_SET(void)
+{
+	WFI;		  
+}
+//关闭所有中断(但是不包括fault和NMI中断)
+__asm void INTX_DISABLE(void)
+{
+	CPSID   I
+	BX      LR	  
+}
+//开启所有中断
+__asm void INTX_ENABLE(void)
+{
+	CPSIE   I
+	BX      LR  
+}
+//设置栈顶地址
+//addr:栈顶地址
+__asm void MSR_MSP(u32 addr) 
+{
+	MSR MSP, r0 			//set Main Stack value
+	BX r14
+}
+#endif

+ 83 - 0
sys/sys_api.h

@@ -0,0 +1,83 @@
+#ifndef SYS_API_H
+#define SYS_API_H
+#include "stm32f7xx.h"
+#include "core_cm7.h"
+#include "stm32f7xx_hal.h"
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//系统时钟初始化	
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2017/6/7
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved
+//********************************************************************************
+//修改说明
+//无
+//////////////////////////////////////////////////////////////////////////////////  
+
+//0,不支持os
+//1,支持os
+#define SYSTEM_SUPPORT_OS		0		//定义系统文件夹是否支持OS	
+///////////////////////////////////////////////////////////////////////////////////
+//定义一些常用的数据类型短关键字 
+typedef int32_t  s32;
+typedef int16_t s16;
+typedef int8_t  s8;
+
+typedef const int32_t sc32;  
+typedef const int16_t sc16;  
+typedef const int8_t sc8;  
+
+typedef __IO int32_t  vs32;
+typedef __IO int16_t  vs16;
+typedef __IO int8_t   vs8;
+
+typedef __I int32_t vsc32;  
+typedef __I int16_t vsc16; 
+typedef __I int8_t vsc8;   
+
+typedef uint32_t  u32;
+typedef uint16_t u16;
+typedef uint8_t  u8;
+
+typedef const uint32_t uc32;  
+typedef const uint16_t uc16;  
+typedef const uint8_t uc8; 
+
+typedef __IO uint32_t  vu32;
+typedef __IO uint16_t vu16;
+typedef __IO uint8_t  vu8;
+
+typedef __I uint32_t vuc32;  
+typedef __I uint16_t vuc16; 
+typedef __I uint8_t vuc8;  
+
+#define ON	1
+#define OFF	0
+#define Write_Through() (*(__IO uint32_t*)0XE000EF9C=1UL<<2) //Cache透写模式
+
+void Cache_Enable(void);                                    //使能STM32H7的L1-Cahce
+
+u8 Get_ICahceSta(void);//判断I_Cache是否打开
+u8 Get_DCahceSta(void);//判断I_Dache是否打开
+
+#if defined(__clang__) //使用V6编译器(clang)
+void __attribute__((noinline)) WFI_SET(void);
+void __attribute__((noinline)) INTX_DISABLE(void);
+void __attribute__((noinline)) INTX_ENABLE(void);
+void __attribute__((noinline)) MSR_MSP(u32 addr);
+#elif defined (__CC_ARM)    //使用V5编译器(ARMCC)
+//以下为汇编函数
+void WFI_SET(void);		//执行WFI指令
+void INTX_DISABLE(void);//关闭所有中断
+void INTX_ENABLE(void);	//开启所有中断
+void MSR_MSP(u32 addr);	//设置堆栈地址 
+#endif
+
+
+#endif
+

+ 234 - 0
sys/sys_delay.c

@@ -0,0 +1,234 @@
+#include "sys_delay.h"
+#include "sys_type.h"
+////////////////////////////////////////////////////////////////////////////////// 	 
+//如果使用ucos,则包括下面的头文件即可.
+#if SYSTEM_SUPPORT_OS
+#include "includes.h"					//ucos 使用	  
+#endif
+//////////////////////////////////////////////////////////////////////////////////  
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//使用SysTick的普通计数模式对延迟进行管理(支持ucosii)
+//包括delay_us,delay_ms
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2017/6/8
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved
+//********************************************************************************
+//修改说明
+////////////////////////////////////////////////////////////////////////////////// 
+
+static u32 fac_us=0;							//us延时倍乘数
+
+#if SYSTEM_SUPPORT_OS 	
+static u16 fac_ms=0;							//ms延时倍乘数,在os下,代表每个节拍的ms数
+#endif
+
+#if SYSTEM_SUPPORT_OS							//如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).
+//当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
+//首先是3个宏定义:
+//delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数
+//delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick
+//delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
+//然后是3个函数:
+//delay_osschedlock:用于锁定OS任务调度,禁止调度
+//delay_osschedunlock:用于解锁OS任务调度,重新开启调度
+//delay_ostimedly:用于OS延时,可以引起任务调度.
+
+//本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
+//支持UCOSII
+#ifdef 	OS_CRITICAL_METHOD						//OS_CRITICAL_METHOD定义了,说明要支持UCOSII				
+#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
+#define delay_ostickspersec	OS_TICKS_PER_SEC	//OS时钟节拍,即每秒调度次数
+#define delay_osintnesting 	OSIntNesting		//中断嵌套级别,即中断嵌套次数
+#endif
+
+//支持UCOSIII
+#ifdef 	CPU_CFG_CRITICAL_METHOD					//CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII	
+#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
+#define delay_ostickspersec	OSCfg_TickRate_Hz	//OS时钟节拍,即每秒调度次数
+#define delay_osintnesting 	OSIntNestingCtr		//中断嵌套级别,即中断嵌套次数
+#endif
+
+
+//us级延时时,关闭任务调度(防止打断us级延迟)
+void delay_osschedlock(void)
+{
+#ifdef CPU_CFG_CRITICAL_METHOD   			//使用UCOSIII
+	OS_ERR err; 
+	OSSchedLock(&err);						//UCOSIII的方式,禁止调度,防止打断us延时
+#else										//否则UCOSII
+	OSSchedLock();							//UCOSII的方式,禁止调度,防止打断us延时
+#endif
+}
+
+//us级延时时,恢复任务调度
+void delay_osschedunlock(void)
+{	
+#ifdef CPU_CFG_CRITICAL_METHOD   			//使用UCOSIII
+	OS_ERR err; 
+	OSSchedUnlock(&err);					//UCOSIII的方式,恢复调度
+#else										//否则UCOSII
+	OSSchedUnlock();						//UCOSII的方式,恢复调度
+#endif
+}
+
+//调用OS自带的延时函数延时
+//ticks:延时的节拍数
+void delay_ostimedly(u32 ticks)
+{
+#ifdef CPU_CFG_CRITICAL_METHOD
+	OS_ERR err; 
+	OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);//UCOSIII延时采用周期模式
+#else
+	OSTimeDly(ticks);						//UCOSII延时
+#endif 
+}
+ 
+//systick中断服务函数,使用OS时用到
+void SysTick_Handler(void)
+{	
+    HAL_IncTick();
+	if(delay_osrunning==1)					//OS开始跑了,才执行正常的调度处理
+	{
+		OSIntEnter();						//进入中断
+		OSTimeTick();       				//调用ucos的时钟服务程序               
+		OSIntExit();       	 				//触发任务切换软中断
+	}
+}
+#endif
+			   
+//初始化延迟函数
+//当使用ucos的时候,此函数会初始化ucos的时钟节拍
+//SYSTICK的时钟固定为AHB时钟的1/8
+//SYSCLK:系统时钟频率
+void sys_delay_init(u16 SYSCLK)
+{
+#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
+	u32 reload;
+#endif
+    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK
+	fac_us=SYSCLK;						    //不论是否使用OS,fac_us都需要使用
+#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
+	reload=SYSCLK;					        //每秒钟的计数次数 单位为K	   
+	reload*=1000000/delay_ostickspersec;	//根据delay_ostickspersec设定溢出时间
+											//reload为24位寄存器,最大值:16777216,在216M下,约合77.7ms左右	
+	fac_ms=1000/delay_ostickspersec;		//代表OS可以延时的最少单位	   
+	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
+	SysTick->LOAD=reload; 					//每1/OS_TICKS_PER_SEC秒中断一次	
+	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
+#endif 
+}								    
+
+#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
+//延时nus
+//nus:要延时的us数.	
+//nus:0~204522252(最大值即2^32/fac_us@fac_us=21)	    								   
+void sys_delay_us(u32 nus)
+{		
+	u32 ticks;
+	u32 told,tnow,tcnt=0;
+	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
+	ticks=nus*fac_us; 						//需要的节拍数 
+	delay_osschedlock();					//阻止OS调度,防止打断us延时
+	told=SysTick->VAL;        				//刚进入时的计数器值
+	while(1)
+	{
+		tnow=SysTick->VAL;	
+		if(tnow!=told)
+		{	    
+			if(tnow<told)tcnt+=told-tnow;	//这里注意一下SYSTICK是一个递减的计数器就可以了.
+			else tcnt+=reload-tnow+told;	    
+			told=tnow;
+			if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.
+		}  
+	};
+	delay_osschedunlock();					//恢复OS调度											    
+}  
+//延时nms
+//nms:要延时的ms数
+//nms:0~65535
+void sys_delay_ms(u16 nms)
+{	
+	if(delay_osrunning&&delay_osintnesting==0)//如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)	    
+	{		 
+		if(nms>=fac_ms)						//延时的时间大于OS的最少时间周期 
+		{ 
+   			delay_ostimedly(nms/fac_ms);	//OS延时
+		}
+		nms%=fac_ms;						//OS已经无法提供这么小的延时了,采用普通方式延时    
+	}
+	delay_us((u32)(nms*1000));				//普通方式延时
+}
+#else  //不用ucos时
+//延时nus
+//nus为要延时的us数.	
+//注意:nus的值不要大于1000us
+void sys_delay_us(u32 nus)
+{		
+	u32 ticks;
+	u32 told,tnow,tcnt=0;
+	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
+	ticks=nus*fac_us; 						//需要的节拍数 
+	told=SysTick->VAL;        				//刚进入时的计数器值
+	while(1)
+	{
+		tnow=SysTick->VAL;	
+		if(tnow!=told)
+		{	    
+			if(tnow<told)tcnt+=told-tnow;	//这里注意一下SYSTICK是一个递减的计数器就可以了.
+			else tcnt+=reload-tnow+told;	    
+			told=tnow;
+			if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.
+		}  
+	};
+}
+ 
+//延时nms
+//nms:要延时的ms数
+void sys_delay_ms(u16 nms)
+{
+	u32 i;
+	for(i=0;i<nms;i++) sys_delay_us(1000);
+}
+
+#endif
+			 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 24 - 0
sys/sys_delay.h

@@ -0,0 +1,24 @@
+#ifndef SYS_DELAY_H
+#define SYS_DELAY_H
+#include "sys_type.h"  
+//////////////////////////////////////////////////////////////////////////////////  
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//使用SysTick的普通计数模式对延迟进行管理(支持ucosii)
+//包括delay_us,delay_ms
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2017/6/3
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved
+//********************************************************************************
+//修改说明
+////////////////////////////////////////////////////////////////////////////////// 
+
+void sys_delay_init(u16 SYSCLK);
+void sys_delay_ms(u16 nms);
+void sys_delay_us(u32 nus);
+#endif
+

+ 319 - 0
sys/sys_malloc.c

@@ -0,0 +1,319 @@
+
+#include "sys_malloc.h"	   
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//内存管理 驱动代码	   
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2018/7/30
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved  
+//********************************************************************************
+//修改说明
+//无
+////////////////////////////////////////////////////////////////////////////////// 	 
+
+
+//内存池(64字节对齐)
+__align(64) u8 mem1base[MEM1_MAX_SIZE];													//内部SRAM内存池
+//内存管理表
+u32 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];													//内部SRAM内存池MAP
+
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+__align(64) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0XC01F4000)));					//外部SDRAM内存池,前面2M给LTDC用了(1280*800*2)
+u32 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0XC01F4000+MEM2_MAX_SIZE)));	//外部SDRAM内存池MAP
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+__align(64) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0x30000000)));					//内部SRAM1+SRAM2内存池
+u32 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0x30000000+MEM3_MAX_SIZE)));	//内部SRAM1+SRAM2内存池MAP
+#endif
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+__align(64) u8 mem4base[MEM4_MAX_SIZE] __attribute__((at(0x38000000)));					//内部SRAM4内存池
+u32 mem4mapbase[MEM4_ALLOC_TABLE_SIZE] __attribute__((at(0x38000000+MEM4_MAX_SIZE)));	//内部SRAM4内存池MAP
+#endif
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+__align(64) u8 mem5base[MEM5_MAX_SIZE] __attribute__((at(0x20000000)));					//内部DTCM内存池
+u32 mem5mapbase[MEM5_ALLOC_TABLE_SIZE] __attribute__((at(0x20000000+MEM5_MAX_SIZE)));	//内部DTCM内存池MAP
+#endif
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+__align(64) u8 mem6base[MEM6_MAX_SIZE] __attribute__((at(0x00000000)));					//内部ITCM内存池 
+u32 mem6mapbase[MEM6_ALLOC_TABLE_SIZE] __attribute__((at(0x00000000+MEM6_MAX_SIZE)));	//内部ITCM内存池MAP 
+#endif
+
+
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+
+#endif
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+
+#endif
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+
+#endif
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+
+#endif
+
+
+
+
+
+//内存管理参数	   
+const u32 memtblsize[SRAMBANK]={
+		MEM1_ALLOC_TABLE_SIZE,
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+		MEM2_ALLOC_TABLE_SIZE,
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+		MEM3_ALLOC_TABLE_SIZE,
+#endif
+	
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+		MEM4_ALLOC_TABLE_SIZE,
+#endif
+	
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+		MEM5_ALLOC_TABLE_SIZE,
+#endif
+	
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+		MEM6_ALLOC_TABLE_SIZE
+#endif		
+			};	//内存表大小
+const u32 memblksize[SRAMBANK]={
+	MEM1_BLOCK_SIZE,
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+	MEM2_BLOCK_SIZE,
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+	MEM3_BLOCK_SIZE,
+
+#endif
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+	MEM4_BLOCK_SIZE,
+#endif
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	MEM5_BLOCK_SIZE,
+#endif
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	MEM6_BLOCK_SIZE
+#endif
+	};					//内存分块大小
+const u32 memsize[SRAMBANK]	={
+	MEM1_MAX_SIZE,
+
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+	MEM2_MAX_SIZE,
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+	MEM3_MAX_SIZE,	
+#endif
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+	MEM4_MAX_SIZE,
+#endif
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	MEM5_MAX_SIZE,
+#endif
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	MEM6_MAX_SIZE
+#endif
+
+	};								//内存总大小
+
+//内存管理控制器
+															
+
+struct _m_mallco_dev mallco_dev=
+{
+	.init = my_mem_init,															//内存初始化
+	.perused =  my_mem_perused,															//内存使用率
+	.membase[SRAMIN] = mem1base,					//内存池
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+	.membase[SRAMEX] = mem2base,
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+	mem3base,
+#endif
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+	mem4base,
+#endif
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	mem5base,
+#endif
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	mem6base,
+#endif
+	.memmap[SRAMIN] = mem1mapbase,//内存管理状态表
+#ifdef SRAMEX   	//1		//外部内存池(SDRAM),SDRAM共32MB
+	mem2mapbase,
+#endif
+
+#ifdef SRAM12			//2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+	mem3mapbase,
+#endif
+#ifdef SRAM4		  //3		//SRAM4内存池,SRAM4共64KB
+	mem4mapbase,
+#endif
+#ifdef SRAMDTCM 	//4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	mem5mapbase,
+#endif
+#ifdef SRAMITCM 	//5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+	mem6mapbase
+#endif
+
+	.memrdy= {0,0,0,0,0,0,}								  		 					//内存管理未就绪
+};
+
+//复制内存
+//*des:目的地址
+//*src:源地址
+//n:需要复制的内存长度(字节为单位)
+void mymemcpy(void *des,void *src,u32 n)  
+{  
+    u8 *xdes=des;
+	u8 *xsrc=src; 
+    while(n--)*xdes++=*xsrc++;  
+}  
+//设置内存
+//*s:内存首地址
+//c :要设置的值
+//count:需要设置的内存大小(字节为单位)
+void mymemset(void *s,u8 c,u32 count)  
+{  
+    u8 *xs = s;  
+    while(count--)*xs++=c;  
+}	
+//内存管理初始化  
+//memx:所属内存块
+void my_mem_init(u8 memx)  
+{  
+    mymemset(mallco_dev.memmap[memx],0,memtblsize[memx]*4);	//内存状态表数据清零  
+ 	mallco_dev.memrdy[memx]=1;								//内存管理初始化OK  
+}  
+//获取内存使用率
+//memx:所属内存块
+//返回值:使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
+u16 my_mem_perused(u8 memx)  
+{  
+    u32 used=0;  
+    u32 i;  
+    for(i=0;i<memtblsize[memx];i++)  
+    {  
+        if(mallco_dev.memmap[memx][i])used++; 
+    } 
+    return (used*1000)/(memtblsize[memx]);  
+}  
+//内存分配(内部调用)
+//memx:所属内存块
+//size:要分配的内存大小(字节)
+//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 
+u32 my_mem_malloc(u8 memx,u32 size)  
+{  
+    signed long offset=0;  
+    u32 nmemb;	//需要的内存块数  
+	u32 cmemb=0;//连续空内存块数
+    u32 i;  
+    if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先执行初始化 
+    if(size==0)return 0XFFFFFFFF;//不需要分配
+    nmemb=size/memblksize[memx];  	//获取需要分配的连续内存块数
+    if(size%memblksize[memx])nmemb++;  
+    for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整个内存控制区  
+    {     
+		if(!mallco_dev.memmap[memx][offset])cmemb++;//连续空内存块数增加
+		else cmemb=0;								//连续内存块清零
+		if(cmemb==nmemb)							//找到了连续nmemb个空内存块
+		{
+            for(i=0;i<nmemb;i++)  					//标注内存块非空 
+            {  
+                mallco_dev.memmap[memx][offset+i]=nmemb;  
+            }  
+            return (offset*memblksize[memx]);//返回偏移地址  
+		}
+    }  
+    return 0XFFFFFFFF;//未找到符合分配条件的内存块  
+}  
+//释放内存(内部调用) 
+//memx:所属内存块
+//offset:内存地址偏移
+//返回值:0,释放成功;1,释放失败;  
+u8 my_mem_free(u8 memx,u32 offset)  
+{  
+    int i;  
+    if(!mallco_dev.memrdy[memx])//未初始化,先执行初始化
+	{
+		mallco_dev.init(memx);    
+        return 1;//未初始化  
+    }  
+    if(offset<memsize[memx])//偏移在内存池内. 
+    {  
+        int index=offset/memblksize[memx];			//偏移所在内存块号码  
+        int nmemb=mallco_dev.memmap[memx][index];	//内存块数量
+        for(i=0;i<nmemb;i++)  						//内存块清零
+        {  
+            mallco_dev.memmap[memx][index+i]=0;  
+        }  
+        return 0;  
+    }else return 2;//偏移超区了.  
+}  
+//释放内存(外部调用) 
+//memx:所属内存块
+//ptr:内存首地址 
+void myfree(u8 memx,void *ptr)  
+{  
+	u32 offset;   
+	if(ptr==NULL)return;//地址为0.  
+ 	offset=(u32)ptr-(u32)mallco_dev.membase[memx];     
+    my_mem_free(memx,offset);	//释放内存      
+}  
+//分配内存(外部调用)
+//memx:所属内存块
+//size:内存大小(字节)
+//返回值:分配到的内存首地址.
+void *mymalloc(u8 memx,u32 size)  
+{  
+    u32 offset;   
+	offset=my_mem_malloc(memx,size);  	   	 	   
+    if(offset==0XFFFFFFFF)return NULL;  
+    else return (void*)((u32)mallco_dev.membase[memx]+offset);  
+}  
+//重新分配内存(外部调用)
+//memx:所属内存块
+//*ptr:旧内存首地址
+//size:要分配的内存大小(字节)
+//返回值:新分配到的内存首地址.
+void *myrealloc(u8 memx,void *ptr,u32 size)  
+{  
+    u32 offset;    
+    offset=my_mem_malloc(memx,size);   	
+    if(offset==0XFFFFFFFF)return NULL;     
+    else  
+    {  									   
+	    mymemcpy((void*)((u32)mallco_dev.membase[memx]+offset),ptr,size);	//拷贝旧内存内容到新内存   
+        myfree(memx,ptr);  											  		//释放旧内存
+        return (void*)((u32)mallco_dev.membase[memx]+offset);  				//返回新内存首地址
+    }  
+}
+
+
+
+
+
+
+
+
+
+
+
+

+ 115 - 0
sys/sys_malloc.h

@@ -0,0 +1,115 @@
+#ifndef __MALLOC_H
+#define __MALLOC_H
+#include "sys_type.h" 
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32H7开发板
+//内存管理 驱动代码	   
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2018/7/30
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved  
+//********************************************************************************
+//修改说明
+//无
+////////////////////////////////////////////////////////////////////////////////// 	 
+
+ 
+#ifndef NULL
+#define NULL 0
+#endif
+
+//定义六个内存池
+#define SRAMIN	 		0		//AXI内存池,AXI共512KB 
+//#define SRAMEX   	1		//外部内存池(SDRAM),SDRAM共32MB
+//#define SRAM12		2		//SRAM1/2/3内存池,SRAM1+SRAM2,共256KB
+//#define SRAM4		  3		//SRAM4内存池,SRAM4共64KB
+//#define SRAMDTCM 	4		//DTCM内存池,DTCM共128KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+//#define SRAMITCM 	5		//ITCM内存池,DTCM共64 KB,此部分内存仅CPU和MDMA(通过AHBS)可以访问!!!!
+
+
+
+#define SRAMBANK 	6		//定义支持的SRAM块数.	
+
+#ifdef SRAMIN
+//mem1内存参数设定.mem1是H7内部的AXI内存.
+#define MEM1_BLOCK_SIZE			64  	  						//内存块大小为64字节
+#define MEM1_MAX_SIZE			448*1024  						//最大管理内存 448K,H7的AXI内存总共512KB
+#define MEM1_ALLOC_TABLE_SIZE	MEM1_MAX_SIZE/MEM1_BLOCK_SIZE 	//内存表大小
+#endif 
+
+#ifdef SRAMEX
+//mem2内存参数设定.mem2是外部的SDRAM内存
+#define MEM2_BLOCK_SIZE			64  	  						//内存块大小为64字节
+#define MEM2_MAX_SIZE			28912 *1024  					//最大管理内存28912K,外扩SDRAM总共32MB,LTDC占了2MB,还剩30MB.
+#define MEM2_ALLOC_TABLE_SIZE	MEM2_MAX_SIZE/MEM2_BLOCK_SIZE 	//内存表大小
+#endif 	
+
+#ifdef SRAM12
+//mem3内存参数设定.mem3是H7内部的SRAM1+SRAM2内存
+#define MEM3_BLOCK_SIZE			64  	  						//内存块大小为64字节
+#define MEM3_MAX_SIZE			240 *1024  						//最大管理内存240K,H7的SRAM1+SRAM2共256KB
+#define MEM3_ALLOC_TABLE_SIZE	MEM3_MAX_SIZE/MEM3_BLOCK_SIZE 	//内存表大小
+#endif 		
+
+#ifdef SRAM4
+//mem4内存参数设定.mem4是H7内部的SRAM4内存
+#define MEM4_BLOCK_SIZE			64  	  						//内存块大小为64字节
+#define MEM4_MAX_SIZE			60 *1024  						//最大管理内存60K,H7的SRAM4共64KB
+#define MEM4_ALLOC_TABLE_SIZE	MEM4_MAX_SIZE/MEM4_BLOCK_SIZE 	//内存表大小
+#endif 	
+
+#ifdef SRAMDTCM
+//mem5内存参数设定.mem5是H7内部的DTCM内存,此部分内存仅CPU和MDMA可以访问!!!!!!
+#define MEM5_BLOCK_SIZE			64  	  						//内存块大小为64字节
+#define MEM5_MAX_SIZE			120 *1024  						//最大管理内存120K,H7的DTCM共128KB
+#define MEM5_ALLOC_TABLE_SIZE	MEM5_MAX_SIZE/MEM5_BLOCK_SIZE 	//内存表大小
+#endif 	
+
+#ifdef SRAMITCM
+//mem6内存参数设定.mem6是H7内部的ITCM内存,此部分内存仅CPU和MDMA可以访问!!!!!!
+#define MEM6_BLOCK_SIZE			64  	  						//内存块大小为64字节
+#define MEM6_MAX_SIZE			60 *1024  						//最大管理内存60K,H7的ITCM共64KB
+#define MEM6_ALLOC_TABLE_SIZE	MEM6_MAX_SIZE/MEM6_BLOCK_SIZE 	//内存表大小
+#endif 			 
+
+
+//内存管理控制器
+struct _m_mallco_dev
+{
+	void (*init)(u8);					//初始化
+	u16 (*perused)(u8);		  	    	//内存使用率
+	u8 	*membase[SRAMBANK];				//内存池 管理SRAMBANK个区域的内存
+	u32 *memmap[SRAMBANK]; 				//内存管理状态表
+	u8  memrdy[SRAMBANK]; 				//内存管理是否就绪
+};
+extern struct _m_mallco_dev mallco_dev;	 //在mallco.c里面定义
+
+void mymemset(void *s,u8 c,u32 count);	//设置内存
+void mymemcpy(void *des,void *src,u32 n);//复制内存     
+void my_mem_init(u8 memx);				//内存管理初始化函数(外/内部调用)
+u32 my_mem_malloc(u8 memx,u32 size);	//内存分配(内部调用)
+u8 my_mem_free(u8 memx,u32 offset);		//内存释放(内部调用)
+u16 my_mem_perused(u8 memx) ;			//获得内存使用率(外/内部调用) 
+////////////////////////////////////////////////////////////////////////////////
+//用户调用函数
+void myfree(u8 memx,void *ptr);  			//内存释放(外部调用)
+void *mymalloc(u8 memx,u32 size);			//内存分配(外部调用)
+void *myrealloc(u8 memx,void *ptr,u32 size);//重新分配内存(外部调用)
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 63 - 0
sys/sys_type.h

@@ -0,0 +1,63 @@
+#ifndef SYS_TYPE_H
+#define SYS_TYPE_H
+#include "stm32f7xx.h"
+#include "core_cm7.h"
+#include "stm32f7xx_hal.h"
+//////////////////////////////////////////////////////////////////////////////////	 
+//本程序只供学习使用,未经作者许可,不得用于其它任何用途
+//ALIENTEK STM32F429开发板
+//系统时钟初始化	
+//包括时钟设置/中断管理/GPIO设置等
+//正点原子@ALIENTEK
+//技术论坛:www.openedv.com
+//创建日期:2015/6/10
+//版本:V1.0
+//版权所有,盗版必究。
+//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
+//All rights reserved
+//********************************************************************************
+//修改说明
+//无
+//////////////////////////////////////////////////////////////////////////////////  
+
+//0,不支持os
+//1,支持os
+//#define SYSTEM_SUPPORT_OS		0		//定义系统文件夹是否支持OS
+///////////////////////////////////////////////////////////////////////////////////
+//定义一些常用的数据类型短关键字 
+typedef int32_t  s32;
+typedef int16_t s16;
+typedef int8_t  s8;
+
+typedef const int32_t sc32;  
+typedef const int16_t sc16;  
+typedef const int8_t sc8;  
+
+typedef __IO int32_t  vs32;
+typedef __IO int16_t  vs16;
+typedef __IO int8_t   vs8;
+
+typedef __I int32_t vsc32;  
+typedef __I int16_t vsc16; 
+typedef __I int8_t vsc8;   
+
+typedef uint32_t  u32;
+typedef uint16_t u16;
+typedef uint8_t  u8;
+
+typedef const uint32_t uc32;  
+typedef const uint16_t uc16;  
+typedef const uint8_t uc8; 
+
+typedef __IO uint32_t  vu32;
+typedef __IO uint16_t vu16;
+typedef __IO uint8_t  vu8;
+
+typedef __I uint32_t vuc32;  
+typedef __I uint16_t vuc16; 
+typedef __I uint8_t vuc8;  
+	 
+
+
+#endif
+