STM32G74的boot升级程序 ymodem协议

   要使用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>&copy; 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或者私我。

  • 32
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值