add event-driven framework

see examples/event_driven_at_module and examples/event_driven_hello_world, demo project: TencentOS-tiny\board\TencentOS_tiny_EVB_MX\KEIL\event_driven_hello_world
This commit is contained in:
SheldonDai
2019-09-24 17:21:58 +08:00
parent 97be1b9e93
commit 9727512631
45 changed files with 16682 additions and 7 deletions

View File

@@ -0,0 +1,405 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef _TOS_AT_H_
#define _TOS_AT_H_
#include "tos_evtdrv.h"
#include "tos_at_utils_evtdrv.h"
#include "tos_hal.h"
#define AT_AGENT_ECHO_OK "OK"
#define AT_AGENT_ECHO_FAIL "FAIL"
#define AT_AGENT_ECHO_ERROR "ERROR"
#define AT_DATA_CHANNEL_NUM 6
#define AT_DATA_CHANNEL_FIFO_BUFFER_SIZE (2048 + 1024)
#define AT_UART_RX_FIFO_BUFFER_SIZE (2048 + 1024)
#define AT_RECV_CACHE_SIZE 2048
#define AT_CMD_BUFFER_SIZE 512
#define AT_PARSER_TASK_STACK_SIZE 2048
#define AT_PARSER_TASK_PRIO 2
#define EVENT_AT_UART_INCOMING (1u << 0)
#define EVENT_AT_PARSE_STATUS_OVERFLOW (1u << 1)
#define EVENT_AT_PARSE_STATUS_EVENT (1u << 2)
#define EVENT_AT_PARSE_STATUS_EXPECT (1U << 3)
#define EVENT_AT_PARSE_STATUS_NEWLINE (1U << 4)
typedef enum at_status_en {
AT_STATUS_OK,
AT_STATUS_ERROR,
AT_STATUS_INVALID_ARGS,
} at_status_t;
typedef struct at_cache_st {
uint8_t *buffer;
size_t buffer_size;
size_t recv_len;
size_t curr_len;
size_t last_data;
} at_cache_t;
typedef enum at_parse_status_en {
AT_PARSE_STATUS_NONE,
AT_PARSE_STATUS_NEWLINE,
AT_PARSE_STATUS_EVENT,
AT_PARSE_STATUS_EXPECT,
AT_PARSE_STATUS_OVERFLOW,
} at_parse_status_t;
typedef enum at_echo_status_en {
AT_ECHO_STATUS_NONE,
AT_ECHO_STATUS_OK,
AT_ECHO_STATUS_FAIL,
AT_ECHO_STATUS_ERROR,
AT_ECHO_STATUS_EXPECT,
} at_echo_status_t;
typedef enum at_channel_status_en {
AT_CHANNEL_STATUS_NONE, /*< usually means we are try to get a channel status with invalid id */
AT_CHANNEL_STATUS_HANGING, /*< channel is not used */
AT_CHANNEL_STATUS_WORKING, /*< channel is being using */
AT_CHANNEL_STATUS_BROKEN, /*< channel is broken(module link to remote server is broken) */
} at_channel_status_t;
typedef struct at_data_channel_st {
uint8_t is_free;
k_fifo_t rx_fifo;
uint8_t *rx_fifo_buffer;
at_channel_status_t status;
const char *remote_ip;
const char *remote_port;
} at_data_channel_t;
typedef struct at_echo_st {
char *buffer;
size_t buffer_size;
char *echo_expect;
evtdrv_task_id_t module_task_id;
evtdrv_event_flag_t event_flags;
int line_num;
at_echo_status_t status;
size_t __w_idx;
evtdrv_event_flag_t __expect_event;
} at_echo_t;
typedef void (*at_event_callback_t)(void);
typedef struct at_event_st {
const char *event_header;
at_event_callback_t event_callback;
} at_event_t;
typedef struct at_agent_st {
evtdrv_task_id_t at_task_id;
at_data_channel_t data_channel[AT_DATA_CHANNEL_NUM];
at_event_t *event_table;
size_t event_table_size;
at_echo_t *echo;
at_cache_t recv_cache;
at_timer_t timer;
char *cmd_buf;
hal_uart_t uart;
k_fifo_t uart_rx_fifo;
uint8_t *uart_rx_fifo_buffer;
} at_agent_t;
#define AT_AGENT ((at_agent_t *)(&at_agent))
/**
* @brief Write data to a channel.
* Write data to a channel with certain id.
*
* @attention None
*
* @param[in] channel_id id of the channel.
* @param[in] buffer data buffer to write.
* @param[in] buffer_len length of the buffer.
*
* @return errcode
* @retval -1 write failed(error).
* @retval none -1 the number of bytes written.
*/
int tos_at_channel_write(int channel_id, uint8_t *buffer, size_t buffer_len);
/**
* @brief Read data from a channel.
* Read data from a channel with a timeout.
*
* @attention None
*
* @param[in] channel_id id of the channel.
* @param[out] buffer buffer to hold the data read.
* @param[in] buffer_len length of the buffer.
* @param[in] timeout timeout.
*
* @return errcode
* @retval -1 read failed(error).
* @retval none -1 the number of bytes read.
*/
int tos_at_channel_read_timed(int channel_id, uint8_t *buffer, size_t buffer_len, uint32_t timeout);
/**
* @brief Read data from a channel.
* Read data from a channel.
*
* @attention None
*
* @param[in] channel_id id of the channel.
* @param[out] buffer buffer to hold the data read.
* @param[in] buffer_len length of the buffer.
*
* @return errcode
* @retval -1 read failed(error).
* @retval none -1 the number of bytes read.
*/
int tos_at_channel_read(int channel_id, uint8_t *buffer, size_t buffer_len);
/**
* @brief Allocate a channel.
* Allocate a channel with certain id.
*
* @attention None
*
* @param[in] channel_id id of the channel.
* @param[in] ip remote ip of the channel.
* @param[in] port remote port of the channel.
*
* @return errcode
* @retval -1 allocate failed(error).
* @retval none -1 the id of the channel.
*/
int tos_at_channel_alloc_id(int channel_id, const char *ip, const char *port);
/**
* @brief Allocate a channel.
* Allocate a channel.
*
* @attention None
*
* @param[in] ip remote ip of the channel.
* @param[in] port remote port of the channel.
*
* @return errcode
* @retval -1 allocate failed(error).
* @retval none -1 the id of the channel.
*/
int tos_at_channel_alloc(const char *ip, const char *port);
/**
* @brief Free a channel.
* Free a channel with certain id.
*
* @attention None
*
* @param[in] channel_id id of the channel.
*
* @return errcode
* @retval -1 free failed(error).
* @retval 0 free successfully.
*/
int tos_at_channel_free(int channel_id);
/**
* @brief Set channel broken.
*
* @attention None
*
* @param[in] channel_id id of the channel.
*
* @return errcode
* @retval -1 set failed(error).
* @retval 0 set successfully.
*/
__API__ int tos_at_channel_set_broken(int channel_id);
/**
* @brief Judge whether channel is working.
*
* @attention None
*
* @param[in] channel_id id of the channel.
*
* @return at channel status(type of at_channel_status_t)
*/
__API__ int tos_at_channel_is_working(int channel_id);
/**
* @brief Initialize the at framework.
*
* @attention None
*
* @param[in] uart_port port number of the uart thougth which the module connect to the MCU.
* @param[in] event_table the listened event table.
* @param[in] event_table_size the size of the listened event table.
*
* @return errcode
* @retval -1 initialize failed(error).
* @retval 0 initialize successfully.
*/
__API__ int tos_at_init(hal_uart_port_t uart_port, evtdrv_task_id_t at_task_id, at_event_t *event_table, size_t event_table_size);
/**
* @brief De-initialize the at framework.
*
* @attention None
*
* @return
None
*/
void tos_at_deinit(void);
/**
* @brief Create a echo struct.
*
* @attention None
*
* @param[in] echo pointer to the echo struct.
* @param[out] buffer buffer to hold the received message from the module.
* @param[in] buffer_size size of the buffer.
* @param[in] echo_expect the expected echo message.
*
* @return errcode
* @retval -1 create failed(error).
* @retval 0 create successfully.
*/
int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect, evtdrv_task_id_t module_task_id, evtdrv_event_flag_t event_flags);
/**
* @brief Execute an at command.
*
* @attention None
*
* @param[in] echo pointer to the echo struct.
* @param[in] timeout command wait timeout .
* @param[in] cmd at command.
*
* @return errcode
* @retval -1 execute failed(error).
* @retval 0 execute successfully.
*/
int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...);
/**
* @brief Send raw data througth uart.
*
* @attention None
*
* @param[in] echo pointer to the echo struct.
* @param[in] timeout command wait timeout .
* @param[in] buf data to send.
* @param[in] size size of the buf.
*
* @return errcode
* @retval -1 execute failed(error).
* @retval 0 execute successfully.
*/
int tos_at_raw_data_send(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size);
/**
* @brief Write byte to the at uart.
* The function called by the uart interrupt, to put the data from the uart to the at framework.
*
* @attention None
*
* @param[in] data uart received data.
*
* @return None
*/
void tos_at_uart_write_byte(uint8_t data);
/**
* @brief Read data from the uart.
* Read data from the uart, usually called in listened event callback.
*
* @attention None
*
* @param[out] buffer buffer to hold the data read from the uart.
* @param[in] buffer_len length of the buffer.
*
* @return length of the data read from the uart.
*/
int tos_at_uart_read(uint8_t *buffer, size_t buffer_len);
/**
* @brief Read data from the uart.
* Read data from the uart until meet a '\n', usually called in listened event callback.
*
* @attention None
*
* @param[out] buffer buffer to hold the data read from the uart.
* @param[in] buffer_len length of the buffer.
*
* @return length of the data read from the uart.
*/
int tos_at_uart_readline(uint8_t *buffer, size_t buffer_len);
/**
* @brief Read data from the uart.
* Read data from the uart until no more incoming data, usually called in listened event callback.
*
* @attention None
*
* @param[out] buffer buffer to hold the data read from the uart.
* @param[in] buffer_len length of the buffer.
*
* @return length of the data read from the uart.
*/
int tos_at_uart_drain(uint8_t *buffer, size_t buffer_len);
/**
* @brief Get the remote ip of a channel.
* Get the remote ip of a channel with certain id.
*
* @attention None
*
* @param[in] channel_id id of the channel.
*
* @return remote ip of the channel.
*/
const char *tos_at_agent_channel_ip_get(int channel_id);
/**
* @brief Get the remote port of a channel.
* Get the remote port of a channel with certain id.
*
* @attention None
*
* @param[in] channel_id id of the channel.
*
* @return remote port of the channel.
*/
const char *tos_at_agent_channel_port_get(int channel_id);
evtdrv_event_flag_t tos_at_evtdrv_task(evtdrv_event_flag_t event);
#endif /* __AT_AGENT_H_ */

