【OTA专题】4 .搭建初阶Bootloader所需的相关外设功能
目录
一、外设资源
1.配置一个Key,和一个GPIO,代码:
2.配置串口
3.配置一个对MCU内部Flash读写的文件:
根据自己的开发板进行调整
一、外设资源
1.配置一个Key,和一个GPIO,代码:
GPIO.c
/******************************************************************************* Copyright (C) 2024 EternalChip, Inc.(Gmbh) or its affiliates.* * All Rights Reserved.* * @file Gpio.c* * @par dependencies * - Gpio.h* * @author Jack | R&D Dept. | EternalChip 立芯嵌入式* * @brief Functions related to reading and writing in the chip's flash area.* * Processing flow:* * call directly.* * @version V1.0 2024-09-13** @note 1 tab == 4 spaces!* *****************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "Gpio.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* extern variables ---------------------------------------------------------*/void Key_IO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* Enable the GPIOA peripheral */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 作为输入模式,不需要考虑是推挽还是开漏GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA, &GPIO_InitStructure);
}uint8_t Key_Scan(void)
{if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == Bit_RESET){Delay(50);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == Bit_RESET){return 1;}}return 0;
}void Led_IO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* Enable the GPIOC peripheral */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);GPIO_InitStructure.GPIO_Pin = LED_C13_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(LED_C13_PORT, &GPIO_InitStructure);
}void Breathing_light(void)
{/* C13 呼吸灯测试 */static uint8_t pwmset;static uint16_t time;static uint8_t timeflag;static uint8_t timecount;/* 呼吸灯 */if(timeflag == 0){time ++;if(time >= 1600) timeflag = 1;}else{time --;if(time == 0) timeflag = 0;}/* 占空比设置 */pwmset = time/80;/* 20ms 脉宽 */if(timecount > 20) timecount = 0;else timecount ++;if(timecount >= pwmset ) GPIO_SetBits(LED_C13_PORT,LED_C13_PIN);else GPIO_ResetBits(LED_C13_PORT,LED_C13_PIN);Delay(1);
}
GPIO.h
/******************************************************************************* Copyright (C) 2024 EternalChip, Inc.(Gmbh) or its affiliates.* * All Rights Reserved.* * @file Flash.c* * @par dependencies * - Flash.h* * @author Jack | R&D Dept. | EternalChip 立芯嵌入式* * @brief Functions related to reading and writing in the chip's flash area.* * Processing flow:* * call directly.* * @version V1.0 2024-09-13** @note 1 tab == 4 spaces!* *****************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H
#define __GPIO_H#define LED_C13_PORT GPIOC
#define LED_C13_PIN GPIO_Pin_13
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "main.h"
//#include "Systim.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#define LED_OFF GPIO_SetBits(LED_C13_PORT,LED_C13_PIN);
#define LED_ON GPIO_ResetBits(LED_C13_PORT,LED_C13_PIN);
/* Exported functions ------------------------------------------------------- */extern void Key_IO_Init(void);
extern uint8_t Key_Scan(void);
extern void Led_IO_Init(void);
extern void Breathing_light(void);
#endif /* __GPIO_H */
2.配置串口
115200 波特率
8 bit
1个停止位
无校验
初阶使用阻塞的方式进行接收
代码:
Uart.c
/******************************************************************************* Copyright (C) 2024 EternalChip, Inc.(Gmbh) or its affiliates.* * All Rights Reserved.* * @file USART.c* * @par dependencies * - USART.h* * @author Jack | R&D Dept. | EternalChip 立芯嵌入式* * @brief Functions related to reading and writing in the chip's flash area.* * Processing flow:* * call directly.* * @version V1.0 2024-09-13** @note 1 tab == 4 spaces!* *****************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "USART.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* extern variables ---------------------------------------------------------*//*** @brief RCC配置初始化 USART1 USART2* @param Null* @retval None*/
static void RCC_Configuration(void) {// 启用GPIOA时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);// 启用USART1时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
}
/*** @brief 串口GPIO配置初始化 USART1 USART2* GPIO使用Pin_Speed_50MHz,Pull_Up_Pull_Down_None* @param Null* @retval None*/
static void GPIO_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 配置PA9为USART1_TXGPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置PA10为USART1_RXGPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOA, &GPIO_InitStructure);// 连接PA9和PA10到USART1的复用功能GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
}/*** @brief 串口外设相关配置 USART1 USART2* BaudRate = 115200, 8N1 模式* @param Null* @retval None*/
static void USART_Configuration(void)
{USART_InitTypeDef USART_InitStructure;// 配置USART1// USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);// // 配置USART2// USART_InitStructure.USART_BaudRate = 115200;// USART_Init(USART2, &USART_InitStructure);// USART_Cmd(USART2, ENABLE);
}/*** @brief 串口发送字节函数,使用USART2或USART1,使用阻塞方式* @param USARTx USART2, USART1* @param data 数据字节* @retval None*/
void USART_SendChar(USART_TypeDef* USARTx, uint8_t data) {// 等待发送数据寄存器空while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);// 发送一个字节数据到USARTUSART_SendData(USARTx, data);
}
/*** @brief 串口接收字节函数,使用USART2或USART1,使用阻塞方式* @param USARTx USART2, USART1* @retval 返回数据*/
uint8_t USART_ReceiveChar(USART_TypeDef* USARTx) {// 等待接收数据寄存器满while (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);// 读取接收到的数据return USART_ReceiveData(USARTx);
}void USART1_Init(void)
{RCC_Configuration();GPIO_Configuration();USART_Configuration();
}
Uart.h
/******************************************************************************* Copyright (C) 2024 EternalChip, Inc.(Gmbh) or its affiliates.* * All Rights Reserved.* * @file Flash.c* * @par dependencies * - Flash.h* * @author Jack | R&D Dept. | EternalChip 立芯嵌入式* * @brief Functions related to reading and writing in the chip's flash area.* * Processing flow:* * call directly.* * @version V1.0 2024-09-13** @note 1 tab == 4 spaces!* *****************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H
#define __USART_H/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
extern void USART1_Init(void);
extern void USART_SendChar(USART_TypeDef* USARTx, uint8_t data);
extern uint8_t USART_ReceiveChar(USART_TypeDef* USARTx);
#endif
3.配置一个对MCU内部Flash读写的文件:
代码:
Flash.c
/******************************************************************************* Copyright (C) 2024 EternalChip, Inc.(Gmbh) or its affiliates.* * All Rights Reserved.* * @file Flash.c* * @par dependencies * - Flash.h* * @author Jack | R&D Dept. | EternalChip 立芯嵌入式* * @brief Functions related to reading and writing in the chip's flash area.* * Processing flow:* * call directly.* * @version V1.0 2024-09-13** @note 1 tab == 4 spaces!* *****************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "Flash.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static uint16_t STMFLASH_GetFlashSector(u32 addr);
/* Private functions ---------------------------------------------------------*/
/* extern variables ---------------------------------------------------------*/const uint32_t Flash_Sectorsize[12] = \
{ FLASH_Sector_0, //Sector1FLASH_Sector_1, //Sector2FLASH_Sector_2, //Sector3FLASH_Sector_3, //Sector4FLASH_Sector_4, //Sector5FLASH_Sector_5, //Sector6FLASH_Sector_6, //Sector7FLASH_Sector_7, //Sector8FLASH_Sector_8, //Sector9FLASH_Sector_9, //Sector10FLASH_Sector_10, //Sector11FLASH_Sector_11 //Sector12
};/*** @brief This function is used to erase the flash area.* @param None* @retval 0 : Success* 1 : Fail*/
uint8_t Flash_erase(u32 addr,u32 size)
{//将App代码的所有涉及到的扇区全部擦除/*判断size在几个扇区内*/
// FLASH_Status ret = 1;uint32_t flash_start_sector = 0;uint32_t flash_end_sector = 0;flash_start_sector = STMFLASH_GetFlashSector(addr);flash_end_sector = STMFLASH_GetFlashSector(addr + size);for(uint8_t i = 0; i <= 12; i++){if((Flash_Sectorsize[i]) >= flash_start_sector && (Flash_Sectorsize[i]) <= flash_end_sector){if(EreaseAppSector(Flash_Sectorsize[i]) != FLASH_COMPLETE) return 1;}}return 0;
}//通过地址获取扇区位置
static uint16_t STMFLASH_GetFlashSector(u32 addr)
{if(addr<ADDR_FLASH_SECTOR_1)return FLASH_Sector_0;else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_Sector_1;else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_Sector_2;else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_Sector_3;else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_Sector_4;else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_Sector_5;else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_Sector_6;else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_Sector_7;else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_Sector_8;else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10; return FLASH_Sector_11;
}void Flash_Unlock(void) {FLASH_Unlock();while (FLASH_GetStatus() == FLASH_BUSY);
}void Flash_Lock(void) {FLASH_Lock();
}//擦除APP区域的数据
// f4是按扇区操作,计划将app放在扇区6 FLASH_Sector_6,备份app放在扇区7
FLASH_Status EreaseAppSector(uint32_t FLASH_Sector)
{Flash_Unlock();FLASH_Status FLASHStatus = FLASH_EraseSector(FLASH_Sector, VoltageRange_3);Flash_Lock();return FLASHStatus;
}void Flash_Write(uint32_t address, uint32_t data) {// 解锁FlashFlash_Unlock();// 清除所有标志位// FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);// 编程一个字(32位)FLASH_Status status = FLASH_ProgramWord(address, data);// 检查编程是否成功if (status == FLASH_COMPLETE) {// 数据写入成功// log_d("Flash_Write success"); } else {// 数据写入失败// 在这里添加错误处理代码//log_e("Flash_Write fail"); }// 锁定FlashFlash_Lock();
}
Flash.h
/******************************************************************************* Copyright (C) 2024 EternalChip, Inc.(Gmbh) or its affiliates.* * All Rights Reserved.* * @file Flash.h* * @par dependencies * - Flash.h* * @author Jack | R&D Dept. | EternalChip 立芯嵌入式* * @brief Functions related to reading and writing in the chip's flash area.* * Processing flow:* * call directly.* * @version V1.0 2024-09-13** @note 1 tab == 4 spaces!* *****************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FLASH_H
#define __FLASH_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "main.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
//FLASH 扇区的起始地址
#define ADDR_FLASH_SECTOR_0 ((u32)0x08000000) //扇区0起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_1 ((u32)0x08004000) //扇区1起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_2 ((u32)0x08008000) //扇区2起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_3 ((u32)0x0800C000) //扇区3起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_4 ((u32)0x08010000) //扇区4起始地址, 64 Kbytes
#define ADDR_FLASH_SECTOR_5 ((u32)0x08020000) //扇区5起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_6 ((u32)0x08040000) //扇区6起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_7 ((u32)0x08060000) //扇区7起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_8 ((u32)0x08080000) //扇区8起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_9 ((u32)0x080A0000) //扇区9起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_10 ((u32)0x080C0000) //扇区10起始地址,128 Kbytes
#define ADDR_FLASH_SECTOR_11 ((u32)0x080E0000) //扇区11起始地址,128 Kbytes
/* Exported functions ------------------------------------------------------- */
uint8_t Flash_erase(u32 addr,u32 size);
FLASH_Status EreaseAppSector(uint32_t FLASH_Sector);
void Flash_Write(uint32_t address, uint32_t data);
#endif /* __FLASH_H */
使用示例:
对扇形区域3进行查擦除字再写入
EreaseAppSector(FLASH_Sector_3);
Flash_Write(0x800C000,0x55);