$LOADER

From MCS Wiki AVR
Jump to: navigation, search

Contents

Action

Instruct the compiler to create a boot loader at the specified address.

Can be used for all AVR that support a boot loader like ATMEGA and ATXMEGA chips.

 

Syntax

$LOADER = address

 

Remarks

address

The address where the boot loader is located. You can find this address in the data sheet.

 

A lot of AVR microcontrollers are configured such that it is possible to use a boot

loader able to receive firmware updates and to reprogram the Flash memory on

demand.

These AVR which support boot loader have a so called boot section.

Normally a chip will start at address 0 when it resets.

This is also called the reset vector.

Chips that have a boot section, split the flash memory in two parts. The boot section is a small part of the normal flash and by setting a fuse bit you select that the chip runs code at the boot sector when it resets instead of the normal reset vector.

 

The Program Flash memory space of ATXMEGA chips is also divided into Application and Boot sections. Both sections

have dedicated Lock Bits for setting restrictions on write or read/write operations.

 

ATXMEGA Program Flash memory parts:

1. Application Section for application code
2. Application Table Section for application code or data storage
3. Boot Section for application code or bootloader code

 

 

Notice.jpg
You need to set the fuse bits so the chip jump to the boot loader address at reset (BOOTRST) !

 

Some chips also have fuse bits to select the size of the boot loader (e.g. 1024 words, 2048 words, 4096 words)

 

The boot loader start address depends also on the boot size.

You can find following information in the data sheet of the device (example for ATMEGA644):

 

Boot Size

Boot Loader Flash Section

Boot Reset Address (Start Boot Loader Section)

512 words

0x7E00 - 0x7FFF

$loader = $7E00

1024 words

0x7C00 - 0x7FFF

$loader = $7C00

2048 words

0x7800 - 0x7FFF

$loader = $7800

4096 words

0x7000 - 0x7FFF

$loader = $7000

 

For ATXMEGA chips like ATXMEGA32A4 the boot section is part of the Flash Program Memory.

You can find following information in the data sheet of the ATXMEGA device under Flash Program Memory

(example for ATxmega16A4 .....ATxmega128A4):

 

Chip

Boot Loader Flash Section

Boot Reset Address (Start Boot Loader Section)

ATxmega16A4

0x2000 - 0x7FFF

$loader = &H2000

ATxmega32A4

0x4000 - 0x47FF

$loader = &H4000

ATxmega64A4

0x8000 - 0x87FF

$loader = &H8000

ATxmega128A4

0x10000 - 0x10FFF

$loader = &H10000

 

 

Notice.jpg
An external programmer is needed to program the boot loader into the chip. After the fuse bits are set and the boot loader is programmed you do not need the external programmer anymore for this chip (except you want to change the fuse bits).

 

The MCS boot loader sample is a serial boot loader that uses the serial port (USART).

 

With ATXMEGA or with ATMEGA with more then one USART you can choose which USART (COM port) should be used with the boot loader.

 

For example you can use COM7 with an ATXMEGA:

 
Config Com7 = 57600 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8       
Open "COM7:" For Binary As #7
 