View File

@@ -0,0 +1,23 @@
#ifndef _TOS_AT_UTILS_H_
#define _TOS_AT_UTILS_H_
typedef struct at_timer_st {
evtdrv_tick_t end_time;
} at_timer_t;
void at_delay(evtdrv_tick_t tick);
void at_delay_ms(uint32_t millisec);
int at_timer_is_expired(at_timer_t *tmr);
void at_timer_countdown(at_timer_t *tmr, evtdrv_tick_t tick);
void at_timer_countdown_ms(at_timer_t *tmr, uint32_t millisec);
evtdrv_tick_t at_timer_remain(at_timer_t *tmr);
void at_timer_init(at_timer_t *tmr);
#endif

View File

@@ -0,0 +1,756 @@
#include "tos_at_evtdrv.h"
__STATIC__ at_agent_t at_agent;
__STATIC__ int at_uart_getchar(uint8_t *data, k_tick_t timeout)
{
k_err_t err;
at_delay(1);
err = tos_fifo_pop(&AT_AGENT->uart_rx_fifo, data);
return err == K_ERR_NONE ? 0 : -1;
}
__STATIC__ at_event_t *at_event_do_get(char *buffer, size_t buffer_len)
{
int i = 0;
at_event_t *event_table = K_NULL, *event = K_NULL;
size_t event_table_size = 0, event_len;
event_table = AT_AGENT->event_table;
event_table_size = AT_AGENT->event_table_size;
for (i = 0; i < event_table_size; ++i) {
event = &event_table[i];
event_len = strlen(event->event_header);
if (buffer_len < event_len) {
continue;
}
if (strncmp(event->event_header, buffer, event_len) == 0) {
return event;
}
}
return K_NULL;
}
__STATIC__ at_event_t *at_get_event(void)
{
char *buffer;
size_t buffer_len;
at_cache_t *at_cache = K_NULL;
at_cache = &AT_AGENT->recv_cache;
buffer = (char *)at_cache->buffer;
buffer_len = at_cache->recv_len;
return at_event_do_get(buffer, buffer_len);
}
__API__ int tos_at_uart_read(uint8_t *buffer, size_t buffer_len)
{
uint8_t data;
size_t read_len = 0;
while (K_TRUE) {
if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
return read_len;
}
buffer[read_len++] = data;
if (read_len == buffer_len) {
return buffer_len;
}
}
}
__API__ int tos_at_uart_readline(uint8_t *buffer, size_t buffer_len)
{
uint8_t data;
size_t read_len = 0;
while (K_TRUE) {
if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
return read_len;
}
buffer[read_len++] = data;
if (data == '\n') {
return read_len;
} else if (read_len == buffer_len) {
return buffer_len;
}
}
}
__API__ int tos_at_uart_drain(uint8_t *buffer, size_t buffer_len)
{
uint8_t data;
size_t read_len = 0;
while (K_TRUE) {
if (at_uart_getchar(&data, TOS_TIME_NOWAIT) != 0) {
return read_len;
}
buffer[read_len++] = data;
if (read_len == buffer_len) {
return buffer_len;
}
}
}
__STATIC__ int at_is_echo_expect(void)
{
char *recv_buffer, *expect;
size_t recv_buffer_len, expect_len;
at_echo_t *at_echo = K_NULL;
at_cache_t *at_cache = K_NULL;
at_echo = AT_AGENT->echo;
if (!at_echo || !at_echo->echo_expect) {
return 0;
}
at_cache = &AT_AGENT->recv_cache;
recv_buffer = (char *)at_cache->buffer;
recv_buffer_len = at_cache->recv_len;
expect = at_echo->echo_expect;
expect_len = strlen(expect);
if (recv_buffer_len < expect_len) {
return 0;
}
if (strncmp(expect, recv_buffer, expect_len) == 0) {
return 1;
}
return 0;
}
__STATIC__ void at_echo_buffer_copy(at_cache_t *at_cache, at_echo_t *echo)
{
uint8_t *recv_buffer = K_NULL;
size_t recv_buffer_len, copy_len, remain_len;
recv_buffer = at_cache->buffer;
recv_buffer_len = at_cache->recv_len;
remain_len = echo->buffer_size - echo->__w_idx;
if (remain_len == 0) {
return;
}
copy_len = remain_len < recv_buffer_len ? remain_len : recv_buffer_len;
memcpy(echo->buffer + echo->__w_idx, recv_buffer, copy_len);
echo->__w_idx += copy_len;
++echo->line_num;
}
__STATIC__ int at_uart_send(const uint8_t *buf, size_t size, uint32_t timeout)
{
return tos_hal_uart_write(&AT_AGENT->uart, buf, size, timeout);
}
__API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect, evtdrv_task_id_t module_task_id, evtdrv_event_flag_t event_flags)
{
if (!echo) {
return -1;
}
if (buffer) {
memset(buffer, 0, buffer_size);
}
echo->buffer = buffer;
echo->buffer_size = buffer_size;
echo->echo_expect = echo_expect;
echo->module_task_id = module_task_id;
echo->event_flags = event_flags;
echo->line_num = 0;
echo->status = AT_ECHO_STATUS_NONE;
echo->__w_idx = 0;
return 0;
}
__STATIC_INLINE__ void at_echo_flush(at_echo_t *echo)
{
echo->line_num = 0;
echo->status = AT_ECHO_STATUS_NONE;
echo->__w_idx = 0;
}
__STATIC_INLINE void at_echo_attach(at_echo_t *echo)
{
at_echo_flush(echo);
AT_AGENT->echo = echo;
}
__API__ int tos_at_raw_data_send(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size)
{
int ret = 0;
if (echo) {
at_echo_attach(echo);
}
ret = at_uart_send(buf, size, 0xFFFF);
return ret;
}
__STATIC__ int at_cmd_do_exec(const char *format, va_list args)
{
size_t cmd_len = 0;
cmd_len = vsnprintf(AT_AGENT->cmd_buf, AT_CMD_BUFFER_SIZE, format, args);
printf("AT CMD:\n%s\n", AT_AGENT->cmd_buf);
at_uart_send((uint8_t *)AT_AGENT->cmd_buf, cmd_len, 0xFFFF);
return 0;
}
__API__ int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
{
int ret = 0;
va_list args;
if (echo) {
at_echo_attach(echo);
}
va_start(args, cmd);
ret = at_cmd_do_exec(cmd, args);
va_end(args);
if (ret != 0) {
AT_AGENT->echo = K_NULL;
return -1;
}
return 0;
}
__STATIC__ int at_recv_cache_init(void)
{
uint8_t *buffer = K_NULL;
buffer = tos_mmheap_alloc(AT_RECV_CACHE_SIZE);
if (!buffer) {
AT_AGENT->recv_cache.buffer = K_NULL;
return - 1;
}
AT_AGENT->recv_cache.buffer = buffer;
AT_AGENT->recv_cache.buffer_size = AT_RECV_CACHE_SIZE;
AT_AGENT->recv_cache.recv_len = 0;
return 0;
}
__STATIC__ void at_recv_cache_deinit(void)
{
uint8_t *buffer = K_NULL;
buffer = AT_AGENT->recv_cache.buffer;
if (buffer) {
tos_mmheap_free(buffer);
}
AT_AGENT->recv_cache.buffer = K_NULL;
AT_AGENT->recv_cache.buffer_size = 0;
AT_AGENT->recv_cache.recv_len = 0;
}
__STATIC__ at_data_channel_t *at_channel_get(int channel_id, int is_alloc)
{
/*
if is_alloc is K_TRUE, means we are allocating a channel with certain id,
data_channel[channel_id] must be free if return none K_NULL.
otherwise if is_alloc is K_FALSE, means we are trying to get a channel with
certain id, data_channel[channel_id] must be not free if return none K_NULL.
*/
at_data_channel_t *data_channel = K_NULL;
if (channel_id < 0 || channel_id >= AT_DATA_CHANNEL_NUM) {
return K_NULL;
}
data_channel = &AT_AGENT->data_channel[channel_id];
if (is_alloc && data_channel->is_free) {
return data_channel;
}
if (!is_alloc && !data_channel->is_free) {
return data_channel;
}
return K_NULL;
}
__API__ int tos_at_channel_read(int channel_id, uint8_t *buffer, size_t buffer_len)
{
int read_len;
size_t total_read_len = 0;
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel || data_channel->status == AT_CHANNEL_STATUS_BROKEN) {
return -1;
}
while (K_TRUE) {
read_len = tos_fifo_pop_stream(&data_channel->rx_fifo, buffer, buffer_len);
total_read_len += read_len;
if (total_read_len < buffer_len) {
continue;
} else {
return buffer_len;
}
}
}
__API__ int tos_at_channel_read_timed(int channel_id, uint8_t *buffer, size_t buffer_len, uint32_t timeout)
{
int read_len = 0;
size_t total_read_len = 0;
k_tick_t tick, remain_tick;
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel || data_channel->status == AT_CHANNEL_STATUS_BROKEN) {
return -1;
}
tick = tos_millisec2tick(timeout);
at_timer_countdown(&AT_AGENT->timer, tick);
while (!at_timer_is_expired(&AT_AGENT->timer)) {
remain_tick = at_timer_remain(&AT_AGENT->timer);
if (remain_tick == (k_tick_t)0u) {
return total_read_len;
}
read_len = tos_fifo_pop_stream(&data_channel->rx_fifo, buffer + read_len, buffer_len - total_read_len);
total_read_len += read_len;
if (total_read_len < buffer_len) {
continue;
} else {
return buffer_len;
}
}
return total_read_len;
}
__API__ int tos_at_channel_write(int channel_id, uint8_t *buffer, size_t buffer_len)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel) {
return -1;
}
return tos_fifo_push_stream(&data_channel->rx_fifo, buffer, buffer_len);
}
__STATIC_INLINE__ int at_channel_construct(at_data_channel_t *data_channel, const char *ip, const char *port)
{
uint8_t *fifo_buffer = K_NULL;
fifo_buffer = tos_mmheap_alloc(AT_DATA_CHANNEL_FIFO_BUFFER_SIZE);
if (!fifo_buffer) {
return -1;
}
data_channel->rx_fifo_buffer = fifo_buffer;
tos_fifo_create(&data_channel->rx_fifo, fifo_buffer, AT_DATA_CHANNEL_FIFO_BUFFER_SIZE);
data_channel->remote_ip = ip;
data_channel->remote_port = port;
data_channel->is_free = K_FALSE;
data_channel->status = AT_CHANNEL_STATUS_WORKING;
return 0;
}
__API__ int tos_at_channel_alloc_id(int channel_id, const char *ip, const char *port)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_TRUE);
if (!data_channel) {
return -1;
}
if (at_channel_construct(data_channel, ip, port) != 0) {
return -1;
}
return channel_id;
}
__API__ int tos_at_channel_alloc(const char *ip, const char *port)
{
int id = 0;
at_data_channel_t *data_channel = K_NULL;
for (id = 0; id < AT_DATA_CHANNEL_NUM; ++id) {
data_channel = &AT_AGENT->data_channel[id];
if (data_channel->is_free) {
break;
}
}
if (id == AT_DATA_CHANNEL_NUM || !data_channel) {
return -1;
}
if (at_channel_construct(data_channel, ip, port) != 0) {
return -1;
}
return id;
}
__API__ int tos_at_channel_free(int channel_id)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel) {
return -1;
}
tos_mmheap_free(data_channel->rx_fifo_buffer);
tos_fifo_destroy(&data_channel->rx_fifo);
memset(data_channel, 0, sizeof(at_data_channel_t));
data_channel->is_free = K_TRUE;
data_channel->status = AT_CHANNEL_STATUS_HANGING;
return 0;
}
__API__ int tos_at_channel_set_broken(int channel_id)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel) {
return -1;
}
data_channel->status = AT_CHANNEL_STATUS_BROKEN;
return 0;
}
__API__ int tos_at_channel_is_working(int channel_id)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
return data_channel && data_channel->status == AT_CHANNEL_STATUS_WORKING;
}
__STATIC__ void at_channel_init(void)
{
int i = 0;
for (i = 0; i < AT_DATA_CHANNEL_NUM; ++i) {
memset(&AT_AGENT->data_channel[i], 0, sizeof(at_data_channel_t));
AT_AGENT->data_channel[i].is_free = K_TRUE;
AT_AGENT->data_channel[i].status = AT_CHANNEL_STATUS_HANGING;
}
}
__STATIC__ void at_channel_deinit(void)
{
int i = 0;
for (i = 0; i < AT_DATA_CHANNEL_NUM; ++i) {
tos_at_channel_free(i);
}
}
__API__ const char *tos_at_channel_ip_get(int channel_id)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel) {
return K_NULL;
}
return data_channel[channel_id].remote_ip;
}
__API__ const char *tos_at_channel_port_get(int channel_id)
{
at_data_channel_t *data_channel = K_NULL;
data_channel = at_channel_get(channel_id, K_FALSE);
if (!data_channel) {
return K_NULL;
}
return data_channel[channel_id].remote_port;
}
__STATIC__ void at_event_table_set(at_event_t *event_table, size_t event_table_size)
{
AT_AGENT->event_table = event_table;
AT_AGENT->event_table_size = event_table_size;
}
__API__ int tos_at_init(hal_uart_port_t uart_port, evtdrv_task_id_t at_task_id, at_event_t *event_table, size_t event_table_size)
{
void *buffer = K_NULL;
memset(AT_AGENT, 0, sizeof(at_agent_t));
AT_AGENT->at_task_id = at_task_id;
at_event_table_set(event_table, event_table_size);
at_channel_init();
at_timer_init(&AT_AGENT->timer);
buffer = tos_mmheap_alloc(AT_UART_RX_FIFO_BUFFER_SIZE);
if (!buffer) {
return -1;
}
AT_AGENT->uart_rx_fifo_buffer = (uint8_t *)buffer;
tos_fifo_create(&AT_AGENT->uart_rx_fifo, (uint8_t *)buffer, AT_UART_RX_FIFO_BUFFER_SIZE);
buffer = tos_mmheap_alloc(AT_CMD_BUFFER_SIZE);
if (!buffer) {
goto errout0;
}
AT_AGENT->cmd_buf = (char *)buffer;
if (at_recv_cache_init() != 0) {
goto errout1;
}
if (tos_hal_uart_init(&AT_AGENT->uart, uart_port) != 0) {
goto errout2;
}
return 0;
errout2:
at_recv_cache_deinit();
errout1:
tos_mmheap_free(AT_AGENT->cmd_buf);
AT_AGENT->cmd_buf = K_NULL;
errout0:
tos_mmheap_free(AT_AGENT->uart_rx_fifo_buffer);
AT_AGENT->uart_rx_fifo_buffer = K_NULL;
tos_fifo_destroy(&AT_AGENT->uart_rx_fifo);
return -1;
}
__API__ void tos_at_deinit(void)
{
tos_hal_uart_deinit(&AT_AGENT->uart);
at_recv_cache_deinit();
tos_mmheap_free(AT_AGENT->cmd_buf);
AT_AGENT->cmd_buf = K_NULL;
tos_mmheap_free(AT_AGENT->uart_rx_fifo_buffer);
AT_AGENT->uart_rx_fifo_buffer = K_NULL;
tos_fifo_destroy(&AT_AGENT->uart_rx_fifo);
at_channel_deinit();
}
/* To completely decouple the uart intterupt and at agent, we need a more powerful
hal(driver framework), that would be a huge work, we place it in future plans. */
__API__ void tos_at_uart_write_byte(uint8_t data)
{
if (tos_fifo_push(&AT_AGENT->uart_rx_fifo, data) == K_ERR_NONE) {
tos_evtdrv_event_set(AT_AGENT->at_task_id, EVENT_AT_UART_INCOMING);
}
}
__STATIC__ void at_echo_event_emit(at_echo_t *echo)
{
tos_evtdrv_event_set(echo->module_task_id, echo->event_flags);
}
__STATIC__ void at_echo_status_set(at_echo_t *echo)
{
char *buffer;
at_cache_t *at_cache;
at_cache = &AT_AGENT->recv_cache;
buffer = (char *)at_cache->buffer;
if (strstr(buffer, AT_AGENT_ECHO_OK) != K_NULL) {
echo->status = AT_ECHO_STATUS_OK;
} else if (strstr(buffer, AT_AGENT_ECHO_ERROR) != K_NULL) {
echo->status = AT_ECHO_STATUS_ERROR;
} else if (strstr(buffer, AT_AGENT_ECHO_FAIL) != K_NULL) {
echo->status = AT_ECHO_STATUS_FAIL;
}
}
__STATIC__ void at_recv_cache_reset(void)
{
at_cache_t *recv_cache = K_NULL;
recv_cache = &AT_AGENT->recv_cache;
recv_cache->recv_len = 0;
recv_cache->curr_len = 0;
recv_cache->last_data = 0;
memset(recv_cache->buffer, 0, recv_cache->buffer_size);
}
evtdrv_event_flag_t tos_at_evtdrv_task(evtdrv_event_flag_t event)
{
at_echo_t *at_echo = K_NULL;
at_event_t *at_event = K_NULL;
at_cache_t *recv_cache = K_NULL;
recv_cache = &AT_AGENT->recv_cache;
if (event & TOS_EVTDRV_SYS_EVENT_INIT) {
at_recv_cache_reset();
return TOS_EVTDRV_SYS_EVENT_INIT;
}
if (event & TOS_EVTDRV_SYS_EVENT_MSG) {
return TOS_EVTDRV_SYS_EVENT_MSG;
}
if (event & EVENT_AT_PARSE_STATUS_OVERFLOW) {
// TODO: fix me
at_recv_cache_reset();
return EVENT_AT_PARSE_STATUS_OVERFLOW;
}
if (event & EVENT_AT_PARSE_STATUS_EVENT) {
at_event = at_get_event();
if (at_event && at_event->event_callback) {
at_event->event_callback();
}
at_recv_cache_reset();
return EVENT_AT_PARSE_STATUS_EVENT;
}
if (event & EVENT_AT_PARSE_STATUS_EXPECT ||
event & EVENT_AT_PARSE_STATUS_NEWLINE) {
printf("--->%s\n", recv_cache->buffer);
at_echo = AT_AGENT->echo;
if (!at_echo) {
at_recv_cache_reset();
return event & EVENT_AT_PARSE_STATUS_EXPECT ?
EVENT_AT_PARSE_STATUS_EXPECT : EVENT_AT_PARSE_STATUS_NEWLINE;
}
if (at_echo->status == AT_ECHO_STATUS_NONE) {
if (event & EVENT_AT_PARSE_STATUS_EXPECT) {
at_echo->status = AT_ECHO_STATUS_EXPECT;
} else if (event & EVENT_AT_PARSE_STATUS_NEWLINE) {
at_echo_status_set(at_echo);
}
if (at_echo->status != AT_ECHO_STATUS_NONE) {
at_echo_event_emit(at_echo);
}
}
if (at_echo->buffer) {
at_echo_buffer_copy(recv_cache, at_echo);
}
at_recv_cache_reset();
return event & EVENT_AT_PARSE_STATUS_EXPECT ?
EVENT_AT_PARSE_STATUS_EXPECT : EVENT_AT_PARSE_STATUS_NEWLINE;
}
if (event & EVENT_AT_UART_INCOMING) {
uint8_t data;
if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
return EVENT_AT_UART_INCOMING;
}
if (data == '\0') {
return EVENT_AT_UART_INCOMING;
}
if (recv_cache->curr_len < recv_cache->buffer_size) {
recv_cache->buffer[recv_cache->curr_len++] = data;
recv_cache->recv_len = recv_cache->curr_len;
} else {
recv_cache->buffer[recv_cache->buffer_size - 1] = '\0';
tos_evtdrv_event_set(AT_AGENT->at_task_id, EVENT_AT_PARSE_STATUS_OVERFLOW);
return EVENT_AT_UART_INCOMING;
}
if (at_get_event() != K_NULL) {
tos_evtdrv_event_set(AT_AGENT->at_task_id, EVENT_AT_PARSE_STATUS_EVENT);
return EVENT_AT_UART_INCOMING;
}
if (at_is_echo_expect()) {
tos_evtdrv_event_set(AT_AGENT->at_task_id, EVENT_AT_PARSE_STATUS_EXPECT);
return EVENT_AT_UART_INCOMING;
}
if (data == '\n' && recv_cache->last_data == '\r') { // 0xd 0xa
recv_cache->curr_len -= 1;
recv_cache->buffer[recv_cache->curr_len - 1] = '\n';
recv_cache->recv_len = recv_cache->curr_len;
if (recv_cache->curr_len == 1) { // only a blank newline, ignore
recv_cache->last_data = 0;
recv_cache->curr_len = 0;
recv_cache->recv_len = 0;
tos_evtdrv_event_set(AT_AGENT->at_task_id, EVENT_AT_PARSE_STATUS_NEWLINE);
return EVENT_AT_UART_INCOMING;
}
tos_evtdrv_event_set(AT_AGENT->at_task_id, EVENT_AT_PARSE_STATUS_NEWLINE);
return EVENT_AT_UART_INCOMING;
}
recv_cache->last_data = data;
return EVENT_AT_UART_INCOMING;
}
return TOS_EVTDRV_EVENT_NONE;
}

