manually merged with ARM version
This commit is contained in:
171
x502api-1.1.34/devs/l502/l502api_eeprom.c
Normal file
171
x502api-1.1.34/devs/l502/l502api_eeprom.c
Normal file
@ -0,0 +1,171 @@
|
||||
#include "l502api_private.h"
|
||||
#include "ltimer.h"
|
||||
#include "l502_fpga_regs.h"
|
||||
|
||||
#define L502_EEPROM_BIG_SECTOR_SIZE (64*1024)
|
||||
#define L502_EEPROM_SMALL_SECTOR_SIZE (4*1024)
|
||||
|
||||
#define L502_FLASH_WRITE_TOUT 500
|
||||
#define L502_FLASH_ERASE_TOUT 500
|
||||
|
||||
/** биты регистра статуса */
|
||||
typedef enum {
|
||||
SST25_STATUS_BUSY = 0x01,
|
||||
SST25_STATUS_WEL = 0x02,
|
||||
SST25_STATUS_BP0 = 0x04,
|
||||
SST25_STATUS_BP1 = 0x08,
|
||||
SST25_STATUS_BP2 = 0x10,
|
||||
SST25_STATUS_BP3 = 0x20,
|
||||
SST25_STATUS_AAI = 0x40,
|
||||
SST25_STATUS_BPL = 0x80
|
||||
} t_sst25_status_bits;
|
||||
|
||||
static uint8_t f_prot_bits[] = {
|
||||
SST25_STATUS_BP2 | SST25_STATUS_BP1 | SST25_STATUS_BP0,
|
||||
SST25_STATUS_BP2 | SST25_STATUS_BP0,
|
||||
SST25_STATUS_BP2,
|
||||
SST25_STATUS_BP0,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
|
||||
static LINLINE int32_t f_eeprom_rd_status(t_x502_hnd hnd, uint8_t* stat) {
|
||||
uint32_t val;
|
||||
int32_t err = l502_port_fpga_reg_read(hnd, L502_REGS_EEPROM_RD_STATUS, &val);
|
||||
if (err == X502_ERR_OK)
|
||||
*stat = (val>>24)&0xFF;
|
||||
return err;
|
||||
}
|
||||
|
||||
static LINLINE int32_t f_eeprom_wr_status(t_x502_hnd hnd, uint8_t stat) {
|
||||
int32_t err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_STATUS_EN, 1);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_STATUS, stat);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int32_t f_eeprom_wr_byte(t_x502_hnd hnd, uint32_t addr, uint8_t val) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
t_ltimer tmr;
|
||||
uint8_t stat = SST25_STATUS_BUSY;
|
||||
|
||||
/* разрешаем запись в EEPROM */
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_EN, 1);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_BYTE, ((addr & 0xFFFFFF) << 8) | val);
|
||||
if (err != X502_ERR_OK)
|
||||
l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_DIS, 1);
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(L502_FLASH_WRITE_TOUT));
|
||||
|
||||
/* Ожидаем завершения записи */
|
||||
while ((err == X502_ERR_OK) && (stat & SST25_STATUS_BUSY) && !ltimer_expired(&tmr)) {
|
||||
err = f_eeprom_rd_status(hnd, &stat);
|
||||
}
|
||||
|
||||
if ((err == X502_ERR_OK) && (stat & SST25_STATUS_BUSY)) {
|
||||
err = X502_ERR_FLASH_WRITE_TOUT;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int32_t l502_iface_flash_rd(t_x502_hnd hnd, uint32_t addr, uint8_t* data, uint32_t size) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
uint32_t val;
|
||||
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_SET_RD_ADDR, (addr & 0xFFFFFF) << 8);
|
||||
if (err == X502_ERR_OK)
|
||||
err = l502_port_fpga_reg_read(hnd, L502_REGS_EEPROM_RD_DWORD, &val);
|
||||
if (err == X502_ERR_OK) {
|
||||
unsigned int i;
|
||||
for (i=0; (i < sizeof(val)) && size; i++, size--) {
|
||||
*data++ = val & 0xFF;
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t l502_iface_flash_wr(t_x502_hnd hnd, uint32_t addr, const uint8_t* data, uint32_t size) {
|
||||
uint32_t i;
|
||||
int32_t err = X502_ERR_OK;
|
||||
for (i=0; (i < size) && (err == X502_ERR_OK); i++) {
|
||||
err = f_eeprom_wr_byte(hnd, addr+i, data[i]);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t l502_iface_flash_erase(t_x502_hnd hnd, uint32_t addr, uint32_t size) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
if (((addr & (L502_EEPROM_SMALL_SECTOR_SIZE-1)) ||
|
||||
(size & (L502_EEPROM_SMALL_SECTOR_SIZE-1)))) {
|
||||
err = X502_ERR_FLASH_SECTOR_BOUNDARY;
|
||||
}
|
||||
|
||||
while((size != 0) && (err == X502_ERR_OK)) {
|
||||
uint32_t er_size;
|
||||
/* разрешаем запись в EEPROM */
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_EN, 1);
|
||||
if (err == X502_ERR_OK) {
|
||||
uint8_t stat = SST25_STATUS_BUSY;
|
||||
t_ltimer tmr;
|
||||
/* проверяем - можем ли стереть целиком большой сектор или
|
||||
придется писать в мелкий */
|
||||
if ((size >= L502_EEPROM_BIG_SECTOR_SIZE) &&
|
||||
!(size & (L502_EEPROM_BIG_SECTOR_SIZE-1))) {
|
||||
er_size = L502_EEPROM_BIG_SECTOR_SIZE;
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_ERASE_64K, addr<<8);
|
||||
} else {
|
||||
er_size = L502_EEPROM_SMALL_SECTOR_SIZE;
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_ERASE_4K, addr<<8);
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(L502_FLASH_ERASE_TOUT));
|
||||
|
||||
/* ожидаем завершения стирания */
|
||||
while ((err == X502_ERR_OK) && (stat & SST25_STATUS_BUSY) && !ltimer_expired(&tmr)) {
|
||||
err = f_eeprom_rd_status(hnd, &stat);
|
||||
}
|
||||
|
||||
if ((err == X502_ERR_OK) && (stat & SST25_STATUS_BUSY)) {
|
||||
err = X502_ERR_FLASH_ERASE_TOUT;
|
||||
}
|
||||
|
||||
/* запрещаем запись, если произошла ошибка. при успешном стирании
|
||||
запись будут запрещена атоматически */
|
||||
if (err != X502_ERR_OK)
|
||||
l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_EN, 0);
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
addr += er_size;
|
||||
size -= er_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t l502_iface_flash_set_prot(t_x502_hnd hnd, uint32_t prot, const uint8_t* prot_data, uint32_t size) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
uint16_t prot_code = 0;
|
||||
if (size == 2) {
|
||||
prot_code = ((uint16_t)prot_data[1] << 8) | prot_data[0];
|
||||
}
|
||||
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_STATUS_EN, 1);
|
||||
if ((err == X502_ERR_OK) && (prot_code != 0))
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_HARD_WR_STATUS_EN, prot_code);
|
||||
if (err == X502_ERR_OK)
|
||||
err = l502_port_fpga_reg_write(hnd, L502_REGS_EEPROM_WR_STATUS, f_prot_bits[prot]);
|
||||
return err;
|
||||
}
|
||||
Reference in New Issue
Block a user