NXP

Cortex-M单片机下载数据到外部flash

2019-07-12 13:56发布

主机环境:Windows 10 64bit开发环境:MDK 5.23目标板:LPC54114之前在NXP社区得到一块LPC54114的板卡,是由万利制作的,LPC54114是一款双核MCU,包含了一颗M4主核和一颗M0+从核,利用该板卡学习了一下双核MCU的开发流程,板卡中提供了一颗W25P80FLASH,之前拥有的板卡都没有挂外部FLASH,刚好之前利用LPC54608学习TouchGFX时可以把图片资源下载到外部FLASH中,因此借此机会来学习一下如何把数据下载到外部FLASH。平时烧录代码我们都是烧录到MCU内部的FLASH中,如下图:
可以看到下载的时片上256KB的FLASH,该算法文件是由DFP包提供的,具体可以在keil5的安装目录下找到,如下:
加载到内部FLASH的算法有了,但加载到外部FLASH的算法还没得。keil5中提供了LPC54608板卡的外部FLASH算法,LPC54114的外部FLASH算法就需要我们自己实现了,而且我们的板卡不是NXP官方的板卡,更不可能提供外部FLASH的加载算法了。。。进入到keil的FLASH目录,如下:
拷贝LPC5460x_MT25QL128文件夹到LPC54114_W25P80文件夹,并把其中有关信息全部替换成LPC54114相关信息。keil中提供了FlashOS.h头文件,定义了烧录到外部FLASH的相关接口,很简单,如下:
这就是本次我们需要实现的相关接口,修改的关键文件只有两个:FlashDev.c以及FlashPrg.c,首先看FlashDev.c文件,该文件定义了外部Flash的相关信息,经过简单修改就可以使用了,如下:[cpp] view plain copy
  1. #ifdef W25P80  
  2. struct FlashDevice const FlashDevice  =  {  
  3.    FLASH_DRV_VERS,             // Driver Version, do not modify!  
  4.    "LPC54114 W25P80 SPI"// Device Name  
  5.    EXTSPI,                     // Device Type  
  6.    0x10000000,                 // Device Start Address  
  7.    0x00100000,                 // Device Size (1MB)  
  8.    256,                        // Programming Page Size  
  9.    0,                          // Reserved, must be 0  
  10.    0xFF,                       // Initial Content of Erased Memory  
  11.    300,                        // Program Page Timeout 300 mSec  
  12.    3000,                       // Erase Sector Timeout 3000 mSec  
  13.   
  14. // Specify Size and Address of Sectors  
  15.    0x010000, 0x000000,         // Sector Size 64kB (16 Sectors)  
  16.    SECTOR_END  
  17. };  
  18. #endif  
