Nut/OS  4.10.3
API Reference
flashc.c
Go to the documentation of this file.
00001 
00042 #include <sys/atom.h>
00043 #include <dev/nvmem.h>
00044 
00045 #include <stdint.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 
00049 #include <arch/avr32.h>
00050 #include <arch/avr32/flashc.h>
00051 
00052 #include <avr32/io.h>
00053 
00054 
00059 
00062 #ifndef FLASH_CONF_SECTOR
00063 #define FLASH_CONF_SECTOR  0x0003FF00
00064 #endif
00065 
00066 
00076 #ifndef FLASH_CONF_SIZE
00077 #define FLASH_CONF_SIZE         AVR32_FLASHC_PAGE_SIZE
00078 #endif
00079 
00080 #ifndef FLASH_WRITE_WAIT
00081 #define FLASH_WRITE_WAIT        60000
00082 #endif
00083 
00084 #ifndef FLASH_ERASE_WAIT
00085 #define FLASH_ERASE_WAIT        60000
00086 #endif
00087 
00088 #ifndef FLASH_CHIP_ERASE_WAIT
00089 #define FLASH_CHIP_ERASE_WAIT   600000
00090 #endif
00091 
00092 
00093 typedef uint32_t flashdat_t;
00094 typedef unsigned long flashadr_t;
00095 typedef volatile flashdat_t *flashptr_t;
00096 
00097 static int flashc_is_ready(void)
00098 {
00099     return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_FRDY_MASK) != 0);
00100 }
00101 
00106 int Avr32FlashcCmd(unsigned int cmd, uint32_t tmo)
00107 {
00108     int rc = 0;
00109 
00110     /* Make sure that the previous command has finished. */
00111     while (!flashc_is_ready()) {
00112         if (tmo && --tmo < 1) {
00113             return -1;
00114         }
00115     }
00116 
00117     /* IRQ handlers are located in flash. Disable them. */
00118     NutEnterCritical();
00119 
00120     /* Write command. */
00121     outr(AVR32_FLASHC.fcmd, AVR32_FLASHC_FCMD_KEY_KEY | cmd);
00122 
00123     /* Wait for ready flag set. */
00124     while (!flashc_is_ready()) {
00125         if (tmo && --tmo < 1) {
00126             rc = -1;
00127             break;
00128         }
00129     }
00130 
00131     /* Flash command finished. Re-enable IRQ handlers. */
00132     NutExitCritical();
00133 
00134     /* Check result. */
00135     if (AVR32_FLASHC.fsr & (AVR32_FLASHC_FSR_LOCKE_MASK | AVR32_FLASHC_FSR_PROGE_MASK)) {
00136         rc = -1;
00137     }
00138     return rc;
00139 }
00140 
00150 int Avr32FlashcSectorRead(unsigned int off, void *data, unsigned int len)
00151 {
00152     memcpy(data, (void *) (uptr_t) (AVR32_FLASH_ADDRESS + off), len);
00153 
00154     return 0;
00155 }
00156 
00169 int Avr32FlashcSectorWrite(unsigned int off, CONST void *data, unsigned int len)
00170 {
00171     flashptr_t dp = (flashptr_t) (uptr_t) (AVR32_FLASH_ADDRESS + off);
00172     int rc;
00173     unsigned int i;
00174 
00175     if (data) {
00176         flashptr_t sp = (flashptr_t) data;
00177 
00178         /* Copy data to the flash write buffer. */
00179         for (i = 0; i < len; i += sizeof(flashdat_t)) {
00180             *dp++ = *sp++;
00181         }
00182     } else {
00183         /* All bits set to emulate sector erasing. */
00184         for (i = 0; i < len; i += sizeof(flashdat_t)) {
00185             *dp++ = (flashdat_t) (-1);
00186         }
00187     }
00188 
00189     /* Erase target flash page. */
00190     Avr32FlashcSectorErase(off);
00191     /* Execute page write command. */
00192     rc = Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_WP, FLASH_WRITE_WAIT);
00193 
00194     return rc;
00195 }
00196 
00200 int Avr32FlashcSectorErase(unsigned int off)
00201 {
00202     return Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_EP, FLASH_ERASE_WAIT);
00203 }
00204 
00212 int Avr32FlashcRegionLock(unsigned int off)
00213 {
00214     return Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_LP, FLASH_WRITE_WAIT);
00215 }
00216 
00224 int Avr32FlashcRegionUnlock(unsigned int off)
00225 {
00226     return Avr32FlashcCmd((off & AVR32_FLASHC_FCMD_PAGEN_MASK) | AVR32_FLASHC_FCMD_CMD_UP, FLASH_WRITE_WAIT);
00227 }
00228 
00240 int Avr32FlashcParamRead(unsigned int pos, void *data, unsigned int len)
00241 {
00242     return Avr32FlashcSectorRead(FLASH_CONF_SECTOR + pos, data, len);
00243 }
00244 
00259 int Avr32FlashcParamWrite(unsigned int pos, CONST void *data, unsigned int len)
00260 {
00261     int rc = -1;
00262     uint8_t *buff;
00263 
00264     /* Load the complete configuration area. */
00265     if ((buff = malloc(FLASH_CONF_SIZE)) != NULL) {
00266 
00267         rc = Avr32FlashcSectorRead(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00268         /* Compare old with new contents. */
00269         if (memcmp(buff + pos, data, len)) {
00270             /* New contents differs. Copy it into the sector buffer. */
00271             memcpy(buff + pos, data, len);
00272             /* Write back new data. Maintain region lock. */
00273             if (Avr32FlashcRegionUnlock(FLASH_CONF_SECTOR) == 0) {
00274                 rc = Avr32FlashcSectorWrite(FLASH_CONF_SECTOR, buff, FLASH_CONF_SIZE);
00275                 Avr32FlashcRegionLock(FLASH_CONF_SECTOR);
00276             }
00277         }
00278         free(buff);
00279     }
00280     return rc;
00281 }
00282