View File

@@ -0,0 +1,79 @@
#include "tos_evtdrv.h"
#include "tos_at_evtdrv.h"
void at_delay(evtdrv_tick_t tick)
{
evtdrv_tick_t now;
now = tos_evtdrv_systick_get();
while ((tos_evtdrv_systick_get() - now) < tick) {
;
}
}
void at_delay_ms(uint32_t millisec)
{
evtdrv_tick_t tick;
tick = tos_evtdrv_millisec2tick(millisec);
at_delay(tick);
}
int at_timer_is_expired(at_timer_t *tmr)
{
evtdrv_tick_t now;
if (!tmr) {
return -1;
}
now = tos_evtdrv_systick_get();
return now >= tmr->end_time;
}
void at_timer_countdown(at_timer_t *tmr, evtdrv_tick_t tick)
{
evtdrv_tick_t now;
if (!tmr) {
return;
}
now = tos_evtdrv_systick_get();
tmr->end_time = now + tick;
}
void at_timer_countdown_ms(at_timer_t *tmr, uint32_t millisec)
{
evtdrv_tick_t expire;
if (!tmr) {
return;
}
expire = tos_millisec2tick(millisec);
at_timer_countdown(tmr, expire);
}
evtdrv_tick_t at_timer_remain(at_timer_t *tmr)
{
evtdrv_tick_t now;
now = tos_evtdrv_systick_get();
if (at_timer_is_expired(tmr)) {
return (evtdrv_tick_t)0u;
}
return tmr->end_time - now;
}
void at_timer_init(at_timer_t *tmr)
{
if (!tmr) {
return;
}
tmr->end_time = 0;
}

