查看完整版本: uuprog开发教程:Bootloader应用讲解2

liyf 发表于 2014-11-16 06:23:22

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



shangdawei 发表于 2014-11-16 13:55:26

密切关注:victory:

dwl65 发表于 2014-11-18 22:17:10

门外汉,门外羡慕嫉妒恨中~~~~~~:curse:

bywqdq 发表于 2015-1-11 21:29:04

不知完成了编程器,还学习了mcu技术.赞

wlecust06 发表于 2021-1-24 13:44:54

可以的 其实最好能发命令进入bootloader 直接搞短接 不太好
页: [1]
查看完整版本: uuprog开发教程:Bootloader应用讲解2