aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-12-28 20:51:34 -0500
committerKevin O'Connor <kevin@koconnor.net>2019-01-07 19:33:26 -0500
commit212813906a7ae3b81b47ac12648f3080ba26dbde (patch)
treefd0a890a7c84fcade4698a5844b53928b6a7b706 /src
parent4683036f98b319d1c36853c1a200d63c36b470ff (diff)
downloadkutter-212813906a7ae3b81b47ac12648f3080ba26dbde.tar.gz
kutter-212813906a7ae3b81b47ac12648f3080ba26dbde.tar.xz
kutter-212813906a7ae3b81b47ac12648f3080ba26dbde.zip
sam3: Merge sam4e_spi.c into spi.c
Determine at runtime if the SPI or USART devices should be used. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src')
-rw-r--r--src/sam3/Makefile7
-rw-r--r--src/sam3/gpio.h2
-rw-r--r--src/sam3/sam4e_spi.c120
-rw-r--r--src/sam3/spi.c227
4 files changed, 193 insertions, 163 deletions
diff --git a/src/sam3/Makefile b/src/sam3/Makefile
index 3f98b28f..97503af4 100644
--- a/src/sam3/Makefile
+++ b/src/sam3/Makefile
@@ -20,15 +20,14 @@ 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
+src-y += sam3/main.c sam3/timer.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 sam3/spi.c
+src-$(CONFIG_MACH_SAM3X8E) += sam3/adc.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/sam4e_spi.c
-src-$(CONFIG_MACH_SAM4E8E) += sam3/sam4_cache.c
+src-$(CONFIG_MACH_SAM4E8E) += sam3/sam4e_afec.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
diff --git a/src/sam3/gpio.h b/src/sam3/gpio.h
index 26a05aff..e106e094 100644
--- a/src/sam3/gpio.h
+++ b/src/sam3/gpio.h
@@ -30,7 +30,7 @@ uint16_t gpio_adc_read(struct gpio_adc g);
void gpio_adc_cancel_sample(struct gpio_adc g);
struct spi_config {
- void *sspi;
+ void *spidev;
uint32_t cfg;
};
struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate);
diff --git a/src/sam3/sam4e_spi.c b/src/sam3/sam4e_spi.c
deleted file mode 100644
index 2648eeff..00000000
--- a/src/sam3/sam4e_spi.c
+++ /dev/null
@@ -1,120 +0,0 @@
-// SAM4e8e SPI port
-//
-// Copyright (C) 2018 Florian Heilmann <Florian.Heilmann@gmx.net>
-//
-// This file may be distributed under the terms of the GNU GPLv3 license.
-
-#include "autoconf.h" // CONFIG_CLOCK_FREQ
-#include "command.h" // shutdown
-#include "gpio.h" // spi_setup
-#include "internal.h" // gpio_peripheral
-#include "sam4e.h" // USART0
-#include "sched.h" // sched_shutdown
-
-#define SSPI_USART0 0
-#define SSPI_USART1 1
-#define SSPI_SPI 2
-
-struct spi_config
-spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
-{
- Usart *p_usart = USART0;
- if (bus > 2) {
- shutdown("Invalid spi_setup parameters");
- }
-
- if (bus == SSPI_USART0) {
- // DUET_USART0_SCK as per dc42 CoreNG
- gpio_peripheral(GPIO('B', 13), 'C', 0);
- // DUET_USART0_MOSI as per dc42 CoreNG
- gpio_peripheral(GPIO('B', 1), 'C', 0);
- // DUET_USART0_MISO as per dc42 CoreNG
- gpio_peripheral(GPIO('B', 0), 'C', 1);
-
- enable_pclock(ID_USART0);
- p_usart = USART0;
- } else if (bus == SSPI_USART1) {
- // DUET_USART1_SCK as per dc42 CoreNG
- gpio_peripheral(GPIO('A', 23), 'A', 0);
- // DUET_USART1_MOSI as per dc42 CoreNG
- gpio_peripheral(GPIO('A', 22), 'A', 0);
- // DUET_USART1_MISO as per dc42 CoreNG
- gpio_peripheral(GPIO('A', 21), 'A', 1);
-
- enable_pclock(ID_USART1);
- p_usart = USART1;
- }
-
- if (bus < 2) {
- p_usart->US_MR = 0;
- p_usart->US_RTOR = 0;
- p_usart->US_TTGR = 0;
-
- p_usart->US_CR = US_CR_RSTTX | US_CR_RSTRX | US_CR_TXDIS | US_CR_RXDIS;
-
- uint32_t br = (CONFIG_CLOCK_FREQ + rate / 2) / rate;
- p_usart-> US_BRGR = br << US_BRGR_CD_Pos;
-
- uint32_t reg = US_MR_CHRL_8_BIT |
- US_MR_USART_MODE_SPI_MASTER |
- US_MR_CLKO |
- US_MR_CHMODE_NORMAL;
- switch (mode) {
- case 0:
- reg |= US_MR_CPHA;
- reg &= ~US_MR_CPOL;
- break;
- case 1:
- reg &= ~US_MR_CPHA;
- reg &= ~US_MR_CPOL;
- break;
- case 2:
- reg |= US_MR_CPHA;
- reg |= US_MR_CPOL;
- break;
- case 3:
- reg &= ~US_MR_CPHA;
- reg |= US_MR_CPOL;
- break;
- }
-
- p_usart->US_MR |= reg;
- p_usart->US_CR = US_CR_RXEN | US_CR_TXEN;
- return (struct spi_config){ .sspi=p_usart, .cfg=p_usart->US_MR };
- }
-
- // True SPI implementation still ToDo
- return (struct spi_config){ .sspi = 0, .cfg=0};
-}
-
-void
-spi_transfer(struct spi_config config, uint8_t receive_data
- , uint8_t len, uint8_t *data)
-{
- if ((config.sspi == USART0) || (config.sspi == USART1)) {
- Usart *p_usart = config.sspi;
- if (receive_data) {
- for (uint32_t i = 0; i < len; ++i) {
- uint32_t co = (uint32_t)*data & 0x000000FF;
- while(!(p_usart->US_CSR & US_CSR_TXRDY)) {}
- p_usart->US_THR = US_THR_TXCHR(co);
- uint32_t ci = 0;
- while(!(p_usart->US_CSR & US_CSR_RXRDY)) {}
- ci = p_usart->US_RHR & US_RHR_RXCHR_Msk;
- *data++ = (uint8_t)ci;
- }
- } else {
- for (uint32_t i = 0; i < len; ++i) {
- uint32_t co = (uint32_t)*data & 0x000000FF;
- while(!(p_usart->US_CSR & US_CSR_TXRDY)) {}
- p_usart->US_THR = US_THR_TXCHR(co);
- while(!(p_usart->US_CSR & US_CSR_RXRDY)) {}
- (void)(p_usart->US_RHR & US_RHR_RXCHR_Msk);
- (void)*data++;
- }
- }
- }
-}
-
-void
-spi_prepare(struct spi_config config) {}
diff --git a/src/sam3/spi.c b/src/sam3/spi.c
index a92a766b..0c96baca 100644
--- a/src/sam3/spi.c
+++ b/src/sam3/spi.c
@@ -1,6 +1,8 @@
// SPI transmissions on sam3
//
// Copyright (C) 2018 Petri Honkala <cruwaller@gmail.com>
+// Copyright (C) 2018 Florian Heilmann <Florian.Heilmann@gmx.net>
+// Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
@@ -9,54 +11,88 @@
#include "internal.h" // gpio_peripheral
#include "sched.h" // sched_shutdown
-#define REGPTR SPI0
-#define PERIPH_ID ID_SPI0
-#define CHANNEL 0 // Use same channel for all
+/****************************************************************
+ * SPI/USART buses and pins
+ ****************************************************************/
+
+struct spi_info {
+ void *dev;
+ uint32_t dev_id;
+ uint8_t miso_pin, mosi_pin, sck_pin, rxtx_periph, sck_periph;
+};
+
+static const struct spi_info spi_bus[] = {
+#if CONFIG_MACH_SAM3X8E
+ { SPI0, ID_SPI0, GPIO('A', 25), GPIO('A', 26), GPIO('A', 27), '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'},
+#endif
+};
+
+static int
+is_spihw(void *dev)
+{
+#if CONFIG_MACH_SAM3X8E
+ return dev == SPI0;
+#else
+ return dev == SPI;
+#endif
+}
static void
-spi_init(void)
+init_pins(uint32_t bus)
{
- /* Configure SCK, MISO and MOSI */
- gpio_peripheral(GPIO('A', 25), 'A', 0); // Arduino 74
- gpio_peripheral(GPIO('A', 26), 'A', 0); // Arduino 75
- gpio_peripheral(GPIO('A', 27), 'A', 0); // Arduino 76
+ const struct spi_info *si = &spi_bus[bus];
+ gpio_peripheral(si->sck_pin, si->sck_periph, 0);
+ gpio_peripheral(si->miso_pin, si->rxtx_periph, 1);
+ gpio_peripheral(si->mosi_pin, si->rxtx_periph, 0);
+ enable_pclock(si->dev_id);
+}
- // Enable SPI clocks
- enable_pclock(PERIPH_ID);
+
+/****************************************************************
+ * SPI hardware
+ ****************************************************************/
+
+#define CHANNEL 0 // Use same channel for all
+
+static void
+spihw_init(uint32_t bus)
+{
+ init_pins(bus);
+ Spi *pSpi = spi_bus[bus].dev;
/* Disable SPI */
- REGPTR->SPI_CR = SPI_CR_SPIDIS;
+ pSpi->SPI_CR = SPI_CR_SPIDIS;
/* Execute a software reset of the SPI twice */
- REGPTR->SPI_CR = SPI_CR_SWRST;
- REGPTR->SPI_CR = SPI_CR_SWRST;
+ pSpi->SPI_CR = SPI_CR_SWRST;
+ pSpi->SPI_CR = SPI_CR_SWRST;
- REGPTR->SPI_MR = ( SPI_MR_MSTR | // Set master mode
- SPI_MR_MODFDIS | // Disable fault detection
- SPI_MR_PCS(CHANNEL) // Fixes peripheral select
- );
- REGPTR->SPI_IDR = 0xffffffff; // Disable ISRs
+ pSpi->SPI_MR = ( SPI_MR_MSTR | // Set master mode
+ SPI_MR_MODFDIS | // Disable fault detection
+ SPI_MR_PCS(CHANNEL) // Fixes peripheral select
+ );
+ pSpi->SPI_IDR = 0xffffffff; // Disable ISRs
/* Clear Chip Select Registers */
- REGPTR->SPI_CSR[0] = 0;
- REGPTR->SPI_CSR[1] = 0;
- REGPTR->SPI_CSR[2] = 0;
- REGPTR->SPI_CSR[3] = 0;
+ pSpi->SPI_CSR[0] = 0;
+ pSpi->SPI_CSR[1] = 0;
+ pSpi->SPI_CSR[2] = 0;
+ pSpi->SPI_CSR[3] = 0;
/* Set basic channel config */
- REGPTR->SPI_CSR[CHANNEL] = 0;
+ pSpi->SPI_CSR[CHANNEL] = 0;
/* Enable SPI */
- REGPTR->SPI_CR = SPI_CR_SPIEN;
+ pSpi->SPI_CR = SPI_CR_SPIEN;
}
-struct spi_config
-spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
+static struct spi_config
+spihw_setup(uint32_t bus, uint8_t mode, uint32_t rate)
{
- if (bus != CHANNEL)
- shutdown("Invalid spi_setup parameters");
-
// Make sure bus is enabled
- spi_init();
+ spihw_init(bus);
uint32_t config = 0;
uint32_t clockDiv;
@@ -90,20 +126,21 @@ spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
};
config |= ((clockDiv & 0xffu) << SPI_CSR_SCBR_Pos);
- return (struct spi_config){.cfg = config};
+ return (struct spi_config){ .spidev = spi_bus[bus].dev, .cfg = config };
}
-void
-spi_prepare(struct spi_config config)
+static void
+spihw_prepare(struct spi_config config)
{
- REGPTR->SPI_CSR[CHANNEL] = config.cfg;
+ Spi *pSpi = config.spidev;
+ pSpi->SPI_CSR[CHANNEL] = config.cfg;
}
-void
-spi_transfer(struct spi_config config, uint8_t receive_data
- , uint8_t len, uint8_t *data)
+static void
+spihw_transfer(struct spi_config config, uint8_t receive_data
+ , uint8_t len, uint8_t *data)
{
- Spi* const pSpi = REGPTR;
+ Spi *pSpi = config.spidev;
if (receive_data) {
while (len--) {
pSpi->SPI_TDR = *data;
@@ -124,3 +161,117 @@ spi_transfer(struct spi_config config, uint8_t receive_data
}
}
}
+
+
+/****************************************************************
+ * USART hardware
+ ****************************************************************/
+
+static struct spi_config
+usart_setup(uint32_t bus, uint8_t mode, uint32_t rate)
+{
+ init_pins(bus);
+ Usart *p_usart = spi_bus[bus].dev;
+
+ p_usart->US_MR = 0;
+ p_usart->US_RTOR = 0;
+ p_usart->US_TTGR = 0;
+
+ p_usart->US_CR = US_CR_RSTTX | US_CR_RSTRX | US_CR_TXDIS | US_CR_RXDIS;
+
+ uint32_t br = DIV_ROUND_UP(CHIP_FREQ_CPU_MAX, rate);
+ p_usart->US_BRGR = br << US_BRGR_CD_Pos;
+
+ uint32_t reg = US_MR_CHRL_8_BIT |
+ US_MR_USART_MODE_SPI_MASTER |
+ US_MR_CLKO |
+ US_MR_CHMODE_NORMAL;
+ switch (mode) {
+ case 0:
+ reg |= US_MR_CPHA;
+ reg &= ~US_MR_CPOL;
+ break;
+ case 1:
+ reg &= ~US_MR_CPHA;
+ reg &= ~US_MR_CPOL;
+ break;
+ case 2:
+ reg |= US_MR_CPHA;
+ reg |= US_MR_CPOL;
+ break;
+ case 3:
+ reg &= ~US_MR_CPHA;
+ reg |= US_MR_CPOL;
+ break;
+ }
+
+ p_usart->US_MR |= reg;
+ p_usart->US_CR = US_CR_RXEN | US_CR_TXEN;
+ return (struct spi_config){ .spidev=p_usart, .cfg=p_usart->US_MR };
+}
+
+static void
+usart_prepare(struct spi_config config)
+{
+}
+
+static void
+usart_transfer(struct spi_config config, uint8_t receive_data
+ , uint8_t len, uint8_t *data)
+{
+ Usart *p_usart = config.spidev;
+ if (receive_data) {
+ for (uint32_t i = 0; i < len; ++i) {
+ uint32_t co = (uint32_t)*data & 0x000000FF;
+ while(!(p_usart->US_CSR & US_CSR_TXRDY)) {}
+ p_usart->US_THR = US_THR_TXCHR(co);
+ uint32_t ci = 0;
+ while(!(p_usart->US_CSR & US_CSR_RXRDY)) {}
+ ci = p_usart->US_RHR & US_RHR_RXCHR_Msk;
+ *data++ = (uint8_t)ci;
+ }
+ } else {
+ for (uint32_t i = 0; i < len; ++i) {
+ uint32_t co = (uint32_t)*data & 0x000000FF;
+ while(!(p_usart->US_CSR & US_CSR_TXRDY)) {}
+ p_usart->US_THR = US_THR_TXCHR(co);
+ while(!(p_usart->US_CSR & US_CSR_RXRDY)) {}
+ (void)(p_usart->US_RHR & US_RHR_RXCHR_Msk);
+ (void)*data++;
+ }
+ }
+}
+
+
+/****************************************************************
+ * Interface
+ ****************************************************************/
+
+struct spi_config
+spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
+{
+ if (bus >= ARRAY_SIZE(spi_bus))
+ shutdown("Invalid spi bus");
+ if (is_spihw(spi_bus[bus].dev))
+ return spihw_setup(bus, mode, rate);
+ return usart_setup(bus, mode, rate);
+}
+
+void
+spi_prepare(struct spi_config config)
+{
+ if (is_spihw(config.spidev))
+ spihw_prepare(config);
+ else
+ usart_prepare(config);
+}
+
+void
+spi_transfer(struct spi_config config, uint8_t receive_data
+ , uint8_t len, uint8_t *data)
+{
+ if (is_spihw(config.spidev))
+ spihw_transfer(config, receive_data, len, data);
+ else
+ usart_transfer(config, receive_data, len, data);
+}