要使用Ymodem协议进行STM32G74的boot升级程序,你需要一个支持Ymodem协议的串口通信程序,比如Tera Term或者Minicom。然后,你需要在STM32G74的bootloader中实现Ymodem协议的解析和处理逻辑,以便能够通过串口接收Ymodem协议传输的固件数据。最后,你可以通过Ymodem协议将固件数据发送到STM32G74的bootloader中,完成固件升级。记得在bootloader中实现错误处理和校验机制,以确保固件传输的可靠性和完整性。
一旦你实现了Ymodem协议的解析和处理逻辑,你可以在STM32G74的bootloader中添加相应的功能,使其能够接收通过Ymodem协议传输的固件数据,并将其写入设备的存储器中。在传输过程中,你可能还需要考虑数据包的重传机制以及校验和错误处理,以确保数据的完整性和可靠性。同时,确保bootloader的大小足够容纳Ymodem协议所需的额外代码和数据存储空间。完成这些步骤后,你就可以使用支持Ymodem协议的串口通信程序将固件文件发送到STM32G74的bootloader中,完成固件的升级过程。
这里使用的是超级终端,代码如下
首先是boot
#include "Bootloader.h"
#include "stdint.h"
#include "usart.h"
#include "string.h"
#include "fm.h"
#include "myiic.h"
#define POLYNOMIAL 0xEDB88320
uint32_t crc32(uint8_t data, uint32_t crc)
{
crc ^= data;
for (uint32_t j = 0; j < 8; j++)
{
if (crc & 1)
{
crc = (crc >> 1) ^ POLYNOMIAL;
}
else
{
crc >>= 1;
}
}
return crc;
}
extern uint8_t EEPROM_erase;//EEPRM擦除
__asm void MSR_MSP(uint32_t addr)
{
MSR MSP, r0
BX r14;
}
void iap_load_app(void)
{
APP_FUNC jump2app;//定义一个函数指针
/* 栈顶地址是否合法(这里sram大小为8k) */
if (((*(uint32_t *)APP_ADDR)&0xFFFF8000) == 0x20000000)
{
/* 设置栈指针 */
MSR_MSP(APP_ADDR);
/* 获取复位地址 */
jump2app=(APP_FUNC)*(volatile uint32_t *)(APP_ADDR+4);
/* 设置栈指针 */
__set_MSP(*(volatile uint32_t *)APP_ADDR);
#ifdef BOOTLOADER_LOG
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, (uint8_t*)"Bootloader end load app\r\n", (uint16_t)strlen("Bootloader end load app\r\n"), 0xf);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
#endif
//HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);//低为rs485,高为rs232
/* 关闭全局中断 */
__disable_irq(); // 关闭所有中断
/* 设置所有时钟到默认状态,使用HSI时钟 */
HAL_RCC_DeInit();
/* 关闭滴答定时器,复位到默认值 */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* 关闭所有中断,清除所有中断挂起标志 */
for (int i = 0; i < 8; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* 跳转至APP */
jump2app();
}
#ifdef BOOTLOADER_LOG
else
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, (uint8_t*)"APP is error!resetting!!\n", (uint16_t)strlen("APP is error!resetting!!\n"), 0xf);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
// while (!EEPROM_Write(&EEPROM_erase, 0X0051, 4)) {}
// while (!EEPROM_Write(&EEPROM_erase, 0x1111, 4)) {}
// while (!EEPROM_Write(0, 0xfff0, 4)) {}
HAL_NVIC_SystemReset();
}
#endif
}
#ifndef _BOOTLOADER_H_
#define _BOOTLOADER_H_
#include "main.h"
#define APP_ADDR 0x8006000 //应用程序首地址定义
/*选择性开启相应的LOG信息*/
#define BOOTLOADER_LOG
#define CLOSE_ALL_INT() __set_PRIMASK(1) //关闭所有中断
typedef void (*APP_FUNC)(); //函数指针类型定义
void iap_load_app(void); //跳转函数
uint32_t crc32(uint8_t data, uint32_t crc);
#endif
下面是主程序
int main(void)
{
/* USER CODE BEGIN 1 */
SCB->VTOR = FLASH_BASE|0x8000000;
__enable_irq();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
TM1629D_Init();
iic_init();
delay(5);
EEPROM_Read(READ_BAUD, 0X0380, 4);
EEPROM_Read((uint8_t*)&BOOT_flag_VPG, 0xfff0, 4);
EEPROM_Read(READ_Port, 0X1111, 4);
pdata64_y[0]=*(__IO uint32_t *)(0x8005900);
EEPROM_Read(WRITE_KW, 0X1114, 1);
visn_flag=WRITE_KW[0];
Displayclean();
int flag=WRITE_KW[0];
char temp[2]= {0};
strcpy(temp, " ");
sprintf(temp, "%d", WRITE_KW[0]);
if (visn_flag==255||TM1629D_Read_key()==3)
{
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
while (1)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
if (TM1629D_Read_key()==5)
{
if (WRITE_KW[0]==1)
{
WRITE_KW[0]=2;
Displayclean();
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
strcpy(temp, " ");
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
else if (WRITE_KW[0]==2)
{
WRITE_KW[0]=3;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
else if (WRITE_KW[0]==3)
{
WRITE_KW[0]=5;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
else if (WRITE_KW[0]==5)
{
WRITE_KW[0]=1;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
}
if (TM1629D_Read_key()==6)
{
if (WRITE_KW[0]==5)
{
WRITE_KW[0]=3;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
else if (WRITE_KW[0]==3)
{
WRITE_KW[0]=2;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
else if (WRITE_KW[0]==2)
{
WRITE_KW[0]=1;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
else if (WRITE_KW[0]==1)
{
WRITE_KW[0]=5;
Displayclean();
strcpy(temp, " ");
Display_Str(5, viosion, 0);
Display_Str(0, Viosion, 0);
sprintf(temp, "%d", WRITE_KW[0]);
while (TM1629D_Read_key()!=0);
}
}
if (TM1629D_Read_key()==1)
{
EEPROM_Write(WRITE_KW, 0X1114, 1);
Displayclean();
break;
}
Display_Str(5, "visn", 1);
Display_Str(0, temp, 1);
}
}
EEPROM_Read(WRITE_KW, 0X1114, 1);
if (WRITE_KW[0]==255)
{
Displayclean();
Display_Str(8, "no", 1);
Display_Str(0, "visn", 1);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
delay(2000);
HAL_NVIC_SystemReset();
}
if (pdata64_y[0]==0)
{
EEPROM_Write(&EEPROM_erase[0], 0xfff0, 4);
pdata64_y[0]=1;
Flash_write(0x8005900, &pdata64_y[0], 64);
}
EEPROM_Read((uint8_t*)&BOOT_flag_VPG, 0xfff0, 4);
EEPROM_Read(READ_PORT, 0X1111, 4);
if (READ_PORT[0]==0)
{
Display_Str(0, "rs232", 0);
Display_Str(5, "mains", 0);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);//rs232
F_read_date.PORT=0;
}
else
{
Display_Str(0, "rs485", 0);
Display_Str(5, "mains", 0);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);//rs485
F_read_date.PORT=1;
}
EEPROM_Read(READ_BAUD, 0X0380, 4);
BAUD_FLAG=READ_BAUD[0];
if (BAUD_FLAG==0)
BAUD_FLAG=1;
switch (BAUD_FLAG)
{
case 1:
Display_Str(5, "9.6k", 1);
F_read_date.BAUD=9600;
MX_USART1_UART_Init();
break;
case 2:
F_read_date.BAUD=57600;
Display_Str(5, "56.7k", 1);
MX_USART1_UART_Init();
break;
case 3:
F_read_date.BAUD=115200;
Display_Str(5, "115.2k", 1);
MX_USART1_UART_Init();
break;
case 4:
F_read_date.BAUD=4800;
Display_Str(5, "4.8k", 1);
MX_USART1_UART_Init();
break;
default:
F_read_date.BAUD=9600;
Display_Str(5, "9.6k", 1);
MX_USART1_UART_Init();
break;
}
printf("READ_PORT:%d\r\n", READ_PORT[0]);
printf("BAUD_FLAG:%d\r\n", BAUD_FLAG);
printf("READ_BAUD[0]:%d\r\n", READ_BAUD[0]);
printf("pdata64_y[0]:%d\r\n", (int)pdata64_y[0]);
printf("BOOT_flag_VPG:%d\r\n", (int)BOOT_flag_VPG);
flash_write_read_date(&F_read_date, 0);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7|GPIO_PIN_9, GPIO_PIN_SET);
Display_Str(0, "boot", 1);
printf("this is boot\r\n");
printf("wait run app...");
/* 开启 USART 1 中断 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
HAL_UART_Receive_IT(&huart1, &boot_rx_buf, sizeof(boot_rx_buf));
//等待5s
for (int i=0; i<10; i++)
{
if (TM1629D_Read_key()==4)
{
BOOT_flag_VPG=0;
}
if (BOOT_flag_VPG==0)
{
EEPROM_Write(&EEPROM_erase[0], 0xfff0, 4);
__HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE);
break;
}
else
{
if (i==500||i==1000||i==1500||i==2000||i==2500)
printf(".");
delay(1);
}
}
if (BOOT_flag_VPG==0)
{
Displayclean();
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
Display_Str(5, "UPG", 0);
__HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE);
// iap_load_app();
/*
stm32g474 flsah为128K,分为bank2 bank1
bank2 有32页 0-31 每页大小为2kb
bank1 有32页 31-63 每页大小为2kb
*/
ymodem_revce_size=Ymodem_Receive(boot_tab_1024);
uint32_t crc_value = 0xFFFFFFFF;
rs458tx;
printf(" s:%d\r\n", ymodem_revce_size);
//crc校验 s为app大小
for (int i=0; i<ymodem_revce_size-4; i++)
{
crc_value =crc32(*(__IO uint8_t *)(0x8006000+i), crc_value);
}
crc_value = ~crc_value;
uint32_t flcrc_value=*(__IO uint32_t *)(0x8006000+ymodem_revce_size-4);
printf("crc_value:0x%08X\r\n", crc_value);
printf("flcrc_value: 0x%08X\r\n", flcrc_value);
if (crc_value==flcrc_value)
{
// while (!EEPROM_Write(&EEPROM_erase, 0X0051, 4)) {}
// while (!EEPROM_Write(&EEPROM_erase, 0x1111, 4)) {}
while (!EEPROM_Write(&EEPROM_erase[0], 0xfff0, 4)) {}
// while(!EEPROM_Write(&EEPROM_erase, 0x0300, 4)){}
// while(!EEPROM_Write(&EEPROM_erase, 0x0320, 4)){}
// for (int i=0; i<0x31; i++)
// {
// while (!EEPROM_Write(&EEPROM_erase[0], i, 4));
// }
printf("升级成功!!!");
}
else
{
printf("升级失败!!!");
while (Flash_erase_page(12, 64, 1)) {};
while (Flash_erase_page(0, 64, 2)) {};
}
BOOT_flag_VPG=1;
while (!EEPROM_Write(&EEPROM_erase[0], 0xfff0, 4)) {}
}
Displayclean();
__HAL_UART_DISABLE_IT(&huart1, UART_IT_RXNE);
if (*(__IO uint32_t *)(0x8005960)==88||*(__IO uint32_t *)(0x8005960)==-1)
{
iap_load_app();
}
iap_load_app();
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7|GPIO_PIN_9, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
Displayclean();
Display_Str(5, "app", 0);
Display_Str(0, "err", 0);
delay(1000);
HAL_NVIC_SystemReset();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
下面是ymodem协议
/**
******************************************************************************
* @file STM32F0xx_IAP/src/ymodem.c
* @author MCD Application Team
* @version V1.0.0
* @date 29-May-2012
* @brief Main program body
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WarrANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "ymodem.h"
#include "usart.h"
#include "gpio.h"
#include "lcd.h"
#include "stmflash.h"
#include "Bootloader.h"
#include <stdlib.h>
//#include "common.h"
//#include "rs485.h"
//#include "flash_if.h"
/** @addtogroup STM32F0xx_IAP
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
// #define PAGE_SIZE (0x800) /* 2 Kbytes */
// #define FLASH_SIZE (0x40000) /* 512 KBytes */
uint8_t file_name[FILE_NAME_LENGTH];
uint16_t PageSize = 0x800;
uint32_t EraseCounter = 0x0;
uint32_t NbrOfPage = 0;
FLASH_Status FLASHStatus = my_FLASH_COMPLETE;
uint8_t test[1000];
uint16_t k =0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Receive byte from sender
* @param c: Character
* @param timeout: Timeout
* @retval 0: Byte received
* -1: Timeout
*/
static int32_t Receive_Byte (uint8_t *c, uint32_t timeout)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
while (timeout-- > 0)
{
if ( __HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
{
//HAL_UART_Receive(&huart1, (c), 8, 10);
*c = (uint8_t)USART1->RDR; return 0;
}
}
// printf("1");
return -1;
}
/**
* @brief Send a byte
* @param c: Character
* @retval 0: Byte sent
*/
static uint32_t Send_Byte (uint8_t c)
{
//int temp=(c&(uint16_t)0x01FF);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
// USART1->TDR =(c&(uint16_t)0x01FF);
HAL_UART_Transmit(&huart1, (uint8_t *)&(c), sizeof(c), 0xffff);
//printf("%u",(c&(uint16_t)0x01FF));
while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) == RESET)
{}
return 0;
}
/**
* @brief Update CRC16 for input byte
* @param CRC input value
* @param input byte
* @retval Updated CRC value
*/
uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte)
{
uint32_t crc = crcIn;
uint32_t in = byte|0x100;
do
{
crc <<= 1;
in <<= 1;
if(in&0x100)
{
++crc;
}
if(crc&0x10000)
{
crc ^= 0x1021;
}
} while(!(in&0x10000));
return (crc&0xffffu);
}
/**
* @brief Cal CRC16 for YModem Packet
* @param data
* @param length
* @retval CRC value
*/
uint16_t Cal_CRC16(const uint8_t* data, uint32_t size)
{
uint32_t crc = 0;
const uint8_t* dataEnd = data+size;
while(data<dataEnd)
{
crc = UpdateCRC16(crc,*data++);
}
crc = UpdateCRC16(crc,0);
crc = UpdateCRC16(crc,0);
return (crc&0xffffu);
}
/**
* @brief Cal Check sum for YModem Packet
* @param data
* @param length
* @retval None
*/
uint8_t CalChecksum(const uint8_t* data, uint32_t size)
{
uint32_t sum = 0;
const uint8_t* dataEnd = data+size;
while(data < dataEnd)
{
sum += *data++;
}
return (sum&0xffu);
}
/**
* @brief Receive a packet from sender
* @param data
* @param length
* @param timeout
* 0: end of transmission
* -1: abort by sender
* >0: packet length
* @retval 0: normally return
* -1: timeout or packet error
* 1: abort by user
*/
static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout)
{
uint16_t i, packet_size, computedcrc;
uint8_t c;
*length = 0;
if (Receive_Byte(&c, timeout) != 0)
{
return -1;
}
switch (c)
{
case SOH:
packet_size = PACKET_SIZE;
break;
case STX:
packet_size = PACKET_1K_SIZE;
break;
case EOT: //数据传输完毕,发送方发送EOT
return 0;
case CA:
if ((Receive_Byte(&c, timeout) == 0) && (c == CA))
{
*length = -1;
return 0;
}
else
{
return -1;
}
case ABORT2:
return 1;
default:
return -1;
}
*data = c;
for (i = 1; i < (packet_size + PACKET_OVERHEAD); i ++) //接收app.bin 每一帧
{
if (Receive_Byte(data + i, timeout) != 0)
{
return -1;
}
}
if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
{
return -1;
}
/* Compute the CRC */
computedcrc = Cal_CRC16(&data[PACKET_HEADER], (uint32_t)packet_size);
/* Check that received CRC match the already computed CRC value
data[packet_size+3]<<8) | data[packet_size+4] contains the received CRC
computedcrc contains the computed CRC value */
if (computedcrc != (uint16_t)((data[packet_size+3]<<8) | data[packet_size+4]))
{
/* CRC error */
return -1;
}
*length = packet_size;
return 0;
}
/**
* @brief Receive a file using the ymodem protocol
* @param buf: Address of the first byte
* @retval The size of the file
*/
uint8_t *file_ptr, *buf_ptr;
int32_t Ymodem_Receive (uint8_t *buf)
{
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH];
int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
uint32_t ramsource,flash_i=0;
int flash_flag=0;
/* Initialize flashdestination variable */
//flashdestination = ApplicationAddress;
// flashdestination =0x8003000;
for (session_done = 0, errors = 0, session_begin = 0; ;)
{
for (packets_received = 0, file_done = 0, buf_ptr = buf; ;)
{
switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) //每接收完一帧数据,进行对应解析
{
case 0:
errors = 0;
switch (packet_length)
{
/* Abort by sender */
case - 1:
Send_Byte(ACK);
return 0;
/* End of transmission */
case 0:
Send_Byte(ACK);
file_done = 1; // 跳出第二层for循环, packets_received = 0
break;
/* Normal packet */
default:
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK);
}
else
{
if (packets_received == 0)
{
/* Filename packet */
if (packet_data[PACKET_HEADER] != 0)
{
/* Filename packet has valid data */
for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);)
{
file_name[i++] = *file_ptr++;
}
file_name[i++] = '\0';
for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < (FILE_SIZE_LENGTH - 1));)
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
//Str2Int(file_size, &size);
/* Test the size of the image to be sent */
/* Image size is greater than Flash size */
//if (size > (FLASH_SIZE + 1)) //using FLASH_IMAGE_SIZE is more accurate
if (size > ( 0x40000 + 1))
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
return -1;
}
// //计算需要擦除Flash的页
// NbrOfPage = FLASH_PagesMask(size);
// //擦除Flash /* erase user application area */
// for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
// {
// FLASHStatus = FLASH_ErasePage(flashdestination + (PageSize * EraseCounter));
// }
Send_Byte(ACK); //接收方在收到第一帧数据包后,发送ACK正确应答
Send_Byte(CRC16); //然后再发送一个字符'C'
}
/* Filename packet is empty, end session */
else
{
Send_Byte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
/* Data packet */
else
{
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
ramsource =(uint32_t)buf;
/* Write received data in Flash */
for (j = 0; (j < packet_length) ; j += 8)
{
if(flash_flag==0)
{
while (Flash_erase_page(12, 64, 1)) {};
while (Flash_erase_page(0, 64, 2)) {};
flash_flag=1;
}
//把接收到的数据编写到Flash中
while(Flash_write(0x8006000+flash_i*8, (u64*)(ramsource),8));
//验证刚被写入数据的地址,所存储的数值 是否等于写入值
if (*(uint32_t*)(0x8006000+flash_i*8) != *(uint32_t*)ramsource)
{
//结束
Send_Byte(CA);
Send_Byte(CA);
printf("flash_i %d\n",flash_i);
return -2;
}
flash_i+=1;
ramsource += 8;
}
Send_Byte(ACK); //从第二帧数据开始,接收方每次收到数据后,发送一个ACK作为响应,直至所有数据传输完毕
}
packets_received ++;
session_begin = 1;
}
}
break;
case 1:
Send_Byte(CA);
Send_Byte(CA);
return -3;
default:
if (session_begin > 0)
{
errors ++;
}
if (errors > MAX_ERRORS)
{
Send_Byte(CA);
Send_Byte(CA);
return 0;
}
Display_VPG();
Send_Byte(CRC16); //发送'C',请求数据
//
break;
}
if (file_done != 0)
{
break;
}
}
if (session_done != 0)
{
break;
}
}
printf("flash_i %d\n",flash_i);
printf("file_size %s\n",file_size);
return atoi((char*)file_size);
}
/**
* @brief check response using the ymodem protocol
* @param buf: Address of the first byte
* @retval The size of the file
*/
int32_t Ymodem_CheckResponse(uint8_t c)
{
return 0;
}
/**
* @brief Prepare the first block
* @param timeout
* @retval None
*/
void Ymodem_PrepareIntialPacket(uint8_t *data, const uint8_t* fileName, uint32_t *length)
{
uint16_t i, j;
uint8_t file_ptr[10];
/* Make first three packet */
data[0] = SOH;
data[1] = 0x00;
data[2] = 0xff;
/* Filename packet has valid data */
for (i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH);i++)
{
data[i + PACKET_HEADER] = fileName[i];
}
data[i + PACKET_HEADER] = 0x00;
sprintf((char*)&file_ptr[0],"%d",(int)length);
for (j =0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0' ; )
{
data[i++] = file_ptr[j++];
}
for (j = i; j < PACKET_SIZE + PACKET_HEADER; j++)
{
data[j] = 0;
}
}
/**
* @brief Prepare the data packet
* @param timeout
* @retval None
*/
void Ymodem_PreparePacket(uint8_t *SourceBuf, uint8_t *data, uint8_t pktNo, uint32_t sizeBlk)
{
uint16_t i, size, packetSize;
uint8_t* file_ptr;
/* Make first three packet */
packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
size = sizeBlk < packetSize ? sizeBlk :packetSize;
if (packetSize == PACKET_1K_SIZE)
{
data[0] = STX;
}
else
{
data[0] = SOH;
}
data[1] = pktNo;
data[2] = (~pktNo);
file_ptr = SourceBuf;
/* Filename packet has valid data */
for (i = PACKET_HEADER; i < size + PACKET_HEADER;i++)
{
data[i] = *file_ptr++;
}
if ( size <= packetSize)
{
for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++)
{
data[i] = 0x1A; /* EOF (0x1A) or 0x00 */
}
}
}
/**
* @brief Transmit a data packet using the ymodem protocol
* @param data
* @param length
* @retval None
*/
void Ymodem_SendPacket(uint8_t *data, uint16_t length)
{
uint16_t i;
i = 0;
while (i < length)
{
Send_Byte(data[i]);
i++;
}
}
/**
* @brief Transmit a file using the ymodem protocol
* @param buf: Address of the first byte
* @retval The size of the file
*/
uint8_t Ymodem_Transmit (uint8_t *buf, const uint8_t* sendFileName, uint32_t sizeFile)
{
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
uint8_t FileName[FILE_NAME_LENGTH];
uint8_t *buf_ptr, tempCheckSum ;
uint16_t tempCRC, blkNumber;
uint8_t receivedC[2], CRC16_F = 0, i;
uint32_t errors = 0, ackReceived = 0, size = 0, pktSize;
for (i = 0; i < (FILE_NAME_LENGTH - 1); i++)
{
FileName[i] = sendFileName[i];
}
CRC16_F = 1;
/* Prepare first block */
Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile);
do
{
/* Send Packet */
Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
/* Send CRC or Check Sum based on CRC16_F */
if (CRC16_F)
{
tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
Send_Byte(tempCRC >> 8);
Send_Byte(tempCRC & 0xFF);
}
else
{
tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE);
Send_Byte(tempCheckSum);
}
/* Wait for Ack and 'C' */
if (Receive_Byte(&receivedC[0], 1000000) == 0)
{
if (receivedC[0] == ACK)
{
/* Packet transfered correctly */
ackReceived = 1;
}
}
else
{
errors++;
}
}while (!ackReceived && (errors < 0x0A));
if (errors >= 0x0A)
{
return errors;
}
buf_ptr = buf;
size = sizeFile;
blkNumber = 0x01;
/* Here 1024 bytes package is used to send the packets */
while (size)
{
/* Prepare next packet */
Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size);
ackReceived = 0;
receivedC[0]= 0;
errors = 0;
do
{
/* Send next packet */
if (size >= PACKET_1K_SIZE)
{
pktSize = PACKET_1K_SIZE;
}
else
{
pktSize = PACKET_SIZE;
}
Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER);
/* Send CRC or Check Sum based on CRC16_F */
if (CRC16_F)
{
tempCRC = Cal_CRC16(&packet_data[3], pktSize);
Send_Byte(tempCRC >> 8);
Send_Byte(tempCRC & 0xFF);
}
else
{
tempCheckSum = CalChecksum (&packet_data[3], pktSize);
Send_Byte(tempCheckSum);
}
/* Wait for Ack */
if (Receive_Byte(&receivedC[0], 1000000) == 0)
{ if (receivedC[0] == ACK)
{
ackReceived = 1;
if (size > pktSize)
{
buf_ptr += pktSize;
size -= pktSize;
// if (blkNumber == (FLASH_IMAGE_SIZE/1024))
// {
// return 0xFF; /* error */
// }
// else
{
blkNumber++;
}
}
else
{
buf_ptr += pktSize;
size = 0;
}
}
}
else
{
errors++;
}
}while(!ackReceived && (errors < 0x0A));
/* Resend packet if NAK for a count of 10 else end of commuincation */
if (errors >= 0x0A)
{
return errors;
}
}
ackReceived = 0;
receivedC[0] = 0x00;
receivedC[1] = 0x00;
errors = 0;
do
{
Send_Byte(EOT);
/* Send (EOT); */
/* Wait for Ack */
//receivedC[0] = USART_ReceiveData(EVAL_COM1);
//if (receivedC[0] == ACK)
if ((Receive_Byte(&receivedC[0], 10000) == 0) && receivedC[0] == ACK)
{
ackReceived = 1;
}
else
{
errors++;
}
/* Clear Overrun flag of the USART2 */
//USART_ClearFlag(EVAL_COM1, USART_FLAG_ORE);
}while (!ackReceived && (errors < 0x0A));
if (errors >= 0x0A)
{
return errors;
}
/* Last packet preparation */
ackReceived = 0;
receivedC[0] = 0x00;
receivedC[1] = 0x00;
errors = 0;
packet_data[0] = SOH;
packet_data[1] = 0;
packet_data [2] = 0xFF;
for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++)
{
packet_data [i] = 0x00;
}
do
{
/* Send Packet */
Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
/* Send CRC or Check Sum based on CRC16_F */
tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
Send_Byte(tempCRC >> 8);
Send_Byte(tempCRC & 0xFF);
/* Wait for Ack and 'C' */
if (Receive_Byte(&receivedC[1], 1000000) == 0)
{
if (receivedC[1] == ACK)
{
/* Packet transfered correctly */
ackReceived = 1;
}
}
else
{
errors++;
}
}while (!ackReceived && (errors < 0x0A));
/* Resend packet if NAK for a count of 10 else end of commuincation */
if (errors >= 0x0A)
{
return errors;
}
receivedC[0] = 0x00;
do
{
Send_Byte(EOT);
/* Send (EOT); */
/* Wait for Ack */
if ((Receive_Byte(&receivedC[0], 1000000) == 0) && receivedC[0] == ACK)
{
ackReceived = 1;
}
else
{
errors++;
}
/* Clear Overrun flag of the USART2 */
//USART_ClearFlag(EVAL_COM1, USART_FLAG_ORE);
}while (!ackReceived && (errors < 0x0A));
if (errors >= 0x0A)
{
return errors;
}
return 0; /* file trasmitted successfully */
}
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
谢谢浏览,有需要完整的程序可以加QQ153443979或者私我。