加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 19:52:40 所属栏目:百科 来源:网络整理
导读:主机环境:Windows 10 64bit 开发环境:MDK 5.23 目标板:LPC54114 之前在NXP社区得到一块LPC54114的板卡,是由万利制作的,LPC54114是一款双核MCU,包含了一颗M4主核和一颗M0+从核,利用该板卡学习了一下双核MCU的开发流程,板卡中提供了一颗W25P80FLASH,

主机环境: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的相关信息,经过简单修改就可以使用了,如下:

#ifdef W25P80
struct FlashDevice const FlashDevice  =  {
   FLASH_DRV_VERS,// Driver Version,do not modify!
   "LPC54114 W25P80 SPI",// Device Name
   EXTSPI,// Device Type
   0x10000000,// Device Start Address
   0x00100000,// Device Size (1MB)
   256,// Programming Page Size
   0,// Reserved,must be 0
   0xFF,// Initial Content of Erased Memory
   300,// Program Page Timeout 300 mSec
   3000,// Erase Sector Timeout 3000 mSec

// Specify Size and Address of Sectors
   0x010000,0x000000,// Sector Size 64kB (16 Sectors)
   SECTOR_END
};
#endif
我们只需要修改设备名字、设备类型、起始地址、大小、页大小、扇区大小等等,这些信息都可以在W25P80的手册中找到。其中设备的起始地址可以随便定义,但不要和内部FLASH地址冲突即可。这里定义的是0x10000000.FlashPrg.c文件是接口的实现文件,这里我把LPC54114SDK中的polling_flash下的驱动文件拿来直接使用了,即mx25r_flash.c/h文件,只需要在FlashPrg.c中简单调用即可,如下:

/* -----------------------------------------------------------------------------
 * Copyright (c) 2016 ARM Ltd.
 *
 * This software is provided 'as-is',without any express or implied warranty.
 * In no event will the authors be held liable for any damages arising from
 * the use of this software. Permission is granted to anyone to use this
 * software for any purpose,including commercial applications,and to alter
 * it and redistribute it freely,subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software in
 *    a product,an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such,and must not be
 *    misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source distribution.
 *
 *
 * $Date:        29. August 2017
 * $Revision:    V1.0.0
 *
 * Project:      Flash Device Algorithm for
 *               NXP LPC54114 W25P80 SPI Flash
 * --------------------------------------------------------------------------- */

#include "..FlashOS.H"        // FlashOS Structures
#include "fsl_iocon.h"
#include "fsl_spi.h"
#include "mx25r_flash.h"

#define SECTOR_ADDR 0
#define SECTOR_SIZE 65536
#define FLASH_SPI_SSEL 3
#define EXAMPLE_SPI_MASTER SPI2
#define EXAMPLE_SPI_MASTER_CLK_SRC kCLOCK_Flexcomm2
#define EXAMPLE_SPI_MASTER_CLK_FREQ 12000000
unsigned long base_adr;
unsigned char chk_buf[256];
struct mx25r_instance mx25r;

