Added thread safety to USB TX, servo control thread, primitive ADC thread, python test codes
This commit is contained in:
+88
-32
@@ -17,11 +17,11 @@ LOG_MODULE_REGISTER(usb, LOG_LEVEL_INF);
|
||||
const struct device *const uart_dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart);
|
||||
static struct usbd_context *usb_context;
|
||||
|
||||
// THREAD
|
||||
static struct k_thread usb_thread_data;
|
||||
static k_tid_t usb_thread_id = NULL;
|
||||
#define USB_THREAD_STACK_SIZE 2048
|
||||
K_THREAD_STACK_DEFINE(usb_thread_stack, USB_THREAD_STACK_SIZE);
|
||||
// RX THREAD
|
||||
static struct k_thread usb_rx_thread_data;
|
||||
static k_tid_t usb_rx_thread_id = NULL;
|
||||
#define USB_RX_THREAD_STACK_SIZE 2048
|
||||
K_THREAD_STACK_DEFINE(usb_rx_thread_stack, USB_RX_THREAD_STACK_SIZE);
|
||||
|
||||
// RX BUFFER
|
||||
#define RING_BUF_SIZE 255
|
||||
@@ -29,10 +29,21 @@ static uint8_t ring_buffer[RING_BUF_SIZE];
|
||||
static struct ring_buf ringbuf;
|
||||
struct k_sem rx_semaphore;
|
||||
|
||||
// TX THREAD
|
||||
static struct k_thread usb_tx_thread_data;
|
||||
static k_tid_t usb_tx_thread_id = NULL;
|
||||
#define USB_TX_THREAD_STACK_SIZE 512
|
||||
K_THREAD_STACK_DEFINE(usb_tx_thread_stack, USB_TX_THREAD_STACK_SIZE);
|
||||
|
||||
// TX BUFFER (add ack and nack at the and as static)
|
||||
#define TX_BUFFER_SIZE 10
|
||||
struct command_message_t usb_tx_buffer[TX_BUFFER_SIZE + 2];
|
||||
struct command_message_t *usb_tx_buf_ptr;
|
||||
char usb_tx_ptr_msgq_buffer[(TX_BUFFER_SIZE + 2) * sizeof(struct command_message_t *)];
|
||||
struct k_msgq usb_tx_ptr_msgq;
|
||||
|
||||
// ACK / NACK messages
|
||||
#define RETURN_ACK true
|
||||
struct command_message_t ack_msg;
|
||||
struct command_message_t nack_msg;
|
||||
|
||||
|
||||
static void interrupt_handler(const struct device *dev, void *user_data) {
|
||||
@@ -73,7 +84,7 @@ static void interrupt_handler(const struct device *dev, void *user_data) {
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_thread(void *p1, void *p2, void *p3) {
|
||||
static void usb_rx_thread(void *p1, void *p2, void *p3) {
|
||||
ARG_UNUSED(p1);
|
||||
ARG_UNUSED(p2);
|
||||
ARG_UNUSED(p3);
|
||||
@@ -109,7 +120,7 @@ static void usb_thread(void *p1, void *p2, void *p3) {
|
||||
if (calculated_crc != msg.crc) {
|
||||
if (RETURN_ACK) {
|
||||
// Send NACK
|
||||
usb_send_command(&nack_msg);
|
||||
usb_send_command(&usb_tx_buffer[TX_BUFFER_SIZE + 1]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -118,13 +129,13 @@ static void usb_thread(void *p1, void *p2, void *p3) {
|
||||
if (ret == 0) {
|
||||
if (RETURN_ACK) {
|
||||
// Send ACK
|
||||
usb_send_command(&ack_msg);
|
||||
usb_send_command(&usb_tx_buffer[TX_BUFFER_SIZE]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (RETURN_ACK) {
|
||||
// Send NACK
|
||||
usb_send_command(&nack_msg);
|
||||
usb_send_command(&usb_tx_buffer[TX_BUFFER_SIZE + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,12 +173,36 @@ static void usb_msg_cb(struct usbd_context *const ctx, const struct usbd_msg *ms
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_tx_thread(void *p1, void *p2, void *p3) {
|
||||
struct command_message_t *data;
|
||||
|
||||
while (1) {
|
||||
k_msgq_get(&usb_tx_ptr_msgq, &data, K_FOREVER);
|
||||
|
||||
if (!device_is_ready(uart_dev)) {
|
||||
// FIXME: Don't drop packages
|
||||
continue;
|
||||
}
|
||||
|
||||
// Message size: prefix + length + id + command + crc + data
|
||||
size_t msg_size = COMMAND_HEADER_SIZE + data->length;
|
||||
uint8_t *msg_bytes = (uint8_t *)data;
|
||||
|
||||
/* uart_poll_out blocks until sent, ensuring data integrity */
|
||||
for (size_t i = 0; i < msg_size; i++) {
|
||||
uart_poll_out(uart_dev, msg_bytes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usb_init() {
|
||||
ring_buf_init(&ringbuf, sizeof(ring_buffer), ring_buffer);
|
||||
k_sem_init(&rx_semaphore, 0, 1);
|
||||
usb_tx_buf_ptr = usb_tx_buffer;
|
||||
k_msgq_init(&usb_tx_ptr_msgq, usb_tx_ptr_msgq_buffer, sizeof(struct command_message_t *), TX_BUFFER_SIZE);
|
||||
|
||||
command_create_ack(&ack_msg);
|
||||
command_create_nack(&nack_msg);
|
||||
command_create_ack(&usb_tx_buffer[TX_BUFFER_SIZE]);
|
||||
command_create_nack(&usb_tx_buffer[TX_BUFFER_SIZE + 1]);
|
||||
|
||||
int ret;
|
||||
|
||||
@@ -194,38 +229,59 @@ int usb_init() {
|
||||
uart_irq_callback_set(uart_dev, interrupt_handler);
|
||||
uart_irq_rx_enable(uart_dev);
|
||||
|
||||
usb_thread_id = k_thread_create(
|
||||
&usb_thread_data,
|
||||
usb_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(usb_thread_stack),
|
||||
usb_thread,
|
||||
// RX THREAD
|
||||
usb_rx_thread_id = k_thread_create(
|
||||
&usb_rx_thread_data,
|
||||
usb_rx_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(usb_rx_thread_stack),
|
||||
usb_rx_thread,
|
||||
NULL, NULL, NULL,
|
||||
5,
|
||||
0,
|
||||
K_NO_WAIT
|
||||
);
|
||||
|
||||
if (usb_thread_id == NULL) {
|
||||
LOG_ERR("Failed to create USB thread");
|
||||
if (usb_rx_thread_id == NULL) {
|
||||
LOG_ERR("Failed to create USB RX thread");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// TX THREAD
|
||||
usb_tx_thread_id = k_thread_create(
|
||||
&usb_tx_thread_data,
|
||||
usb_tx_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(usb_tx_thread_stack),
|
||||
usb_tx_thread,
|
||||
NULL, NULL, NULL,
|
||||
5,
|
||||
0,
|
||||
K_NO_WAIT
|
||||
);
|
||||
|
||||
if (usb_tx_thread_id == NULL) {
|
||||
LOG_ERR("Failed to create USB TX thread");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct command_message_t* usb_get_next_tx_buf() {
|
||||
struct command_message_t *buf = usb_tx_buf_ptr;
|
||||
|
||||
// Increment the buffer pointer
|
||||
usb_tx_buf_ptr++;
|
||||
|
||||
if (usb_tx_buf_ptr > &usb_tx_buffer[TX_BUFFER_SIZE-1]) {
|
||||
usb_tx_buf_ptr = usb_tx_buffer;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int usb_send_command(struct command_message_t *msg) {
|
||||
if (!device_is_ready(uart_dev)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Message size: prefix + length + id + command + crc + data
|
||||
size_t msg_size = 5 + msg->length;
|
||||
uint8_t *msg_bytes = (uint8_t *)msg;
|
||||
|
||||
/* uart_poll_out blocks until sent, ensuring data integrity */
|
||||
for (size_t i = 0; i < msg_size; i++) {
|
||||
uart_poll_out(uart_dev, msg_bytes[i]);
|
||||
}
|
||||
|
||||
k_msgq_put(&usb_tx_ptr_msgq, &msg, K_NO_WAIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user