查看: 1503|回复: 8

【LPC845月饼板】+搞定W25Qxx SPIFLASH的keil下载算法(一)

[复制链接]
  • TA的每日心情
    奋斗
    昨天 11:05
  • 签到天数: 1950 天

    [LV.Master]伴坛终老

    61

    主题

    1万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    17382
    最后登录
    2024-5-6
    发表于 2022-10-30 00:03:10 | 显示全部楼层 |阅读模式
    本帖最后由 流水源 于 2022-10-30 00:11 编辑

       上篇搞定了W25Qxx SPIFLASH的驱动,这次就想想把keil的下载算法搞一搞,后面方便存储下载一些资源了。
    下面就参考论坛关于keil的flash下载算法内容:
    编写Keil的自定义Flash烧写算法FLM
    (出处: 恩智浦技术社区)

    浅析Keil MDK下的串行Flash下载算法设计
    (出处: 恩智浦技术社区)

    使用keil的下载算法模板工程,在keil安装目录的ARM/FLASH下。拷贝模板工程出来,添加flash的驱动以及MCU初始化文件。
    2.png
    下载算法主要是修改FlashPrg.c和FlashDev.c内的接口文件,然后就是MCU的初始化。
    1.png
    首先是FlashDev.c文件,这里面主要提供了一些Flash的基本硬件信息,定义了诸如Flash器件名,sector大小,写入块大小等。下面就是我修改的结构体信息。
    1. struct FlashDevice const FlashDevice  =  {
    2.    FLASH_DRV_VERS,             // Driver Version, do not modify!
    3.    "LPC845_Mooncake_SPIFLASH", // Device Name
    4.    EXTSPI,                     // Device Type
    5.    0x30000000,                 // Device Start Address
    6.    0x01000000,                 // Device Size in Bytes (25Q128=16M)
    7.    4096,                       // Programming Page Size
    8.    0,                          // Reserved, must be 0
    9.    0xFF,                       // Initial Content of Erased Memory
    10.    10000,                        // Program Page Timeout 100 mSec
    11.    10000,                       // Erase Sector Timeout 3000 mSec

    12. // Specify Size and Address of Sectors
    13.    0x001000, 0x000000,         // Sector Size  4kB (8 Sectors)
    14.    SECTOR_END
    15. };
    复制代码
    然后就是FlashPrg.c文件flash下载的接口函数了。
    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);
    复制代码
    下面就是我修改的接口函数
    1. void w25qxx_gpio_init(void)
    2. {
    3.     CLOCK_EnableClock(kCLOCK_Iocon);
    4.     CLOCK_EnableClock(kCLOCK_Gpio0);
    5.     CLOCK_EnableClock(kCLOCK_Gpio1);

    6.     gpio_pin_config_t SPILCD_IN_config = {
    7.         .pinDirection = kGPIO_DigitalInput,
    8.         .outputLogic = 1U,
    9.     };
    10.     gpio_pin_config_t SPILCD_IOH_config = {
    11.         .pinDirection = kGPIO_DigitalOutput,
    12.         .outputLogic = 1U,
    13.     };
    14.     gpio_pin_config_t SPILCD_IOL_config = {
    15.         .pinDirection = kGPIO_DigitalOutput,
    16.         .outputLogic = 0U,
    17.     };
    18.     /* Initialize GPIO functionality on pin */
    19.    
    20.     GPIO_PinInit(GPIO, 1,8, &SPILCD_IOH_config); //FLASH_CS
    21.     GPIO_PinInit(GPIO, 1,9, &SPILCD_IN_config); //FLASH_MISO
    22.     GPIO_PinInit(GPIO, 0,12, &SPILCD_IOH_config);//FLASH_CLK
    23.     GPIO_PinInit(GPIO, 0,13, &SPILCD_IOH_config);//FLASH_MOSI
    24.    
    25.     const uint32_t spilcd_ioc = (/* Selects pull-up function */
    26.                               IOCON_PIO_MODE_PULLUP |
    27.                               /* Enable hysteresis */
    28.                               IOCON_PIO_HYS_EN |
    29.                               /* Input not invert */
    30.                               IOCON_PIO_INV_DI |
    31.                               /* Disables Open-drain function */
    32.                               IOCON_PIO_OD_DI |
    33.                               /* Bypass input filter */
    34.                               IOCON_PIO_SMODE_BYPASS |
    35.                               /* IOCONCLKDIV0 */
    36.                               IOCON_PIO_CLKDIV0);
    37.         
    38.     const uint32_t SPI_MISO = (/* Selects pull-up function */
    39.                                     0 |
    40.                                     /* Enable hysteresis */
    41.                                     IOCON_PIO_HYS_EN |
    42.                                     /* Input not invert */
    43.                                     IOCON_PIO_INV_DI |
    44.                                     /* Disables Open-drain function */
    45.                                     IOCON_PIO_OD_DI |
    46.                                     /* Bypass input filter */
    47.                                     IOCON_PIO_SMODE_BYPASS |
    48.                                     /* IOCONCLKDIV0 */
    49.                                     IOCON_PIO_CLKDIV0);
    50.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_9, SPI_MISO);   //f_miso

    51.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_8,   spilcd_ioc);   //f_cs
    52.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_12,  spilcd_ioc);   //f_clk
    53.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_13,  spilcd_ioc);   //f_mosi
    54.    
    55.     CLOCK_EnableClock(kCLOCK_Swm);
    56.     SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MISO,  kSWM_PortPin_P1_9);  //F_MISO
    57.     SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MOSI,  kSWM_PortPin_P0_13); //F_MOSI
    58.     SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_SCK ,  kSWM_PortPin_P0_12); //F_CLK
    59.     CLOCK_DisableClock(kCLOCK_Swm);
    60.    
    61.     CLOCK_EnableClock(kCLOCK_Spi1);
    62.     CLOCK_Select(kSPI1_Clk_From_MainClk);
    63.     RESET_PeripheralReset(kSPI1_RST_N_SHIFT_RSTn);
    64.    
    65.     SPI1->CFG = 0x05;
    66.     SPI1->DLY = 0;
    67.     SPI1->DIV = 0;
    68.    
    69. }

    70. #define IOCON_PIO_CLKDIV0       0x00u       /*!<@brief IOCONCLKDIV0 */
    71. #define IOCON_PIO_HYS_EN        0x20u       /*!<@brief Enable hysteresis */
    72. #define IOCON_PIO_I2CMODE_FAST  0x00u       /*!<@brief Standard/Fast mode */
    73. #define IOCON_PIO_INV_DI        0x00u       /*!<@brief Input not invert */
    74. #define IOCON_PIO_MODE_PULLUP   0x10u       /*!<@brief Selects pull-up function */
    75. #define IOCON_PIO_OD_DI         0x00u       /*!<@brief Disables Open-drain function */
    76. #define IOCON_PIO_SMODE_BYPASS  0x00u       /*!<@brief Bypass input filter */

    77. void usart_send_str(char *s,int len)
    78. {
    79.     for(int i=0;i<len;i++){
    80.         while (0U == (USART0->STAT & USART_STAT_TXRDY_MASK))   {; }
    81.         USART0->TXDAT = *s++;
    82.     }
    83. }

    84. int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {

    85.     /* Add your Code */
    86.     extern void BOARD_BootClockFRO30M(void);
    87.     BOARD_BootClockFRO30M();
    88.     W25QXX_Init();
    89.    
    90.     gpio_pin_config_t LED_config = {
    91.         .pinDirection = kGPIO_DigitalOutput,
    92.         .outputLogic = 1U,
    93.     };
    94.     GPIO_PinInit(GPIO, 0, 0, &LED_config);
    95.     const uint32_t LED_RED = (/* Selects pull-up function */
    96.                               IOCON_PIO_MODE_PULLUP |
    97.                               /* Enable hysteresis */
    98.                               IOCON_PIO_HYS_EN |
    99.                               /* Input not invert */
    100.                               IOCON_PIO_INV_DI |
    101.                               /* Disables Open-drain function */
    102.                               IOCON_PIO_OD_DI |
    103.                               /* Bypass input filter */
    104.                               IOCON_PIO_SMODE_BYPASS |
    105.                               /* IOCONCLKDIV0 */
    106.                               IOCON_PIO_CLKDIV0);
    107.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_0, LED_RED);
    108.     GPIO->CLR[0] = (1u << 0);


    109.     /* Enables clock for switch matrix.: enable */
    110.     CLOCK_EnableClock(kCLOCK_Swm);
    111.     const uint32_t DEBUG_UART_RX = (/* Selects pull-up function */
    112.                                     IOCON_PIO_MODE_PULLUP |
    113.                                     /* Enable hysteresis */
    114.                                     IOCON_PIO_HYS_EN |
    115.                                     /* Input not invert */
    116.                                     IOCON_PIO_INV_DI |
    117.                                     /* Disables Open-drain function */
    118.                                     IOCON_PIO_OD_DI |
    119.                                     /* Bypass input filter */
    120.                                     IOCON_PIO_SMODE_BYPASS |
    121.                                     /* IOCONCLKDIV0 */
    122.                                     IOCON_PIO_CLKDIV0);
    123.     /* PIO1 PIN16 (coords: 36) is configured as USART0, RXD. */
    124.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_24, DEBUG_UART_RX);

    125.     const uint32_t DEBUG_UART_TX = (/* Selects pull-up function */
    126.                                     IOCON_PIO_MODE_PULLUP |
    127.                                     /* Enable hysteresis */
    128.                                     IOCON_PIO_HYS_EN |
    129.                                     /* Input not invert */
    130.                                     IOCON_PIO_INV_DI |
    131.                                     /* Disables Open-drain function */
    132.                                     IOCON_PIO_OD_DI |
    133.                                     /* Bypass input filter */
    134.                                     IOCON_PIO_SMODE_BYPASS |
    135.                                     /* IOCONCLKDIV0 */
    136.                                     IOCON_PIO_CLKDIV0);
    137.     /* PIO1 PIN17 (coords: 37) is configured as USART0, TXD. */
    138.     IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_25, DEBUG_UART_TX);
    139.     /* USART0_TXD connect to P0_25 */
    140.     SWM_SetMovablePinSelect(SWM0, kSWM_USART0_TXD, kSWM_PortPin_P0_25);
    141.     /* USART0_RXD connect to P0_24 */
    142.     SWM_SetMovablePinSelect(SWM0, kSWM_USART0_RXD, kSWM_PortPin_P0_24);
    143.     /* Disable clock for switch matrix. */
    144.     CLOCK_DisableClock(kCLOCK_Swm);
    145.    
    146.     CLOCK_EnableClock(kCLOCK_Uart0);
    147.     CLOCK_Select(kUART0_Clk_From_MainClk);
    148.     RESET_PeripheralReset(kUART0_RST_N_SHIFT_RSTn);
    149.     USART0->CFG = 0x05;
    150.     USART0->BRG = 0x13;
    151.     USART0->OSR = 0x0c;
    152.    
    153.     USART0->TXDAT = 0xaa;
    154.     return (0);                                  // Finished without Errors
    155. }

    156. /*
    157. *  De-Initialize Flash Programming Functions
    158. *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
    159. *    Return Value:   0 - OK,  1 - Failed
    160. */

    161. int UnInit (unsigned long fnc) {

    162.   /* Add your Code */
    163.   return (0);                                  // Finished without Errors
    164. }


    165. /*
    166. *  Erase complete Flash Memory
    167. *    Return Value:   0 - OK,  1 - Failed
    168. */

    169. int EraseChip (void) {

    170.   /* Add your Code */
    171.     USART0->TXDAT = 0x55;
    172.     GPIO->SET[0] = (1u << 0);
    173.     W25QXX_EraseChip();
    174.     GPIO->CLR[0] = (1u << 0);
    175.   return (0);                                  // Finished without Errors
    176. }


    177. /*
    178. *  Erase Sector in Flash Memory
    179. *    Parameter:      adr:  Sector Address
    180. *    Return Value:   0 - OK,  1 - Failed
    181. */

    182. int EraseSector (unsigned long adr) {

    183.   /* Add your Code */
    184. //    usart_send_str((char *)adr,4);
    185.     USART0->TXDAT = 0x5a;
    186.     GPIO->SET[0] = (1u << 0);
    187.     W25QXX_EraseSector(adr-0x30000000);
    188.     GPIO->CLR[0] = (1u << 0);
    189.   return (0);                                  // Finished without Errors
    190. }


    191. /*
    192. *  Program Page in Flash Memory
    193. *    Parameter:      adr:  Page Start Address
    194. *                    sz:   Page Size
    195. *                    buf:  Page Data
    196. *    Return Value:   0 - OK,  1 - Failed
    197. */

    198. int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {

    199.   /* Add your Code */
    200. //    usart_send_str((char *)adr,4);
    201. //    usart_send_str((char *)sz,4);
    202. //    USART0->TXDAT = buf[0];
    203.     GPIO->SET[0] = (1u << 0);
    204.     W25QXX_Write_NoCheck(adr-0x30000000,buf,sz);
    205.     GPIO->CLR[0] = (1u << 0);
    206.   return (0);                                  // Finished without Errors
    207. }


    208. unsigned long Verify      ( unsigned long adr,   // Verify Function
    209.                             unsigned long sz,
    210.                             unsigned char *buf)
    211. {
    212. //    unsigned long i=0;
    213. //    unsigned char buff[16];
    214. //    USART0->TXDAT = buf[0];
    215. //    while(i<sz)
    216. //    {
    217. //        W25QXX_Read(adr-0x30000000 + i,buff, 16);
    218. //        for(int j=0;j<16;j++)
    219. //        {
    220. //            if(buff[j] != buf[i+j])
    221. //            {
    222. //                return adr+i+j;
    223. //            }
    224. //        }        
    225. //        i+=16;
    226. //    }
    227.   return (adr+sz);
    228. }

    229. int  BlankCheck  (unsigned long adr,   // Blank Check
    230.                     unsigned long sz,
    231.                     unsigned char pat)
    232. {
    233.     USART0->TXDAT = 0x5f;
    234.   return (0);
    235. }

    复制代码


    下面看看模板工程的设置
    4.png 3.png 5.png 6.png 7.png 8.png

    编译之后就可以得到下载算法文件了。把下载算法文件复制到keil目录ARM/FLASH下,后面就可以用了。


    下载算法工程。
    lpc845_spiflash_flm.rar (136.32 KB, 下载次数: 1, 售价: 10 NXP金币)
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    昨天 14:17
  • 签到天数: 1337 天

    [LV.10]以坛为家III

    88

    主题

    4294

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9059
    最后登录
    2024-5-6
    发表于 2022-10-30 11:05:35 | 显示全部楼层
    这个flash下载算法的意义是使用jlink将bin文件烧写入SPI flash里面吗?
    今天天气不错!签到!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 11:05
  • 签到天数: 1950 天

    [LV.Master]伴坛终老

    61

    主题

    1万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    17382
    最后登录
    2024-5-6
     楼主| 发表于 2022-10-30 11:34:13 | 显示全部楼层
    jobszheng5 发表于 2022-10-30 11:05
    这个flash下载算法的意义是使用jlink将bin文件烧写入SPI flash里面吗?

    这个就是方便直接在程序中定义图片,字体等bin数据,直接下载到spiflash中。就不用额外搞个程序下载spiflash了。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 14:17
  • 签到天数: 1337 天

    [LV.10]以坛为家III

    88

    主题

    4294

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9059
    最后登录
    2024-5-6
    发表于 2022-10-31 09:54:57 | 显示全部楼层
    感觉明白了一些,我再去看看帖子开篇提到的两篇参考文档。
    谢谢楼主

    今天天气不错!签到!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 11:05
  • 签到天数: 1950 天

    [LV.Master]伴坛终老

    61

    主题

    1万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    17382
    最后登录
    2024-5-6
     楼主| 发表于 2022-10-31 10:52:05 | 显示全部楼层
    jobszheng5 发表于 2022-10-31 09:54
    感觉明白了一些,我再去看看帖子开篇提到的两篇参考文档。
    谢谢楼主

    可以看看我第二篇,如何用这个下载算法,
    【LPC845月饼板】+测试SPIFLASH的keil下载算法(二)
    https://www.nxpic.org.cn/module/ ... amp;fromuid=3327992
    (出处: 恩智浦技术社区)
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 00:52
  • 签到天数: 1221 天

    [LV.10]以坛为家III

    22

    主题

    4788

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    8126

    活跃会员

    最后登录
    2024-5-6
    发表于 2022-10-31 15:32:47 | 显示全部楼层
    前排支持,不愧是点灯侠
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2024-2-5 12:06
  • 签到天数: 627 天

    [LV.9]以坛为家II

    94

    主题

    1628

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    4429

    热心会员

    最后登录
    2024-2-5
    发表于 2022-10-31 15:38:48 | 显示全部楼层
    不错,有意思~
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 11:15
  • 签到天数: 691 天

    [LV.9]以坛为家II

    12

    主题

    3058

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    3711
    最后登录
    2024-5-6
    发表于 2022-11-1 09:51:20 | 显示全部楼层
    楼主辛苦了,谢谢您的资料
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-2-21 10:06
  • 签到天数: 310 天

    [LV.8]以坛为家I

    2

    主题

    5670

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    11646
    最后登录
    2024-2-21
    发表于 2023-8-24 10:55:37 | 显示全部楼层
    活动第9天打卡
    活动第9天.png
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-5-7 06:38 , Processed in 0.131476 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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