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