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
chen
Associate II
Posted on April 01, 2014 at 15:52

Hi

It sounds like the Flash programming is failing.

Check the Flash Erase has worked. Check the whole sector is erased - it should read 0xff when erased.

If the program still fails on erase (or will not erase) - check the sectors are not 'locked' by the option byte

Sietse
Associate III
Posted on April 02, 2014 at 11:20

> It sounds like the Flash programming is failing.

> Check the Flash Erase has worked. Check the whole sector is erased - it should read 0xff when erased. Erasing works perfectly. > If the program still fails on erase (or will not erase) - check the sectors are not 'locked' by the option byte According to the output of the following code the option bytes are OK. Note that, until now I newer ran code on the target that uses the option bytes. And why does it work a fraction of the time?

// Prepare flash 
flashadr = APPLICATION_ADDRESS;
FLASH_If_Init();
FLASH_If_Erase(flashadr); // parameter not used! 

for (i = APPLICATION_ADDRESS; i < APPLICATION_ADDRESS + 0x20000; i++) {
if (*(char *)i != 0xff) {printf(''%x not properly erased!

'',i);}
}
FLASH_If_DisableWriteProtection();
if (!FLASH_If_GetWriteProtectionStatus()) printf(''Still some write protection bits on.

'');

None of the printf's are executed. After this code the flashing is tried as shown earlier. I also tried another discovery board, and it behave exactly the same: in about 1 out of 3 attempts the flashing works. In the others the contents of the flash remains 0xff. Anything else I can try? Regards, Sietse
chen
Associate II
Posted on April 02, 2014 at 11:42

Hi

''In the others the contents of the flash remains 0xff.

Anything else I can try?''

Go back to basics!

Decouple the serial download from the Flash programming

Write some test code to exercise (test/verify) the flash programming code you have written.

Try test routines to write a known/fixed pattern.

Then write a count into Flash.

Check the reference manual - what does it say the Flash programming procedure should be.

(Are you using the Standard Peripheral Library or have you written your own driver code?)

To get more help then this - you are going to have to show your code so that we can analyse it.

Sietse
Associate III
Posted on April 08, 2014 at 15:19

> Go back to basics!

Hello, Thats what I did. I first made a testprogram only using the LED's on the discovery board with the flash code. That works perfectly. Then I created a version that also used usart2 via syscalls/printf. This also works perfectly. The printf's are used for debugging and logging. I now have a version the also uses USB in 2 variants. One that is complete, but usually only works for small files to flash. The other has all usb code removed and flashes random data. This one always works perfectly. But as soon I do something with usb I am in trouble. My code can be found at

http://fwnhousing.rug.nl/stm-test

