intflash.c


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
}