added python tool inital version

This commit is contained in:
2026-02-25 10:09:17 +01:00
parent 288b1e45ef
commit 80c0e825a7
26 changed files with 369 additions and 0 deletions

156
firmware/src/usb.c Normal file
View 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;
}