Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clean up data structures, remove dynamic memory allocation and make use of Linux compatible lists #135

Merged
merged 5 commits into from
Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ set(
include/dfu.h src/dfu.c
include/gpio.h src/gpio.c
include/led.h src/led.c
include/queue.h src/queue.c
include/timer.h src/timer.c
include/util.h src/util.c

Expand Down Expand Up @@ -170,7 +169,7 @@ populate_ldscript(CPU_FAMILY STM32F042X6
RAM_START 0x20000000
RAM_SIZE 6k
STACK_SIZE 1k
HEAP_SIZE 1k
HEAP_SIZE 0k
)

populate_ldscript(CPU_FAMILY STM32F072XB
Expand All @@ -179,7 +178,7 @@ populate_ldscript(CPU_FAMILY STM32F072XB
RAM_START 0x20000000
RAM_SIZE 16k
STACK_SIZE 2k
HEAP_SIZE 1k
HEAP_SIZE 0k
)

populate_ldscript(CPU_FAMILY STM32F407XE
Expand Down
19 changes: 10 additions & 9 deletions include/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,20 +428,21 @@ static inline int list_is_last(const struct list_head *list,
return list->next == head;
}

#define list_first_entry_or_null_locked(ptr, type, member) \
({ \
bool was_irq_enabled = disable_irq(); \
type *entry = list_first_entry_or_null(ptr, type, member); \
restore_irq(was_irq_enabled); \
entry; \
})
static inline void
list_add_locked(struct list_head *entry, struct list_head *head)
{
bool was_irq_enabled = disable_irq();

list_add(entry, head);
restore_irq(was_irq_enabled);
}

static inline void
list_move_tail_locked(struct list_head *entry, struct list_head *head)
list_add_tail_locked(struct list_head *entry, struct list_head *head)
{
bool was_irq_enabled = disable_irq();

list_move_tail(entry, head);
list_add_tail(entry, head);
restore_irq(was_irq_enabled);
}

Expand Down
42 changes: 0 additions & 42 deletions include/queue.h

This file was deleted.

18 changes: 12 additions & 6 deletions include/usbd_gs_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ THE SOFTWARE.
#include "config.h"
#include "gs_usb.h"
#include "led.h"
#include "queue.h"
#include "list.h"
#include "usbd_def.h"

/* Define these here so they can be referenced in other files */
Expand All @@ -48,17 +48,23 @@ THE SOFTWARE.

extern USBD_ClassTypeDef USBD_GS_CAN;

struct gs_host_frame_object {
struct list_head list;
struct gs_host_frame frame;
};

typedef struct {
uint8_t ep0_buf[CAN_CMD_PACKET_SIZE];

__IO uint32_t TxState;

USBD_SetupReqTypedef last_setup_request;

queue_t *q_frame_pool;
queue_t *q_from_host;
struct list_head list_frame_pool;
struct list_head list_from_host;
struct list_head list_to_host;

struct gs_host_frame *from_host_buf;
struct gs_host_frame_object *from_host_buf;

can_data_t channels[NUM_CAN_CHANNEL];

Expand All @@ -70,7 +76,7 @@ typedef struct {

bool pad_pkts_to_max_pkt_size;

struct gs_host_frame msgbuf[CAN_QUEUE_SIZE];
struct gs_host_frame_object msgbuf[CAN_QUEUE_SIZE];
} USBD_GS_CAN_HandleTypeDef __attribute__ ((aligned (4)));

#if defined(STM32F0)
Expand All @@ -86,7 +92,7 @@ typedef struct {
# define USB_RX_FIFO_SIZE ((256U / 4U) + 1U)
#endif

uint8_t USBD_GS_CAN_Init(USBD_GS_CAN_HandleTypeDef *hcan, USBD_HandleTypeDef *pdev, queue_t *q_frame_pool, queue_t *q_from_host, led_data_t *leds);
uint8_t USBD_GS_CAN_Init(USBD_GS_CAN_HandleTypeDef *hcan, USBD_HandleTypeDef *pdev, led_data_t *leds);
void USBD_GS_CAN_SuspendCallback(USBD_HandleTypeDef *pdev);
void USBD_GS_CAN_ResumeCallback(USBD_HandleTypeDef *pdev);
bool USBD_GS_CAN_TxReady(USBD_HandleTypeDef *pdev);
Expand Down
110 changes: 68 additions & 42 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ THE SOFTWARE.
#include "gs_usb.h"
#include "hal_include.h"
#include "led.h"
#include "queue.h"
#include "timer.h"
#include "usbd_conf.h"
#include "usbd_core.h"
Expand All @@ -46,17 +45,12 @@ THE SOFTWARE.

void HAL_MspInit(void);
static void SystemClock_Config(void);
static bool send_to_host_or_enqueue(struct gs_host_frame *frame);
static void send_to_host(void);

static USBD_GS_CAN_HandleTypeDef hGS_CAN;
static USBD_HandleTypeDef hUSB = {0};
static led_data_t hLED = {0};

static queue_t *q_frame_pool = NULL;
static queue_t *q_from_host = NULL;
static queue_t *q_to_host = NULL;

int main(void)
{
can_data_t *channel = &hGS_CAN.channels[0];
Expand All @@ -83,49 +77,67 @@ int main(void)
can_init(channel, CAN_INTERFACE);
can_disable(channel);

INIT_LIST_HEAD(&hGS_CAN.list_frame_pool);
INIT_LIST_HEAD(&hGS_CAN.list_from_host);
INIT_LIST_HEAD(&hGS_CAN.list_to_host);

q_frame_pool = queue_create(CAN_QUEUE_SIZE);
q_from_host = queue_create(CAN_QUEUE_SIZE);
q_to_host = queue_create(CAN_QUEUE_SIZE);
assert_basic(q_frame_pool && q_from_host && q_to_host);

for (unsigned i=0; i<CAN_QUEUE_SIZE; i++) {
queue_push_back(q_frame_pool, &hGS_CAN.msgbuf[i]);
for (unsigned i = 0; i < ARRAY_SIZE(hGS_CAN.msgbuf); i++) {
list_add_tail(&hGS_CAN.msgbuf[i].list, &hGS_CAN.list_frame_pool);
}

USBD_Init(&hUSB, (USBD_DescriptorsTypeDef*)&FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUSB, &USBD_GS_CAN);
USBD_GS_CAN_Init(&hGS_CAN, &hUSB, q_frame_pool, q_from_host, &hLED);
USBD_GS_CAN_Init(&hGS_CAN, &hUSB, &hLED);
USBD_Start(&hUSB);

#ifdef CAN_S_GPIO_Port
HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_RESET);
#endif

while (1) {
struct gs_host_frame *frame = queue_pop_front(q_from_host);
if (frame != 0) { // send can message from host
struct gs_host_frame_object *frame_object;

bool was_irq_enabled = disable_irq();
frame_object = list_first_entry_or_null(&hGS_CAN.list_from_host,
struct gs_host_frame_object,
list);
if (frame_object) { // send CAN message from host
struct gs_host_frame *frame = &frame_object->frame;

list_del(&frame_object->list);
restore_irq(was_irq_enabled);

if (can_send(channel, frame)) {
// Echo sent frame back to host
frame->flags = 0x0;
frame->reserved = 0x0;
frame->timestamp_us = timer_get();
send_to_host_or_enqueue(frame);

list_add_tail_locked(&frame_object->list, &hGS_CAN.list_to_host);

fenugrec marked this conversation as resolved.
Show resolved Hide resolved
led_indicate_trx(&hLED, led_tx);
} else {
queue_push_front(q_from_host, frame); // retry later
list_add_locked(&frame_object->list, &hGS_CAN.list_from_host);
}
} else {
restore_irq(was_irq_enabled);
}

if (USBD_GS_CAN_TxReady(&hUSB)) {
send_to_host();
}

if (can_is_rx_pending(channel)) {
struct gs_host_frame *frame = queue_pop_front(q_frame_pool);
if (frame != 0)
{
bool was_irq_enabled = disable_irq();
frame_object = list_first_entry_or_null(&hGS_CAN.list_frame_pool,
struct gs_host_frame_object,
list);
if (frame_object) {
struct gs_host_frame *frame = &frame_object->frame;

list_del(&frame_object->list);
restore_irq(was_irq_enabled);

if (can_receive(channel, frame)) {

frame->timestamp_us = timer_get();
Expand All @@ -134,30 +146,42 @@ int main(void)
frame->flags = 0;
frame->reserved = 0;

send_to_host_or_enqueue(frame);
list_add_tail_locked(&frame_object->list, &hGS_CAN.list_to_host);

led_indicate_trx(&hLED, led_rx);
} else {
list_add_tail_locked(&frame_object->list, &hGS_CAN.list_frame_pool);
}
else
{
queue_push_back(q_frame_pool, frame);
}
} else {
restore_irq(was_irq_enabled);
}
// If there are frames to receive, don't report any error frames. The
// best we can localize the errors to is "after the last successfully
// received frame", so wait until we get there. LEC will hold some error
// to report even if multiple pass by.
} else {
uint32_t can_err = can_get_error_status(channel);
struct gs_host_frame *frame = queue_pop_front(q_frame_pool);
if (frame != 0) {

bool was_irq_enabled = disable_irq();
frame_object = list_first_entry_or_null(&hGS_CAN.list_frame_pool,
struct gs_host_frame_object,
list);
if (frame_object) {
struct gs_host_frame *frame = &frame_object->frame;

list_del(&frame_object->list);
restore_irq(was_irq_enabled);

frame->timestamp_us = timer_get();
if (can_parse_error_status(can_err, last_can_error_status, channel, frame)) {
send_to_host_or_enqueue(frame);
list_add_tail_locked(&frame_object->list, &hGS_CAN.list_to_host);

marckleinebudde marked this conversation as resolved.
Show resolved Hide resolved
last_can_error_status = can_err;
} else {
queue_push_back(q_frame_pool, frame);
list_add_tail_locked(&frame_object->list, &hGS_CAN.list_frame_pool);
}
} else {
restore_irq(was_irq_enabled);
}
}

Expand Down Expand Up @@ -281,22 +305,24 @@ void SystemClock_Config(void)
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

bool send_to_host_or_enqueue(struct gs_host_frame *frame)
{
queue_push_back(q_to_host, frame);
return true;
}

void send_to_host(void)
{
struct gs_host_frame *frame = queue_pop_front(q_to_host);

if (!frame)
struct gs_host_frame_object *frame_object;

bool was_irq_enabled = disable_irq();
frame_object = list_first_entry_or_null(&hGS_CAN.list_to_host,
struct gs_host_frame_object,
list);
if (!frame_object) {
restore_irq(was_irq_enabled);
return;
}
list_del(&frame_object->list);
restore_irq(was_irq_enabled);

if (USBD_GS_CAN_SendFrame(&hUSB, frame) == USBD_OK) {
queue_push_back(q_frame_pool, frame);
if (USBD_GS_CAN_SendFrame(&hUSB, &frame_object->frame) == USBD_OK) {
list_add_tail_locked(&frame_object->list, &hGS_CAN.list_frame_pool);
} else {
queue_push_front(q_to_host, frame);
list_add_locked(&frame_object->list, &hGS_CAN.list_to_host);
}
}
Loading