Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5662694
  • 博文数量: 1320
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 15754
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1320)

文章存档

2020年(104)

2019年(193)

2018年(81)

2017年(80)

2016年(70)

2015年(52)

2014年(41)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: 其他平台

2020-08-05 09:31:51

1.      首先启用 Flash模式.

a)       确认 stm32f7xx_hal_conf.h 中 启用了 #define HAL_FLASH_MODULE_ENABLED

b)       在 Drivers/STM32F7xx_HAL_Drivers中确认添加了源码  stm32f7xx_hal_cortex/flash/flash_ex.c 三个文件.

2.      对flash进行分区.

512K 8个扇区. 擦除的时候只能根据删除擦除.

/* Base address of the Flash sectors Bank 1 */

#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */

#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */

#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */

#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */

#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */

#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */

#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */

#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */

我们的要求.

l  我们自己的 bootloader.  <16K

l  信息区. <16K.

l  程序区. 自己的程序 < 64K.

l  OTA升级区. < 64K.

所以设定

#define NDADDR_BOOT                 ADDR_FLASH_SECTOR_0  //SECTOR_0 16K

#define NDADDR_INFO                  ADDR_FLASH_SECTOR_1  //SECTOR_1 16K

#define NDADDR_FW_APP               ADDR_FLASH_SECTOR_5  //SECTOR_5 128K

#define NDADDR_FW_OTA               ADDR_FLASH_SECTOR_6  //SECTOR_6 128K

#define FW_MAX_SIZE                           ((uint32_t)0x00020000)  //固件最大 128K

3.      Flash 操作代码

#ifndef _FIRMWARE_OTA_CONF_INC_H_

#define _FIRMWARE_OTA_CONF_INC_H_

#include

#include

/* Exported types ------------------------------------------------------------*/

typedef  void (*pFunction)(void);

/* Base address of the Flash sectors Bank 1 */

#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */

#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */

#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */

#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */

#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */

#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */

#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */

#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */

#if 0

#define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */

#define ADDR_FLASH_SECTOR_9     ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */

#define ADDR_FLASH_SECTOR_10    ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */

#define ADDR_FLASH_SECTOR_11    ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */

/* Base address of the Flash sectors Bank 2 */

#define ADDR_FLASH_SECTOR_12     ((uint32_t)0x08100000) /* Base @ of Sector 0, 16 Kbytes */

#define ADDR_FLASH_SECTOR_13     ((uint32_t)0x08104000) /* Base @ of Sector 1, 16 Kbytes */

#define ADDR_FLASH_SECTOR_14     ((uint32_t)0x08108000) /* Base @ of Sector 2, 16 Kbytes */

#define ADDR_FLASH_SECTOR_15     ((uint32_t)0x0810C000) /* Base @ of Sector 3, 16 Kbytes */

#define ADDR_FLASH_SECTOR_16     ((uint32_t)0x08110000) /* Base @ of Sector 4, 64 Kbytes */

#define ADDR_FLASH_SECTOR_17     ((uint32_t)0x08120000) /* Base @ of Sector 5, 128 Kbytes */

#define ADDR_FLASH_SECTOR_18     ((uint32_t)0x08140000) /* Base @ of Sector 6, 128 Kbytes */

#define ADDR_FLASH_SECTOR_19     ((uint32_t)0x08160000) /* Base @ of Sector 7, 128 Kbytes */

#define ADDR_FLASH_SECTOR_20     ((uint32_t)0x08180000) /* Base @ of Sector 8, 128 Kbytes  */

#define ADDR_FLASH_SECTOR_21     ((uint32_t)0x081A0000) /* Base @ of Sector 9, 128 Kbytes  */

#define ADDR_FLASH_SECTOR_22     ((uint32_t)0x081C0000) /* Base @ of Sector 10, 128 Kbytes */

#define ADDR_FLASH_SECTOR_23     ((uint32_t)0x081E0000) /* Base @ of Sector 11, 128 Kbytes */

