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
|