'BootloaderXMega.DMA.v1.2.Mar27.18.bas
'
$regfile = "xm192A3Udef.dat"
$hwstack = 80
$swstack = 80
$framesize = 80
$crystal = 32000000
Config Osc = Enabled , 32mhzosc = Enabled ' 32 MHz enabled
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1 'use 32 MHz
'=========================================
'
' --Select Bootloader Vector for uC
' and page length Maxwordbit
'
'=========================================
$loader = $18000 ' bootloader starts after the application
Const Maxwordbit = 7 ' Z7 is maximum bit '
'=========================================
'
' --Using DMA requires Interrupts to know when
' message/transaction is complete.
'
' Interrupt vector table (IVR) is moved into
' Bootloader memory space
'
'=========================================
$bootvector
Config Intvectorselection = Enabled
'=========================================
$timeout = 1600000 'we use a timeout
Config Watchdog = 8000 'to Restart in case something goes wrong with Bitwaits ...
Start Watchdog
Config Priority = Static , Vector = Application , Lo = Enabled , Hi = Enabled
'=========================================
'
' Select Bootloading USART for the uC
' and the necessary Baud Rate
'
'=========================================
Config Com7 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Open "COM7:" For Binary As #1
'Config Com3 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
'Open "COM3:" For Binary As #1
'Config Com1 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
'Open "COM1:" For Binary As #1
'=========================================
'
' Define LED if needed
'
'=========================================
Red_led Alias Porta.3
Config Red_led = Output
Red_led = 0
Const Maxword =(2 ^ Maxwordbit) * 2 '128
Const Maxwordshift = Maxwordbit + 1
Const Cnak = &H15
Const Cack = &H06
Const Ccan = &H18
Dim Bstatus As Byte , Bretries As Byte , Bmincount As Byte , Bblocklocal As Byte , Csum As Byte
Dim Spmcrval As Byte ' self program command byte value
Dim Z As Long 'this is the Z pointer word
Dim Wrd As Word , Page As Word 'these vars contain the page and word address
Dim J As Byte , I As Byte
'=========================================
'
' This array structure is a workaround for the
' problem with BASCOM not being able to
' handle multi-dimensional arrays in the
' Bootloader area.......................
'
'=========================================
Dim Tbuf(276) As Byte , Buf0(138) As Byte At Tbuf(1) Overlay , Buf1(138) As Byte At Tbuf(139) Overlay
Dim Buf_idxl(2) As Byte , Buf_idxh(2) As Word , W As Word , Wi As Word
Dim Bblock_idx(2) As Byte , Bcsum1_idx(2) As Byte , Bcsum2_idx(2) As Word
Buf_idxl(1) = 4 : Buf_idxl(2) = 142
Buf_idxh(1) = 131 : Buf_idxh(2) = 269
Bblock_idx(1) = 2 : Bblock_idx(2) = 140
Bcsum1_idx(1) = 3 : Bcsum1_idx(2) = 141
Bcsum2_idx(1) = 132 : Bcsum2_idx(2) = 270
Dim Dma_channel As Byte , Uart_rx As Byte , Buf_array As Byte
'=========================================
' ---Match the Bootloader USART here---
'
' Use the matching Trigger Source in the
' DMA Channel definition Trigger,
'
' and,
'
' Match the USART COM Port in SADR
'
'=========================================
'(
COM1 - Uart_c0 Portc.3 Portc.2 Serialin Or Serialin0
COM2 - UART_C1 PORTC.7 PORTC.6 SERIALIN1
COM3 - UART_D0 PORTD.3 PORTD.2 SERIALIN2
COM4 - UART_D1 PORTD.7 PORTD.6 SERIALIN3
COM5 - Uart_e0 Porte.3 Porte.2 Serialin4
COM6 - UART_E1 PORTE.7 PORTE.6 SERIALIN5
Com7 - Uart_f0 Portf.3 Portf.2 Serialin6
COM8 - Uart_f1 Portf.7 Portf.6 Serialin7
')
'UARTS:
'Trigsrc Base Value Group Configuration Description
'0x4b Usartc0 Usart C0 Dma Triggers Base Value
'0x4e Usartc1 Usart C1 Dma Triggers Base Value
'0x6b Usartd0 Usart D0 Dma Triggers Base Value
'0x6e Usartd1 Usart D1 Dma Triggers Base Value
'0x8b Usarte0 Usart E0 Dma Triggers Base Value
'0x8e Usarte1 Usart E1 Dma Triggers Base Value
'0xab Usartf0 Usart F0 Dma Triggers Base Value
'0xae Usartf1 Usart F1 Dma Triggers Base Value
'TRGSRC offset value Group Configuration Description
'0x00 RXC Receive complete
'0x01 Dre Data Register Empty
'=========================================
' ---Found speed to be faster if all 4 channels
' are used in circular pattern,
' versus using Round Robin
'
'=========================================
Config Dma = Enabled , Doublebuf = Disabled , Cpm = Ch0123 'use all channels in circular pattern
Dma_ctrl.7 = 0 'disable DMA at start
Config Dmach0 = Enabled , Burstlen = 1 , Chanrpt = Disabled , Tci = Hi , Eil = Off , Singleshot = Enabled , Trigger = &HAB , _
Btc = 132 , Dar = Transaction , Dam = Inc , Dadr = Varptr(buf0(1)) , Sar = Burst , Sam = Fixed , Sadr = Varptr(usartf0_data)
Config Dmach1 = Enabled , Burstlen = 1 , Chanrpt = Disabled , Tci = Hi , Eil = Off , Singleshot = Enabled , Trigger = &HAB , _
Btc = 132 , Dar = Transaction , Dam = Inc , Dadr = Varptr(buf1(1)) , Sar = Burst , Sam = Fixed , Sadr = Varptr(usartf0_data)
Config Dmach2 = Enabled , Burstlen = 1 , Chanrpt = Disabled , Tci = Hi , Eil = Off , Singleshot = Enabled , Trigger = &HAB , _
Btc = 132 , Dar = Transaction , Dam = Inc , Dadr = Varptr(buf0(1)) , Sar = Burst , Sam = Fixed , Sadr = Varptr(usartf0_data)
Config Dmach3 = Enabled , Burstlen = 1 , Chanrpt = Disabled , Tci = Hi , Eil = Off , Singleshot = Enabled , Trigger = &HAB , _
Btc = 132 , Dar = Transaction , Dam = Inc , Dadr = Varptr(buf1(1)) , Sar = Burst , Sam = Fixed , Sadr = Varptr(usartf0_data)
'=========================================
Dma_ch0_ctrla.7 = 0 'disable all channels at start
Dma_ch1_ctrla.7 = 0
Dma_ch2_ctrla.7 = 0
Dma_ch3_ctrla.7 = 0
On Dma_ch0 Dmach_rx_isr 'Interrupt MUST be cleared in ISR!!!!!
On Dma_ch1 Dmach_rx_isr 'Interrupt indicates complete TX of buffer
On Dma_ch2 Dmach_rx_isr
On Dma_ch3 Dmach_rx_isr
Enable Dma_ch0 , Hi 'use HI priority
Enable Dma_ch1 , Hi
Enable Dma_ch2 , Hi
Enable Dma_ch3 , Hi
Enable Interrupts
Rampz = 0
Bretries = 10 : Bmincount = 3 'try 10 times and want to get 123 at least 3 times
Do
Bstatus = Waitkey(#1) 'wait for the loader to send a byte
Toggle Red_led
Reset Watchdog
If Bstatus = 123 Then 'received value 123 ?
If Bmincount > 0 Then
Decr Bmincount
Else
Print #1 , Chr(bstatus);
Goto Loader 'yes so run bootloader
End If
Else 'received some other data
If Bretries > 0 Then 'retries left?
Bmincount = 10
Decr Bretries
Else
Goto Proces_reset 'goto the normal reset vector at address 0
End If
End If
Loop
Loader:
Do
Bstatus = Waitkey(#1)
Loop Until Bstatus = 0
Spmcrval = &H20 : Gosub Do_spm ' erase all app pages
Reset Watchdog
Do
Bblocklocal = 1
Dma_channel = 0
Buf_array = 1
Uart_rx = 0
Print #1 , Chr(cnak); ' firt time send a nack
Dma_ctrl.7 = 1 'enable DMA
Bstatus = Waitkey(#1) 'wait for statuse byte
Dma_ch0_ctrla = Dma_ch0_ctrla Or &B10010000 'start first Ch 0 RX buffer
Do
Select Case Bstatus
Case 1: ' start of heading, PC is ready to send
Bitwait Uart_rx.0 , Set
Reset Watchdog
Csum = 1
Csum = Csum + Tbuf(bblock_idx(buf_array))
Csum = Csum + Tbuf(bcsum1_idx(buf_array))
For W = Buf_idxl(buf_array) To Buf_idxh(buf_array)
Csum = Csum + Tbuf(w)
Next
If Bblocklocal = Tbuf(bblock_idx(buf_array)) And Csum = Tbuf(bcsum2_idx(buf_array)) Then 'are the blocks the same?
Print #1 , Chr(cack); 'acknowledge
Bstatus = Waitkey(#1) 'wait for status byte
If Bstatus = 1 Then
Select Case Dma_channel
Case 0
Dma_ch1_ctrla = Dma_ch1_ctrla Or &B10010000 'DMA RX in circular pattern
Dma_channel = 1
Case 1
Dma_ch2_ctrla = Dma_ch2_ctrla Or &B10010000
Dma_channel = 2
Case 2
Dma_ch3_ctrla = Dma_ch3_ctrla Or &B10010000
Dma_channel = 3
Case 3
Dma_ch0_ctrla = Dma_ch0_ctrla Or &B10010000
Dma_channel = 0
End Select
End If
Toggle Red_led
Gosub Writepage 'yes write page
Incr Bblocklocal 'increase local block count
If Dma_channel = 0 Or Dma_channel = 2 Then Buf_array = 1 Else Buf_array = 2 'switch buffer
Else
Dma_channel = 0
Print #1 , Chr(cnak); 'block does not match - resent block
Bstatus = Waitkey(#1) 'wait for status byte
If Bstatus = 1 Then
Dma_ch0_ctrla = Dma_ch0_ctrla Or &B10010000 'start over with channel 0
Buf_array = 1
End If
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
End If
Print #1 , Chr(cack); ' send ack and ready
Waitms 20
Goto Proces_reset
Case &H18 ' PC aborts transmission
Goto Proces_reset ' ready
Case Else
Exit Do ' no valid data
End Select
Uart_rx = 0
Loop
If Bretries > 0 Then 'attemptleft?
Waitms 1000
Decr Bretries 'decrease attempts
Else
Goto Proces_reset 'reset chip
End If
Loop
Proces_reset:
Red_led = 0
Rampz = 0
Goto _reset
End
Writepage:
For W = Buf_idxl(buf_array) To Buf_idxh(buf_array) Step 2 'we write 2 bytes into a page
R0 = Tbuf(w) 'store them into r0 and r1 registers
R1 = Tbuf(w + 1)
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
#endif
Nvm_cmd = Spmcrval
Cpu_ccp = &H9D
!spm
Do_spm_busy:
!lds r23, NVM_STATUS
!sbrc r23,7
!rjmp do_spm_busy
Return
Dmach_rx_isr:
If Dma_intflags.dma_channel = 1 Then
Dma_intflags.dma_channel = 1 'Clear Interrupt
Uart_rx.0 = 1 'set flag
End If
Return
|