mirror of
https://github.com/andreili/katapult.git
synced 2025-08-23 19:34:06 +02:00
src: update generic files
Bring up generic files to accommodate the latest version of Klipper. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
72bde3bbf8
commit
73d7ddd5aa
@ -14,17 +14,45 @@ extern uint32_t _data_start, _data_end, _data_flash;
|
||||
extern uint32_t _bss_start, _bss_end, _stack_start;
|
||||
extern uint32_t _stack_end;
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Basic interrupt handlers
|
||||
****************************************************************/
|
||||
|
||||
// Initial code entry point - invoked by the processor after a reset
|
||||
void
|
||||
ResetHandler(void)
|
||||
static void __noreturn
|
||||
reset_handler_stage_two(void)
|
||||
{
|
||||
// Disable SysTick irq (for some bootloaders that don't)
|
||||
int i;
|
||||
|
||||
// Clear all enabled user interrupts and user pending interrupts
|
||||
for (i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) {
|
||||
NVIC->ICER[i] = 0xFFFFFFFF;
|
||||
__DSB();
|
||||
NVIC->ICPR[i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
// Reset all user interrupt priorities
|
||||
for (i = 0; i < ARRAY_SIZE(NVIC->IP); i++)
|
||||
NVIC->IP[i] = 0;
|
||||
|
||||
// Disable SysTick interrupt
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk;
|
||||
__DSB();
|
||||
|
||||
// Clear pending pendsv and systick interrupts
|
||||
SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk | SCB_ICSR_PENDSTCLR_Msk;
|
||||
|
||||
// Reset all system interrupt priorities
|
||||
#if __CORTEX_M >= 7
|
||||
for (i = 0; i < ARRAY_SIZE(SCB->SHPR); i++)
|
||||
SCB->SHPR[i] = 0;
|
||||
#else
|
||||
for (i = 0; i < ARRAY_SIZE(SCB->SHP); i++)
|
||||
SCB->SHP[i] = 0;
|
||||
#endif
|
||||
|
||||
__DSB();
|
||||
__ISB();
|
||||
__enable_irq();
|
||||
|
||||
// Copy global variables from flash to ram
|
||||
uint32_t count = (&_data_end - &_data_start) * 4;
|
||||
@ -45,6 +73,18 @@ ResetHandler(void)
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
// Initial code entry point - invoked by the processor after a reset
|
||||
// Reset interrupts and stack to take control from bootloaders
|
||||
void
|
||||
ResetHandler(void)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
// Explicitly load the stack pointer, jump to stage two
|
||||
asm volatile("mov sp, %0\n bx %1"
|
||||
: : "r"(&_stack_end), "r"(reset_handler_stage_two));
|
||||
}
|
||||
DECL_ARMCM_IRQ(ResetHandler, -15);
|
||||
|
||||
// Code called for any undefined interrupts
|
||||
|
@ -4,6 +4,7 @@
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
#include "board/internal.h" // __CORTEX_M
|
||||
#include "irq.h" // irqstatus_t
|
||||
|
||||
void
|
||||
@ -36,6 +37,10 @@ irq_restore(irqstatus_t flag)
|
||||
void
|
||||
irq_wait(void)
|
||||
{
|
||||
if (__CORTEX_M >= 7)
|
||||
// Cortex-m7 may disable cpu counter on wfi, so use nop
|
||||
asm volatile("cpsie i\n nop\n cpsid i\n" ::: "memory");
|
||||
else
|
||||
asm volatile("cpsie i\n wfi\n cpsid i\n" ::: "memory");
|
||||
}
|
||||
|
||||
@ -43,3 +48,26 @@ void
|
||||
irq_poll(void)
|
||||
{
|
||||
}
|
||||
|
||||
// Clear the active irq if a shutdown happened in an irq handler
|
||||
void
|
||||
clear_active_irq(void)
|
||||
{
|
||||
uint32_t psr;
|
||||
asm volatile("mrs %0, psr" : "=r" (psr));
|
||||
if (!(psr & 0x1ff))
|
||||
// Shutdown did not occur in an irq - nothing to do.
|
||||
return;
|
||||
// Clear active irq status
|
||||
psr = 1<<24; // T-bit
|
||||
uint32_t temp;
|
||||
asm volatile(
|
||||
" push { %1 }\n"
|
||||
" adr %0, 1f\n"
|
||||
" push { %0 }\n"
|
||||
" push { r0, r1, r2, r3, r4, lr }\n"
|
||||
" bx %2\n"
|
||||
".balign 4\n"
|
||||
"1:\n"
|
||||
: "=&r"(temp) : "r"(psr), "r"(0xfffffff9) : "r12", "cc");
|
||||
}
|
||||
|
8
src/generic/armcm_timer.h
Normal file
8
src/generic/armcm_timer.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __GENERIC_ARMCM_TIMER_H
|
||||
#define __GENERIC_ARMCM_TIMER_H
|
||||
|
||||
#include <stdint.h> // uint32_t
|
||||
|
||||
void udelay(uint32_t usecs);
|
||||
|
||||
#endif // armcm_timer.h
|
@ -87,67 +87,88 @@ canboot_sendf(uint8_t* data, uint16_t size)
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* CAN command handling
|
||||
* CAN "admin" command handling
|
||||
****************************************************************/
|
||||
|
||||
// Helper to retry sending until successful
|
||||
static void
|
||||
canbus_send_blocking(uint32_t id, uint32_t len, uint8_t *data)
|
||||
// Available commands and responses
|
||||
#define CANBUS_CMD_QUERY_UNASSIGNED 0x00
|
||||
#define CANBUS_CMD_SET_NODEID 0x01
|
||||
#define CANBUS_RESP_NEED_NODEID 0x20
|
||||
|
||||
// Helper to verify a UUID in a command matches this chip's UUID
|
||||
static int
|
||||
can_check_uuid(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
return len >= 7 && memcmp(&data[1], canbus_uuid, sizeof(canbus_uuid)) == 0;
|
||||
}
|
||||
|
||||
// Helpers to encode/decode a CAN identifier to a 1-byte "nodeid"
|
||||
static int
|
||||
can_get_nodeid(void)
|
||||
{
|
||||
if (!canbus_assigned_id)
|
||||
return 0;
|
||||
return (canbus_assigned_id - 0x100) >> 1;
|
||||
}
|
||||
static uint32_t
|
||||
can_decode_nodeid(int nodeid)
|
||||
{
|
||||
return (nodeid << 1) + 0x100;
|
||||
}
|
||||
|
||||
static void
|
||||
can_process_query_unassigned(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
if (canbus_assigned_id)
|
||||
return;
|
||||
uint8_t send[8];
|
||||
send[0] = CANBUS_RESP_NEED_NODEID;
|
||||
memcpy(&send[1], canbus_uuid, sizeof(canbus_uuid));
|
||||
// Send with retry
|
||||
for (;;) {
|
||||
int ret = canbus_send(id, len, data);
|
||||
int ret = canbus_send(CANBUS_ID_ADMIN_RESP, 7, send);
|
||||
if (ret >= 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
can_process_ping(uint32_t id, uint32_t len, uint8_t *data)
|
||||
can_id_conflict(void)
|
||||
{
|
||||
canbus_send_blocking(canbus_assigned_id + 1, 0, NULL);
|
||||
canbus_assigned_id = 0;
|
||||
canbus_set_filter(canbus_assigned_id);
|
||||
// TODO: We should likely do something here, such as report back
|
||||
}
|
||||
|
||||
static void
|
||||
can_process_reset(uint32_t id, uint32_t len, uint8_t *data)
|
||||
can_process_set_nodeid(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
/*uint32_t reset_id = data[0] | (data[1] << 8);
|
||||
if (reset_id == canbus_assigned_id)
|
||||
canbus_reboot();*/
|
||||
}
|
||||
|
||||
static void
|
||||
can_process_uuid(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
if (canbus_assigned_id)
|
||||
if (len < 8)
|
||||
return;
|
||||
canbus_send_blocking(CANBUS_ID_UUID_RESP, sizeof(canbus_uuid), canbus_uuid);
|
||||
}
|
||||
|
||||
static void
|
||||
can_process_set_id(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
// compare my UUID with packet to check if this packet mine
|
||||
if (memcmp(&data[2], canbus_uuid, sizeof(canbus_uuid)) == 0) {
|
||||
canbus_assigned_id = data[0] | (data[1] << 8);
|
||||
canbus_set_dataport(canbus_assigned_id);
|
||||
uint32_t newid = can_decode_nodeid(data[7]);
|
||||
if (can_check_uuid(id, len, data)) {
|
||||
if (newid != canbus_assigned_id) {
|
||||
canbus_assigned_id = newid;
|
||||
canbus_set_filter(canbus_assigned_id);
|
||||
}
|
||||
} else if (newid == canbus_assigned_id) {
|
||||
can_id_conflict();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle an "admin" command
|
||||
static void
|
||||
can_process(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
if (id == canbus_assigned_id) {
|
||||
if (len)
|
||||
canboot_process_rx(id, len, data);
|
||||
else
|
||||
can_process_ping(id, len, data);
|
||||
} else if (id == CANBUS_ID_UUID) {
|
||||
if (len)
|
||||
can_process_reset(id, len, data);
|
||||
else
|
||||
can_process_uuid(id, len, data);
|
||||
} else if (id==CANBUS_ID_SET) {
|
||||
can_process_set_id(id, len, data);
|
||||
if (!len)
|
||||
return;
|
||||
switch (data[0]) {
|
||||
case CANBUS_CMD_QUERY_UNASSIGNED:
|
||||
can_process_query_unassigned(id, len, data);
|
||||
break;
|
||||
case CANBUS_CMD_SET_NODEID:
|
||||
can_process_set_nodeid(id, len, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,12 +179,23 @@ can_process(uint32_t id, uint32_t len, uint8_t *data)
|
||||
|
||||
static volatile uint8_t canbus_rx_wake;
|
||||
|
||||
// Handle incoming data (called from IRQ handler)
|
||||
void
|
||||
canbus_process_data(uint32_t id, uint32_t len, uint8_t *data)
|
||||
{
|
||||
if (!id || id != canbus_assigned_id)
|
||||
return;
|
||||
canboot_process_rx(id, len, data);
|
||||
canbus_notify_rx();
|
||||
}
|
||||
|
||||
void
|
||||
canbus_notify_rx(void)
|
||||
{
|
||||
canbus_rx_wake = 1;
|
||||
}
|
||||
|
||||
// Task to process incoming commands and admin messages
|
||||
void
|
||||
canbus_rx_task(void)
|
||||
{
|
||||
@ -178,6 +210,9 @@ canbus_rx_task(void)
|
||||
int ret = canbus_read(&id, data);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (id && id == canbus_assigned_id + 1)
|
||||
can_id_conflict();
|
||||
else if (id == CANBUS_ID_ADMIN)
|
||||
can_process(id, ret, data);
|
||||
}
|
||||
}
|
||||
@ -190,7 +225,12 @@ void
|
||||
canbus_set_uuid(void *uuid)
|
||||
{
|
||||
memcpy(canbus_uuid, uuid, sizeof(canbus_uuid));
|
||||
|
||||
// Send initial message
|
||||
can_process_uuid(0, 0, NULL);
|
||||
canbus_notify_rx();
|
||||
}
|
||||
|
||||
void
|
||||
canbus_shutdown(void)
|
||||
{
|
||||
canbus_notify_tx();
|
||||
canbus_notify_rx();
|
||||
}
|
@ -3,24 +3,22 @@
|
||||
|
||||
#include <stdint.h> // uint32_t
|
||||
|
||||
#define CANBUS_ID_UUID 0x321
|
||||
#define CANBUS_ID_SET 0x322
|
||||
#define CANBUS_ID_UUID_RESP 0x323
|
||||
#define CANBUS_ID_ADMIN 0x3f0
|
||||
#define CANBUS_ID_ADMIN_RESP 0x3f1
|
||||
#define CANBUS_UUID_LEN 6
|
||||
|
||||
// callbacks provided by board specific code
|
||||
int canbus_read(uint32_t *id, uint8_t *data);
|
||||
int canbus_send(uint32_t id, uint32_t len, uint8_t *data);
|
||||
void canbus_set_dataport(uint32_t id);
|
||||
void canbus_set_filter(uint32_t id);
|
||||
void canbus_reboot(void);
|
||||
void can_init(void);
|
||||
|
||||
// canbus.c
|
||||
void canbus_notify_tx(void);
|
||||
void canbus_notify_rx(void);
|
||||
void canbus_process_data(uint32_t id, uint32_t len, uint8_t *data);
|
||||
void canbus_set_uuid(void *data);
|
||||
|
||||
// canboot prototypes
|
||||
void can_init(void);
|
||||
void canbus_tx_task(void);
|
||||
void canbus_rx_task(void);
|
||||
uint8_t canbus_tx_clear(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user