用烧录器下载程序,每次插拔下载接口都非常的费劲。就想着能够实现无线烧录程序就好;查了相关资料,需要先写一个Bootloader,然后下载到F28035主控板,然后通过上位机通过无线串口对主控板实现升级;对DSP内部存储器的调用得用官方提供的API库;安装C2000ware之后,在下面路径可以搜索到API_lib;而且有例程可以参考;

参考例程学会如何调用API函数后,就可以开始写Bootloader,之前有发过帖子分享了F103的串口Bootloader,直接引用之前的程序,再加上OLED显示Bootloader的状态;代码如下:
//============================================================================
// * Function : BootloaderAPP()
// * Purpose : This function initializes the BootloaderAPP.
// * Parameters : Null
// * Return : Null
//============================================================================
#pragma CODE_SECTION(BootloaderAPP,"ramfuncs");
void BootloaderAPP(void)
{
Uint16 Status;
Uint32 u32OffsetAddress = 0;
Uint16 u16ProgramCount = 0;
Uint16 u16VerityCount = 0;
Uint32 u32TimerCount = 0;
u8Program_Cnt=0;
memset(&tSCICom, 0, sizeof(tSCICom));
memset(&tSCICom.u8SCIRXBuffer, 0, (PacketSize+8));
while(1)
{
tUpdateFlash.u8UpdateDataFlag = 1;
while(tUpdateFlash.u8UpdateDataFlag == 1)
{
u32TimerCount++;
if(u32TimerCount > 15000000)
{
u32TimerCount = 0;
Status = Flash_Verify((Uint16 *)VerifyAddr,(Uint16 *)UpdataFlag16,8,&FlashStatus);
if(Status == STATUS_SUCCESS)
{
return;
}
}
}
if(tUpdateFlash.u8UpdateDataStatus == 0)
{
switch(tSCICom.u8SCIRXBuffer[Data_Commad])
{
case Update_Keep:
tUpdateFlash.u8UpdateDataStatus = M_ACK;
//============================OLED显示==============================//
OLED_Clear();
OLED_ShowString(20,10,"<-BootAPP->");
OLED_ShowString(0,30,"Link_Success");
OLED_Refresh_Gram();
//================================================================//
break;
case Update_EraseAll:
DINT;
Status = Flash_Erase((SECTORD|SECTORE|SECTORF|SECTORG|SECTORH),&FlashStatus);
EINT;
if(Status == STATUS_SUCCESS)
{
tUpdateFlash.u8UpdateDataStatus = EraseAll_Success;
//============================OLED显示==============================//
OLED_Clear();
OLED_ShowString(20,10,"<-BootAPP->");
OLED_ShowString(0,30,"Erase_Success");
OLED_Refresh_Gram();
//================================================================//
}
else
{
tUpdateFlash.u8UpdateDataStatus = Com_Fail;
}
break;
case Update_ProgramCommand:
u32OffsetAddress = ((long)tSCICom.u8SCIRXBuffer[4]<<8)+((long)tSCICom.u8SCIRXBuffer[5]);
if(u32OffsetAddress <= 0xFFFF)
{
for(u16ProgramCount = 0; u16ProgramCount < (tSCICom.u16UpdateDataLength/2); u16ProgramCount++)
{
tSCICom.Update_Buffer[u16ProgramCount]=(tSCICom.u8SCIRXBuffer[2*u16ProgramCount+6] << 8)+(tSCICom.u8SCIRXBuffer[2*u16ProgramCount+7]);
}
for(u16VerityCount = 0; u16VerityCount < (tSCICom.u16UpdateDataLength/4); u16VerityCount++)
{
tSCICom.Verify_Buffer[u16VerityCount]=((Uint32)tSCICom.u8SCIRXBuffer[2*u16VerityCount+1] << 16)+((Uint32)tSCICom.u8SCIRXBuffer[2*u16VerityCount]);
}
Status = Flash_Program((Uint16 *)(u32OffsetAddress + Flash_ProjectStart),(Uint16 *)tSCICom.Update_Buffer,tSCICom.u16UpdateDataLength/2,&FlashStatus);
if(Status == STATUS_SUCCESS)
{
tUpdateFlash.u8UpdateDataStatus = ProgramCommand_Success;
//============================OLED显示==============================//
u8Program_Cnt++;
OLED_ShowString(20,10,"<-BootAPP->");
OLED_ShowString(0,30,"Programming ");
OLED_ShowNumber(96,30,u8Program_Cnt,3,12);
OLED_Refresh_Gram();
//================================================================//
}
else
{
tUpdateFlash.u8UpdateDataStatus = Com_Fail;
}
}
else
{
tUpdateFlash.u8UpdateDataStatus = Com_Fail;
}
break;
case Update_End:
tUpdateFlash.u8UpdateDataStatus = M_NACK;
break;
}
}
UpdateReplyData();
tSCICom.u16BuffCountNum = 0;
u32TimerCount = 0;
if(tUpdateFlash.u8UpdateDataStatus == M_NACK)
{
WriteVerfyData();
//============================OLED显示==============================//
u8Program_Cnt=0;
OLED_Clear();
OLED_ShowString(20,10,"<-BootAPP->");
OLED_ShowString(0,30,"Upgrade_Success");
OLED_Refresh_Gram();
//================================================================//
memset(&tSCICom , 0 , sizeof(tSCICom));
memset(tSCICom.u8SCIRXBuffer , 0xFF , (PacketSize+8));
break;
}
}
}
Bootloader写好之后就是上位机的编写,之前就有过C#的学习经历,还有点基础,其他不懂的就问DeekSeek ;上位机主要难点有三个,1、是如何对烧录下载文件的解析;2、是如何对下载到DSP的每一帧数据处理;3、是跟DSP之间的通信协议;
对烧录文件的解析如下:
private UInt16 File_Parsing(object sender)
{
byte DataLen = 0;
byte FileCom;
UInt16 count = 0;
while (count < PacketSize)
{
if ((LineDataCount == 0) && (SupdataFlag == 0))
{
File_String = reader.ReadLine();
SendBox.AppendText(File_String);
SendBox.AppendText(Environment.NewLine);
LineNumCount++;
}
if (File_String.IndexOf(':') == 0)
{
DataLen = Convert.ToByte(File_String.Substring(1, 2), 16);
AddressOffset = Convert.ToUInt32((Convert.ToByte(File_String.Substring(3, 2), 16) << 8) + (Convert.ToByte(File_String.Substring(5, 2), 16)));
if (DataLen != 0)
{
if (UpgradeObject.Text == "DSP")
{
if (LineNumCount == 2)
{
AddressRecord = AddressOffset + AddressBase;
}
AddressReal = AddressBase + AddressOffset;
AddressTemp = Convert.ToUInt32(AddressReal - AddressRecord);
AddressTemp = Convert.ToUInt32(AddressOffset * 2);
}
else if (UpgradeObject.Text == "MCU")
{
AddressReal = AddressBase + AddressOffset;
AddressTemp = Convert.ToUInt32(AddressReal);
}
}
FileCom = Convert.ToByte(File_String.Substring(7, 2), 16);
switch (FileCom)
{
case 0x00:
while (((AddressTemp - PreviousAddress) != PreviousDataLen) && (FristFlag == 1) && (count < PacketSize))
{
Data[count + 6] = 0xFF;
count++;
PreviousAddress++;
if (count == PacketSize)
{
SupdataFlag = 1;
return count;
}
}
for (; (LineDataCount < DataLen) && (count < PacketSize); LineDataCount++)
{
Data[count + 6] = Convert.ToByte(File_String.Substring(LineDataCount * 2 + 9, 2), 16);
count++;
}
if (LineDataCount == DataLen)
{
PreviousDataLen = DataLen;
PreviousAddress = AddressTemp;
LineDataCount = 0;
SupdataFlag = 0;
}
FristFlag = 1;
break;
case 0x01:
reader.Close();
UpdataFlag = 1;
return count;
case 0x04:
AddressBase = Convert.ToUInt32((Convert.ToByte(File_String.Substring(3, 2), 16) << 8) +
(Convert.ToByte(File_String.Substring(5, 2), 16)) +
(Convert.ToByte(File_String.Substring(9, 2), 16) << 24) +
(Convert.ToByte(File_String.Substring(11, 2), 16) << 16));
break;
}
}
}
return count;
}
发送数据处理代码如下:
private void Updata_Packaging(object sender)
{
UInt16 crc = 0;
UInt16 i;
UInt16 strlen;
//起始字节
Data[0] = 0xDD;
//数据长度 + 数据获取
strlen = File_Parsing(sender);
if (strlen != PacketSize)
{
for (i = strlen; i < PacketSize; i++ )
{
Data[i + 6] = 0xFF;
}
strlen = PacketSize;
}
Data[1] = Convert.ToByte(strlen >> 8);
Data[2] = Convert.ToByte(strlen & 0xFF);
//命令
Data[3] = 0x0E;
//地址
Data[4] = Convert.ToByte(Download_Addr >> 8);
Data[5] = Convert.ToByte(Download_Addr & 0xFF);
Download_Addr += PacketSize/2;
//crc校验
strlen = Convert.ToUInt16(strlen + 6);
crc = CalculateCrc16(Data, strlen);
Data[strlen] = Convert.ToByte(crc >> 8);
Data[strlen + 1] = Convert.ToByte(crc & 0xFF);
//将待发送数据拷贝到DataBuffer,等待发送
DataLength = strlen + 2;
Array.Copy(Data, DataBuffer, DataLength);
}
与DSP通讯交互代码如下:
private void StartUpdata_Click(object sender, EventArgs e)
{
int num;
ushort crc = 0;
Calculagraph.Reset();
Calculagraph.Start();
//1.引导进入Boot
num = 1;
while (num <= AgainCount)
{
Data[0] = 0xDD;
Data[1] = 0x00;
Data[2] = 0x1A;
Data[3] = 0x2A;
Data[4] = 0x3A;
crc = CalculateCrc16(Data, 5);
Data[5] = Convert.ToByte(crc >> 8);
Data[6] = Convert.ToByte(crc & 0xFF);
serialPort.Write(Data, 0, 7);
Delay(200);
num++;
}
//2.状态检测
num = 1;
while (num <= AgainCount)
{
Data[0] = 0xDD;
Data[1] = 0x00;
Data[2] = 0x00;
Data[3] = 0x0A;
Data[4] = 0x00;
Data[5] = 0x00;
crc = CalculateCrc16(Data, 6);
Data[6] = Convert.ToByte(crc >> 8);
Data[7] = Convert.ToByte(crc & 0xFF);
serialPort.Write(Data, 0, 8);
Delay(200);
num++;
if (Cmdata[2] == 0xAA)
{
Cmdata[2] = 0x00;
RecState.Text = "连接成功";
StartUpdata.Enabled = false;
break;
}
if (num == AgainCount)
{
MessageBox.Show(" 升级等待超时1 ");
return;
}
}
//3.擦除Flash
num = 1;
while (num <= AgainCount)
{
Data[0] = 0xDD;
Data[1] = 0x00;
Data[2] = 0x00;
Data[3] = 0x0C;
Data[4] = 0x00;
Data[5] = 0x00;
crc = CalculateCrc16(Data, 6);
Data[6] = Convert.ToByte(crc >> 8);
Data[7] = Convert.ToByte(crc & 0xFF);
serialPort.Write(Data, 0, 8);
Delay(3000);
num++;
if (Cmdata[2] == 0xC1)
{
Cmdata[2] = 0x00;
RecState.Text = "擦除全部成功";
break;
}
if (num == AgainCount)
{
MessageBox.Show(" 升级等待超时2 ");
return;
}
}
//4.烧录数据
UpdataFlag = 0;
while (UpdataFlag == 0)
{
Updata_Packaging(sender);
num = 1;
while (num <= AgainCount)
{
serialPort.Write(DataBuffer, 0, DataLength);
Delay(100);
num++;
if (Cmdata[2] == 0xE1)
{
Cmdata[2] = 0x00;
RecState.Text = "正在升级";
break;
}
if (num == AgainCount)
{
MessageBox.Show(" 升级等待超时3 ");
return;
}
}
}
//5.升级完成
if (UpdataFlag == 1)
{
num = 1;
while (num <= AgainCount)
{
Delay(100);
Data[0] = 0xDD;
Data[1] = 0x00;
Data[2] = 0x00;
Data[3] = 0x0B;
Data[4] = 0x00;
Data[5] = 0x00;
crc = CalculateCrc16(Data, 6);
Data[6] = Convert.ToByte(crc >> 8);
Data[7] = Convert.ToByte(crc & 0xFF);
serialPort.Write(Data, 0, 8);
Delay(100);
num++;
if (Cmdata[2] == 0xBB)
{
Cmdata[2] = 0x00;
Calculagraph.Stop();
RecState.Text = "升级成功";
break;
}
if (num == AgainCount)
{
MessageBox.Show(" 升级等待超时4 ");
return;
}
}
}
}
下面视频介绍上位机如何生成一个单独应用程序
