manually merged with ARM version

This commit is contained in:
2025-11-13 17:43:55 +03:00
parent 77005d7863
commit b7ba42765b
463 changed files with 119514 additions and 45 deletions

391
x502/x502api_bf.c Normal file
View File

@ -0,0 +1,391 @@
#include "x502api_private.h"
#include "ltimer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BF_LDR_HDR_SIZE (16)
#define BF_LDR_HDRSGN (0xAD)
#define BF_LDR_HDRPOS_SGN (3)
#define BF_LDR_FLAG_SAVE (0x0010) //не используется
#define BF_LDR_FLAG_AUX (0x0020) //не используется
#define BF_LDR_FLAG_FILL (0x0100)
#define BF_LDR_FLAG_QUICKBOOT (0x0200) //не используется
#define BF_LDR_FLAG_CALLBACK (0x0400) //не используется
#define BF_LDR_FLAG_INIT (0x0800) //не используется
#define BF_LDR_FLAG_IGNORE (0x1000)
#define BF_LDR_FLAG_INDIRECT (0x2000) //не используется
#define BF_LDR_FLAG_FIRST (0x4000)
#define BF_LDR_FLAG_FINAL (0x8000)
#define BF_WAIT_LOAD_RDY_TOUT 500
#define BF_MUTEX_LOCK_TOUT 1000
#define LDR_BUFF_SIZE 4096
#define BF_CHECK_ADDR(addr) (((addr) < 0xFFA0C000) && ((addr)>= 0xFFA0000)) || \
(((addr) < 0xFF908000) && ((addr) >=0xFF900000)) || \
(((addr) < 0xFF808000) && ((addr) >=0xFF800000)) || \
(((addr) < 0x2000000)) ? 0 : X502_ERR_BF_INVALID_ADDR
#define BF_CHECK_ADDR_SIZE(addr, size) BF_CHECK_ADDR(addr) ? X502_ERR_BF_INVALID_ADDR : \
BF_CHECK_ADDR(addr+size*4-1) ? X502_ERR_BF_INVALID_ADDR : 0
#define BF_CMD_FIRST_DATA_BLOCK_SIZE ((X502_BF_REQ_DATA_SIZE_MAX-offsetof(t_l502_bf_cmd, data))/4)
typedef struct st_bf_ldr_pkt {
uint8_t res;
uint8_t dma_mode;
uint16_t flags;
uint32_t addr;
uint32_t size;
uint32_t arg;
} t_bf_ldr_pkt;
/* Разбираем заголовок блока LDR-формата из буфера размером BF_LDR_HDR_SIZE
и сохраняем параметры в структуре pkt */
int f_parse_ldr_hdr(const uint8_t* hdr, t_bf_ldr_pkt* pkt) {
int err = 0;
uint32_t* pdw_buff = (uint32_t*)hdr;
uint8_t xor_ch = 0;
int i;
for (i=0; i < BF_LDR_HDR_SIZE; i++) {
xor_ch ^= hdr[i];
}
if ((xor_ch!=0) || (hdr[BF_LDR_HDRPOS_SGN] != BF_LDR_HDRSGN)) {
err = X502_ERR_LDR_FILE_FORMAT;
} else {
pkt->res = 0;
pkt->dma_mode = pdw_buff[0]&0xF;
pkt->flags = pdw_buff[0]&0xFFF0;
pkt->addr = pdw_buff[1];
pkt->size = pdw_buff[2];
pkt->arg = pdw_buff[3];
if ((pkt->flags & BF_LDR_FLAG_INIT) && (pkt->flags & BF_LDR_FLAG_FILL))
err = X502_ERR_LDR_FILE_FORMAT;
else if (pkt->flags & (BF_LDR_FLAG_CALLBACK | BF_LDR_FLAG_INDIRECT | BF_LDR_FLAG_INIT))
err = X502_ERR_LDR_FILE_UNSUP_FEATURE;
else if ((pkt->flags & BF_LDR_FLAG_INIT) && (pkt->addr != 0xFFA00000))
err = X502_ERR_LDR_FILE_UNSUP_STARTUP_ADDR;
}
return err;
}
static int32_t f_bf_mem_wr(t_x502_hnd hnd, uint32_t addr, const uint32_t* regs, uint32_t size) {
int32_t err = 0;
/* данные записываем блоками по L502_BF_REQ_DATA_SIZE */
while (!err && size) {
int put_size = (size < hnd->iface_hnd->bf_mem_block_size) ? size :
hnd->iface_hnd->bf_mem_block_size;
err = hnd->iface_hnd->bf_mem_block_wr(hnd, addr, regs, put_size);
if (!err) {
size -= put_size;
regs += put_size;
addr += put_size*4;
}
}
return err;
}
static int32_t f_bf_mem_rd(t_x502_hnd hnd, uint32_t addr, uint32_t* regs, uint32_t size) {
int err = 0;
while (!err && size) {
int get_size = (size < hnd->iface_hnd->bf_mem_block_size) ? size :
hnd->iface_hnd->bf_mem_block_size;
err = hnd->iface_hnd->bf_mem_block_rd(hnd, addr, regs, get_size);
if (!err) {
size -= get_size;
regs += get_size;
addr += get_size*4;
}
}
return err;
}
int32_t bf_fpga_reg_wr(t_x502_hnd hnd, uint32_t addr, uint32_t val) {
int32_t err = hnd->mode != X502_MODE_DSP ? X502_ERR_INVALID_MODE :
(hnd->bf_features & L502_BF_FEATURE_FPGA_REG_ACCESS) ?
X502_ERR_OK : X502_ERR_NOT_IMPLEMENTED;
if (err == X502_ERR_OK) {
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_FPGA_REG_WR, addr, &val, 1, NULL, 0,
X502_BF_CMD_DEFAULT_TOUT, NULL);
}
return err;
}
int32_t bf_fpga_reg_rd(t_x502_hnd hnd, uint32_t addr, uint32_t* val) {
int32_t err = hnd->mode != X502_MODE_DSP ? X502_ERR_INVALID_MODE :
(hnd->bf_features & L502_BF_FEATURE_FPGA_REG_ACCESS) ?
X502_ERR_OK : X502_ERR_NOT_IMPLEMENTED;
if (err == X502_ERR_OK) {
uint32_t recvd;
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_FPGA_REG_RD, addr, NULL, 0, val, 1,
X502_BF_CMD_DEFAULT_TOUT, &recvd);
if ((err == X502_ERR_OK) && (recvd < 1)) {
err = X502_ERR_BF_CMD_RETURN_INSUF_DATA;
}
}
return err;
}
static int32_t f_check_bf_firm(t_x502_hnd hnd) {
int32_t err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CMD, X502_BF_CMD_HDMA_RST);
if (!err) {
uint32_t rcv_wrds[2], recvd;
/* Проверяем версию прошивки BlackFin */
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_GET_PARAM, L502_BF_PARAM_FIRM_VERSION,
NULL, 0, rcv_wrds, 2, X502_BF_CMD_DEFAULT_TOUT, &recvd);
if (!err) {
if (recvd >= 1) {
hnd->bf_ver = rcv_wrds[0];
} else {
err = X502_ERR_BF_CMD_RETURN_INSUF_DATA;
}
hnd->bf_features = recvd >= 2 ? rcv_wrds[1] : 0;
}
}
/* Проверка состояния прошивки (запущен поток сбора или нет) */
if (!err) {
uint32_t mode, streams;
err = x502_bf_get_par(hnd, L502_BF_PARAM_STREAM_MODE, &mode, 1);
if (!err)
err = x502_bf_get_par(hnd, L502_BF_PARAM_ENABLED_STREAMS, &streams, 1);
if (!err) {
err = osspec_mutex_lock(hnd->mutex_cfg, BF_MUTEX_LOCK_TOUT);
if (!err) {
if (mode==L502_BF_MODE_IDLE) {
hnd->flags &= ~PRIV_FLAGS_STREAM_RUN;
} else {
hnd->flags |= PRIV_FLAGS_STREAM_RUN;
}
hnd->streams = streams;
osspec_mutex_release(hnd->mutex_cfg);
}
}
}
/* передаем информацию о модуле */
if (!err && !(hnd->flags & PRIV_FLAGS_STREAM_RUN)) {
uint32_t put_wrds[3];
uint32_t ch;
put_wrds[0] = hnd->info.devflags;
put_wrds[1] = hnd->info.fpga_ver | ((uint32_t)hnd->info.plda_ver<<16);
err = x502_bf_set_par(hnd, L502_BF_PARAM_MODULE_INFO, put_wrds, 2);
for (ch=0; !err && (ch < X502_DAC_CH_CNT); ch++) {
float* pk = (float*)&put_wrds[1];
float* po = (float*)&put_wrds[2];
put_wrds[0] = ch;
*pk = (float)hnd->info.cbr.dac[ch].k;
*po = (float)hnd->info.cbr.dac[ch].offs;
err = x502_bf_set_par(hnd, L502_BF_PARAM_DAC_COEF, put_wrds, 3);
}
}
if (!err && (hnd->mode!=X502_MODE_DSP))
err = X502_SetMode(hnd, X502_MODE_DSP);
return err;
}
X502_EXPORT(int32_t) X502_BfCheckFirmwareIsLoaded(t_x502_hnd hnd, uint32_t *version) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err) {
err = f_check_bf_firm(hnd);
if (!err && version)
*version = hnd->bf_ver;
}
return err;
}
X502_EXPORT(int32_t) X502_BfLoadFirmware(t_x502_hnd hnd, const char* filename) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
err = X502_ERR_BF_NOT_PRESENT;
if (!err) {
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
if (!err) {
err = hnd->iface_hnd->bf_firm_load(hnd, filename);
osspec_mutex_release(hnd->mutex_bf);
}
}
if (!err) {
SLEEP_MS(100);
err = f_check_bf_firm(hnd);
}
return err;
}
X502_EXPORT(int32_t) X502_BfMemWrite(t_x502_hnd hnd, uint32_t addr,
const uint32_t* regs, uint32_t size) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
err = X502_ERR_BF_NOT_PRESENT;;
if (!err)
err = BF_CHECK_ADDR_SIZE(addr, size);
if (!err)
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
if (!err) {
int32_t release_err;
err = f_bf_mem_wr(hnd, addr, regs, size);
release_err = osspec_mutex_release(hnd->mutex_bf);
if (!err)
err = release_err;
}
return err;
}
X502_EXPORT(int32_t) X502_BfMemRead(t_x502_hnd hnd, uint32_t addr,
uint32_t* regs, uint32_t size) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
err = X502_ERR_BF_NOT_PRESENT;
if (!err)
err = BF_CHECK_ADDR_SIZE(addr,size);
if (!err)
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
if (!err) {
int32_t release_err;
err = f_bf_mem_rd(hnd, addr, regs, size);
release_err = osspec_mutex_release(hnd->mutex_bf);
if (!err)
err = release_err;
}
return err;
}
static int f_bf_start_cmd(t_x502_hnd hnd, uint16_t cmd_code, uint32_t par,
const uint32_t* data, uint32_t size) {
int err = X502_CHECK_HND_OPENED(hnd);
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
err = X502_ERR_BF_NOT_PRESENT;
if (size > L502_BF_CMD_DATA_SIZE_MAX)
err = X502_ERR_BF_INVALID_CMD_DATA_SIZE;
if (!err)
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
if (!err) {
t_l502_bf_cmd cmd;
cmd.code = cmd_code;
cmd.data_size = size;
cmd.param = par;
cmd.result = 0;
cmd.status = L502_BF_CMD_STATUS_REQ;
if (size!=0) {
memcpy(cmd.data, data, size*sizeof(data[0]));
}
/* если размер больше, чем можем записать за раз, то сперва записываем
* хвост, чтобы не получилось, что информация о команде будет записана
* раньше данных */
if (size > BF_CMD_FIRST_DATA_BLOCK_SIZE) {
err = f_bf_mem_wr(hnd, X502_BF_MEMADDR_CMD+X502_BF_REQ_DATA_SIZE_MAX*4,
&cmd.data[BF_CMD_FIRST_DATA_BLOCK_SIZE],
size - BF_CMD_FIRST_DATA_BLOCK_SIZE);
size = BF_CMD_FIRST_DATA_BLOCK_SIZE;
}
if (!err) {
err = f_bf_mem_wr(hnd, X502_BF_MEMADDR_CMD, (const uint32_t*)&cmd,
(offsetof(t_l502_bf_cmd, data))/4 + size);
}
if (err) {
osspec_mutex_release(hnd->mutex_bf);
}
}
return err;
}
static int f_bf_cmd_check(t_x502_hnd hnd, int32_t *res) {
t_l502_bf_cmd cmd;
int err = f_bf_mem_rd(hnd, X502_BF_MEMADDR_CMD, (uint32_t*)&cmd,
X502_BF_REQ_DATA_SIZE_MIN);
if (!err) {
if (cmd.status != L502_BF_CMD_STATUS_DONE) {
err = X502_ERR_BF_CMD_IN_PROGRESS;
} else if (res) {
*res = cmd.result;
}
}
if (err != X502_ERR_BF_CMD_IN_PROGRESS)
osspec_mutex_release(hnd->mutex_bf);
return err;
}
X502_EXPORT(int32_t) X502_BfExecCmd(t_x502_hnd hnd, uint16_t cmd_code, uint32_t par,
const uint32_t* snd_data, uint32_t snd_size,
uint32_t* rcv_data, uint32_t rcv_size, uint32_t tout,
uint32_t* recvd_size) {
t_l502_bf_cmd cmd;
int done = 0;
t_ltimer tmr;
int err;
ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(tout));
err = f_bf_start_cmd(hnd, cmd_code, par, snd_data, snd_size);
while (!err && !done) {
err = f_bf_cmd_check(hnd, &cmd.result);
if (!err) {
done = 1;
if (rcv_size != 0) {
err = X502_BfMemRead(hnd, X502_BF_MEMADDR_CMD, (uint32_t*)&cmd,
(offsetof(t_l502_bf_cmd, data))/4 + rcv_size);
memcpy(rcv_data, cmd.data, rcv_size*sizeof(rcv_data[0]));
if (recvd_size!=NULL)
*recvd_size = cmd.data_size;
}
if (!err)
err = cmd.result;
} else if (err==X502_ERR_BF_CMD_IN_PROGRESS) {
if (ltimer_expired(&tmr)) {
err = X502_ERR_BF_CMD_TIMEOUT;
osspec_mutex_release(hnd->mutex_bf);
} else {
err = 0;
SLEEP_MS(20);
}
}
}
return err;
}