|
前面已经说了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,
- // 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;
- }
- }
复制代码 具体的每个功能函数的实现就自己下载源代码看了,师父领进门,修行在个人嘛,不可能面面俱到的,实现代码不难,难在你自己怎么看。不理解的代码就赶紧进补下。
下次将讲解上位机怎么控制这个固件实现你得功能,欢迎大家密切关注。
|
|