3634 views|3 replies

36

Posts

1

Resources
The OP
 

APM32E103VET6 Review: IAP Upgrade [Copy link]

 This post was last edited by Zachary_yo on 2022-9-21 22:58

This issue shares the serial port IAP online upgrade program (Bootloader) of APM32E103VET5, which uses the Ymodem protocol. This protocol is derived from the official ST program. Due to the different sizes of Flash pages or sectors (such as sectors for the F4 series and page erase for the F1 series), changes have been made. The following is the Flash storage structure of APM32E103VET6, as shown in the figure below. Each page is 2K, with a total of 256 pages, totaling 512K. We use the first 8 pages, that is, the first 16K (0x08000000-0x08003FFF) to store the Bootloader program, and the remaining Flash space is used to store the App program. Here I only share the online upgrade method of Bootloader+App. In addition to the first time, in order to prevent sudden failures during the upgrade process, you can also use the Bootloader+App+App backup method to upgrade.

Next, let's talk about the principle of this upgrade program. First, the App program area (0x08004000-0807FFFF) needs to be erased (the Flash feature is that new bytes can be written only after erasing); after the erasing is completed, each 1K App data received through the serial port is written to the corresponding Flash address. After the write is successful, the Flash address increments automatically, and this cycle repeats until the host computer has completely sent the data (protocol control).

The following is the program content. Copy the files required for Ymodem from the ST official program and add them to the project. Modify commom.c, flash_if.c, and menu.c accordingly. The program fragment is as follows.

The following is the content of the common.c file. Only the content of the uint32_t SerialKeyPressed( uint8_t *key ) function is modified. The function is to query the serial port to receive data.

/*
*********************************************************************************************************
*	函 数 名: SerialKeyPressed
*	功能说明: 获取整数输入
*	形    参: key 按键
*	返 回 值: 1 返回数据 2 没有返回
*********************************************************************************************************
*/
uint32_t SerialKeyPressed( uint8_t *key )
{
    if ( USART_ReadStatusFlag( IAP_COM, USART_FLAG_RXBNE ) != RESET )
    {
        //*key = (uint8_t)USART_DATA(IAP_COM);
        *key = USART_RxData( IAP_COM );
//        USART_ClearStatusFlag( IAP_COM, USART_FLAG_RXBNE );

        return 1;
    }
    else
    {
        return 0;
    }
}

The following is the content of the flash_if.c file. In this file, all the functions mentioned above need to be modified. The modified content needs to be changed according to the Flash storage structure of different MCUs. The following changes are made according to APM32E103VET6.

/**************************************************************
  * [url=home.php?mod=space&uid=32621]@name[/url]  FLASH_If_Init
  * [url=home.php?mod=space&uid=159083]@brief[/url]  * @param   None
  * @retval
  * [url=home.php?mod=space&uid=1315547]@author[/url]  Zachary
  * [url=home.php?mod=space&uid=34591]@data[/url]  2022-09-01
 **************************************************************/
void FLASH_If_Init( void )
{
    FMC_Unlock();
	FMC_ClearStatusFlag( FMC_FLAG_OC );
	FMC_ClearStatusFlag( FMC_FLAG_PE  );
	FMC_ClearStatusFlag( FMC_FLAG_WPE );
}

/**************************************************************
  * @Name    FLASH_If_Erase
  * @brief
  * @param   StartSector: [输入/出]
  * @retval  
  * @author  Zachary
  * @Data    2022-09-01
 **************************************************************/
uint32_t FLASH_If_Erase( uint32_t StartSector )
{
    uint32_t UserStartSector = 0, i = 0, EndSector = 0,pageaddr = 0x08000000;

	EndSector = 255;

    /* 用户flash区所在的扇区 */
    UserStartSector = GetPage( StartSector );
	pageaddr = pageaddr + ( UserStartSector * 0x800 );

    for( i = UserStartSector; i <= EndSector; i++ )
    {
        if ( FMC_ErasePage( pageaddr ) != FMC_STATUS_COMPLETE )
        {
            return ( 1 );
        }
		FMC_ClearStatusFlag( FMC_FLAG_OC );
		FMC_ClearStatusFlag( FMC_FLAG_PE  );
		FMC_ClearStatusFlag( FMC_FLAG_WPE );
		pageaddr += 0x800;

    }

    return ( 0 );
}


/**************************************************************
  * @Name    FLASH_If_Write
  * @brief
  * @param   FlashAddress: [输入/出]
**			 Data: [输入/出]
**			 DataLength: [输入/出]
  * @retval
  * @author  Zachary
  * @Data    2022-05-22
 **************************************************************/
