DIY编程器网
标题:
uuprog开发教程:Bootloader应用讲解2
[打印本页]
作者:
liyf
时间:
2014-11-16 06:23
标题:
uuprog开发教程:Bootloader应用讲解2
前面已经说了bootloader的基本设置,这次讲解下怎么控制bootloader工作,以便实现我们想要的功能。我们用他来做什么呢?这就是我们的目的:更新固件。要更新固件就要烧写固件代码,那就需要实现:擦出,烧写,校验这几个最基本的功能,当然其他功能就需要你自己发挥了。
QQ图片20141115182132.png
(59.08 KB, 下载次数: 94)
下载附件
保存到相册
2014-11-15 18:21 上传
这里就是要实现的功能,其实很简单的,我们用到了字符型的控制命令,这样的好处当然是为了容易理解。当然你要是用于商业化最好还是不要用这种明码方式了,自己想想吧,题外话了。
我们这里设置了个专门的处理函数,就是为了大家方便添加自己的处理功能,而不用关心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,
// after an 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[1] == 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[2] == 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 packet was 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[1])
{
case 'E': //擦除
FlashErase(*((unsigned int *)(cmdbuf + 2)));
cmdbuf[1] = RES_OK;
cmdbuf[2] = 2;
return 1;
case 'C': //校验数据
cmdbuf[1] = FlashCheck(*((unsigned int *)(cmdbuf + 2)),&cmdbuf[5],cmdbuf[4]);
cmdbuf[2] = 2;
return 1;
case 'W': //写数据
FlashWrite(*((unsigned int *)(cmdbuf + 2)),&cmdbuf[5],cmdbuf[4]);
cmdbuf[1] = RES_OK;
cmdbuf[2] = 2;
return 1;
case 'V': //读版本
cmdbuf[1] = RES_OK;
cmdbuf[2] = 7;
cmdbuf[3] = 'V';
cmdbuf[4] = '1';
cmdbuf[5] = '.';
cmdbuf[6] = '0';
cmdbuf[7] = '0';
cmdbuf[8] = '\0';
return 1;
case 'R': //运行客户程序
RunUserProg();
return 2;
case 'T': //Bootloader测试
cmdbuf[1] = RES_OK;
cmdbuf[2] = 1;
cmdbuf[3] = '-';
return 1;
default:
return 0;
}
}
复制代码
具体的每个功能函数的实现就自己下载源代码看了,师父领进门,修行在个人嘛,不可能面面俱到的,实现代码不难,难在你自己怎么看。不理解的代码就赶紧进补下。
下次将讲解上位机怎么控制这个固件实现你得功能,欢迎大家密切关注。
作者:
shangdawei
时间:
2014-11-16 13:55
密切关注
作者:
dwl65
时间:
2014-11-18 22:17
门外汉,门外羡慕嫉妒恨中~~~~~~
作者:
bywqdq
时间:
2015-1-11 21:29
不知完成了编程器,还学习了mcu技术.赞
作者:
wlecust06
时间:
2021-1-24 13:44
可以的 其实最好能发命令进入bootloader 直接搞短接 不太好
欢迎光临 DIY编程器网 (http://diybcq.com/)
Powered by Discuz! X3.2