View File

@@ -0,0 +1,687 @@
#include "tos_at_evtdrv.h"
#include "esp8266_evtdrv.h"
#include "sal_module_wrapper.h"
#include "stdio.h"
#include "stdbool.h"
#include "ctype.h"
typedef struct esp8266_send_info_st {
int sockid;
void *buf;
size_t len;
} esp8266_send_info_t;
typedef struct esp8266_domain_parse_info_st {
char *host_ip;
size_t host_ip_len;
} esp8266_domain_parse_info_t;
typedef struct esp8266_context_st {
at_echo_t echo;
char echo_buffer[64];
int try;
evtdrv_task_id_t self_task_id;
int sockid;
evtdrv_task_id_t caller_task_id;
char *ssid;
char *pwd;
esp8266_send_info_t send_info;
esp8266_domain_parse_info_t domain_parse_info;
} esp8266_context_t;
esp8266_context_t esp8266_context;
#define CONTEXT(field) (esp8266_context.##field)
static void esp8266_restore(void)
{
tos_at_echo_create(&CONTEXT(echo), NULL, 0, NULL, CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_RESTORE);
tos_at_cmd_exec(&CONTEXT(echo), 3000, "AT+RESTORE\r\n");
}
static void esp8266_echo_close(void)
{
tos_at_echo_create(&CONTEXT(echo), NULL, 0, NULL, CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_ECHO_CLOSE);
tos_at_cmd_exec(&CONTEXT(echo), 1000, "ATE0\r\n");
}
static void esp8266_net_mode_set(sal_net_mode_t mode)
{
char *cmd = NULL;
switch (mode) {
case SAL_NET_MODE_STA:
cmd = "AT+CWMODE=1\r\n";
break;
case SAL_NET_MODE_AP:
cmd = "AT+CWMODE=2\r\n";
break;
case SAL_NET_MODE_STA_AP:
cmd = "AT+CWMODE=3\r\n";
break;
default:
return;
}
tos_at_echo_create(&CONTEXT(echo), NULL, 0, "no change", CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_NET_MODE_SET);
tos_at_cmd_exec(&CONTEXT(echo), 1000, cmd);
}
static void esp8266_send_mode_set(sal_send_mode_t mode)
{
tos_at_echo_create(&CONTEXT(echo), NULL, 0, NULL, CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_SEND_MODE_SET);
tos_at_cmd_exec(&CONTEXT(echo), 1000, "AT+CIPMODE=%d\r\n", mode == SAL_SEND_MODE_NORMAL ? 0 : 1);
}
static void esp8266_multilink_set(sal_multilink_state_t state)
{
tos_at_echo_create(&CONTEXT(echo), NULL, 0, NULL, CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_MULTILINK_SET);
tos_at_cmd_exec(&CONTEXT(echo), 500, "AT+CIPMUX=%d\r\n", state == SAL_MULTILINK_STATE_ENABLE ? 1 : 0);
}
static void esp8266_do_join_ap(const char *ssid, const char *pwd)
{
tos_at_echo_create(&CONTEXT(echo), NULL, 0, "OK", CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_JOIN_AP);
tos_at_cmd_exec(&CONTEXT(echo), 1000, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);
}
static int esp8266_do_connect(const char *ip, const char *port, sal_proto_t proto)
{
CONTEXT(sockid) = tos_at_channel_alloc(ip, port);
if (CONTEXT(sockid) == -1) {
return -1;
}
tos_at_echo_create(&CONTEXT(echo), NULL, 0, "OK", CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_CONNECT);
tos_at_cmd_exec(&CONTEXT(echo), 10000,
"AT+CIPSTART=%d,\"%s\",\"%s\",%s\r\n",
CONTEXT(sockid), proto == TOS_SAL_PROTO_UDP ? "UDP" : "TCP", ip, port);
return 0;
}
static int esp8266_recv_timeout(int id, void *buf, size_t len, uint32_t timeout)
{
return tos_at_channel_read_timed(id, buf, len, timeout);
}
static int esp8266_recv(int id, void *buf, size_t len)
{
return esp8266_recv_timeout(id, buf, len, (uint32_t)4000);
}
static int esp8266_is_link_broken(const char *echo_buffer)
{
if (strstr(echo_buffer, "CLOSED") ||
strstr(echo_buffer, "link is not valid")) {
return 1;
}
return 0;
}
static int esp8266_do_send(int id, const void *buf, size_t len)
{
tos_at_echo_create(&CONTEXT(echo), CONTEXT(echo_buffer), sizeof(CONTEXT(echo_buffer)), "SEND OK", CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_SEND);
/*
ATTENTION: we should wait util "SEND OK" is echoed, otherwise the next
time we execute at command, the esp8266 maybe in a "busy s ..." state.
*/
tos_at_raw_data_send(&CONTEXT(echo), 10000, (uint8_t *)buf, len);
return 0;
}
static int esp8266_do_send_ready(int id, const void *buf, size_t len)
{
if (!tos_at_channel_is_working(id)) {
return -1;
}
CONTEXT(sockid) = id;
tos_at_echo_create(&CONTEXT(echo), CONTEXT(echo_buffer), sizeof(CONTEXT(echo_buffer)), ">", CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_SEND_READY);
tos_at_cmd_exec(&CONTEXT(echo), 1000,
"AT+CIPSEND=%d,%d\r\n",
id, len);
return 0;
}
static int esp8266_do_close(int id)
{
tos_at_cmd_exec(NULL, 1000, "AT+CIPCLOSE=%d\r\n", id);
tos_at_channel_free(id);
return 0;
}
static int esp8266_close(int id)
{
esp8266_imsg_close_t *msg_close;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_imsg_close_t));
msg_close = (esp8266_imsg_close_t *)msg_body;
msg_close->header.event = EVENT_IMSG_ESP8266_CLOSE;
msg_close->header.sender_id = tos_evtdrv_task_self();
msg_close->sockid = id;
if (tos_evtdrv_msg_send(CONTEXT(self_task_id), (evtdrv_msg_body_t)msg_close) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
static int esp8266_send(int id, const void *buf, size_t len)
{
esp8266_imsg_send_t *msg_send;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_imsg_send_t));
msg_send = (esp8266_imsg_send_t *)msg_body;
msg_send->header.event = EVENT_IMSG_ESP8266_SEND;
msg_send->header.sender_id = tos_evtdrv_task_self();
msg_send->sockid = id;
msg_send->buf = (void *)buf;
msg_send->len = len;
if (tos_evtdrv_msg_send(CONTEXT(self_task_id), (evtdrv_msg_body_t)msg_send) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
static int esp8266_connect(const char *ip, const char *port, sal_proto_t proto)
{
esp8266_imsg_connect_t *msg_connect;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_imsg_connect_t));
msg_connect = (esp8266_imsg_connect_t *)msg_body;
msg_connect->header.event = EVENT_IMSG_ESP8266_CONNECT;
msg_connect->header.sender_id = tos_evtdrv_task_self();
msg_connect->ip = (char *)ip;
msg_connect->port = (char *)port;
msg_connect->proto = proto;
if (tos_evtdrv_msg_send(CONTEXT(self_task_id), (evtdrv_msg_body_t)msg_connect) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
static int esp8266_do_parse_domain(const char *host_name, char *host_ip, size_t host_ip_len)
{
tos_at_echo_create(&CONTEXT(echo), CONTEXT(echo_buffer), sizeof(CONTEXT(echo_buffer)), NULL, CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_DOMAIN_PARSE);
tos_at_cmd_exec(&CONTEXT(echo), 2000, "AT+CIPDOMAIN=\"%s\"\r\n", host_name);
return 0;
}
static int esp8266_parse_domain(const char *host_name, char *host_ip, size_t host_ip_len)
{
esp8266_imsg_domain_parse_t *msg_domain_parse;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_imsg_domain_parse_t));
msg_domain_parse = (esp8266_imsg_domain_parse_t *)msg_body;
msg_domain_parse->header.event = EVENT_IMSG_ESP8266_DOMAIN_PARSE;
msg_domain_parse->header.sender_id = tos_evtdrv_task_self();
msg_domain_parse->host_name = (char *)host_name;
msg_domain_parse->host_ip = (char *)host_ip;
msg_domain_parse->host_ip_len = host_ip_len;
if (tos_evtdrv_msg_send(CONTEXT(self_task_id), (evtdrv_msg_body_t)msg_domain_parse) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
static int esp8266_init(void)
{
if (tos_evtdrv_event_set(CONTEXT(self_task_id), EVENT_INTERNAL_ESP8266_INIT) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
__STATIC__ uint8_t incoming_data_buffer[512];
__STATIC__ void esp8266_incoming_data_process(void)
{
uint8_t data;
int channel_id = 0, data_len = 0;
/*
+IPD,0,44:1234...
+IPD: prefix
0: link id
44: data length
1234...: data content
*/
while (1) {
if (tos_at_uart_read(&data, 1) != 1) {
return;
}
if (data == ',') {
break;
}
channel_id = channel_id * 10 + (data - '0');
}
while (1) {
if (tos_at_uart_read(&data, 1) != 1) {
return;
}
if (data == ':') {
break;
}
data_len = data_len * 10 + (data - '0');
}
if (data_len > sizeof(incoming_data_buffer)) {
data_len = sizeof(incoming_data_buffer);
}
if (tos_at_uart_read(incoming_data_buffer, data_len) != data_len) {
return;
}
tos_at_channel_write(channel_id, incoming_data_buffer, data_len);
}
at_event_t esp8266_at_event[] = {
{ "+IPD,", esp8266_incoming_data_process },
};
sal_module_t sal_module_esp8266 = {
.init = esp8266_init,
.connect = esp8266_connect,
.send = esp8266_send,
.recv_timeout = esp8266_recv_timeout,
.recv = esp8266_recv,
.close = esp8266_close,
.parse_domain = esp8266_parse_domain,
};
int esp8266_join_ap(const char *ssid, const char *pwd)
{
esp8266_imsg_join_ap_t *msg_join_ap;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_imsg_join_ap_t));
msg_join_ap = (esp8266_imsg_join_ap_t *)msg_body;
msg_join_ap->header.event = EVENT_IMSG_ESP8266_JOIN_AP;
msg_join_ap->header.sender_id = tos_evtdrv_task_self();
msg_join_ap->ssid = (char *)ssid;
msg_join_ap->pwd = (char *)pwd;
if (tos_evtdrv_msg_send(CONTEXT(self_task_id), (evtdrv_msg_body_t)msg_join_ap) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
int esp8266_sal_init(hal_uart_port_t uart_port, evtdrv_task_id_t at_task_id, evtdrv_task_id_t esp8266_task_id)
{
esp8266_imsg_init_t *msg_init;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_imsg_init_t));
msg_init = (esp8266_imsg_init_t *)msg_body;
msg_init->header.event = EVENT_IMSG_ESP8266_INIT;
msg_init->header.sender_id = tos_evtdrv_task_self();
msg_init->uart_port = uart_port;
msg_init->at_task_id = at_task_id;
msg_init->esp8266_task_id = esp8266_task_id;
if (tos_evtdrv_msg_send(esp8266_task_id, (evtdrv_msg_body_t)msg_init) != EVTDRV_ERR_NONE) {
return -1;
}
return 0;
}
static void esp8266_send_msg_reply(int write_len)
{
esp8266_omsg_send_t *omsg_send;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_omsg_send_t));
omsg_send = (esp8266_omsg_send_t *)msg_body;
omsg_send->header.event = EVENT_OMSG_ESP8266_SEND;
omsg_send->header.sender_id = tos_evtdrv_task_self();
omsg_send->write_len = write_len;
tos_evtdrv_msg_send(CONTEXT(caller_task_id), (evtdrv_msg_body_t)omsg_send);
}
static void esp8266_connect_msg_reply(int sockid)
{
esp8266_omsg_connect_t *omsg_connect;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_omsg_connect_t));
omsg_connect = (esp8266_omsg_connect_t *)msg_body;
omsg_connect->header.event = EVENT_OMSG_ESP8266_CONNECT;
omsg_connect->header.sender_id = tos_evtdrv_task_self();
omsg_connect->sockid = sockid;
tos_evtdrv_msg_send(CONTEXT(caller_task_id), (evtdrv_msg_body_t)omsg_connect);
}
static void esp8266_common_msg_reply(evtdrv_event_flag_t event_flag, int return_code)
{
esp8266_omsg_common_t *omsg_common;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(esp8266_omsg_common_t));
omsg_common = (esp8266_omsg_common_t *)msg_body;
omsg_common->header.event = event_flag;
omsg_common->header.sender_id = tos_evtdrv_task_self();
omsg_common->return_code = return_code;
tos_evtdrv_msg_send(CONTEXT(caller_task_id), (evtdrv_msg_body_t)omsg_common);
}
evtdrv_event_flag_t esp8266_task(evtdrv_event_flag_t event)
{
esp8266_event_hdr_t *event_hdr;
esp8266_imsg_init_t *imsg_init;
esp8266_imsg_join_ap_t *imsg_join_ap;
esp8266_imsg_connect_t *imsg_connect;
esp8266_imsg_send_t *imsg_send;
esp8266_imsg_close_t *imsg_close;
esp8266_imsg_domain_parse_t *imsg_domain_parse;
if (event & TOS_EVTDRV_SYS_EVENT_INIT) {
return TOS_EVTDRV_SYS_EVENT_INIT;
}
if (event & TOS_EVTDRV_SYS_EVENT_MSG) {
while (event_hdr = (esp8266_event_hdr_t *)tos_evtdrv_msg_recv()) {
switch (event_hdr->event) {
case EVENT_IMSG_ESP8266_INIT:
imsg_init = (esp8266_imsg_init_t *)event_hdr;
CONTEXT(caller_task_id) = event_hdr->sender_id;
CONTEXT(self_task_id) = imsg_init->esp8266_task_id;
CONTEXT(try) = 0;
if (tos_at_init(imsg_init->uart_port, imsg_init->at_task_id, esp8266_at_event,
sizeof(esp8266_at_event) / sizeof(esp8266_at_event[0])) != 0) {
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
break;
}
if (tos_sal_module_register(&sal_module_esp8266) != 0) {
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
break;
}
tos_sal_module_init();
break;
case EVENT_IMSG_ESP8266_JOIN_AP:
imsg_join_ap = (esp8266_imsg_join_ap_t *)event_hdr;
CONTEXT(ssid) = imsg_join_ap->ssid;
CONTEXT(pwd) = imsg_join_ap->pwd;
esp8266_do_join_ap(imsg_join_ap->ssid, imsg_join_ap->pwd);
break;
case EVENT_IMSG_ESP8266_CONNECT:
imsg_connect = (esp8266_imsg_connect_t *)event_hdr;
if (esp8266_do_connect(imsg_connect->ip, imsg_connect->port, imsg_connect->proto) < 0) {
esp8266_connect_msg_reply(-1);
}
break;
case EVENT_IMSG_ESP8266_SEND:
imsg_send = (esp8266_imsg_send_t *)event_hdr;
CONTEXT(send_info).sockid = imsg_send->sockid;
CONTEXT(send_info).buf = imsg_send->buf;
CONTEXT(send_info).len = imsg_send->len;
if (esp8266_do_send_ready(imsg_send->sockid, imsg_send->buf, imsg_send->len) != 0) {
esp8266_send_msg_reply(-1);
}
break;
case EVENT_IMSG_ESP8266_CLOSE:
imsg_close = (esp8266_imsg_close_t *)event_hdr;
esp8266_do_close(imsg_close->sockid);
break;
case EVENT_IMSG_ESP8266_DOMAIN_PARSE:
imsg_domain_parse = (esp8266_imsg_domain_parse_t *)event_hdr;
CONTEXT(domain_parse_info).host_ip = imsg_domain_parse->host_ip;
CONTEXT(domain_parse_info).host_ip_len = imsg_domain_parse->host_ip_len;
esp8266_do_parse_domain(imsg_domain_parse->host_name, imsg_domain_parse->host_ip, imsg_domain_parse->host_ip_len);
break;
}
tos_evtdrv_msg_free((evtdrv_msg_body_t)event_hdr);
}
return TOS_EVTDRV_SYS_EVENT_MSG;
}
if (event & EVENT_INTERNAL_ESP8266_INIT) {
esp8266_restore();
return EVENT_INTERNAL_ESP8266_INIT;
}
if (event & EVENT_INTERNAL_ESP8266_RESTORE) {
at_delay_ms(3000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK) {
if (CONTEXT(try)++ < 10) {
esp8266_restore();
} else {
printf("restore failed\n");
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
}
} else {
esp8266_echo_close();
}
CONTEXT(try) = 0;
return EVENT_INTERNAL_ESP8266_RESTORE;
}
if (event & EVENT_INTERNAL_ESP8266_ECHO_CLOSE) {
at_delay_ms(2000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK) {
printf("echo close failed\n");
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
} else {
esp8266_net_mode_set(SAL_NET_MODE_STA);
}
return EVENT_INTERNAL_ESP8266_ECHO_CLOSE;
}
if (event & EVENT_INTERNAL_ESP8266_NET_MODE_SET) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK &&
CONTEXT(echo).status != AT_ECHO_STATUS_EXPECT) {
if (CONTEXT(try)++ < 10) {
esp8266_net_mode_set(SAL_NET_MODE_STA);
} else {
printf("net mode set failed\n");
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
}
} else {
esp8266_send_mode_set(SAL_SEND_MODE_NORMAL);
}
CONTEXT(try) = 0;
return EVENT_INTERNAL_ESP8266_NET_MODE_SET;
}
if (event & EVENT_INTERNAL_ESP8266_SEND_MODE_SET) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK) {
if (CONTEXT(try)++ < 10) {
esp8266_send_mode_set(SAL_SEND_MODE_NORMAL);
} else {
printf("send mode set failed\n");
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
}
} else {
esp8266_multilink_set(SAL_MULTILINK_STATE_ENABLE);
}
CONTEXT(try) = 0;
return EVENT_INTERNAL_ESP8266_SEND_MODE_SET;
}
if (event & EVENT_INTERNAL_ESP8266_MULTILINK_SET) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK) {
if (CONTEXT(try)++ < 10) {
esp8266_multilink_set(SAL_MULTILINK_STATE_ENABLE);
} else {
printf("multilink set failed\n");
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, -1);
}
} else {
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_INIT, 0);
}
CONTEXT(try) = 0;
return EVENT_INTERNAL_ESP8266_MULTILINK_SET;
}
if (event & EVENT_INTERNAL_ESP8266_JOIN_AP) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_EXPECT) {
if (CONTEXT(try)++ < 10) {
esp8266_do_join_ap(CONTEXT(ssid), CONTEXT(pwd));
} else {
printf("esp8266 join ap failed");
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_JOIN_AP, -1);
}
} else {
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_JOIN_AP, 0);
}
CONTEXT(try) = 0;
return EVENT_INTERNAL_ESP8266_JOIN_AP;
}
if (event & EVENT_INTERNAL_ESP8266_CONNECT) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_EXPECT &&
CONTEXT(echo).status != AT_ECHO_STATUS_OK) {
printf("esp8266 connect failed\n");
esp8266_connect_msg_reply(-1);
} else {
esp8266_connect_msg_reply(CONTEXT(sockid));
}
return EVENT_INTERNAL_ESP8266_CONNECT;
}
if (event & EVENT_INTERNAL_ESP8266_SEND_READY) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK &&
CONTEXT(echo).status != AT_ECHO_STATUS_EXPECT) {
if (esp8266_is_link_broken((const char *)CONTEXT(echo).buffer)) {
tos_at_channel_set_broken(CONTEXT(sockid));
}
esp8266_send_msg_reply(-1);
} else {
esp8266_do_send(CONTEXT(send_info).sockid, CONTEXT(send_info).buf, CONTEXT(send_info).len);
}
return EVENT_INTERNAL_ESP8266_SEND_READY;
}
if (event & EVENT_INTERNAL_ESP8266_SEND) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_EXPECT) {
if (esp8266_is_link_broken((const char *)CONTEXT(echo).buffer)) {
tos_at_channel_set_broken(CONTEXT(sockid));
}
esp8266_send_msg_reply(-1);
} else {
esp8266_send_msg_reply(CONTEXT(send_info).len);
}
return EVENT_INTERNAL_ESP8266_SEND;
}
if (event & EVENT_INTERNAL_ESP8266_DOMAIN_PARSE) {
at_delay_ms(1000);
if (CONTEXT(echo).status != AT_ECHO_STATUS_OK) {
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_DOMAIN_PARSE, -1);
} else {
/*
+CIPDOMAIN:183.232.231.172
*/
char *str = strstr((const char *)CONTEXT(echo_buffer), "+CIPDOMAIN:");
if (!str) {
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_DOMAIN_PARSE, -1);
} else {
char *host_ip_buffer = CONTEXT(domain_parse_info).host_ip;
size_t host_ip_buffer_len = CONTEXT(domain_parse_info).host_ip_len;
sscanf(str, "+CIPDOMAIN:%s", host_ip_buffer);
host_ip_buffer[host_ip_buffer_len - 1] = '\0';
printf("GOT IP: %s\n", host_ip_buffer);
esp8266_common_msg_reply(EVENT_OMSG_ESP8266_DOMAIN_PARSE, 0);
}
}
return EVENT_INTERNAL_ESP8266_DOMAIN_PARSE;
}
return TOS_EVTDRV_EVENT_NONE;
}

