16 changed files with 924 additions and 138 deletions
-
54app/MDK-ARM/app.uvguix.29643
-
48app/MDK-ARM/app.uvoptx
-
19app/MDK-ARM/app.uvprojx
-
75src/encoder_acquistion.c
-
20src/encoder_acquistion.h
-
434src/encoder_acquistion_service.c
-
14src/encoder_acquistion_service.h
-
2src/protocol.h
-
10src/usermain.c
-
6src/zassert.h
-
2src/zport.c
-
0src/zport.h
-
96src/zthread.c
-
46src/zthread.h
@ -0,0 +1,75 @@ |
|||
#include "encoder_acquistion.h" |
|||
|
|||
#include "config.h" |
|||
#include "stdlib.h" |
|||
#include "zassert.h" |
|||
#include "zboard.h" |
|||
#include "zthread.h" |
|||
|
|||
#define REPORT_BUF_SIZE 1000 |
|||
|
|||
#define TAG "aencoder_acquistion_driver" |
|||
static zthread_t s_workingthread; |
|||
uint8_t *s_reportbuf; |
|||
uint32_t s_reportbufsize; |
|||
encoder_acquisition_cb_t s_cb; |
|||
|
|||
/** |
|||
* @brief 在这里上报语音 |
|||
* |
|||
* @param arg |
|||
* |
|||
* PS: |
|||
* 函数效率在240MHZ的情况下,1s的语音数据(32bit,16k)大概需要2ms的处理时间 |
|||
*/ |
|||
|
|||
static void prv_workingthread(void *arg) { |
|||
while (!zthread_is_expect_stop(&s_workingthread)) { |
|||
size_t bytes_read; |
|||
// ESP_LOGI(TAG, "read %d ", bytes_read); |
|||
if (s_cb) { |
|||
#if 0 |
|||
//测试放大方法效率 |
|||
uint32_t sticket = xTaskGetTickCount(); |
|||
for(unsigned i = 0; i < 16*4; ++i) { |
|||
amf_voice(s_reportbuf, bytes_read); |
|||
} |
|||
uint32_t endticket = xTaskGetTickCount(); |
|||
ESP_LOGI(TAG, " %d use %d", bytes_read,endticket - sticket); |
|||
#else |
|||
// amf_voice(s_reportbuf, bytes_read); |
|||
#endif |
|||
|
|||
// 因为MIC最大响度能够达到的幅值为0.316v,和3.3v差了3.3/0.316倍, |
|||
// 又因为PCM1808位宽为24bit,32位中低八位为零,已经默认放大 |
|||
// 则可以保证数据放大3.3/0.316后数据是无损的. |
|||
for (size_t i = 0; i < bytes_read; i += 4) { |
|||
int32_t *rxdata = (int32_t *)&s_reportbuf[i]; |
|||
(*rxdata) = (*rxdata) * 3.3 / 0.316; |
|||
} |
|||
|
|||
// 对音频按照配置进行放大 |
|||
for (size_t i = 0; i < bytes_read; i += 4) { |
|||
int32_t *rxdata = (int32_t *)&s_reportbuf[i]; |
|||
} |
|||
|
|||
s_cb(s_reportbuf, bytes_read); |
|||
} |
|||
} |
|||
} |
|||
void encoder_acquisition_init(encoder_acquisition_cb_t cb) { |
|||
// s_workingthread |
|||
|
|||
// s_workingthread |
|||
|
|||
s_reportbuf = malloc(REPORT_BUF_SIZE); |
|||
s_reportbufsize = REPORT_BUF_SIZE; |
|||
s_cb = cb; |
|||
Z_ASSERT(s_reportbuf); |
|||
Z_ASSERT(s_reportbufsize); |
|||
Z_ASSERT(s_cb); |
|||
|
|||
zthread_init(&s_workingthread, "encoder_acquistion_driver", prv_workingthread); |
|||
} |
|||
void encoder_acquisition_start_cauture() { zthread_start(&s_workingthread); } |
|||
void encoder_acquisition_stop_cauture() { zthread_stop(&s_workingthread); } |
@ -0,0 +1,20 @@ |
|||
#pragma once |
|||
#include <stdint.h> |
|||
|
|||
//采集端配置 |
|||
#define CONFIG_MODE (I2S_MODE_SLAVE | I2S_MODE_RX) //模式 |
|||
#define CONFIG_SAMPLE_RATE 48000 //采样率 |
|||
#define CONFIG_BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_24BIT //采样位数 |
|||
#define CONFIG_CHANNEL_FORMAT I2S_CHANNEL_FMT_RIGHT_LEFT // I2S格式 |
|||
#define CONFIG_COMMUNICATION_FORMAT (I2S_COMM_FORMAT_STAND_MSB) // I2S标准 |
|||
#define CONFIG_INTR_ALLOC_FLAGS ESP_INTR_FLAG_LEVEL1 // |
|||
//上报端格式配置 |
|||
#define CONFIG_REPORT_BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_16BIT //上报数据 采样位数 |
|||
#define CONFIG_REPORT_SAMPLE_RATE CONFIG_SAMPLE_RATE //上报数据 采样率 |
|||
#define CONFIG_REPORT_BUF_SIZE 600 //每次上报的字节数(注意需要和采样位数存在倍数关系) |
|||
|
|||
typedef void (*encoder_acquisition_cb_t)(uint8_t *data, uint32_t size); |
|||
|
|||
void encoder_acquisition_init(encoder_acquisition_cb_t cb); |
|||
void encoder_acquisition_start_cauture(); |
|||
void encoder_acquisition_stop_cauture(); |
@ -0,0 +1,434 @@ |
|||
#include "lwip/err.h" |
|||
#include "lwip/sockets.h" |
|||
#include "lwip/sys.h" |
|||
#include <lwip/netdb.h> |
|||
|
|||
#include "zboard.h" |
|||
#include "config.h" |
|||
#include "FreeRTOS.h" |
|||
#include "event_groups.h" |
|||
#include "task.h" |
|||
#include "protocol.h" |
|||
#include "encoder_acquistion.h" |
|||
//#include "sys/time.h" |
|||
#include "zassert.h" |
|||
#include "zthread.h" |
|||
|
|||
#define TAG "encoder_acquistion_service" |
|||
|
|||
__attribute__((weak)) void hook_before_restart_device(); |
|||
|
|||
int sock = -1; |
|||
|
|||
static zthread_t s_workingthread; |
|||
static struct sockaddr_storage now_source_addr; |
|||
static struct sockaddr_storage |
|||
s_request_encoder_acquist_udp_add; // 请求语音传输的端口 |
|||
|
|||
static bool s_report_voice_flag = false; |
|||
static protocol_header_t s_report_receipt_buf; |
|||
static uint32_t s_voice_index = 0; |
|||
|
|||
static void do_restart_device() { |
|||
ZLOGE(TAG, "we doon't kown why it happen,so restart device"); |
|||
ZLOGE(TAG, "restart device"); |
|||
|
|||
hook_before_restart_device(); |
|||
// esp_restart(); |
|||
} |
|||
|
|||
bool protocol_check_packet(char *data, uint32_t size) { |
|||
|
|||
protocol_header_t *rxcmd = (protocol_header_t *)data; |
|||
if (rxcmd->packet_type != PROTOCOL_HEADER || |
|||
rxcmd->minus_packet_type != PROTOCOL_HEADER_MINUS) { |
|||
ZLOGE(TAG, "rx error packet,header is ilegal header a = 0x%02x 0x%02x", |
|||
rxcmd->packet_type, rxcmd->minus_packet_type); |
|||
return false; |
|||
} |
|||
|
|||
uint8_t sum8 = 0; |
|||
|
|||
for (unsigned i = 0; i < size - 1; ++i) { |
|||
sum8 += data[i]; |
|||
} |
|||
|
|||
if (sum8 != data[size - 1]) { |
|||
ZLOGE(TAG, "rx error packet,sumcheck fail,real:0x%02x != expect:0x%02x", |
|||
data[size - 1], sum8); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
uint8_t computesum8(char *data, size_t size) { |
|||
uint8_t sum8 = 0; |
|||
for (unsigned i = 0; i < size; ++i) { |
|||
sum8 += data[i]; |
|||
// ZLOGI(TAG, "%d", sum8); |
|||
} |
|||
return sum8; |
|||
} |
|||
|
|||
static void report_packet(uint8_t *data, uint32_t size) { |
|||
int err = sendto(sock, data, size, 0, (struct sockaddr *)&now_source_addr, |
|||
sizeof(now_source_addr)); |
|||
if (err < 0) { |
|||
ZLOGE(TAG, "report_packet fail: errno %d", errno); |
|||
return; |
|||
} |
|||
} |
|||
static void report_voice(uint8_t *data, uint32_t size) { |
|||
int err = sendto(sock, data, size, 0, |
|||
(struct sockaddr *)&s_request_encoder_acquist_udp_add, |
|||
sizeof(s_request_encoder_acquist_udp_add)); |
|||
if (err < 0) { |
|||
ZLOGE(TAG, "report_voice fail: errno %d", errno); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @brief 语音上报控制寄存器 |
|||
* |
|||
* @param data |
|||
* @param size |
|||
*/ |
|||
|
|||
int create_receipt(char *data, size_t size, uint32_t regvalue, |
|||
uint32_t errocode) { |
|||
protocol_header_t *rxcmd = (protocol_header_t *)data; |
|||
s_report_receipt_buf.packet_type = rxcmd->packet_type; |
|||
s_report_receipt_buf.minus_packet_type = rxcmd->minus_packet_type; |
|||
s_report_receipt_buf.index = rxcmd->index; |
|||
s_report_receipt_buf.action_type = rxcmd->action_type; |
|||
s_report_receipt_buf.reg = rxcmd->reg; |
|||
|
|||
int receiptlen = 0; |
|||
|
|||
s_report_receipt_buf.value.receipt.regvalue = regvalue; |
|||
s_report_receipt_buf.value.receipt.error = errocode; |
|||
|
|||
//计算包长 |
|||
receiptlen = sizeof(protocol_header_t) - sizeof(rxcmd->value) + 4 + 4 + 1; |
|||
|
|||
//计算sum8 |
|||
((char *)&s_report_receipt_buf)[receiptlen - 1] = |
|||
computesum8((char *)&s_report_receipt_buf, receiptlen - 1); |
|||
|
|||
return receiptlen; |
|||
} |
|||
|
|||
void create_and_send_receipt(char *data, size_t size, uint32_t regvalue, |
|||
uint32_t errocode) { |
|||
int len = create_receipt(data, size, regvalue, 0); |
|||
ZLOGI(TAG, "create_and_send_receipt-->"); |
|||
// ZLOG_BUFFER_HEX(TAG, (uint8_t *)&s_report_receipt_buf, len); |
|||
ZLOGI(TAG, "<-"); |
|||
|
|||
report_packet((uint8_t *)&s_report_receipt_buf, len); |
|||
} |
|||
|
|||
/*************************************************************************************/ |
|||
/*************************************指令处理**************************************/ |
|||
/*************************************************************************************/ |
|||
|
|||
void encoder_acquisition_cb(uint8_t *data, uint32_t size) { |
|||
// lock socket |
|||
|
|||
/** |
|||
* @brief 在这里上报语音 |
|||
*/ |
|||
|
|||
// clang-format off |
|||
/* |
|||
| packetlen = 1+1+4+2+1+ voicelen = 9 + voicelen |
|||
| packet_type(8bit) | minus_packet_type(8bit) | voice_index(32bit) | voice_length(16bit) | voice_payload(0->1024byte) | checksum(8bit) | |
|||
| ------------ | ------------------ | ------------------ | ------------------- | -------------------------- | -------------- | |
|||
| 0x55 | 0xAA | 0 | 0 | 1 | | |
|||
| | | | | | | |
|||
*/ |
|||
// clang-format on |
|||
|
|||
//测试模式直接上报 |
|||
// Z_ASSERT(size <= REPORT_VOICE_SIZE); |
|||
|
|||
if (!s_report_voice_flag) { |
|||
return; |
|||
} |
|||
|
|||
/** |
|||
* @brief 按照协议封包上报 |
|||
*/ |
|||
// ZLOGI(TAG, "report voice %d", size); |
|||
|
|||
static uint8_t * reportvoicebuf = NULL; |
|||
|
|||
if(reportvoicebuf == NULL){ |
|||
reportvoicebuf = malloc(size+100); |
|||
} |
|||
|
|||
reportvoicebuf[0] = 0x55; |
|||
reportvoicebuf[1] = 0xAA; |
|||
*(uint32_t *)(&reportvoicebuf[2]) = s_voice_index; |
|||
*(uint16_t *)(&reportvoicebuf[6]) = (uint16_t)size; |
|||
memcpy(&reportvoicebuf[8], data, size); |
|||
|
|||
reportvoicebuf[9 + size - 1] = |
|||
computesum8((char *)reportvoicebuf, 9 + size - 1); |
|||
|
|||
// for (unsigned i = 0; i < config_get()->encoder_report_times; ++i) { |
|||
report_voice(reportvoicebuf, 9 + size); |
|||
// } |
|||
s_voice_index++; |
|||
ZLOGI(TAG,"%d",s_voice_index); |
|||
// unlocksocket |
|||
} |
|||
void process_reg_report_voice(char *data, size_t size) { |
|||
protocol_header_t *rxcmd = (protocol_header_t *)data; |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
|
|||
if (rxcmd->value.regvalue == 1) { |
|||
/** |
|||
* @brief 开始采集语音 |
|||
*/ |
|||
ZLOGI(TAG, "processs packet:encoder_acquisition_start_cauture"); |
|||
s_request_encoder_acquist_udp_add = |
|||
now_source_addr; //拷贝当前指令对应的端口号进行上报 |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
s_voice_index = 0; |
|||
s_report_voice_flag = true; |
|||
|
|||
} else if (rxcmd->value.regvalue == 0) { |
|||
/** |
|||
* @brief 停止采集语音 |
|||
*/ |
|||
ZLOGI(TAG, "processs packet:encoder_acquisition_stop_cauture"); |
|||
ZLOGI(TAG, "has report voice packet %u", s_voice_index); |
|||
s_voice_index = 0; |
|||
s_report_voice_flag = false; |
|||
//简单延时,等待本次上报结束 |
|||
vTaskDelay(10); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @brief 语音上报次数设置寄存器 |
|||
* |
|||
* @param data |
|||
* @param size |
|||
*/ |
|||
void process_reg_report_voice_repect_times(char *data, size_t size) { |
|||
protocol_header_t *rxcmd = (protocol_header_t *)data; |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
// config_get()->encoder_report_times = rxcmd->value.regvalue; |
|||
// config_update(); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
} |
|||
|
|||
/**************************************************************/ |
|||
/**************************************************************/ |
|||
/**************************************************************/ |
|||
|
|||
/** |
|||
* @brief 处理接收到消息 |
|||
* |
|||
* @param data |
|||
* @param size |
|||
*/ |
|||
static void prv_process_rx(char *data, size_t size) { |
|||
ZLOGI(TAG, "process rx data packet [...]%d->", size); |
|||
// ZLOG_BUFFER_HEX(TAG, (uint8_t *)data, size); |
|||
ZLOGI(TAG, "<-"); |
|||
|
|||
/** |
|||
* @brief 这里处理接收到的消息,并进行回复 |
|||
*/ |
|||
|
|||
protocol_header_t *rxcmd = (protocol_header_t *)data; |
|||
if (!protocol_check_packet(data, size)) { |
|||
return; |
|||
} |
|||
|
|||
ZLOGI(TAG, "processs packet:reg %d", rxcmd->reg); |
|||
if (rxcmd->reg == REG_RESTART_DEVICE) { // 0 |
|||
// restart device |
|||
ZLOGI(TAG, "do restart device order"); |
|||
// esp_restart(); |
|||
} else if (rxcmd->reg == REG_REPORT_VOICE) { // 1 |
|||
process_reg_report_voice(data, size); |
|||
} else if (rxcmd->reg == REG_REPORT_VOICE_REPECT_TIMES) { // 2 |
|||
process_reg_report_voice_repect_times(data, size); |
|||
} else if (rxcmd->reg == REG_OBTAINING_IP_MODE) { // 3 |
|||
|
|||
/** |
|||
* @brief 设置获取IP模式 |
|||
*/ |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
config_get()->obtaining_ip_mode = rxcmd->value.regvalue; |
|||
// config_update(); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
|
|||
} else if (rxcmd->reg == REG_STATIC_IP) { // 4 |
|||
|
|||
/** |
|||
* @brief 设置静态IP |
|||
*/ |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
config_get()->ip = rxcmd->value.regvalue; |
|||
// config_update(); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
} else if (rxcmd->reg == REG_IP_MASK) { // 5 |
|||
|
|||
/** |
|||
* @brief 设置掩码 |
|||
*/ |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
config_get()->netmask = rxcmd->value.regvalue; |
|||
// config_update(); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
} else if (rxcmd->reg == REG_ROUTER_IP) { // 6 |
|||
|
|||
/** |
|||
* @brief 设置gateway ip |
|||
*/ |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
config_get()->gw = rxcmd->value.regvalue; |
|||
// config_update(); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
|
|||
} else if (rxcmd->reg == REG_ENCODER_AMPLIFY_FACTOR) { // 10 |
|||
|
|||
/** |
|||
* @brief 设置音频方法倍数 |
|||
*/ |
|||
if (rxcmd->action_type == PROTOCOL_PACKET_TYPE_WRITE) { |
|||
// config_get()->encoder_magnification_factors = rxcmd->value.regvalue; |
|||
// config_update(); |
|||
create_and_send_receipt(data, size, rxcmd->value.regvalue, 0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void prv_workingthread(void *arg) { |
|||
|
|||
// static struct sockaddr_in6 dest_addr; |
|||
// memset(&dest_addr, 0, sizeof(dest_addr)); |
|||
|
|||
// struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr; |
|||
// dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); |
|||
// dest_addr_ip4->sin_family = AF_INET; |
|||
// dest_addr_ip4->sin_port = htons(SERVICE_PORT); |
|||
|
|||
// /** |
|||
// * @brief 创建socket |
|||
// * |
|||
// */ |
|||
// sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); |
|||
|
|||
// if (sock < 0) { |
|||
// /** |
|||
// * @brief 当socket创建失败的时候可能有很多原因, |
|||
// * 但这里没有很好的解决办法,所以打印一个日志直接结束 |
|||
// */ |
|||
// ZLOGE(TAG, "unable to create socket: errno %d", errno); |
|||
// do_restart_device(); |
|||
// } |
|||
|
|||
// /** |
|||
// * @brief 绑定端口号 |
|||
// * |
|||
// */ |
|||
// ZLOGI(TAG, "socket created"); |
|||
// int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); |
|||
// if (err < 0) { |
|||
// /** |
|||
// * @brief 当绑定失败的时候可能有很多原因, |
|||
// * 但这里没有很好的解决办法,所以打印一个日志直接结束 |
|||
// */ |
|||
// ZLOGE(TAG, "socket unable to bind: errno %d", errno); |
|||
// do_restart_device(); |
|||
// } |
|||
// ZLOGI(TAG, "socket bound, port %d", SERVICE_PORT); |
|||
|
|||
// //设置recvfrom超时时间 |
|||
// struct timeval tv = {1, 0}; |
|||
// int32_t b = |
|||
// setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); |
|||
|
|||
// while (!zthread_is_expect_stop(&s_workingthread)) { |
|||
// // static 是为了节省栈空间 |
|||
// static char rx_buffer[1024]; |
|||
// static char clientip[128]; |
|||
|
|||
// socklen_t socklen = sizeof(now_source_addr); |
|||
// int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0 /*flag */, |
|||
// (struct sockaddr *)&now_source_addr, &socklen); |
|||
|
|||
// // Error occurred during receiving |
|||
// if (len < 0) { |
|||
|
|||
// if (errno == EAGAIN || errno == EINTR) { |
|||
// //超时,或者被信号量打断 |
|||
// continue; |
|||
// } |
|||
|
|||
// ZLOGE(TAG, "recvfrom failed: errno %d", errno); |
|||
// continue; |
|||
// } |
|||
// if (len == 0) { |
|||
// continue; |
|||
// } |
|||
|
|||
// // Get the sender's ip address as string |
|||
// inet_ntoa_r(((struct sockaddr_in *)&now_source_addr)->sin_addr, clientip, |
|||
// sizeof(clientip) - 1); |
|||
// ZLOGI(TAG, "Received %d bytes from %s:", len, clientip); |
|||
// /** |
|||
// * @brief 处理接收到的消息 |
|||
// * |
|||
// */ |
|||
// prv_process_rx(rx_buffer, len); |
|||
// } |
|||
|
|||
// /** |
|||
// * @brief 如果停止服务,要同时停止语音采集 |
|||
// */ |
|||
// s_report_voice_flag = false; |
|||
// encoder_acquisition_stop_cauture(); |
|||
|
|||
// if (sock != -1) { |
|||
// ZLOGI(TAG, "Shutting down socket and restarting..."); |
|||
// shutdown(sock, 0); |
|||
// close(sock); |
|||
// } |
|||
// sock = -1; |
|||
} |
|||
void encoder_acquistion_service_init() { |
|||
encoder_acquisition_init( |
|||
encoder_acquisition_cb); |
|||
zthread_init(&s_workingthread, "encoder_acquistion_service", prv_workingthread); |
|||
} |
|||
|
|||
void encoder_acquistion_service_start() { |
|||
ZLOGI(TAG, "call encoder_acquistion_service_start"); |
|||
encoder_acquisition_start_cauture(); |
|||
zthread_start(&s_workingthread); |
|||
} |
|||
void encoder_acquistion_service_stop() { |
|||
ZLOGI(TAG, "call encoder_acquistion_service_stop"); |
|||
zthread_stop(&s_workingthread); |
|||
} |
|||
void encoder_acquistion_enter_test_mode() {} |
|||
|
|||
bool encoder_acquistion_service_is_working() { |
|||
return s_workingthread.threadisworking; |
|||
} |
@ -0,0 +1,14 @@ |
|||
#pragma once |
|||
#include <stdint.h> |
|||
#include <stdio.h> |
|||
#include <stdbool.h> |
|||
/** |
|||
* @brief |
|||
* 声音采集服务,主要用于接收来自上位机的指令,并对其做出相应的处理 |
|||
* |
|||
*/ |
|||
|
|||
void encoder_acquistion_service_init(); |
|||
void encoder_acquistion_service_start(); |
|||
void encoder_acquistion_service_stop(); |
|||
bool encoder_acquistion_service_is_working(); |
@ -0,0 +1,6 @@ |
|||
#pragma once |
|||
#include "iflytop_microcontroller/sdk/stm32/stm32sdk.h" |
|||
#define Z_ASSERT(condition) \ |
|||
if (!(condition)) { \ |
|||
ZLOGI(TAG, "do " #condition " fail") \ |
|||
} |
@ -1,4 +1,4 @@ |
|||
#include "port.h" |
|||
#include "zport.h" |
|||
|
|||
#include <stdint.h> |
|||
#include <stdio.h> |
@ -0,0 +1,96 @@ |
|||
#include "zthread.h" |
|||
#include "stdbool.h" |
|||
#include "iflytop_microcontroller/sdk/stm32/stm32sdk.h" |
|||
// #include "Middlewares\Third_Party\FreeRTOS\Source\portable\RVDS\ARM_CM4F\port.h" |
|||
#include "zassert.h" |
|||
|
|||
#define TAG "zthread" |
|||
|
|||
extern __asm uint32_t vPortGetIPSR(void); |
|||
|
|||
static __inline bool IS_IRQ(void) |
|||
{ |
|||
if (vPortGetIPSR()) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
static void tasksleep(uint32_t ms) { ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(ms)); } |
|||
|
|||
static void taskwake(zthread_t *thread) { |
|||
BaseType_t state; |
|||
if (IS_IRQ()) |
|||
vTaskNotifyGiveFromISR(thread->handler, &state); |
|||
else |
|||
xTaskNotifyGive(thread->handler); |
|||
} |
|||
|
|||
static void prvtaskfunction(void *_taskhandler) { |
|||
zthread_t *thread = (zthread_t *)_taskhandler; |
|||
Z_ASSERT(_taskhandler); |
|||
|
|||
while (true) { |
|||
thread->threadisworking = false; |
|||
|
|||
// 等待taskworking |
|||
xEventGroupWaitBits(thread->zthreadstartworkevent, 0x01, pdTRUE, pdTRUE, portMAX_DELAY); |
|||
// ZLOGI(TAG, "thread %s startwork", thread->name); |
|||
ZLOGI(TAG, "thread %s startwork", thread->name); |
|||
thread->threadisworking = true; |
|||
thread->taskfunction(NULL); |
|||
ZLOGI(TAG, "thread %s end work", thread->name); |
|||
} |
|||
}; |
|||
|
|||
void zthread_init(zthread_t *thread, const char *name, TaskFunction_t taskfunction) { |
|||
Z_ASSERT(thread); |
|||
Z_ASSERT(taskfunction); |
|||
Z_ASSERT(name); |
|||
|
|||
thread->lock = xSemaphoreCreateMutex(); |
|||
Z_ASSERT(thread->lock); |
|||
|
|||
if (thread->stacksize == 0) { |
|||
thread->stacksize = ZTHREAD_DEFAULT_STACK_SIZE; |
|||
} |
|||
if (thread->uxPriority == 0) { |
|||
thread->uxPriority = ZTHREAD_DEFAULT_PRIORITY; |
|||
} |
|||
thread->taskfunction = taskfunction; |
|||
thread->zthreadstartworkevent = xEventGroupCreate(); |
|||
thread->name = name; |
|||
|
|||
xTaskCreate(prvtaskfunction, name, thread->stacksize, (void *)thread, thread->uxPriority, &thread->handler); |
|||
} |
|||
void zthread_start(zthread_t *thread) { |
|||
/** |
|||
* @brief |
|||
*/ |
|||
|
|||
Z_ASSERT(thread); |
|||
xSemaphoreTake(thread->lock, portMAX_DELAY); |
|||
xEventGroupSetBits(thread->zthreadstartworkevent, 0x01); |
|||
while (thread->threadisworking != true) { |
|||
vTaskDelay(10); |
|||
} |
|||
xSemaphoreGive(thread->lock); |
|||
} |
|||
|
|||
bool zthread_is_expect_stop(zthread_t *thread) { return thread->_expect_stop; } |
|||
|
|||
void zthread_stop(zthread_t *thread) { |
|||
Z_ASSERT(thread); |
|||
xSemaphoreTake(thread->lock, portMAX_DELAY); |
|||
|
|||
thread->_expect_stop = true; |
|||
while (thread->threadisworking == true) { |
|||
taskwake(thread); |
|||
vTaskDelay(10); |
|||
} |
|||
thread->_expect_stop = false; |
|||
xSemaphoreGive(thread->lock); |
|||
} |
|||
|
|||
void zthread_sleep(uint32_t ms) { tasksleep(ms); } |
|||
void zthread_weak(zthread_t *thread) { taskwake(thread); } |
@ -0,0 +1,46 @@ |
|||
#pragma once |
|||
#include "FreeRTOS.h" |
|||
#include "event_groups.h" |
|||
#include "semphr.h" |
|||
#include "task.h" |
|||
#include "stdbool.h" |
|||
|
|||
#if 0 |
|||
static inline IRAM_ATTR BaseType_t |
|||
xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, |
|||
const uint32_t usStackDepth, void *const pvParameters, |
|||
UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask) { |
|||
return xTaskCreatePinnedToCore(pvTaskCode, pcName, usStackDepth, pvParameters, |
|||
uxPriority, pvCreatedTask, tskNO_AFFINITY); |
|||
} |
|||
#endif |
|||
|
|||
#define ZTHREAD_DEFAULT_STACK_SIZE 4096 |
|||
#define ZTHREAD_DEFAULT_PRIORITY 5 |
|||
|
|||
typedef struct { |
|||
|
|||
const char *name; |
|||
|
|||
size_t stacksize; |
|||
int uxPriority; |
|||
|
|||
TaskFunction_t taskfunction; |
|||
|
|||
TaskHandle_t handler; |
|||
EventGroupHandle_t zthreadstartworkevent; |
|||
|
|||
bool threadisworking; |
|||
bool _expect_stop; |
|||
SemaphoreHandle_t lock; |
|||
|
|||
} zthread_t; |
|||
|
|||
void zthread_init(zthread_t *thread, const char *name, |
|||
TaskFunction_t taskfunction); |
|||
void zthread_start(zthread_t *thread); |
|||
void zthread_stop(zthread_t *thread); |
|||
bool zthread_is_expect_stop(zthread_t *thread); |
|||
|
|||
void zthread_sleep(uint32_t ms); |
|||
void zthread_weak(zthread_t *thread); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue