cancel
Showing results for 
Search instead for 
Did you mean: 

IAP programming errors

Sietse
Associate III
Posted on April 01, 2014 at 15:06

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
14 REPLIES 14
Sietse
Associate III
Posted on April 10, 2014 at 14:18

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.
chen
Associate II
Posted on April 10, 2014 at 15:12

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
Sietse
Associate III
Posted on April 11, 2014 at 13:41

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
Posted on April 11, 2014 at 15:54

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.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Sietse
Associate III
Posted on April 22, 2014 at 10:29

  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