Files
kunlun/dtest/dtest3/common/dtest_fpga_communication.c
2024-09-28 14:24:04 +08:00

285 lines
8.7 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "iot_uart_h.h"
#include "dtest_fpga_communication.h"
#include "iot_gptmr_api.h"
#include "uart.h"
#include "uart_e.h"
extern struct uart_ctrl uart_e_ctrl;
#define dtest_uart_rxc() (uart_e_ctrl.rx_fifo_cnt(UART_PT1))
#define dtest_uart_txc() (UART_TX_FIFO_LEN - uart_e_ctrl.tx_fifo_cnt(UART_PT1))
#define dtest_uart_putc(x) (uart_e_ctrl.putc(UART_PT1, x))
#define dtest_uart_getc() (uart_e_ctrl.getc(UART_PT1))
#define DTEST_UART_MAX_BUFFER 1024
static char g_dtest_rbuf[DTEST_UART_MAX_BUFFER];
static char g_dtest_tbuf[DTEST_UART_MAX_BUFFER];
#define DTEST_UART_TRX_TIMEOUT 10000 /* 10 Seconds. */
static const unsigned short CRC16_Table[256]= {
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
};
static unsigned short CRC16(const char *buf, int len)
{
register int counter;
register unsigned short crc = 0;
for( counter = 0; counter < len; counter++)
crc = (crc<<8) ^ CRC16_Table[((crc>>8) ^ *(char *)buf++)&0x00FF];
return crc;
}
static uint16_t dtest_cmcn_calc_crc16(dtest_cmd_header_t *dpntr)
{
uint16_t res = 0;
uint32_t len = dpntr->data_length + sizeof(uint16_t);
res = CRC16((char*)&dpntr->data_length, len);
return res;
}
uint32_t dtest_cmcn_tm_calc_delta (uint32_t old_t, uint32_t new_t)
{
return new_t >= old_t ? (new_t - old_t) : ((uint32_t)(-1) - old_t + new_t);
}
static uint32_t dtest_cmcn_timeout_start()
{
return iot_gp_timer_get_curr_ts();
}
static int dtest_cmcn_timeout_check(uint32_t old_t)
{
uint32_t new_t = iot_gp_timer_get_curr_ts();
if (DTEST_UART_TRX_TIMEOUT*1000 <= dtest_cmcn_tm_calc_delta (old_t, new_t)) {
return 1;
} else {
return 0;
}
}
static int dtest_cmcn_make_frame(void *dpntr, int len)
{
dtest_cmd_header_t *pntr_hd = (dtest_cmd_header_t *)g_dtest_tbuf;
dtest_cmd_tail_t *pntr_tl = (dtest_cmd_tail_t *)(pntr_hd->data + pntr_hd->data_length);
pntr_hd ->pre_code = 0xAAAA;
os_mem_cpy(pntr_hd->data, dpntr, len);
pntr_hd->data_length = len;
pntr_tl = (dtest_cmd_tail_t *)(pntr_hd->data + pntr_hd->data_length);
pntr_tl->crc16 = dtest_cmcn_calc_crc16(pntr_hd);
pntr_tl->pst_code = 0xFF;
return sizeof(*pntr_hd) + sizeof(*pntr_tl) + pntr_hd->data_length;
}
static int dtest_cmcn_parse_frame(void *dpntr, int len)
{
int rcvLen = 0, rcvFrmlen = 0, frmLen = -1;
char *pntr_frm = g_dtest_rbuf;
uint8_t rcvDone = 0;
dtest_cmd_header_t *pntr_hd = (dtest_cmd_header_t *)g_dtest_rbuf;
dtest_cmd_tail_t *pntr_tl = NULL;
uint32_t index = 0;
uint32_t tm_old = 0;
/* Clear the rcv frame buffer. */
os_mem_set(g_dtest_rbuf, 0, DTEST_UART_MAX_BUFFER);
tm_old = dtest_cmcn_timeout_start();
/* Receive from UART & parse the frame. */
do
{
/* 1. Read data from UART */
/* 2. Search AAAA & get dataLength. */
/* 3. Wait whole frame is complate. */
/* 4. CRC check. */
if(dtest_uart_rxc() > 0)
{
*pntr_frm = dtest_uart_getc();
pntr_frm++;
rcvLen++;
rcvFrmlen++;
}
/* Receive data over buffer size. */
if (rcvLen > DTEST_UART_MAX_BUFFER) {
break;
}
/* Update the head position to search pre_code AAAA. */
pntr_hd = (dtest_cmd_header_t *)(g_dtest_rbuf + index);
/* If rcv frame length over the cmd head size, start to search pre_code. */
if (rcvFrmlen >= sizeof(dtest_cmd_header_t)) {
if (pntr_hd->pre_code == 0xAAAA) {
frmLen = sizeof(dtest_cmd_header_t) + sizeof(dtest_cmd_tail_t) +
pntr_hd->data_length;
pntr_tl = (dtest_cmd_tail_t *)((uint8_t *)pntr_hd +
sizeof(dtest_cmd_header_t) + pntr_hd->data_length);
} else {
/* If not find the pre_code, shift head position one btye to right, */
/* and the rcv frame length minus one. */
index++;
rcvFrmlen--;
}
}
/* The whole length received complete. */
if (rcvFrmlen == frmLen) {
if (pntr_tl->crc16 == dtest_cmcn_calc_crc16(pntr_hd) &&
pntr_tl->pst_code == 0xFF) {
if (len >= pntr_hd->data_length) {
os_mem_cpy(dpntr, pntr_hd->data, pntr_hd->data_length);
rcvLen = pntr_hd->data_length;
rcvDone = 1;
}
break;
} else {
/* CRC or post code wrong. */
break;
}
}
if (dtest_cmcn_timeout_check(tm_old)) {
break;
}
} while (rcvDone == 0);
if (rcvDone == 0) {
rcvLen = 0;
}
return rcvLen;
}
int dtest_cmcn_send(void *dpntr, int len)
{
int frmLen, sentLen = 0, timeout = 0;
char *pntr_frm = g_dtest_tbuf;
uint8_t retry = 0;
uint32_t tm_old = 0;
frmLen = dtest_cmcn_make_frame(dpntr, len);
tm_old = dtest_cmcn_timeout_start();
while(sentLen < frmLen)
{
if(dtest_uart_txc() > 0)
{
dtest_uart_putc(*pntr_frm);
pntr_frm++;
sentLen++;
}
if(dtest_cmcn_timeout_check(tm_old))
{
sentLen = 0;
pntr_frm = g_dtest_tbuf;
tm_old = dtest_cmcn_timeout_start();
retry++;
if (retry >= 3) {
timeout = 1;
break;
}
continue;
}
}
if(timeout)
{
/* TODO */
sentLen = 0;
return sentLen;
}
if(sentLen == frmLen)
{
sentLen -= sizeof(dtest_cmd_header_t) + sizeof(dtest_cmd_tail_t);
}
else
{
sentLen = 0;
}
return sentLen;
}
int dtest_cmcn_receive(void *dpntr, int len)
{
int dataLen = 0;
dataLen = dtest_cmcn_parse_frame(dpntr, len);
return dataLen;
}
int dtest_cmcn_init(uint8_t rx_pin, uint8_t tx_pin)
{
/* Init UART port. */
uart_e_ctrl.init(UART_PT1);
/* Bind the uart signal into tx and rx pin. */
iot_uart_set_pin(UART_PT1, rx_pin, tx_pin);
return 0;
}