2014-04-01 06:06 AM
Dear List,
I am working on IAP on the STM32F4Discovery board and flashing only occasionally works. I started from the example describing IAP using an USART. But I use USB to download the data to be flashed, with code derived from the USB-Device-VCP example. Downloading via USB works flawlessly. I also use USART2 as a debug-port, via syscalls.c/printf. I try to flash a few words, but it only occasionally works. On avarage 1 out of 3 progammings (of 3 words) are ok. Programming larger pieces never works. The flash is programmed using the interface from flash_if.c from the IAP-USART example. To flash I do: initially:FLASH_If_Init();
FLASH_If_Erase(flashadr);
and then as often as needed:
if ((j=FLASH_If_Write((volatile uint32_t *)&flashadr, (uint32_t*) buf, (uint16_t) bufsize/4)) != 0) { FLASH_If_Lock(); return j;}
and finally:
FLASH_If_Lock();
When the flashing fails, this is signalled in function
FLASH_Status FLASH_GetStatus(void)
(which is called from FLASH_ProgramWord(uint32_t Address, uint32_t Data))
When the error occurs, always in trying to flash address 0x8020000 (first word of section 5), then
FLASH->SR yields 0xC0, meaning (PGPERR and PGSERR)
The USB- and UART- code does not reside in section 5 that is to be reprogrammed, but in 1 to 4.
But maybe the problem is that USB and USART code is used, that use interrupts?
Disabling interrups in FLASH_ProgramWord did not help.
Can anybody point me in the right direction?
Thanks in advance,
Sietse
2014-04-10 05:18 AM
I am confused.
''That is why generally during Flash programming, the IRQs are disabled.'' But am I not doing that with this (in FLASH_If_Write())? __disable_irq();
t=FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data+i));
__enable_irq();
Is there another way to disable the interrupts?
I think the while loop is ok.
readblock()
This is the usb-read. The sending side sends exactly the number of bytes as expected by readblok.
It than starts to wait for an ack, that will be send AFTER flashit using send_request_chunk.
So no usb traffic after readblock until send_request_chunk.
(Or is there some ''keep-alive'' traffic or so from usb?)
Or am I missing something?
I also tried the following with chunks of 256 byte.
flash_lock();
while (not_ready) {
read_chunk();
__disable_irq; flash_unlock();
flashit();
__enable_irq ; flash_lock();
send_request_chunk;
}
Behaves the same. The first round in the loop is ok, but the very first FLASH_ProgramWord() in the second
round give the error (FLASH_SR == 0xC0)
And this version with all usb communication removed still works o.k.
2014-04-10 06:12 AM
Hi
'' __disable_irq();
t=FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data+i));
__enable_irq();
''
This is OK but probably too 'atomic'
It is probably more efficient to disable IRQs then write the 'block' of Flash data
rather than disable IRQs for each word.
'' (Or is there some ''keep-alive'' traffic or so from usb?)''
I think there is but I am not sure. It has not proved to be a problem for the project I am on.
I think the idea is right, just the implementation is not quite right.
The firmware download code hat I wrote does this:
Start Session. >
< Ack Start Session
< Start SessionComplete
Reqest to erase Flash (start address, end address) >
< Ack EraseREquest
(Flash Erase)
< EraseComplete
PacketToProgram( start address, length, data) >
< Ack PacketToProgram
(Flash program)
< PacketToProgramComplete
PacketToProgram( start address, length, data) >
< Ack PacketToProgram
(Flash program)
< PacketToProgramComplete
.
.
.
where > shows PC to STM32 USB comms
where < shows STM32 to PC USB comms
where ( ) shows Flash routine which disables IRQ while it is doing Flash activity
2014-04-11 04:41 AM
Hi,
The difference with my program is that the communication before the flashing is TO the PC. So I tried that to, by adding a few extra ''sendack()'' calls. But alas, no change.I now have:
FLASH_If_Lock();
// read and flash whole buffers
for (a=0; a<nmbr; a++) {
readblock(256);
sendack('A');
__disable_irq();
FLASH_If_UnLock();
flashadr = APPLICATION_ADDRESS + a*256;
printf(''I %d adr %x
'',a, flashadr);
prefl=flashadr;
if ((j=FLASH_If_Write((volatile uint32_t *)&flashadr, (uint32_t*) buf, (uint16_t) 256/4)) != 0)
{ __enable_irq(); printf(''FLASH_If_Write error block nr. %d
'',j); FLASH_If_Lock(); return j;}
FLASH_If_Lock();
__enable_irq();
// check flashing of buffer
for (i=0; i<256; i++) {
if (((char *)prefl)[i]!=buf[i]) printf(''Error %d %d %d
'',i, ((char *)prefl)[i], buf[i]);
else
// printf(''Data index %d, flash %d buf %d
'',i, ((char *)prefl)[i], buf[i]);
printf(''.'');if ((i%64) == 0) printf(''
'');
}
printf(''
'');
sendack('A');
}
But only the first round though the for loop works, and the there is an immediate flash error.
Interrupts are disabled throughout the entire flash operations, also when erasing.
So what can be the problem, considering the the non-usb version still works flawlessly.
I really am at a loss.
Sietse
2014-04-11 06:54 AM
The main reason it would fail is if you try to write to some non-erased memory. This can occur if the code re-enters, or there is other code writing to flash somewhere else.
printf(''I %d adr %x [%x]
'', a, flashadr, *((uint32_t *)flashadr));
Provide a complete diagnostic log for the failing condition.
2014-04-22 01:29 AM
Hallo,
after cleaning up the code in preparation of a good diagnostic log, I tried the code again, and now it works perfectly! I thought I didn't change anything relevant, but somehow I did. It is a bit unsatisfactory that i cannot find the exact cause, but the important thing is it works! Thanks for the help! Sietse