stm32f103 canbus Bootloader 升级程序代码
时间: 2023-08-03 16:08:50 浏览: 60
以下是一个简单的基于CAN总线的STM32F103固件升级程序的代码示例,你可以根据实际情况进行修改:
```
#include "stm32f10x.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_can.h"
#define FLASH_PAGE_SIZE ((uint16_t)0x400)
#define APP_ADDR ((uint32_t)0x08004000)
#define APP_SIZE ((uint32_t)0x0001C000)
#define BOOTLOADER_ADDR ((uint32_t)0x08000000)
#define BOOTLOADER_SIZE ((uint32_t)0x00004000)
#define CRC32_POLY ((uint32_t)0xEDB88320)
uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len)
{
crc = ~crc;
while (len--) {
crc ^= *buf++;
for (int i = 0; i < 8; i++)
crc = crc & 1 ? (crc >> 1) ^ CRC32_POLY : crc >> 1;
}
return ~crc;
}
void flash_erase(uint32_t addr)
{
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(addr);
FLASH_Lock();
}
void flash_write(uint32_t addr, const uint8_t *buf, uint32_t len)
{
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
for (uint32_t i = 0; i < len; i += 4) {
uint32_t data = buf[i] | (buf[i+1] << 8) | (buf[i+2] << 16) | (buf[i+3] << 24);
FLASH_ProgramWord(addr + i, data);
}
FLASH_Lock();
}
void bootloader_upgrade(uint8_t *buf, uint32_t len)
{
if (len < 8)
return;
uint32_t crc = crc32(0, buf, len - 4);
if (crc != ((uint32_t)buf[len-4] | ((uint32_t)buf[len-3] << 8) | ((uint32_t)buf[len-2] << 16) | ((uint32_t)buf[len-1] << 24)))
return;
uint32_t addr = APP_ADDR;
if (buf[0] == 0x12 && buf[1] == 0x34) { // check magic number
uint32_t size = ((uint32_t)buf[2] << 24) | ((uint32_t)buf[3] << 16) | ((uint32_t)buf[4] << 8) | buf[5];
if (size <= APP_SIZE) {
flash_erase(addr);
flash_write(addr, buf + 8, size);
crc = crc32(0, (uint8_t *)addr, size);
flash_write(addr + size, (uint8_t *)&crc, 4);
}
} else if (buf[0] == 0x56 && buf[1] == 0x78) { // check magic number
flash_erase(BOOTLOADER_ADDR);
flash_write(BOOTLOADER_ADDR, buf + 8, BOOTLOADER_SIZE);
}
}
int main()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
CAN_InitTypeDef CAN_InitStructure;
CAN_StructInit(&CAN_InitStructure);
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;
CAN_InitStructure.CAN_Prescaler = 4;
CAN_Init(CAN1, &CAN_InitStructure);
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
uint8_t buf[256];
uint32_t len = 0;
while (1) {
if (CAN_MessagePending(CAN1, CAN_FIFO0) > 0) {
CanRxMsg msg;
CAN_Receive(CAN1, CAN_FIFO0, &msg);
if (msg.IDE == CAN_Id_Standard && msg.RTR == CAN_RTR_Data && msg.DLC <= 8) {
for (int i = 0; i < msg.DLC; i++)
buf[len++] = msg.Data[i];
if (msg.DLC < 8) {
bootloader_upgrade(buf, len);
len = 0;
}
}
}
}
}
```
这段代码实现了一个基本的CAN总线固件升级程序,它监听CAN总线上的数据,当收到完整的固件升级包时,将新的固件写入FLASH中。需要注意的是,这段代码并没有进行完整性和安全性的检查,如果你需要更加安全可靠的固件升级方案,需要进行更多的优化和改进。