【MPC5744P】Bootloader下位机开发(CAN通讯)

Bootloader上位机、下位机及用户APP范例直接下载:https://gitee.com/beatfan/mpc5744-p_-bootloader.git

此下位机开发通讯采用CAN,所有Hex文件解析工作在上位机,下位机尽可能避免复杂操作,以加快烧录速度。

使用的为NXP DEVKIT-MPC5744P开发板。

为保证烧录过程不出现错误,上下位机采用一问一答模式,上位机发送一帧数据后,下位机接收处理完毕再回馈给上位机,上位机再决定下一步动作。

核心代码逻辑部分,将命令分成EntryBootloader, Reset, Data, DataEnd, CheckBootloader, Erase, ERR几个部分。

烧录时会先检查是否处于Bootloader,然后执行擦写操作(擦写地址范围由上位机发送),再发送数据(地址+数据为一帧),最后发送结束命令。由于Flash编程最小单位为64bits,所以为防止出现奇数个数据,最后结束检查必不可少。

void CAN_Tasks()
{
//	uint32_t iflag = CAN_0.IFLAG1.R;
	if(CAN_0.IFLAG1.B.BUF6I==1)       /*is new CAN data received*/
	{
		CAN_RxMsg = CAN0_ReceiveMsg(MB6);
		//CAN_0.IFLAG1.B.BUF6I=0;
		AfterBootloader_CmdType result = Bootloader_DataParse_g(CAN_RxMsg.Frame_Data,CAN_RxMsg.Frame_Length);

		switch (result)
		{
			case EntryBootloader:
				break;
			case Reset:
				bootloader_entry();          /*jump to app and should not back */
				break;
			case Data:
				UserFlash_DataParseAddrData(CAN_RxMsg.Frame_Data,CAN_RxMsg.Frame_Length);
				SIUL2.GPDO[LED_R].B.PDO ^= 1; //red led blink

				Load_ReponseToUpMachine(g_Bootloader_DataReponse,8);
//				g_ReceiveCount++;
				break;

			case DataEnd:
				UserFlash_LastIsFull64Bits_g();

				SIUL2.GPDO[LED_R].B.PDO = 1; //red off
				SIUL2.GPDO[LED_G].B.PDO = 0; //green on
				SIUL2.GPDO[LED_B].B.PDO = 1; // blue off

				Load_ReponseToUpMachine(g_Bootloader_DataProgramEndReponse,8);

				app_entry();          /*jump to app and should not back */
				break;

			case CheckBootloader:
				Load_ReponseToUpMachine(g_Bootloader_CheckBootloaderReponse,8);
				break;

			case Erase:
				countTimer=(1000*g_GOTOAPP_TIMEOUT)+1;
				UserFlash_EraseIvtAndUserAppBlock_g(CAN_RxMsg.Frame_Data,CAN_RxMsg.Frame_Length);

				SIUL2.GPDO[LED_R].B.PDO = 1; //red off
				SIUL2.GPDO[LED_G].B.PDO = 1; //green off
				SIUL2.GPDO[LED_B].B.PDO = 1; // blue off
				Load_ReponseToUpMachine(g_Bootloader_EraseFlashReponse,8);
			  break;
			default:
				break;
		}/*end if switch*/



	}
}
//每帧CAN数据类型解析
AfterBootloader_CmdType Bootloader_DataParse_g(uint8_t *data, uint8_t dataLength)
{
    uint8_t result=0;
    if(dataLength!=8)
        return 0xff;
    
    //第一个字节为数据类型
    switch(data[0])
    {
        case EntryBootloader:
            result = EntryBootloader;
            break;
        case Reset:
            result = Reset;
            break;
        case Data:
            result = Data;
            break;
        case DataEnd:
            result = DataEnd;
            break;
        case CheckBootloader:
            result = CheckBootloader;
            break;
        case Erase:
            result = Erase;
            break;
        default:return 0xff;
    }
    
    return result;
}

Flash焼写逻辑(注意,由于CAN长度为8字节,而32位地址已经占用4字节,Flash地址从0x800000开始,所以所有地址减去0x800000,3字节即可,首字节作为数据类型):