我们只需要修改设备名字、设备类型、起始地址、大小、页大小、扇区大小等等,这些信息都可以在W25P80的手册中找到。其中设备的起始地址可以随便定义,但不要和内部FLASH地址冲突即可。这里定义的是0x10000000.FlashPrg.c文件是接口的实现文件,这里我把LPC54114SDK中的polling_flash下的驱动文件拿来直接使用了,即mx25r_flash.c/h文件,只需要在FlashPrg.c中简单调用即可,如下:[cpp] view plain copy
  1. /* ----------------------------------------------------------------------------- 
  2.  * Copyright (c) 2016 ARM Ltd. 
  3.  * 
  4.  * This software is provided 'as-is', without any express or implied warranty. 
  5.  * In no event will the authors be held liable for any damages arising from 
  6.  * the use of this software. Permission is granted to anyone to use this 
  7.  * software for any purpose, including commercial applications, and to alter 
  8.  * it and redistribute it freely, subject to the following restrictions: 
  9.  * 
  10.  * 1. The origin of this software must not be misrepresented; you must not 
  11.  *    claim that you wrote the original software. If you use this software in 
  12.  *    a product, an acknowledgment in the product documentation would be 
  13.  *    appreciated but is not required. 
  14.  * 
  15.  * 2. Altered source versions must be plainly marked as such, and must not be 
  16.  *    misrepresented as being the original software. 
  17.  * 
  18.  * 3. This notice may not be removed or altered from any source distribution. 
  19.  * 
  20.  * 
  21.  * $Date:        29. August 2017 
  22.  * $Revision:    V1.0.0 
  23.  * 
  24.  * Project:      Flash Device Algorithm for 
  25.  *               NXP LPC54114 W25P80 SPI Flash 
  26.  * --------------------------------------------------------------------------- */  
  27.   
  28. #include "..FlashOS.H"        // FlashOS Structures  
  29. #include "fsl_iocon.h"  
  30. #include "fsl_spi.h"  
  31. #include "mx25r_flash.h"  
  32.   
  33. #define SECTOR_ADDR 0  
  34. #define SECTOR_SIZE 65536  
  35. #define FLASH_SPI_SSEL 3  
  36. #define EXAMPLE_SPI_MASTER SPI2  
  37. #define EXAMPLE_SPI_MASTER_CLK_SRC kCLOCK_Flexcomm2  
  38. #define EXAMPLE_SPI_MASTER_CLK_FREQ 12000000  
  39. unsigned long base_adr;  
  40. unsigned char chk_buf[256];  
  41. struct mx25r_instance mx25r;  
  42.   
  43. void SPI_InitPins(void) {  
  44.   
  45.   CLOCK_EnableClock(kCLOCK_Iocon);   /* enable clock for IOCON */  
  46.     
  47.   /* SPI pins */  
  48.   IOCON_PinMuxSet(IOCON, 0, 8, (IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_MOSI */  
  49.   IOCON_PinMuxSet(IOCON, 0, 9, (IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_MISO */  
  50.   IOCON_PinMuxSet(IOCON, 0, 10, (IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_SCK */  
  51.   IOCON_PinMuxSet(IOCON, 0, 2, (IOCON_FUNC2 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_CSN */  
  52. }  
  53.   
  54. int flash_transfer_cb(void *transfer_prv, uint8_t *tx_data, uint8_t *rx_data, size_t dataSize, bool eof)  
  55. {  
  56.     spi_transfer_t xfer = {0};  
  57.     xfer.txData = tx_data;  
  58.     xfer.rxData = rx_data;  
  59.     xfer.dataSize = dataSize;  
  60.     /* terminate frame */  
  61.     if (eof)  
  62.     {  
  63.         xfer.configFlags |= kSPI_FrameAssert;  
  64.     }  
  65.     SPI_MasterTransferBlocking((SPI_Type *)transfer_prv, &xfer);  
  66.     return 0;  
  67. }  
  68.   
  69. int flash_init(void)  
  70. {  
  71.   spi_master_config_t masterConfig = {0};  
  72.   SPI_MasterGetDefaultConfig(&masterConfig);  
  73.   masterConfig.direction = kSPI_MsbFirst;  
  74.   masterConfig.polarity = kSPI_ClockPolarityActiveHigh;  
  75.   masterConfig.phase = kSPI_ClockPhaseFirstEdge;  
  76.   masterConfig.baudRate_Bps = 1000000;  
  77.   masterConfig.sselNum = (spi_ssel_t)FLASH_SPI_SSEL;  
  78.   SPI_MasterInit(EXAMPLE_SPI_MASTER, &masterConfig, EXAMPLE_SPI_MASTER_CLK_FREQ);  
  79.   
  80.   mx25r_init(&mx25r, flash_transfer_cb, EXAMPLE_SPI_MASTER);  
  81.   return mx25r_err_ok;  
  82. }  
  83.   
  84. /* 
  85.  *  Initialize Flash Programming Functions 
  86.  *    Parameter:      adr:  Device Base Address 
  87.  *                    clk:  Clock Frequency (Hz) 
  88.  *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify) 
  89.  *    Return Value:   0 - OK,  1 - Failed 
  90.  */  
  91.   
  92. int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {  
  93.     
  94.   SYSCON->FXCOMCLKSEL[2] = 0;  
  95.   /* reset FLEXCOMM for SPI */