Created
September 8, 2015 00:44
-
-
Save spirilis/1002c873cdaad4a61e60 to your computer and use it in GitHub Desktop.
RX62N DataFlash R/W example library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* dataflash_rx62n.c | |
* | |
* Created on: Nov 30, 2012 | |
* Author: spirilis | |
*/ | |
#include <stdint.h> | |
#include "iodefine.h" | |
#include "dataflash_rx62n.h" | |
/* Assumes 48MHz PCLK, does not use interrupts. */ | |
volatile uint8_t *df_start = (void*)0x00100000UL; | |
void _dataflash_PE_mode(); | |
void _dataflash_PE_exit(); | |
uint8_t _dataflash_needs_reset(); | |
uint8_t dataflash_init() | |
{ | |
uint32_t i=0; | |
volatile uint32_t *fcufw_source = (volatile uint32_t *)0xFEFFE000UL, *fcuram = (volatile uint32_t *)0x007F8000UL; | |
volatile uint32_t *fcufw_end = (volatile uint32_t *)0xFEFFFFFFUL; | |
// Step 1: Enable read/write lockbits for data flash segments | |
FLASH.DFLRE0.WORD = 0x2DFF; | |
FLASH.DFLRE1.WORD = 0xD2FF; | |
FLASH.DFLWE0.WORD = 0x1EFF; | |
FLASH.DFLWE1.WORD = 0xE1FF; | |
// Step 2: Enter Program/Erase Mode | |
// Step 2a: Disable interrupts | |
FLASH.FAEINT.BIT.ROMAEIE = 0; | |
FLASH.FAEINT.BIT.CMDLKIE = 0; | |
FLASH.FAEINT.BIT.DFLAEIE = 0; | |
FLASH.FAEINT.BIT.DFLRPEIE = 0; | |
FLASH.FAEINT.BIT.DFLWPEIE = 0; | |
// Step 2b: Initialize FCU controller, write firmware | |
FLASH.FENTRYR.WORD = 0xAA00; | |
asm("nop"); asm("nop"); | |
FLASH.FCURAME.WORD = 0xC401; | |
while (fcufw_source < fcufw_end) | |
*fcuram++ = *fcufw_source++; | |
// Step 2b: Reset FCU controller | |
FLASH.FRESETR.WORD = 0xCC01; | |
for (i=0; i<4000; i++) { asm("nop"); } | |
FLASH.FRESETR.WORD = 0xCC00; | |
while (!FLASH.FSTATR0.BIT.FRDY) | |
; | |
FLASH.FENTRYR.WORD = 0xAA80; | |
asm("nop"); asm("nop"); | |
// Step 2c: Clear Status | |
if (FLASH.FSTATR0.BIT.ILGLERR) { | |
if (FLASH.FASTAT.BYTE != 0x10) | |
FLASH.FASTAT.BYTE = 0x10; | |
} | |
*df_start = 0x50; // Issue Status Clear cmd | |
// Step 2c: Enable master write bit | |
FLASH.FWEPROR.BYTE = 0x01; | |
// Step 2d: Check for errors before continuing | |
if (FLASH.FSTATR0.BYTE & 0x70 || FLASH.FSTATR1.BIT.FCUERR) { | |
return 0; | |
} | |
// Step 2e: Issue Peripheral Clock Notification | |
FLASH.PCKAR.WORD = 48; | |
*df_start = 0xE9; | |
*df_start = 0x03; | |
*(volatile uint16_t*)df_start = 0x0F0F; | |
*(volatile uint16_t*)df_start = 0x0F0F; | |
*(volatile uint16_t*)df_start = 0x0F0F; | |
*df_start = 0xD0; | |
// Check if Peripheral Clock Notification caused an error | |
while (!FLASH.FSTATR0.BIT.FRDY) | |
; | |
if (FLASH.FSTATR0.BIT.ILGLERR) { | |
return 0; | |
} | |
_dataflash_PE_exit(); | |
return 1; // Data Flash and FCU fully initialized | |
} | |
void _dataflash_PE_mode() | |
{ | |
// Enable Data Flash writing | |
FLASH.FENTRYR.WORD = 0xAA80; | |
asm("nop"); asm("nop"); | |
// Enable Master Write bit | |
FLASH.FWEPROR.BYTE = 0x01; | |
/* Clear Status (note: we need FENTRYD set before we can do this, b/c we're | |
* writing a command to a pointer in the data flash addr space) | |
*/ | |
if (FLASH.FSTATR0.BIT.ILGLERR) { | |
if (FLASH.FASTAT.BYTE != 0x10) | |
FLASH.FASTAT.BYTE = 0x10; | |
} | |
*df_start = 0x50; // Issue Status Clear cmd | |
} | |
void _dataflash_PE_exit() | |
{ | |
// Disable Data Flash writing | |
FLASH.FENTRYR.WORD = 0xAA00; | |
asm("nop"); asm("nop"); | |
// Disable Master Write bit | |
FLASH.FWEPROR.BYTE = 0x02; | |
} | |
uint8_t _dataflash_needs_reset() | |
{ | |
return FLASH.FSTATR1.BIT.FCUERR; | |
} | |
uint8_t dataflash_is_blank(void* flashaddr) | |
{ | |
_dataflash_PE_mode(); | |
if (_dataflash_needs_reset()) { | |
if (!dataflash_init()) | |
return 255; | |
_dataflash_PE_mode(); | |
} | |
FLASH.FMODR.BIT.FRDMD = 1; | |
FLASH.DFLBCCNT.BIT.BCSIZE = 1; | |
*(volatile uint8_t *)flashaddr = 0x71; | |
*(volatile uint8_t *)flashaddr = 0xD0; | |
while (!FLASH.FSTATR0.BIT.FRDY) | |
; | |
FLASH.FMODR.BIT.FRDMD = 0; | |
if (FLASH.FSTATR0.BIT.ILGLERR) { | |
_dataflash_PE_exit(); | |
return 255; | |
} | |
_dataflash_PE_exit(); | |
if (FLASH.DFLBCSTAT.BIT.BCST) { | |
return 0; | |
} | |
return 1; | |
} | |
uint8_t dataflash_erase(void* flashaddr) | |
{ | |
_dataflash_PE_mode(); | |
if (_dataflash_needs_reset()) { | |
if (!dataflash_init()) | |
return 0; | |
_dataflash_PE_mode(); | |
} | |
*(volatile uint8_t *)flashaddr = 0x20; | |
*(volatile uint8_t *)flashaddr = 0xD0; | |
while (!FLASH.FSTATR0.BIT.FRDY) | |
; | |
if (FLASH.FSTATR0.BIT.ILGLERR || FLASH.FSTATR0.BIT.ERSERR) { | |
_dataflash_PE_exit(); | |
return 0; | |
} | |
_dataflash_PE_exit(); | |
return 1; | |
} | |
uint8_t dataflash_write(void* flashaddr, void* buffer, uint8_t bytes) | |
{ | |
uint16_t i; | |
volatile uint8_t *fa = (volatile uint8_t *)flashaddr; | |
uint8_t *bytebuf = (uint8_t *)buffer; | |
if (bytes < 1 || bytes > 128 || bytes % 2 != 0) | |
return 0; // Not supporting >128 byte writes yet, maybe work on that later | |
if (bytes < 9 && (fa-df_start) % 8 != 0) | |
return 0; // Only write on properly aligned boundaries please... | |
if (bytes > 8 && (fa-df_start) % 128 != 0) | |
return 0; // Ditto (but for 128-byte writes)... | |
_dataflash_PE_mode(); | |
if (_dataflash_needs_reset()) { | |
if (!dataflash_init()) | |
return 0; | |
_dataflash_PE_mode(); | |
} | |
if (bytes > 8) { // 128-byte page mode | |
*fa = 0xE8; | |
*fa = 0x40; // 128-bytes | |
for (i=0; i<128; i+=2) { | |
if (bytes) { | |
*(volatile uint16_t *)fa = (uint16_t) (bytebuf[i] | (bytebuf[i+1] << 8)); | |
bytes -= 2; | |
} else | |
*(volatile uint16_t *)fa = 0x0000; | |
} | |
*fa = 0xD0; | |
} else { | |
*fa = 0xE8; | |
*fa = 0x04; // 8-bytes | |
for (i=0; i<8; i+=2) { | |
if (bytes) { | |
*(volatile uint16_t *)fa = (uint16_t) (bytebuf[i] | (bytebuf[i+1] << 8)); | |
bytes -= 2; | |
} else | |
*(volatile uint16_t *)fa = 0x0000; | |
} | |
*fa = 0xD0; | |
} | |
while (!FLASH.FSTATR0.BIT.FRDY) | |
; | |
if (FLASH.FSTATR0.BIT.ILGLERR || FLASH.FSTATR0.BIT.PRGERR) { | |
_dataflash_PE_exit(); | |
return 0; | |
} | |
_dataflash_PE_exit(); | |
return 1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* dataflash_rx62n.h | |
* | |
* Created on: Nov 30, 2012 | |
* Author: spirilis | |
*/ | |
#ifndef DATAFLASH_RX62N_H_ | |
#define DATAFLASH_RX62N_H_ | |
#include <stdint.h> | |
uint8_t dataflash_init(); | |
uint8_t dataflash_is_blank(void *); | |
uint8_t dataflash_erase(void *); | |
uint8_t dataflash_write(void *, void *, uint8_t); | |
#endif /* DATAFLASH_RX62N_H_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment