uuprog开发教程:Bootloader应用讲解2
前面已经说了bootloader的基本设置,这次讲解下怎么控制bootloader工作,以便实现我们想要的功能。我们用他来做什么呢?这就是我们的目的:更新固件。要更新固件就要烧写固件代码,那就需要实现:擦出,烧写,校验这几个最基本的功能,当然其他功能就需要你自己发挥了。这里就是要实现的功能,其实很简单的,我们用到了字符型的控制命令,这样的好处当然是为了容易理解。当然你要是用于商业化最好还是不要用这种明码方式了,自己想想吧,题外话了。
我们这里设置了个专门的处理函数,就是为了大家方便添加自己的处理功能,而不用关心usb协议的工作原理。说真的usb协议确实很难理解,所以很多人一说到usb就说头大,其实头大的不是usb协议,而是usb调试比较困难,不是很直观,不像串口调试那么简单而已。现在都有专业化的usb协议框架,自己只需要处理相关的函数就行。
这里我们用到的是端点1,他的相关处理函数如下:
//-----------------------------------------------------------------------------
// Handle_In1
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine loads the current value from In_Packet on the Endpoint 2 fifo,
// afteran interrupt is received from the last packet being transmitted
//
//-----------------------------------------------------------------------------
void U_Handle_In1()
{
BYTE ControlReg;
POLL_WRITE_BYTE(INDEX, 1); // Set index to endpoint 1 registers
POLL_READ_BYTE(EINCSR1, ControlReg); // Read contol register for EP 1
if (U_Ep_Status == EP_HALT) // If endpoint is currently halted, send a stall
{
POLL_WRITE_BYTE(EINCSR1, rbInSDSTL);
}
else // Otherwise send last updated data to host
{
if(ControlReg & rbInINPRDY)
{
return;
}
if (ControlReg & rbInSTSTL) // Clear sent stall if last packet returned a stall
{
POLL_WRITE_BYTE(EINCSR1, rbInCLRDT);
}
if (ControlReg & rbInUNDRUN) // Clear underrun bit if it was set
{
POLL_WRITE_BYTE(EINCSR1, 0x00);
}
if(U_EP1SendLen > 0)
{
U_Fifo_Write(FIFO_EP1, U_EP1SendLen, cmdbuf); // Put new data on Fifo
POLL_WRITE_BYTE(EINCSR1, rbInINPRDY); // Set In Packet ready bit, indicating
U_EP1SendLen = 0;
}
} // fresh data on Fifo 1
}
//-----------------------------------------------------------------------------
// Handle_Out1
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Take the received packet from the host off the fifo and put it into
// the Out_Packet array
//
//-----------------------------------------------------------------------------
void U_Handle_Out1()
{
BYTE Count = 0;
BYTE ControlReg;
POLL_WRITE_BYTE(INDEX, 1); // Set index to endpoint 2 registers
POLL_READ_BYTE(EOUTCSR1, ControlReg);
if (U_Ep_Status == EP_HALT) // If endpoint is halted, send a stall
{
POLL_WRITE_BYTE(EOUTCSR1, rbOutSDSTL);
}
else // Otherwise read packet from host
{
if (ControlReg & rbOutSTSTL) // Clear sent stall bit if last packetwas a stall
{
POLL_WRITE_BYTE(EOUTCSR1, rbOutCLRDT);
}
POLL_READ_BYTE(EOUTCNTL, Count);
U_Fifo_Read(FIFO_EP1, Count, cmdbuf);
Cmd_process();
U_EP1SendLen = 0x40;
U_Handle_In1();
POLL_WRITE_BYTE(EOUTCSR1, 0); // Clear Out Packet ready bit
}
}
里面已经添加了专门处理函数Cmd_process(),下面是这个函数的实现代码:
unsigned char Cmd_process(void)
{
switch(cmdbuf)
{
case 'E': //擦除
FlashErase(*((unsigned int *)(cmdbuf + 2)));
cmdbuf = RES_OK;
cmdbuf = 2;
return 1;
case 'C': //校验数据
cmdbuf = FlashCheck(*((unsigned int *)(cmdbuf + 2)),&cmdbuf,cmdbuf);
cmdbuf = 2;
return 1;
case 'W': //写数据
FlashWrite(*((unsigned int *)(cmdbuf + 2)),&cmdbuf,cmdbuf);
cmdbuf = RES_OK;
cmdbuf = 2;
return 1;
case 'V': //读版本
cmdbuf = RES_OK;
cmdbuf = 7;
cmdbuf = 'V';
cmdbuf = '1';
cmdbuf = '.';
cmdbuf = '0';
cmdbuf = '0';
cmdbuf = '\0';
return 1;
case 'R': //运行客户程序
RunUserProg();
return 2;
case 'T': //Bootloader测试
cmdbuf = RES_OK;
cmdbuf = 1;
cmdbuf = '-';
return 1;
default:
return 0;
}
}具体的每个功能函数的实现就自己下载源代码看了,师父领进门,修行在个人嘛,不可能面面俱到的,实现代码不难,难在你自己怎么看。不理解的代码就赶紧进补下。
下次将讲解上位机怎么控制这个固件实现你得功能,欢迎大家密切关注。
密切关注:victory: 门外汉,门外羡慕嫉妒恨中~~~~~~:curse: 不知完成了编程器,还学习了mcu技术.赞 可以的 其实最好能发命令进入bootloader 直接搞短接 不太好
页:
[1]