plus4的klipper版本

This commit is contained in:
whb0514
2024-09-02 13:37:34 +08:00
parent 653d7a8f6e
commit b90736975b
1006 changed files with 1195894 additions and 11114 deletions

View File

@@ -13,6 +13,7 @@
#include "board/pgm.h" // PROGMEM
#include "board/usb_cdc_ep.h" // USB_CDC_EP_BULK_IN
#include "byteorder.h" // cpu_to_le16
#include "command.h" // DECL_CONSTANT
#include "generic/usbstd.h" // struct usb_device_descriptor
#include "sched.h" // sched_wake_task
#include "usb_cdc.h" // usb_notify_ep0
@@ -103,20 +104,18 @@ struct gs_host_frame {
static struct usbcan_data {
struct task_wake wake;
// Canbus data from host
union {
struct gs_host_frame host_frame;
uint8_t rx_frame_pad[USB_CDC_EP_BULK_OUT_SIZE];
};
uint8_t host_status;
// Canbus data routed locally
uint8_t notify_local;
uint8_t notify_local, usb_send_busy;
uint32_t assigned_id;
// Canbus data from host
uint8_t host_status;
uint32_t host_pull_pos, host_push_pos;
struct gs_host_frame host_frames[16];
// Data from physical canbus interface
uint32_t pull_pos, push_pos;
struct canbus_msg queue[8];
uint32_t canhw_pull_pos, canhw_push_pos;
struct canbus_msg canhw_queue[32];
} UsbCan;
enum {
@@ -125,6 +124,8 @@ enum {
HS_TX_LOCAL = 4,
};
DECL_CONSTANT("CANBUS_BRIDGE", 1);
void
canbus_notify_tx(void)
{
@@ -136,16 +137,16 @@ void
canbus_process_data(struct canbus_msg *msg)
{
// Add to admin command queue
uint32_t pushp = UsbCan.push_pos;
if (pushp - UsbCan.pull_pos >= ARRAY_SIZE(UsbCan.queue))
uint32_t pushp = UsbCan.canhw_push_pos;
if (pushp - UsbCan.canhw_pull_pos >= ARRAY_SIZE(UsbCan.canhw_queue))
// No space - drop message
return;
if (UsbCan.assigned_id && (msg->id & ~1) == UsbCan.assigned_id)
// Id reserved for local
return;
uint32_t pos = pushp % ARRAY_SIZE(UsbCan.queue);
memcpy(&UsbCan.queue[pos], msg, sizeof(*msg));
UsbCan.push_pos = pushp + 1;
uint32_t pos = pushp % ARRAY_SIZE(UsbCan.canhw_queue);
memcpy(&UsbCan.canhw_queue[pos], msg, sizeof(*msg));
UsbCan.canhw_push_pos = pushp + 1;
usb_notify_bulk_out();
}
@@ -163,21 +164,44 @@ send_frame(struct canbus_msg *msg)
}
// Send any pending hw frames to host
static int
drain_hw_queue(void)
static void
drain_canhw_queue(void)
{
uint32_t pull_pos = UsbCan.canhw_pull_pos;
for (;;) {
uint32_t push_pos = readl(&UsbCan.push_pos);
uint32_t pull_pos = UsbCan.pull_pos;
if (push_pos != pull_pos) {
uint32_t pos = pull_pos % ARRAY_SIZE(UsbCan.queue);
int ret = send_frame(&UsbCan.queue[pos]);
if (ret < 0)
return -1;
UsbCan.pull_pos = pull_pos + 1;
continue;
uint32_t push_pos = readl(&UsbCan.canhw_push_pos);
if (push_pos == pull_pos) {
// No more data to send
UsbCan.usb_send_busy = 0;
return;
}
return 0;
uint32_t pos = pull_pos % ARRAY_SIZE(UsbCan.canhw_queue);
int ret = send_frame(&UsbCan.canhw_queue[pos]);
if (ret < 0) {
// USB is busy - retry later
UsbCan.usb_send_busy = 1;
return;
}
UsbCan.canhw_pull_pos = pull_pos = pull_pos + 1;
}
}
// Fill local queue with any USB messages sent from host
static void
fill_usb_host_queue(void)
{
uint32_t pull_pos = UsbCan.host_pull_pos, push_pos = UsbCan.host_push_pos;
for (;;) {
if (push_pos - pull_pos >= ARRAY_SIZE(UsbCan.host_frames))
// No more space in queue
break;
uint32_t pushp = push_pos % ARRAY_SIZE(UsbCan.host_frames);
struct gs_host_frame *gs = &UsbCan.host_frames[pushp];
int ret = usb_read_bulk_out(gs, sizeof(*gs));
if (ret <= 0)
// No more messages ready
break;
UsbCan.host_push_pos = push_pos = push_pos + 1;
}
}
@@ -186,79 +210,79 @@ usbcan_task(void)
{
if (!sched_check_wake(&UsbCan.wake))
return;
for (;;) {
// Send any pending hw frames to host
int ret = drain_hw_queue();
if (ret < 0)
return;
// Send any pending hw frames to host
drain_canhw_queue();
// Fill local queue with any USB messages arriving from host
fill_usb_host_queue();
// Route messages received from host
uint32_t pull_pos = UsbCan.host_pull_pos, push_pos = UsbCan.host_push_pos;
uint32_t pullp = pull_pos % ARRAY_SIZE(UsbCan.host_frames);
struct gs_host_frame *gs = &UsbCan.host_frames[pullp];
for (;;) {
// See if previous host frame needs to be transmitted
uint_fast8_t host_status = UsbCan.host_status;
if (host_status & (HS_TX_HW | HS_TX_LOCAL)) {
struct gs_host_frame *gs = &UsbCan.host_frame;
struct canbus_msg msg;
msg.id = gs->can_id;
msg.dlc = gs->can_dlc;
msg.data32[0] = gs->data32[0];
msg.data32[1] = gs->data32[1];
if (host_status & HS_TX_LOCAL) {
canserial_process_data(&msg);
UsbCan.host_status = host_status = host_status & ~HS_TX_LOCAL;
}
if (host_status & HS_TX_HW) {
ret = canbus_send(&msg);
int ret = canhw_send(&msg);
if (ret < 0)
return;
break;
UsbCan.host_status = host_status = host_status & ~HS_TX_HW;
}
if (host_status & HS_TX_LOCAL) {
ret = canserial_process_data(&msg);
if (ret < 0) {
usb_notify_bulk_out();
return;
}
UsbCan.host_status = host_status & ~HS_TX_LOCAL;
}
continue;
}
// Send any previous echo frames
if (host_status) {
ret = usb_send_bulk_in(&UsbCan.host_frame
, sizeof(UsbCan.host_frame));
if (UsbCan.notify_local || UsbCan.usb_send_busy)
// Don't send echo frame until other traffic is sent
break;
int ret = usb_send_bulk_in(gs, sizeof(*gs));
if (ret < 0)
return;
UsbCan.host_status = 0;
continue;
UsbCan.host_pull_pos = pull_pos = pull_pos + 1;
}
// See if can read a new frame from host
ret = usb_read_bulk_out(&UsbCan.host_frame, USB_CDC_EP_BULK_OUT_SIZE);
if (ret > 0) {
uint32_t id = UsbCan.host_frame.can_id;
UsbCan.host_status = HS_TX_ECHO | HS_TX_HW;
if (id == CANBUS_ID_ADMIN)
UsbCan.host_status = HS_TX_ECHO | HS_TX_HW | HS_TX_LOCAL;
else if (UsbCan.assigned_id && UsbCan.assigned_id == id)
UsbCan.host_status = HS_TX_ECHO | HS_TX_LOCAL;
continue;
}
// No more work to be done
if (UsbCan.notify_local) {
UsbCan.notify_local = 0;
canserial_notify_tx();
}
return;
// Process next frame from host
if (pull_pos == push_pos)
// No frame available - no more work to be done
break;
gs = &UsbCan.host_frames[pull_pos % ARRAY_SIZE(UsbCan.host_frames)];
uint32_t id = gs->can_id;
UsbCan.host_status = HS_TX_ECHO | HS_TX_HW;
if (id == CANBUS_ID_ADMIN)
UsbCan.host_status = HS_TX_ECHO | HS_TX_HW | HS_TX_LOCAL;
else if (UsbCan.assigned_id && UsbCan.assigned_id == id)
UsbCan.host_status = HS_TX_ECHO | HS_TX_LOCAL;
}
// Wake up local message response handling (if usb is not busy)
if (UsbCan.notify_local && !UsbCan.usb_send_busy)
canserial_notify_tx();
}
DECL_TASK(usbcan_task);
int
canserial_send(struct canbus_msg *msg)
canbus_send(struct canbus_msg *msg)
{
int ret = drain_hw_queue();
if (ret < 0)
goto retry_later;
ret = send_frame(msg);
if (UsbCan.usb_send_busy)
goto retry_later;
int ret = send_frame(msg);
if (ret < 0)
goto retry_later;
if (UsbCan.notify_local && UsbCan.host_status)
canbus_notify_tx();
UsbCan.notify_local = 0;
return msg->dlc;
retry_later:
@@ -267,7 +291,7 @@ retry_later:
}
void
canserial_set_filter(uint32_t id)
canbus_set_filter(uint32_t id)
{
UsbCan.assigned_id = id;
}