#endif

#define NDADDR_BOOT                 ADDR_FLASH_SECTOR_0  //SECTOR_0 16K

#define NDADDR_INFO                 ADDR_FLASH_SECTOR_1  //SECTOR_1 16K

#define NDADDR_FW_APP               ADDR_FLASH_SECTOR_5  //SECTOR_5 128K

#define NDADDR_FW_OTA               ADDR_FLASH_SECTOR_6  //SECTOR_6 128K

#define FW_MAX_SIZE                           ((uint32_t)0x00020000)  //固件最大 128K

#define FW_PAGE_SIZE                ((uint32_t)0x00000800)  //写入的单位 2K.

/*

* 固件升级步骤.

* 确定当前的 FW的位置是那个, FW1/FW2, 确定完毕后就知道要写那个.

* YMODEM 获取满 2K 数据.  FMC_FLASH_PAGE_SIZE, 然后写入一个页中.

* 最后改写配置, 引导的 APROM 起始地址.

*/

void nd_FlashUnlock(void);

void nd_FlashLock(void);

bool ota_EraseSector(void);

bool app_EraseSector(void);

bool config_EraseSector(void);

bool nd_flash_write(uint32_t Address, uint8_t *pData, uint32_t size);

void nd_flash_read(uint32_t Address, uint8_t *pData, uint32_t size);

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

/* 出厂设置内容. 保证4字节对齐. */

typedef struct {

    uint32_t            fw_addr;    //最新有效的固件的flash地址. 

    uint32_t            page_cnt;  //最新有效的固件的页数   (2K计数)

    uint64_t                     sn;

}nd_ota_config_t;

extern nd_ota_config_t g_ota_conf ;

void load_factory_config(void);

void save_factory_config(void);

#endif //_FIRMWARE_OTA_CONF_INC_H_

Flash部分的封装 实现

#include "main.h"

#include "fw_ota.h"

void NVIC_SetVectorTable(uint32_t ApplicationFlashAddress)

{

  SCB->VTOR = ApplicationFlashAddress;

}

//Unlocks the Flash to enable the flash control register access.

void nd_FlashUnlock(void)

{

  HAL_FLASH_Unlock();

  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR);

}

void nd_FlashLock(void)

{

  HAL_FLASH_Lock();

}

/*对指定地址上写入4字节数据.

  Address + data 必须 4字节对齐.  写完之后下次写入的 Address data 都要+4.

  * @retval true: Data successfully written to Flash memory

  *         false: Error occurred while writing data in Flash memory

  */

static bool flash_Write_Word(uint32_t Address, uint32_t *Data)

{

  return (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, *Data));

}

static bool flash_Write_HalfWord(uint32_t Address, uint16_t *Data)

{

  return (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Data));

}

bool nd_flash_write(uint32_t Address, uint8_t *pData, uint32_t size)

{

  if ((size % 4) != 0) return false;

  uint32_t nbWrites = size / 4;

  uint32_t idx;

 

  for (idx = 0; idx < nbWrites; idx++) {

    if (false == flash_Write_Word(Address, (uint32_t *)pData)) 

      return false;

    pData+=4;

    Address+=4;

  }

  return true;

}

//读 不需要做 unlock.

void nd_flash_read(uint32_t Address, uint8_t *pData, uint32_t size)

{

  uint32_t idx;

  for (idx = 0; idx < size; idx++)  {

    *pData = *(__IO uint8_t *)Address;

    pData++;

    Address++;

  }

}

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

bool ota_EraseSector(void)

{

  nd_FlashUnlock();

 

  FLASH_EraseInitTypeDef FLASH_EraseInitStruct;

 

  FLASH_EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;

  FLASH_EraseInitStruct.Sector = FLASH_SECTOR_6;

  FLASH_EraseInitStruct.NbSectors = 1;

  FLASH_EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

  uint32_t SectorError = 0;

  return (HAL_OK == HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError));

}

bool app_EraseSector(void)

