产品己经完成一年,中间使用I2C介面来更新APROM,在此提供的范例是I2C bootloader。使用的一年中,还没有发生问题。如果大家有需求时,可以直接使用。这是一个I2C从机的boot loader。程序流程很简单。程序上电时,会判断重置旗标,如果是软重置,就进行程序更新流程,反之就跳到APROM。在跳到APROM之前,会对APROM check sum。保证APROM的程序是正确,才会跳到APROM。一旦check sum错误,就进行程序更新流程。
程序更新流程提供以下6个I2C指令。从机地址设定为0x32,主机可以使用0x32, 0x04, DATA0 ~DATA31。依序烧写料到APROM里。程序大小设定为8KB。这8KB资料全部都要烧录进去。才不会在check sum时产生错误。烧写完後,使用0x32, 0x03, 0xA5跳到APROM。
0x00 | R | MicroP H/W ID code | 0x01 | R | uP F/W version provided by vendor | 0x02 | R | uP_Boot_Selection | 0x03 | W | Set uP boot from APROM | 0x04 | W | Program and verify APROM | 0x05 | R | Read programming address |
如果要自行新增I2C指令,可以修改DrvI2C_HW.c, 按照以下红字,遂一增加你需求的CMD。
以PV_APROM_Address为例,
#define PV_APROM_Address 0x05
uint32_t u32APROMaddress = 0;
PV_APROM_Address指令为4B,read only。
HW_I2C_Data_t const HW_I2C_Cmd[]={
{uP_HW_ID_code ,HW_I2C_RO,4,(uint8_t*)&u32HW_ID_code}, /*--------- 0 ------------*/
{uP_FW_ID_code ,HW_I2C_RO,2,&u8FW_ID_code[0]}, /*--------- 1 ------------*/
{uP_Boot_Selection ,HW_I2C_RO,1,&u8uP_Boot_Selection},
{Set_uP_boot_from_APROM ,HW_I2C_WO,1,&u8Set_uP_boot_from_APROM},
{PV_APROM ,HW_I2C_WO,32,(uint8_t*)u32PV_APROM},
{UNDEF_CMD ,HW_I2C_RW,HW_I2C_MAX_DATA_LENGHT,&HW_I2C_temp_val[0]}, /*--------- 5 ------------*/
{PV_APROM_Address ,HW_I2C_RO,4,(uint8_t*)&u32APROMaddress},
};
这是一个look out table,对应i2c cmd,指向那一个指令,以对应到HW_I2C_Cmd的命令。
const uint8_t HW_I2C_Cmd_LookUp_Tab1[]={
0,1,2,3,4,6,5,5 ,5,5,5,5,5,5,5,5, /*0x00~0x0F*/
};
void Do_HW_I2C(HW_I2C_Data_t* HW_I2C_Data_Temp)
{
switch(HW_I2C_Data_Temp->Cmd)
{
case Set_uP_boot_from_APROM:
if(u8Set_uP_boot_from_APROM == 0xA5)
{
EnterAPROM();
u32APROMaddress = 0;
#ifdef DEBUG_ENABLE_LED
O_R_LED = 1;
#endif
}
break;
case PV_APROM:
Set_PV_flag();
break;
case PV_APROM_Address:
break;
}
}
void Read_HW_I2C(HW_I2C_Data_t* HW_I2C_Data_Temp)
{
switch(HW_I2C_Data_Temp->Cmd)
{
case PV_APROM_Address:
break;
}
}
在这个程序里,只能支持16指令。如果需更多指令,需要修改以下数字。如果大家有空也可以修改以下程序,不要使用look out table。用polling的方式,一个一个判断,寻找HW_I2C_Cmd[]对应的指令。如果没对找到对应的指令,就使用HW_I2C_Cmd[5]。
if(u32Temp<0x10)
{
HW_I2C_Data = (HW_I2C_Data_t*) &HW_I2C_Cmd[HW_I2C_Cmd_LookUp_Tab1[u32Temp]];
}else
{
HW_I2C_Data = (HW_I2C_Data_t*) &HW_I2C_Cmd[5];
}
|