Files
E502_ADC_BF_PC_companion/x502/x502api_eeprom.c

214 lines
8.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "x502api_private.h"
#include "x502_eeprom.h"
#include "fast_crc.h"
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "../devs/e502/e502_fpga_regs.h"
#define X502_CHECK_ADDR(hnd, addr, size) ((addr+size)>hnd->info.flash_size ? \
X502_ERR_FLASH_INVALID_ADDR : (size==0) ? X502_ERR_FLASH_INVALID_SIZE : X502_ERR_OK)
X502_EXPORT(int32_t) X502_FlashRead(t_x502_hnd hnd, uint32_t addr, uint8_t* data,
uint32_t size) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (err==X502_ERR_OK) {
err = X502_CHECK_ADDR(hnd, addr, size);
}
if (err==X502_ERR_OK) {
for ( ; (size!=0) && (err==X502_ERR_OK); ) {
uint32_t rd_size = size;
if (rd_size > hnd->iface_hnd->flash_rd_size)
rd_size = hnd->iface_hnd->flash_rd_size;
err = hnd->iface_hnd->flash_rd(hnd, addr, data, rd_size);
if (err==X502_ERR_OK) {
data+=rd_size;
addr+=rd_size;
size-=rd_size;
}
}
}
return err;
}
X502_EXPORT(int32_t) X502_FlashWrite(t_x502_hnd hnd, uint32_t addr,
const uint8_t* data, uint32_t size) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (err==X502_ERR_OK) {
err = X502_CHECK_ADDR(hnd, addr, size);
}
if (err==X502_ERR_OK) {
for ( ; (size!=0) && (err==X502_ERR_OK); ) {
uint32_t wr_size = size;
if (wr_size > hnd->iface_hnd->flash_wr_size)
wr_size = hnd->iface_hnd->flash_wr_size;
err = hnd->iface_hnd->flash_wr(hnd, addr, data, wr_size);
if (err==X502_ERR_OK) {
data+=wr_size;
addr+=wr_size;
size-=wr_size;
}
}
}
return err;
}
X502_EXPORT(int32_t) X502_FlashErase(t_x502_hnd hnd, uint32_t addr, uint32_t size) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (err==X502_ERR_OK) {
err = X502_CHECK_ADDR(hnd, addr, size);
}
if (err==X502_ERR_OK) {
err = hnd->iface_hnd->flash_erase(hnd, addr, size);
}
return err;
}
X502_EXPORT(int32_t) X502_FlashWriteEnable(t_x502_hnd hnd) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (err==X502_ERR_OK) {
err = hnd->iface_hnd->flash_set_prot(hnd, X502_EEPROM_PROT_WR_USER, NULL, 0);
}
return err;
}
X502_EXPORT(int32_t) X502_FlashWriteDisable(t_x502_hnd hnd) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (err==X502_ERR_OK) {
err = hnd->iface_hnd->flash_set_prot(hnd, X502_EEPROM_PROT_ALL, NULL, 0);
}
return err;
}
X502_EXPORT(int32_t) X502_FlashSetProtection(t_x502_hnd hnd, uint32_t prot, uint8_t *prot_data, uint32_t prot_data_size) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (err==X502_ERR_OK) {
err = hnd->iface_hnd->flash_set_prot(hnd, prot, prot_data, prot_data_size);
}
return err;
}
bool x502_is_E16(t_x502_hnd hnd) {
if (strcmp(hnd->info.name, E16_DEVICE_NAME) == 0) {
return true;
} else {
return false;
}
}
/** Функция проверяет правильность информации о устройстве, записанной в EEPROM.
При наличии верной инофрмации, из EEPROM считывается название устройства и
серийный номер, а так же, при наличии, калибровочные коэффициенты */
int x502_check_eeprom(t_x502_hnd hnd, uint32_t flags) {
int err;
uint32_t sign, size;
if (x502_is_E16(hnd)) {
// в E16 добавился новый регистр и мы можем узнать размер flash-памяти
uint32_t flash_size;
err = hnd->iface_hnd->fpga_reg_read(hnd, E502_REGS_ARM_FLASHSIZE, &flash_size);
if (err != X502_ERR_OK) {
hnd->info.flash_size = 0;
return err;
}
hnd->info.flash_size = flash_size;
} else {
hnd->info.flash_size = X502_EEPROM_SIZE;
}
hnd->info.devflags &= ~(X502_DEVFLAGS_FLASH_DATA_VALID |
((flags & X502_RELOAD_FLAGS_NO_ADC) ? 0 : X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID) |
((flags & X502_RELOAD_FLAGS_NO_DAC) ? 0 : X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID));
/* проверяем признак правильного описателя в EEPROM и его размер */
err = X502_FlashRead(hnd, X502_EEPROM_ADDR_DESCR, (uint8_t*)&sign, (uint32_t)sizeof(sign));
if (err == X502_ERR_OK)
err = X502_FlashRead(hnd, X502_EEPROM_ADDR_DESCR+sizeof(sign), (uint8_t*)&size, (uint32_t)sizeof(size));
if (err == X502_ERR_OK) {
if ((sign == X502_EEPROM_SIGN) && (size >= X502_DESCR_MIN_SIZE) && (size <= X502_DESCR_MAX_SIZE)) {
t_x502_descr* pdescr = (t_x502_descr*)malloc(size);
/* читаем весь описатель */
if (pdescr!=NULL) {
err = X502_FlashRead(hnd, X502_EEPROM_ADDR_DESCR, (uint8_t*)pdescr, size);
} else {
err = X502_ERR_MEMORY_ALLOC;
}
/* сверяем crc */
if (err == X502_ERR_OK) {
uint32_t crc, crc2;
crc = CRC32_Block8(0, (uint8_t*)pdescr, (uint32_t)(size-sizeof(crc)));
memcpy(&crc2, &((uint8_t*)pdescr)[size-4], 4);
if (crc == crc2) {
hnd->info.devflags |= X502_DEVFLAGS_FLASH_DATA_VALID;
memcpy(hnd->info.serial, pdescr->hdr.serial, sizeof(pdescr->hdr.serial));
memcpy(hnd->info.name, pdescr->hdr.name, sizeof(pdescr->hdr.name));
memcpy(hnd->info.factory_mac, pdescr->hdr.factory_mac, sizeof(pdescr->hdr.factory_mac));
if (!(flags & X502_RELOAD_FLAGS_NO_ADC)) {
if ((pdescr->cbr_adc.hdr.cbr_sign == X502_EEPROM_CBR_SIGN) &&
(pdescr->cbr_adc.hdr.format == X502_EEPROM_CBR_FROMAT) &&
(pdescr->cbr_adc.hdr.src == X502_EEPROM_CBR_SRC_ADC) &&
(pdescr->cbr_adc.hdr.range_cnt == X502_ADC_RANGE_CNT || pdescr->cbr_adc.hdr.range_cnt == E16_ADC_RANGE_CNT) &&
(pdescr->cbr_adc.hdr.channel_cnt == 1)) {
unsigned int i;
hnd->info.devflags |= X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID;
for (i=0; (i < pdescr->cbr_adc.hdr.range_cnt) && (err == X502_ERR_OK); i++) {
if (x502_is_E16(hnd)) {
if (i > E16_ADC_RANGE_CNT) {
break;
}
} else {
if (i > X502_ADC_RANGE_CNT) {
break;
}
}
err = X502_SetAdcCoef(hnd, i, pdescr->cbr_adc.coefs[i].k,
pdescr->cbr_adc.coefs[i].offs);
}
}
}
if (!(flags & X502_RELOAD_FLAGS_NO_DAC)) {
if ((pdescr->cbr_dac.hdr.cbr_sign == X502_EEPROM_CBR_SIGN) &&
(pdescr->cbr_dac.hdr.format == X502_EEPROM_CBR_FROMAT) &&
(pdescr->cbr_dac.hdr.src == X502_EEPROM_CBR_SRC_DAC) &&
(pdescr->cbr_dac.hdr.range_cnt == 1) &&
(pdescr->cbr_dac.hdr.channel_cnt == X502_DAC_CH_CNT)) {
unsigned int i;
hnd->info.devflags |= X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID;
for (i=0; (i < pdescr->cbr_dac.hdr.channel_cnt) &&
(i < X502_ADC_RANGE_CNT) && (err == X502_ERR_OK); i++) {
err = X502_SetDacCoef(hnd, i, pdescr->cbr_dac.coefs[i].k,
pdescr->cbr_dac.coefs[i].offs);
}
}
}
}
}
free(pdescr);
}
}
return err;
}
X502_EXPORT(int32_t) X502_ReloadDevInfo(t_x502_hnd hnd, uint32_t flags) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if ((err==X502_ERR_OK) && (hnd->iface_hnd->reload_dev_info!=NULL))
err = hnd->iface_hnd->reload_dev_info(hnd);
if (err==X502_ERR_OK)
err = x502_check_eeprom(hnd, flags);
return err;
}