Технический форум по робототехнике.
EdGull » 20 дек 2009, 20:57
Т.к. у нас с MibbiM появилась острая необходимость в перепрошивке роботов по радиоканалу потому что мы с ним уманались лазить под стол и перетыкивать программаторский разъем, решили всё таки добить бутлоадер.
Данный код проверял на МиниБоте 2.1 т.е. с закороченными Rx и Tx, при получениие P пишет Programming.
Т.е. всё Ок
- Код: Выделить всё • Развернуть
$regfile = "m32DEF.dat"
$crystal = 7372800
$baud = 115200
$hwstack = 64
$swstack = 64
$framesize = 64
'светодиоды
Config Pinc.6 = Output : Led Alias Portc.6 : Led = 0
Dim S As Byte
Dim Tmp1 As Byte
Waitms 500
For Tmp1 = 1 To 255
Print "Wait P for programming -" ; Tmp1
Waitms 100
S = Inkey()
If S = 80 Then
Print ""
Print "Programing!!!"
'Jmp $3800
Wait 3
End If
Next
Do
Led = 1 : Waitms 250
Led = 0 : Waitms 250
Loop
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
' B O O T L O A D E R
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'The fusebit FE is set so that we have 512 bytes for the boot code
'Only a part is used btw
'But it sets the bootstart address to 1E00 hex. which happens to be in the M161 too
'The $boot diretive will bind the code below into address specified
'This will generate large files with FFFF opcode from the end of the normal program to the start
'of the bootcode
'Note that the bootloader is written in ASM. This because the bootloader may not call routines from
'the main program. Why? Because during programming they get erased!
'$boot = $3800
'no interrupts are allowed during bootloader programming
Disable Interrupts
'Standard Intel hex file can be sent
':10 0000 00 0C 94 2400189500001895000018950000 25
':00 0000 01 FF
' size , address,record type, data, checksum
'The sample bootloader does not use the checksum
'The same baudrate is used as the main program is using
'but we can change it here when we like. Just unremark the next line and/or change it
'But take in mind that the bootloader sender must use the same baud rate !!!
'Baud = 19200
clr r18 ; word counter for written data
clr r23 ; page counter
rcall _erase_page ; erase first page
_read_lines:
rcall _rec_line ; get line into SRAM pointed by X
ldi r26,$61 ; point to start of line
clr r27
ld r24,x+ ; get char in r24
rcall _hex2number ; convert result in r17
ld r24,x+
rcall _hex2number2 ; convert second char , r17 holds the number of hex pairs to get
mov r19,r17 ; number of entries
tst r19
brne _readnext ; not the end record
rjmp _write_last_page ; final line so write the last page
_readnext:
adiw xl,6 ; point to first pair
_readnextpair:
ld r24,x+ ; get char in r24
rcall _hex2number ; convert result in r17
ld r24,x+
rcall _hex2number2 ; convert second char , r17 holds the data
mov r0,r17 ; save in r0
dec r19 ; adjust pair data counter
ld r24,x+ ; get char in r24
rcall _hex2number ; convert result in r17
ld r24,x+
rcall _hex2number2 ; convert second char , r17 holds the data
mov r1,r17 ; save data
rcall _write_page ; write into page buffer
cpi r18,64 ; page is 128 bytes is 64 words
breq _writeit ; write page since it is full
_lbl1:
dec r19 ; adjust data pair
brne _readnextpair ; more data
rjmp _read_lines ; next line
_writeit:
rcall _save_page ; save page
rcall _erase_page ; erase next page
Rjmp _lbl1 ; continue
_write_last_page:
rcall _save_page ; save last page
rjmp _exit_page ; exit needs a reset
' get 1 byte from serial port and store in R24
_recbyte:
Sbis USR, 7 ; Wait for character
rjmp _recbyte
in r24, UDR ; get byte
Ret
'get one line from the serial port and store in location pointed by X
_rec_line:
ldi r26,$60 ; point to first location in SRAM
clr r27
_rec_line5:
sbis usr,5
rjmp _rec_line5
ldi r24, 63 ; ?
!out udr,r24 ; show ? so we know we can send next line
_rec_line1:
rcall _recbyte ; get byte
cpi r24,13 ; enter?
breq _rec_line2 ; yes ready
st x+,r24 ; no so store in sram buffer
rjmp _rec_line1 ; next byte
_rec_line2:
clr r24 ; string terminator
st x,r24
ret
' convert HEX byte in r24 into bin value , on exit byte in r17
_hex2number:
clr r17
_hex2number4:
Subi R24,65 ; subtract 65
Brcc _hex2number3 ; in case carry was cleared
Subi R24,249 ; not
_hex2number3:
Subi R24,246
Add R17,R24 ; add to accu
ret
';called for the second byte
_hex2number2:
Lsl R17 ; shift data
Lsl R17
Lsl R17
Lsl R17
rjmp _hex2number4 ; handle the conversion
'page address in z7-z13
_erase_page:
mov r31,r23 ; page address
lsr r31 ; get z8-z13 shift ls bit into carry
clr r30
ror r30 ; get z7
ldi r24,3 ; page erase command
rcall _do_spm
clr r16 ; page cleared indicator
ret
_write_page:
mov r31,r23 ; page address z8-z13
lsr r31
clr r30
ror r30 ; carry to z7
mov r24,r18 ; word address buffer counter
lsl r24
add r30,r24 ; z1-z6
ldi r24,1 ; buffer fill
rcall _do_spm
inc r18
ret
_save_page:
'z0-z6 must be 0
'z7-z13 is the page address
'r0 and r1 are ignored
mov r31,r23
lsr r31
clr r30
ror r30
ldi r24,5 ; write page
rcall _do_spm
clr r18 ; page word address counter
inc r23 ; page counter
ret
_exit_page:
in r24,spmcr
sbrs r24,asb
rjmp _exit_page1
ldi r24,17
rcall _do_spm
rjmp _exit_page
_exit_page1:
End
'; execute spm instruction , data in R24
_do_spm:
sbic eecr, eewe
rjmp _Do_spm
! Out Spmcr , R24
spm
!.obj Ffff ; needs FFFF according to datasheet
nop
_wait_spm:
In r24,spmcr
sbrc r24, 0
rjmp _wait_spm
ret
End
кулер 23 » 20 дек 2009, 21:19
Надо будет попробовать
EdGull » 20 дек 2009, 21:24
нечего пока пробывать, пока еще не готово
и всё будет заточено под радиоканал, которого если я не ошибаюсь у тебя нет.
avr123.nm.ru » 20 дек 2009, 21:33
Можно подробней чуть расказать как им пользоваться ? В чем обсобенность "под радиоканал" ?
SMT » 20 дек 2009, 23:13
То есть вот так можно периодически ожидать получения в UART специального символа и перейти на адрес бутлоадера?
EdGull » 20 дек 2009, 23:43
2Авр небольшие особенности связанные с архитектурой МиниБота, для конечного пользоввателя это будет прозрачно, поэтому интереса не представляет.
2SMT Естественно. Всегда можно перейти на нужную метку.
Только мы в будущем будем посылать не символ, а служебное слово-команду.
Наверное это будет "Prog"
EdGull » 07 янв 2010, 20:27
текущие версии нижепример основного кода.
важным является переход к бутзагрузчику, осуществляемый кодом:
- Код: Выделить всё • Развернуть
If S = "boot" Then
Goto &H3C00
End If
- Код: Выделить всё • Развернуть
$regfile = "m32DEF.dat"
$crystal = 7372800
$baud = 115200
$hwstack = 64
$swstack = 64
$framesize = 64
' Светодиод для индикации процесса. Мигающий красный - прошивка, горящий зеленый - успешное завершение
Config Pinc.4 = Output : Led_r1 Alias Portc.4 : Led_r1 = 0
Config Pinc.5 = Output : Led_g1 Alias Portc.5 : Led_g1 = 0
Config Pinc.6 = Output : Led_r2 Alias Portc.6 : Led_r2 = 0
Config Pinc.7 = Output : Led_g2 Alias Portc.7 : Led_g2 = 0
Config Pind.2 = Input : Button Alias Pind.2
Dim S As String * 20
Dim Arr(20) As Byte At S Overlay
Dim Substr As String * 18 At Arr(3) Overlay
' процедуры
Declare Sub Printf(byval S As String)
Dim Text As String * 50
S = "abcd"
Wait 3
Do
Input S Noecho
If S = "boot" Then
Toggle Led_g2
Goto &H3C00
End If
Call Printf( "")
Mid(s , 1 , 1) = "'"
Call Printf(s)
Loop
Sub Printf(byval S As String)
Local Cnt As Byte
Local Len1 As Byte
Local Buf As String * 1
Reset Ucsrb.rxen
Len1 = Len(s)
For Cnt = 1 To Len1
Bitwait Ucsra.udre , Set ' ожидаю момента, когда можно загрузить новые данные
Buf = Mid(s , Cnt , 1)
Udr = Asc(buf)
Next
Bitwait Ucsra.udre , Set
Udr = 13
Bitwait Ucsra.udre , Set
Udr = 10
Set Ucsra.txc ' очищаю флаг прерывания
Bitwait Ucsra.txc , Set ' жду пока передатчик не передаст весь пакет (из внутреннего буфера, не UDR)
Set Ucsrb.rxen
End Sub
MiBBiM » 07 янв 2010, 20:27
PC-часть, написана на Borland Delphi 7, екзешник нужно подсовывать баскому вместо нативного stk500.exe
- Вложения
-
- stk500.rar
- екзек
- (172.64 КиБ) Скачиваний: 5
-
- stk500-emu.rar
- сырцы
- (20.38 КиБ) Скачиваний: 5
Последний раз редактировалось
MiBBiM 07 янв 2010, 21:18, всего редактировалось 1 раз.
EdGull » 07 янв 2010, 20:55
boot
- Код: Выделить всё • Развернуть
'----------------------------------------------------------------
' (c) 2010
'@Author: mibbim
'@Description: Бутлоадер для Мега32 робота МиниБот
'-----------------------------------------------------------------
' !!!!!!!ТОЛЬКО ДЛЯ МЕГА32!!!!!!
$prog &HFF , &HBD , &HCA , &H00 ' generated. Take care that the chip supports all fuse bytes.
$crystal = 7372800 '8000000
$baud = 115200 '38400 'this loader uses serial com
' Не использовать буферизованный ввод, ибо прерывания ЗАПРЕЩЕНЫ
$regfile = "m32def.dat"
' процедуры
Declare Sub Chr_print(byval S As Byte)
' mega32
$loader = $3c00 ' 1024 слова занимает бут
Const Maxwordbit = 6 ' Z6 is maximum bit
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Const Maxword =(2 ^ Maxwordbit) * 2 ' 128
Const Maxwordshift = Maxwordbit + 1
' Используемые переменные
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 ' Z указатель
Dim Vl As Byte , Vh As Byte ' Два байта будут использованы для данных
Dim Wrd As Word , Page As Word ' Адреса страницы и слова
Dim Bkind As Byte , Bstarted As Byte
Disable Interrupts ' Прерывания не используются!!!
'wait 100 msec sec
'We start with receiving a file. The PC must send this binary file
' Константы для управляющих символов
Const Nak = &H15
Const Ack = &H06
Const Can = &H18
' Светодиод для индикации процесса. Мигающий красный - прошивка, горящий зеленый - успешное завершение
Config Pinc.4 = Output : Led_r1 Alias Portc.4 : Led_r1 = 0
Config Pinc.5 = Output : Led_g1 Alias Portc.5 : Led_g1 = 0
Config Pinc.6 = Output : Led_r2 Alias Portc.6 : Led_r2 = 0
Config Pinc.7 = Output : Led_g2 Alias Portc.7 : Led_g2 = 0
$timeout = 3500000 ' Таймаут для выхода
' Если лоадер сбоит, увеличиваем значение таймаута
Bretries = 10 ' Пробуем 5 раз
Testfor123:
Bstatus = Waitkey() 'wait for the loader to send a byte
If Bstatus = 123 Then ' "{", 0x7B
Call Chr_print(ack)
Bkind = 0 ' Переход в режим FLASH лодера, Bkind = 0
Goto Loader
Elseif Bstatus = 124 Then ' "|"
Call Chr_print(ack)
Bkind = 1 ' Переход в режим EPPROM лодера, Bkind = 1
Goto Loader
Elseif Bstatus <> 0 Then
Decr Bretries
If Bretries <> 0 Then Goto Testfor123 ' Неверный символ, пробуем ещё раз
End If
For J = 1 To 10 ' Простая индикация того, что мы переходим по нормальному ресет вектору 0x0000
Toggle Led_r1 : Waitms 100
Next
Goto _reset ' Переход по адресу 0x0000 на начало программы
' Процедура лоадера, реализует Xmodem-checksum
Loader:
Do
Bstatus = Waitkey()
Loop Until Bstatus = 125 ' Очистка буфера
For J = 1 To 3 ' Простая индикация того, что мы переходим по нормальному ресет вектору 0x0000 (!!!) или таки прошли в бутлоадер??
Toggle Led_r1 : Waitms 50
Next
If Bkind = 0 Then ' Если в режиме FLASH программатора
Spmcrval = 3 : Gosub Do_spm ' стирание страницы по адресу Z
Spmcrval = 17 : Gosub Do_spm ' разрешить доступ к RWW памяти (стирание буфера)
End If
Bretries = 10 ' Количество попыток
Do
Bstarted = 0 ' Мы ещё не стартовали
Csum = 0 ' Чексумма = 0 при старте
Call Chr_print(nak) ' Первый раз шлем nack
Do
Bstatus = Waitkey() ' Ждем статус-байт
Select Case Bstatus
Case 1: ' Начало заголовка, PC готов слать данные
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 And Bcsum2 = Csum Then 'are the blocks and the checksum the same?
Gosub Writepage 'yes go write the page
Call Chr_print(ack) 'acknowledge
Else
Call Chr_print(nak) 'blocks do not match, so send nack
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
Call Chr_print(ack) ' send ack and ready
Led_g1 = 1 ' simple indication that we are finished and ok
Led_r1 = 0
Waitms 20
Goto _reset ' start new program
Case Can: ' PC aborts transmission
Goto _reset ' ready
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
'(
Spmcrval:
1 - запись регистровой пары R0 : R1 в Z
3 - стирание страницы по адресу Z
5 - запись страницы по адресу Z
17 - разрешить доступ к Rww памяти(стирание буфера)
')
'write one or more pages
Writepage:
If Bkind = 0 Then ' FLASH лоадер
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 Led_r1 : Waitms 10 : Toggle Led_r1 '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
Sub Chr_print(byval S As Byte)
Reset Ucsrb.rxen
Bitwait Ucsra.udre , Set
Udr = S
Set Ucsra.txc ' очищаю флаг прерывания
Bitwait Ucsra.txc , Set ' жду пока передатчик не передаст весь пакет (из внутреннего буфера, не UDR)
Set Ucsrb.rxen
End Sub
MiBBiM » 09 янв 2010, 00:00
как-то я забыл упомянуть, что это все действительно работает
необходимые настройки:
где путь до stk500.exe - это путь до моей прожки, ком-порт соответственно порт, на котором висит минибот.
войти в режим бутлодера можно несколькими способами:
- первый и самый брутальный - перезапуском питания минибота.
- второй: программа до начала прошивки шлет комбинацию "boot"+chr(13), соответственно где-то в прошивке её можно обрабатывать и делать goto
- третий: любой ваш способ (например, по прерыванию от кнопки), конструкция перехода выглядит так: goto &H3C00
после входа в режим бута жмем F4 и вуаля
- 09.011.png (3.73 КиБ) Просмотров: 3695
setar » 09 апр 2010, 18:27
Бутлоадер работает только по радиоканалу,
или через USB тоже будет работать ?
EdGull » 09 апр 2010, 21:07
по уарту, а вот как он туда попадет через USB или по радиоканалу это тебе решать
setar » 12 апр 2010, 10:51
есть предложение в подобных темах держать перезаписываемым и прикреплённым первый пост, в котором самое свежее чтобы было, а ниже историю как обычно
Myp » 14 май 2010, 18:48
так господа
а в первый минибот это вкорячить можно надеюсь?
galex1981 » 14 май 2010, 22:06
Конечно можно! Бутлоадер реализуется для МК а не для версии минибота