aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--klippy/pins.py2
-rw-r--r--src/sam3/Kconfig4
-rw-r--r--src/sam3/Makefile15
-rw-r--r--src/sam3/adc.c7
-rw-r--r--src/sam3/gpio.c2
-rw-r--r--src/sam3/i2c.c7
-rw-r--r--src/sam3/internal.h2
-rw-r--r--src/sam3/sam4s_sysinit.c65
-rw-r--r--src/sam3/sam4s_timer.c118
-rw-r--r--src/sam3/serial.c6
-rw-r--r--src/sam3/spi.c4
-rw-r--r--test/configs/sam4s8c.config3
12 files changed, 226 insertions, 9 deletions
diff --git a/klippy/pins.py b/klippy/pins.py
index 6c82f0d1..0b6bc5ff 100644
--- a/klippy/pins.py
+++ b/klippy/pins.py
@@ -45,8 +45,8 @@ MCU_PINS = {
"atmega32u4": port_pins(6),
"atmega1280": port_pins(12), "atmega2560": port_pins(12),
"sam3x8e": port_pins(4, 32),
+ "sam4s8c": port_pins(3, 32), "sam4e8e" : port_pins(5, 32),
"samd21g": port_pins(2, 32),
- "sam4e8e" : port_pins(5,32),
"stm32f103": port_pins(5, 16),
"lpc176x": lpc_pins(),
"pru": beaglebone_pins(),
diff --git a/src/sam3/Kconfig b/src/sam3/Kconfig
index 1e79812a..e7085eaf 100644
--- a/src/sam3/Kconfig
+++ b/src/sam3/Kconfig
@@ -19,6 +19,8 @@ choice
prompt "Processor model"
config MACH_SAM3X8E
bool "SAM3x8e (Arduino Due)"
+ config MACH_SAM4S8C
+ bool "SAM4s8c (Duet Maestro)"
config MACH_SAM4E8E
bool "SAM4e8e (Duet Wifi/Eth)"
endchoice
@@ -26,11 +28,13 @@ endchoice
config MCU
string
default "sam3x8e" if MACH_SAM3X8E
+ default "sam4s8c" if MACH_SAM4S8C
default "sam4e8e" if MACH_SAM4E8E
config CLOCK_FREQ
int
default 42000000 if MACH_SAM3X8E # 84000000/2
+ default 15000000 if MACH_SAM4S8C # 120000000/8
default 60000000 if MACH_SAM4E8E # 120000000/2
config SERIAL
diff --git a/src/sam3/Makefile b/src/sam3/Makefile
index 97503af4..30361ed8 100644
--- a/src/sam3/Makefile
+++ b/src/sam3/Makefile
@@ -5,29 +5,36 @@ CROSS_PREFIX=arm-none-eabi-
dirs-y += src/sam3 src/generic
dirs-$(CONFIG_MACH_SAM3X8E) += lib/sam3x/gcc/gcc
+dirs-$(CONFIG_MACH_SAM4S8C) += lib/sam4s/gcc/gcc
dirs-$(CONFIG_MACH_SAM4E8E) += lib/sam4e/gcc/gcc
CFLAGS-$(CONFIG_MACH_SAM3X8E) += -mcpu=cortex-m3 -falign-loops=16
CFLAGS-$(CONFIG_MACH_SAM3X8E) += -Ilib/sam3x/include -D__SAM3X8E__
+CFLAGS-$(CONFIG_MACH_SAM4S8C) += -mcpu=cortex-m4
+CFLAGS-$(CONFIG_MACH_SAM4S8C) += -Ilib/sam4s/include -D__SAM4S8C__
CFLAGS-$(CONFIG_MACH_SAM4E8E) += -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS-$(CONFIG_MACH_SAM4E8E) += -Ilib/sam4e/include -D__SAM4E8E__
CFLAGS += -mthumb $(CFLAGS-y) -Ilib/cmsis-core
eflags-$(CONFIG_MACH_SAM3X8E) += -Llib/sam3x/gcc/gcc
eflags-$(CONFIG_MACH_SAM3X8E) += -T lib/sam3x/gcc/gcc/sam3x8e_flash.ld
+eflags-$(CONFIG_MACH_SAM4S8C) += -Llib/sam4s/gcc/gcc
+eflags-$(CONFIG_MACH_SAM4S8C) += -T lib/sam4s/gcc/gcc/sam4s8c_flash.ld
eflags-$(CONFIG_MACH_SAM4E8E) += -Llib/sam4e/gcc/gcc
eflags-$(CONFIG_MACH_SAM4E8E) += -T lib/sam4e/gcc/gcc/sam4e8e_flash.ld
CFLAGS_klipper.elf += $(eflags-y) --specs=nano.specs --specs=nosys.specs
# Add source files
-src-y += sam3/main.c sam3/timer.c sam3/gpio.c sam3/i2c.c sam3/spi.c
+src-y += sam3/main.c sam3/gpio.c sam3/i2c.c sam3/spi.c
src-y += generic/crc16_ccitt.c generic/alloc.c
src-y += generic/armcm_irq.c generic/timer_irq.c
src-$(CONFIG_SERIAL) += sam3/serial.c generic/serial_irq.c
-src-$(CONFIG_MACH_SAM3X8E) += sam3/adc.c
+src-$(CONFIG_MACH_SAM3X8E) += sam3/adc.c sam3/timer.c
src-$(CONFIG_MACH_SAM3X8E) += ../lib/sam3x/gcc/system_sam3xa.c
src-$(CONFIG_MACH_SAM3X8E) += ../lib/sam3x/gcc/gcc/startup_sam3xa.c
-src-$(CONFIG_MACH_SAM4E8E) += sam3/sam4e_afec.c sam3/sam4_cache.c
+src-$(CONFIG_MACH_SAM4S8C) += sam3/adc.c sam3/sam4s_timer.c sam3/sam4s_sysinit.c
+src-$(CONFIG_MACH_SAM4S8C) += ../lib/sam4s/gcc/gcc/startup_sam4s.c
+src-$(CONFIG_MACH_SAM4E8E) += sam3/sam4e_afec.c sam3/timer.c sam3/sam4_cache.c
src-$(CONFIG_MACH_SAM4E8E) += ../lib/sam4e/gcc/system_sam4e.c
src-$(CONFIG_MACH_SAM4E8E) += ../lib/sam4e/gcc/gcc/startup_sam4e.c
@@ -47,4 +54,4 @@ flash: $(OUT)klipper.bin lib/bossac/bin/bossac
@echo " Flashing $^ to $(FLASH_DEVICE) via bossac"
$(Q)if [ -z $(FLASH_DEVICE) ]; then echo "Please specify FLASH_DEVICE"; exit 1; fi
$(Q)lib/bossac/bin/bossac -U -p "$(FLASH_DEVICE)" -a -e -w $(OUT)klipper.bin -v -b
- $(Q)lib/bossac/bin/bossac -p "$(FLASH_DEVICE)" -R > /dev/null 2>&1 || true
+ $(Q)lib/bossac/bin/bossac -p "$(FLASH_DEVICE)" -b -R > /dev/null 2>&1 || true
diff --git a/src/sam3/adc.c b/src/sam3/adc.c
index 0baf9118..425d60a9 100644
--- a/src/sam3/adc.c
+++ b/src/sam3/adc.c
@@ -13,10 +13,17 @@
#include "sched.h" // sched_shutdown
static const uint8_t adc_pins[] = {
+#if CONFIG_MACH_SAM3X8E
GPIO('A', 2), GPIO('A', 3), GPIO('A', 4), GPIO('A', 6),
GPIO('A', 22), GPIO('A', 23), GPIO('A', 24), GPIO('A', 16),
GPIO('B', 12), GPIO('B', 13), GPIO('B', 17), GPIO('B', 18),
GPIO('B', 19), GPIO('B', 20)
+#elif CONFIG_MACH_SAM4S8C
+ GPIO('A', 17), GPIO('A', 18), GPIO('A', 19), GPIO('A', 20),
+ GPIO('B', 0), GPIO('B', 1), GPIO('B', 2), GPIO('B', 3),
+ GPIO('A', 21), GPIO('A', 22), GPIO('C', 13), GPIO('C', 15),
+ GPIO('C', 12), GPIO('C', 29), GPIO('C', 30)
+#endif
};
#define ADC_FREQ_MAX 20000000
diff --git a/src/sam3/gpio.c b/src/sam3/gpio.c
index 065663f9..7e6a1dab 100644
--- a/src/sam3/gpio.c
+++ b/src/sam3/gpio.c
@@ -14,6 +14,8 @@
static Pio * const digital_regs[] = {
#if CONFIG_MACH_SAM3X8E
PIOA, PIOB, PIOC, PIOD
+#elif CONFIG_MACH_SAM4S8C
+ PIOA, PIOB, PIOC
#elif CONFIG_MACH_SAM4E8E
PIOA, PIOB, PIOC, PIOD, PIOE
#endif
diff --git a/src/sam3/i2c.c b/src/sam3/i2c.c
index 27a04738..910471fd 100644
--- a/src/sam3/i2c.c
+++ b/src/sam3/i2c.c
@@ -5,7 +5,6 @@
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include "autoconf.h" // CONFIG_CLOCK_FREQ
#include "board/misc.h" // timer_from_us
#include "command.h" // shutdown
#include "gpio.h" // i2c_setup
@@ -18,7 +17,7 @@
#define TWI0_SDA_GPIO GPIO('A', 17)
#define TWI1_SCL_GPIO GPIO('B', 13)
#define TWI1_SDA_GPIO GPIO('B', 12)
-#elif CONFIG_MACH_SAM4E8E
+#elif CONFIG_MACH_SAM4S8C || CONFIG_MACH_SAM4E8E
#define TWI0_SCL_GPIO GPIO('A', 4)
#define TWI0_SDA_GPIO GPIO('A', 3)
#define TWI1_SCL_GPIO GPIO('B', 5)
@@ -48,7 +47,7 @@ i2c_init(Twi *p_twi, uint32_t rate)
uint32_t chdiv = 0;
uint32_t ckdiv = 0;
- cldiv = CONFIG_CLOCK_FREQ / ((rate > 384000 ? 384000 : rate) * 2) - 4;
+ cldiv = SystemCoreClock / ((rate > 384000 ? 384000 : rate) * 4) - 4;
while((cldiv > 255) && (ckdiv < 7)) {
ckdiv++;
@@ -56,7 +55,7 @@ i2c_init(Twi *p_twi, uint32_t rate)
}
if (rate > 348000) {
- chdiv = CONFIG_CLOCK_FREQ / ((2 * rate - 384000) * 2) - 4;
+ chdiv = SystemCoreClock / ((2 * rate - 384000) * 4) - 4;
while((chdiv > 255) && (ckdiv < 7)) {
ckdiv++;
chdiv /= 2;
diff --git a/src/sam3/internal.h b/src/sam3/internal.h
index e9457ed2..dd94a609 100644
--- a/src/sam3/internal.h
+++ b/src/sam3/internal.h
@@ -7,6 +7,8 @@
#if CONFIG_MACH_SAM3X8E
#include "sam3x8e.h"
+#elif CONFIG_MACH_SAM4S8C
+#include "sam4s.h"
#elif CONFIG_MACH_SAM4E8E
#include "sam4e.h"
#endif
diff --git a/src/sam3/sam4s_sysinit.c b/src/sam3/sam4s_sysinit.c
new file mode 100644
index 00000000..41a2dcfe
--- /dev/null
+++ b/src/sam3/sam4s_sysinit.c
@@ -0,0 +1,65 @@
+// This code is from lib/sam4e/gcc/system_sam4e.c - it is unclear why
+// it is not defined in the Atmel sam4s cmsis code.
+
+#include "internal.h"
+
+/* Clock Settings (120MHz) */
+#define SYS_BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8U))
+#define SYS_BOARD_PLLAR (CKGR_PLLAR_ONE \
+ | CKGR_PLLAR_MULA(0x13U) \
+ | CKGR_PLLAR_PLLACOUNT(0x3fU) \
+ | CKGR_PLLAR_DIVA(0x1U))
+#define SYS_BOARD_MCKR (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)
+
+#define SYS_CKGR_MOR_KEY_VALUE CKGR_MOR_KEY(0x37) /* Key to unlock MOR register */
+
+uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
+
+void SystemInit( void )
+{
+ /* Set FWS according to SYS_BOARD_MCKR configuration */
+ EFC0->EEFC_FMR = EEFC_FMR_FWS(5);
+
+ /* Initialize main oscillator */
+ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
+ {
+ PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
+
+ while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) )
+ {
+ }
+ }
+
+ /* Switch to 3-20MHz Xtal oscillator */
+ PMC->CKGR_MOR = SYS_CKGR_MOR_KEY_VALUE | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
+
+ while ( !(PMC->PMC_SR & PMC_SR_MOSCSELS) )
+ {
+ }
+
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
+
+ while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) )
+ {
+ }
+
+ /* Initialize PLLA */
+ PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
+ while ( !(PMC->PMC_SR & PMC_SR_LOCKA) )
+ {
+ }
+
+ /* Switch to main clock */
+ PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
+ while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) )
+ {
+ }
+
+ /* Switch to PLLA */
+ PMC->PMC_MCKR = SYS_BOARD_MCKR;
+ while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) )
+ {
+ }
+
+ SystemCoreClock = CHIP_FREQ_CPU_MAX;
+}
diff --git a/src/sam3/sam4s_timer.c b/src/sam3/sam4s_timer.c
new file mode 100644
index 00000000..a586dd64
--- /dev/null
+++ b/src/sam3/sam4s_timer.c
@@ -0,0 +1,118 @@
+// SAM4s 16bit timer interrupt scheduling
+//
+// Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "board/io.h" // readl
+#include "board/irq.h" // irq_disable
+#include "board/misc.h" // timer_read_time
+#include "board/timer_irq.h" // timer_dispatch_many
+#include "command.h" // DECL_SHUTDOWN
+#include "internal.h" // TC0
+#include "sched.h" // DECL_INIT
+
+
+/****************************************************************
+ * Low level timer code
+ ****************************************************************/
+
+// Get the 16bit timer value
+static uint32_t
+timer_get(void)
+{
+ return TC0->TC_CHANNEL[0].TC_CV;
+}
+
+// Set the next irq time
+static void
+timer_set(uint32_t value)
+{
+ TC0->TC_CHANNEL[0].TC_RA = value;
+}
+
+// Activate timer dispatch as soon as possible
+void
+timer_kick(void)
+{
+ timer_set(timer_read_time() + 50);
+}
+
+
+/****************************************************************
+ * 16bit hardware timer to 32bit conversion
+ ****************************************************************/
+
+// High bits of timer (top 17 bits)
+static uint32_t timer_high;
+
+// Return the current time (in absolute clock ticks).
+uint32_t __always_inline
+timer_read_time(void)
+{
+ uint32_t th = readl(&timer_high);
+ uint32_t cur = timer_get();
+ // Combine timer_high (high 17 bits) and current time (low 16
+ // bits) using method that handles rollovers correctly.
+ return (th ^ cur) + (th & 0x8000);
+}
+
+// Update timer_high every 0x8000 clock ticks
+static uint_fast8_t
+timer_event(struct timer *t)
+{
+ timer_high += 0x8000;
+ t->waketime = timer_high + 0x8000;
+ return SF_RESCHEDULE;
+}
+static struct timer wrap_timer = {
+ .func = timer_event,
+ .waketime = 0x8000,
+};
+
+void
+timer_reset(void)
+{
+ sched_add_timer(&wrap_timer);
+}
+DECL_SHUTDOWN(timer_reset);
+
+
+/****************************************************************
+ * Timer init
+ ****************************************************************/
+
+void
+timer_init(void)
+{
+ TcChannel *tc = &TC0->TC_CHANNEL[0];
+ // Reset the timer
+ tc->TC_CCR = TC_CCR_CLKDIS;
+ tc->TC_IDR = 0xFFFFFFFF;
+ // Enable it
+ enable_pclock(ID_TC0);
+ tc->TC_CMR = TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK2;
+ tc->TC_IER = TC_IER_CPAS;
+ NVIC_SetPriority(TC0_IRQn, 1);
+ NVIC_EnableIRQ(TC0_IRQn);
+ timer_kick();
+ timer_reset();
+ tc->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
+}
+DECL_INIT(timer_init);
+
+
+/****************************************************************
+ * Main timer dispatch irq handler
+ ****************************************************************/
+
+// IRQ handler
+void __visible __aligned(16) // aligning helps stabilize perf benchmarks
+TC0_Handler(void)
+{
+ irq_disable();
+ uint32_t next = timer_dispatch_many();
+ timer_set(next);
+ TC0->TC_CHANNEL[0].TC_SR; // read to clear irq pending
+ irq_enable();
+}
diff --git a/src/sam3/serial.c b/src/sam3/serial.c
index b7df5680..c87539ad 100644
--- a/src/sam3/serial.c
+++ b/src/sam3/serial.c
@@ -16,6 +16,12 @@ static Uart * const Port = UART;
static const uint32_t Pmc_id = ID_UART, Irq_id = UART_IRQn;
static const uint32_t rx_pin = GPIO('A', 8);
static const uint32_t tx_pin = GPIO('A', 9);
+#elif CONFIG_MACH_SAM4S8C
+#define Serial_IRQ_Handler UART1_Handler
+static Uart * const Port = UART1;
+static const uint32_t Pmc_id = ID_UART1, Irq_id = UART1_IRQn;
+static const uint32_t rx_pin = GPIO('B', 2);
+static const uint32_t tx_pin = GPIO('B', 3);
#elif CONFIG_MACH_SAM4E8E
#define Serial_IRQ_Handler UART0_Handler
static Uart * const Port = UART0;
diff --git a/src/sam3/spi.c b/src/sam3/spi.c
index 61b773e6..5f79a02c 100644
--- a/src/sam3/spi.c
+++ b/src/sam3/spi.c
@@ -28,6 +28,10 @@ static const struct spi_info spi_bus[] = {
{ USART0, ID_USART0, GPIO('A', 10), GPIO('A', 11), GPIO('A', 17), 'A', 'B'},
{ USART1, ID_USART1, GPIO('A', 12), GPIO('A', 13), GPIO('A', 16), 'A', 'A'},
{ USART2, ID_USART2, GPIO('B', 21), GPIO('B', 20), GPIO('B', 24), 'A', 'A'},
+#elif CONFIG_MACH_SAM4S8C
+ { SPI, ID_SPI, GPIO('A', 12), GPIO('A', 13), GPIO('A', 14), 'A', 'A' },
+ { USART0, ID_USART0, GPIO('A', 5), GPIO('A', 6), GPIO('A', 2), 'A', 'B' },
+ { USART1, ID_USART1, GPIO('A', 21), GPIO('A', 22), GPIO('A', 23), 'A', 'A'},
#elif CONFIG_MACH_SAM4E8E
{ USART0, ID_USART0, GPIO('B', 0), GPIO('B', 1), GPIO('B', 13), 'C', 'C' },
{ USART1, ID_USART1, GPIO('A', 21), GPIO('A', 22), GPIO('A', 23), 'A', 'A'},
diff --git a/test/configs/sam4s8c.config b/test/configs/sam4s8c.config
new file mode 100644
index 00000000..3b032bea
--- /dev/null
+++ b/test/configs/sam4s8c.config
@@ -0,0 +1,3 @@
+# Base config file for Atmel SAM4S8C ARM processor
+CONFIG_MACH_SAM3=y
+CONFIG_MACH_SAM4S8C=y