在上一章节中,我们了解了AGDI的函数接口,在这一章节中,我们根据AGDI接口来实现仿真器下载的功能。我们可以在AGDI.cpp文档中找到下载程序的所有功能接口,首先,在AGDI.cpp文档中搜索:“Flash Download interface functions follow ”。
我们可以看到,在注释后面是一组用于闪存编程的函数。这些功能就是封装了烧录的一些函数。具体的烧录实现步骤就得我们根据自己要调试的芯片烧录步骤进行代码的添加。
在这些接口中,首先,需要完成的第一组函数是 InitProgrammer() 和 ExitProgrammer()。这一组函数主要功能是用来开启和关闭你的仿真硬件是否开始工作,InitProgrammer()接口函数主要是做开启仿真硬件,说白了就是你通过发送USB命令的形式来告诉你的仿真硬件说:我界面准备好了,你可以开始运作了,开始初始化和准备写入和读取的功能;ExitProgrammer()接口函数主要是做关闭仿真硬件,也是通过向USB发送命令的形式来告诉仿真硬件,告诉仿真硬件烧录流程已经完整结束了,可以给调试芯片放电,让被调试的芯片处于没上电的状态。
值得注意的是,ExitProgrammer() 应将所有 Flash 器件引脚上的电压电平设置为低电平,并断开器件电源,以便安全地从 仿真器的插槽插入和移除 Flash 器件。
其次,然后应该实现 InitDevFlash() 和 FlashLoad() 函数。InitDevFlash() 函数用于初始化 Flash 存储器,初始化设备是包含了对被调试芯片的Flash区域进行擦除。此时,Flash 器件被擦除并准备好进行 Flash 编程。如果需要对不同类型的设备进行编程,还可以执行 CheckDevID() 函数来读取设备 ID 并选择合适的编程算法进行 Flash 编程。一些 Flash 器件需要特殊的程序(像芯片设置的一组指令来进入烧录模式等等)来激活器件的 Flash 编程模式。这是通过函数 EnterProgMode() 完成的。
FlashLoad() 函数用于实际的闪存编程和验证。如果仿真硬件有足够的 SRAM 资源来保存完整的 Flash 数据,那么将会将其作为代码程序的缓冲区。当数据被写入闪存时,它也被存储到 SRAM 并在以后重新用于数据验证。如果使用“慢速”RS232 通信接口对大文件进行编程,这可以大大加快闪存加载过程。
以上的操作是在做:将Keil IDE界面上的代码编译后,通过仿真硬件烧录到被调试的芯片Flash当中。将这些函数接口实现后,我们可以来验证我们编写的功能是否正确。
测试方法是将Keil安装目录下的TOOL.ini文件中的TDRV配置成SampTarg工程项目Release下的SampTarg.dll目录。也就是更改 TOOLS.INI 文件:
TDRV0=D:\Src32\Target\Release\SampTarg.DLL(“Serven Debug Driver”),其中的Serven Debug Driver可以设置为自己想要设置的名称。
//--- Flash Download interface functions follow
//------------------------------------------------------
/*
* Initialize Flash programmer, download programmer firmware.
* Return 0 if Ok, 1 if failed.
*/
int InitProgrammer (void)
{
FlashProg = 1; // we have started the Flash Programmer
//---TODO: Add your initialization code here
//再次添加启动仿真器的代码,初始化仿真器
return (0); // say 'Ok.'
}
/*
* Stop Flash programmer, disconnect device power
* Return 0 if Ok, 1 if failed.
*/
int ExitProgrammer (void)
{
if (!FlashProg) return (0); // if Already done, just return
//---TODO: Add your deinitialization code here
//---If insertion socket is used for target Flash, make sure that all address,
//---data and control pins are held low and target VCC is disconnected here.
// 再次添加关闭仿真器的功能
FlashProg = 0;
return (0); // say 'Ok.'
}
/*
* Enter programming mode for the flash device
* Return 0 if Ok, 1 if failed.
*/
int EnterProgMode (void)
{
//---TODO: Add code for activating programming mode or just return if not needed
// 再次添加被调试芯片的进行烧录Flash的一组指令
return (0); // say 'Ok.'
}
/*
* Check device ID
* Return 0 if Ok, 1 if failed.
*/
int CheckDevID (void)
{
//---TODO: Add code to Read device ID and verify device type
// 添加检测被调试的芯片型号功能代码
return (0); // say 'Ok.'
}
/*
* Erase the flash device
* Return 0 if Ok, 1 if failed.
*/
int EraseFlash (void)
{
//---TODO: Add Flash Erase code here
// 添加擦除被调试芯片的Flash区域
return (0); // say 'Ok.'
}
/*
* Write data to Flash device
* Return 0 if Ok, 1 if failed.
*/
int WriteToFlash (DWORD nAdr, BYTE *pb, DWORD nCnt, DWORD *eAdr)
{
//---TODO: Add Flash Write Code here
//---Note: nAdr has uVision2 address convention
//---if write fails, set write error addres and return 1
// 开始对被调试的芯片Flash进行程序的烧录
*eAdr = 0;
return (0); // say 'Ok.'
}
/*
* Verify the content of Flash device
* Return 0 if Ok, 1 if failed.
*/
int VerifyFlash (DWORD nAdr, BYTE *pb, DWORD nCnt, DWORD *eAdr)
{
//---TODO: Verify Flash Code here
//---Note: nAdr has uVision2 address convention
//---if verify fails, set verify error addres and return 1
// 向被调试的芯片进行读取Flash,将读回来的程序与我们烧录的程序进行对比,验证烧录的程序是否正确
*eAdr = 0;
return (0); // say 'Ok.'
}
/*
* Send text Error message to Build window
*/
static void PgmError (char *pCmd) {
txtout ("*** Error: %s\n", pCmd);
}
/*
* Initialize target Flash device.
* Return 0 if Ok, 1 if failed.
*/
int InitDevFlash (void)
{
int nE;
//---We use 'EnterProgMode()' function to activate the programming mode of the device
//---when a special procedure to activate the programming mode is required.
//---If this is not required, we can skip this function.
nE = EnterProgMode ();
if (nE) {
PgmError ("Programming failed. Device in programming socket does not response.");
return (1); // failed
}
//---We use 'CheckDevID()' function to verify if right target device is attached.
//---If this is not required, we can skip this function.
nE = CheckDevID ();
if (nE) {
PgmError ("Programming failed. This device is not supported");
return (1); // failed
}
if (!(MonConf.Opt & FLASH_ERASE)) { // check if Download Function-Erase Flash enabled
return (0);
}
//---We erase the target flash here and prepare for flash writing.
nE = EraseFlash ();
if (nE) {
PgmError ("Flash Erase failed.");
return (1); // failed Flash not Erased
}
txtout ("Flash Erase Done.\n");
return (0); // Ok.
}
/*
* Write data for Flash Memory to Target
*
* If target hardware has installed SRAM that is big enough to hold the
* complete Flash image data, it is a good practice to use it as a buffer.
* This would speedup the flash verify process a lot if a big flash with
* big amount of data is programmed using 'slow RS232' interface.
*/
int FlashLoad (void) {
FLASHPARM *pF;
DWORD bCnt,errAdr;
char szMsg[80];
int nE = 0;
if (!(MonConf.Opt & FLASH_PROGRAM)) goto skipProg;
//---Write Flash memory if enabled
InitProgress("Loading...");
//---Get Flash Parameters from S8051.DLL
pF = (FLASHPARM *)pCbFunc (AG_CB_GETFLASHPARAM, NULL);
bCnt = 0;
while (pF->many != 0) { // while more chunks..
nE = WriteToFlash (pF->start, pF->image, pF->many, &errAdr);
if (nE) { // failed, send message
sprintf (szMsg,"Flash Write Failed at %04X", errAdr);
PgmError (szMsg);
goto x;
}
bCnt += pF->many;
SetProgress (bCnt*100/pF->ActSize);
pF = (FLASHPARM *)pCbFunc (AG_CB_GETFLASHPARAM, pF);// Get next parameters
}
SetProgress (100);
txtout ("Flash Write Done: %d bytes programmed.\n", bCnt);
StopProgress ();
skipProg:
if (!(MonConf.Opt & FLASH_VERIFY)) goto x;
//---Verify Flash memory if enabled
InitProgress("Verifying...");
//---Get Flash Parameters from S8051.DLL
pF = (FLASHPARM *)pCbFunc (AG_CB_GETFLASHPARAM, NULL);
bCnt = 0;
while (pF->many != 0) { // while more chunks..
nE = VerifyFlash (pF->start, pF->image, pF->many, &errAdr);
if (nE) { // failed, send message
sprintf (szMsg,"Flash Verify Failed at %04X", errAdr);
PgmError (szMsg);
goto x;
}
bCnt += pF->many;
SetProgress (bCnt*100/pF->ActSize);
pF = (FLASHPARM *)pCbFunc (AG_CB_GETFLASHPARAM, pF);// Get next parameters
}
SetProgress (100);
txtout ("Flash Verify Done: %d bytes verified.\n", bCnt);
x:StopProgress ();
ExitProgrammer ();
return (nE);
}