Notice.jpg
When using another UART as COM1 do not forget to add the Interface number (in this example #7) to all the Serial IO functions like Waitkey(#7or   Print #, Chr(bstatus); in the boot loader example
 

The boot loader uses the X-modem checksum protocol to receive the data. (XModem protocol (packet size = 128))

Most terminal emulators can send X-modem checksum.

 

The Boot loader sample can upload both normal flash programs and EEPROM images.

The Boot loader sends a byte with value of 123 to the AVR Boot loader. This boot loader program then enter the boot loader or will jump to the reset vector (0000) to execute the normal flash program.

 

When it receives 124 instead of 123, it will upload the EEPROM.

When you select a BIN file the flash will be uploaded. When you select an EEP file, the EEPROM will be uploaded.

 

The following sample is written so it supports all chips with a boot section.

 

How you need to use this ATMEGA boot loader  example program:

 

1. Uncomment the Chip type and Const Loaderchip you want to use (for example ATMEGA644)

 

$regfile = "m644def.dat"
'$regfile = "m644Pdef.dat"
Const Loaderchip = 644

 

2. Double check the baud rate and COM port you want to use
3. Compile the boot loader example
4. Program it into the chip with an external programmer like AVR ISP MKII
5. Select MCS Bootloader from programmer (select the right COM Port and baud rate)
6. compile a new program or example for this chip
7. reset the chip

 

 

Ways to reset the AVR chip:

 

Hardware reset:

1. Hardware Reset switch/button to GND (manual)
2. MCS Bootloader can set and reset the DTR or RTS line of serial COM port which can be used to reset the AVR (automatic)

 

Software Reset:

1. Reset with Watchdog Timer (e.g. setting the Watchdog to 16ms, start it and let it time out)
2. With GOTO command (e.g. when ATMEGA644 is used the boot loader start at $7c00 ($loader = $7c00).

 Then  you  can use:

 GOTO &H7c00

  to jump to the boot loader start.

3. With ATXMEGA there is a special register to reset the ATXMEGA via software. See also topic ATXMEGA
4. With MCS Bootloader you can send one or several ASCII character to reset the chip like with string "boot_me". In this case the "boot_me" must be detected in your main application on the AVR and then use for example Watchdog or GOTO to reset the chip.

 

The boot loader is written to work at a baud rate of 57600. This baud rate works for most chips that use the internal oscillator. But it is best to check it first with a simple program. When you use a crystal you might even use a higher baud rate.

You can change this by changing the baud rate in the boot loader example (take care to use also the same baud rate in the boot loader application (e.g. MCS Bootloader) on the PC side)

 

Now make a new test program and compile it. Press F4 to start the MCS bootloader. You now need to reset the chip so that it will start the boot loader section. The boot loader will send a byte with value of 123 and the Bascom boot loader receives this and thus starts the loader process.

 

There will be a stand alone boot loader available too. And the sample will be extended to support other AVR chips with boot section too.

 

Notice.jpg
 There is a $BOOT directive too. It is advised to use $LOADER as it allows you to write the boot loader in BASIC.

 

Important.jpg
You can not use interrupts in your boot loader program as the interrupts will point to the reset vector which is located in the lower section of the flash. When you start to writing pages, you overwrite this part.

 

Notice.jpg
Take care when Watchdog is enabled by fuse bits and using a boot loader. You need to reset or deactivate the Watchdog in the boot loader example otherwise the firmware upload could be terminated by watchdog reset !

 

Notice.jpg
If you want to analyze the MCU Control and Status Register to know which reset source caused the reset you need to save this register already in the boot loader example because this register will be cleared and it will be always 0 when you check it at start of your application.

 

Notice.jpg
When you use a boot loader it will use space from the available flash memory. The compiler does not know if you use a boot loader or not. When your program exceeds the available space and runs into the boot sector space, it will overwrite the boot loader.

The $LOADERSIZE directive will take the boot loader size into account so you will get an error when the target file gets too big.

 

 

Encryption/Decryption with Bootloader:

You can use for example AES or XTEA ( XTEADECODEXTEAENCODE ) in combination with boot loader examples.

There is an AES with boot loader and AVR-DOS example in the ...BASCOM-AVR\SAMPLES\boot     folder (xmega_dos_boot_AES.zip).

 

See also

$BOOT , $LOADERSIZEMCS Bootloader

 

 

There is an example for ATMEGA chips and for ATXMEGA Chips:

 

ATMEGA Example:


'----------------------------------------------------------------
' (c) 1995-2009, MCS
' Bootloader.bas
' This sample demonstrates how you can write your own bootloader
' in BASCOM BASIC
' VERSION 2 of the BOOTLOADER. The waiting for the NAK is stretched
' further a bug was resolved for the M64/M128 that have a big page size
'-----------------------------------------------------------------
'This sample will be extended to support other chips with bootloader
'The loader is supported from the IDE
 
$crystal = 8000000
'$crystal = 14745600
$baud = 57600 'this loader uses serial com
'It is VERY IMPORTANT that the baud rate matches the one of the boot loader
'do not try to use buffered com as we can not use interrupts
 
'possible return codes of the PC bootloader.exe
' -6005 Cancel requested
' -6006 Fatal time out
' -6007 Unrecoverable event during protocol
' -6008 Too many errors during protocol
' -6009 Block sequence error in Xmodem
' -6016 Session aborted
 
 
 
 
'$regfile = "m8def.dat"
 
'Const Loaderchip = 8
'$regfile = "m168def.dat"
'Const Loaderchip = 168
 
'$regfile = "m16def.dat"
'Const Loaderchip = 16
 
'$regfile = "m32def.dat"
'Const Loaderchip = 32
 
'$regfile = "m88def.dat"
'Const Loaderchip = 88
 
'$regfile = "m162def.dat"
'Const Loaderchip = 162
 
'$regfile = "m8515.dat"
'Const Loaderchip = 8515
 
'$regfile = "m128def.dat"
'Const Loaderchip = 128
 
'$regfile = "m64def.dat"
'Const Loaderchip = 64
 
'$regfile = "m2561def.dat"
'Const Loaderchip = 2561
 
 
'$regfile = "m2560def.dat"
'Const Loaderchip = 2560
 
'$regfile = "m329def.dat"
'Const Loaderchip = 329
 
'$regfile = "m324pdef.dat"
'Const Loaderchip = 324
 
 
$regfile = "m644def.dat"
'$regfile = "m644Pdef.dat"
Const Loaderchip = 644
 
 
#if Loaderchip = 88 'Mega88
 $loader = $c00 'this address you can find in the datasheet
 'the loader address is the same as the boot vector address
 Const Maxwordbit = 5
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 168 'Mega168
 $loader = $1c00 'this address you can find in the datasheet
 'the loader address is the same as the boot vector address
 Const Maxwordbit = 6
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 32 ' Mega32
 $loader = $3c00 ' 1024 words
 Const Maxwordbit = 6 'Z6 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
#if Loaderchip = 8 ' Mega8
 $loader = $c00 ' 1024 words
 Const Maxwordbit = 5 'Z5 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
#if Loaderchip = 161 ' Mega161
 $loader = $1e00 ' 1024 words
 Const Maxwordbit = 6 'Z6 is maximum bit '
#endif
#if Loaderchip = 162 ' Mega162
 $loader = $1c00 ' 1024 words
 Const Maxwordbit = 6 'Z6 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 8515 ' Mega8515
 $loader = $c00 ' 1024 words
 Const Maxwordbit = 5 'Z6 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
 Osccal = &HB3 ' the internal osc needed a new value
#endif
 
#if Loaderchip = 64 ' Mega64
 $loader = $7c00 ' 1024 words
 Const Maxwordbit = 7 'Z7 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 128 ' Mega128
 $loader = &HFC00 ' 1024 words
 Const Maxwordbit = 7 'Z7 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 2561 ' Mega2561
 $loader = &H1FC00 ' 1024 words
 Const Maxwordbit = 7 'Z7 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
 
#if Loaderchip = 2560 ' Mega2560
 $loader = &H1FC00 ' 1024 words
 Const Maxwordbit = 7 'Z7 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 16 ' Mega16
 $loader = $1c00 ' 1024 words
 Const Maxwordbit = 6 'Z6 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 329 ' Mega32
 $loader = $3c00 ' 1024 words
 Const Maxwordbit = 6 'Z6 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
#if Loaderchip = 324 ' Mega32
 $loader = $3c00 ' 1024 words
 Const Maxwordbit = 6 'Z6 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
 
#if Loaderchip = 644 ' Mega644P
 $loader = $7c00 ' 1024 words
 Const Maxwordbit = 7 'Z7 is maximum bit '
 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
#endif
 
 
Const Maxword =(2 ^ Maxwordbit) * 2 '128
Const Maxwordshift = Maxwordbit + 1
Const Cdebug = 0 ' leave this to 0
 
#if Cdebug
 Print Maxword
 Print Maxwordshift
#endif
 
 
 
'Dim the used variables
Dim Bstatus As Byte , Bretries As Byte , Bblock As Byte , Bblocklocal As Byte
Dim Bcsum1 As Byte , Bcsum2 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 is the Z pointer word
Dim Vl As Byte , Vh As Byte ' these bytes are used for the data values
Dim Wrd As Word , Page As Word 'these vars contain the page and word address
Dim Bkind As Byte , Bstarted As Byte
'Mega 88 : 32 words, 128 pages
 
 
 
Disable Interrupts 'we do not use ints
 
 
'Waitms 100 'wait 100 msec sec
'We start with receiving a file. The PC must send this binary file
 
'some constants used in serial com
Const Nak = &H15
Const Ack = &H06
Const Can = &H18
 
'we use some leds as indication in this sample , you might want to remove it
Config Pinb.2 = Output
Portb.2 = 1 'the stk200 has inverted logic for the leds
Config Pinb.3 = Output
Portb.3 = 1
 
$timeout = 400000 'we use a timeout
'When you get LOADER errors during the upload, increase the timeout value
'for example at 16 Mhz, use 200000
 
Bretries = 5 'we try 5 times
Testfor123:
#if Cdebug
 Print "Try " ; Bretries
 Print "Wait"
#endif
Bstatus = Waitkey() 'wait for the loader to send a byte
#if Cdebug
 Print "Got "
#endif
 
Print Chr(bstatus);
 
If Bstatus = 123 Then 'did we received value 123 ?
 Bkind = 0 'normal flash loader
 Goto Loader
Elseif Bstatus = 124 Then ' EEPROM
 Bkind = 1 ' EEPROM loader
 Goto Loader
Elseif Bstatus <> 0 Then
 Decr Bretries
 If Bretries <> 0 Then Goto Testfor123 'we test again
End If
 
For J = 1 To 10 'this is a simple indication that we start the normal reset vector
 Toggle Portb.2 : Waitms 100
Next
 
#if Cdebug
Print "RESET"
#endif
Goto _reset 'goto the normal reset vector at address 0
 
 
'this is the loader routine. It is a Xmodem-checksum reception routine
Loader:
#if Cdebug
 Print "Clear buffer"
#endif
Do
 Bstatus = Waitkey()
Loop Until Bstatus = 0
 
 
For J = 1 To 3 'this is a simple indication that we start the normal reset vector
 Toggle Portb.2 : Waitms 50
Next
 
If Bkind = 0 Then
 Spmcrval = 3 : Gosub Do_spm ' erase the first page
 Spmcrval = 17 : Gosub Do_spm ' re-enable page
End If
 
 
Bretries = 10 'number of retries
 
Do
 Bstarted = 0 ' we were not started yet
 Csum = 0 'checksum is 0 when we start
Print Chr(nak); ' firt time send a nack
Do
 
 Bstatus = Waitkey() 'wait for statuse byte
 
 Select Case Bstatus
 Case 1: ' start of heading, PC is ready to send
 Incr Bblocklocal 'increase local block count
 Csum = 1 'checksum is 1
 Bblock = Waitkey() : Csum = Csum + Bblock 'get block
 Bcsum1 = Waitkey() : Csum = Csum + Bcsum1 'get checksum first byte
 For J = 1 To 128 'get 128 bytes
 Buf(j) = Waitkey() : Csum = Csum + Buf(j)
 Next
 Bcsum2 = Waitkey() 'get second checksum byte
 If Bblocklocal = Bblock Then 'are the blocks the same?
 If Bcsum2 = Csum Then 'is the checksum the same?
 Gosub Writepage 'yes go write the page
 Print Chr(ack); 'acknowledge
 Else 'no match so send nak
 Print Chr(nak);
 End If
 Else
 Print Chr(nak); 'blocks do not match
 End If
 Case 4: ' end of transmission , file is transmitted
 If Wrd > 0 And Bkind = 0 Then 'if there was something left in the page
 Wrd = 0 'Z pointer needs wrd to be 0
 Spmcrval = 5 : Gosub Do_spm 'write page
 Spmcrval = 17 : Gosub Do_spm ' re-enable page
 End If
 ' Waitms 100 ' OPTIONAL REMARK THIS IF THE DTR SIGNAL ARRIVES TO EARLY
 Print Chr(ack); ' send ack and ready
 
 Portb.3 = 0 ' simple indication that we are finished and ok
 Waitms 20
 Goto _reset ' start new program
 Case &H18: ' PC aborts transmission
 Goto _reset ' ready
 Case 123 : 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 _reset 'reset chip
End If
Loop
 
 
 
'write one or more pages
Writepage:
If Bkind = 0 Then
 For J = 1 To 128 Step 2 'we write 2 bytes into a page
 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 = 1 : Gosub Do_spm 'write value into page at word address
 Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used
 If Wrd = Maxword Then ' page is full
 Wrd = 0 'Z pointer needs wrd to be 0
 Spmcrval = 5 : Gosub Do_spm 'write page
 Spmcrval = 17 : Gosub Do_spm ' re-enable page
 
 Page = Page + 1 'next page
 Spmcrval = 3 : Gosub Do_spm ' erase next page
 Spmcrval = 17 : Gosub Do_spm ' re-enable page
 End If
 Next
 
Else 'eeprom
 For J = 1 To 128
 Writeeeprom Buf(j) , Wrd
 Wrd = Wrd + 1
 Next
End If
Toggle Portb.2 : Waitms 10 : Toggle Portb.2 'indication that we write
Return
 
 
Do_spm:
Bitwait Spmcsr.0 , Reset ' check for previous SPM complete
Bitwait Eecr.1 , Reset 'wait for eeprom
 
 Z = Page 'make equal to page
Shift Z , Left , Maxwordshift 'shift to proper place
 Z = Z + Wrd 'add word
lds r30,{Z}
lds r31,{Z+1}
 
#if _romsize > 65536
 lds r24,{Z+2}
 sts rampz,r24 ' we need to set rampz also for the M128
#endif
 
Spmcsr = Spmcrval 'assign register
spm 'this is an asm instruction
nop
nop
Return
 
 
'How you need to use this program:
'1- compile this program
'2- program into chip with sample elctronics programmer
'3- select MCS Bootloader from programmers
'4- compile a new program for example M88.bas
'5- press F4 and reset your micro
' the program will now be uploaded into the chip with Xmodem Checksum
' you can write your own loader.too
'A stand alone command line loader is also available
 
 
'How to call the bootloader from your program without a reset ???
'Do
' Print "test"
' Waitms 1000
' If Inkey() = 27 Then
' Print "boot"
' Goto &H1C00
' End If
'Loop
 
'The GOTO will do the work, you need to specify the correct bootloader address
'this is the same as the $LOADER statement.

ATXMEGA Example:

'----------------------------------------------------------------
' (c) 1995-2009, MCS
' BootloaderXmega32A4.bas
' This sample demonstrates how you can write your own bootloader
' in BASCOM BASIC for the XMEGA
'-----------------------------------------------------------------
'The loader is supported from the IDE
$crystal = 32000000 ' xmega128 is running on 32 MHz
$regfile = "xm32a4def.dat"
$lib "xmega.lib" ' add a reference to this lib
 
'first enabled the osc of your choice
Config Osc = Disabled , 32mhzosc = Enabled 'internal 2 MHz and 32 MHz enabled
 
'configure the systemclock
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1 ' we will use 32 MHz and divide by 1 to end up with 32 MHz
 
 
$loader = &H4000 ' bootloader starts after the application
 
Config Com1 = 57600 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 ' use USART C0
'COM0-USARTC0, COM1-USARTC2, COM2-USARTD0. etc.
 
 
Config Portc.3 = Output 'define TX as output
Config Pinc.2 = Input
 
Const Maxwordbit = 7 ' Z7 is maximum bit '
Const Maxword =(2 ^ Maxwordbit) * 2 '128
Const Maxwordshift = Maxwordbit + 1
Const Cdebug = 0 ' leave this to 0
 
 
 
'Dim the used variables
Dim Bstatus As Byte , Bretries As Byte , Bmincount As Byte , Bblock As Byte , Bblocklocal As Byte
Dim Bcsum1 As Byte , Bcsum2 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 is the Z pointer word
Dim Vl As Byte , Vh As Byte ' these bytes are used for the data values
Dim Wrd As Word , Page As Word 'these vars contain the page and word address
 
 
Disable Interrupts 'we do not use ints
 
'We start with receiving a file. The PC must send this binary file
 
'some constants used in serial com
Const Nak = &H15
Const Ack = &H06
Const Can = &H18
 
 
$timeout = 300000 'we use a timeout
'When you get LOADER errors during the upload, increase the timeout value
'for example at 16 Mhz, use 200000
 
Bretries = 5 : Bmincount = 3 'we try 10 times and want to get 123 at least 3 times
Do
 Bstatus = Waitkey() 'wait for the loader to send a byte
 
If Bstatus = 123 Then 'did we received value 123 ?
 If Bmincount > 0 Then
 Decr Bmincount
 Else
 Print Chr(bstatus);
 Goto Loader ' yes so run bootloader
 End If
Else 'we received some other data
 If Bretries > 0 Then 'retries left?
 Bmincount = 3
 Decr Bretries
 Else
 Rampz = 0
 Goto Proces_reset 'goto the normal reset vector at address 0
 End If
End If
Loop
 
 
 
 
'this is the loader routine. It is a Xmodem-checksum reception routine
Loader:
Do
 Bstatus = Waitkey()
Loop Until Bstatus = 0
 
 Spmcrval = &H20 : Gosub Do_spm ' erase all app pages
 
 
Bretries = 10 'number of retries
 
Do
 Csum = 0 'checksum is 0 when we start
Print Chr(nak); ' firt time send a nack
Do
 
 Bstatus = Waitkey() 'wait for statuse byte
 
 Select Case Bstatus
 Case 1: ' start of heading, PC is ready to send
 Incr Bblocklocal 'increase local block count
 Csum = 1 'checksum is 1
 Bblock = Waitkey() : Csum = Csum + Bblock 'get block
 Bcsum1 = Waitkey() : Csum = Csum + Bcsum1 'get checksum first byte
 For J = 1 To 128 'get 128 bytes
 Buf(j) = Waitkey() : Csum = Csum + Buf(j)
 Next
 Bcsum2 = Waitkey() 'get second checksum byte
 
 If Bblocklocal = Bblock Then 'are the blocks the same?
 
 If Bcsum2 = Csum Then 'is the checksum the same?
 Gosub Writepage 'yes go write the page
 Print Chr(ack); 'acknowledge
 Else 'no match so send nak
 Print Chr(nak);
 End If
 Else
 Print Chr(nak); 'blocks do not match
 End If
 Case 4: ' 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
 Print Chr(ack); ' send ack and ready
 Waitms 20
 Goto Proces_reset
 Case &H18: ' PC aborts transmission
 Goto Proces_reset ' ready
 Case 123 : 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
 
 
 
'write one or more pages
Writepage:
 For J = 1 To 128 Step 2 'we write 2 bytes into a page
 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 value into page at word address
 Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used
 If Wrd = Maxword Then ' page is full
 Wrd = 0 'Z pointer needs wrd to be 0
 Spmcrval = &H24 : Gosub Do_spm 'write page
 Page = Page + 1 'next page
 End If
 Next
Return
 
 
Do_spm:
 Z = Page 'make equal to page
Shift Z , Left , Maxwordshift 'shift to proper place
 Z = Z + Wrd 'add word
lds r30,{Z}
lds r31,{Z+1}
 
#if _romsize > 65536
 lds r24,{Z+2}
 sts rampz,r24 ' we need to set rampz also for the M128
#endif
 
Nvm_cmd = Spmcrval
Cpu_ccp = &H9D
spm 'this is an asm instruction
Do_spm_busy:
 lds r23, NVM_STATUS
 sbrc r23,7 ;if busy bit is cleared skip next instruc tion
 rjmp do_spm_busy
Return
 
 
 
Proces_reset:
Rampz = 0
Goto _reset 'start at address 0

Languages   English Deutsch  
Personal tools
Namespaces
Variants
Actions
Navigation
In other languages
Language