[技术问答] 如何访问MCU505内部的 SPI Flash ?

[复制链接]
1535|3
 楼主| seawwh 发表于 2016-6-18 17:23 | 显示全部楼层 |阅读模式
假如需要使用MCU505内部的 SPI Flash,如何操作,有没有相关资料?
捉虫天师 发表于 2016-6-19 22:06 | 显示全部楼层
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V2.0
  4. * $Revision: 11 $
  5. * $Date: 15/03/04 9:47a $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Access the SPI Flash through a SPI interface.
  7. *
  8. * @note
  9. * Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. #include <stdio.h>
  13. #include "NUC505Series.h"

  14. #define TEST_NUMBER 1   /* page numbers */
  15. #define TEST_LENGTH 256 /* length */

  16. #define SPI_FLASH_PORT  SPI0

  17. uint8_t SrcArray[TEST_LENGTH];
  18. uint8_t DestArray[TEST_LENGTH];

  19. /* Function prototype declaration */
  20. void SYS_Init(void);
  21. void UART0_Init(void);
  22. void SPI0_Init(void);

  23. uint16_t SpiFlash_ReadMidDid(void)
  24. {
  25.     uint8_t u8RxData[6], u8IDCnt = 0;

  26.     // /CS: active
  27.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  28.     // send Command: 0x90, Read Manufacturer/Device ID
  29.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x90);

  30.     // send 24-bit '0', dummy
  31.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
  32.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
  33.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);

  34.     // receive 16-bit
  35.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
  36.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);

  37.     // wait tx finish
  38.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  39.     // /CS: de-active
  40.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);

  41.     while(!SPI_GET_RX_FIFO_EMPTY_FLAG(SPI_FLASH_PORT))
  42.         u8RxData[u8IDCnt ++] = SPI_READ_RX(SPI_FLASH_PORT);

  43.     return ( (u8RxData[4]<<8) | u8RxData[5] );
  44. }

  45. void SpiFlash_ChipErase(void)
  46. {
  47.     // /CS: active
  48.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  49.     // send Command: 0x06, Write enable
  50.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x06);

  51.     // wait tx finish
  52.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  53.     // /CS: de-active
  54.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);

  55.     //////////////////////////////////////////

  56.     // /CS: active
  57.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  58.     // send Command: 0xC7, Chip Erase
  59.     SPI_WRITE_TX(SPI_FLASH_PORT, 0xC7);

  60.     // wait tx finish
  61.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  62.     // /CS: de-active
  63.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);

  64.     SPI_ClearRxFIFO(SPI0);
  65. }

  66. uint8_t SpiFlash_ReadStatusReg(void)
  67. {
  68.     // /CS: active
  69.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  70.     // send Command: 0x05, Read status register
  71.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x05);

  72.     // read status
  73.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);

  74.     // wait tx finish
  75.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  76.     // /CS: de-active
  77.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);

  78.     // skip first rx data
  79.     SPI_READ_RX(SPI_FLASH_PORT);

  80.     return (SPI_READ_RX(SPI_FLASH_PORT) & 0xff);
  81. }

  82. void SpiFlash_WriteStatusReg(uint8_t u8Value)
  83. {
  84.     // /CS: active
  85.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  86.     // send Command: 0x06, Write enable
  87.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x06);

  88.     // wait tx finish
  89.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  90.     // /CS: de-active
  91.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);

  92.     ///////////////////////////////////////

  93.     // /CS: active
  94.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  95.     // send Command: 0x01, Write status register
  96.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x01);

  97.     // write status
  98.     SPI_WRITE_TX(SPI_FLASH_PORT, u8Value);

  99.     // wait tx finish
  100.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  101.     // /CS: de-active
  102.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);
  103. }

  104. void SpiFlash_WaitReady(void)
  105. {
  106.     uint8_t ReturnValue;

  107.     do {
  108.         ReturnValue = SpiFlash_ReadStatusReg();
  109.         ReturnValue = ReturnValue & 1;
  110.     } while(ReturnValue!=0); // check the BUSY bit
  111. }

  112. void SpiFlash_NormalPageProgram(uint32_t StartAddress, uint8_t *u8DataBuffer)
  113. {
  114.     uint32_t i = 0;

  115.     // /CS: active
  116.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  117.     // send Command: 0x06, Write enable
  118.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x06);

  119.     // wait tx finish
  120.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  121.     // /CS: de-active
  122.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);


  123.     // /CS: active
  124.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  125.     // send Command: 0x02, Page program
  126.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x02);

  127.     // send 24-bit start address
  128.     SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>16) & 0xFF);
  129.     SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>8)  & 0xFF);
  130.     SPI_WRITE_TX(SPI_FLASH_PORT, StartAddress       & 0xFF);

  131.     // write data
  132.     while(1) {
  133.         if(!SPI_GET_TX_FIFO_FULL_FLAG(SPI_FLASH_PORT)) {
  134.             SPI_WRITE_TX(SPI_FLASH_PORT, u8DataBuffer[i++]);
  135.             if(i >= 255) break;
  136.         }
  137.     }

  138.     // wait tx finish
  139.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  140.     // /CS: de-active
  141.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);

  142.     SPI_ClearRxFIFO(SPI_FLASH_PORT);
  143. }

  144. void SpiFlash_NormalRead(uint32_t StartAddress, uint8_t *u8DataBuffer)
  145. {
  146.     uint32_t i;

  147.     // /CS: active
  148.     SPI_SET_SS_LOW(SPI_FLASH_PORT);

  149.     // send Command: 0x03, Read data
  150.     SPI_WRITE_TX(SPI_FLASH_PORT, 0x03);

  151.     // send 24-bit start address
  152.     SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>16) & 0xFF);
  153.     SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>8)  & 0xFF);
  154.     SPI_WRITE_TX(SPI_FLASH_PORT, StartAddress       & 0xFF);

  155.     while(SPI_IS_BUSY(SPI_FLASH_PORT));
  156.     // clear RX buffer
  157.     SPI_ClearRxFIFO(SPI_FLASH_PORT);

  158.     // read data
  159.     for(i=0; i<256; i++) {
  160.         SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
  161.         while(SPI_IS_BUSY(SPI_FLASH_PORT));
  162.         u8DataBuffer[i] = SPI_READ_RX(SPI_FLASH_PORT);
  163.     }

  164.     // wait tx finish
  165.     while(SPI_IS_BUSY(SPI_FLASH_PORT));

  166.     // /CS: de-active
  167.     SPI_SET_SS_HIGH(SPI_FLASH_PORT);
  168. }

  169. /* Main */
  170. int main(void)
  171. {
  172.     uint32_t u32ByteCount, u32FlashAddress, u32PageNumber;
  173.     uint32_t nError = 0;
  174.     uint16_t u16ID;

  175.     /* Init System, IP clock and multi-function I/O */
  176.     SYS_Init();

  177.     /* Init UART0 to 115200-8n1 for print message */
  178.     UART0_Init();

  179.                 /* Init SPI0, IP clock and multi-function I/O */
  180.                 SPI0_Init();
  181.                
  182.     /* Configure SPI_FLASH_PORT as a master, MSB first, 8-bit transaction, SPI Mode-0 timing, clock is 2MHz */
  183.     SPI_Open(SPI_FLASH_PORT, SPI_MASTER, SPI_MODE_0, 8, 2000000);

  184.     /* Enable the automatic hardware slave select function. Select the SS0 pin and configure as low-active. */
  185.     SPI_EnableAutoSS(SPI_FLASH_PORT, SPI_SS, SPI_SS_ACTIVE_LOW);
  186.     SPI_ENABLE(SPI_FLASH_PORT);

  187.     printf("\n+------------------------------------------------------------------------+\n");
  188.     printf("|            NUC505        SPI Sample with SPI Flash                     |\n");
  189.     printf("+------------------------------------------------------------------------+\n");

  190.     /* Wait ready */
  191.     SpiFlash_WaitReady();

  192. ///    if((u16ID = SpiFlash_ReadMidDid()) != 0x1C14) {
  193.                 if((u16ID = SpiFlash_ReadMidDid()) != 0xEF14) {
  194.         printf("Wrong ID, 0x%x\n", u16ID);
  195.         return -1;
  196.     } else
  197.         printf("Flash found: Winbond 25Q16OVSEG ...\n");

  198.     printf("Erase chip ...");

  199.     /* Erase SPI flash */
  200.     SpiFlash_ChipErase();

  201.     /* Wait ready */
  202.     SpiFlash_WaitReady();

  203.     printf("[OK]\n");

  204.     /* init source data buffer */
  205.     for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) {
  206.         SrcArray[u32ByteCount] = u32ByteCount;
  207.     }

  208.     printf("Start to normal write data to Flash ...");
  209.     /* Program SPI flash */
  210.     u32FlashAddress = 0;
  211.     for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) {
  212.         /* page program */
  213.         SpiFlash_NormalPageProgram(u32FlashAddress, SrcArray);
  214.         SpiFlash_WaitReady();
  215.         u32FlashAddress += 0x100;
  216.     }

  217.     printf("[OK]\n");

  218.     /* clear destination data buffer */
  219.     for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) {
  220.         DestArray[u32ByteCount] = 0;
  221.     }

  222.     printf("Normal Read & Compare ...");

  223.     /* Read SPI flash */
  224.     u32FlashAddress = 0;
  225.     for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) {
  226.         /* page read */
  227.         SpiFlash_NormalRead(u32FlashAddress, DestArray);
  228.         u32FlashAddress += 0x100;

  229.         for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) {
  230.             if(DestArray[u32ByteCount] != SrcArray[u32ByteCount])
  231.                 nError ++;
  232.         }
  233.     }

  234.     if(nError == 0)
  235.         printf("[OK]\n");
  236.     else
  237.         printf("[FAIL]\n");

  238.     while(1);
  239. }

  240. void SYS_Init(void)
  241. {

  242. /*---------------------------------------------------------------------------------------------------------*/
  243. /* Init System Clock                                                                                       */
  244. /*---------------------------------------------------------------------------------------------------------*/
  245.     /* Unlock protected registers */
  246.     //SYS_UnlockReg();
  247.      
  248.     /* Enable  XTAL */
  249.     CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;

  250.     CLK_SetCoreClock(FREQ_96MHZ);
  251.    
  252.                 /* PCLK divider */
  253.                 CLK_SetModuleClock(PCLK_MODULE, NULL, 1);
  254.                
  255.     /* Lock protected registers */
  256.     //SYS_LockReg();
  257.         
  258. }

  259. void UART0_Init(void)
  260. {
  261.                 /* Enable UART0 Module clock */
  262.     CLK_EnableModuleClock(UART0_MODULE);
  263.                 /* UART0 module clock from EXT */
  264.                 CLK_SetModuleClock(UART0_MODULE, CLK_UART0_SRC_EXT, 0);
  265.     /* Reset IP */
  266.     SYS_ResetModule(UART0_RST);   
  267.     /* Configure UART0 and set UART0 Baud-rate */
  268.                 UART_Open(UART0, 115200);
  269.                 /*---------------------------------------------------------------------------------------------------------*/
  270.     /* Init I/O Multi-function                                                                                 */
  271.     /*---------------------------------------------------------------------------------------------------------*/
  272.     /* Configure multi-function pins for UART0 RXD and TXD */
  273.                 SYS->GPB_MFPL  = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB0MFP_Msk) ) | SYS_GPB_MFPL_PB0MFP_UART0_TXD;       
  274.                 SYS->GPB_MFPL  = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB1MFP_Msk) ) | SYS_GPB_MFPL_PB1MFP_UART0_RXD;       
  275.        
  276. }

  277. void SPI0_Init(void)
  278. {
  279.                 /* Enable SPI0 Module clock */
  280.     CLK_EnableModuleClock(SPI0_MODULE);
  281.                 /* SPI0 module clock from EXT */
  282.                 CLK_SetModuleClock(SPI0_MODULE, CLK_SPI0_SRC_PLL, 0);
  283.     /* Reset IP */
  284.     SYS_ResetModule(SPI0_RST);   
  285.     /*---------------------------------------------------------------------------------------------------------*/
  286.     /* Init I/O Multi-function                                                                                 */
  287.     /*---------------------------------------------------------------------------------------------------------*/
  288.     /* Configure multi-function pins for SPI0 */
  289.                 SYS->GPB_MFPL  = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB2MFP_Msk) ) | SYS_GPB_MFPL_PB2MFP_SPI0_SS;       
  290.                 SYS->GPB_MFPL  = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB3MFP_Msk) ) | SYS_GPB_MFPL_PB3MFP_SPI0_CLK;       
  291.                 SYS->GPB_MFPL  = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB4MFP_Msk) ) | SYS_GPB_MFPL_PB4MFP_SPI0_MOSI;       
  292.                 SYS->GPB_MFPL  = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB5MFP_Msk) ) | SYS_GPB_MFPL_PB5MFP_SPI0_MISO;       
  293.        
  294. }

  295. /*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/



捉虫天师 发表于 2016-6-19 22:10 | 显示全部楼层
 楼主| seawwh 发表于 2016-6-20 11:12 | 显示全部楼层
我看过NUC505的 SPIM 的相关例子,可以推敲出某些Flash 的参数,但毕竟希望看到厂家的明确表述,例如:

1. 块擦除的大小和时间,全片擦除的时间?
2. 写入的时间
3. 擦写寿命等等
您需要登录后才可以回帖 登录 | 注册

本版积分规则

145

主题

368

帖子

1

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