Hallo, hat es schon mal jemand geschafft diese User Row zur Laufzeit zu schreiben bzw. zu ändern? Fan
Hi Leute, ich schiebe den Beitrag mal hoch, weil ich ebenfalls Probleme habe die User Signature Row zu beschreiben. Ich verwende die Dateien sp_driver.h bzw. sp_driver.s aus dem "AVR1316 - XMEGA Self-programming" Paket. void GLOBALS_Write_User_Sig (void) { SP_EraseFlashBuffer(); //Flash Puffer löschen SP_WaitForSPM(); //Wait for NVM to finish SP_EraseUserSignatureRow(); //Erase the user signature row SP_WaitForSPM(); //Wait for NVM to finish SP_LoadFlashWord(0, 0x1234); //load one word into page buffer SP_WaitForSPM(); //Wait for NVM to finish SP_WriteUserSignatureRow(); //Write to the user signature row SP_WaitForSPM(); //Wait for NVM to finish } Leider ohne Erfolg. Wenn ich const char userdata[] _attribute_ ((section (".user_signatures"))) ="Hello User Signatures"; in mein Programm einfüge, werden die entspr. Daten in der User Sig. abgelegt. Sie lassen sich auch auslesen. result=SP_ReadUserSignatureByte(0); //Read byte from user signature NVM_CMD=NVM_CMD_NO_OPERATION_gc; //Noop/Ordinary LPM Wobei beim Lesen LPM statt SPM verwendet wird. Hat jemand eine Idee wo der Fehler liegt? Gruß Micha
Also ich hatte das damals als ich den bootloader fuer http://matrixstorm.com/avr/avrstick/ programmierte hingekommen. Ich sehe mal im source nach und poste dann gl. wieder. MfG
Okay ganze "gleich wieder" 2 Tage spaeter: Das folgende wird sehr technisch, eine bessere Nutzersichtbeschreibung gibt es hier: http://matrixstorm.com/avr/avrstick/#msdbootloader Zum Ausprobieren der API gibt es code hier: http://matrixstorm.com/avr/avrstick/#msdbootloader_api Die eigentliche Schreibfunktion fuer die User Signature Row sieht so aus: (Die Funktion habe ich der Uebersicht halber aufgeraeumt und einige Makros fuer bedingtes Uebersetzten entfernt.)
1 | int16_t usermap_write(const uint8_t in_blockBuffer[BLOCKVMA_BLOCKSIZE], const uint32_t in_BlockAddress) { |
2 | if (in_BlockAddress==0) { |
3 | __do_spm(0, NVM_CMD_ERASE_USER_SIG_ROW_gc, 0xff); |
4 | return flash_updatepage_Ex(&spmfunc, in_blockBuffer, 0, NVM_CMD_READ_USER_SIG_ROW_gc, NVM_CMD_WRITE_USER_SIG_ROW_gc); |
5 | }
|
6 | return 0; |
7 | }
|
"__do_spm" verannlast dabei eine universelle Schreibfunktion innerhalb der apipage des bootloaders. "__do_spm" ist eine Api-funktion, welche die register dafuer mappt:
1 | void __do_spm(const uint_farptr_t flashword_ptr, const uint8_t nvmCommand, const uint16_t dataWord) { |
2 | uint8_t sreg_backup = CPU_SREG; |
3 | cli(); |
4 | #if (USE_SPMINTEREFACE_MAGICVALUE != 0)
|
5 | __do_spm_complex(((uint32_t)APIPAGE__bootloader__do_spm_magicblock)>>1, flashword_ptr, nvmCommand, dataWord, (uint32_t)USE_SPMINTEREFACE_MAGICVALUE); |
6 | #else
|
7 | /* DANGER: ignores platform protection by magical value */
|
8 | # warning USE_SPMINTEREFACE_MAGICVALUE is zero - platform protection deactivated!
|
9 | __do_spm_complex(((uint32_t)APIPAGE__bootloader__do_spm)>>1 , flashword_ptr, nvmCommand, dataWord, (uint32_t)USE_SPMINTEREFACE_MAGICVALUE); |
10 | #endif
|
11 | CPU_SREG=sreg_backup; |
12 | }
|
In der apipage passiert dann das eigentliche schreiben:
1 | /*
|
2 | bootloader__do_spm: (currently within last page: 0x21e00)
|
3 |
|
4 | ;disable interrupts (if enabled) before calling!
|
5 | ;you may also want to disable wdt, since this routine may busy-loop
|
6 | ;==================================================================
|
7 | ;-->INPUT:
|
8 | ;#if HAVE_SPMINTEREFACE_MAGICVALUE
|
9 | ;magicvalue in r23:r22:r21:r20
|
10 | ;#endif
|
11 | ;NVM.CMD (command code) will be (was spmcr on ATmega) register: r18
|
12 | ;MCU dependend RA(MPZ should be transfered within register: r11
|
13 | ;lo8(Z) should be transfered within register: r12
|
14 | ;hi8(Z) should be transfered within register: r13
|
15 | ;( as definition of SPM low8bit of dataword are stored within r0 )
|
16 | ;( as definition of SPM hi8bit of dataword are stored within r1 )
|
17 |
|
18 | ;<-->USED/CHANGED:
|
19 | ;temp0 will be register: r11
|
20 | ;temp1 will be register: r12
|
21 | ;temp2 will be register: r13
|
22 | ;command code (r18) will change during CCP and status r18
|
23 | ;Z (r31:r30) (and RAMPZ) wil be changed during operation
|
24 | ;NVM.CMD will become changed during operation
|
25 |
|
26 | ;<--OUT:
|
27 | ;<magicvalue specific code (not depicted here)>
|
28 | ;load pageaddress (Z) from (r11:)r13:12 since it may was used for icall
|
29 | */
|
30 | void __bootloader__do_spm(void) { |
31 | asm volatile ( |
32 | /* MAGIC NOT IMPLEMENTED YET */
|
33 | "sts %[rampz] , r11 \n\t" |
34 | "movw r30 , r12 \n\t" |
35 | |
36 | /* save the nvm command to temp0 sice we need an upper register */
|
37 | "mov r11 , r18 \n\t" |
38 | |
39 | /* wait the flash to unblock */
|
40 | "rcall __do_spm__flash_block_spinwait%= \n\t" |
41 | |
42 | |
43 | /* do the mystic stuff */
|
44 | "ldi r18 , %[spmmagic] \n\t" |
45 | "sts %[cmdreg] , r11 \n\t" |
46 | "sts %[ccpreg] , r18 \n\t" |
47 | "spm \n\t" |
48 | |
49 | |
50 | /* again wait the flash to unblock */
|
51 | "__do_spm__flash_block_spinwait%=: \n\t" |
52 | "lds r18 , %[status] \n\t" |
53 | "andi r18 , %[stat_block] \n\t" |
54 | "brne __do_spm__flash_block_spinwait%= \n\t" |
55 | "ret \n\t" |
56 | :
|
57 | : [ccpreg] "i" (_SFR_MEM_ADDR(CCP)), |
58 | [rampz] "i" (_SFR_MEM_ADDR(RAMPZ)), |
59 | [cmdreg] "i" (_SFR_MEM_ADDR(NVM.CMD)), |
60 | [status] "i" (_SFR_MEM_ADDR(NVM.STATUS)), |
61 | |
62 | [stat_block] "M" (NVM_NVMBUSY_bm | NVM_FBUSY_bm), |
63 | |
64 | [spmmagic] "M" (CCP_SPM_gc), |
65 | |
66 | [eol] "M" (0) |
67 | );
|
68 | }
|
Fuer Fragen, Anregungen, Ideen oder einfach nur fuer ein Schwaetzchen stehe ich gern zur Verfuegung. MfG Stephan
:
Bearbeitet durch User
Danke Stephan, danke für Deine Mühe. Ich werde es mir am Dienstag, wenn ich wieder auf Arbeit bin, genauer ansehen. Ich wollte allerdings in diese Funktion nicht so viel Arbeit reinstecken und hatte gehofft, mit den Atmel-Treibern die Sache schnell "abfrühstücken" zu können. Gruß Micha
Hallo Michael W. schrieb: > nicht so viel Arbeit reinstecken und hatte gehofft, mit den > Atmel-Treibern die Sache schnell "abfrühstücken" zu können. Das wirst du mit "normalen" application-section firmwares vergessen koennen. Den Flash schreiben darf nur Code aus der bootloader-section (a.k.a. bootloader). Diese Hardwarebeschraenkung zu umgehen ist moeglich, aber sicher nicht innerhalb der Atmel libs. Weclhen XMega verwendest du genau? Fuer den XMega128A3U (und aufgrund von Anfragen auch schon diverse andere) kann man meine apipage im BLS installieren und dann meine apipage library nutzen. Flash schreiben ist dann so einfach wie eeprom - einfach per C funktionen. MfG Stephan
Stephan B. schrieb: > Den Flash schreiben darf nur Code aus der bootloader-section (a.k.a. > bootloader). Damit hat sich das Thema erledigt. Dann nehme ich halt den EEPROM. Danke für die Info. Das ist mein erstes Xmega Projekt. Ich hatte im Datenblatt nur folgendes gelesen: "The user signature row is a separate memory section that is fully accessible (read and write) from application software and external programmers." Den Abschnitt habe ich überlesen: "A boot loader (application code located in the boot loader section of the flash) can both read and write the flash program memory, user signature row, and EEPROM, and write the lock bits to a more secure setting. Application code in the application section can read from the flash, user signature row, production signature (calibration) row, and fuses, and read and write the EEPROM." Gruß Micha
Stephan B. schrieb: > Zum Ausprobieren der API gibt es code hier: > http://matrixstorm.com/avr/avrstick/#msdbootloader_api Hallo Stephan, ich ab gerade mal versucht deine API-Page -Exmaple zu übersetzen, bin ab leider gescheitert. Wenn ich Dein makefile verwende läßt es sich Übersetzen, wenn ich dann aber den xmega128a3u gegen meinen a4u austausche, dann bekomme ich folgende Fehlermeldung: avr:106 architecture of input file `apipage.a(apipage.o)' is incompatible with avr:107 Output kannst Du oder jemand anders mir da weiterhelfen? Ich möchte mit Hilfe der API-Page ein Programm schreiben was mir einen vorhandenen Bootloader ersetzt. Sollte doch damit gehen oder?? Gruß Claus
Hallo Claus Der Bootloader laesst sich nur dann austauschen, wenn bereits eine API-page vorhanden ist. Die Updater-Firmware nutzt diese dann um den neuen Bootloader in die BLS zu Flashen. Bei nicht vorgesehenen, nachtraeglichen Nachbesserungen an existierenden Bootloadern koennten auch gesetzte Lockbits oder geaenderte Systemregister ein Problem darstellen. Ggf. kannst du deine Situation naeher darstellen - gern auch auf einen Schwatz. (Ich bin z.B. heute (nachmittag?) auf meinen Teamspeak Server anzutreffen.) Gerne compiliere ich die auch ATxMegaA4u objects (auch wenn ich dachte das schoneinmal getan zu haben...) MfG Stephan
Hallo Stephan, danke dass Du Dich so schnell gemeldet hast. Leider hast Du mir damit auch jede Hoffnung geraubt:-( Denn als ich Dir gerade beschreiben wollte wie ich es machen wollte, viel mir ein, dass der alte Bootloader blöderweise nur in App-Section schreiben kann. Denn in dessen Source steht sinngemäß:
1 | for(...) |
2 | {
|
3 | ...
|
4 | nvm_wait_until_ready(); |
5 | nvm_flash_load_word_to_buffer(address, word); |
6 | }
|
7 | nvm_flash_atomic_write_app_page(address); |
... ist eine Anpassung der AVR1605. Denn ich dachte ich könne eine Firmware schreiben, die sowohl in der App-Section als auch in der Boot-Section steht (nämlich Deine API) und dann den Bootloader ersetzt. Jetzt muss ich die Geräte leider auseinander bauen und leider hab ich nicht auf alle physikalischen Zugriff. Teamspeak hab ich leider nicht. Gruß Claus
Noch ist nicht alles verloren. Bevor du auseinander baust: Hast du den Quellcode des Bootloader? (oder/und:) Kannst du den Binaercode ruecklesen? Ich hatte mal ein aehnliches Problem mit Atmels DFU. Ich habe dann gezielt den vorliegenden ASM Code angesehen, und mir einen Codeblock ausgesucht der das SPM ausfuehrt. Damit konnte ich dann was minimales druberschreiben und letztendlich den Bootloader auf etwas mit API tauschen... (Das geht aber nur mit Versionen, die nicht den Bootloader schreibschützen) MfG
:
Bearbeitet durch User
Ja ich hab alles Quellcode, .o .lss ..., da ich den Bootloader damals selbst angepasst habe (musste schnell gehen und nun ist ein Bug darin, wie nicht anders zu erwarten:-( ). Du meinst die Einsprungadrssee für das spm im alten Bootloader suchen und aus der Application heraus nutzen um Deine Api-Page zu installieren? klingt nach einer Hoffnung. Claus
In der alten Bootloader .lss seht:
1 | nvm_wait_until_ready(); |
2 | nvm_common_spm(page_addr, NVM_CMD_ERASE_APP_PAGE_gc); |
3 | 20342: 42 e2 ldi r20, 0x22 ; 34 |
4 | 20344: 0f 94 bf 0b call 0x2177e ; 0x2177e <_etext> |
dann ist 0x2177e die Einsprungadresse für nvm_common_spm? und in r20 könnte ich dann NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc übergeben?
:
Bearbeitet durch User
Hallo Claus Ich werfe gerne mal einen Blick rein. Aber wenn moeglich (gern auch nur "privat" per mail), stelle mir die vollen Dateien zur Verfuegung. (Insbesondere den konkreten BinaryDump.) Bitte nenne mir auch den konkreten Typ des verwendeten AVRs. (Seitengroessen und Adressen variieren ja moeglicherweise innerhalb der Familie) Meine mail: matrixstorm@gmx.de MfG Stephan p.s.: Ggf. ist noch etwas Platz in der BLS uebrig, sodass man die API-page zunaechst per HACK nachruestet. Wichtig ist halt das BLS weiterhin schreibbar ist und man einen SPM findet mit nahem RET. (Sodass man den quasi als Unterprogramm missbrauchen kann.)
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.