1 | /************************************************
|
2 | ******************* INCLUDES *******************
|
3 | ************************************************/
|
4 |
|
5 | // System includes
|
6 |
|
7 |
|
8 | // User includes
|
9 | #include "Board.h"
|
10 | #include "intflash.h"
|
11 |
|
12 | /************************************************
|
13 | ******************** DEFINES *******************
|
14 | ************************************************/
|
15 |
|
16 | // Pages pro Sector
|
17 | #define PAGES_PER_SECTOR 64
|
18 |
|
19 | #define NUM_LOCKBITS FLASH_PAGE_NB / PAGES_PER_SECTOR
|
20 |
|
21 | /************************************************
|
22 | ************** STATIC DEFINITIONS **************
|
23 | ************************************************/
|
24 |
|
25 | RAMFUNC static void _IntFlash_NVM_Init(void);
|
26 |
|
27 | RAMFUNC static UINT32 _IntFlash_Ready(void);
|
28 |
|
29 | RAMFUNC static BOOL _IntFlash_IsLocked(UINT8 sector);
|
30 |
|
31 | /************************************************
|
32 | *************** GLOBAL FUNCTIONS ***************
|
33 | ************************************************/
|
34 |
|
35 | void IntFlash_Init(void) {
|
36 | // Setze Anzahl Master Clock Ciycles pro 1.5 Microsecond
|
37 | AT91C_BASE_MC->MC_FMR = (((3 * MCK) / 2000000 + 2) << 16) | AT91C_MC_FWS_1FWS;
|
38 | }
|
39 |
|
40 | RAMFUNC RETCODE IntFlash_Write(UINT32 addr, UINT32 len, UINT32 *data) {
|
41 | volatile UINT32 statreg;
|
42 | volatile UINT32 *dest = (UINT32*)addr;
|
43 | UINT32 i, written, page;
|
44 |
|
45 | AT91C_BASE_MC->MC_FMR &= ~AT91C_MC_FRDY; // Kein Interrupt, wenn fertig
|
46 | AT91C_BASE_MC->MC_FMR &= ~AT91C_MC_LOCKE; // Kein Interrupt, wenn locked
|
47 | AT91C_BASE_MC->MC_FMR &= ~AT91C_MC_PROGE; // Kein Interrupt, wenn Programmierfehler
|
48 | AT91C_BASE_MC->MC_FMR &= ~AT91C_MC_NEBP; // Lösche Page bevor geschrieben wird
|
49 |
|
50 | written = 0;
|
51 | len /= 4; // Bytes -> Words
|
52 |
|
53 | while (written < len) {
|
54 | page = ((UINT32)dest) / FLASH_PAGE_SIZE;
|
55 | // Lock von zu beschreibender Page entfernen
|
56 | IntFlash_Unlock(page / PAGES_PER_SECTOR);
|
57 |
|
58 | // Initialisiere Schreib-Routine für internes Flash
|
59 | IntFlash_Init();
|
60 |
|
61 | // Buffer füllen
|
62 | for (i = 0; i < (FLASH_PAGE_SIZE / 4); i++) {
|
63 | dest[i] = data[i];
|
64 | written++;
|
65 | }
|
66 |
|
67 | statreg = 0;
|
68 |
|
69 | // Key, zu beschreibende Page und Schreib-Modus setzen
|
70 | AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | ((page << 8) & AT91C_MC_PAGEN) | AT91C_MC_FCMD_START_PROG;
|
71 |
|
72 | // Warten bis Schreib-Routine fertig
|
73 | statreg = _IntFlash_Ready();
|
74 |
|
75 | // Auf Programmier-Fehler prüfen
|
76 | if (statreg & AT91C_MC_PROGE) {
|
77 | return E_INTFLASH_PROG;
|
78 | }
|
79 | // Auf Lock-Fehler prüfen
|
80 | else if (statreg & AT91C_MC_LOCKE) {
|
81 | return E_INTFLASH_ISLOCKED;
|
82 | }
|
83 |
|
84 | dest += (FLASH_PAGE_SIZE / 4);
|
85 | data += (FLASH_PAGE_SIZE / 4);
|
86 | }
|
87 |
|
88 | return E_OK;
|
89 | }
|
90 |
|
91 | RAMFUNC void IntFlash_Lock(UINT8 sector) {
|
92 | if (_IntFlash_IsLocked(sector)) {
|
93 | return;
|
94 | }
|
95 |
|
96 | _IntFlash_NVM_Init();
|
97 |
|
98 | AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | ((sector << 8) & AT91C_MC_PAGEN) | AT91C_MC_FCMD_LOCK;
|
99 |
|
100 | // Warten bis Lock fertig
|
101 | _IntFlash_Ready();
|
102 | }
|
103 |
|
104 | RAMFUNC void IntFlash_Unlock(UINT8 sector) {
|
105 | if (!_IntFlash_IsLocked(sector)) {
|
106 | return;
|
107 | }
|
108 |
|
109 | _IntFlash_NVM_Init();
|
110 |
|
111 | AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | ((sector << 8) & AT91C_MC_PAGEN) | AT91C_MC_FCMD_UNLOCK;
|
112 |
|
113 | // Warten bis Unlock fertig
|
114 | _IntFlash_Ready();
|
115 | }
|
116 |
|
117 | /************************************************
|
118 | *************** STATIC FUNCTIONS ***************
|
119 | ************************************************/
|
120 |
|
121 | RAMFUNC static void _IntFlash_NVM_Init(void) {
|
122 | // Setze Anzahl Master Clock Ciycles pro Microsecond
|
123 | AT91C_BASE_MC->MC_FMR = (AT91C_BASE_MC->MC_FMR & ~AT91C_MC_FMCN) | (AT91F_MC_EFC_ComputeFMCN(MCK) << 16);
|
124 | }
|
125 |
|
126 | RAMFUNC static UINT32 _IntFlash_Ready(void) {
|
127 | UINT32 status;
|
128 | status = 0;
|
129 |
|
130 | // Warten bis Ready-Flag signalisiert, dass Aktion fertig ausgeführt wurde
|
131 | while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY ) {
|
132 | status = AT91C_BASE_MC->MC_FSR;
|
133 | }
|
134 |
|
135 | return status;
|
136 | }
|
137 |
|
138 | RAMFUNC static BOOL _IntFlash_IsLocked(UINT8 sector) {
|
139 | return (AT91C_BASE_MC->MC_FSR & (AT91C_MC_LOCKS0 << sector)) ? TRUE : FALSE;
|
140 | }
|