/***************************************
 * Flash Block Range

锛�
// LOW--not program, partition 0 and 1
0x00800000-0x00803FFF		--		16KB,EEPROM-low block0, RWW_P:0
0x00804000-0x00807FFF		--		16KB,EEPROM-low block1, RWW_P:0
0x00F98000-0x00F9BFFF		--		16KB,low flash memory block2, RWW_P:1  //bootloader
0x00F9C000-0x00F9FFFF		--		16KB,low flash memory block3, RWW_P:1  //bootloader

// MID , partition 2 and 3
0x00808000-0x0080FFFF		--		32KB,EEPROM-mid block0, RWW_P:2
0x00810000-0x00817FFF		--		32KB,EEPROM-mid block1, RWW_P:3

//HIGH, , partition 4 and 5
0x00FA0000-0x00FAFFFF		--		64KB,high flash memory block0, RWW_P:4  //User App
0x00FB0000-0x00FBFFFF		--		64KB,high flash memory block1, RWW_P:4
0x00FC0000-0x00FCFFFF		--		64KB,high flash memory block2, RWW_P:4
0x00FD0000-0x00FDFFFF		--		64KB,high flash memory block3, RWW_P:5
0x00FE0000-0x00FEFFFF		--		64KB,high flash memory block4, RWW_P:5
0x00FF0000-0x00FFFFFF		--		64KB,high flash memory block5, RWW_P:5

//256K--all used
0x01000000-0x0103FFFF		--		256KB,256k flash memory block0, RWW_P:6
0x01040000-0x0107FFFF		--		256KB,256k flash memory block1, RWW_P:6
0x01080000-0x010BFFFF		--		256KB,256k flash memory block2, RWW_P:6
0x010C0000-0x010FFFFF		--		256KB,256k flash memory block3, RWW_P:6
0x01100000-0x0113FFFF		--		256KB,256k flash memory block4, RWW_P:7
0x01140000-0x0117FFFF		--		256KB,256k flash memory block5, RWW_P:7
0x01180000-0x011BFFFF		--		256KB,256k flash memory block6, RWW_P:7
0x011C0000-0x011FFFFF		--		256KB,256k flash memory block7, RWW_P:7

 **************************************/

uint32_t USERAPPFLASH_STARTADDR=0x00FA0000;
uint32_t USERAPPFLASH_ENDADDR=0x011FFFFF;

//erase
//0xFD0000-0x010032E4, 0x05,0x7d,0x00,0x00,0x80,0x32,0xe4,0x00
void UserFlash_EraseIvtAndUserAppBlock_g(uint8_t *data, uint8_t length)
{
	uint32_t count=0;
	USERAPPFLASH_STARTADDR = data[1]*256*256 + data[2]*256 + data[3] + 0x800000;
	USERAPPFLASH_ENDADDR = data[4]*256*256 + data[5]*256 + data[6] + 0x800000;

	Flash_Unlock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);

	Flash_Erase_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);

	//Flash_Check_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);
	while(count<100000)
		count++;

//	erase_flash_except_bootloader();
}

//length%2==0,length must be even number
void UserFlash_WriteData(uint32_t addr, uint32_t *data, uint32_t length)
{
	uint32_t startAddr;
	uint32_t endAddr;
	startAddr = addr;
	endAddr = startAddr+length-1;

//	Flash_Unlock_g(startAddr,endAddr);

//	ret = Flash_Erase_g(startAddr,endAddr);

	//ret = Flash_Check_g(startAddr,endAddr);

	Flash_Program_g(startAddr,endAddr, data,length);

//	Flash_Lock_g(startAddr,endAddr);
}

uint32_t m_LastAddr=0x000004+0x800000; //program every 8 address
uint32_t dataForWrite[2]; //最小写入单位64bits