uint32_t FLASH_If_Write( __IO uint32_t* FlashAddress, uint32_t* Data, uint32_t DataLength )
{
    uint32_t i = 0;

    for ( i = 0; ( i < DataLength ) && ( *FlashAddress <= ( USER_FLASH_END_ADDRESS - 4 ) ); i++ )
    {
        /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
        be done by word */
        if ( FMC_ProgramWord( *FlashAddress, *( uint32_t* )( Data + i ) ) == FMC_STATUS_COMPLETE )
        {
            /* 检查写入的数据 */
            if ( *( uint32_t* )*FlashAddress != *( uint32_t* )( Data + i ) )
            {
                /* 读出的和写入的不相同 */
                return( 2 );
            }

            /* 地址递增 */
            *FlashAddress += 4;
        }
        else
        {
            return ( 1 );
        }
    }

    return ( 0 );
}
/**************************************************************
  * @Name    FLASH_If_GetWriteProtectionStatus
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2022-09-01
 **************************************************************/
uint16_t FLASH_If_GetWriteProtectionStatus( void )
{
//    uint32_t UserStartSector = 0;

//    UserStartSector = GetPage( APPLICATION_ADDRESS );

//    if ( FMC_GetReadProtectionStatus() != RESET )
//    {
        return 1;
//    }
//    else
//    {
//        return 0;
//    }
}

/**************************************************************
  * @Name    FLASH_If_DisableWriteProtection
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2022-09-01
 **************************************************************/
uint32_t FLASH_If_DisableWriteProtection( void )
{
	
	FMC_Unlock();
    FMC_DisableReadOutProtection();

    return ( 1 );
}

/**************************************************************
  * @Name    GetSector
  * @brief
  * @param   Address: [输入/出]
  * @retval
  * @author  Zachary
  * @Data    2022-09-01
 **************************************************************/
static uint32_t GetPage( uint32_t Address )
{
    uint32_t sector = 0;

    sector = ( Address - 0x08000000 ) / 0x800;

    return sector;
}

The following is the content of the menu.c file. In this file, only the Main_Menu() function is changed to change the way the program jumps from the Bootloader to the App.

void Main_Menu( void )
{
    uint8_t key = 0;

    /* Test if any sector of Flash memory where user application will be loaded is write protected */
    if ( FLASH_If_GetWriteProtectionStatus() == 0 )
    {
        FlashProtection = 1;
    }
    else
    {
        FlashProtection = 0;
    }

    while ( 1 )
    {
        SerialPutString( "\r\n================== Bootloader Menu =======================\r\n\n" );
        SerialPutString( "  Download Image To the GD32F470 Internal Flash -------- 1\r\n\n" );
        SerialPutString( "  Upload Image From the GD32F470 Internal Flash -------- 2\r\n\n" );
        SerialPutString( "  Execute The New Program ------------------------------ 3\r\n\n" );

        if( FlashProtection != 0 )
        {
            SerialPutString( "  Disable the write protection(Not Used) --------------- 4\r\n\n" );
        }

        SerialPutString( "==========================================================\r\n\n" );

        /* Receive key */
        key = GetKey();

        if ( key == 0x31 )
        {
            /* Download user application in the Flash */
            SerialDownload();
        }
        else if ( key == 0x32 )
        {
            //SerialUpload();
        }
        else if ( key == 0x33 )
        {
            if ( 0x20000000 == ( ( *( __IO uint32_t* )APPLICATION_ADDRESS ) & 0x2FFE0000 ) )
            {
				SysTick->VAL = 0;
				SysTick->LOAD = 0;
                SysTick->CTRL = 0;
				USART_Disable( IAP_COM );
                JumpAddress = *( __IO uint32_t* ) ( APPLICATION_ADDRESS + 4 );
                /* Jump to user application */
                Jump_To_Application = ( pFunction ) JumpAddress;
                /* Initialize user application's Stack Pointer */
                __set_MSP( *( __IO uint32_t* ) APPLICATION_ADDRESS );
                Jump_To_Application();
            }
        }
        else if ( ( key == 0x34 ) && ( FlashProtection == 1 ) )
        {
            /* Disable the write protection */
            switch ( FLASH_If_DisableWriteProtection() )
            {
            case 1:
            {
                SerialPutString( "Write Protection disabled...\r\n" );
                FlashProtection = 0;
                break;
            }
            case 2:
            {
                SerialPutString( "Error: Flash write unprotection failed...\r\n" );
                break;
            }
            default:
            {
            }
            }
        }
        else
        {
            if ( FlashProtection == 0 )
            {
                SerialPutString( "Invalid Number ! ==> The number should be either 1, 2 or 3\r" );
            }
            else
            {
                SerialPutString( "Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r" );
            }
        }
    }
}

The following are the important contents in main.c. When the microcontroller is powered on, it starts with the Bootloader. In the main program, it is determined whether it needs to be upgraded or jump to the App to run the program. In the main program, UpgradeFlag is used to determine whether an online upgrade is required. If no upgrade is required, check whether there is a program in the App area. If not, perform an online upgrade. The upgrade flag UpgradeFlag is defined as uint16_t UpgradeFlag __attribute__ ((at(0x2001FC00))). And the RAM space after 0x2001FC00 is set to uninitialized. The purpose is to reset the microcontroller software and not lose data, so that it is convenient to jump from the App flag to the Bootloader for upgrading.

