dspi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: dspi.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2008-08-19
  7. 功能说明: dspi驱动程序。
  8. 其它说明:
  9. 修改记录:
  10. */
  11. /*------------------------------- 头文件 --------------------------------------
  12. */
  13. #include "head.h"
  14. /*------------------------------- 宏定义 --------------------------------------
  15. */
  16. //DSPI内部RAM地址
  17. //四个DSPI模块地址
  18. #define DSPI0_MODULE_ADDRESS 0xFC05C000
  19. #define DSPI1_MODULE_ADDRESS 0xFC03C000
  20. #define DSPI2_MODULE_ADDRESS 0xEC038000
  21. #define DSPI3_MODULE_ADDRESS 0xEC03C000
  22. #if (CFG_DSPI_INDEX == 0)
  23. #define DSPI_PM_REG MCF_PMM_PPMCR0
  24. #define DSPI_PM_INDEX 23
  25. #elif (CFG_DSPI_INDEX == 1)
  26. #define DSPI_PM_REG MCF_PMM_PPMCR0
  27. #define DSPI_PM_INDEX 15
  28. #endif
  29. /*------------------------------ 全局变量 -------------------------------------
  30. */
  31. //总线占用状态
  32. int gh_dspi = 0;
  33. /*------------------------------ 函数声明 -------------------------------------
  34. */
  35. /*------------------------------ 外部函数 -------------------------------------
  36. */
  37. /******************************************************************************
  38. 函数名称: dspi_init
  39. 函数版本: 01.01
  40. 创建作者: sunxi
  41. 创建日期: 2008-08-19
  42. 函数说明: qspi初始化。
  43. 参数说明: 无
  44. 返回值: 成功返回0.
  45. 修改记录:
  46. */
  47. #define _MCF_DSPI_MCR(x) (*(vuint32*)(0xEC038000 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  48. #define _MCF_DSPI_TCR(x) (*(vuint32*)(0xEC038008 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  49. #define _MCF_DSPI_RSER(x) (*(vuint32*)(0xEC038030 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  50. #define _MCF_DSPI_CTAR1(x) (*(vuint32*)(0xEC038010 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  51. #define _MCF_DSPI_SR(x) (*(vuint32*)(0xEC03802C + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  52. #define _MCF_DSPI_PUSHR(x) (*(vuint32*)(0xEC038034 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  53. #define _MCF_DSPI_POPR(x) (*(vuint32*)(0xEC038038 + ((x<2)? (0x10024000 + ((x)*0x4000) - ((x)*0x24000)) : ((x-2)*0x4000))))
  54. int dspi_init(void)
  55. {
  56. #if 0
  57. // SPI总线初始化前,先打开ESAM模块的电源,解决esam模块有时工作不正常的问题。
  58. // 上电并延时1ms
  59. GPIO_ESAM_POWER_INIT();
  60. ustimer_delay(USTIMER_MS*10);
  61. //模块打开
  62. DSPI_PM_REG = DSPI_PM_INDEX;
  63. //使用GPIO控制CS
  64. GPIO_DSPI_CS_ESAM_INIT();
  65. // 设置为DSPI管脚
  66. #if (CFG_DSPI_INDEX == 0)
  67. MCF_PAD_PAR_DSPIOWH = 0xFC;
  68. MCF_PAD_PAR_DSPIOWL = 0;
  69. MCF_PAD_SRCR_DSPIOW = 0x01; // 调整管脚驱动能力,2太强,过冲太厉害,改为1
  70. #elif (CFG_DSPI_INDEX == 1)
  71. MCF_PAD_PAR_SDHCH |= 0x01;
  72. MCF_PAD_PAR_SDHCL |= 0X05;
  73. MCF_PAD_SRCR_SDHC = 0x1; // 调整管脚驱动能力,2太强,过冲太厉害,改为1
  74. #endif
  75. //初始化TCR寄存器
  76. _MCF_DSPI_TCR(CFG_DSPI_INDEX) = 0;
  77. //初始化MCR寄存器
  78. _MCF_DSPI_MCR(CFG_DSPI_INDEX) = 0;
  79. //设置模式寄存器
  80. _MCF_DSPI_MCR(CFG_DSPI_INDEX) = MCF_DSPI_MCR_MSTR
  81. //| MCF_DSPI_MCR_SMPL_PT(x)
  82. //| MCF_DSPI_MCR_SMPL_PT_0CLK
  83. //| MCF_DSPI_MCR_SMPL_PT_1CLK
  84. //| MCF_DSPI_MCR_SMPL_PT_2CLK
  85. | MCF_DSPI_MCR_CLR_RXF
  86. | MCF_DSPI_MCR_CLR_TXF
  87. | MCF_DSPI_MCR_DIS_RXF // 禁止接收FIFO,打开后,接收数据前请FIFO会导致出错
  88. | MCF_DSPI_MCR_DIS_TXF
  89. //| MCF_DSPI_MCR_MDIS
  90. //| MCF_DSPI_MCR_PCSIS0;
  91. // | MCF_DSPI_MCR_ROOE
  92. //| MCF_DSPI_MCR_MTFE
  93. //| MCF_DSPI_MCR_FRZ
  94. //| MCF_DSPI_MCR_DCONF(x)
  95. //| MCF_DSPI_MCR_CONT_SCKE;
  96. // | MCF_DSPI_MCR_HALT
  97. | MCF_DSPI_MCR_PCSIS1;
  98. //| MCF_DSPI_MCR_PCSIS2;
  99. // MCF_DSPI_MCR_PCSIS3;
  100. //初始化DMA/中断请求选择和使能寄存器
  101. _MCF_DSPI_RSER(CFG_DSPI_INDEX) = 0;//MCF_DSPI_RSER_EOQF_RE
  102. //| MCF_DSPI_RSER_TCF_RE;
  103. //| MCF_DSPI_RSER_TFFF_DIRS
  104. //| MCF_DSPI_RSER_RFDF_DIRS
  105. //| MCF_DSPI_RSER_TFFF_RE
  106. //| MCF_DSPI_RSER_RFDF_RE;
  107. // 频率:125M/(4*7)=4.46M.字节与字节之间延时:125M/(1*128)=1.024us.
  108. _MCF_DSPI_CTAR1(CFG_DSPI_INDEX) = MCF_DSPI_CTAR_BR(1)
  109. |MCF_DSPI_CTAR_PBR_7CLK
  110. // |MCF_DSPI_CTAR_PCSSCK(1)
  111. // |MCF_DSPI_CTAR_CSSCK(1)
  112. |MCF_DSPI_CTAR_PASC_1CLK
  113. |MCF_DSPI_CTAR_ASC(3)
  114. |MCF_DSPI_CTAR_PDT_1CLK
  115. |MCF_DSPI_CTAR_DT(6)
  116. //|MCF_DSPI_CTAR_LSBFE
  117. |MCF_DSPI_CTAR_CPOL // 空闲时,时钟为高
  118. //|MCF_DSPI_CTAR_DBR
  119. |MCF_DSPI_CTAR_CPHA // 时钟相位
  120. |MCF_DSPI_CTAR_FMSZ(7);
  121. _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_EOQF
  122. |MCF_DSPI_SR_TCF;
  123. #endif
  124. return 0;
  125. }
  126. /******************************************************************************
  127. 函数名称: dspi_open
  128. 函数版本: 01.01
  129. 创建作者: sunxi
  130. 创建日期: 2008-08-19
  131. 函数说明: 打开一个DSPI设备,所有的DSPI设备互斥,一次只能打开一个,在这个函数
  132. 主要是根据设备的属性,设置DSPI的波特率、CLK极性、CLK相位,并使相应
  133. 的片选有效。
  134. 注意:此函数在资源竞争问题上,有一定的系统要求,如果要求不满足,用户应
  135. 自己处理资源竞争问题.这个要求为:系统中每个任务(一个中断服务程序也算
  136. 一个任务)都具有唯一优先级.目前UT800S的系统满足这个条件.
  137. 参数说明:
  138. dspi_id: 指定需要打开DSPI设备的标识符(以DSPI_ID_开头)。
  139. 返回值:
  140. >=0 : 打开设备的句柄
  141. <0 : 打开失败。
  142. 修改记录:
  143. */
  144. int dspi_open(int dspi_id)
  145. {
  146. //如果QSPI总线空闲,占有它。
  147. if(gh_dspi == 0)
  148. gh_dspi = dspi_id;
  149. else
  150. return -1;
  151. //解决资源竞争问题,如果两个值不相等,说明在竞争中失败,退出。
  152. if(gh_dspi != dspi_id)
  153. {
  154. return -2;
  155. }
  156. switch(dspi_id)
  157. {
  158. case DSPI_ID_ESAM:
  159. // 片选有效
  160. //GPIO_DSPI_CS_ESAM_LOW();
  161. //ustimer_delay(4*USTIMER_US);
  162. break;
  163. default:
  164. gh_dspi = 0;
  165. return -3;
  166. }
  167. return dspi_id;
  168. }
  169. /******************************************************************************
  170. 函数名称: dspi_close
  171. 函数版本: 01.01
  172. 创建作者: sunxi
  173. 创建日期: 2008-08-21
  174. 函数说明: 关闭一个DSPI设备。
  175. 参数说明:
  176. h_dspi:关闭设备的句柄。
  177. 返回值: 成功返回0.
  178. 修改记录:
  179. */
  180. int dspi_close(int h_dspi)
  181. {
  182. if(h_dspi != gh_dspi)
  183. {
  184. return -1;
  185. }
  186. switch(h_dspi)
  187. {
  188. case DSPI_ID_ESAM:
  189. //片选无效
  190. //GPIO_DSPI_CS_ESAM_HIGH();
  191. break;
  192. default:
  193. return -2;
  194. }
  195. gh_dspi = 0;
  196. return 0;
  197. }
  198. /******************************************************************************
  199. 函数名称: dspi_read
  200. 函数版本: 01.01
  201. 创建作者: sunxi
  202. 创建日期: 2008-08-21
  203. 函数说明: 从DSPI总线上读取数据。
  204. 参数说明:
  205. h_dspi(in):DSPI设备句柄。.
  206. buffer(out):读出数据的buffer。
  207. length(in): 需要读出数据的长度。
  208. 返回值: 成功返回0.
  209. 修改记录:
  210. */
  211. int dspi_read(int h_dspi,unsigned char *buffer, uint32_t length)
  212. {
  213. if(h_dspi != gh_dspi || buffer == 0)
  214. {
  215. return -1;
  216. }
  217. #if 0
  218. // 清空接收buffer
  219. _MCF_DSPI_MCR(CFG_DSPI_INDEX) |= MCF_DSPI_MCR_CLR_RXF;
  220. while(length)
  221. {
  222. //执行命令
  223. _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1); // 开始执行
  224. while (!(_MCF_DSPI_SR(CFG_DSPI_INDEX) & MCF_DSPI_SR_TCF)) ; // 等待结束
  225. _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; // 清除标志
  226. *buffer++ = (unsigned char)_MCF_DSPI_POPR(CFG_DSPI_INDEX);
  227. //长度减放在这个地方,不放在while条件中,否则由于编译器的bug,
  228. //会导致程序流程执行不正确。
  229. length--;
  230. }
  231. #endif
  232. return 0;
  233. }
  234. /******************************************************************************
  235. 函数名称: dspi_write
  236. 函数版本: 01.01
  237. 创建作者: sunxi
  238. 创建日期: 2008-08-21
  239. 函数说明: 写数据到QSPI总线。
  240. 参数说明:
  241. h_dspi(in):DSPI设备句柄。.
  242. buffer(in):写入数据的buffer。
  243. length(in): 需要写入数据的长度。
  244. 返回值: 成功返回0.
  245. 修改记录:
  246. */
  247. int dspi_write(int h_dspi,unsigned char *buffer, uint32_t length)
  248. {
  249. #if 0
  250. if(h_dspi != gh_dspi || buffer == 0)
  251. {
  252. return -1;
  253. }
  254. while(length)
  255. {
  256. _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1) | (unsigned char)(*buffer++);
  257. while (!(_MCF_DSPI_SR(CFG_DSPI_INDEX) & MCF_DSPI_SR_TCF)) ; // 等待结束
  258. _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF;
  259. //长度减放在这个地方,不放在while条件中,否则由于编译器的bug,
  260. //会导致程序流程执行不正确。
  261. length--;
  262. }
  263. #endif
  264. return 0;
  265. }
  266. /******************************************************************************
  267. 函数名称: dspi_dummy_byte
  268. 函数版本: 01.01
  269. 创建作者: sunxi
  270. 创建日期: 2008-08-21
  271. 函数说明: 往SPI总线上发空的CLOCK。
  272. 参数说明:
  273. h_dspi(in):DSPI设备句柄。.
  274. length(in): 需要发空CLOCK的长度,以BYTE为单位。
  275. 返回值: 成功返回0.
  276. 修改记录:
  277. */
  278. int dspi_dummy_byte(int h_dspi,uint32_t length)
  279. {
  280. if(h_dspi != gh_dspi)
  281. {
  282. return -1;
  283. }
  284. #if 0
  285. while(length)
  286. {
  287. //执行命令
  288. _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1); // 开始执行
  289. while (!(_MCF_DSPI_SR(CFG_DSPI_INDEX) & MCF_DSPI_SR_TCF)) ; // 等待结束
  290. _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; // 清除标志
  291. //长度减放在这个地方,不放在while条件中,否则由于编译器的bug,
  292. //会导致程序流程执行不正确。
  293. length--;
  294. }
  295. #endif
  296. return 0;
  297. }
  298. void dspi_esam_cs(int cs)
  299. {
  300. #if 0
  301. if(cs)
  302. {
  303. GPIO_DSPI_CS_ESAM_HIGH();
  304. ustimer_delay(11*USTIMER_US);
  305. }
  306. else
  307. {
  308. GPIO_DSPI_CS_ESAM_LOW();
  309. ustimer_delay(51*USTIMER_US);
  310. }
  311. #endif
  312. }
  313. u8 dspi_esam_send(u8 c)
  314. {
  315. #if 0
  316. u32 flag;
  317. // 发送数据、接收数据字节间延时至少设为 1μs。
  318. ustimer_delay(USTIMER_US);
  319. _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1) | (unsigned char)(c);
  320. flag = (MCF_DSPI_SR_TCF | MCF_DSPI_SR_RFDF);
  321. while ((_MCF_DSPI_SR(CFG_DSPI_INDEX) & flag) != flag) ; // 等待结束
  322. _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF;
  323. c = (unsigned char)_MCF_DSPI_POPR(CFG_DSPI_INDEX);
  324. #endif
  325. return c;
  326. }
  327. u8 dspi_esam_recv(void)
  328. {
  329. #if 0
  330. u8 c;
  331. u32 flag;
  332. // 发送数据、接收数据字节间延时至少设为 1μs。
  333. ustimer_delay(USTIMER_US);
  334. // 清空接收buffer
  335. // 以下语句必须屏蔽。在接收FIFO打开的情况下,如果在此处清BUF,在非常罕见的情况下会出错,具体原因未知。
  336. // _MCF_DSPI_MCR(CFG_DSPI_INDEX) |= MCF_DSPI_MCR_CLR_RXF;
  337. //执行命令
  338. _MCF_DSPI_PUSHR(CFG_DSPI_INDEX) = MCF_DSPI_PUSHR_CTAS(1); // 开始执行
  339. flag = (MCF_DSPI_SR_TCF | MCF_DSPI_SR_RFDF);
  340. while ((_MCF_DSPI_SR(CFG_DSPI_INDEX) & flag) != flag) ; // 等待结束
  341. _MCF_DSPI_SR(CFG_DSPI_INDEX) = MCF_DSPI_SR_TCF; // 清除标志
  342. c = (unsigned char)_MCF_DSPI_POPR(CFG_DSPI_INDEX);
  343. return c;
  344. #endif
  345. return 0;
  346. }
  347. /*------------------------------ 内部函数 -------------------------------------
  348. */
  349. /*------------------------------ 测试函数 -------------------------------------
  350. */
  351. /*------------------------------ 文件结束 -------------------------------------
  352. */