在线时间2412 小时
UID3327992
注册时间2018-4-5
NXP金币3373
TA的每日心情 | 奋斗 昨天 11:05 |
---|
签到天数: 1950 天 [LV.Master]伴坛终老
版主
- 积分
- 17382
- 最后登录
- 2024-5-6
|
本帖最后由 流水源 于 2022-10-30 00:11 编辑
上篇搞定了W25Qxx SPIFLASH的驱动,这次就想想把keil的下载算法搞一搞,后面方便存储下载一些资源了。
下面就参考论坛关于keil的flash下载算法内容:
编写Keil的自定义Flash烧写算法FLM
(出处: 恩智浦技术社区)
浅析Keil MDK下的串行Flash下载算法设计
(出处: 恩智浦技术社区)
使用keil的下载算法模板工程,在keil安装目录的ARM/FLASH下。拷贝模板工程出来,添加flash的驱动以及MCU初始化文件。
下载算法主要是修改FlashPrg.c和FlashDev.c内的接口文件,然后就是MCU的初始化。
首先是FlashDev.c文件,这里面主要提供了一些Flash的基本硬件信息,定义了诸如Flash器件名,sector大小,写入块大小等。下面就是我修改的结构体信息。
- struct FlashDevice const FlashDevice = {
- FLASH_DRV_VERS, // Driver Version, do not modify!
- "LPC845_Mooncake_SPIFLASH", // Device Name
- EXTSPI, // Device Type
- 0x30000000, // Device Start Address
- 0x01000000, // Device Size in Bytes (25Q128=16M)
- 4096, // Programming Page Size
- 0, // Reserved, must be 0
- 0xFF, // Initial Content of Erased Memory
- 10000, // Program Page Timeout 100 mSec
- 10000, // Erase Sector Timeout 3000 mSec
- // Specify Size and Address of Sectors
- 0x001000, 0x000000, // Sector Size 4kB (8 Sectors)
- SECTOR_END
- };
复制代码 然后就是FlashPrg.c文件flash下载的接口函数了。
- // Flash Programming Functions (Called by FlashOS)
- extern int Init (unsigned long adr, // Initialize Flash
- unsigned long clk,
- unsigned long fnc);
- extern int UnInit (unsigned long fnc); // De-initialize Flash
- extern int BlankCheck (unsigned long adr, // Blank Check
- unsigned long sz,
- unsigned char pat);
- extern int EraseChip (void); // Erase complete Device
- extern int EraseSector (unsigned long adr); // Erase Sector Function
- extern int ProgramPage (unsigned long adr, // Program Page Function
- unsigned long sz,
- unsigned char *buf);
- extern unsigned long Verify (unsigned long adr, // Verify Function
- unsigned long sz,
- unsigned char *buf);
复制代码 下面就是我修改的接口函数- void w25qxx_gpio_init(void)
- {
- CLOCK_EnableClock(kCLOCK_Iocon);
- CLOCK_EnableClock(kCLOCK_Gpio0);
- CLOCK_EnableClock(kCLOCK_Gpio1);
- gpio_pin_config_t SPILCD_IN_config = {
- .pinDirection = kGPIO_DigitalInput,
- .outputLogic = 1U,
- };
- gpio_pin_config_t SPILCD_IOH_config = {
- .pinDirection = kGPIO_DigitalOutput,
- .outputLogic = 1U,
- };
- gpio_pin_config_t SPILCD_IOL_config = {
- .pinDirection = kGPIO_DigitalOutput,
- .outputLogic = 0U,
- };
- /* Initialize GPIO functionality on pin */
-
- GPIO_PinInit(GPIO, 1,8, &SPILCD_IOH_config); //FLASH_CS
- GPIO_PinInit(GPIO, 1,9, &SPILCD_IN_config); //FLASH_MISO
- GPIO_PinInit(GPIO, 0,12, &SPILCD_IOH_config);//FLASH_CLK
- GPIO_PinInit(GPIO, 0,13, &SPILCD_IOH_config);//FLASH_MOSI
-
- const uint32_t spilcd_ioc = (/* Selects pull-up function */
- IOCON_PIO_MODE_PULLUP |
- /* Enable hysteresis */
- IOCON_PIO_HYS_EN |
- /* Input not invert */
- IOCON_PIO_INV_DI |
- /* Disables Open-drain function */
- IOCON_PIO_OD_DI |
- /* Bypass input filter */
- IOCON_PIO_SMODE_BYPASS |
- /* IOCONCLKDIV0 */
- IOCON_PIO_CLKDIV0);
-
- const uint32_t SPI_MISO = (/* Selects pull-up function */
- 0 |
- /* Enable hysteresis */
- IOCON_PIO_HYS_EN |
- /* Input not invert */
- IOCON_PIO_INV_DI |
- /* Disables Open-drain function */
- IOCON_PIO_OD_DI |
- /* Bypass input filter */
- IOCON_PIO_SMODE_BYPASS |
- /* IOCONCLKDIV0 */
- IOCON_PIO_CLKDIV0);
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_9, SPI_MISO); //f_miso
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_8, spilcd_ioc); //f_cs
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_12, spilcd_ioc); //f_clk
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_13, spilcd_ioc); //f_mosi
-
- CLOCK_EnableClock(kCLOCK_Swm);
- SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MISO, kSWM_PortPin_P1_9); //F_MISO
- SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MOSI, kSWM_PortPin_P0_13); //F_MOSI
- SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_SCK , kSWM_PortPin_P0_12); //F_CLK
- CLOCK_DisableClock(kCLOCK_Swm);
-
- CLOCK_EnableClock(kCLOCK_Spi1);
- CLOCK_Select(kSPI1_Clk_From_MainClk);
- RESET_PeripheralReset(kSPI1_RST_N_SHIFT_RSTn);
-
- SPI1->CFG = 0x05;
- SPI1->DLY = 0;
- SPI1->DIV = 0;
-
- }
- #define IOCON_PIO_CLKDIV0 0x00u /*!<@brief IOCONCLKDIV0 */
- #define IOCON_PIO_HYS_EN 0x20u /*!<@brief Enable hysteresis */
- #define IOCON_PIO_I2CMODE_FAST 0x00u /*!<@brief Standard/Fast mode */
- #define IOCON_PIO_INV_DI 0x00u /*!<@brief Input not invert */
- #define IOCON_PIO_MODE_PULLUP 0x10u /*!<@brief Selects pull-up function */
- #define IOCON_PIO_OD_DI 0x00u /*!<@brief Disables Open-drain function */
- #define IOCON_PIO_SMODE_BYPASS 0x00u /*!<@brief Bypass input filter */
- void usart_send_str(char *s,int len)
- {
- for(int i=0;i<len;i++){
- while (0U == (USART0->STAT & USART_STAT_TXRDY_MASK)) {; }
- USART0->TXDAT = *s++;
- }
- }
- int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
- /* Add your Code */
- extern void BOARD_BootClockFRO30M(void);
- BOARD_BootClockFRO30M();
- W25QXX_Init();
-
- gpio_pin_config_t LED_config = {
- .pinDirection = kGPIO_DigitalOutput,
- .outputLogic = 1U,
- };
- GPIO_PinInit(GPIO, 0, 0, &LED_config);
- const uint32_t LED_RED = (/* Selects pull-up function */
- IOCON_PIO_MODE_PULLUP |
- /* Enable hysteresis */
- IOCON_PIO_HYS_EN |
- /* Input not invert */
- IOCON_PIO_INV_DI |
- /* Disables Open-drain function */
- IOCON_PIO_OD_DI |
- /* Bypass input filter */
- IOCON_PIO_SMODE_BYPASS |
- /* IOCONCLKDIV0 */
- IOCON_PIO_CLKDIV0);
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_0, LED_RED);
- GPIO->CLR[0] = (1u << 0);
- /* Enables clock for switch matrix.: enable */
- CLOCK_EnableClock(kCLOCK_Swm);
- const uint32_t DEBUG_UART_RX = (/* Selects pull-up function */
- IOCON_PIO_MODE_PULLUP |
- /* Enable hysteresis */
- IOCON_PIO_HYS_EN |
- /* Input not invert */
- IOCON_PIO_INV_DI |
- /* Disables Open-drain function */
- IOCON_PIO_OD_DI |
- /* Bypass input filter */
- IOCON_PIO_SMODE_BYPASS |
- /* IOCONCLKDIV0 */
- IOCON_PIO_CLKDIV0);
- /* PIO1 PIN16 (coords: 36) is configured as USART0, RXD. */
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_24, DEBUG_UART_RX);
- const uint32_t DEBUG_UART_TX = (/* Selects pull-up function */
- IOCON_PIO_MODE_PULLUP |
- /* Enable hysteresis */
- IOCON_PIO_HYS_EN |
- /* Input not invert */
- IOCON_PIO_INV_DI |
- /* Disables Open-drain function */
- IOCON_PIO_OD_DI |
- /* Bypass input filter */
- IOCON_PIO_SMODE_BYPASS |
- /* IOCONCLKDIV0 */
- IOCON_PIO_CLKDIV0);
- /* PIO1 PIN17 (coords: 37) is configured as USART0, TXD. */
- IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_25, DEBUG_UART_TX);
- /* USART0_TXD connect to P0_25 */
- SWM_SetMovablePinSelect(SWM0, kSWM_USART0_TXD, kSWM_PortPin_P0_25);
- /* USART0_RXD connect to P0_24 */
- SWM_SetMovablePinSelect(SWM0, kSWM_USART0_RXD, kSWM_PortPin_P0_24);
- /* Disable clock for switch matrix. */
- CLOCK_DisableClock(kCLOCK_Swm);
-
- CLOCK_EnableClock(kCLOCK_Uart0);
- CLOCK_Select(kUART0_Clk_From_MainClk);
- RESET_PeripheralReset(kUART0_RST_N_SHIFT_RSTn);
- USART0->CFG = 0x05;
- USART0->BRG = 0x13;
- USART0->OSR = 0x0c;
-
- USART0->TXDAT = 0xaa;
- return (0); // Finished without Errors
- }
- /*
- * De-Initialize Flash Programming Functions
- * Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
- * Return Value: 0 - OK, 1 - Failed
- */
- int UnInit (unsigned long fnc) {
- /* Add your Code */
- return (0); // Finished without Errors
- }
- /*
- * Erase complete Flash Memory
- * Return Value: 0 - OK, 1 - Failed
- */
- int EraseChip (void) {
- /* Add your Code */
- USART0->TXDAT = 0x55;
- GPIO->SET[0] = (1u << 0);
- W25QXX_EraseChip();
- GPIO->CLR[0] = (1u << 0);
- 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) {
- /* Add your Code */
- // usart_send_str((char *)adr,4);
- USART0->TXDAT = 0x5a;
- GPIO->SET[0] = (1u << 0);
- W25QXX_EraseSector(adr-0x30000000);
- GPIO->CLR[0] = (1u << 0);
- return (0); // Finished without Errors
- }
- /*
- * 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 long sz, unsigned char *buf) {
- /* Add your Code */
- // usart_send_str((char *)adr,4);
- // usart_send_str((char *)sz,4);
- // USART0->TXDAT = buf[0];
- GPIO->SET[0] = (1u << 0);
- W25QXX_Write_NoCheck(adr-0x30000000,buf,sz);
- GPIO->CLR[0] = (1u << 0);
- return (0); // Finished without Errors
- }
- unsigned long Verify ( unsigned long adr, // Verify Function
- unsigned long sz,
- unsigned char *buf)
- {
- // unsigned long i=0;
- // unsigned char buff[16];
- // USART0->TXDAT = buf[0];
- // while(i<sz)
- // {
- // W25QXX_Read(adr-0x30000000 + i,buff, 16);
- // for(int j=0;j<16;j++)
- // {
- // if(buff[j] != buf[i+j])
- // {
- // return adr+i+j;
- // }
- // }
- // i+=16;
- // }
- return (adr+sz);
- }
- int BlankCheck (unsigned long adr, // Blank Check
- unsigned long sz,
- unsigned char pat)
- {
- USART0->TXDAT = 0x5f;
- return (0);
- }
复制代码
下面看看模板工程的设置
编译之后就可以得到下载算法文件了。把下载算法文件复制到keil目录ARM/FLASH下,后面就可以用了。
下载算法工程。
lpc845_spiflash_flm.rar
(136.32 KB, 下载次数: 1, 售价: 10 NXP金币)
|
|