UART Demo
```language
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "osa.h"
#include "UART.h"
#include "sockets.h"
#include "ip_addr.h"
#include "netdb.h"
#include "sys.h"
#include "sdk_api.h"
#undef printf
#define printf(fmt, args...) do { fatal_printf("[sdk]"fmt, ##args); } while(0)
#define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )
#define sleep(x) OSATaskSleep((x) * 200)//second
extern UART_Port gATUARTIntPortNum;
#define DATA_MODE 0
#define AT_MODE 1
#define MAX_LINE_SIZE 260
#define AT_CMD_NAME_MAX_LEN 16
typedef enum {
DSAT_CMD_PREP_STATE_HUNT,
DSAT_CMD_PREP_STATE_FOUND_A,
DSAT_CMD_PREP_STATE_FOUND_AT,
} dsat_cmd_prep_state_enum_type;
typedef struct dsat_sio_info_s {
char cmd_line_buffer[MAX_LINE_SIZE];
char *build_cmd_ptr;
dsat_cmd_prep_state_enum_type at_cmd_prep_state;
} dsat_sio_info_s_type;
typedef enum {
DSAT_OK = 0,
DSAT_NO_CARRIER = 3,
DSAT_ERROR = 4,
} dsat_result_enum_type;
typedef struct {
int result;
char *response;
} AtCmdResponse;
static int dtu_atcmd_regen(char *atName, char *atLine, AtCmdResponse *resp);
static int dtu_atcmd_regtp(char *atName, char *atLine, AtCmdResponse *resp);
static int dtu_atcmd_regdt(char *atName, char *atLine, AtCmdResponse *resp);
typedef struct {
unsigned char at_cmd_name[AT_CMD_NAME_MAX_LEN + 1];
int (*proc_func)(char *, char *, AtCmdResponse *);
} ATCmdTable;
static ATCmdTable dtu_atcmd_table[] = {
{ "+REGEN", dtu_atcmd_regen },
{ "+REGTP", dtu_atcmd_regtp },
{ "+REGDT", dtu_atcmd_regdt }
// add
};
static dsat_sio_info_s_type g_sio_info;
extern OSMsgQRef MsgUartData_sdk;
extern void set_UartDataSwitch_sdk(BOOL flag);
extern BOOL get_UartDataSwitch_sdk(void);
static void uartdata_thread(void);
uint8_t serial_mode; // 0:DATA_MODE 1:AT_MDOE
// Device bootup hook before Phase1Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase1Inits_enter(void);
// Device bootup hook after Phase1Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase1Inits_exit(void);
// Device bootup hook before Phase2Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase2Inits_enter(void);
// Device bootup hook after Phase2Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase2Inits_exit(void);
void Phase1Inits_enter(void)
{
}
void Phase1Inits_exit(void)
{
}
void Phase2Inits_enter(void)
{
}
void Phase2Inits_exit(void)
{
OSA_STATUS status;
printf("%s[%d]: starting...\n", __FUNCTION__, __LINE__);
status = OSAMsgQCreate(&MsgUartData_sdk, "MsgUartData_sdk", sizeof(MsgUartDataParam_sdk), 500, OS_FIFO);
DIAG_ASSERT(status == OS_SUCCESS);
sys_thread_new("uartdata_thread", uartdata_thread, NULL, DEFAULT_THREAD_STACKSIZE*2, 161);
}
/* process transparent data function */
static void send_serial_data(char *transData, int data_len)
{
printf("%s[%d]: DATA_MODE recvdata: %s\n", __FUNCTION__, __LINE__, transData);
}
/* This function send data to uart. */
static void send_to_uart(char *toUart, int length)
{
char *sendData = NULL;
printf("%s[%d]:toUart=%s, length=%d\n", __FUNCTION__, __LINE__, toUart, length);
sendData = (char *)malloc(length+1);
ASSERT(sendData != NULL);
memset(sendData, 0, length+1);
memcpy(sendData, toUart, length);
sendData[length] = '\0';
printf("%s[%d]:send to uart data=%s, length=%d\n", __FUNCTION__, __LINE__, sendData, length);
send_data_2uart(gATUARTIntPortNum, (UINT8 *)sendData, length);
printf("%s[%d]:sendData==NULL = %d\n", __FUNCTION__, __LINE__, (sendData==NULL));
if (sendData)
free(sendData);
}
static void check_serial_mode(MsgUartDataParam_sdk *msgUartData)
{
printf("%s[%d]:check_serial_mode=%d\n", __FUNCTION__, __LINE__, serial_mode);
if (serial_mode == DATA_MODE) {
if(msgUartData->len == 3 && memcmp(msgUartData->UArgs, "+++", 3) == 0) {
serial_mode = 0xFF;
send_to_uart("a", 1);
// T0D0: Exit 0xff mode after 3 seconds, change to DATA_MODE
}
} else if (serial_mode == 0xFF) {
if(msgUartData->len == 1 && memcmp(msgUartData->UArgs, "a", 1) == 0) {
serial_mode = AT_MODE;
send_to_uart("+ok", 3);
} else {
serial_mode = DATA_MODE;
if (msgUartData->len > 0)
send_serial_data((char *)msgUartData->UArgs, msgUartData->len);
}
}
}
static void sendResponse(AtCmdResponse *response)
{
static const char *MSG_OK="\r\nOK\r\n";
static const char *MSG_ERROR="\r\nERROR\r\n";
char resp_buffer[MAX_LINE_SIZE];
const char *msg = NULL;
int sz;
if (response->result == DSAT_OK) {
if (response->response && response->response[0]) {
sz = sprintf((char *)resp_buffer, "\r\n%s\r\n", response->response);
send_to_uart((char *)resp_buffer, sz);
}
msg = MSG_OK;
} else {
msg = MSG_ERROR;
}
send_to_uart(msg, strlen(msg));
}
static int process_at_cmd_line(char *cmdName, char *cmdLine)
{
AtCmdResponse *response;
int i;
response = malloc(sizeof(AtCmdResponse));
if ( response != NULL ) {
memset(response, 0x0, sizeof(AtCmdResponse));
response->response = malloc(MAX_LINE_SIZE);
response->response[0] = 0;
response->result = DSAT_ERROR;
ATCmdTable *atcmd_ptr = dtu_atcmd_table;
int nCommands = sizeof(dtu_atcmd_table) / sizeof(dtu_atcmd_table[0]);
for (i = 0; i < nCommands; i++, atcmd_ptr++) {
if (!strncasecmp((char *)atcmd_ptr->at_cmd_name, cmdName, strlen(cmdName))) {
response->result = DSAT_OK;
if (atcmd_ptr->proc_func != NULL) {
response->result = atcmd_ptr->proc_func(cmdName, cmdLine, response);
}
break;
}
}
sendResponse(response);
if (response->response)
free(response->response);
free(response);
}
return 0;
}
static void process_at_cmd_mode(const char *atCmdData, int data_len)
{
dsat_sio_info_s_type *sio_info_ptr = &g_sio_info;
char *buf_ptr = NULL;
char cc, atName[MAX_LINE_SIZE] = {0};
int step = 0;
buf_ptr = atCmdData;
printf("%s[%d]: AT_MODE recv ATCMD: %s\n", __FUNCTION__, __LINE__, buf_ptr);
while (data_len > 0) {
cc = *buf_ptr++;
data_len--;
switch (sio_info_ptr->at_cmd_prep_state) {
case DSAT_CMD_PREP_STATE_HUNT:
if ( UPCASE( cc ) == 'A' ) {
sio_info_ptr->at_cmd_prep_state = DSAT_CMD_PREP_STATE_FOUND_A;
}
break;
case DSAT_CMD_PREP_STATE_FOUND_A:
if ( UPCASE( cc ) == 'T' ) {
sio_info_ptr->build_cmd_ptr = sio_info_ptr->cmd_line_buffer;
sio_info_ptr->at_cmd_prep_state = DSAT_CMD_PREP_STATE_FOUND_AT;
} else if ( UPCASE( cc ) != 'A' ) {
sio_info_ptr->at_cmd_prep_state = DSAT_CMD_PREP_STATE_HUNT;
}
break;
case DSAT_CMD_PREP_STATE_FOUND_AT:
step++;
if (cc != '\r') {
if (cc == '=') {
printf("sio_info_ptr->cmd_line_buffer:%s\n", sio_info_ptr->cmd_line_buffer);
strncpy(atName, sio_info_ptr->cmd_line_buffer, step);
atName[step-1] = '\0';
printf("atName is %s\n", atName);
}
*sio_info_ptr->build_cmd_ptr++ = cc;
} else {
/* EOL found, terminate and parse */
*sio_info_ptr->build_cmd_ptr = '\0';
if (!strlen(atName)) {
strncpy(atName, sio_info_ptr->cmd_line_buffer, step-1);
atName[step-1] = '\0';
printf("[%d]: atName is %s\n", __LINE__, atName);
}
printf("%s[%d]: cmd_line_buffer=%s\n", __FUNCTION__, __LINE__, sio_info_ptr->cmd_line_buffer);
// T0D0: here should add AT command parse
process_at_cmd_line(atName, sio_info_ptr->cmd_line_buffer);
sio_info_ptr->at_cmd_prep_state = DSAT_CMD_PREP_STATE_HUNT;
}
break;
default:
sio_info_ptr->at_cmd_prep_state = DSAT_CMD_PREP_STATE_HUNT;
break;
}
}
}
static void handle_serial_data(MsgUartDataParam_sdk *uartData)
{
printf("%s[%d]:check_serial_mode=%s\n", __FUNCTION__, __LINE__, uartData->UArgs);
check_serial_mode(uartData);
if (serial_mode == DATA_MODE) {
printf("It time, serial_mode is DATA_MODE!\n");
send_serial_data((char *)uartData->UArgs, uartData->len);
} else if (serial_mode == AT_MODE) {
printf("It time, serial_mode is AT_MODE!\n");
process_at_cmd_mode((char *)uartData->UArgs, uartData->len);
}
}
static void uartdata_thread(void)
{
MsgUartDataParam_sdk uart_temp;
OSA_STATUS status;
serial_mode = DATA_MODE;
set_UartDataSwitch_sdk(1); // open pass-through
while (1) {
memset(&uart_temp, 0, sizeof(MsgUartDataParam_sdk));
status = OSAMsgQRecv(MsgUartData_sdk, (UINT8 *)&uart_temp, sizeof(MsgUartDataParam_sdk), OSA_SUSPEND);
if (status == OS_SUCCESS) {
if (uart_temp.UArgs) {
printf("%s[%d]: uart_temp len:%d, data:%s\n", __FUNCTION__, __LINE__, uart_temp.len, (char *)(uart_temp.UArgs));
handle_serial_data(&uart_temp);
free(uart_temp.UArgs);
}
}
}
}
static int dtu_atcmd_regen(char *atName, char *atLine, AtCmdResponse *resp)
{
dsat_result_enum_type result = DSAT_ERROR;
if (atName) {
CPUartLogPrintf("[atcmd_test]: recv AT command then exec:AT%s\n", atLine);
snprintf(resp->response, strlen(atLine)+1, "%s", atLine);
result = DSAT_OK;
}
return result;
}
static int dtu_atcmd_regtp(char *atName, char *atLine, AtCmdResponse *resp)
{
dsat_result_enum_type result = DSAT_ERROR;
if (atName) {
CPUartLogPrintf("[atcmd_test]: recv AT command then exec:AT%s\n", atLine);
snprintf(resp->response, strlen(atLine)+1, "%s", atLine);
result = DSAT_OK;
}
return result;
}
static int dtu_atcmd_regdt(char *atName, char *atLine, AtCmdResponse *resp)
{
dsat_result_enum_type result = DSAT_ERROR;
if (atName) {
CPUartLogPrintf("[atcmd_test]: recv AT command then exec:AT%s\n", atLine);
snprintf(resp->response, strlen(atLine)+1, "%s", atLine);
result = DSAT_OK;
}
return result;
}
```