//program addr must add 0x800000
void UserFlash_DataParseAddrData(uint8_t *data, uint8_t length)
{
    uint32_t addr;
    uint32_t dataTmp;
    
    addr = data[1]*256*256 + data[2]*256 + data[3] + 0x800000;
    
    //large-endian
    dataTmp = data[4]*256*256*256 +data[5]*256*256+ data[6]*256 + data[7];
   

    if(addr%8==0) //本次第一个地址
        {
            if(m_LastAddr%8==0) //上一次也为第一个
            {
                dataForWrite[1] = 0xFFFFFFFF; //上一次第二个填充FFFFFFFF
                UserFlash_WriteData(m_LastAddr,dataForWrite,2); 
            }
            //无论上次是否为第一个,本次都是开始
            dataForWrite[0] = dataTmp; //鏈涓虹涓�涓寚浠ゅ瓧

        }
        else //本次为第二个地址
        {
            if(m_LastAddr%8==0) //上次为第一个
            {
                if((addr-m_LastAddr)==4) //与上次连续
                {
                    dataForWrite[1] = dataTmp; //本地为上次同一组第二个
                    UserFlash_WriteData(m_LastAddr,dataForWrite,2); 
                }
                else //与上一次不连续
                {
                    dataForWrite[1] = 0xFFFFFFFF; //上次第二个填充FFFFFFFF
                    UserFlash_WriteData(m_LastAddr,dataForWrite,2); 

                    dataForWrite[0] = 0xFFFFFFFF; //本次第一个填充FFFFFFFF
                    dataForWrite[1] = dataTmp; /
                    UserFlash_WriteData(addr-4,dataForWrite,2); 
                }
            }
            else //上次为第二个,仅填充本次组即可
            {
                    dataForWrite[0] = 0xFFFFFFFF; 
                    dataForWrite[1] = dataTmp; 
                    UserFlash_WriteData(addr-4,dataForWrite,2); 
            }
        }
    

    m_LastAddr = addr;
    

}


void UserFlash_LastIsFull64Bits_g()
{
	if(m_LastAddr%8==0) //最后是否为单个数据
	{
		dataForWrite[1] = 0xFFFFFFFF; 
		UserFlash_WriteData(m_LastAddr,dataForWrite,2); 
	}

	Flash_Lock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);
}

 

另外提醒大家一下,在没有Bootloader时,首次通过JTAG烧录程序时,可以将Bootloader和App合并烧录,一般是将Bootloader的Hex文件最后一行删除,将App的所有行复制到Bootloader后面。

 

 

下面贴几个文件:

 

Bootloader.h

#ifndef _AFTER_PROTOCOL_BOOTLOADER_H_
#define _AFTER_PROTOCOL_BOOTLOADER_H_

#include <stdint.h>

//bootloader wait time (seconds)
#define g_GOTOAPP_TIMEOUT 4

/// <summary>
/// Command type
/// </summary>
typedef enum 
{
    EntryBootloader=0,Reset=1,Data=2,DataEnd=3,CheckBootloader=4,Erase=5,ERR=0xff
}AfterBootloader_CmdType;


/// <summary>
/// Bootloader Entry
/// </summary>
uint8_t m_Bootloader_EntryBootloaderCmd[8];

/// <summary>
/// reset in bootloader
/// </summary>
uint8_t m_Bootloader_ResetCmd_g[8];

/// <summary>
/// Check Mcu is whether in bootloader
/// </summary>
uint8_t m_Bootloader_CheckBootloaderCmd[8];


/// <summary>
/// reponse to up machine with "I am in bootloader" for once enter bootloader
/// </summary>
uint8_t g_Bootloader_EntryBootloaderReponse[8];

/// <summary>
/// reponse for check bootloader command, if mcu is in bootloader and up machine ask for reply
/// </summary>
uint8_t g_Bootloader_CheckBootloaderReponse[8];

/// <summary>
/// reponse for erasing completed
/// </summary>
uint8_t g_Bootloader_EraseFlashReponse[8];

/// <summary>
/// reponse for filling one data completed
/// 02 00 00 00 00 00 00 00
/// </summary>
uint8_t g_Bootloader_DataReponse[8];
        
/// <summary>
/// reponse for the last data writing completed
/// </summary>
extern uint8_t g_Bootloader_DataProgramEndReponse[8];


//check received can data, and parse command type
AfterBootloader_CmdType Bootloader_DataParse_g(uint8_t *data, uint8_t dataLength);


#endif

 

 

Bootloader.c

