查看: 12795|回复: 10

[分享] LPC54114外部FLASH编程算法

[复制链接]
  • TA的每日心情
    开心
    2018-6-6 08:45
  • 签到天数: 328 天

    连续签到: 1 天

    [LV.8]以坛为家I

    10

    主题

    1047

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2006
    最后登录
    2019-5-1
    发表于 2017-8-29 22:51:29 | 显示全部楼层 |阅读模式
    本帖最后由 anobodykey 于 2017-8-30 21:58 编辑

    根据LPC54608的外部FLASH编程算法工程修改而来,放入到keil5\ARM\Flash目录下即可,编译后生成LPC54114_W25P80.FLM,测试可用,欢迎下载测试。
    放一些知识点:
    LPC54114板卡资源是片上256KB的FLASH,以及192KB的SRAM,平时我们在编辑代码生成的固件一般都是直接下载到片内256KB的FLASH中,但有时我们想要把一些数据放到外部FLASH中以便节省内部FLASH空间,即把代码和数据分开存储,这里就是实现该功能。平时我们是如何把代码通过调试器下载到片内FLASH中呢?在Debug Setting中有一个FLASH Download选项卡,如下:
    捕获.PNG
    其中下面的编程算法中我们加载的是LPC5411x_IAP 256KB Flash算法,该算法由MDK的DFP包提供,具体在以下路径中
    捕获.PNG
    其中有算法文件FLM以及算法的相应源文件,正是由于该算法的存在,才使得我们能够通过调试器把代码下载到板卡中。
    现在我们需要把数据烧录到外部FLASH中,同样需要这样一个算法文件,但很可惜MDK并没有给出LPC54114板卡的烧录外部FLASH算法文件,但是有一个LPC54608板卡的外部FLASH算法文件,如下:
    捕获.PNG
    其中LPC5460x_MT25QL128 SPIFI即是。不要意外上面的LPC54114 W25P80 SPI算法文件是我们自己生成的。在MDK的安装目录中有一个Flash路径,存放了各种FLASH的算法文件,我们只需要找到跟我们板卡 相近的工程文件修改一下即可,这里就是使用的LPC5460x_MT25QL128工程文件,拷贝一份该工程并命名为LPC54114 W25P80,并把其中跟LPC54608相关的宏都替换成LPC54114,并从LPC54114的SDK中拷贝出我们需要的库文件
    捕获.PNG
    由于LPC54114SDK中有spi flash的相关代码,这里我直接拷贝的driver_examples\spi\polling_flash工程中的mx25r_flash.c/h文件,我们需要关注的核心文件只有两个:FlashDev.c以及FlashPrg.c,前者定义了外部FLASH的相关信息,如下:
    1. #include "..\FlashOS.H"        // FlashOS Structures


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

    14. // Specify Size and Address of Sectors
    15.    0x010000, 0x000000,         // Sector Size 64kB (16 Sectors)
    16.    SECTOR_END
    17. };
    18. #endif
    复制代码
    其中flashos.h头文件是ARM提供的,其定义了编程flash的相关接口,以及flash的定义。该结构体所需要的相关信息都可以从W25P80手册中找到,设备的起始地址由我们随意指定,但不能和片内FLASH地址冲突,这里定义的是0x10000000,大小为0x00100000,页大小为256字节,扇区大小为64KB。再来看flashprg.c文件,该文件实现了flashos.h定义的相关接口,我们需要实现以下接口
    1. // Flash Programming Functions (Called by FlashOS)
    2. extern          int  Init        (unsigned long adr,   // Initialize Flash
    3.                                   unsigned long clk,
    4.                                   unsigned long fnc);
    5. extern          int  UnInit      (unsigned long fnc);  // De-initialize Flash
    6. extern          int  BlankCheck  (unsigned long adr,   // Blank Check
    7.                                   unsigned long sz,
    8.                                   unsigned char pat);
    9. extern          int  EraseChip   (void);               // Erase complete Device
    10. extern          int  EraseSector (unsigned long adr);  // Erase Sector Function
    11. extern          int  ProgramPage (unsigned long adr,   // Program Page Function
    12.                                   unsigned long sz,
    13.                                   unsigned char *buf);
    14. extern unsigned long Verify      (unsigned long adr,   // Verify Function
    15.                                   unsigned long sz,
    16.                                   unsigned char *buf);
    复制代码
    在FlashPrg.c文件中我们直接调用mx25r_flash的相关接口即可。
    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. #include "..\FlashOS.H"        // FlashOS Structures
    28. #include "fsl_iocon.h"
    29. #include "fsl_spi.h"
    30. #include "mx25r_flash.h"

    31. #define SECTOR_ADDR 0
    32. #define SECTOR_SIZE 65536
    33. #define FLASH_SPI_SSEL 3
    34. #define EXAMPLE_SPI_MASTER SPI2
    35. #define EXAMPLE_SPI_MASTER_CLK_SRC kCLOCK_Flexcomm2
    36. #define EXAMPLE_SPI_MASTER_CLK_FREQ 12000000
    37. unsigned long base_adr;
    38. unsigned char chk_buf[256];
    39. struct mx25r_instance mx25r;

    40. void SPI_InitPins(void) {

    41.   CLOCK_EnableClock(kCLOCK_Iocon);   /* enable clock for IOCON */
    42.   
    43.   /* SPI pins */
    44.   IOCON_PinMuxSet(IOCON, 0, 8, (IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_MOSI */
    45.   IOCON_PinMuxSet(IOCON, 0, 9, (IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_MISO */
    46.   IOCON_PinMuxSet(IOCON, 0, 10, (IOCON_FUNC1 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_SCK */
    47.   IOCON_PinMuxSet(IOCON, 0, 2, (IOCON_FUNC2 | IOCON_MODE_PULLUP | IOCON_DIGITAL_EN));  /* SPI_CSN */
    48. }

    49. int flash_transfer_cb(void *transfer_prv, uint8_t *tx_data, uint8_t *rx_data, size_t dataSize, bool eof)
    50. {
    51.     spi_transfer_t xfer = {0};
    52.     xfer.txData = tx_data;
    53.     xfer.rxData = rx_data;
    54.     xfer.dataSize = dataSize;
    55.     /* terminate frame */
    56.     if (eof)
    57.     {
    58.         xfer.configFlags |= kSPI_FrameAssert;
    59.     }
    60.     SPI_MasterTransferBlocking((SPI_Type *)transfer_prv, &xfer);
    61.     return 0;
    62. }

    63. int flash_init(void)
    64. {
    65.   spi_master_config_t masterConfig = {0};
    66.   SPI_MasterGetDefaultConfig(&masterConfig);
    67.   masterConfig.direction = kSPI_MsbFirst;
    68.   masterConfig.polarity = kSPI_ClockPolarityActiveHigh;
    69.   masterConfig.phase = kSPI_ClockPhaseFirstEdge;
    70.   masterConfig.baudRate_Bps = 1000000;
    71.   masterConfig.sselNum = (spi_ssel_t)FLASH_SPI_SSEL;
    72.   SPI_MasterInit(EXAMPLE_SPI_MASTER, &masterConfig, EXAMPLE_SPI_MASTER_CLK_FREQ);

    73.   mx25r_init(&mx25r, flash_transfer_cb, EXAMPLE_SPI_MASTER);
    74.   return mx25r_err_ok;
    75. }

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

    83. int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
    84.   
    85.   SYSCON->FXCOMCLKSEL[2] = 0;
    86.   /* reset FLEXCOMM for SPI */
    87.   SYSCON->PRESETCTRLSET[1] = (uint32_t)(1<<13);
    88.   SYSCON->PRESETCTRLCLR[1] = (uint32_t)(1<<13);
    89.   
    90.   SPI_InitPins();
    91.   flash_init();
    92.   base_adr = adr;

    93.   return (0);
    94. }


    95. /*
    96. *  De-Initialize Flash Programming Functions
    97. *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
    98. *    Return Value:   0 - OK,  1 - Failed
    99. */

    100. int UnInit (unsigned long fnc) {

    101.   return (0);
    102. }


    103. /*
    104. *  Erase complete Flash Memory
    105. *    Return Value:   0 - OK,  1 - Failed
    106. */

    107. int EraseChip (void) {

    108.   mx25r_cmd_chip_erase(&mx25r);
    109.   return (0);                                        /* Finished without Errors */
    110. }


    111. /*
    112. *  Erase Sector in Flash Memory
    113. *    Parameter:      adr:  Sector Address
    114. *    Return Value:   0 - OK,  1 - Failed
    115. */

    116. int EraseSector (unsigned long adr) {

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


    120. /*
    121. *  Blank Check Checks if Memory is Blank
    122. *    Parameter:      adr:  Block Start Address
    123. *                    sz:   Block Size (in bytes)
    124. *                    pat:  Block Pattern
    125. *    Return Value:   0 - OK,  1 - Failed
    126. */

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

    128.   return (1);                                        /* Always Force Erase */
    129. }


    130. /*
    131. *  Program Page in Flash Memory
    132. *    Parameter:      adr:  Page Start Address
    133. *                    sz:   Page Size
    134. *                    buf:  Page Data
    135. *    Return Value:   0 - OK,  1 - Failed
    136. */

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


    142. /*  
    143. *  Verify Flash Contents
    144. *    Parameter:      adr:  Start Address
    145. *                    sz:   Size (in bytes)
    146. *                    buf:  Data
    147. *    Return Value:   (adr+sz) - OK, Failed Address
    148. */

    149. unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf)
    150. {
    151.   int i = 0;       
    152.   mx25r_cmd_read(&mx25r,adr-base_adr,chk_buf,sz);
    153.   for(i = 0; i < sz; i++)
    154.   {
    155.     if(buf[i] != chk_buf[i])
    156.     {
    157.           return (adr+i);
    158.         }               
    159.   }
    160.   return (adr+sz);
    161. }
    复制代码
    为了避免使用过多的库文件,时钟那块直接使用的寄存器操作。整个实现还是很简单的。编译工程即可生成我们所需的LPC54114 W25P80 FLASH算法文件,下面我们来测试一下该算法文件是否起作用,在polling flash工程的基础上增加一小段代码来测试,如下:
    1. const uint8_t extFlash[] __attribute__ ((at(0x10000000))) =
    2. {'N','X','P','I','C'};
    复制代码
    指定extFlash数组存放在0x10000000地址,该地址就是我们之前定义的外部FLASH的起始地址,其他地方无需改动,在debug选项卡中添加我们生成的算法文件,如下:
    捕获.PNG
    点击下载,本以为就此成功了,结果弹出框框说下载失败,说无法加载算法文件,MDK输出信息:Insufficient RAM for Flash Algorithms !,经过百度说是RAM空间分配不够,上图默认的4KB RAM,于是乎改成8KB。
    捕获.PNG
    再来下载即可成功,赶紧打开串口终端,
    捕获.PNG
    可以看到已经读取出了我们之前存放的‘NXPIC’字符信息。测试成功!


    捕获.PNG

    LPC54114_W25P80.rar

    90.72 KB, 下载次数: 22, 下载积分: 威望 1

    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    719

    主题

    6378

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    25367
    最后登录
    2025-9-1
    发表于 2017-8-30 14:57:37 | 显示全部楼层
    感谢楼主的资料分享!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-6-6 08:45
  • 签到天数: 328 天

    连续签到: 1 天

    [LV.8]以坛为家I

    10

    主题

    1047

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2006
    最后登录
    2019-5-1
     楼主| 发表于 2017-8-30 15:42:36 | 显示全部楼层
    好像没什么人感兴趣。。。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    719

    主题

    6378

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    25367
    最后登录
    2025-9-1
    发表于 2017-8-30 15:48:46 | 显示全部楼层
    anobodykey 发表于 2017-8-30 15:42
    好像没什么人感兴趣。。。

    可能大家还没研究到这块,你可以把具体算法的原理知识也放点出来。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-6-6 08:45
  • 签到天数: 328 天

    连续签到: 1 天

    [LV.8]以坛为家I

    10

    主题

    1047

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2006
    最后登录
    2019-5-1
     楼主| 发表于 2017-8-30 21:59:00 | 显示全部楼层
    小恩GG 发表于 2017-8-30 15:48
    可能大家还没研究到这块,你可以把具体算法的原理知识也放点出来。

    嗯,刚放出了
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2023-9-15 08:42
  • 签到天数: 1952 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    1

    主题

    4686

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9405
    最后登录
    2023-9-15
    发表于 2017-8-31 07:02:52 | 显示全部楼层
    谢谢分享!
    今天天气不错!签到!
    回复

    使用道具 举报

    该用户从未签到

    719

    主题

    6378

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    25367
    最后登录
    2025-9-1
    发表于 2017-8-31 15:21:14 | 显示全部楼层

    好东西!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    61

    主题

    233

    帖子

    7

    高级会员

    Rank: 4

    积分
    750
    最后登录
    2021-1-25
    发表于 2017-9-12 09:09:20 | 显示全部楼层
    你好,我怎么没有LPC5460x_MT25QL128 SPIFI 这个
    截图.png
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-6-6 08:45
  • 签到天数: 328 天

    连续签到: 1 天

    [LV.8]以坛为家I

    10

    主题

    1047

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2006
    最后登录
    2019-5-1
     楼主| 发表于 2017-9-12 11:22:12 | 显示全部楼层
    paulkiyt 发表于 2017-9-12 09:09
    你好,我怎么没有LPC5460x_MT25QL128 SPIFI 这个

    你看下你的MDK版本号,我的是MDK5.23
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    61

    主题

    233

    帖子

    7

    高级会员

    Rank: 4

    积分
    750
    最后登录
    2021-1-25
    发表于 2018-1-10 16:08:04 | 显示全部楼层
    anobodykey 发表于 2017-9-12 11:22
    你看下你的MDK版本号,我的是MDK5.23

    你好,你这里测试只是做个常量的存储,其实不用外部flash算法,把scf文件增加一块qflash就可以了。外部flash算法,如果你用如何将代码下载到qflash这样的例子就很好了。我也在开始研究这个,还不知道怎么搞
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-9-2 05:51 , Processed in 0.101194 second(s), 29 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表