mirror of
https://gitlab.com/hyperglitch/jellyfish.git
synced 2025-12-26 23:16:46 +00:00
205 lines
5.8 KiB
C
205 lines
5.8 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2025 Igor Brkic <igor@hyperglitch.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "usbd_bulk.h"
|
|
#include "usbd_desc.h"
|
|
|
|
#include "jf_usb.h"
|
|
|
|
#include "cmsis_os2.h"
|
|
#include "FreeRTOS.h"
|
|
#include "stream_buffer.h"
|
|
#include "projdefs.h"
|
|
#include "task.h"
|
|
|
|
USBD_HandleTypeDef USBD_Device;
|
|
uint8_t cdc_ep[3] = {CDC_IN_EP, CDC_OUT_EP, CDC_CMD_EP};
|
|
uint8_t bulk_ep[2] = {BULK_EPIN_ADDR, BULK_EPOUT_ADDR};
|
|
|
|
volatile bool tx_in_progress = false;
|
|
volatile bool usb_initialized = false;
|
|
volatile bool usb_tx_ready = false;
|
|
|
|
#define USB_STREAM_BUFFER_SIZE (10*1024)
|
|
#define USB_STREAM_TRIGGER_LEVEL (512)
|
|
|
|
static uint8_t usb_stream_buffer_storage[USB_STREAM_BUFFER_SIZE+1];
|
|
static StaticStreamBuffer_t usb_stream_buffer_struct;
|
|
static StreamBufferHandle_t usb_stream_buffer_handle = NULL;
|
|
|
|
|
|
//static TaskHandle_t usb_stream_task_handle = NULL;
|
|
static osThreadId_t task_handle;
|
|
static const osThreadAttr_t task_attributes = {
|
|
.name = "USB_TX",
|
|
.stack_size = 512,
|
|
};
|
|
|
|
|
|
extern PCD_HandleTypeDef hpcd;
|
|
|
|
void OTG_HS_IRQHandler(void)
|
|
{
|
|
HAL_PCD_IRQHandler(&hpcd);
|
|
}
|
|
|
|
|
|
#define USB_DATA_BUFFER_SIZE 512
|
|
__ALIGN_BEGIN uint8_t usb_tx_buffer[2][USB_DATA_BUFFER_SIZE] __ALIGN_END;
|
|
volatile int tx_buffer_idx = 0;
|
|
volatile int data_buffer_idx = 1;
|
|
volatile int data_idx = 0;
|
|
|
|
|
|
void usb_clear_send(void) {
|
|
tx_in_progress = false;
|
|
/*
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
vTaskNotifyGiveFromISR(usb_stream_task_handle, &xHigherPriorityTaskWoken);
|
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
*/
|
|
}
|
|
|
|
void usb_send_buffer(void) {
|
|
tx_in_progress = true;
|
|
USBD_LL_Transmit(&USBD_Device, BULK_EPIN_ADDR, usb_tx_buffer[tx_buffer_idx], USB_DATA_BUFFER_SIZE);
|
|
}
|
|
|
|
static void usb_tx_task(void *args) {
|
|
(void)args;
|
|
printf("USB_TX task started\r\n");
|
|
uint8_t buf[512];
|
|
|
|
// wait for the USB initialization to complete
|
|
while (!USBD_BULK_Is_Initialized() || !usb_initialized) {
|
|
osDelay(100);
|
|
}
|
|
printf("USB_TX endpoint initialized\r\n");
|
|
|
|
uint32_t last_tm = 0;
|
|
uint32_t duration = 0;
|
|
for (;;) {
|
|
/*
|
|
if (usb_initialized && !tx_in_progress) {
|
|
printf("usb tx\r\n");
|
|
usb_send_buffer();
|
|
}
|
|
osDelay(50);
|
|
continue;
|
|
*/
|
|
|
|
// block until enough data is in the buffer
|
|
size_t len = xStreamBufferReceive(usb_stream_buffer_handle, buf, sizeof(buf), portMAX_DELAY);
|
|
duration = HAL_GetTick() - last_tm;
|
|
last_tm = HAL_GetTick();
|
|
if (len>0) {
|
|
jf_usb_send_data_to_host(buf, len);
|
|
//USBD_LL_Transmit(&USBD_Device, BULK_EPIN_ADDR, buf, len);
|
|
//tx_in_progress = true;
|
|
//ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void usb_error(const char *cause) {
|
|
printf("USB initialization error: %s\r\n", cause);
|
|
// ReSharper disable once CppDFAEndlessLoop
|
|
while (true);
|
|
}
|
|
|
|
|
|
void jf_usb_init(void) {
|
|
if (USBD_Init(&USBD_Device, &HS_Desc, 1) != USBD_OK) {
|
|
usb_error("USBD_Init");
|
|
}
|
|
|
|
// Register the CDC interface callbacks
|
|
if (USBD_CDC_RegisterInterface(&USBD_Device, &USBD_CDC_fops) != USBD_OK) {
|
|
usb_error("USBD_CDC_RegisterInterface");
|
|
}
|
|
// Register the CDC class in the USB composite device with its endpoints
|
|
if (USBD_RegisterClassComposite(&USBD_Device, &USBD_CDC, CLASS_TYPE_CDC, cdc_ep) != USBD_OK) {
|
|
usb_error("USBD_RegisterClassComposite - CDC");
|
|
}
|
|
|
|
// Register the Bulk interface callbacks
|
|
if (USBD_BULK_RegisterInterface(&USBD_Device, &USBD_BULK) != USBD_OK) {
|
|
usb_error("USBD_BULK_RegisterInterface");
|
|
}
|
|
// Register the Bulk class in the USB composite device with its endpoints
|
|
if (USBD_RegisterClassComposite(&USBD_Device, &USBD_BULK, 3, bulk_ep) != USBD_OK) {
|
|
usb_error("USBD_RegisterClassComposite - BULK");
|
|
}
|
|
|
|
// Start the USB Device Core so it begins communicating with the host
|
|
if (USBD_Start(&USBD_Device) != USBD_OK) {
|
|
usb_error("USBD_Start");
|
|
}
|
|
|
|
// register the bulk transfer complete callback
|
|
USBD_BULK_Register_TxCplt_Callback(usb_clear_send);
|
|
|
|
usb_stream_buffer_handle = xStreamBufferCreateStatic(USB_STREAM_BUFFER_SIZE, USB_STREAM_TRIGGER_LEVEL, usb_stream_buffer_storage, &usb_stream_buffer_struct);
|
|
//usb_stream_buffer_handle = xStreamBufferCreate(USB_STREAM_BUFFER_SIZE, USB_STREAM_TRIGGER_LEVEL);
|
|
if (usb_stream_buffer_handle==NULL) {
|
|
usb_error("xStreamBufferCreateStatic");
|
|
}
|
|
|
|
//xTaskCreate(usb_tx_task, "USB_TX", 512, NULL, tsk, &usb_stream_task_handle);
|
|
task_handle = osThreadNew(usb_tx_task, NULL, &task_attributes);
|
|
|
|
usb_initialized = true;
|
|
printf("USB initialized\r\n");
|
|
}
|
|
|
|
|
|
void jf_usb_set_cdc_rx_callback(usb_cdc_rx_callback_t callback) {
|
|
USBD_CDC_Register_Rx_Callback(callback);
|
|
}
|
|
|
|
|
|
void jf_usb_cdc_tx(uint8_t* data, uint32_t length) {
|
|
USBD_CDC_SetTxBuffer(&USBD_Device, data, length, 0);
|
|
USBD_CDC_TransmitPacket(&USBD_Device, 0);
|
|
}
|
|
|
|
|
|
void jf_usb_send_data_to_host(const uint8_t* data, uint32_t length) {
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
usb_tx_buffer[data_buffer_idx][data_idx] = data[i];
|
|
data_idx++;
|
|
if (data_idx == USB_DATA_BUFFER_SIZE) {
|
|
data_idx = 0;
|
|
// switch buffers
|
|
data_buffer_idx ^= 0x01;
|
|
tx_buffer_idx ^= 0x01;
|
|
|
|
if (!tx_in_progress && USBD_BULK_Is_Initialized()) {
|
|
// send data
|
|
usb_send_buffer();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void jf_usb_add_to_buffer_from_isr(uint8_t *data, size_t len) {
|
|
//jf_usb_send_data_to_host(data, len);
|
|
//return;
|
|
if (!usb_initialized) return;
|
|
if (len==0) return;
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
xStreamBufferSendFromISR(usb_stream_buffer_handle, data, len, &xHigherPriorityTaskWoken);
|
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
}
|
|
|
|
|