首先在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)下載這個文件 3)下載這個文件 最終目錄結構應為: 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 |