/****************************************************************************** 版权所有: 文件名称: dspi.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2008-08-19 功能说明: dspi驱动程序。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ //DSPI内部RAM地址 //四个DSPI模块地址 #define DSPI0_MODULE_ADDRESS 0xFC05C000 #define DSPI1_MODULE_ADDRESS 0xFC03C000 #define DSPI2_MODULE_ADDRESS 0xEC038000 #define DSPI3_MODULE_ADDRESS 0xEC03C000 #if (CFG_DSPI_INDEX == 0) #define DSPI_PM_REG MCF_PMM_PPMCR0 #define DSPI_PM_INDEX 23 #elif (CFG_DSPI_INDEX == 1) #define DSPI_PM_REG MCF_PMM_PPMCR0 #define DSPI_PM_INDEX 15 #endif /*------------------------------ 全局变量 ------------------------------------- */ //总线占用状态 int gh_dspi = 0; /*------------------------------ 函数声明 ------------------------------------- */ /*------------------------------ 外部函数 ------------------------------------- */ /****************************************************************************** 函数名称: dspi_init 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-19 函数说明: qspi初始化。 参数说明: 无 返回值: 成功返回0. 修改记录: */ #define _MCF_DSPI_MCR(x) (*(vuint32*)(0xEC038000 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) #define _MCF_DSPI_TCR(x) (*(vuint32*)(0xEC038008 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) #define _MCF_DSPI_RSER(x) (*(vuint32*)(0xEC038030 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) #define _MCF_DSPI_CTAR1(x) (*(vuint32*)(0xEC038010 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) #define _MCF_DSPI_SR(x) (*(vuint32*)(0xEC03802C + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) #define _MCF_DSPI_PUSHR(x) (*(vuint32*)(0xEC038034 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) #define _MCF_DSPI_POPR(x) (*(vuint32*)(0xEC038038 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000)))) int dspi_init(void) { #if 0 // SPI总线初始化前,先打开ESAM模块的电源,解决esam模块有时工作不正常的问题。 // 上电并延时1ms GPIO_ESAM_POWER_INIT(); ustimer_delay(USTIMER_MS*10); //模块打开 DSPI_PM_REG = DSPI_PM_INDEX; //使用GPIO控制CS GPIO_DSPI_CS_ESAM_INIT(); // 设置为DSPI管脚 #if (CFG_DSPI_INDEX == 0) MCF_PAD_PAR_DSPIOWH = 0xFC; MCF_PAD_PAR_DSPIOWL = 0; MCF_PAD_SRCR_DSPIOW = 0x01; // 调整管脚驱动能力,2太强,过冲太厉害,改为1 #elif (CFG_DSPI_INDEX == 1) MCF_PAD_PAR_SDHCH |= 0x01; MCF_PAD_PAR_SDHCL |= 0X05; MCF_PAD_SRCR_SDHC = 0x1; // 调整管脚驱动能力,2太强,过冲太厉害,改为1 #endif //初始化TCR寄存器 _MCF_DSPI_TCR(CFG_DSPI_INDEX) = 0; //初始化MCR寄存器 _MCF_DSPI_MCR(CFG_DSPI_INDEX) = 0; //设置模式寄存器 _MCF_DSPI_MCR(CFG_DSPI_INDEX) = MCF_DSPI_MCR_MSTR //| MCF_DSPI_MCR_SMPL_PT(x) //| MCF_DSPI_MCR_SMPL_PT_0CLK //| MCF_DSPI_MCR_SMPL_PT_1CLK //| MCF_DSPI_MCR_SMPL_PT_2CLK | MCF_DSPI_MCR_CLR_RXF | MCF_DSPI_MCR_CLR_TXF | MCF_DSPI_MCR_DIS_RXF // 禁止接收FIFO,打开后,接收数据前请FIFO会导致出错 | MCF_DSPI_MCR_DIS_TXF //| MCF_DSPI_MCR_MDIS //| MCF_DSPI_MCR_PCSIS0; // | MCF_DSPI_MCR_ROOE //| MCF_DSPI_MCR_MTFE //| MCF_DSPI_MCR_FRZ //| MCF_DSPI_MCR_DCONF(x) //| MCF_DSPI_MCR_CONT_SCKE; // | MCF_DSPI_MCR_HALT | MCF_DSPI_MCR_PCSIS1; //| MCF_DSPI_MCR_PCSIS2; // MCF_DSPI_MCR_PCSIS3; //初始化DMA/中断请求选择和使能寄存器 _MCF_DSPI_RSER(CFG_DSPI_INDEX) = 0;//MCF_DSPI_RSER_EOQF_RE //| MCF_DSPI_RSER_TCF_RE; //| MCF_DSPI_RSER_TFFF_DIRS //| MCF_DSPI_RSER_RFDF_DIRS //| MCF_DSPI_RSER_TFFF_RE //| MCF_DSPI_RSER_RFDF_RE; // 频率:125M/(4*7)=4.46M.字节与字节之间延时:125M/(1*128)=1.024us. _MCF_DSPI_CTAR1(CFG_DSPI_INDEX) = MCF_DSPI_CTAR_BR(1) |MCF_DSPI_CTAR_PBR_7CLK // |MCF_DSPI_CTAR_PCSSCK(1) // |MCF_DSPI_CTAR_CSSCK(1) |MCF_DSPI_CTAR_PASC_1CLK |MCF_DSPI_CTAR_ASC(3) |MCF_DSPI_CTAR_PDT_1CLK |MCF_DSPI_CTAR_DT(6) //|MCF_DSPI_CTAR_LSBFE |MCF_DSPI_CTAR_CPOL // 空闲时,时钟为高 //|MCF_DSPI_CTAR_DBR |MCF_DSPI_CTAR_CPHA // 时钟相位 |MCF_DSPI_CTAR_FMSZ(7); _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_EOQF |MCF_DSPI_SR_TCF; #endif return 0; } /****************************************************************************** 函数名称: dspi_open 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-19 函数说明: 打开一个DSPI设备,所有的DSPI设备互斥,一次只能打开一个,在这个函数 主要是根据设备的属性,设置DSPI的波特率、CLK极性、CLK相位,并使相应 的片选有效。 注意:此函数在资源竞争问题上,有一定的系统要求,如果要求不满足,用户应 自己处理资源竞争问题.这个要求为:系统中每个任务(一个中断服务程序也算 一个任务)都具有唯一优先级.目前UT800S的系统满足这个条件. 参数说明: dspi_id: 指定需要打开DSPI设备的标识符(以DSPI_ID_开头)。 返回值: >=0 : 打开设备的句柄 <0 : 打开失败。 修改记录: */ int dspi_open(int dspi_id) { //如果QSPI总线空闲,占有它。 if(gh_dspi == 0) gh_dspi = dspi_id; else return -1; //解决资源竞争问题,如果两个值不相等,说明在竞争中失败,退出。 if(gh_dspi != dspi_id) { return -2; } switch(dspi_id) { case DSPI_ID_ESAM: // 片选有效 //GPIO_DSPI_CS_ESAM_LOW(); //ustimer_delay(4*USTIMER_US); break; default: gh_dspi = 0; return -3; } return dspi_id; } /****************************************************************************** 函数名称: dspi_close 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-21 函数说明: 关闭一个DSPI设备。 参数说明: h_dspi:关闭设备的句柄。 返回值: 成功返回0. 修改记录: */ int dspi_close(int h_dspi) { if(h_dspi != gh_dspi) { return -1; } switch(h_dspi) { case DSPI_ID_ESAM: //片选无效 //GPIO_DSPI_CS_ESAM_HIGH(); break; default: return -2; } gh_dspi = 0; return 0; } /****************************************************************************** 函数名称: dspi_read 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-21 函数说明: 从DSPI总线上读取数据。 参数说明: h_dspi(in):DSPI设备句柄。. buffer(out):读出数据的buffer。 length(in): 需要读出数据的长度。 返回值: 成功返回0. 修改记录: */ int dspi_read(int h_dspi,unsigned char *buffer, uint32_t length) { if(h_dspi != gh_dspi || buffer == 0) { return -1; } #if 0 // 清空接收buffer _MCF_DSPI_MCR(CFG_DSPI_INDEX) |= MCF_DSPI_MCR_CLR_RXF; while(length) { //执行命令 _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1); // 开始执行 while (!(_MCF_DSPI_SR(CFG_DSPI_INDEX) & MCF_DSPI_SR_TCF)) ; // 等待结束 _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; // 清除标志 *buffer++ = (unsigned char)_MCF_DSPI_POPR(CFG_DSPI_INDEX); //长度减放在这个地方,不放在while条件中,否则由于编译器的bug, //会导致程序流程执行不正确。 length--; } #endif return 0; } /****************************************************************************** 函数名称: dspi_write 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-21 函数说明: 写数据到QSPI总线。 参数说明: h_dspi(in):DSPI设备句柄。. buffer(in):写入数据的buffer。 length(in): 需要写入数据的长度。 返回值: 成功返回0. 修改记录: */ int dspi_write(int h_dspi,unsigned char *buffer, uint32_t length) { #if 0 if(h_dspi != gh_dspi || buffer == 0) { return -1; } while(length) { _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1) | (unsigned char)(*buffer++); while (!(_MCF_DSPI_SR(CFG_DSPI_INDEX) & MCF_DSPI_SR_TCF)) ; // 等待结束 _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; //长度减放在这个地方,不放在while条件中,否则由于编译器的bug, //会导致程序流程执行不正确。 length--; } #endif return 0; } /****************************************************************************** 函数名称: dspi_dummy_byte 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-21 函数说明: 往SPI总线上发空的CLOCK。 参数说明: h_dspi(in):DSPI设备句柄。. length(in): 需要发空CLOCK的长度,以BYTE为单位。 返回值: 成功返回0. 修改记录: */ int dspi_dummy_byte(int h_dspi,uint32_t length) { if(h_dspi != gh_dspi) { return -1; } #if 0 while(length) { //执行命令 _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1); // 开始执行 while (!(_MCF_DSPI_SR(CFG_DSPI_INDEX) & MCF_DSPI_SR_TCF)) ; // 等待结束 _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; // 清除标志 //长度减放在这个地方,不放在while条件中,否则由于编译器的bug, //会导致程序流程执行不正确。 length--; } #endif return 0; } void dspi_esam_cs(int cs) { #if 0 if(cs) { GPIO_DSPI_CS_ESAM_HIGH(); ustimer_delay(11*USTIMER_US); } else { GPIO_DSPI_CS_ESAM_LOW(); ustimer_delay(51*USTIMER_US); } #endif } u8 dspi_esam_send(u8 c) { #if 0 u32 flag; // 发送数据、接收数据字节间延时至少设为 1μs。 ustimer_delay(USTIMER_US); _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1) | (unsigned char)(c); flag = (MCF_DSPI_SR_TCF | MCF_DSPI_SR_RFDF); while ((_MCF_DSPI_SR(CFG_DSPI_INDEX) & flag) != flag) ; // 等待结束 _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; c = (unsigned char)_MCF_DSPI_POPR(CFG_DSPI_INDEX); #endif return c; } u8 dspi_esam_recv(void) { #if 0 u8 c; u32 flag; // 发送数据、接收数据字节间延时至少设为 1μs。 ustimer_delay(USTIMER_US); // 清空接收buffer // 以下语句必须屏蔽。在接收FIFO打开的情况下,如果在此处清BUF,在非常罕见的情况下会出错,具体原因未知。 // _MCF_DSPI_MCR(CFG_DSPI_INDEX) |= MCF_DSPI_MCR_CLR_RXF; //执行命令 _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1); // 开始执行 flag = (MCF_DSPI_SR_TCF | MCF_DSPI_SR_RFDF); while ((_MCF_DSPI_SR(CFG_DSPI_INDEX) & flag) != flag) ; // 等待结束 _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; // 清除标志 c = (unsigned char)_MCF_DSPI_POPR(CFG_DSPI_INDEX); return c; #endif return 0; } /*------------------------------ 内部函数 ------------------------------------- */ /*------------------------------ 测试函数 ------------------------------------- */ /*------------------------------ 文件结束 ------------------------------------- */