View File

@@ -0,0 +1,134 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#ifndef __ESP8266_H__
#define __ESP8266_H__
#include "tos_evtdrv.h"
#include "tos_hal.h"
#include "sal_module_wrapper.h"
#define EVENT_INTERNAL_ESP8266_INIT (1u << 0)
#define EVENT_INTERNAL_ESP8266_RESTORE (1u << 1)
#define EVENT_INTERNAL_ESP8266_ECHO_CLOSE (1u << 2)
#define EVENT_INTERNAL_ESP8266_NET_MODE_SET (1u << 3)
#define EVENT_INTERNAL_ESP8266_SEND_MODE_SET (1u << 4)
#define EVENT_INTERNAL_ESP8266_MULTILINK_SET (1u << 5)
#define EVENT_INTERNAL_ESP8266_JOIN_AP (1u << 6)
#define EVENT_INTERNAL_ESP8266_CONNECT (1u << 7)
#define EVENT_INTERNAL_ESP8266_SEND_READY (1u << 8)
#define EVENT_INTERNAL_ESP8266_SEND (1u << 9)
#define EVENT_INTERNAL_ESP8266_DOMAIN_PARSE (1u << 10)
#define EVENT_IMSG_ESP8266_INIT (1u << 0)
#define EVENT_IMSG_ESP8266_JOIN_AP (1u << 1)
#define EVENT_IMSG_ESP8266_CONNECT (1u << 2)
#define EVENT_IMSG_ESP8266_SEND (1u << 3)
#define EVENT_IMSG_ESP8266_CLOSE (1u << 4)
#define EVENT_IMSG_ESP8266_DOMAIN_PARSE (1u << 5)
#define EVENT_OMSG_ESP8266_INIT (1u << 0)
#define EVENT_OMSG_ESP8266_JOIN_AP (1u << 1)
#define EVENT_OMSG_ESP8266_CONNECT (1u << 2)
#define EVENT_OMSG_ESP8266_SEND (1u << 3)
#define EVENT_OMSG_ESP8266_DOMAIN_PARSE (1u << 4)
typedef struct esp8266_event_header_st {
evtdrv_event_flag_t event;
evtdrv_task_id_t sender_id;
} esp8266_event_hdr_t;
typedef struct esp8266_in_msg_init_st {
esp8266_event_hdr_t header;
hal_uart_port_t uart_port;
evtdrv_task_id_t at_task_id;
evtdrv_task_id_t esp8266_task_id;
} esp8266_imsg_init_t;
typedef struct esp8266_in_msg_join_ap_st {
esp8266_event_hdr_t header;
char *ssid;
char *pwd;
} esp8266_imsg_join_ap_t;
typedef struct esp8266_in_msg_connect_st {
esp8266_event_hdr_t header;
char *ip;
char *port;
sal_proto_t proto;
} esp8266_imsg_connect_t;
typedef struct esp8266_in_msg_send_st {
esp8266_event_hdr_t header;
int sockid;
void *buf;
size_t len;
} esp8266_imsg_send_t;
typedef struct esp8266_in_msg_close_st {
esp8266_event_hdr_t header;
int sockid;
} esp8266_imsg_close_t;
typedef struct esp8266_in_msg_domain_parse_st {
esp8266_event_hdr_t header;
char *host_name;
char *host_ip;
size_t host_ip_len;
} esp8266_imsg_domain_parse_t;
typedef struct esp8266_out_msg_common_st {
esp8266_event_hdr_t header;
int return_code;
} esp8266_omsg_common_t;
typedef struct esp8266_out_msg_connect_st {
esp8266_event_hdr_t header;
int sockid;
} esp8266_omsg_connect_t;
typedef struct esp8266_out_msg_send_st {
esp8266_event_hdr_t header;
int write_len;
} esp8266_omsg_send_t;
typedef enum sal_net_mode {
SAL_NET_MODE_STA,
SAL_NET_MODE_AP,
SAL_NET_MODE_STA_AP,
} sal_net_mode_t ;
typedef enum sal_send_mode {
SAL_SEND_MODE_NORMAL,
SAL_SEND_MODE_TRANSPARENT,
} sal_send_mode_t;
typedef enum sal_multilink_state {
SAL_MULTILINK_STATE_ENABLE,
SAL_MULTILINK_STATE_DISABLE,
} sal_multilink_state_t;
int esp8266_sal_init(hal_uart_port_t uart_port, evtdrv_task_id_t at_task_id, evtdrv_task_id_t esp8266_task_id);
int esp8266_join_ap(const char *ssid, const char *pwd);
evtdrv_event_flag_t esp8266_task(evtdrv_event_flag_t event);
#endif /* __ESP8266_H__ */