#include "Bootloader.h"

        
/// <summary>
/// Bootloader Entry
/// </summary>
uint8_t m_Bootloader_EntryBootloaderCmd[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

/// <summary>
/// reset in bootloader
/// </summary>
uint8_t m_Bootloader_ResetCmd_g[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

/// <summary>
/// Check Mcu is whether in bootloader
/// </summary>
uint8_t m_Bootloader_CheckBootloaderCmd[8] = {  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };


/// <summary>
/// reponse to up machine with "I am in bootloader" for once enter bootloader
/// </summary>
uint8_t g_Bootloader_EntryBootloaderReponse[8] = { 0x00, g_GOTOAPP_TIMEOUT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

/// <summary>
/// reponse for check bootloader command, if mcu is in bootloader and up machine ask for reply
/// </summary>
uint8_t g_Bootloader_CheckBootloaderReponse[8] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

/// <summary>
/// reponse for erasing completed
/// </summary>
uint8_t g_Bootloader_EraseFlashReponse[8] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

/// <summary>
/// reponse for filling one data completed
/// 02 00 00 00 00 00 00 00
/// </summary>
uint8_t g_Bootloader_DataReponse[8] ={ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        
/// <summary>
/// reponse for the last data writing completed
/// </summary>
uint8_t g_Bootloader_DataProgramEndReponse[8] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

//compare array
uint8_t ArrayCheck(uint8_t *data1,uint8_t *data2,uint8_t length)
{
    uint8_t i,result=0;
    for(i=0;i<length;i++)
    {
        if(data1[i]!=data2[i])
        {
            result=1;
            return result;
        }
    }
    return result;
}

//check received can data, and parse command type
AfterBootloader_CmdType Bootloader_DataParse_g(uint8_t *data, uint8_t dataLength)
{
    uint8_t result=0;
    if(dataLength!=8)
        return 0xff;
    
    //data[0] is command type
    switch(data[0])
    {
        case EntryBootloader:
            result = EntryBootloader;
            break;
        case Reset:
            result = Reset;
            break;
        case Data:
            result = Data;
            break;
        case DataEnd:
            result = DataEnd;
            break;
        case CheckBootloader:
            result = CheckBootloader;
            break;
        case Erase:
            result = Erase;
            break;
        default:return 0xff;
    }
    
    return result;
}

 

UserAppFlash.h

#ifndef _AFTER_PROTOCOL_USERAPPFLASH_H_
#define _AFTER_PROTOCOL_USERAPPFLASH_H_

#include <stdint.h>


//erase, 8 bits data is can receive data
void UserFlash_EraseIvtAndUserAppBlock_g(uint8_t *data, uint8_t length);

//fill data, 8 bits data is can receive data
void UserFlash_DataParseAddrData(uint8_t *data, uint8_t length);

//receive data end, check data is whether writed completed
void UserFlash_LastIsFull64Bits_g();

#endif

 

UserAppFlash.c

#include "Bootloader.h"
#include "Drivers/Flash/flash.h"


/***************************************
 * Flash Block Range

锛�
// LOW--not program, partition 0 and 1
0x00800000-0x00803FFF		--		16KB,EEPROM-low block0, RWW_P:0
0x00804000-0x00807FFF		--		16KB,EEPROM-low block1, RWW_P:0
0x00F98000-0x00F9BFFF		--		16KB,low flash memory block2, RWW_P:1  //bootloader
0x00F9C000-0x00F9FFFF		--		16KB,low flash memory block3, RWW_P:1  //bootloader

// MID , partition 2 and 3
0x00808000-0x0080FFFF		--		32KB,EEPROM-mid block0, RWW_P:2
0x00810000-0x00817FFF		--		32KB,EEPROM-mid block1, RWW_P:3

//HIGH, , partition 4 and 5
0x00FA0000-0x00FAFFFF		--		64KB,high flash memory block0, RWW_P:4  //User App
0x00FB0000-0x00FBFFFF		--		64KB,high flash memory block1, RWW_P:4
0x00FC0000-0x00FCFFFF		--		64KB,high flash memory block2, RWW_P:4
0x00FD0000-0x00FDFFFF		--		64KB,high flash memory block3, RWW_P:5
0x00FE0000-0x00FEFFFF		--		64KB,high flash memory block4, RWW_P:5
0x00FF0000-0x00FFFFFF		--		64KB,high flash memory block5, RWW_P:5

//256K--all used
0x01000000-0x0103FFFF		--		256KB,256k flash memory block0, RWW_P:6
0x01040000-0x0107FFFF		--		256KB,256k flash memory block1, RWW_P:6
0x01080000-0x010BFFFF		--		256KB,256k flash memory block2, RWW_P:6
0x010C0000-0x010FFFFF		--		256KB,256k flash memory block3, RWW_P:6
0x01100000-0x0113FFFF		--		256KB,256k flash memory block4, RWW_P:7
0x01140000-0x0117FFFF		--		256KB,256k flash memory block5, RWW_P:7
0x01180000-0x011BFFFF		--		256KB,256k flash memory block6, RWW_P:7
0x011C0000-0x011FFFFF		--		256KB,256k flash memory block7, RWW_P:7

 **************************************/

uint32_t USERAPPFLASH_STARTADDR=0x00FA0000;
uint32_t USERAPPFLASH_ENDADDR=0x011FFFFF;

//erase
//0xFD0000-0x010032E4, 0x05,0x7d,0x00,0x00,0x80,0x32,0xe4,0x00
void UserFlash_EraseIvtAndUserAppBlock_g(uint8_t *data, uint8_t length)
{
	uint32_t count=0;
	USERAPPFLASH_STARTADDR = data[1]*256*256 + data[2]*256 + data[3] + 0x800000;
	USERAPPFLASH_ENDADDR = data[4]*256*256 + data[5]*256 + data[6] + 0x800000;

	Flash_Unlock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);

	Flash_Erase_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);

	//Flash_Check_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);
	while(count<100000)
		count++;

//	erase_flash_except_bootloader();
}

//write one group (64bits) data
//length%2==0,length must be even number
void UserFlash_WriteData(uint32_t addr, uint32_t *data, uint32_t length)
{
	uint32_t startAddr;
	uint32_t endAddr;
	startAddr = addr;
	endAddr = startAddr+length-1;

//	Flash_Unlock_g(startAddr,endAddr);

//	ret = Flash_Erase_g(startAddr,endAddr);

	//ret = Flash_Check_g(startAddr,endAddr);

	Flash_Program_g(startAddr,endAddr, data,length);

//	Flash_Lock_g(startAddr,endAddr);
}

uint32_t m_LastAddr=0x000004+0x800000; //program every 8 address锛�64bits
uint32_t dataForWrite[2]; //every 64bits for programming

//program addr must add 0x800000
//every 64bits for programming (one group with two data)
void UserFlash_DataParseAddrData(uint8_t *data, uint8_t length)
{
    uint32_t addr;
    uint32_t dataTmp;
    
    addr = data[1]*256*256 + data[2]*256 + data[3] + 0x800000;
    
    //large-endian
    dataTmp = data[4]*256*256*256 +data[5]*256*256+ data[6]*256 + data[7];
   

    if(addr%8==0) //is the first 32bits data of 64bits , every 32bits occupy 4 address uints
        {
            if(m_LastAddr%8==0) // last address is first of a group
            {
                dataForWrite[1] = 0xFFFFFFFF; //fill second data of last group with 0xffffffff
                UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write last group data to flash
            }
            //Hower last group is really filled, the new group start
            dataForWrite[0] = dataTmp; //new group first data

        }
        else //is the second data of group
        {
            if(m_LastAddr%8==0) // last address is first of a group
            {
                if((addr-m_LastAddr)==4) //this is the next of last data within one group
                {
                    dataForWrite[1] = dataTmp; //fill the second data of group
                    UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write this group to flash
                }
                else //last address is first data of a group, and this address is second, but they are not in one group
                {
                    dataForWrite[1] = 0xFFFFFFFF; //fill second data of last group with 0xffffffff
                    UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write last group data to flash

                    dataForWrite[0] = 0xFFFFFFFF; //fill first data of this group with 0xffffffff
                    dataForWrite[1] = dataTmp; //fill second data of this group
                    UserFlash_WriteData(addr-4,dataForWrite,2); //write this group data to flash
                }
            }
            else// last address is second of a group, and this address is second
            {
                    dataForWrite[0] = 0xFFFFFFFF; //fill first data of this group with 0xffffffff
                    dataForWrite[1] = dataTmp; //fill second data of this group
                    UserFlash_WriteData(addr-4,dataForWrite,2);  //write this group data to flash
            }
        }
    

    m_LastAddr = addr;
    

}

//receive data end, check data is whether writed completed
void UserFlash_LastIsFull64Bits_g()
{
	if(m_LastAddr%8==0) // last address is first of a group
	{
		dataForWrite[1] = 0xFFFFFFFF; //fill second data of last group with 0xffffffff
		UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write last group data to flash
	}

	Flash_Lock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR);
}


 

posted on 2018-12-28 08:33  Beatfan  阅读(662)  评论(0)    收藏  举报

导航