Forum: Mikrocontroller und Digitale Elektronik [XMega][C] Flash Write möglich aus Anwendung?


von Robert O. (rob_o)


Lesenswert?

Hallo allerseits,
habe nach längerer Zeit wieder mit C Programmieren angefangen und mich 
gleichzeitig für einen XMega entschieden. Meine bisherigen Erfahrungen 
beschränken sich auf die mega Serie. Nun habe ich auch schon das erste 
Problem (zumindest das erste über das ich schreibe ;) ), ich möchte für 
meine Anwendung ein Array welches im Flash angesiedelt ist und 7200byte 
groß ist auf einem port ausgeben, das sollte mit pgm_read_byte kein 
problem sein.
Jetzt kommts aber, das Array soll über USART zu ändern gehen, also alle 
7200 byte über die serielle Schnittstelle empfangen und nach eventueller 
Checksummen Prüfung in den Flash Speicher schreiben.
Geht das aus der Anwendung?
Gibt es eine Alternative?
Mir ist schon eingefallen den Bootloader code zu erweitern denn der 
macht ja prinzipiell genau das was ich will, jedoch müsste ich dann 
meine Kommunikation umbauen (ich verwende ein Matlab Frontend) da die ja 
dannn lernen müsste mit dem BL zu kommunizieren.

Bin für Vorschläge und Codeschnipsel dankbar.
mfg. Robert

von Moby (Gast)


Lesenswert?

Xmega Flash beschreiben geht grundsätzlich nur mit Code in der 
Boot-Section.

von Stephan B. (matrixstorm)


Lesenswert?

Mit entsprechender API im BLS geht sowas schon.
Man muss aber ein paar Dinge beachten, sonst crasht der AVR.


http://matrixstorm.com/avr/avrstick/#msdbootloader_api


MfG

von Robert O. (rob_o)


Lesenswert?

Habe mir die Seite matrixstorm einmal angesehen. Ich verwende jedoch 
einen 128A1 ohne USB, müsste also den Bootloader reverse-engineeren und 
die relevanten Stellen auf einen "normalen" Bootloader umschreiben damit 
ich die API verwenden kann, das ist jedoch außerhalb meiner 
Möglichkeiten.

von Stephan B. (matrixstorm)



Lesenswert?

Hallo.

API ist nur eine Flashseite, mehr oder weniger unabhaengig vom 
Bootloader.
Hab das ganze sogar ins FLIP reingepatch, ohne FLIP jemals neu zu 
compilen.

Ich haenge dir mal die API Seite an.

Bei Fragen helfe ich gern.

MfG

von Robert O. (rob_o)


Lesenswert?

