在EK-STM32F学习套件上实现了USB-DFU设备功能

chuangxin129   2008-1-8 15:51 楼主
首先在ST官网上下载了STM32的USB开发套件
地址:http://www.st.com/stonline/products/support/micro/files/um0424.zip

由于此开发套件基于ST的官方开发板,与EK-STM32F的电路有所不同。

比较了一下,不同之处在于
1, 官方的开发套件使用PD.09作为USB识别使能线,而EK-STM32F使用PD.08。
2, 官方的开发套件通过PB.09来判断是否进入DFU模式, 而EK-STM32F的按键使用了PD.03和PD.04。
3,  EK-STM32F没有接外部SPI Flash, 所以只能更新内部flash。

因此修改代码如下:

void DFU_Button_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable GPIOD clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
  
  /* Configure PD.04 as input floating (Key push-button on EK-STM32F) */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
}

u8 DFU_Button_Read (void)
{
  /* Return the value of PD.04 */
  return GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_4); 
}

void Set_System(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  FLASH_Unlock(); 

  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
 
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }

  /* Enable GPIOD clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
  
  /* PD.08 used as USB pull-up --> EK-STM32F */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  USB_Cable_Config (DISABLE);
 // SPI_FLASH_Init();
  USB_Cable_Config (ENABLE);
}

void USB_Cable_Config (FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    GPIO_ResetBits(GPIOD, GPIO_Pin_8);
  }
  else
  {
    GPIO_SetBits(GPIOD, GPIO_Pin_8);
  }    
}

修改后烧入EK-STM32F学习板,果然能识别出一个DFU设备。


/******************************************************************/
已上传移植到EKSTM32F的USB开发套件
https://bbs.eeworld.com.cn/upfiles/img/20081/200818174511397.zip
https://bbs.eeworld.com.cn/upfiles/img/20081/200818174737153.zip

下载了后要把001.zip改成zip.001, 002.zip改成zip.002


/******************************************************************/
由于我用的7-zip看上去和大家的winzip不太兼容,所以请按23楼的说明,重新下载。

ZT 23楼如下:

 香水城 发表于 2008-1-9 14:02 ST MCU ←返回版面    

23楼: 问题找到了,是楼主使用的压缩软件与Windows自带的不兼容 

通过与各方沟通,发现不能正确解压缩的原因是,楼主使用的压缩软件与Windows自带的不兼容。我下载并成功解压楼主的文件包,里面有两个目录,我把他们分别做了两个压缩包,因为项目文件中有相联关系,请下载后把他们放到同一个目录下(STM32F10xUSBLib)。

自建一个STM32F10xUSBLib目录
  下载https://bbs.eeworld.com.cn/upfiles/img/20081/200819135956499.zip文件并解压到STM32F10xUSBLib目录
  再下载https://bbs.eeworld.com.cn/upfiles/img/20081/20081914129199.zip文件并解压到STM32F10xUSBLib目录

最终目录结构应为:
STM32F10xUSBLib
  FWLib
    library
      inc
      src
  USBLib
    demos
      Device_Firmware_Upgrade  本帖介绍的DFU演示软件
      JoyStickMouse
      Mass_Storage
      Virtual_COM_Port
    library
      inc
      src
 
 



回复评论 (44)

继续

在ST官网下载PC端驱动和应用程序
地址:http://www.st.com/stonline/products/support/micro/files/um0412.zip

安装后运行DfuSeDemo(V2.1),在DFU Device中识别到一个STM Device in DFU Mode设备。

选择Internal Flash,选择STM32 USB开发套件的DFU DEMO中的任意image, 按下Upgrade按键。

出现一个对话框:擦除操作失败

。。。。。。




点赞  2008-1-8 16:01

继续

DFU的代码我曾经在ST的官方开发板上测试过,没有出过错,那么现在的错误在哪里呢?

拿了USB分析仪,看USB线上数据,发现设备总在某次的DFU_GETSTATUS请求后响应一个STALL信号,导致出错。

根据USB DFU协议(下载地址:http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf), 对DFU_GETSTATUS的响应应该由:bStatus(1byte) + bwPollTimeout(3Bytes,以ms为单位) + bState(1byte) + iString(1byte)组成,但看USB线上数据,设备的响应为:00 00 00 00 04 00,显然是要求的Poll Time时间太短,导致设备在擦除flash的等待时间内无法响应PC端的又一个请求。

仔细看u8 *GETSTATUS(u16 Length)的代码:
    case   STATE_dfuDNLOAD_SYNC:
      if (wlength != 0)
      {
        DeviceState = STATE_dfuDNBUSY;
        DeviceStatus[4] = DeviceState;
        if ((wBlockNum == 0) && (Load_Buffer[0] == CMD_ERASE))
        {
          if  (Pointer < 0x800000) /* 64K sectors of SPI Flash */
          {
            DeviceStatus[1] = 0xDC;  /* 1.5 seconds */
            DeviceStatus[2] = 0x05;
            DeviceStatus[3] = 0x00;
          }
                  <=====================此处值得商榷
        }
        else
        {
          DeviceStatus[1] = (wlength >> 8) * 2  ; /* Nb of Pages(of 256 )* 2ms */
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0;
        }
     
      }
      else  /* (wlength==0)*/
      {
        DeviceState = STATE_dfuDNLOAD_IDLE;
        DeviceStatus[4] = DeviceState;
        DeviceStatus[1] = 0;
        DeviceStatus[2] = 0;
        DeviceStatus[3] = 0;
        
      }
   break;

代码在分析到当前操作为CMD_ERASE命令时,仅仅对SPI FLASH的操作定义了Poll的时间,而对内部flash的操作没有定义,因此设备直接返回了0。

