[Cortex-M0技术交流] 【第四批】sh007笔记【第一帖】-SPI通过PDMA对Flash进行读写

[复制链接]
 楼主| sh007 发表于 2011-11-17 08:58 | 显示全部楼层 |阅读模式
本帖最后由 sh007 于 2011-11-17 13:07 编辑

拿到板子 本来想尽快学习使用,但是工作实在忙得没能按计划进行。最近也用到SPI FLASH,所以就先忽悠这个吧。
     板子上的串口 看来挺多人跟我一样 打印不了的。我用的是USBTOCOM的线,看资料调了一下串口,居然没反应,再我插拔串口线时,数据出来了,很奇怪,看了原理图后发现,串口的三个控制端也都引出,而且DTR还接了复位信号控制。但拔出来后DTR脚接触不好时,通讯就正常了。所以就先把R5,R6先焊掉,以后再研究串口控制。先不说上代码先。

SPI_PDMA_W25Q16BV.C主控函数文件
       设置主频50MHz,SPI 12MHz,然后对SPI FLASH 擦除,写和读进行操作
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /* */
  3. /* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
  4. /*---------------------------------------------------------------------------------------------------------*/

  5. #include <stdio.h>
  6. #include "NUC1xx.h"
  7. #include "DrvUART.h"
  8. #include "DrvSYS.h"
  9. #include "DrvSPI.h"
  10. #include "DrvPDMA.h"
  11. #include "SPI_FLASH_PDMA.h"
  12. #include "Driver\DrvGPIO.h"

  13. #define RW_LEN 80

  14. uint8_t SPI_PDMA_RXBuf[RW_LEN];
  15. uint8_t SPI_PDMA_TXBuf[RW_LEN];

  16. void RCC_Config(void);
  17. void UART_Config(void);

  18. int main()
  19. {
  20. uint16_t writenum,readnum;

  21. RCC_Config();
  22. UART_Config();
  23. SPI_Init();
  24. PDMA_Init(RW_LEN);


  25. printf("\n");
  26. printf("+----------------------------------------------------------------------+\n");
  27. printf("| NUC120助学板之SPI PDMA FLASH---W25Q16BV |\n");
  28. printf("+----------------------------------------------------------------------+\n");
  29. printf("***NUC120***配置主频为: %2d MHz.\n",DrvSYS_GetHCLKFreq()/1000000);
  30. printf("---SPI1主机模式,频率为: %2d MHz.\n", DrvSPI_GetClock1Freq(eDRVSPI_PORT1)/1000000);

  31. printf("开始擦除整片FLASH...\n");
  32. SPIFlash_ChipErase();
  33. SPIFlash_WaitReady();
  34. printf("整片FLASH擦除完成。\n");
  35. for(writenum=0;writenum<RW_LEN;writenum++)
  36. {
  37. SPI_PDMA_TXBuf[writenum]= writenum;
  38. SPI_PDMA_RXBuf[writenum]= 0;
  39. }
  40. DrvSYS_Delay(500000);
  41. printf("开始写入数据:\n");
  42. // Trigger PDMA specified Channel
  43. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1);
  44. SPIFlash_PDMA_PageProgram(0x0);

  45. for(writenum=0;writenum<RW_LEN;writenum++)
  46. {
  47. if(writenum%16 == 0 ) printf("\n");
  48. printf("0x%x,", SPI_PDMA_TXBuf[writenum]);
  49. }

  50. DrvSYS_Delay(500000);
  51. printf("开始读出数据:\n");
  52. // Trigger PDMA specified Channel
  53. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0);
  54. SPIFlash_PDMA_Read(0x0);
  55. for(readnum=0;readnum<RW_LEN;readnum++)
  56. {
  57. if(readnum%16 == 0 ) printf("\n");
  58. printf("0x%x,", SPI_PDMA_RXBuf[readnum]);
  59. }
  60. while(1)
  61. {}

  62. }
  63. void RCC_Config(void)
  64. {
  65. UNLOCKREG();
  66. SYSCLK->WRCON.XTL12M_EN = 1;
  67. // Waiting for 12M Xtal stalble
  68. DrvSYS_Delay(5000);

  69. //HCLK 为外部12M 通过PLL倍频到 50MHz.
  70. DrvSYS_Open(50000000);
  71. DrvSYS_Delay(5000);
  72. LOCKREG();

  73. }
  74. void UART_Config()
  75. {
  76. STR_UART_T sParam;
  77. // Set UART I/O
  78. DrvGPIO_InitFunction(E_FUNC_UART0);

  79. //Select UART Clock Source From 12MHz
  80. DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0);

  81. // UART Setting
  82. sParam.u32BaudRate = 9600;
  83. sParam.u8cDataBits = DRVUART_DATABITS_8;
  84. sParam.u8cStopBits = DRVUART_STOPBITS_1;
  85. sParam.u8cParity = DRVUART_PARITY_NONE;
  86. sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;

  87. // Set UART Configuration
  88. DrvUART_Open(UART_PORT0, &sParam);

  89. }