Ich denke ich bekomme eine Ahnung wie das funkt.
In der letzten flash page in der BL Section steht deine API page 
(compilierte __bootloader__**** files) Am Beginn der API Page ist eine 
Sprungtabelle die unter anderem do_spm (Offset 2) anspringt.
In der Applikation wird wird apipage.h inkludiert, dort wird mit extern 
definierten funktionen auf die Sprungtabelle verwiesen.
(#define APIPAGE__bootloader__do_spm  (APIPAGE_PAGEBYTEADDRESS+0x08))

Es wird also gar kein code aus dem BL verwendet, somit patcht man die 
apipage anstelle der letzten flash page in den Bootloader.

Einiges ist jedoch noch unklar:
.) APIPAGEAUXSECTION ist nirgendwo definiert oder ist das nicht 
notwendig?
.) section (".apipage") müsste im Makefile def. sein. Kannst Du mir das 
auch zeigen?
.) was ist apipage.a?
.) Kannst Du mir die compilierte APIPage schicken damit ich den BL 
patchen kann? Ich plane avr-xboot (https://code.google.com/p/avr-xboot/) 
zu verwenden.

Danke für die Hilfe.
mfg. Robert

von Stephan B. (matrixstorm)


Lesenswert?

Hallo

Robert Offner schrieb:
> APIPAGEAUXSECTION ist nirgendwo definiert oder ist das nicht
> notwendig?

Das ist ein Makro welches von meinem internen AUXSECTION System 
definiert wird. Du kannst es aber auch leer lassen, dann lander der 
entpsrechende Code eben in .text.
Der Grund fuer diese allgmeinere Programmierung: Manchmal passt (bei der 
Bootloaderprogrammierung) nicht alles in die BLS. Das AUXSECTION Level 
entscheidet dann per Makro, was statt in .text/.boot in einer Pseudo-BLS 
landet.

Robert Offner schrieb:
> section (".apipage") müsste im Makefile def. sein. Kannst Du mir das
> auch zeigen?

Das wird einfach als Linkeranweisung an den Anfang der letzten Seite des 
Flash positioniert. "-Wl,--section-start=.apipage=0x21e00" (im Falle von 
ATxmega128A3U)

Robert Offner schrieb:
> Kannst Du mir die compilierte APIPage schicken damit ich den BL
> patchen kann? Ich plane avr-xboot (https://code.google.com/p/avr-xboot/)
> zu verwenden.

Kann ich machen - aber schwatzen wir mal bei Tageslicht dueber. Bin 
schon ziemlich KO jetzt um diese Zeit.
Fuer meine 
http://www.ebay.de/itm/231298084713?ssPageName=STRK:MESELX:IT&_trksid=p3984.m1555.l2649 
habe ich aber auch einen Bootloader nach AVR1605 direkt mit APIPage 
vorhanden. (Ist das nicht sogar die Refernezimplementierung von XBoot?)



Robert Offner schrieb:
> was ist apipage.a?

Eine vorkompilierte Bibliothek fuers statische Linken (eingentlich 
object archive), welches das minimale __do_spm auf bequemere Funktionen 
umsetzt - siehe apipage.h .

Beispielsweise musst du nur noch "flash_writepage" aufrufen, waehrend 
ansonsten das alles gemacht werden muesste:
1
/*
2
 * __do_spm:
3
 * 
4
 * Call the "bootloader__do_spm"-function, located within the BLS via comfortable C-interface
5
 * During operation code will block - disable or reset watchdog before call.
6
 *
7
 * REMEMBER: interrupts have to be disabled! (otherwise code may crash non-deterministic)
8
 */
9
10
11
#if ((APIPAGE_TOTALADDRESSSPACEBYTESIZE_EXEC) >= 131071)
12
#  define __do_spm_complex__PROCESSEIND                \
13
    /* prepare the EIND for following (e)icall */              \
14
    "lds  r18  ,  %[eind]                \n\t"  \
15
    "push  r18                    \n\t"  \
16
    "ldi  r18  ,  %[spmfuncaddrEIND]            \n\t"  \
17
    "sts  %[eind]  ,  r18                \n\t"
18
#  define __do_spm_complex__RESTOREEIND                \
19
    "pop  __tmp_reg__                  \n\t"  \
20
    "sts  %[eind]  ,  __tmp_reg__              \n\t"
21
#  define __do_spm_complex__CALLOPCODE  "eicall\n\t"
22
#else
23
#  define __do_spm_complex__PROCESSEIND
24
#  define __do_spm_complex__RESTOREEIND
25
#  define __do_spm_complex__CALLOPCODE  "icall\n\t"
26
#endif
27
28
/* WARNING: "___bootloader__do_spm__ptr" is a functionptr in flash. 
29
 * Using "APIPAGE__bootloader__do_spm*" (flash location) without conversion will break code!
30
 * 
31
 * "__do_spm_complex" is based on spminterface of USBaspLoader, by Stephan Baerwolf
32
 */
33
#define __do_spm_complex(___bootloader__do_spm__ptr, flashword_ptr, nvmcommand, dataword, MagicValue)  \
34
({                          \
35
    asm volatile (                      \
36
    "push  r0                    \n\t"  \
37
    "push  r1                    \n\t"   \
38
                          \
39
    /* load the magic value (MagicValue) */                \
40
    "ldi  r23  ,  %[magicD]              \n\t"  \
41
    "ldi  r22  ,  %[magicC]              \n\t"  \
42
    "ldi  r21  ,  %[magicB]              \n\t"  \
43
    "ldi  r20  ,  %[magicA]              \n\t"  \
44
                          \
45
    /* load the address (flashword_ptr) */                \
46
    "mov  r13  ,  %B[flashptr]              \n\t"  \
47
    "mov  r12  ,  %A[flashptr]              \n\t"  \
48
    "mov  r11  ,  %C[flashptr]              \n\t"  \
49
                          \
50
    __do_spm_complex__PROCESSEIND                  \
51
                          \
52
    /* also load the nvm command */                  \
53
    "mov  r18  ,  %[nvmcmd]              \n\t"  \
54
                          \
55
    /* load the data (dataword) */                  \
56
    "mov  r1  ,  %B[data]              \n\t"  \
57
    "mov  r0  ,  %A[data]              \n\t"  \
58
                          \
59
    /* finally call the bootloader-function */                \
60
    __do_spm_complex__CALLOPCODE                  \
61
    __do_spm_complex__RESTOREEIND                  \
62
                          \
63
    "pop  r1                    \n\t"  \
64
    "pop  r0                    \n\t"  \
65
                          \
66
    /* stop further execution in case of unexpected error */            \
67
    "cpi  r18  ,  0xff                \n\t"   \
68
    "errorloop%=:                    \n\t"  \
69
    "breq errorloop%=                    \n\t"  \
70
    :                          \
71
    : [flashptr]    "r"  (flashword_ptr),            \
72
      [spmfunctionaddress]  "z"  ((uint16_t)((uint32_t)___bootloader__do_spm__ptr)),    \
73
      [spmfuncaddrEIND]    "M"  ((uint8_t)(((uint32_t)___bootloader__do_spm__ptr)>>16)),  \
74
      [eind]      "i"  (_SFR_MEM_ADDR(EIND)),            \
75
      [data]      "r"  (dataword),              \
76
      [magicD]      "M"  (((MagicValue)>>24)&0xff),          \
77
      [magicC]      "M"  (((MagicValue)>>16)&0xff),          \
78
      [magicB]      "M"  (((MagicValue)>> 8)&0xff),          \
79
      [magicA]      "M"  (((MagicValue)>> 0)&0xff),          \
80
      [nvmcmd]      "r"  (nvmcommand)              \
81
    : "r0","r1","r11","r12","r13","r18","r20","r21","r22","r23"            \
82
    );                          \
83
})
84
85
86
[...]
87
88
/* write operations using __bootloader_do_spm driver */
89
90
void __do_spm(const uint_farptr_t flashword_ptr, const uint8_t nvmCommand, const uint16_t dataWord) {
91
  uint8_t sreg_backup = CPU_SREG;
92
  cli();
93
#if (USE_SPMINTEREFACE_MAGICVALUE != 0)
94
  __do_spm_complex(((uint32_t)APIPAGE__bootloader__do_spm_magicblock)>>1, flashword_ptr, nvmCommand, dataWord, (uint32_t)USE_SPMINTEREFACE_MAGICVALUE);
95
#else
96
  /* DANGER: ignores platform protection by magical value */
97
#  warning USE_SPMINTEREFACE_MAGICVALUE is zero - platform protection deactivated!
98
  __do_spm_complex(((uint32_t)APIPAGE__bootloader__do_spm)>>1           , flashword_ptr, nvmCommand, dataWord, (uint32_t)USE_SPMINTEREFACE_MAGICVALUE);
99
#endif
100
  CPU_SREG=sreg_backup;
101
}
102
103
[...]
104
105
size_t flash_writepage_Ex(__extfuncptr_type(apipage__do_spm_t) *spmfunc, const uint8_t in_pageBuffer[SPM_PAGESIZE], const uint_farptr_t in_pageNr, const uint8_t nvmCommand) {
106
  uint_farptr_t flashAddress = in_pageNr*((uint_farptr_t)SPM_PAGESIZE);
107
108
  flash_eraseflashbuffer_Ex(spmfunc, in_pageBuffer, flashAddress);
109
  flash_loadflashbuffer_Ex(spmfunc, in_pageBuffer, flashAddress);
110
  __extfuncptr_function(apipage__do_spm_t, spmfunc, flashAddress, nvmCommand, 0);
111
112
  return SPM_PAGESIZE;
113
}
114
115
[...]
116
117
#if (!(defined(APIPAGE_OLDFLASHWRITE)))
118
size_t flash_writepage(const uint8_t in_pageBuffer[SPM_PAGESIZE], const uint_farptr_t in_pageNr) {
119
  __extfuncptr_type(apipage__do_spm_t) spmfunc = __extfuncptr_getPtr(apipage__do_spm_t, __do_spm);
120
  return flash_writepage_Ex(&spmfunc, in_pageBuffer, in_pageNr, NVM_CMD_ERASE_WRITE_FLASH_PAGE_gc);
121
}
122
#else
123
/* very poor: old ATxmegas don't support some types of erasing/wrting  - working around */
124
size_t flash_writepage(const uint8_t in_pageBuffer[SPM_PAGESIZE], const uint_farptr_t in_pageNr) {
125
  __extfuncptr_type(apipage__do_spm_t) spmfunc = __extfuncptr_getPtr(apipage__do_spm_t, __do_spm);
126
#if (APIPAGE_OLDFLASHWRITE)
127
  return flash_writepage_Ex(&spmfunc, in_pageBuffer, in_pageNr, APIPAGE_OLDFLASHWRITE);
128
#else
129
  return flash_writepage_Ex(&spmfunc, in_pageBuffer, in_pageNr, (in_pageNr<(BOOT_SECTION_START/SPM_PAGESIZE))?NVM_CMD_ERASE_WRITE_APP_PAGE_gc:NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc);
130
#endif
131
}
132
#endif



Bis nachher/morgen.

MfG Stephan

p.s.: Nur zur Erwaehnung die ganzen Codeauszuege sind Bestandteil meines 
AVR Stick Projektes: http://matrixstorm.com/avr/avrstick/

: 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
Noch kein Account? Hier anmelden.