察看STM32F103的Datasheet:
Page(1KB)erase time 为 Min20ms,  Max40ms
Word programming time 为 Min20us, Max40us


修改代码如下:
   case   STATE_dfuDNLOAD_SYNC:
      if (wlength != 0)
      {
        DeviceState = STATE_dfuDNBUSY;
        DeviceStatus[4] = DeviceState;
        if ((wBlockNum == 0) && (Load_Buffer[0] == CMD_ERASE))
        {
          if  (Pointer < 0x800000) /* 64K sectors of SPI Flash */
          {
            DeviceStatus[1] = 0xDC;  /* 1.5 seconds */
            DeviceStatus[2] = 0x05;
            DeviceStatus[3] = 0x00;
          }
          else {
            DeviceStatus[1] = 0x28; 
            DeviceStatus[2] = 0x00;
            DeviceStatus[3] = 0x00;
          }
        }
        else
        {
//          DeviceStatus[1] = (wlength >> 8) * 2  ; /* Nb of Pages(of 256 )* 2ms */
          DeviceStatus[1] = (wlength >> 8) * 10  ; /* Nb of Pages(of 256 )* 10ms */
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0;
        }
     
      }
      else  /* (wlength==0)*/
      {
        DeviceState = STATE_dfuDNLOAD_IDLE;
        DeviceStatus[4] = DeviceState;
        DeviceStatus[1] = 0;
        DeviceStatus[2] = 0;
        DeviceStatus[3] = 0;
        
      }
      break;


修改后重新烧录代码,重新执行Upgrade操作,OK。
点赞  2008-1-8 16:25

继续

至于原先在测试DFU代码时为何没有出错,我认为是因为我刚新换了电脑的缘故,PC跑的快了,愿意等待的时间短了。。。。。

DUF搞完,开始考虑image的生成。

PC端的应用程序除了DfuSeDemo,还有个DfuFileManage(V2.1),能将S19,HEX和BIN文件生成DFU文件。


随便找了个LCD的demo,修改lnkarm_flash.xcl文件如下:
// Code memory in FLASH
-DROMSTART=0x8003000
-DROMEND=0x801FFFF


修改stm32f10x_nvic.h文件对于Vector Table地址的定义如下:
#define NVIC_VectTab_RAM             ((u32)0x20000000)
#define NVIC_VectTab_FLASH           ((u32)0x08003000)

使用IAR生成raw-binary文件。

运行DFU File Manager Generation程序, 选择Mullti Bin injection,输入刚才生成的bin文件,选择地址为0x08003000, 生成OK。

运行DfuSeDemo程序,将刚才生成的DFU文件烧录到内部flash中。

按下Reset按键,LCD DEMO程序如愿跑了起来,再次按下Reset按键,同时按下KEY3,PC识别到一个DFU设备。

至此,DFU设备在EK-STM32F学习板上移植成功。
点赞  2008-1-8 16:38

赏两条裤子

本主题帖的选题非常好,为各位学习STM32的USB开了个好头,这个第一条裤子。

3搂在移植的基础上发现了原来程序的Bug,通过对照USB-DFU协议,找到问题所在,使得所有功能正常运行;这就赚到了第二条裤子。
点赞  2008-1-8 16:53

学习中

                                 等我忙完了这段也玩玩强大的DFU
点赞  2008-1-8 17:34

谢谢版主赏裤子,正好要降温了。。。

再接再厉,上传移植到EK-STM32F学习板的USB开发套件。


相关链接:https://bbs.eeworld.com.cn/upfiles/img/20081/200818174511397.zip
点赞  2008-1-8 17:45

继续

文件太大了,压成了两个包,下载了以后要把001.zip改成zip.001, 002.zip改成zip.002
相关链接:https://bbs.eeworld.com.cn/upfiles/img/20081/200818174737153.zip
点赞  2008-1-8 17:47

哈哈~~~谢谢~~~

                                  
点赞  2008-1-8 17:50

好,我喜欢。

                                  
点赞  2008-1-8 18:59

顶一个,啥事俺也要玩玩。

                                  
点赞  2008-1-8 19:03

怎么解压啊!谢谢

                                 怎么解压啊!谢谢
点赞  2008-1-8 21:53

楼上居然连zip文件如何解压都不知道?

                                 外星人?
点赞  2008-1-8 21:55

先做记号

                                  
点赞  2008-1-8 22:29

这帖子不错,有质量

                                  
点赞  2008-1-8 22:29

文件是不是有问题啊,解压不了



好像第二个压缩包有问题
点赞  2008-1-9 08:30

可以解压呀

                                 按8楼指示,下载7楼文件并改名为xxxx.zip.001,下载8楼文件并改名为xxxx.zip.002,这两个文件放到同一个目录下,然后双击文件xxxx.zip.001,既可解压。
点赞  2008-1-9 08:37

晕倒,还是不行,难道是电脑出问题了??


能否把修改的文件直接打包传上来?

或者发我邮箱吧
liuhang20011@163.com

谢谢
点赞  2008-1-9 09:18

1、3、4楼已经讲解了所有修改的部分,你可以自己手动改一

我这里又下载了一遍,没有问题。估计你是下载的窗口中存文件是改的文件名,这样有可能文件被存为xxxx.zip.001.zip和xxxx.zip.002.zip,这当然有问题。

请务必下载后确认文件名为xxxx.zip.001和xxxx.zip.002!!

看了一下,压缩包里有其他几个例子,不知道是否已经修改过。
点赞  2008-1-9 09:47

报告

压缩包里的DEMO都是已经移植好的

和ST官方的USB开发套件相比,少了一个Audio_Speaker的DEMO,我还没想好怎么改过去。
点赞  2008-1-9 10:32
123下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复