214 lines
8.6 KiB
C
214 lines
8.6 KiB
C
#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;
|
||
}
|