, both as a tar file and directly. Note that I use linux and the GNU tools for ARM embedded processors from Launchpad. It is created from the VCP example from STM32_USB-Host-Device_Lib_V2.1.0. - Discovery board has a 8 MHz crystal. - usart2 code is removed an a basic send/receive library is created in rtiostream_serial_stm32f4-usb.c - this has been extensively tested separately. - most unused code is removed For IAP we use flash_if.[ch] from STM32F4xx_AN3965_V1.0.0. The file app.c is the complete code, and app.c-nousb does not use usb. The file app.c is to be used with the program sendcode on the host-side, which sends the data to be flashed from a file. The file app.c-nousb runs without a PC program, it flashes and checks the result. Below the relevant part of app.c is included. The complete code can be found on the website. Flashing works perfectly, and usb communication works perfectly, but the combination fails. For example a small file of 200 byte can usually be flashed, but files larger than 391 bytes never. This is fairly reproducable. I really could use some help :( (more details on the website in

http://fwnhousing.rug.nl/stm-test/STM32_USB-Host-Device_Lib_V2.1.0-test/Project/USB_Device_Examples/Flash/ReadmeFirst

) Sietse

int32_t getcode(void) {
int a, i, j; 
size_t sizeRecv, sizeSend, length;
char buf[1024], sendbuf[10];
unsigned char check, ch2;
size_t flashadr, prefl, flashsize, nmbr, rest;
void readblock(uint32_t length) {
int i=0;
while (i<
length
) {
j
= 
rtIOStreamRecv
(1,buf+i, length-i, &sizeRecv);
i += j;
}
if (i != length) printf(''readblock error %d 

'', i);
// checksum
for (
i
=
0
; i<length; i++) {
check += (unsigned char)buf[i];
}
}
check
= 
0
;
// read info packet
i
=
0
;
while (i< 21) {
j
= 
rtIOStreamRecv
(1,buf+i, 21-i, &sizeRecv);
i += j;
}
length = (buf[17]<<24) + (buf[18]<<16) + (buf[19]<<8) + buf[20] ;
// reply of the info packet
flashsize
= 
1024
*100; // enough fot the moment
if ((buf[0] != 0x2) || length > flashsize ) {
sendbuf[0] = 'E'; // Error message
j = rtIOStreamSend(1,sendbuf,1,&sizeSend);
return -1;
} else {
sendbuf[0] = 'A'; // ack
j = rtIOStreamSend(1,sendbuf,1,&sizeSend);
if (j != 1) printf(''Send ack error

'');
}
nmbr = length/1024;
rest = length%1024;
printf(''number of whole pages %d, rest %d

'',nmbr, rest);
// Prepare flash
flashadr = APPLICATION_ADDRESS;
printf(''flashadr %x

'', flashadr);
FLASH_If_Init();
if(FLASH_If_Erase(APPLICATION_ADDRESS)) { printf(''FLASH_If_Erase error

''); return -1; }
else
printf(''Erase done

'');
for (i = APPLICATION_ADDRESS; i < USER_FLASH_END_ADDRESS + 1; i++) {
if (*(char *)i != 0xff) {printf(''Address %x not properly erased!

'',i);}
}
// read and flash whole buffers
for (a=0; a<nmbr; a++) {
readblock(1024);
flashadr = APPLICATION_ADDRESS + a*1024;
printf(''I %d adr %x

'',a, flashadr);
prefl=flashadr;
if ((j=FLASH_If_Write((volatile uint32_t *)&flashadr, (uint32_t*) buf, (uint16_t) 1024/4)) != 0) { printf(''FLASH_If_Write error block nr. %d

'',j); FLASH_If_Lock(); return j;}
// check flashing of buffer
for (i=0; i<1024; 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(''

'');
}
// the rest 
if (rest != 0) {
readblock(rest);
// make sure we flash also the very last byte
flashadr = APPLICATION_ADDRESS + a*1024;
printf(''II %d adr %x

'',a, flashadr);
prefl=flashadr;
if ((j=FLASH_If_Write((volatile uint32_t *)&flashadr, (uint32_t*) buf, (uint16_t) rest/4+1)) != 0) { printf(''FLASH_If_Write error rest %d, addr %x

'',j,flashadr); FLASH_If_Lock(); return j;}
// check flashing rest
for (i=0; i<rest; i++) {
if (((char *)prefl)[i]!=buf[i]) printf(''Error %d %d %d 

'',i, ((char *)prefl)[i], buf[i]);
else
// printf(''Data index %d, flash %x buf %x 

'',i, ((char *)prefl)[i], buf[i]);
printf(''.'');if ((i%64) == 0) printf(''

'');
}
printf(''

'');
}
// Lock flash again
FLASH_If_Lock();
// simple checksum (we do this after flashing ...
ch2=check; // to save proper value
readblock(1);
printf(''Checksum is %x should be %x
'',ch2, buf[0]);
if (ch2 != buf[0]) {
printf(''Checksum error.

'');
sendbuf[0] = 'E'; // foutmelding;
j = rtIOStreamSend(1,sendbuf,1,&sizeSend);
return -4;
} else {
sendbuf[0] = 'A'; // ack
j = rtIOStreamSend(1,sendbuf,1,&sizeSend);
// Test flash data
printf(''Data written:

'');
for (i = APPLICATION_ADDRESS-8; i < APPLICATION_ADDRESS + 16; i++) {
printf(''%x '',*(char *)i);
}
printf(''

'');
return 0;
}
}

Posted on April 08, 2014 at 15:39

GNU/GCC is significantly less prone, but with large local variable allocations you have to be very attentive to stack size.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chen
Associate II
Posted on April 08, 2014 at 18:00

Hi

Sorry, have not had a chance to look at your code.

''I now have a version the also uses USB in 2 variants.

One that is complete, but usually only works for small files to flash.

The other has all usb code removed and flashes random data.

This one always works perfectly. But as soon I do something with usb I am in trouble.''

From this description I deduce that there is a problem between the USB interrupts and writing to Flash.

Most Flash writing routines do NOT like interrupts going off when writing to flash, so they disable them.

The USB library relies heavily on IRQs.

''One that is complete, but usually only works for small files to flash.''

This suggests that you can do file transfer and then write to Flash but for small 'chucks'

Try developing a protocol which runs over the CDC/VCP which allows you to send a large file in 'chunks' (ie break up a large file into smaller sections).

Sietse
Associate III
Posted on April 09, 2014 at 13:29

Thanks for the responses.

In function FLASH_If_Write I did:

 __disable_irq;
 t=FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data+i));
 __enable_irq;

But this did not make any difference. Is this the correct place to disable the interrupts? What does the reference manual RM0090 says about this? I only can find in par. 3.6: Any attempt to read the Flash memory on STM32F4xx while it is being written or erased, causes the bus to stall. Does that influence interrupts at all? Writing a single 32 bit word does not take that long that stalling the bus (and interrupts?) is a problem? So if the reference manual is the spec of the chip I do not see why interrupts should be a problem. Or am I missing something. I also tried using smaller chunks, and change the protocol that no usb communication is needed during flashing, something like:

 while (not_ready) {
read_chunk();
flashit();
send_request_chunk;
 }

But then I get flash errors from the 2-nd of 3-rd chunk. Thanks in advance, Sietse PS.Does the stm32f4 contain an MPU? According the de CMSIS code it does in the sense that the MPU register is define by way of

 #if (__MPU_PRESENT == 1)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
 #endif

see core_cm4.h So MPU is defined, but there is no mentioning of it in the reference manual. Is CMSIS configured wrongly?
Sietse
Associate III
Posted on April 09, 2014 at 14:15

When a flash error occurs FLASH_SR == 0xC0

So PGSERR and PGPERR

chen
Associate II
Posted on April 09, 2014 at 17:34

''I only can find in par. 3.6:

Any attempt to read the Flash memory on STM32F4xx while it is being written or erased, causes the bus to stall. Does that influence interrupts at all?'' Yes, when an IRQ go off, the vector table will be access (Flash read) and the ISR will be executed (Flash read). That is why generally during Flash programming, the IRQs are disabled. ''I also tried using smaller chunks, and change the protocol that no usb communication is needed during flashing, something like:'' The while loop is in the wrong place. The code needs to stop USB activity while Flash programming is going on. I do not think the while loop is correct where it is. There needs to be a guard before the

read_chunk();

There needs to be a guard before the

send_request_chunk;

The sending side must NOT send the next chunk until it is told it is OK to do so.