int main( void )
{
	__disable_irq();
	if( UpgradeFlag == 0x1234 )
	{
		UpgradeFlag = 0x0000;
		FLASH_If_Init();
		SysInit();
		goto __IAP_START;
	}

	if ( 0x20000000 == ( ( *( __IO uint32_t * )APPLICATION_ADDRESS ) & 0x2FFE0000 ) )
    {
        SysTick->CTRL = 0;
        SysTick->LOAD = 0;
        SysTick->VAL = 0;
		USART_Disable( USART1 );
        JumpAddress = *( __IO uint32_t* ) ( APPLICATION_ADDRESS + 4 );
        Jump_To_Application = ( pFunction ) JumpAddress;
        __set_MSP( *( __IO uint32_t* ) APPLICATION_ADDRESS );
		//__set_CONTROL(0);
        Jump_To_Application();
		
    }
	else
	{
		FLASH_If_Init(); /* 初始化flash操作 */
		SysInit();
		goto __IAP_START;
	}

__IAP_START:
    Main_Menu();
    while( 1 )
	{
//		GPIOB->ODATA_B.ODATA9 ^= 1;
//		delay_ms( 1000 );
    }
}

The following are the settings of the UpgradeFlag definition area in the Bootloader program and the App program, uint16_t UpgradeFlag __attribute__ ((at(0x2001FC00))).

Test the App program code. When 0x31 ('1') is received, the flag is set and the software is reset. After the reset, the Bootloader detects the UpgradeFlag flag and enters the upgrade program.

/**************************************************************
  * @Name    main                                    
  * @brief  
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2022-09-13
 **************************************************************/
int main( void )
{
	SCB->VTOR |= 0x4000;
	NVIC_ConfigPriorityGroup( NVIC_PRIORITY_GROUP_4 );
    SysInit();
	
    while( 1 )
	{
		if( comGetChar( COM1, &rxdata ) )
		{
			if( rxdata == 0x31 )
			{
				UpgradeFlag = 0x1234;
				__disable_irq();
				NVIC_SystemReset();
			}
		}
		GPIOB->ODATA_B.ODATA9 ^= 1;
		printf( "hello world\r\n" );
		delay_ms( 1000 );
    }
}

The Bin file is generated as follows: input C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output =BIN\@L.bin !L

Test Video

WeChat_20220921224952

Finally, the program code of App and Bootloader is attached. It has been tested using APM32E103VET6 MINIBOARD development board. If you have any questions, please leave a message.

This program is for testing purposes only.

3_APM32E103VET6_IAP.7z (606.1 KB, downloads: 5, 售价: 10 分芯积分)

This post is from Domestic Chip Exchange

Latest reply

I watched the transplant process, it was very good! Very good. I use F407 here. I will test it to see if it can be ported over.   Details Published on 2024-7-3 07:21
 
 

2

Posts

0

Resources
2
 

Very good, I use F407 here, let's test it and see if it can be transplanted

This post is from Domestic Chip Exchange
 
 
 

3

Posts

0

Resources
3
 
Very good, I use F103 here, I will test it to see if it can be transplanted
This post is from Domestic Chip Exchange
 
 
 

6818

Posts

11

Resources
4
 

I watched the transplant process, it was very good!

Very good. I use F407 here. I will test it to see if it can be ported over.

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Featured Posts
MATLAB APP Designer serial port debugging tool writing

This post was last edited by lb8820265 on 2019-5-9 23:11 Previously, we introduced two ways to use VC6 to make serial ...

About the original picture and packaging

Does anyone have the original picture and package of STM32F103 series?

How to use CPLD to collect asynchronous signals

Scenario: Use CPLD to decode a serial data channel. The data has no accompanying clock and has a fixed frequency but a d ...

Measuring poles and zeros from a Bode plot

This post was last edited by Jack315 on 2021-1-25 00:52 The transfer function of a single zero is: 522846 The Bode plot ...

Encoder counting principle and motor speed measurement principle - multi-picture analysis

This post was last edited by DDZZ669 on 2021-2-14 23:30 Encoder is a sensor used to measure mechanical rotation or displ ...

35 "Ten Thousand Miles" Raspberry Pi Car——ROS Learning (Realizing Hello World)

The best way to learn ROS is to use it. The ROS official website has a Chinese version of the tutorial . After install ...

36 "Ten Thousand Miles" Raspberry Pi Car——ROS Learning (VSCode to Implement Hello World)

It is very convenient to run ROS projects in VSCode. In this section, we use ROS to write and run the "Hello world" pro ...

[The strongest open source] Hand-rubbed 120W switching power supply

I recently took the time to make a switching power supply 645265 645262 645263 645264 645261 645260

Record a blue screen pit

I mentioned a while ago that my company's computers would occasionally blue screen. Now I think about it, the blue scree ...

ESP8266 01+DHT11 acquisition

Could anyone give me some advice? When I collect DHT11 data through one of GPIO 0 and 2, the 8266 01 keeps restarting. O ...

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews

Room 1530, Zhongguancun MOOC Times Building, Block B, 18 Zhongguancun Street, Haidian District, Beijing 100190, China Tel:(010)82350740 Postcode:100190

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list