View previous topic :: View next topic |
Author |
Message |
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Wed Oct 28, 2020 10:12 am Post subject: program is erased from flash |
|
|
Hello All, I hope, I wish, you are not affected by the pandemic,
I have several uC with XMEGA256U in vehicles and after several weeks many of them loose the program. The hardware is OK but only the bootloader is working; the program flash is completely erased.
Since they are connected to a host via RS485 I first thought that the host could be erasing the programm accidentally with the bootloader, but apparently this is not the case. I have a variable in NVM (FRAM) called "Update_state_ee" which is set =0 when programmed for the first time with Atmel Studio, it is set to =99 before erasing the FLASH in the Bootloader and is set =2 when a program is loaded successfully. Therefore, if it is 99 then I know that there has been an error while loading a programm. But all of them come with the FLASH program erased and Update_state_ee = 0 as if the Bootloader had never been executed.
I'm unable to reproduce the problem, any ideas about where to look?
Code: | Spmcrval = &H20 : Gosub Do_spm
Update_state_ee = 99
|
Code: | Case Eot: ' end of transmission , file is transmitted
If Wrd > 0 Then 'if there was something left in the page
Wrd = 0 'Z pointer needs wrd to be 0
Spmcrval = &H24 : Gosub Do_spm 'write page
End If
Gosub Send_ack
Waitms 20
Update_state_ee = 2 |
Encouragement, optimism and solidarity!
(BASCOM-AVR version : 2.0.8.3 ) |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Wed Oct 28, 2020 1:21 pm Post subject: |
|
|
-which lock bits have you set?
-do you use brown out option?
- how exactly can this NVRAM be written? is it i2c/spi ? would a jump be able to write a zero?
to prevent that a jump can erase you can add an extra step where you set a variable to a certain value and check it inside the loader. you also reset it when done.
Code: | if someFlag=57 then
someFlag=0
else
exit/ return
end if
|
from the datasheet :
Protection of NVM
To protect the flash and EEPROM memories from write and/or read, lock bits can be set to restrict access from external
programmers and the application software. Refer to “LOCKBITS – Lock Bit register” on page 30 for details on the
available lock bit settings and how to use them.
33.9 Preventing NVM Corruption
During periods when the VCC voltage is below the minimum operating voltage for the device, the result from a flash
memory write can be corrupt, as supply voltage is too low for the CPU and the flash to operate properly.To ensure that
the voltage is sufficient enough during a complete programming sequence of the flash memory, a voltage detector using
the POR threshold (VPOT+) level is enabled. During chip erase and when the PDI is enabled the brownout detector (BOD)
is automatically enabled at its configured level.
Depending on the programming operation, if any of these Vcc voltage levels are reached, the programming sequence
will be aborted immediately. If this happens, the NVM programming should be restarted when the power is sufficient
again, in case the write sequence failed or only partly succeeded. _________________ Mark |
|
Back to top |
|
|
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Wed Oct 28, 2020 4:02 pm Post subject: |
|
|
Thanks Mark!
I have not programmed any lock bits so there is no restriction to read or write the flash memory. The purpose of the Bootloader is that the host (another CPU device in the vehicle) can update the program of my device when needed.
I'm not using the brownout
Code: | $prog &HFF , &HFF , &H00 , &HBF , &H00 , &HFE , &HF0 'Fuses |
The NVRAM is the FM25L16B SPI chip. I'm using
Code: | $lib "fm25c256.lib" |
Quote: | would a jump be able to write a zero? |
I do not understand this question. The Bootloader is basically the BASCOM Bootloader, witn some changes in the initial handshaking and some flags and counters to register data for debuging.
It doesn't seem a corruption of Flash, all devices with this problem are excatly in the same state: Bootloader working, all FLASH erased (FF) from 00000 to 3FFFF as if it has been erased by the Bootloader routine Do_spm but that should not be the case because Update_state_ee is 0 and not of 99 or 2, and because the Host computer never tried to update my device, at least intentionally. |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Wed Oct 28, 2020 4:30 pm Post subject: |
|
|
i just try to think of a scenario where you can end up with erased flash.
when by some error there would be a jump to a part of the boot loader there could be a problem. but that would result in an empty page, not all of them.
it is a good thing you have NVRAM. Because it uses SPI it is unlikely it is getting altered by accident.
the procedure when/how it is written to 0 is however not clear.
you say after initial ISP programming you write it to 0.
it is probably FF when it is unused.
but this setting to 0. it that some code you call?
And could some odd crash jump to that code?
if there is some control protocol that can perform this, i would log all the data from the commands.
it also would be an option not to use 0 as a value but say 1.
that way you can check it better in this case.
So after ISP set it to 1.
in the boot procedure check if it is 1 or any other allowed value. if not, log some error, and exit
also check the NVRAM to see if it is erased or contains other odd values.
So more info is needed to determine the cause.
cars can give a lot of noise on the power. that is why there are special automotive versions of some processors. but then again i would expect the boot loader to be erased as well.
in any case, i would recommend to check the errata of the revision of the used chip. _________________ Mark |
|
Back to top |
|
|
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Wed Oct 28, 2020 7:44 pm Post subject: |
|
|
OK, I understand. I'm puzzled with this error; cannot think any scenario that can leave the devices in this state.
Unlike EEPROM, the FRAM (FM25L16B) is 0 by default.
The devices are programmed with Atmel Studio from an .elf file that contains the Bootloader and the program so the FRAM is in its original state when the device is first programmed. I'm not using 0 or FF for any flag. Anything done through the Bootloader should left the Update_state_ee flag to 99 or to 2. The fact that this flag is 0 tells me that the Bootloader has never been used to try to programm the chip of these devices. The rest of the FRAM is as it should be, mostly 0 except for the eram variables wich contain correct values; nothing that makes me think that anything could be wrong.
Quote: | And could some odd crash jump to that code? |
I'm setting Update_state_ee = 99 inmediately after the line that erases the FLASH (Spmcrval = &H20 : Gosub Do_spm) so any accidental jump to this line will result in erasing the program FLASH but also in Update_state_ee = 99, which is not the case.
Quote: | cars can give a lot of noise on the power. that is why there are special automotive versions of some processors. but then again i would expect the boot loader to be erased as well. |
it is installed in buses, which generate even more noise, but the HW is protected and there is nothing random about this error, they all end up in the same state, with the same part of the FLASH erased and no more issues at all.
Quote: | So more info is needed to determine the cause. |
I can only think that the problem is in the bootloader, here is the code:
Code: | $version 1 , 48 , 12
Const Print_monitor = 0 '0=don't print via COM1
'____________________________________________________________________________________
' BOOTLOADER Ei2
'
'|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'____________________________________________________________________________________
$regfile = "xm256a3Udef.dat"
'____________________________________________________________________________________
Const Boot_address_128 = &H10000 ' Para el ATxmega128A3
Const Boot_address_192 = &H18000 ' Para el ATxmega192A3
Const Boot_address_256 = &H20000 ' Para el ATxmega 256A3
$loader = Boot_address_256 ' bootloader starts after the application at this address
'____________________________________________________________________________________
$hwstack = 256
$swstack = 128
$framesize = 128
'____________________________________________________________________________________
' CONFIG SYSTEM CLOCK
Config Osc = Disabled , Extosc = Enabled , Range = 12mhz_16mhz , Startup = Xtal_16kclk , 32khzosc = Enabled , Pllosc = Enabled , Pllsource = Extclock , Pllmul = 2 ' 16x2=32MHz
Config Sysclock = Pll , Prescalea = 1 , Prescalebc = 1_1 ' 32/1=32 MHz
$crystal = 32000000
'|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| FUSES |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
' LockB Fus0 Fus1 Fus2 Fus3 Fus4 Fus5
$prog &HFF , &HFF , &H00 , &HBF , &H00 , &HFE , &HF0 ' Bootloader
' $prog &HFF , &HFF , &H00 , &HFF , &H00 , &HFE , &HF0 'Aplicacion
' LockB = FF => No locks
' Fus0 = FF These fuses can be used to set the default JTAG user ID for the device
' Fus1 = 00 Bit 7:4 – WDWPER[3:0]: Watchdog Window Timeout Period ||| Bit 3:0 – WDPER[3:0]: Watchdog Timeout Period
' Fus2 = BF &B1_0_1_111_11
' Bit 7 RFU - Bit 6 Reset vector, Bit 6=1=>Arrancar desde la aplicacion, Bit 6=0=> Arrancar desde el Bootloader,
' Bit5=TOSC SELECT Bit5=1=>XTAL Bit4:2=RFU Bit1:0=11=> BOD operation mode in sleep mode Disabled
' Fus3 = 00 = RFU
' Fus4 Bit7:5=Reserved | Bit4=0=>External Reset Disable!! poner Bit4=1 siempre | Bit3:2=11=>0 cycles delay StartupTime /=10=>RRFU /=01=>4 cycles /=00=>64 cycles (no usar nunca) | Bit1=1 Watchdog Timer Lock @ Bit0=1=> JTAG Disabled /=0=> JTAG Enabled
' ' Fus4 = FE = 111_1_11_1_0 => JTAG Enable. Lo deshabilitamos por software
' Start-up configuration = 0ms (OJO: si se pusiera en 64ms no se podría programar con el AVRISP MkII)
' External reset Enabled (sin esto no se podría programar!)
' Fus5 = F0 = 11_11_0_000 => BOD Disabled | Preserve EEPROM trhough chip erase | BOD Level 7
' Bit 7:6 Reserved
' Bit 5:4 BODACT Brown out detection mode of operation in Active mode:
' 00 Reserved
' 01 Sampled at 1KHz to save power
' 10 Enabled (continuosly monitored) Normal
' 11 Disabled
' Bit 3
' 0 EEPROM is preserved during chip erase
' 1 EEPROM is erased during chip erase
' Bit 2:0 BODLEVEL Brown out detection voltage level:
' 111 = Level0 = 1,6V
' 110 = Level1 = 1,8V
' 101 = Level2 = 2,0V
' 100 = Level3 = 2,2V
' 011 = Level4 = 2,4V
' 010 = Level5 = 2,6V
' 001 = Level6 = 2,8V
' 000 = Level7 = 3,0V
'|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
' VARIABLES
'____________________________________________________________________________________
'____________________________________________________________________________________
' VARIABLES SHARED WITH THE MAIN APP (SHOULD BE DECLARED IN THE SAME ORDER IN THE MAIN APP).
Dim Dummy_ee As Eram Word ' According to a data sheet from ATMEL, the first location in the EEPROM with address 0, can be overwritten during a reset so don't use it. NUEVO 09-AGO-2019
Dim Str_version_ee As Eram String * 13 'For instance V1.23.97. It is set in the main App
Dim Reset_cause_eram As Eram Byte
Dim Update_state_ee As Eram Byte
Dim Str_version_boot_ee As Eram String * 13 ' 'For instance V1.43.10.
Dim Ei_id_ee As Eram Word : Dim Ei_id As Word '
Dim Ei_lote_ee As Eram Word : Dim Ei_lote As Word '
'
'____________________________________________________________________________________
Dim Bstatus As Byte , Bretries As Byte , Bmincount As Byte , Bblock As Byte , Bblocklocal As Byte
Dim Bblock2 As Byte , Bcsum As Byte , Buf(128) As Byte , Csum As Byte
Dim J As Byte , Spmcrval As Byte ' self program command byte value
Dim Z As Long 'this will contain the 24 bit flash address pointer to be loaded into RAMPZ:Z
Dim Vl As Byte , Vh As Byte ' these bytes are used for the data values to be writen to flash
Dim Wrd As Word , Page As Word 'these vars contain the page and word address
Dim Str_version As String * 13
Dim Update_state As Byte '
Dim Str_version_boot As String * 17
'____________________________________________________________________________________
' COMMUNICATIONS
'Constants used in serial com
Const Cmd_start_update = 123
Const Cmd_send_version = 150
Const Cmd_start_app = 160
Const Cmd_send_version_boot = 151 ' Send Bootloader version to HOST
Const Cmd_ei_id = 152 ' Sent device ID and batch ID to HOST
Const Nak = &H15 ' 21
Const Ack = &H06 ' 6
Const Cancel = &H18 ' 24
Const Soh = 1 'Start of Header
Const Eot = 4 ' End of Transmission
Const Cr = 13 'Carriage Return
Const Tx2rx = 1 'ms Time we give to the HOST to chang from TX to RX before responding
' $Timeout for WIATKEY
$timeout = 300000 ' ~150ms
'|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
' HARDWARE
'____________________________________________________________________________________
' Flash size (KB) Page size (Words) Number of Pages Last App. Flash Adr. First Boot Flash Adr.
' ATxmega64A3 64 + 4 KB 128 256
' ATxmega128A3 128 + 8 KB 256 256 FFFF = 65535 => 10000 = 65.536 Words x2 = 131.072 Bytes/1024 = 128KB
' ATxmega192A3 192 + 8 KB 256 384 17FFF = 98303 => 18000 = 98.304 Words x2 = 196.608 Bytes /1024 = 192KB
' ATxmega256A3 256 + 8 KB 256 512 1FFFF = 131071 => 20000 =131.072 Words x2 = 262.144 Bytes /1024 = 256KB
Const Maxwordbit = 7 ' Z7 is maximum bit
Const Maxword =(2 ^ Maxwordbit) * 2 '=256 = Page Size in Words for ATxmega128A3, 192A3 y 256A3
Const Maxwordshift = Maxwordbit + 1 '= 8
'____________________________________________________________________________________
' PINES
Testpin_xt5 Alias Porta.5 : Config Porta.5 = Output
Testpin_xt4 Alias Porta.6 : Config Porta.6 = Output
Const Tx = 1
Const Rx = 0
Rs485_dir Alias Portf.4 : Config Portf.4 = Output : Rs485_dir = Rx
'____________________________________________________________________________________
' CONFIG INTERRUPTS
Disable Interrupts 'we do not use ints
'____________________________________________________________________________________
Disable Jtag
'____________________________________________________________________________________
' CONFIG FM25L16B FRAM
Fram_cs Alias Portc.4 : Const Fram_csp = 4 : Const Fram_csport = Portc : Config Portc.4 = Output
Fram_si Alias Portc.5 : Const Fram_sip = 5 : Const Fram_siport = Portc : Config Portc.5 = Output
Fram_sck Alias Portc.7 : Const Fram_sckp = 7 : Const Fram_sckport = Portc : Config Portc.7 = Output
' Fram_so Alias Portc.6 : Const Fram_sop = 6 : Const Fram_soport = Pinc : Config Pinc.6 = Input
Fram_so Alias Pinc.6 : Const Fram_sop = 6 : Const Fram_soport = Pinc
$eepromsize = &H800 ' Size, in bytes, in HEX of the FM25L16B memory H800 = 2048 = 2KBytes = 16Kbits
$lib "fm25c256.lib"
'____________________________________________________________________________________
Config Eeprom = Mapped 'Setup memory mode for EEPROM in XMEGA
'____________________________________________________________________________________
' RS485 (<->HOST)
Config Print6 = Portf.4 , Mode = Set ' BASCOM takes care of Rs485 switch from TX to RX and viceversa
Config Com7 = 38400 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Open "COM7:" For Binary As #7
'____________________________________________________________________________________
' COM1 (Monitor)
Const Bps_com1 = 230400
Config Com1 = Bps_com1 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Open "COM1:" For Binary As #1
'____________________________________________________________________________________
'|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
' BOOTLOADER CODE
'____________________________________________________________________________________
Wait 2 ' Needed to avoid sending anything twice due to double reset at power on
'____________________________________________________________________________________
' Bootloader version
Str_version_boot = Version(2) ' returns a string xxx.yyy.zzz
Str_version = Str_version_boot_ee ' temp
If Str_version_boot <> Str_version Then ' Save Boot Version in NVM only if it differs
Str_version_boot_ee = Str_version_boot
End If
'____________________________________________________________________________________
' Print App version
Str_version = Str_version_ee
Update_state = Update_state_ee
If Update_state = 99 Then ' Failure loading a new Appr
Str_version = "X" + Str_version
Else ' If it is 0 or 2, there is a correct App loaded
Str_version = "V" + Str_version
End If
Print #7 , Str_version ' Send App Version to HOST
'____________________________________________________________________________________
' HANDSHAKING
' - Waits up to 4s to receive a byte from the HOST
' - If nothing is received in that time, exit Bootloader to the main App
' - If a Byte is received, we expect to receive it Bmincount times with a timeout of ~400ms between bytes
' - If a bayte is not received 400ms after the previous byte, exit Bootloader to the main App
' - Each time a byte is received, test if it is equal to the previous received byte
' - If it is not equal, exit Bootloader to the main App
' - If the same byte is received Bmincount times, then:
' - If the byte is Cmd_start_update, returns Cmd_start_update to the HOST and calls Loader
' - If the byte is Cmd_send_version, returns the App version and goes back to handshaking
' - If the byte is Cmd_start_app o or any other byte, exit Bootloader to the main App
'____________________________________________________________________________________
Dim Rxbyte As Byte '
Dim Rxcmd As Byte '
Dim N_loops_max As Long
Const N_loops_to_first_byte = 26 ' ~4s (26xTIMEOUT=26x150ms)
Const N_loops_to_next_byte = 3 ' ~400ms
Dim N_loops_count As Long
'____________________________________________________________________________________
Handshaking:
N_loops_max = N_loops_to_first_byte
N_loops_count = 0
Bmincount = 4 'Número mínimo de veces que requerimos recibir --------- CFG
' un byte para darlo por bueno y procesarlo
Rxcmd = 0
' ---------------------------------
Do
Rxbyte = Waitkey(#7) ' Waits up to ~150ms (according to $timeout = 300000)
If Rxbyte > 0 Then '
N_loops_count = 0 ' Reset timeout to wait for next byte
N_loops_max = N_loops_to_next_byte ' Update timeout, to interbyte timeout
If Rxcmd = 0 Then ' First byte received
Rxcmd = Rxbyte ' save it in Rxcmd
Else
If Rxbyte = Rxcmd Then '
Bmincount = Bmincount - 1 '
If Bmincount = 0 Then ' If the same byte is received Bmincount times
Goto Procesar_cmd
End If
Else '
Goto Proces_reset
End If
End If
Else
N_loops_count = N_loops_count + 1
If N_loops_count >= N_loops_max Then
Goto Proces_reset
End If
End If
Loop
' ---------------------------------
' If we are here is because we have received a valid command
Procesar_cmd:
Select Case Rxcmd
Case Cmd_start_update
Waitms Tx2rx '
Printbin #7 , Cmd_start_update
Goto Loader
Case Cmd_send_version
Waitms Tx2rx '
Print #7 , Str_version ' xxx.yyy.zzz+CR+LF
Goto Handshaking
Case Cmd_start_app
' No need to do anything, exit Bootloader
Case Cmd_send_version_boot
Waitms Tx2rx
Str_version_boot = Version(2)
Print #7 , Str_version_boot
Goto Handshaking
Case Cmd_ei_id
Waitms Tx2rx
Ei_id = Ei_id_ee
Ei_lote = Ei_lote_ee
Print #7 , Ei_id ; "," ; Ei_lote
Goto Handshaking
End Select
'
Goto Proces_reset
'----------------------------------------------------------------------------------------------------------------------------------------------------
' LOADER
' This is the loader routine. It is a Xmodem-checksum reception routine
' The Host must send a binary file
' Xmodem Packet format:
' SOH
' Bblock = Packet number (starts with 1, not 0) 1 2 3 4 etc.
' Bblock2 = Negative Packet number (starts with 254, not 255) 254 253 252 251 etc
' 128 bytes (The last packet will be padded with FF if we do not have 128 bytes to send)
' Csum = Checksum of the data bytes (sum of all bytes in the packet, modulo 256)
' After de last packet, an single EOT character is sent.
' CANCEL = 24
' SOH = 1
' EOT = 4
'----------------------------------------------------------------------------------------------------------------------------------------------------
Loader:
' ------------------------
' Clear COM1 Buffer
Do
Bstatus = Waitkey(#7)
Loop Until Bstatus = 0
' Nota: Bstatus será = 0 cuando se cumpla el timeout de WAITKEY (unos 150ms)
' aunque no se haya recibido nada
' ------------------------
Spmcrval = &H20 : Gosub Do_spm ' Erase app flash completely
' ------------------------
Update_state_ee = 99
Bretries = 10 'number of retries
Do
Bblocklocal = 1
Csum = 0 'checksum is 0 when we start
Gosub Send_nak
Do
Bstatus = Waitkey(#7) 'wait for statuse byte
Select Case Bstatus
'---------------------------------------------------------------------------------------------------------------
Case Soh: ' start of heading, PC is ready to send
Csum = Soh ' Calculated checksum is 1
Bblock = Waitkey(#7) : Csum = Csum + Bblock ' Block number 1 2 3 4 etc : Update calculated checkum
Bblock2 = Waitkey(#7) : Csum = Csum + Bblock2 ' Negative block number 254 253 252 251 etc : Update calculated checkum
'New tested
Bblock2 = Bblock + Bblock2
If Bblock2 <> 255 Then 'block numbers do not match
Gosub Send_nak
End If
For J = 1 To 128 'get 128 bytes
Buf(j) = Waitkey(#7) : Csum = Csum + Buf(j)
Next
Bcsum = Waitkey(#7) 'get checksum byte
If Bblocklocal = Bblock Then 'are the blocks the same?
If Bcsum = Csum Then 'is the checksum the same?
Gosub Writepage 'yes go write the page
Gosub Send_ack
Incr Bblocklocal 'increase local block count
Else 'no match so send nak
Gosub Send_nak
End If
Else
Gosub Send_nak
End If
' -------------------------------------------------------------------------------------------------------------
Case Eot: ' end of transmission , file is transmitted
If Wrd > 0 Then 'if there was something left in the page
Wrd = 0 'Z pointer needs wrd to be 0
Spmcrval = &H24 : Gosub Do_spm 'write page
End If
Gosub Send_ack
Waitms 20
Update_state_ee = 2 ' Actualización correcta NUEVO 20-AGO-2019 ***
Goto Proces_reset
' -------------------------------------------------------------------------------------------------------------
Case Cancel: ' PC aborts transmission
Goto Proces_reset ' ready
Case Cmd_start_update : Exit Do 'was probably still in the buffer
Case 124 : Exit Do
Case Else
Exit Do
' no valid data
End Select
Loop
If Bretries > 0 Then 'attempte left?
Waitms 1000
Decr Bretries 'decrease attempts
Else
Goto Proces_reset 'reset chip
End If
Loop
'----------------------------------------------------------------------------------------------------------------------------------------------------
' WRITEPAGE
' Writes the 128 bytes received into one or more application flash pages and keeps the Page pointer to continue writing more pages the
' next time is called
' INPUTS:
' - Buf() Contains the 128 bytes
' - Page Application flash page to be writen. It is updated (incremented) only here in WRITEPAGE. It is 0 at the Bootloader start
' - Wrd Flash page buffer address where the first Word have to be stored. It is updated (incremented by 2 or set to 0) here in WRITEPAGE.
' It is set to 0 each time the flash page buffer is completely filled
' This routine:
' - 1 Gets two bytes from Buf()
' - 2 Writes the two bytes into the Page buffer
' Loads the two bytes into R0 and R1
' Executes an SPM instruction with the following parameters:
' Spmcrval = &H23 = Write word into the flash page buffer
' The word to write is composed by the bytes in R0 and R1; i.e., the bytes taken from Buf()
' The adress where the Word is writen in the page buffer is indicated in Wrd
' Increments Wrd in order to point to the next Word space in the page buffer to be written (¿Why increments by 2?)
' - 3 If the page buffer is full after writing the 2 bytes, it loads the page buffer into the next application flash page
' - Go again to step 1 until all bytes have been written into the page buffer
' - The next time it is called, it will start writing bytes at the next position of the page buffer (Wrd) and it will load
' pages to the application flash at the next page position (Page). The value of Wrd y Page should not be change outside WRITEPAGE
' (except at the begining to set them to zero)
'----------------------------------------------------------------------------------------------------------------------------------------------------
Writepage:
For J = 1 To 128 Step 2 'Write 128 Words
Vl = Buf(j) : Vh = Buf(j + 1) 'get Low and High bytes
! lds r0, {vl} 'store them into r0 and r1 registers
! lds r1, {vh}
Spmcrval = &H23 : Gosub Do_spm 'write word value into the flash page buffer at address indicated at Wrd
' #if Test_new = 0
Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used
' #endif
If Wrd = Maxword Then ' We have filled the complete flash page buffer
Wrd = 0 'Z pointer needs wrd to be 0
Testpin_xt5 = 1
Spmcrval = &H24 : Gosub Do_spm ' Write the flash page buffer into the flash page of the aplication flash at Page
Testpin_xt5 = 0
Page = Page + 1 'next page
End If
Next J
Return
'----------------------------------------------------------------------------------------------------------------------------------------------------
' DO_SPM
' INPUT:
' - Spmcrval Determines SPM action:
' Spmcrval = &H20: Erase the complete Flash Aplication Section
' Spmcrval = &H23: Load one Word of data into the flash page buffer
' Spmcrval = &H24: Write the flash page buffer into one flash page of the aplication flash
' - Page Application flash page to be writen (from page 0 to page 511 for ATxmega256A3)
' - Wrd Flash page buffer address where the Word have to be stored in the flash page buffer (with Spmcrval = &H23)
' Should be 0 when writing a page to the application flash memory (with Spmcrval = &H24)
' Can have any value when erasing the application flash memory (with Spmcrval = &H20)
' This routine:
' Loads the pointer variable Z into the extended Z register (R30, R31 and RAMPZ) to set an application flash address
' Executes action indicated by Spmcrval at the application flash address set
' Waits until execution has ended
'----------------------------------------------------------------------------------------------------------------------------------------------------
Do_spm:
Z = Page 'Make equal to Page (1 to 512 for ATxmega256A3)
Shift Z , Left , Maxwordshift 'Shift to proper place. Now the value of Page is in bytes 2 and 1 of variable Z
Z = Z + Wrd 'add word. Now the value of Wrd is in byte 0 of variable Z
'#if Test_new = 1
' Shift Z , Left , 1
'#endif
! lds r30,{Z} ' Put byte0 of variable Z into register R30 = Z-register low byte
! lds r31,{Z+1} ' Put byte1 of variable Z into register R31 = Z-register high byte
#if _romsize > 65536
! lds r24,{Z+2} ' Put byte2 of variable Z into register R24
! sts rampz,r24 ' Put the content of R24 into register RAMPZ
#endif
Nvm_cmd = Spmcrval ' Load the NVM CMD register with the desired command
Cpu_ccp = &H9D ' Enable execution of protected instruction SPM during the next 4 clock cycles
! spm ' Execute action indicated in Spmcrval at Page of application flash
Do_spm_busy: ' Wait until execution of instruction in ended
! lds r23, NVM_STATUS
! sbrc r23,7 'if busy bit is cleared skip next instruc tion (Nota: esto estaba precedido por una " ; " en lugar de por un " ' "
! rjmp do_spm_busy
Return
'----------------------------------------------------------------------------------------------------------------------------------------------------
' PROCESS_RESET
'----------------------------------------------------------------------------------------------------------------------------------------------------
Proces_reset:
Update_state = Update_state_ee
If Update_state <> 99 Then
Rampz = 0
Goto _reset
Else
Goto Handshaking
End If
'----------------------------------------------------------------------------------------------------------------------------------------------------
'----------------------------------------------------------------------------------------------------------------------------------------------------
' SEND NAK SEND ACK
'----------------------------------------------------------------------------------------------------------------------------------------------------
Send_ack:
Waitms Tx2rx
Printbin #7 , Ack
Return
'----------------------------------------------------------------------------------------------------------------------------------------------------
Send_nak:
Waitms Tx2rx
Printbin #7 , Nak
Return
'----------------------------------------------------------------------------------------------------------------------------------------------------
|
Last edited by hzz on Wed Oct 28, 2020 9:50 pm; edited 1 time in total |
|
Back to top |
|
|
Evert :-)
Joined: 18 Feb 2005 Posts: 2156
|
Posted: Wed Oct 28, 2020 8:08 pm Post subject: |
|
|
You can try placing one of the XMEGA256U in the car without connecting the RS485 bus.
With this you can maybe determine if the flash is erased by "the car" due bad power supply or something like that and not an command over RS485 _________________ www.evertdekker.com Bascom code vault |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Wed Oct 28, 2020 8:34 pm Post subject: |
|
|
when you share eeprom between the boot loader and the main application, you best use an INC file where you keep the eeprom variables. then include it in both programs.
This way you can ensure that when you write to an ERAM variable in the main app, it will have the same address as in the boot loader.
maybe there is some overlay variable that writes a zero?
so first i would check the RPT file for the boot loader and the main app and check if the locations have the same address and if there is no overlay used that might access that location.
Especial an ERAM array could be dangerous when wrong indexed.
then i would not trust that the FRAM chip is all zero by default. never assume a state unless you set it.
i do not know the exact procedure.
my personal preferred way is to program only the boot loader, then use it to program the main code and then again use the boot loader to program a second time.
since all is included in the elf file :
is the boot tested before the device is tested? i assume the boot is always performed at least once right?
since you test for 99 it will assume to be ok in all other cases.
i would reverse the test : test for OK and otherwise assume an error
in any case, to track such an error it is advised not to use 0 for update_state.
when you think the problem is in the boot loader, (you did not post the complete code) you need to consider if a jump/goto somewhere in the code, can make the entire flash empty.
i dont think the bascom boot loader can do that since it erase page by page and not the complete flash.
on the other hand in case of hw problem i would expect the boot code to be erased too. _________________ Mark |
|
Back to top |
|
|
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Wed Oct 28, 2020 10:31 pm Post subject: |
|
|
Quote: | You can try placing one of the XMEGA256U in the car without connecting the RS485 bus. |
Thanks. yes I have one like this and other without Bootloader, but it may take several weeks until if fails
Quote: | when you share eeprom between the boot loader and the main application, you best use an INC file where you keep the eeprom variables. then include it in both programs. This way you can ensure that when you write to an ERAM variable in the main app, it will have the same address as in the boot loader. |
Nice. I'll do it.
Quote: | maybe there is some overlay variable that writes a zero?
so first i would check the RPT file for the boot loader and the main app and check if the locations have the same address and if there is no overlay used that might access that location.
Especial an ERAM array could be dangerous when wrong indexed. |
OK. The Bootloader is OK. I will check the main app for this
Quote: | then i would not trust that the FRAM chip is all zero by default. never assume a state unless you set it.
i do not know the exact procedure.
my personal preferred way is to program only the boot loader, then use it to program the main code and then again use the boot loader to program a second time.
since all is included in the elf file :
is the boot tested before the device is tested? i assume the boot is always performed at least once right?
since you test for 99 it will assume to be ok in all other cases.
i would reverse the test : test for OK and otherwise assume an error
in any case, to track such an error it is advised not to use 0 for update_state. |
Yes. Actually I dont care about the default value; only use 2, 99 or any other.
The HOST computer is able to load a .bin file into my device. I test this only in a few units each time a new version is released. The rest of the devices never load the program with the bootloader (unless the HOST needs to do it in the vehicle, which have not happened yet). This is why I do not test for OK (I assume that the FRAM could have any value before using the Bootloader for the first time)
Quote: | when you think the problem is in the boot loader, (you did not post the complete code) you need to consider if a jump/goto somewhere in the code, can make the entire flash empty. i dont think the bascom boot loader can do that since it erase page by page and not the complete flash. |
I didn' notice the code was cut out. I edited my previous message to include the complete code now.
Only the Bootloader uses the SPM instruction therefore it should be impossible to erase the FLASH from other part of the code, shouldn't it? |
|
Back to top |
|
|
JC
Joined: 15 Dec 2007 Posts: 584 Location: Cleveland, OH
|
Posted: Wed Oct 28, 2020 11:16 pm Post subject: |
|
|
Quote: | I'm not using the brownout |
I think that you should enable the Brownout Detector!
Especially for a vehicle based micro.
When the vehicle starts up, ("cranks"), it starter motor draws a very high current, and the battery voltage drops during the crank interval.
It is kpossible that it is dropping below what your voltage regulator needs, and the power is crashing on your PCB!
If the Fuses, (I dind't check), are set to protect the bootlaoder, but not the rest of the memory, then a brownout glitch could leave the bootloader in place and erase the memory.
Also, as mentioned above, vehicles have very noisy power supplies, with both (+) and (-) voltage spikes on the V+ rail!
Your power supply likely needs "extra" input protection against these voltage transients.
Also, EVERY input signal to the micro's I/O pins that connects to anything else that is connected to the car's power supply also needs the input voltage transient protection.
If, for exampleyou had a sensor running off the car's power supply, then a voltage transient can get into your micro via the I/O pin ( s ) used to connect to the sensor.
Just a few thoughts for you to help track down the problem.
JC |
|
Back to top |
|
|
O-Family
Joined: 23 May 2010 Posts: 320 Location: Japan
|
Posted: Thu Oct 29, 2020 12:36 am Post subject: |
|
|
I also recommend enabling BOD.
When the AVR power supply rises and falls slowly, the CPU runs out of control when the power supply voltage drops below 1.6V, and the EEPROM and flash are unintentionally rewritten.
This is especially true if you have programs in your code that access EEPROM or flash.
It is experiencing this disappearing when BOD is enabled. |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Thu Oct 29, 2020 10:09 am Post subject: |
|
|
one other thing. i see you use the goto _RESET. This is not a real reset.
the xmega/xtiny have a soft reset option. in bascom you can use : RESET MICRO to do this (i did not check it that is in the published version already)
or do it manual:
Code: | Cpu_ccp = &HD8
Rst_ctrl = 1
|
That is a better way since it will reset all IO registers too.
since indeed only the boot loader is using SPM you could think that it is the only way to get flash erased. but since your entire flash is erased i do not think that is the case.
you could follow the flow of your code and think what can happen when code jumped into a line.
or in other words : when the main app would do a goto to the bootloader first line, what can happen, and then for the second line, etc.
i do not see any case where entire flash is erased.
but when SPM is loaded with a wrong value, for example to erase_APP (&H20) it would erase the entire flash.
as an extra test you could include code like :
Nvm_cmd = Spmcrval
if nvm_cmd=&H20 then
some error handler here
but as you also have a problem with NVM i am more convinced that a BOD will help better. i know it takes some current but it is best. _________________ Mark |
|
Back to top |
|
|
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Thu Oct 29, 2020 5:51 pm Post subject: |
|
|
Thnaks all for your inputs!
Brownout. Yes, you are all right. The reason I 'm not using it is a bad experiencie with fuses; I lost several boards from a bad fuse programming (not related to the external reset and not related to clock). I had no way to recover them so I just left the configuration that gave me no problems; and it was without Brownout.
Power input: Yes, very important. For your knoweledge, I have good experience with this circuit (actually the PTC should be lower current)
Mark, concerning the analysis you suggest, in the main app there is no way to go to the Bootloader; the only way is a reset.
You mention "but as you also have a problem with NVM " but I didn' find any problem with NVM. The NVRAM is working as expected in any case and there is nothing extrange in the FLASH either except a clean erase which in all cases is excaltly the main app, as if it had been done by the erase Bootloader routine "Spmcrval = &H20 : Gosub Do_spm"
You suggest changing the reset command. Now I have
Code: | Rampz = 0
Goto _reset
|
Should I substitute it for this?
Code: | Cpu_ccp = &HD8
Rst_ctrl = 1
| or this?
Code: | Rampz = 0
Cpu_ccp = &HD8
Rst_ctrl = 1
|
Rgards |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Thu Oct 29, 2020 8:24 pm Post subject: |
|
|
yes replace by :
Code: | Cpu_ccp = &HD8
Rst_ctrl = 1 |
clearing rampz was just to make sure it contained the right value.
you say you dont have a problem with NVRAM but you wrote : Quote: | Update_state_ee = 0 as if the Bootloader had never been executed. |
So the question : is the boot loader used as part of the test/production? And can we assume that it should be 2 ?
Or in case of a problem 99. But never 0.
Or do you ship the device without the boot loader tested? so it contains 0.
if the loader is used once, can we agree the value should be 2 or 99? but not 0 ? And when it is 0, you have a problem ?
or maybe i do not get it. _________________ Mark |
|
Back to top |
|
|
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Thu Oct 29, 2020 9:50 pm Post subject: |
|
|
OK, I didnt explain it clearly. The devices whose program FLASH was erased had never loaded the program using the Bootloader. They were programmed with Almel Studio from an .elf file containing the Bootloader and the program so it is normal that Update_state_ee = 0.
But, since the only way to erase the flash is loading something with the Bootloader, I was hoping the problem to be in an accidental execution of the Bootloader; however, this would have left Update_state with a valid value, 2 or 99, not 0.
I have done many loadings with the Bootloader for testing, complete and incomplete, and Update_state always takes the value 2 (or 99 if the loading was incomplete). Therefore I think the NVRAM is OK although the whole thing doesn't make sense.
Anyway, I will post any useful information about this problem if I identify it.
Many thanks! |
|
Back to top |
|
|
hzz
Joined: 20 Feb 2007 Posts: 314
|
Posted: Fri Oct 30, 2020 1:31 am Post subject: |
|
|
Code: | Cpu_ccp = &HD8
Rst_ctrl = 1 |
cannot be used to jump to the program; it jumps to the bootloader |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|