351 lines
8.8 KiB
C
351 lines
8.8 KiB
C
#include "system/includes.h"
|
||
#include "config/config_interface.h"
|
||
#include "system/event.h"
|
||
#include "app_online_cfg.h"
|
||
#include "asm/uart_dev.h"
|
||
#include "app_config.h"
|
||
#include "app_sound_box_tool.h"
|
||
|
||
#define LOG_TAG "[CI-UART]"
|
||
/* #define LOG_ERROR_ENABLE */
|
||
/* #define LOG_INFO_ENABLE */
|
||
/* #define LOG_DUMP_ENABLE */
|
||
#include "debug.h"
|
||
|
||
#if (TCFG_ONLINE_ENABLE || TCFG_SOUNDBOX_TOOL_ENABLE)
|
||
struct config_uart {
|
||
u32 baudrate;
|
||
int flowcontrol;
|
||
const char *dev_name;
|
||
};
|
||
|
||
struct uart_hdl {
|
||
|
||
struct config_uart config;
|
||
|
||
uart_bus_t *udev;
|
||
void *dbuf;
|
||
|
||
void *pRxBuffer;
|
||
|
||
u8 ucRxIndex;
|
||
u8 rx_type;
|
||
|
||
u16 data_length;
|
||
|
||
void *pTxBuffer;
|
||
|
||
void (*packet_handler)(const u8 *packet, int size);
|
||
};
|
||
|
||
|
||
typedef struct {
|
||
//head
|
||
u16 preamble;
|
||
u8 type;
|
||
u16 length;
|
||
u8 crc8;
|
||
u16 crc16;
|
||
u8 payload[0];
|
||
} _GNU_PACKED_ uart_packet_t;
|
||
|
||
#define UART_FORMAT_HEAD sizeof(uart_packet_t)
|
||
|
||
typedef struct {
|
||
//head
|
||
u16 preamble0;
|
||
u8 preamble1;
|
||
u16 crc16;
|
||
u8 length;
|
||
u8 type;
|
||
u8 sq;
|
||
u8 payload[0];
|
||
} _GNU_PACKED_ uart_tool_packet_t;
|
||
|
||
#define UART_TOOL_FORMAT_HEAD sizeof(uart_tool_packet_t)
|
||
|
||
extern u16 crc_get_16bit(const void *src, u32 len);
|
||
|
||
static void dummy_handler(const u8 *packet, int size);
|
||
|
||
#define UART_PREAMBLE 0xBED6
|
||
#define UART_NEW_TOOL_PREAMBLE0 0xAA5A
|
||
#define UART_NEW_TOOL_PREAMBLE1 0xA5
|
||
|
||
#define UART_RX_SIZE 0x100
|
||
#define UART_TX_SIZE 0x30
|
||
#define UART_DB_SIZE 0x100
|
||
#define UART_BAUD_RATE 115200
|
||
|
||
#ifdef HAVE_MALLOC
|
||
static struct uart_hdl *hdl;
|
||
#define __this (hdl)
|
||
#else
|
||
static struct uart_hdl hdl;
|
||
#define __this (&hdl)
|
||
|
||
static u8 pRxBuffer_static[UART_RX_SIZE] __attribute__((aligned(4))); //rx memory
|
||
static u8 pTxBuffer_static[UART_TX_SIZE] __attribute__((aligned(4))); //tx memory
|
||
static u8 devBuffer_static[UART_DB_SIZE] __attribute__((aligned(4))); //dev DMA memory
|
||
#endif
|
||
|
||
void ci_data_rx_handler(u8 type)
|
||
{
|
||
u16 crc16;
|
||
uart_tool_packet_t *p_newtool;
|
||
|
||
__this->rx_type = type;
|
||
|
||
if (type == CI_UART && __this->udev) {
|
||
__this->data_length += __this->udev->read(&__this->pRxBuffer[__this->data_length], (UART_RX_SIZE - __this->data_length), 0);//串口读取buf剩余空间的长度,实际长度比buf长,导致越界改写问题
|
||
}
|
||
|
||
/* log_info("Rx : %d", __this->data_length); */
|
||
/* log_info_hexdump(__this->pRxBuffer, __this->data_length); */
|
||
if (__this->data_length > UART_RX_SIZE) {
|
||
log_error("Wired");
|
||
}
|
||
|
||
u8 *tmp_buf = NULL;
|
||
tmp_buf = __this->pRxBuffer;
|
||
if (__this->data_length >= 2) {
|
||
unsigned i = 0;
|
||
for (i = 0; i < __this->data_length - 1; ++i) {
|
||
if ((tmp_buf[i] == 0x5A) && (tmp_buf[i + 1] == 0xAA) && (tmp_buf[i + 2] == 0xA5)) {
|
||
break;
|
||
}
|
||
}
|
||
if (i != 0) {
|
||
__this->data_length -= i;
|
||
/* printf("__this->data_length %d i %d\n", __this->data_length, i); */
|
||
if (__this->data_length > 0) {
|
||
memmove(&__this->pRxBuffer[0], &tmp_buf[i], __this->data_length);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (__this->data_length <= UART_TOOL_FORMAT_HEAD) {
|
||
return;
|
||
}
|
||
|
||
p_newtool = __this->pRxBuffer;
|
||
|
||
if ((p_newtool->preamble0 != UART_NEW_TOOL_PREAMBLE0) || (p_newtool->preamble1 != UART_NEW_TOOL_PREAMBLE1)) {
|
||
log_error("preamble err\n");
|
||
log_info_hexdump(__this->pRxBuffer, __this->data_length);
|
||
goto reset_buf;
|
||
}
|
||
|
||
if (__this->data_length >= p_newtool->length + 6) {
|
||
crc16 = crc_get_16bit(&p_newtool->length, p_newtool->length + 1);
|
||
/* log_info("CRC16 0x%x / 0x%x", crc16, p_newtool->crc16); */
|
||
if (p_newtool->crc16 != crc16) {
|
||
log_error("crc16 err\n");
|
||
log_info_hexdump(__this->pRxBuffer, __this->data_length);
|
||
goto reset_buf;
|
||
}
|
||
/* log_info_hexdump(p_newtool, p_newtool->length + 6); */
|
||
online_cfg_tool_data_deal(p_newtool, p_newtool->length + 6);
|
||
} else {
|
||
return;
|
||
}
|
||
|
||
reset_buf:
|
||
__this->data_length = 0;
|
||
}
|
||
|
||
static void ci_uart_isr_cb(void *ut_bus, u32 status)
|
||
{
|
||
if (status == UT_TX) {
|
||
return ;
|
||
}
|
||
struct sys_event e;
|
||
e.type = SYS_DEVICE_EVENT;
|
||
e.arg = (void *)DEVICE_EVENT_FROM_CI_UART;
|
||
e.u.dev.event = 0;
|
||
e.u.dev.value = 0;
|
||
sys_event_notify(&e);
|
||
}
|
||
|
||
static int ci_uart_init()
|
||
{
|
||
struct uart_platform_data_t ut = {0};
|
||
ut.tx_pin = TCFG_ONLINE_TX_PORT;
|
||
ut.rx_pin = TCFG_ONLINE_RX_PORT;
|
||
ut.baud = __this->config.baudrate;
|
||
ut.rx_timeout = 1;
|
||
ut.isr_cbfun = ci_uart_isr_cb;
|
||
ut.rx_cbuf = devBuffer_static;
|
||
ut.rx_cbuf_size = UART_DB_SIZE;
|
||
ut.frame_length = UART_DB_SIZE;
|
||
/* JL_CLOCK->CLK_CON1 |= BIT(11); */
|
||
/* JL_CLOCK->CLK_CON1 &= ~BIT(10); */
|
||
__this->dbuf = devBuffer_static;
|
||
__this->data_length = 0;
|
||
__this->udev = (uart_bus_t *)uart_dev_open(&ut);
|
||
if (__this->udev == NULL) {
|
||
log_error("open uart dev err\n");
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static void ci_uart_putbyte(char a)
|
||
{
|
||
if (__this->udev) {
|
||
__this->udev->putbyte(a);
|
||
}
|
||
}
|
||
|
||
void ci_uart_write(char *buf, u16 len)
|
||
{
|
||
if (__this->udev) {
|
||
__this->udev->write(buf, len);
|
||
}
|
||
}
|
||
|
||
static void dummy_handler(const u8 *packet, int size)
|
||
{
|
||
log_error("Dummy");
|
||
}
|
||
|
||
static void clock_critical_enter(void)
|
||
{
|
||
|
||
}
|
||
static void clock_critical_exit(void)
|
||
{
|
||
if (__this->udev) {
|
||
__this->udev->set_baud(__this->config.baudrate);
|
||
}
|
||
}
|
||
CLOCK_CRITICAL_HANDLE_REG(ci, clock_critical_enter, clock_critical_exit)
|
||
|
||
static void ci_dev_init(const void *config)
|
||
{
|
||
#ifdef HAVE_MALLOC
|
||
__this = malloc(sizeof(struct uart_hdl));
|
||
ASSERT(__this, "Fatal error");
|
||
|
||
memset(__this, 0x0, sizeof(struct uart_hdl));
|
||
|
||
__this->pRxBuffer = malloc(UART_RX_SIZE);
|
||
ASSERT(__this->pRxBuffer, "Fatal error");
|
||
|
||
__this->pTxBuffer = malloc(UART_TX_SIZE);
|
||
ASSERT(__this->pTxBuffer, "Fatal error");
|
||
#else
|
||
log_info("Static");
|
||
__this->pRxBuffer = pRxBuffer_static;
|
||
__this->pTxBuffer = pTxBuffer_static;
|
||
#endif
|
||
|
||
__this->packet_handler = dummy_handler;
|
||
|
||
ci_transport_config_uart_t *ci_config_uart = (ci_transport_config_uart_t *)config;
|
||
|
||
__this->config.baudrate = ci_config_uart->baudrate_init;
|
||
__this->config.flowcontrol = ci_config_uart->flowcontrol;
|
||
__this->config.dev_name = ci_config_uart->device_name;
|
||
|
||
log_info("baudrate : %d", __this->config.baudrate);
|
||
log_info("flowcontrol: %d", __this->config.flowcontrol);
|
||
}
|
||
|
||
static int ci_dev_open(void)
|
||
{
|
||
ci_uart_init();
|
||
return 0;
|
||
}
|
||
|
||
static int ci_dev_close(void)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static void ci_dev_register_packet_handler(void (*handler)(const u8 *packet, int size))
|
||
{
|
||
__this->packet_handler = handler;
|
||
}
|
||
|
||
static int ci_dev_send_packet(const u8 *packet, int size)
|
||
{
|
||
/* dev_stream_out(); */
|
||
int i = 0;
|
||
uart_packet_t *p = (uart_packet_t *)__this->pTxBuffer;
|
||
|
||
p->preamble = UART_PREAMBLE;
|
||
p->type = 0;
|
||
p->length = size;
|
||
p->crc8 = crc_get_16bit(p, UART_FORMAT_HEAD - 3) & 0xff;
|
||
p->crc16 = crc_get_16bit(packet, size);
|
||
|
||
size += UART_FORMAT_HEAD;
|
||
ASSERT(size <= UART_TX_SIZE, "Fatal Error");
|
||
|
||
memcpy(p->payload, packet, size);
|
||
|
||
/* log_info("Tx : %d", size); */
|
||
/* log_info_hexdump(p, size); */
|
||
if (__this->rx_type == CI_UART) {
|
||
#if 0
|
||
while (size--) {
|
||
ci_uart_putbyte(((char *)p)[i++]);
|
||
}
|
||
#else
|
||
ci_uart_write(p, size);
|
||
#endif
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int ci_dev_can_send_packet_now(uint8_t packet_type)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
// get dev api skeletons
|
||
static const ci_transport_t ci_transport_uart = {
|
||
/* const char * name; */ "CI_UART",
|
||
/* void (*init) (const void *transport_config); */ &ci_dev_init,
|
||
/* int (*open)(void); */ &ci_dev_open,
|
||
/* int (*close)(void); */ &ci_dev_close,
|
||
/* void (*register_packet_handler)(void (*handler)(...); */ &ci_dev_register_packet_handler,
|
||
/* int (*can_send_packet_now)(uint8_t packet_type); */ &ci_dev_can_send_packet_now,
|
||
/* int (*send_packet)(...); */ &ci_dev_send_packet,
|
||
};
|
||
|
||
const ci_transport_t *ci_transport_uart_instance(void)
|
||
{
|
||
return &ci_transport_uart;
|
||
}
|
||
|
||
|
||
|
||
#endif
|
||
|
||
#ifdef CONFIG_AC608N
|
||
//该函数在蓝牙库实现,608没有蓝牙库,在此重定义
|
||
u16 crc_get_16bit(const void *src, u32 len)
|
||
{
|
||
/* log_info(__func__); */
|
||
u8 *p = (u8 *)src;
|
||
u16 ret;
|
||
OS_SR_ALLOC();
|
||
// vm_mutex_enter();
|
||
OS_ENTER_CRITICAL();
|
||
JL_CRC->REG = 0 ;
|
||
|
||
while (len--) {
|
||
JL_CRC->FIFO = *p++;
|
||
}
|
||
__asm__ volatile("csync");
|
||
ret = JL_CRC->REG;
|
||
OS_EXIT_CRITICAL();
|
||
// vm_mutex_exit();
|
||
/* printf("CRC16 %02x\r\n", ret); */
|
||
return ret;
|
||
}
|
||
#endif
|