added python tool inital version
This commit is contained in:
156
firmware/src/usb.c
Normal file
156
firmware/src/usb.c
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/usb/usb_device.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
|
||||
#include <io.h>
|
||||
|
||||
LOG_MODULE_REGISTER(usb, LOG_LEVEL_DBG);
|
||||
|
||||
K_SEM_DEFINE(usb_rx_sem, 0, 1);
|
||||
K_SEM_DEFINE(usb_tx_sem, 0, 1);
|
||||
|
||||
#define UART_NODE DT_ALIAS(usb_uart)
|
||||
const struct device *cdc_dev = DEVICE_DT_GET(UART_NODE);
|
||||
|
||||
static void cdc_acm_irq_cb(const struct device *dev, void *user_data)
|
||||
{
|
||||
ARG_UNUSED(user_data);
|
||||
|
||||
if (!uart_irq_update(dev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_irq_rx_ready(dev)) {
|
||||
uart_irq_rx_disable(dev);
|
||||
k_sem_give(&usb_rx_sem);
|
||||
LOG_DBG("RX interrupt: data available");
|
||||
}
|
||||
|
||||
|
||||
if (uart_irq_tx_ready(dev)) {
|
||||
uart_irq_tx_disable(dev);
|
||||
k_sem_give(&usb_tx_sem);
|
||||
LOG_DBG("TX interrupt: ready for more data");
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_wait_for_data(k_timeout_t timeout)
|
||||
{
|
||||
/* Wartet auf das Signal aus der ISR */
|
||||
return (k_sem_take(&usb_rx_sem, timeout) == 0);
|
||||
}
|
||||
|
||||
int usb_read_char(uint8_t *c)
|
||||
{
|
||||
if (!device_is_ready(cdc_dev)) return 0;
|
||||
return uart_fifo_read(cdc_dev, c, 1);
|
||||
}
|
||||
|
||||
int usb_read_buffer(uint8_t *buf, size_t max_len)
|
||||
{
|
||||
if (!device_is_ready(cdc_dev)) return 0;
|
||||
return uart_fifo_read(cdc_dev, buf, max_len);
|
||||
}
|
||||
|
||||
void usb_resume_rx(void)
|
||||
{
|
||||
if (device_is_ready(cdc_dev)) {
|
||||
uart_irq_rx_enable(cdc_dev);
|
||||
LOG_DBG("RX interrupt re-enabled");
|
||||
}
|
||||
}
|
||||
|
||||
void usb_write_char(uint8_t c)
|
||||
{
|
||||
if (!device_is_ready(cdc_dev)) {
|
||||
return;
|
||||
}
|
||||
uart_poll_out(cdc_dev, c);
|
||||
}
|
||||
|
||||
void usb_write_buffer(const uint8_t *buf, size_t len)
|
||||
{
|
||||
if (!device_is_ready(cdc_dev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t written;
|
||||
while (len > 0) {
|
||||
written = uart_fifo_fill(cdc_dev, buf, len);
|
||||
|
||||
len -= written;
|
||||
buf += written;
|
||||
|
||||
if (len > 0) {
|
||||
/* Der FIFO ist voll, aber wir haben noch Daten.
|
||||
* 1. TX-Interrupt aktivieren (meldet sich, wenn wieder Platz ist)
|
||||
* 2. Thread schlafen legen, bis die ISR die Semaphore gibt */
|
||||
uart_irq_tx_enable(cdc_dev);
|
||||
k_sem_take(&usb_tx_sem, K_FOREVER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param)
|
||||
{
|
||||
switch (cb_status) {
|
||||
case USB_DC_CONNECTED:
|
||||
/* VBUS wurde vom Zephyr-Stack erkannt */
|
||||
LOG_DBG("VBUS detected, USB device connected");
|
||||
break;
|
||||
case USB_DC_CONFIGURED:
|
||||
LOG_DBG("USB device configured by host");
|
||||
io_usb_status(true);
|
||||
if (device_is_ready(cdc_dev)) {
|
||||
(void)uart_line_ctrl_set(cdc_dev, UART_LINE_CTRL_DCD, 1);
|
||||
(void)uart_line_ctrl_set(cdc_dev, UART_LINE_CTRL_DSR, 1);
|
||||
|
||||
/* Interrupt-Handler binden und initial aktivieren */
|
||||
uart_irq_callback_set(cdc_dev, cdc_acm_irq_cb);
|
||||
uart_irq_rx_enable(cdc_dev);
|
||||
}
|
||||
break;
|
||||
case USB_DC_DISCONNECTED:
|
||||
/* Kabel wurde gezogen */
|
||||
LOG_DBG("VBUS removed, USB device disconnected");
|
||||
if (device_is_ready(cdc_dev)) {
|
||||
uart_irq_rx_disable(cdc_dev);
|
||||
}
|
||||
io_usb_status(false);
|
||||
break;
|
||||
case USB_DC_RESET:
|
||||
LOG_DBG("USB bus reset");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int usb_cdc_acm_init(void)
|
||||
{
|
||||
LOG_DBG("Initializing USB Stack...");
|
||||
|
||||
/* Zephyr-Treiber registrieren. Verbraucht keinen Strom ohne VBUS. */
|
||||
int ret = usb_enable(usb_status_cb);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("Failed to enable USB (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(cdc_acm_uart0), okay)
|
||||
const struct device *cdc_dev = DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0));
|
||||
|
||||
if (!device_is_ready(cdc_dev)) {
|
||||
LOG_ERR("CDC ACM device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#else
|
||||
LOG_ERR("CDC ACM UART device not found in devicetree");
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
LOG_DBG("USB Stack enabled and waiting for VBUS in hardware");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user