aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--02-usart/include/arch/arm/arch.h3
-rw-r--r--02-usart/include/arch/x86_64/arch.h3
-rw-r--r--02-usart/include/core/spi.h102
-rw-r--r--02-usart/test_harness/fake_env.c4
-rw-r--r--02-usart/test_harness/fake_env.h2
-rw-r--r--02-usart/tests/test_spi.c11
6 files changed, 125 insertions, 0 deletions
diff --git a/02-usart/include/arch/arm/arch.h b/02-usart/include/arch/arm/arch.h
index f140c97..42b33bb 100644
--- a/02-usart/include/arch/arm/arch.h
+++ b/02-usart/include/arch/arm/arch.h
@@ -28,6 +28,9 @@
#define NVIC_BASE (0xE000E004)
#define RCC_BASE (0x40021000)
+#define SPI1_BASE (0x40013000)
+#define SPI3_BASE (0x40003C00)
+
#include <stdint.h>
#ifndef DRY_RUN
_Static_assert(sizeof(void*) == sizeof(uint32_t), "Pointers must be 32 bits");
diff --git a/02-usart/include/arch/x86_64/arch.h b/02-usart/include/arch/x86_64/arch.h
index e87559b..5e1217c 100644
--- a/02-usart/include/arch/x86_64/arch.h
+++ b/02-usart/include/arch/x86_64/arch.h
@@ -24,6 +24,9 @@
#define SYSTEM_CONFIG_BLOCK_BASE (load_fake_scb__())
#define NVIC_BASE (load_fake_nvic__())
+#define SPI1_BASE (load_fake_spi1__())
+#define SPI3_BASE (load_fake_spi3__())
+
// Pretend there's a data segement at the start of SRAM1 for more accurate
// testing.
#define GHOST_DATA_SEGMENT_SIZE 1234
diff --git a/02-usart/include/core/spi.h b/02-usart/include/core/spi.h
new file mode 100644
index 0000000..77cd61e
--- /dev/null
+++ b/02-usart/include/core/spi.h
@@ -0,0 +1,102 @@
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#include "common.h"
+#include "arch.h"
+
+#define SPI1 (*((spi_t*)(SPI1_BASE)))
+#define SPI3 (*((spi_t*)(SPI3_BASE)))
+
+typedef enum {
+ SPI_BAUD_FPCLK_DIV_2 = 0,
+ SPI_BAUD_FPCLK_DIV_4 = 1,
+ SPI_BAUD_FPCLK_DIV_8 = 2,
+ SPI_BAUD_FPCLK_DIV_16 = 3,
+ SPI_BAUD_FPCLK_DIV_32 = 4,
+ SPI_BAUD_FPCLK_DIV_64 = 5,
+ SPI_BAUD_FPCLK_DIV_128 = 6,
+ SPI_BAUD_FPCLK_DIV_256 = 7,
+} spi_baud_rate_t;
+
+typedef enum {
+ SPI_DATA_SIZE_NOT_USED_0 = 0,
+ SPI_DATA_SIZE_NOT_USED_1 = 1,
+ SPI_DATA_SIZE_NOT_USED_2 = 2,
+ SPI_DATA_SIZE_4_BITS = 3,
+ SPI_DATA_SIZE_5_BITS = 4,
+ SPI_DATA_SIZE_6_BITS = 5,
+ SPI_DATA_SIZE_7_BITS = 6,
+ SPI_DATA_SIZE_8_BITS = 7,
+ SPI_DATA_SIZE_9_BITS = 8,
+ SPI_DATA_SIZE_10_BITS = 9,
+ SPI_DATA_SIZE_11_BITS = 10,
+ SPI_DATA_SIZE_12_BITS = 11,
+ SPI_DATA_SIZE_13_BITS = 12,
+ SPI_DATA_SIZE_14_BITS = 13,
+ SPI_DATA_SIZE_15_BITS = 14,
+ SPI_DATA_SIZE_16_BITS = 15,
+} spi_data_size_t;
+
+typedef __IO struct {
+ /* spi control register. */
+#define spi_bidimode (1 << 15) /* Bidirectional data mode enable. */
+#define spi_bidioe (1 << 14) /* Output enable in bidirectional mode */
+#define spi_crcen (1 << 13) /* Hardware CRC calculation enable */
+#define spi_crcnext (1 << 12) /* Transmit CRC next */
+#define spi_crcl (1 << 11) /* CRC length */
+#define spi_rxonly (1 << 10) /* Receive only mode enabled. */
+#define spi_ssm (1 << 9) /* Software slave management */
+#define spi_ssi (1 << 8) /* Internal slave select */
+#define spi_lsbfirst (1 << 7) /* Frame format */
+#define spi_spe (1 << 6) /* SPI enable */
+#define spi_br (7 << 3) /* SPI enable */
+#define spi_mstr (1 << 2) /* Master selection */
+#define spi_cpol (1 << 1) /* Clock polarity */
+#define spi_cpha (1 << 0) /* Clock phase */
+ uint32_t c_r1;
+
+ /* spi control register #2 */
+#define spi_ldma_tx (1 << 14) /* Last DMA transfer for transmission */
+#define spi_ldma_rx (1 << 13) /* Last DMA transfer for reception */
+#define spi_frxth (1 << 12) /* FIFO reception threshold */
+#define spi_ds (0xF << 8) /* Data size */
+#define spi_txeie (1 << 7) /* Tx buffer empty interrupt enable */
+#define spi_rxneie (1 << 6) /* RX buffer not empty interrupt enable */
+#define spi_errie (1 << 5) /* Error interrupt enable */
+#define spi_frf (1 << 4) /* Frame format */
+#define spi_nssp (1 << 3) /*: NSS pulse management */
+#define spi_ssoe (1 << 2) /* SS output enable */
+#define spi_txdmaen (1 << 1) /* Tx buffer DMA enable */
+#define spi_rxdmaen (1 << 0) /* Rx buffer DMA enable */
+ uint32_t c_r2;
+
+ /* spi status register. */
+#define spi_ftlvl (3 << 11) /* Transmisison level */
+#define spi_frlvl (3 << 9) /* Reception level */
+#define spi_fre (1 << 8) /* Frame format error */
+#define spi_bsy (1 << 7) /* Busy flag */
+#define spi_ovr (1 << 6) /* Overrun flag */
+#define spi_modf (1 << 5) /* Mode fault */
+#define spi_crcerr (1 << 4) /* CRC error flag */
+#define spi_txe (1 << 1) /* Transmit buffer empty */
+#define spi_rxne (1 << 0) /* Receive buffer not empty */
+ uint32_t s_r;
+
+ /* spi data register. Really only the least-significant 16 bits are used.
+ * reading from this register reads from the Rx FIFO while writing to it
+ * writes to the Tx FIFO. */
+ __IO uint32_t d_r;
+
+ /* spi CRC polynomial register. */
+ uint32_t crcp_r;
+
+ /* spi rx CRC register. */
+ uint32_t rxcrc_r;
+
+ /* spi tx CRC register. */
+ uint32_t txcrc_r;
+} spi_t;
+
+static_assert(offsetof(spi_t, txcrc_r) == 0x18, "Offset check failed.");
+
+#endif /* CORE_SPI_H_ */
diff --git a/02-usart/test_harness/fake_env.c b/02-usart/test_harness/fake_env.c
index 43a6caa..3175317 100644
--- a/02-usart/test_harness/fake_env.c
+++ b/02-usart/test_harness/fake_env.c
@@ -35,3 +35,7 @@ DEFINE_MEMORY_SEGMENT(nvic, 0xE000E004, 0xE000E4F0)
/* SRAM */
DEFINE_MEMORY_SEGMENT(sram1, 0x20000000, 0x2000C000)
DEFINE_MEMORY_SEGMENT(sram2, 0x2000C000, 0x20018000)
+
+/* Serial Peripheral Interface */
+DEFINE_MEMORY_SEGMENT(spi1, 0x40013000, 0x400133FF)
+DEFINE_MEMORY_SEGMENT(spi3, 0x40003C00, 0x40003FFF)
diff --git a/02-usart/test_harness/fake_env.h b/02-usart/test_harness/fake_env.h
index 787abf5..73323cf 100644
--- a/02-usart/test_harness/fake_env.h
+++ b/02-usart/test_harness/fake_env.h
@@ -12,5 +12,7 @@ void* load_fake_sram2__();
void* load_fake_scb__();
void* load_fake_nvic__();
void* load_fake_rcc__();
+void* load_fake_spi1__();
+void* load_fake_spi3__();
#endif /* FAKE_ENV_H_ */
diff --git a/02-usart/tests/test_spi.c b/02-usart/tests/test_spi.c
new file mode 100644
index 0000000..d6cc24e
--- /dev/null
+++ b/02-usart/tests/test_spi.c
@@ -0,0 +1,11 @@
+#include "test_harness.h"
+
+#include "core/spi.h"
+
+TEST(spi, smoke)
+{
+ __IO spi_t* spi = &SPI1;
+ spi->s_r = 1;
+
+ return 0;
+}