{

  nd_FlashUnlock();

  FLASH_EraseInitTypeDef FLASH_EraseInitStruct;

 

  FLASH_EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;

  FLASH_EraseInitStruct.Sector = FLASH_SECTOR_5;

  FLASH_EraseInitStruct.NbSectors = 1;

  FLASH_EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

  uint32_t SectorError = 0;

  return (HAL_OK == HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError));

}

bool config_EraseSector(void)

{ 

  nd_FlashUnlock();

  FLASH_EraseInitTypeDef FLASH_EraseInitStruct;

 

  FLASH_EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;

  FLASH_EraseInitStruct.Sector = FLASH_SECTOR_1;

  FLASH_EraseInitStruct.NbSectors = 1;

  FLASH_EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

  uint32_t SectorError = 0;

  return (HAL_OK == HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError));

}

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

nd_ota_config_t g_ota_conf = {0};

void load_factory_config(void)

{

  nd_flash_read(NDADDR_INFO, (uint8_t *)&g_ota_conf, sizeof(nd_ota_config_t));

}

void save_factory_config(void)

{

  nd_FlashUnlock();

  nd_flash_write(NDADDR_INFO, (uint8_t *)&g_ota_conf, sizeof(nd_ota_config_t));

}

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////

4.      引导代码.


static void exec_application(void)

{ 

  uint32_t JumpAddress;

  pFunction Jump_To_Application;

 

  if ((((*(__IO uint32_t *) NDADDR_FW_APP)  & 0x2FFE0000) == 0x20000000) /* 检查栈顶地址是否合法 */

        || (((*(__IO uint32_t *) NDADDR_FW_APP) & 0xFF000000) ==

            0x10000000))

  {

    /* Jump to user application */

    JumpAddress = *(__IO uint32_t *) (NDADDR_FW_APP + 4);

    Jump_To_Application = (pFunction) JumpAddress;

    /* Initialize user application's Stack Pointer */

    __set_MSP(*(__IO uint32_t *) NDADDR_FW_APP);

    Jump_To_Application();

  }

}

static void update_app_from_ota(void)

{

  app_EraseSector();

 

  nd_FlashUnlock();

  //g_ota_conf.page_cnt * 2K 的 数据从 OTA区 转移到 App.

  uint32_t idx_pages, idx_oft;

  uint32_t src_addr = NDADDR_FW_OTA;

  uint32_t dst_addr = NDADDR_FW_APP;

 

  for (idx_pages = 0; idx_pages < g_ota_conf.page_cnt; idx_pages++) {

    nd_flash_write(dst_addr, (uint8_t *)src_addr, FW_PAGE_SIZE);

    dst_addr += FW_PAGE_SIZE;

    src_addr += FW_PAGE_SIZE;

  }

}

int main(void)

{

  //首先读取 g_ota_conf, 确定是否需要升级.

  memset(&g_ota_conf, 0, sizeof(g_ota_conf));

  load_factory_config(); 

 

  if (NDADDR_FW_OTA == g_ota_conf.fw_addr) { //不需要升级.

    //OTA更新到APP.

    update_app_from_ota();

   

    //改写配置.

    if (config_EraseSector()) {

      g_ota_conf.fw_addr = NDADDR_FW_APP;

      g_ota_conf.page_cnt = 0; 

      //g_ota_conf.sn = 0x8010191120A90200;  

      save_factory_config();

    }   

  }

 

  exec_application(); //升级完毕后, 调用应用端. 

  while (1)

  {

  }

}

5.      App

main.c 中开始位置写入SCB->VTOR = NDADDR_FW_APP; 即可. 

最好的是写在 system_stm32f7xx.c SystemInit的第一行

同时设置 同样主要是起始地址 和大小

下面就是实现协议从主机下载固件并更新到 OTA区即可.

发现的问题, IAP到了App时候启动比较慢.

MotorDrvEvb.zip
阅读(652) | 评论(0) | 转发(0) |
0

上一篇:ROS2 开发起步

下一篇:ROS2 的参数

给主人留下些什么吧!~~