void SPI_InitPins(void) {

  CLOCK_EnableClock(kCLOCK_Iocon);   /* enable clock for IOCON */
  
  /* SPI pins */
  IOCON_PinMuxSet(IOCON,8,(IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_MOSI */
  IOCON_PinMuxSet(IOCON,9,(IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_MISO */
  IOCON_PinMuxSet(IOCON,10,(IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_SCK */
  IOCON_PinMuxSet(IOCON,2,(IOCON_FUNC2 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_CSN */
}

int flash_transfer_cb(void *transfer_prv,uint8_t *tx_data,uint8_t *rx_data,size_t dataSize,bool eof)
{
    spi_transfer_t xfer = {0};
    xfer.txData = tx_data;
    xfer.rxData = rx_data;
    xfer.dataSize = dataSize;
    /* terminate frame */
    if (eof)
    {
        xfer.configFlags |= kSPI_FrameAssert;
    }
    SPI_MasterTransferBlocking((SPI_Type *)transfer_prv,&xfer);
    return 0;
}

int flash_init(void)
{
  spi_master_config_t masterConfig = {0};
  SPI_MasterGetDefaultConfig(&masterConfig);
  masterConfig.direction = kSPI_MsbFirst;
  masterConfig.polarity = kSPI_ClockPolarityActiveHigh;
  masterConfig.phase = kSPI_ClockPhaseFirstEdge;
  masterConfig.baudRate_Bps = 1000000;
  masterConfig.sselNum = (spi_ssel_t)FLASH_SPI_SSEL;
  SPI_MasterInit(EXAMPLE_SPI_MASTER,&masterConfig,EXAMPLE_SPI_MASTER_CLK_FREQ);

  mx25r_init(&mx25r,flash_transfer_cb,EXAMPLE_SPI_MASTER);
  return mx25r_err_ok;
}

/*
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Device Base Address
 *                    clk:  Clock Frequency (Hz)
 *                    fnc:  Function Code (1 - Erase,2 - Program,3 - Verify)
 *    Return Value:   0 - OK,1 - Failed
 */

int Init (unsigned long adr,unsigned long clk,unsigned long fnc) {
  
  SYSCON->FXCOMCLKSEL[2] = 0;
  /* reset FLEXCOMM for SPI */
  SYSCON->PRESETCTRLSET[1] = (uint32_t)(1<<13);
  SYSCON->PRESETCTRLCLR[1] = (uint32_t)(1<<13);
  
  SPI_InitPins();
  flash_init();
  base_adr = adr;

  return (0);
}


/*
 *  De-Initialize Flash Programming Functions
 *    Parameter:      fnc:  Function Code (1 - Erase,1 - Failed
 */

int UnInit (unsigned long fnc) {

  return (0);
}


/*
 *  Erase complete Flash Memory
 *    Return Value:   0 - OK,1 - Failed
 */

int EraseChip (void) {

  mx25r_cmd_chip_erase(&mx25r);
  return (0);                                        /* Finished without Errors */
}


/*
 *  Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,1 - Failed
 */

int EraseSector (unsigned long adr) {

  mx25r_cmd_sector_erase(&mx25r,adr-base_adr);
  return (0);                                        /* Finished without Errors */
}


/*
 *  Blank Check Checks if Memory is Blank
 *    Parameter:      adr:  Block Start Address
 *                    sz:   Block Size (in bytes)
 *                    pat:  Block Pattern
 *    Return Value:   0 - OK,1 - Failed
 */

int BlankCheck (unsigned long adr,unsigned long sz,unsigned char pat) {

  return (1);                                        /* Always Force Erase */
}


/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,1 - Failed
 */

int ProgramPage (unsigned long adr,unsigned char *buf) {
  
  mx25r_cmd_write(&mx25r,adr-base_adr,buf,sz);
  return (0);                                        /* Finished without Errors */
}


/*  
 *  Verify Flash Contents
 *    Parameter:      adr:  Start Address
 *                    sz:   Size (in bytes)
 *                    buf:  Data
 *    Return Value:   (adr+sz) - OK,Failed Address
 */

unsigned long Verify (unsigned long adr,unsigned char *buf)
{
  int i = 0;	
  mx25r_cmd_read(&mx25r,chk_buf,sz);
  for(i = 0; i < sz; i++)
  {
    if(buf[i] != chk_buf[i])
    {
	  return (adr+i);
	}		
  }
  return (adr+sz);
}
编译该工程,即可产生我们所需要的加载FLASH的算法文件,如下:



下面就来测试下该算法文件是否起作用,在LPC54114的SDK中的polling_flash工程中加入一段测试数据,如下:

const uint8_t extFlash[] __attribute__ ((at(0x10000000))) = 
{'N','X','P','I','C'};
把这几个字符存放到外部FLASH的0地址上,这里0x10000000是我们刚才定义的外部FLASH的起始地址。此外还需要添加一下该算法文件,如下:



下载该代码,本以为就此成功了,结果弹出一个框框,说无法加载FLASH编程算法,


MDK中的输出信息如下:Insufficient RAM for Flash Algorithms !,百度搜索了一下说是为该算法分配的RAM空间小了,默认的是0x1000,4KB大小,这里加大了已被改成了8KB,如下:


再次下载,很顺畅地下载成功了,赶紧打开串口助手查看测试结果:


成功地从外部FLASH读取到了我们定义的‘NXPIC’字符,测试成功!大家一起来测试一下吧!

工程文件:http://download.csdn.net/download/key123zhangxing/9956278

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读