我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 957|回复: 0

在EK-STM32F学习套件上实现了USB-DFU设备功能 - 单片机/处理器

[复制链接]

该用户从未签到

1万

主题

1292

回帖

936

积分

管理员

积分
936

社区居民最爱沙发原创达人社区明星终身成就奖优秀斑竹奖宣传大使奖特殊贡献奖

QQ
发表于 2013-3-29 10:57:48 | 显示全部楼层 |阅读模式
首先在ST官网上下载了STM32的USB开发套件地址:http://www.st.com/stonline/produ ... ro/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开发套件后把他们放到同一个目录下(STM32F10xUSBLib),方法如下:

1)自建一个STM32F10xUSBLib目录

2)下载这个文件
<ignore_js_op>




1.zip

<em class="xg1">(139.44 KB, 下载次数: 4)

</em>



2009-11-25 15:50:32 上传
下载次数: 4
下载积分: 积分 -1



</ignore_js_op>
并解压到STM32F10xUSBLib目录

3)下载这个文件
<ignore_js_op>




2.zip

<em class="xg1">(231.04 KB, 下载次数: 4)

</em>



2009-11-25 15:50:32 上传
下载次数: 4
下载积分: 积分 -1



</ignore_js_op>
并解压到STM32F10xUSBLib目录


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

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

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

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

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

。。。。。。

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。

至于原先在测试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-4-12
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

论坛开启做任务可以
额外奖励金币快速赚
积分升级了


Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

平平安安
TOP
快速回复 返回顶部 返回列表