2013-03-11 09:29 PM
I'm having trouble leaving DFU mode (following instructions on pp 18 ~21 of
) and entering my application while boot0 is high. My application is loaded at 0x08000000 and I'm using STM32F4's system memory bootloader (reset with boot0 high). Here's my C♯ ''Leave DFU'' code for verifying the algorithm.//Open device
STDFUFunction.Call(() => STDFU.API.Open(_path, out _handle)); //Set Start Address. See pp 18 (section 5.2 of application note AN3156) byte[] address = new byte[] { 0x21, 0x00, 0x00, 0x00, 0x08 }; STDFUFunction.Call(() => STDFU.API.Dnload(ref _handle, address, (uint)address.Length, 0)); //Make start address active my issuing a GetStatus STDFU.DFUSTATUS status = new STDFU.DFUSTATUS(); STDFUFunction.Call(() => STDFU.API.GetStatus(ref _handle, ref status)); //A second Get Status to ensure address is accepted status = new STDFU.DFUSTATUS(); STDFUFunction.Call(() => STDFU.API.GetStatus(ref _handle, ref status)); //Command to leave DFU mode see pp 21 (section 5.5 of application note AN3156) byte[] dummy = new byte[] {}; STDFUFunction.Call(() => STDFU.API.Dnload(ref _handle, dummy, 0, 0)); //Get status to activate the command status = new STDFU.DFUSTATUS(); STDFUFunction.Call(() => STDFU.API.GetStatus(ref _handle, ref status)); //Close device STDFUFunction.Call(() => STDFU.API.Close(ref _handle)); Although I'm not checking the statuses in the code above, I've verified they all return the values expected as documented in AN3156. If I leave boot0 high, I hear the Windows USB disconnect ''ding'', but it appears that the my application doesn't run. However, it doesn't seem to be in the DFU mode either, as I can't re-download with resetting the processor again. If I pull boot0 low before the ''leave DFU mode'' code runs, and leave it low, it enters the application fine. I'm fairly certain my linker script and startup scripts properly place the code and vector table where they should be, at 0x08000000. You can find the full source code attached, but here's the relevant parts. Linker script (edited for brevity, see attachment for full code):CCRAM (rxw) : ORIGIN = 0x10000000, LENGTH = 64k
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512k _estack = ORIGIN(CCRAM) + LENGTH(CCRAM); .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } >FLASH Startup (edited for brevity, see attachment for full source code):.section .isr_vector,''a'',%progbits
.type __Vectors, %object .size __Vectors, .-__Vectors __Vectors: .word _estack /* Top of the stack */ .word Reset_Handler /* System Reset Handler */ My SystemInit is stock from the STM32F4 peripheral library. Does anyone see what I'm doing wrong? #stm32f4-dfu #stm32f4-dfu-ccm #dfu-ccm-stm32f42013-03-11 09:44 PM
Update:
I just found out that if I change my stack from CCM to Internal SRAM it works fine. Anyone know how I can keep using CCM for my stack and still leave DFU mode?2013-03-12 06:16 PM
I seemed to have solved this problem by added the following code to my startup assembly file right before the call to SystemInit. (File attached)
// Do the equivalent of RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CCMDATARAMEN, ENABLE); to enable
// CCM so we can use it for our stack. This was necessary to do here because when exiting // from the system memory bootloader (USB DFU), the CCM seems to be disabled movw r3, #14384 movt r3, #16386 ldr r2, [r3, #0] orr r2, r2, #1048576 str r2, [r3, #0] bl SystemInit /* Call the clock system intitialization function. */ If someone has a more elegant solution, I'd be interested in hearing about it. ________________ Attachments : startup_stm32f4xx.S : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HtUm&d=%2Fa%2F0X0000000aQp%2FHLhHWKD.DGMMccqAnqtWpIGmCmk8ff32XS3UBkr8WxU&asPdf=false2013-03-12 09:52 PM
Well the problem is that the DFU code resets the peripherals, but writes zero over the CCM Enable bit, your solutions seems reasonable.
1FFF3178 SUB16 DefaultHardware: ; Xref 1FFF0342 1FFF1AAA 1FFF1F76
1FFF3178 B580 push {r7, lr}
1FFF317A F7FE FEA8 bl sub_1FFF1ECE
1FFF317E F000 F81C bl sub_1FFF31BA
1FFF3182 48CB ldr r0, [pc, #812] ; ($1FFF34B0=$40023810)
1FFF3184 F04F 31FF mov.w r1, #4294967295 ; $FFFFFFFF
1FFF3188 6001 str r1, [r0, #0] ; $40023810 = $FFFFFFFF RCC_APB1RSTR
1FFF318A 2200 movs r2, #0
1FFF318C 6002 str r2, [r0, #0] ; $40023810 = $00000000 RCC_APB1RSTR
1FFF318E 6041 str r1, [r0, #4] ; $40023814 = $FFFFFFFF RCC_APB2RSTR
1FFF3190 6042 str r2, [r0, #4] ; $40023814 = $00000000 RCC_APB2RSTR
1FFF3192 6101 str r1, [r0, #16] ; $40023820 = $FFFFFFFF RCC_APB1RSTR
1FFF3194 6102 str r2, [r0, #16] ; $40023820 = $00000000 RCC_APB1RSTR
1FFF3196 6141 str r1, [r0, #20] ; $40023824 = $FFFFFFFF RCC_APB2RSTR
1FFF3198 6142 str r2, [r0, #20] ; $40023824 = $00000000 RCC_APB2RSTR
1FFF319A 6202 str r2, [r0, #32] ; $40023830 = $00000000 RCC_AHB1ENR (w/CCMDATARAMEN = 0)
1FFF319C 6242 str r2, [r0, #36] ; $40023834 = $00000000 RCC_AHB2ENR
1FFF319E 6342 str r2, [r0, #52] ; $40023844 = $00000000 RCC_APB2ENR
1FFF31A0 6302 str r2, [r0, #48] ; $40023840 = $00000000 RCC_APB1ENR
1FFF31A2 48C4 ldr r0, [pc, #784] ; ($1FFF34B4=$40023C00)
1FFF31A4 6801 ldr r1, [r0, #0] ; $40023C00 FLASH_ACR
1FFF31A6 F421 61E0 bic.w r1, r1, #1792 ; $700 ; $700 &= ~(PRFTEN | ICEN | DCEN)
1FFF31AA 6001 str r1, [r0, #0]
1FFF31AC 48C2 ldr r0, [pc, #776] ; ($1FFF34B8=$E000E010)
1FFF31AE 6002 str r2, [r0, #0] ; $E000E010 = $00000000
1FFF31B0 6082 str r2, [r0, #8] ; $E000E018 = $00000000
1FFF31B2 F44F 2100 mov.w r1, #524288 ; $80000
1FFF31B6 6041 str r1, [r0, #4] ; $E000E014 = $00080000
1FFF31B8 BD01 pop {r0, pc}
Alternate way of enabling CCMDATARAMEN
LDR R0,=0x42470601 ; BB +23830 RCC_AHB1ENR (+1)
STR R0,[R0,#0x4F] ; Set bit 20, see low order bit is 1 ((20*4)-1)