はじめに
サンプルコードはあるのですが動かしている記事があまり見つからず。備忘録的に書き出します。
デバイス
M5stack core2
OV2640搭載 Unit Cam Wi-Fi Camera
groveケーブルもあると便利
接続
今回はPORT Aに接続します。
コード
環境はplatformIoです
main.cpp
uart_frame.cpp
uart_frame.h
main.cpp
#include <M5Core2.h>
#include "uart_frame.h"
typedef struct _JpegFrame_t
{
uint8_t *buf;
uint32_t size;
} JpegFrame_t;
static QueueHandle_t jpeg_fream_queue = NULL;
// UART
const int UART_RX_PIN = 33;
const int UART_TX_PIN = 32;
const int UART_BAUD_RATE = 1500000;
void frame_recv_callback(int cmd, const uint8_t *buf, int len)
{
JpegFrame_t frame;
frame.buf = (uint8_t *)malloc(sizeof(uint8_t) * len);
memcpy(frame.buf, buf, len);
frame.size = len;
if (xQueueSend(jpeg_fream_queue, &frame, 0) != pdTRUE)
{
free(frame.buf);
}
}
void setup()
{
M5.begin();
Serial.begin(1500000);
uart_frame_init(UART_RX_PIN, UART_TX_PIN, UART_BAUD_RATE);
}
void loop()
{
JpegFrame_t frame;
int time_last = 0;
time_last = millis();
xQueueReceive(jpeg_fream_queue, &frame, portMAX_DELAY);
M5.Lcd.drawJpg(frame.buf, frame.size, 0, 0);
Serial.printf("--%ld--size--%d--\r\n", millis() - time_last, frame.size);
free(frame.buf);
}
core2のportAは33,32ピンに該当する。
// UART
const int UART_RX_PIN = 33;
const int UART_TX_PIN = 32;
const int UART_BAUD_RATE = 1500000;
動作確認
サンプルコードそのままだとヌルヌル感はない。チューニングが必要だろう。
(おまけ)ライブラリ
サンプルコードリポジトリにもありますが、こちらもに転記します。
uart_frame.h
#ifndef _UART_FRAME_H
#define _UART_FRAME_H
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
typedef enum {
IDLE = 0x00,
WAIT_FINISH ,
FINISH,
} frame_state_n;
extern volatile frame_state_n frame_state;
void uart_frame_init(int32_t rx, int32_t tx, int baud);
void uart_frame_send(uint8_t cmd, const uint8_t* frame, uint32_t len, bool wait_finish);
void uart_update_pin(int32_t rx, int32_t tx);
#endif
uart_frame.cpp
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "string.h"
#include "esp_heap_caps.h"
#include "uart_frame.h"
#define UART_NUM UART_NUM_1
#define UART_QUEUE_LENGTH 10
#define TX_BUF_SIZE 0
#define FRAME_MAX_SIZE (16 * 1024)
#define RX_BUF_SIZE 2 * 1024
#define PACK_FIRST_BYTE 0xAA
#define PACK_SECOND_BYTE 0x55
volatile frame_state_n frame_state;
static QueueHandle_t uart_queue = NULL;
static QueueHandle_t uart_buffer_queue = NULL;
static void uart_frame_task(void *arg);
static void uart_frame_send_task(void *arg);
typedef struct _UartFrame_t {
bool free_buffer;
uint8_t* buffer;
uint32_t len;
} UartFrame_t;
int32_t baud_rate = 1500000;
uint16_t uart_tx_pin = 26;
uint16_t uart_rx_pin = 36;
void __attribute__((weak)) frame_post_callback(uint8_t cmd) {
}
void __attribute__((weak)) frame_recv_callback(int cmd, const uint8_t*buf, int len) {
}
static void uart_base_init() {
uart_driver_delete(UART_NUM);
const uart_config_t uart_config = {
.baud_rate = baud_rate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM, &uart_config);
uart_set_pin(UART_NUM, uart_tx_pin, uart_rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(UART_NUM, RX_BUF_SIZE, TX_BUF_SIZE, UART_QUEUE_LENGTH, &uart_queue, ESP_INTR_FLAG_LOWMED);
uart_set_rx_timeout(UART_NUM, 50);
}
void uart_frame_init(int32_t rx, int32_t tx, int baud) {
baud_rate = baud;
uart_rx_pin = rx;
uart_tx_pin = tx;
uart_buffer_queue = xQueueCreate(1, sizeof(UartFrame_t));
uart_base_init();
xTaskCreatePinnedToCore(uart_frame_task, "uart_queue_task", 4 * 1024, NULL, 3, NULL, 0);
xTaskCreatePinnedToCore(uart_frame_send_task, "uart_frame_send_task", 2 * 1024, NULL, 1, NULL, 0);
}
void uart_update_pin(int32_t rx, int32_t tx) {
uart_set_pin(UART_NUM, tx, rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
typedef enum {
kWaitStart = 0x00,
kRecvLenght,
kLenghtCheck,
kRecvCMD,
kRecvData,
kCrcCheck,
kSuccess,
} frame_state_t;
static void uart_frame_send_task(void *arg) {
UartFrame_t frame;
for (;;) {
xQueueReceive(uart_buffer_queue, &frame, portMAX_DELAY);
uart_wait_tx_done(UART_NUM, portMAX_DELAY);
uart_write_bytes(UART_NUM, (const char *)frame.buffer, frame.len);
uart_wait_tx_done(UART_NUM, portMAX_DELAY);
frame_post_callback(frame.buffer[7]);
if (frame.free_buffer) {
free(frame.buffer);
}
}
vTaskDelete(NULL);
}
static void uart_frame_task(void *arg) {
uart_event_t xEvent;
// uint32_t buf_pos = 0;
uint8_t *buf = (uint8_t *)heap_caps_calloc(FRAME_MAX_SIZE, sizeof(uint8_t), MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
uint8_t *recv_buf = (uint8_t *)malloc(1024 * sizeof(uint8_t));
uint8_t* ptr = recv_buf;
uint32_t packet_pos = 0;
uint8_t packet_ahead[] = {PACK_FIRST_BYTE, PACK_SECOND_BYTE};
uint32_t frame_length = 0;
uint8_t crc_xor = 0x00;
uint16_t size;
buf[0] = PACK_FIRST_BYTE;
buf[1] = PACK_SECOND_BYTE;
frame_state_t frame_state = kWaitStart;
for(;;) {
if (xQueueReceive(uart_queue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
switch(xEvent.type) {
case UART_DATA: {
uart_read_bytes(UART_NUM, recv_buf, xEvent.size, portMAX_DELAY);
ptr = recv_buf;
size = xEvent.size;
while (size) {
switch (frame_state) {
case kWaitStart:
buf[packet_pos] = *ptr;
ptr += 1;
size -= 1;
if (buf[packet_pos] == packet_ahead[packet_pos]) {
packet_pos += 1;
if (packet_pos == 2) {
frame_length = 0;
frame_state = kRecvLenght;
}
} else {
packet_pos = 0;
}
break;
case kRecvLenght:
buf[packet_pos] = *ptr;
ptr += 1;
size -= 1;
packet_pos += 1;
if (packet_pos == (2 + 4)) {
crc_xor = 0x000;
frame_state = kLenghtCheck;
}
break;
case kLenghtCheck:
buf[packet_pos] = *ptr;
ptr += 1;
size -= 1;
crc_xor = 0x00 ^ buf[2] ^ buf[3] ^ buf[4] ^ buf[5];
if (crc_xor == buf[packet_pos]) {
packet_pos += 1;
frame_length = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | (buf[5] << 0);
if (frame_length > FRAME_MAX_SIZE - 9) {
packet_pos = 0;
frame_state = kWaitStart;
} else {
frame_state = kRecvCMD;
}
} else {
packet_pos = 0;
frame_state = kWaitStart;
}
break;
case kRecvCMD: {
buf[packet_pos] = *ptr;
ptr += 1;
size -= 1;
packet_pos += 1;
frame_state = kRecvData;
break;
}
case kRecvData:
while(size > 0) {
buf[packet_pos] = *ptr;
ptr += 1;
size -= 1;
packet_pos += 1;
if (packet_pos == (frame_length + 6)) {
frame_state = kCrcCheck;
break;
}
}
break;
case kCrcCheck:
buf[packet_pos] = *ptr;
ptr += 1;
size -= 1;
crc_xor = 0x00;
for (uint16_t i = 0; i < packet_pos; i++) {
crc_xor = buf[i] ^ crc_xor;
}
if (crc_xor != buf[packet_pos]) {
packet_pos = 0;
frame_state = kWaitStart;
break;
}
case kSuccess:
packet_pos = 0;
frame_state = kWaitStart;
frame_recv_callback(buf[7], &buf[8], frame_length - 2);
break;
default:
break;
}
}
break;
}
case UART_FIFO_OVF: {
xQueueReset(uart_queue);
break;
}
case UART_BUFFER_FULL: {
uart_flush_input(UART_NUM);
xQueueReset(uart_queue);
break;
}
case UART_BREAK: {
break;
}
case UART_PARITY_ERR: {
break;
}
case UART_FRAME_ERR: {
break;
}
default: {
break;
}
}
}
}
vTaskDelete(NULL);
}
void uart_frame_send(uint8_t cmd, const uint8_t* frame, uint32_t len, bool wait_finish) {
uint32_t out_len = 9 + len;
uint8_t* out_buf = (uint8_t *)malloc(sizeof(uint8_t) * out_len);
out_buf[0] = PACK_FIRST_BYTE;
out_buf[1] = PACK_SECOND_BYTE;
out_buf[2] = (out_len - 7) >> 24;
out_buf[3] = (out_len - 7) >> 16;
out_buf[4] = (out_len - 7) >> 8;
out_buf[5] = (out_len - 7);
out_buf[6] = 0x00 ^ out_buf[2] ^ out_buf[3] ^ out_buf[4] ^ out_buf[5];
out_buf[7] = cmd;
memcpy(&out_buf[8], frame, len);
int xor_resilt = 0x00;
for (uint32_t i = 0; i < out_len - 1; i++) {
xor_resilt = out_buf[i] ^ xor_resilt;
}
out_buf[out_len - 1] = xor_resilt;
if (wait_finish) {
while (uxQueueMessagesWaiting(uart_buffer_queue)) {
vTaskDelay(pdMS_TO_TICKS(10));
}
}
UartFrame_t uart_frame;
uart_frame.buffer = out_buf;
uart_frame.len = out_len;
uart_frame.free_buffer = true;
xQueueSend(uart_buffer_queue, &uart_frame, portMAX_DELAY);
}