View File

@@ -0,0 +1,160 @@
#include "esp8266_evtdrv.h"
#include "tos_at_evtdrv.h"
#include "tos_evtdrv.h"
#include "sal_module_wrapper.h"
evtdrv_task_id_t at_task_id = 0;
evtdrv_task_id_t esp8266_task_id = 1;
evtdrv_task_id_t user_task_id = 2;
int socket_id_0 = 0;
#define RECV_LEN 1024
uint8_t recv_data_0[RECV_LEN];
evtdrv_timer_t task0_send_timer;
#define EVENT_USER_INIT (1u << 0)
#define EVENT_USER_SEND (1u << 1)
#define EVENT_USER_CLOSE (1u << 2)
int send_count = 0;
char host_ip[16];
void timer_callback(void *arg)
{
tos_evtdrv_event_set(user_task_id, EVENT_USER_SEND);
}
evtdrv_event_flag_t user_task(evtdrv_event_flag_t event)
{
esp8266_event_hdr_t *event_hdr;
esp8266_omsg_common_t *omsg_common;
esp8266_omsg_connect_t *omsg_connect;
esp8266_omsg_send_t *omsg_send;
if (event & TOS_EVTDRV_SYS_EVENT_INIT) {
tos_evtdrv_event_set(user_task_id, EVENT_USER_INIT);
return TOS_EVTDRV_SYS_EVENT_INIT;
}
if (event & EVENT_USER_INIT) {
esp8266_sal_init(HAL_UART_PORT_0, at_task_id, esp8266_task_id);
return EVENT_USER_INIT;
}
if (event & TOS_EVTDRV_SYS_EVENT_MSG) {
while (event_hdr = (esp8266_event_hdr_t *)tos_evtdrv_msg_recv()) {
if (event_hdr->sender_id == esp8266_task_id) {
switch (event_hdr->event) {
case EVENT_OMSG_ESP8266_INIT:
omsg_common = (esp8266_omsg_common_t *)event_hdr;
if (omsg_common->return_code == 0) {
esp8266_join_ap("SheldonDai", "srnr6x9xbhmb0");
} else {
printf("esp8266 init failed!\n");
}
break;
case EVENT_OMSG_ESP8266_JOIN_AP:
omsg_common = (esp8266_omsg_common_t *)event_hdr;
if (omsg_common->return_code != 0) {
printf("esp8266 join ap failed!\n");
break;
}
tos_sal_module_parse_domain("www.tencent.com", host_ip, sizeof(host_ip));
break;
case EVENT_OMSG_ESP8266_DOMAIN_PARSE:
omsg_common = (esp8266_omsg_common_t *)event_hdr;
if (omsg_common->return_code != 0) {
printf("esp8266 domain parse failed!\n");
} else {
printf("domain parse(www.tencent.com): %s\n", host_ip);
}
tos_sal_module_connect("39.108.190.129", "8080", TOS_SAL_PROTO_TCP);
break;
case EVENT_OMSG_ESP8266_CONNECT:
omsg_connect = (esp8266_omsg_connect_t *)event_hdr;
socket_id_0 = omsg_connect->sockid;
if (socket_id_0 < 0) {
printf("esp8266 connect failed!\n");
break;
}
/* <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> */
tos_evtdrv_timer_create(&task0_send_timer,
timer_callback, NULL,
EVTDRV_TIMER_OPT_PERIODIC);
tos_evtdrv_timer_start(&task0_send_timer, 6000);
break;
case EVENT_OMSG_ESP8266_SEND:
omsg_send = (esp8266_omsg_send_t *)event_hdr;
int write_len = omsg_send->write_len;
if (write_len < 0) {
printf("write failed! %d\n", write_len);
} else {
printf("task0 write success: %d\n", write_len);
}
break;
}
}
tos_evtdrv_msg_free((evtdrv_msg_body_t)event_hdr);
}
return TOS_EVTDRV_SYS_EVENT_MSG;
}
if (event & EVENT_USER_SEND) {
if (++send_count > 5) {
// after send 5 times, we shutdown the connection
tos_evtdrv_event_set(user_task_id, EVENT_USER_CLOSE);
return EVENT_USER_SEND;
}
tos_sal_module_send(socket_id_0, "hello", 5);
int len = tos_sal_module_recv(socket_id_0, recv_data_0, sizeof(recv_data_0));
if (len > 0) {
printf("task0 receive from server(%d): %s\n", len, recv_data_0);
}
return EVENT_USER_SEND;
}
if (event & EVENT_USER_CLOSE) {
tos_evtdrv_timer_stop(&task0_send_timer);
tos_sal_module_close(socket_id_0);
return EVENT_USER_CLOSE;
}
return TOS_EVTDRV_EVENT_NONE;
}
evtdrv_task_entry_t tasks[] = {
tos_at_evtdrv_task,
esp8266_task,
user_task,
};
int main(void)
{
board_init();
tos_evtdrv_sys_init(tasks, sizeof(tasks) / sizeof(tasks[0]), K_NULL);
tos_evtdrv_sys_start();
}

View File

@@ -0,0 +1,261 @@
#include "tos_evtdrv.h"
typedef struct event_hdr_st {
uint8_t event;
} event_hdr_t;
typedef struct consumer_msg_st {
event_hdr_t hdr;
uint16_t require_len;
} consumer_msg_t;
typedef struct productor_msg_st {
event_hdr_t hdr;
uint16_t payload_len;
char *payload;
} productor_msg_t;
evtdrv_task_id_t productor_id = 0;
evtdrv_task_id_t consumer1_id = 1;
evtdrv_task_id_t consumer2_id = 2;
#define EVENT_CONSUMER1 (1u << 0)
#define EVENT_CONSUMER2 (1u << 1)
#define EVENT_PRODUCTOR (1u << 2)
#define EVENT_CONSUER1_HUNGRY (1u << 3)
#define EVENT_CONSUER2_HUNGRY (1u << 4)
#define CONSUMER1_REQUIRE_LEN 5
#define CONSUMER2_REQUIRE_LEN 9
static void msg_payload_fill(char *payload, uint16_t len)
{
uint16_t i = 0;
for (i = 0; i < len - 1; ++i) {
payload[i] = (i % 10) + 'a';
}
payload[len - 1] = '\0';
}
productor_msg_t *msg4consumer_forge(uint16_t consumer_require_len)
{
productor_msg_t *productor_msg;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(productor_msg_t) + consumer_require_len + 1);
if (!msg_body) {
return K_NULL;
}
productor_msg = (productor_msg_t *)msg_body;
productor_msg->hdr.event = EVENT_PRODUCTOR;
productor_msg->payload_len = consumer_require_len;
productor_msg->payload = (char *)(productor_msg + 1);
msg_payload_fill(productor_msg->payload, consumer_require_len + 1);
return productor_msg;
}
evtdrv_event_flag_t task_productor(evtdrv_event_flag_t event)
{
uint16_t consumer_require_len;
consumer_msg_t *consumer_msg;
productor_msg_t *productor_msg;
if (event & TOS_EVTDRV_SYS_EVENT_INIT) {
printf("init logic for productor\n");
// return event handled
return TOS_EVTDRV_SYS_EVENT_INIT;
}
if (event & TOS_EVTDRV_SYS_EVENT_MSG) {
while (consumer_msg = (consumer_msg_t *)tos_evtdrv_msg_recv()) {
consumer_require_len = consumer_msg->require_len;
switch (consumer_msg->hdr.event) {
case EVENT_CONSUMER1:
printf("msg from consumer1, %d len required\n", consumer_require_len);
productor_msg = msg4consumer_forge(consumer_require_len);
if (productor_msg) {
tos_evtdrv_msg_send(consumer1_id, (evtdrv_msg_body_t)productor_msg);
}
break;
case EVENT_CONSUMER2:
printf("msg from consumer2, %d len required\n", consumer_require_len);
productor_msg = msg4consumer_forge(consumer_require_len);
if (productor_msg) {
tos_evtdrv_msg_send(consumer2_id, (evtdrv_msg_body_t)productor_msg);
}
break;
}
tos_evtdrv_msg_free((evtdrv_msg_body_t)consumer_msg);
}
// return event handled
return TOS_EVTDRV_SYS_EVENT_MSG;
}
if (event & EVENT_CONSUER1_HUNGRY) {
productor_msg = msg4consumer_forge(CONSUMER1_REQUIRE_LEN);
if (productor_msg) {
tos_evtdrv_msg_send(consumer1_id, (evtdrv_msg_body_t)productor_msg);
}
// return event handled
return EVENT_CONSUER1_HUNGRY;
}
if (event & EVENT_CONSUER2_HUNGRY) {
productor_msg = msg4consumer_forge(CONSUMER2_REQUIRE_LEN);
if (productor_msg) {
tos_evtdrv_msg_send(consumer2_id, (evtdrv_msg_body_t)productor_msg);
}
// return event handled
return EVENT_CONSUER2_HUNGRY;
}
return TOS_EVTDRV_EVENT_NONE;
}
consumer_msg_t *msg4productor_forge(uint16_t consumer_event, uint16_t consumer_require_len)
{
consumer_msg_t *consumer_msg;
evtdrv_msg_body_t msg_body;
msg_body = tos_evtdrv_msg_alloc(sizeof(consumer_msg_t));
if (!msg_body) {
return K_NULL;
}
consumer_msg = (consumer_msg_t *)msg_body;
consumer_msg->hdr.event = consumer_event;
consumer_msg->require_len = consumer_require_len;
return consumer_msg;
}
evtdrv_timer_t consumer1_timer;
evtdrv_timer_t consumer2_timer;
void consumer1_timer_callback(void *arg)
{
printf("consumer1_timer_callback\n");
tos_evtdrv_event_set(productor_id, EVENT_CONSUER1_HUNGRY);
}
void consumer2_timer_callback(void *arg)
{
printf("consumer2_timer_callback\n");
tos_evtdrv_event_set(productor_id, EVENT_CONSUER2_HUNGRY);
}
evtdrv_event_flag_t task_consumer1(evtdrv_event_flag_t event)
{
consumer_msg_t *consumer_msg;
productor_msg_t *productor_msg;
if (event & TOS_EVTDRV_SYS_EVENT_INIT) {
printf("init logic for consumer1\n");
tos_evtdrv_timer_create(&consumer1_timer,
consumer1_timer_callback, NULL,
EVTDRV_TIMER_OPT_PERIODIC);
tos_evtdrv_timer_start(&consumer1_timer, 4000);
consumer_msg = msg4productor_forge(EVENT_CONSUMER1, CONSUMER1_REQUIRE_LEN);
if (consumer_msg) {
tos_evtdrv_msg_send(productor_id, (evtdrv_msg_body_t)consumer_msg);
}
// return event handled
return TOS_EVTDRV_SYS_EVENT_INIT;
}
if (event & TOS_EVTDRV_SYS_EVENT_MSG) {
while (productor_msg = (productor_msg_t *)tos_evtdrv_msg_recv()) {
switch (productor_msg->hdr.event) {
case EVENT_PRODUCTOR:
printf("\nconsumer1:\nmsg from productor, payload_len: %d\npayload: %s\n", productor_msg->payload_len, productor_msg->payload);
break;
}
tos_evtdrv_msg_free((evtdrv_msg_body_t)productor_msg);
}
// return event handled
return TOS_EVTDRV_SYS_EVENT_MSG;
}
return TOS_EVTDRV_EVENT_NONE;
}
evtdrv_event_flag_t task_consumer2(evtdrv_event_flag_t event)
{
consumer_msg_t *consumer_msg;
productor_msg_t *productor_msg;
if (event & TOS_EVTDRV_SYS_EVENT_INIT) {
printf("init logic for consumer2\n");
tos_evtdrv_timer_create(&consumer2_timer,
consumer2_timer_callback, NULL,
EVTDRV_TIMER_OPT_PERIODIC);
tos_evtdrv_timer_start(&consumer2_timer, 6000);
consumer_msg = msg4productor_forge(EVENT_CONSUMER2, CONSUMER2_REQUIRE_LEN);
if (consumer_msg) {
tos_evtdrv_msg_send(productor_id, (evtdrv_msg_body_t)consumer_msg);
}
// return event handled
return TOS_EVTDRV_SYS_EVENT_INIT;
}
if (event & TOS_EVTDRV_SYS_EVENT_MSG) {
while (productor_msg = (productor_msg_t *)tos_evtdrv_msg_recv()) {
switch (productor_msg->hdr.event) {
case EVENT_PRODUCTOR:
printf("\nconsumer2:\nmsg from productor, payload_len: %d\npayload: %s\n", productor_msg->payload_len, productor_msg->payload);
break;
}
tos_evtdrv_msg_free((evtdrv_msg_body_t)productor_msg);
}
// return event handled
return TOS_EVTDRV_SYS_EVENT_MSG;
}
return TOS_EVTDRV_EVENT_NONE;
}
evtdrv_task_entry_t tasks[] = {
task_productor,
task_consumer1,
task_consumer2
};
int main(void)
{
board_init();
tos_evtdrv_sys_init(tasks, sizeof(tasks) / sizeof(tasks[0]), K_NULL);
tos_evtdrv_sys_start();
}