SPI_FLASH_PDMA.c SPI 利用PDMA进行读写的操作函数。

  1. #include <stdio.h>
  2. #include "NUC1xx.h"
  3. #include "DrvUART.h"
  4. #include "DrvSYS.h"
  5. #include "DrvSPI.h"
  6. #include "DrvGPIO.h"
  7. #include "DrvPDMA.h"
  8. #include "SPI_FLASH_PDMA.h"

  9. #define Enable_SPI1_W25Q16BV        (GPIOA->DOUT &= ~(1 << 14))
  10. #define Disable_SPI1_W25Q16BV       (GPIOA->DOUT |= (1 << 14))


  11. void PDMA0_Callback(void);
  12. void PDMA1_Callback(void);

  13. volatile uint32_t PDMA0_INT_Flag, PDMA1_INT_Flag;
  14. STR_PDMA_T sPDMA;  
  15. uint32_t  SPIPort;
  16. uint32_t u32ByteCount, u32FlashAddress, u32PageNumber;

  17. extern uint8_t SPI_PDMA_RXBuf[];
  18. extern uint8_t SPI_PDMA_TXBuf[];

  19. void SPI_Init(void)
  20. {  
  21.       
  22.     //SPI1 GPIO Init
  23.     DrvGPIO_InitFunction(E_FUNC_SPI1);
  24.     //Initialize SPI
  25.     // Configure SPI0 as a master, 32-bit transaction
  26.     DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 32,FALSE);
  27.     // MSB first
  28.     DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);
  29.     // Set the active level of slave select.
  30.     DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
  31.     // SPI clock rate 12MHz
  32.     DrvSPI_SetClockFreq(eDRVSPI_PORT1,12000000, 0);

  33.     //设置PA14为输出,PA14为W25Q16BV的位选
  34.     DrvGPIO_Open(E_GPA, 14, E_IO_OUTPUT);
  35.                                                      
  36. }

  37. void PDMA_Init(uint16_t RW_LEN)
  38. {
  39.     /* -------------------------------------------- */
  40.     /* Configure PDMA Channel 0 to receive SPI1 Rx0 */
  41.     /* -------------------------------------------- */
  42.     // PDMA Init
  43.     DrvPDMA_Init();
  44.     // SPI Port = SPI1 Rx0
  45.     SPIPort = SPI1_BASE + 0x10;
  46.     // PDMA Setting
  47.     DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_0, eDRVPDMA_SPI1, eDRVPDMA_READ_APB);
  48.     // CH0 RX Setting
  49.     sPDMA.sSrcCtrl.u32Addr          = SPIPort; //源地址
  50.     sPDMA.sDestCtrl.u32Addr         = (uint32_t)SPI_PDMA_RXBuf;//目标地址,这里是内部RAM的一块区域   
  51.     sPDMA.u8TransWidth              = eDRVPDMA_WIDTH_8BITS;
  52.     sPDMA.u8Mode                    = eDRVPDMA_MODE_APB2MEM;
  53.     sPDMA.sSrcCtrl.eAddrDirection   = eDRVPDMA_DIRECTION_FIXED;
  54.     sPDMA.sDestCtrl.eAddrDirection  = eDRVPDMA_DIRECTION_INCREMENTED;
  55.     sPDMA.i32ByteCnt                = RW_LEN;  
  56.     DrvPDMA_Open(eDRVPDMA_CHANNEL_0, &sPDMA);
  57.     // Enable INT
  58.     DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD);
  59.     // Install Callback function   
  60.     DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA0_Callback );
  61.    
  62.     /* -------------------------------------------- */
  63.     /* Configure PDMA Channel 1 to receive SPI1 Tx0 */
  64.     /* -------------------------------------------- */
  65.     // SPI Port = SPI1 Tx0
  66.     SPIPort = SPI1_BASE + 0x20;
  67.     // PDMA Setting
  68.     DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_1, eDRVPDMA_SPI1, eDRVPDMA_WRITE_APB);
  69.     // CH0 TX Setting
  70.     sPDMA.sSrcCtrl.u32Addr          = (uint32_t)SPI_PDMA_TXBuf;
  71.     sPDMA.sDestCtrl.u32Addr         = SPIPort;   
  72.     sPDMA.u8TransWidth              = eDRVPDMA_WIDTH_8BITS;
  73.     sPDMA.u8Mode                    = eDRVPDMA_MODE_MEM2APB;
  74.     sPDMA.sSrcCtrl.eAddrDirection   = eDRVPDMA_DIRECTION_INCREMENTED;
  75.     sPDMA.sDestCtrl.eAddrDirection  = eDRVPDMA_DIRECTION_FIXED;
  76.     sPDMA.i32ByteCnt                = RW_LEN;  
  77.     DrvPDMA_Open(eDRVPDMA_CHANNEL_1, &sPDMA);
  78.     // Enable INT
  79.     DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD);
  80.     // Install Callback function   
  81.     DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA1_Callback );
  82. }

  83. void SPIFlash_PDMA_PageProgram(uint32_t StartAddr)
  84. {
  85.     uint32_t au32SourceData;
  86.    
  87.     // configure transaction length as 8 bits
  88.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);

  89.     //CS =0 使能W25Q16BV
  90.     Enable_SPI1_W25Q16BV;
  91.    
  92.     // send Command: 0x06, Write enable
  93.     au32SourceData = 0x06;
  94.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
  95.    
  96.     // wait
  97.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
  98.    
  99.     //CS =1 禁止W25Q16BV
  100.     Disable_SPI1_W25Q16BV;

  101.     //CS =0 使能W25Q16BV
  102.     Enable_SPI1_W25Q16BV;
  103.    
  104.     // send Command: 0x02, Page program
  105.     au32SourceData = 0x02;
  106.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
  107.    
  108.     // wait
  109.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
  110.    
  111.     // configure transaction length as 24 bits
  112.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);        
  113.    
  114.     // send 24-bit start address
  115.     au32SourceData = StartAddr;
  116.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
  117.             
  118.     // wait
  119.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
  120.    
  121.     // configure transaction length as 8 bits
  122.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
  123.    
  124.     // enable SPI PDMA
  125.     DrvSPI_SetPDMA(eDRVSPI_PORT1, eDRVSPI_TX_DMA, TRUE);

  126.     // SPI go
  127.     PDMA1_INT_Flag = 0;
  128.     DrvSPI_SetGo(eDRVSPI_PORT1);
  129.    
  130.     // wait PDMA1 done
  131.     while (1)
  132.     {
  133.         if (PDMA1_INT_Flag)
  134.             {
  135.             PDMA1_INT_Flag = 0;
  136.             break;
  137.             }
  138.     }
  139.             
  140.     //CS =1 禁止W25Q16BV
  141.     Disable_SPI1_W25Q16BV;  
  142. }
  143. void SPIFlash_PDMA_Read(uint32_t StartAddr)
  144. {
  145.     uint32_t au32SourceData;
  146.    
  147.     // configure transaction length as 8 bits
  148.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);        

  149.     //CS =0 使能W25Q16BV
  150.     Enable_SPI1_W25Q16BV;

  151.     // send Command: 0x03, Read data
  152.     au32SourceData = 0x03;
  153.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);         

  154.     // wait
  155.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
  156.    
  157.     // configure transaction length as 24 bits
  158.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);        

  159.     // send 24-bit start address
  160.     au32SourceData = StartAddr;
  161.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);         

  162.     // wait
  163.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
  164.    
  165.     // configure transaction length as 8 bits
  166.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);         

  167.     // enable SPI PDMA
  168.     DrvSPI_SetPDMA(eDRVSPI_PORT1, eDRVSPI_RX_DMA, TRUE);

  169.     // SPI go
  170.     PDMA0_INT_Flag = 0;
  171.     DrvSPI_SetGo(eDRVSPI_PORT1);
  172.    
  173.     // wait PDMA0 done        
  174.     while (1)
  175.     {
  176.         if (PDMA0_INT_Flag)
  177.             {
  178.             PDMA0_INT_Flag = 0;
  179.             break;
  180.             }
  181.     }
  182.     //CS =1 禁止W25Q16BV
  183.     Disable_SPI1_W25Q16BV;
  184.    
  185. }


  186. uint32_t SPIFlash_ReadStatusReg(void)
  187. {
  188.     uint32_t au32SourceData;
  189.     uint32_t au32DestinationData;   

  190.     // configure transaction length as 16 bits
  191.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 16);
  192.             
  193.      //CS =0 使能W25Q16BV
  194.     Enable_SPI1_W25Q16BV;
  195.    
  196.     // send Command: 0x05, Read status register 1
  197.     au32SourceData = 0x0500;
  198.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
  199.    
  200.     // wait
  201.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
  202.             
  203.     //CS =1 禁止W25Q16BV
  204.     Disable_SPI1_W25Q16BV;

  205.     // dump Rx register
  206.     DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);

  207.     return (au32DestinationData & 0xFF);
  208. }

  209. void SPIFlash_WaitReady(void)
  210. {
  211.     uint32_t ReturnValue;
  212.    
  213.     do{
  214.         ReturnValue = SPIFlash_ReadStatusReg();
  215.         ReturnValue = ReturnValue & 1;
  216.     }while(ReturnValue!=0); // check the BUSY bit
  217.    
  218. }
  219. void SPIFlash_ChipErase(void)
  220. {
  221.    
  222.     uint32_t au32SourceData;

  223.     // configure transaction length as 8 bits
  224.     DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);         

  225.      //CS =0 使能W25Q16BV
  226.     Enable_SPI1_W25Q16BV;   

  227.     // send Command: 0x06, Write enable
  228.     au32SourceData = 0x06;
  229.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);         

  230.     // wait
  231.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}

  232.     //CS =1 禁止W25Q16BV
  233.     Disable_SPI1_W25Q16BV;

  234.     //CS =0 使能W25Q16BV
  235.     Enable_SPI1_W25Q16BV;   

  236.     // send Command: 0xC7, Chip Erase
  237.     au32SourceData = 0xc7;
  238.     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);         

  239.     // wait
  240.     while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}

  241.     //CS =1 禁止W25Q16BV
  242.     Disable_SPI1_W25Q16BV;
  243. }   


  244. /*---------------------------------------------------------------------------------------------------------*/
  245. /* PDMA Callback function                                                                                  */
  246. /*---------------------------------------------------------------------------------------------------------*/
  247. void PDMA0_Callback(void)
  248. {
  249.     PDMA0_INT_Flag = 1;        

  250. }

  251. void PDMA1_Callback(void)
  252. {
  253.     PDMA1_INT_Flag = 1;        

  254. }
 楼主| sh007 发表于 2011-11-17 09:00 | 显示全部楼层
忘记传工程文件了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
plc_avr 发表于 2011-11-17 09:16 | 显示全部楼层
这个不错,顶!
hotpower 发表于 2011-11-17 09:28 | 显示全部楼层
不错,spi加pdma是很不错的。m05x好像没有pdma
hotpower 发表于 2011-11-17 21:39 | 显示全部楼层
发放裤子,以便参加选美。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

174

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部

0

主题

174

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部