Skip to content

Commit

Permalink
USB Drivers (#1404)
Browse files Browse the repository at this point in the history
### Changelist 
<!-- Give a list of the changes covered in this PR. This will help both
you and the reviewer keep this PR within scope. -->
added a hw_usb layer, which contains CDC class USB calls for
transmitting and receiving function calls.
initialized a queue in the cdc_recieve function to place the information
received under the hood into the queue one byte at a time
### Testing Done
<!-- Outline the testing that was done to demonstrate the changes are
solid. This could be unit tests, integration tests, testing on the car,
etc. Include relevant code snippets, screenshots, etc as needed. -->
tested the receive by sending a message through python client
tested the transmit function by sending a message and receiving it on
the python end
tested hot-plugging the USB device and seeing if the status is changing 

### Resolved Tickets
<!-- Link any tickets that this PR resolves. -->

---------

Co-authored-by: Liam Ilan <[email protected]>
  • Loading branch information
setaremalekiii and liam-ilan authored Jan 11, 2025
1 parent 6694f9b commit 04f8da5
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 23 deletions.
6 changes: 4 additions & 2 deletions firmware/dev/f4dev/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ set(LINKER_SCRIPT "${LINKER_DIR}/stm32f412rgtx/stm32f412rgtx_app_only.ld")
file(GLOB_RECURSE EMBEDDED_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c")
list(APPEND EMBEDDED_SRCS
"${SHARED_HW_INCLUDE_DIR}/hw_sd.c"
"${SHARED_HW_INCLUDE_DIR}/hw_uart.c")
"${SHARED_HW_INCLUDE_DIR}/hw_uart.c"
"${SHARED_HW_INCLUDE_DIR}/hw_usb.c"
)
list(REMOVE_ITEM EMBEDDED_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/cubemx/Src/sysmem.c")
set(EMBEDDED_INCLUDE_DIRS "${SHARED_IO_INCLUDE_DIR}" "${SHARED_HW_INCLUDE_DIR}")
set(EMBEDDED_INCLUDE_DIRS "${SHARED_IO_INCLUDE_DIR}" "${SHARED_HW_INCLUDE_DIR}" "${SHARED_APP_INCLUDE_DIR}")

IF ("${TARGET}" STREQUAL "binary")
generate_stm32cube_code(
Expand Down
7 changes: 3 additions & 4 deletions firmware/dev/f4dev/src/cubemx/Src/usbd_cdc_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include "usbd_cdc_if.h"

/* USER CODE BEGIN INCLUDE */

#include "hw_usb.h"
/* USER CODE END INCLUDE */

/* Private typedef -----------------------------------------------------------*/
Expand Down Expand Up @@ -268,9 +268,8 @@ static int8_t CDC_Receive_FS(uint8_t *Buf, uint32_t *Len)
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);

// Test: Send data back
uint16_t len = (uint16_t)*Len;
CDC_Transmit_FS(Buf, len);
// hook to hw_usb
hw_usb_pushRxMsgToQueue(Buf, *Len);

return (USBD_OK);
/* USER CODE END 6 */
Expand Down
1 change: 0 additions & 1 deletion firmware/quadruna/VC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ list(APPEND IO_SRCS
"${SHARED_IO_INCLUDE_DIR}/io_chimera.c"
"${SHARED_IO_INCLUDE_DIR}/io_led.c"
"${SHARED_IO_INCLUDE_DIR}/io_time.c"
"${SHARED_IO_INCLUDE_DIR}/io_log.c"
)
set(IO_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/io" "${SHARED_IO_INCLUDE_DIR}" "${SHARED_IO_INCLUDE_QUADRUNA_DIR}")

Expand Down
95 changes: 95 additions & 0 deletions firmware/shared/src/hw/hw_usb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include "hw_usb.h"
#include "usbd_cdc_if.h"
#include "cmsis_os.h"
#include "io_log.h"

// setup rx queue
static StaticQueue_t rx_queue_control_block;
static uint8_t rx_queue_buf[RX_QUEUE_SIZE];
static osMessageQueueId_t rx_queue_id = NULL;
static USBD_HandleTypeDef hUsbDeviceFS;

static const osMessageQueueAttr_t rx_queue_attr = { .name = "USB RX Queue",
.attr_bits = 0,
.cb_mem = &rx_queue_control_block,
.cb_size = sizeof(StaticQueue_t),
.mq_mem = rx_queue_buf,
.mq_size = sizeof(rx_queue_buf) };

void hw_usb_init()
{
if (rx_queue_id == NULL)
{
rx_queue_id = osMessageQueueNew(RX_QUEUE_SIZE, sizeof(uint8_t), &rx_queue_attr);
}
}

bool hw_usb_checkConnection()
{
return hUsbDeviceFS.dev_state != USBD_STATE_SUSPENDED;
}

void hw_usb_transmit(uint8_t *msg, uint16_t len)
{
CDC_Transmit_FS(msg, len);
}

uint8_t hw_usb_recieve()
{
// receive pops off the byte queue and returns
uint8_t res = 0;
osStatus_t status = osMessageQueueGet(rx_queue_id, &res, NULL, 100);
if (status == osOK)
return res;
return 0;
}

void hw_usb_pushRxMsgToQueue(uint8_t *packet, uint32_t len)
{
uint32_t space = osMessageQueueGetSpace(rx_queue_id);
if (len < space)
{
LOG_WARN("usb message queue overflow");
}

for (uint32_t i = 0; i < len; i += 1)
{
// write one byte at a time
osStatus_t status = osMessageQueuePut(rx_queue_id, &packet[i], 0, 0);
}
}

void hw_usb_transmit_example()
{
// init usb peripheral
hw_usb_init();
osDelay(1000);

int msg_count = 0;
for (;;)
{
// send hello (without null terminator)
char msg[] = "hello";
uint8_t *packet = (uint8_t *)msg;
hw_usb_transmit(packet, 5);

msg_count += 1;
LOG_INFO("transmitted \"hello\" %d times", msg_count);

osDelay(1000);
}
}

void hw_usb_recieve_example()
{
// init usb peripheral
hw_usb_init();

// dump the queue.
for (int i = 0; true; i += 1)
{
uint8_t result = hw_usb_recieve();
LOG_INFO("char %d: %c", i, (char)result);
osDelay(1000);
}
}
28 changes: 28 additions & 0 deletions firmware/shared/src/hw/hw_usb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <stdint.h>
#include <stdbool.h>

#define RX_QUEUE_SIZE 2048

// initialize the usb peripheral
void hw_usb_init();

// checks if the usb port is connected
bool hw_usb_checkConnection();

// transmits usb message of arbritrary length
void hw_usb_transmit(uint8_t *msg, uint16_t len);

// receive a single byte over usb
uint8_t hw_usb_recieve();

// pushes a message onto the internal usb queue,
// for use in CDC_Receive_FS/CDC_Receive_HS
void hw_usb_pushRxMsgToQueue(uint8_t *packet, uint32_t len);

// runs an example loop where the message "hello" is tx-ed repeatedly
void hw_usb_transmit_example();

// runs an example loop that logs all received bytes as chars
void hw_usb_recieve_example();
16 changes: 0 additions & 16 deletions firmware/shared/src/io/io_log.c

This file was deleted.

42 changes: 42 additions & 0 deletions scripts/usb_experiments/mirror_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import sys
import usb.core
import usb.util
import time
import importlib

devboard = usb.core.find(idVendor=0x0483, idProduct=0x5740)
interface = devboard[0][(1,0)]

endpointW = interface[0]
endpointR = interface[1]

while True:
if devboard.is_kernel_driver_active(interface.bInterfaceNumber):
try:

devboard.detach_kernel_driver(interface.bInterfaceNumber)
usb.util.claim_interface(devboard, interface.bInterfaceNumber)
except usb.core.USBError as e:
sys.exit("Could not detatch kernel driver from interface({0}): {1}".format(i, str(e)))

print("input your data, if you want to end the program input: exit ")
dataIn = input()
if dataIn == "exit":
break
bytesWritten = devboard.write(endpointW.bEndpointAddress, dataIn)
print(f"Endpoint Address (Read): {endpointR.bEndpointAddress}")
print(f"Endpoint Attributes: {endpointR.bmAttributes}")
print(f"Endpoint Address (Read): {endpointW.bEndpointAddress}")
print(f"Endpoint Attributes: {endpointW.bmAttributes}")

print(f"Wrote {bytesWritten} bytes")
time.sleep(1)
buf = devboard.read(endpointR.bEndpointAddress, len(dataIn))

res = bytes(buf).decode()
print(res)

usb.util.release_interface(devboard, interface.bInterfaceNumber)

# Note: We might need this - it throws resource busy errors, may be a problem later-on.
# devboard.attach_kernel_driver(interface.bInterfaceNumber)

0 comments on commit 04f8da5

Please sign in to comment.