dspi.c 12 KB

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