aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2020-12-05 01:53:33 -0700
committerJosh Rahm <joshuarahm@gmail.com>2020-12-05 01:53:33 -0700
commitde81911ef4c15a9518acf32f61ad2d7d0e2f156f (patch)
tree4ca96493f9b07cb2e63c7d0c4abe49d321ea40d8
parent04da2a442392c5bf3dcf4ca4611f42af7b35e596 (diff)
downloadstm32l4-de81911ef4c15a9518acf32f61ad2d7d0e2f156f.tar.gz
stm32l4-de81911ef4c15a9518acf32f61ad2d7d0e2f156f.tar.bz2
stm32l4-de81911ef4c15a9518acf32f61ad2d7d0e2f156f.zip
Got a very basic external interrupt to work.
-rw-r--r--include/arch/arm/arch.h3
-rw-r--r--include/arch/stm32l4xxx/peripherals/exti.h35
-rw-r--r--include/arch/stm32l4xxx/peripherals/syscfg.h87
-rw-r--r--include/arch/x86_64/arch.h2
-rw-r--r--include/kern/gpio/gpio_manager.h56
-rw-r--r--src/kern/gpio/gpio_manager.c9
-rw-r--r--src/kern/main.c86
-rw-r--r--test_harness/fake_env.c3
-rw-r--r--test_harness/fake_env.h2
9 files changed, 201 insertions, 82 deletions
diff --git a/include/arch/arm/arch.h b/include/arch/arm/arch.h
index e4ebb8d..267621f 100644
--- a/include/arch/arm/arch.h
+++ b/include/arch/arm/arch.h
@@ -44,6 +44,9 @@
#define STACK_TOP (0x2000c000)
#define MPU_BASE (0xE000ED90)
+#define SYSCFG_BASE (0x40010000)
+#define EXTI_BASE (0x40010400)
+
#include <stdint.h>
#ifndef DRY_RUN
_Static_assert(sizeof(void*) == sizeof(uint32_t), "Pointers must be 32 bits");
diff --git a/include/arch/stm32l4xxx/peripherals/exti.h b/include/arch/stm32l4xxx/peripherals/exti.h
new file mode 100644
index 0000000..6776d10
--- /dev/null
+++ b/include/arch/stm32l4xxx/peripherals/exti.h
@@ -0,0 +1,35 @@
+#ifndef PERIPHERALS_EXTI_H_
+#define PERIPHERALS_EXTI_H_
+
+#include "arch.h"
+
+#define EXTI (*(exti_regs_t*)(EXTI_BASE))
+
+typedef struct {
+#define exti_im_n(n) (1 << (n))
+ uint32_t im_r1; /* Interrupt mask register 1. */
+
+#define exti_em_n(n) (1 << (n))
+ uint32_t em_r1; /* Event mask register 1. */
+
+#define exti_rt_n(n) (1 << (n))
+ uint32_t rts_r1; /* Rising trigger selection register 1. */
+
+#define exti_ft_n(n) (1 << (n))
+ uint32_t fts_r1; /* Falling trigger selection register 1. */
+
+#define exti_swi_n(n) (1 << (n))
+ uint32_t swie_r1; /* Software interrupt event register 1. */
+
+#define exti_pif_n(n) (1 << (n))
+ uint32_t p_r1; /* Pending register 1. */
+
+ uint32_t im_r2; /* Interrupt mask register 2. */
+ uint32_t em_r2; /* Event mask register 2. */
+ uint32_t rts_r2; /* Rising trigger selection register 2. */
+ uint32_t fts_r2; /* Falling trigger selection register 2. */
+ uint32_t swie_r2; /* Software interrupt event register 2. */
+ uint32_t p_r2; /* Pending register 2. */
+} exti_regs_t;
+
+#endif /* PERIPHERALS_EXTI_H_ */
diff --git a/include/arch/stm32l4xxx/peripherals/syscfg.h b/include/arch/stm32l4xxx/peripherals/syscfg.h
new file mode 100644
index 0000000..65290a0
--- /dev/null
+++ b/include/arch/stm32l4xxx/peripherals/syscfg.h
@@ -0,0 +1,87 @@
+#ifndef PERIPHERALS_SYSCFG_H_
+#define PERIPHERALS_SYSCFG_H_
+
+#include "arch.h"
+#include "kern/common.h"
+
+#define SYSCFG (*(syscfg_t*)SYSCFG_BASE)
+
+typedef __IO struct {
+#define syscfg_memmode (7 << 0) /* Memory mapping selection. */
+#define syscfg_fbmode (1 << 8) /* Flash bank mode selection. */
+ uint32_t memrmp_r; /* Configuration on memory map. */
+
+#define syscfg_fwdis (1 << 0) /* Disable firewall. */
+#define syscfg_boosten (1 << 8) /* Enable analog boost. */
+#define syscfg_i2c4_fmp \
+ (1 << 23) /* Fast-mode Plus driving capability activation (this bit is only \
+ available on */
+#define syscfg_i2c3_fmp \
+ (1 << 22) /* I2C3 Fast-mode Plus driving capability activation */
+#define syscfg_i2c2_fmp \
+ (1 << 21) /* I2C2 Fast-mode Plus driving capability activation */
+#define syscfg_i2c1_fmp \
+ (1 << 20) /* I2C1 Fast-mode Plus driving capability activation */
+#define syscfg_i2c_pb9_fmp \
+ (1 << 19) /* Fast-mode Plus (Fm+) driving capability activation on PB9 */
+#define syscfg_i2c_pb8_fmp \
+ (1 << 18) /* Fast-mode Plus (Fm+) driving capability activation on PB8 */
+#define syscfg_i2c_pb7_fmp \
+ (1 << 17) /* Fast-mode Plus (Fm+) driving capability activation on PB7 */
+#define syscfg_i2c_pb6_fmp \
+ (1 << 16) /* Fast-mode Plus (Fm+) driving capability activation on PB6 */
+#define syscfg_fpe_ie (0x3f << 26) /* Floating point interrupts enabled. */
+ uint32_t cfg_r1; /* Configuration register 1. */
+
+#define syscfg_exti0 (0xf << 0)
+#define syscfg_exti1 (0xf << 4)
+#define syscfg_exti2 (0xf << 8)
+#define syscfg_exti3 (0xf << 12)
+ uint32_t extic_r1; /* External interrupt configuration register 1. */
+
+#define syscfg_exti4 (0xf << 0)
+#define syscfg_exti5 (0xf << 4)
+#define syscfg_exti6 (0xf << 8)
+#define syscfg_exti7 (0xf << 12)
+ uint32_t extic_r2; /* External interrupt configuration register 2. */
+
+#define syscfg_exti8 (0xf << 0)
+#define syscfg_exti9 (0xf << 4)
+#define syscfg_exti10 (0xf << 8)
+#define syscfg_exti11 (0xf << 12)
+ uint32_t extic_r3; /* External interrupt configuration register 3. */
+
+#define syscfg_exti12 (0xf << 0)
+#define syscfg_exti13 (0xf << 4)
+#define syscfg_exti14 (0xf << 8)
+#define syscfg_exti15 (0xf << 12)
+ uint32_t extic_r4; /* External interrupt configuration register 4. */
+
+#define syscfg_sram2er (1 << 0)
+#define syscfg_sram2bsy (1 << 1)
+ uint32_t scs_r; /* SRAM2 control & status register. */
+
+#define syscfg_spf (1 << 8) /* SRAM2 parity error flag */
+#define syscfg_eccl (1 << 3) /* ECC Lock */
+#define syscfg_pvdl (1 << 2) /* PVD lock enable bit */
+#define syscfg_spl (1 << 1) /* SRAM2 parity lock bit */
+#define syscfg_cll (1 << 0) /* Cortex-M4 LOCKUP (Hardfault) output enable bit */
+ uint32_t cfg_r2; /* Configuration register 2. */
+
+#define syscfg_pnwp(n) (1 << (n)) /* Page n write protection on sram2. */
+ uint32_t swp_r1; /* SRAM2 software protection register 1. */
+
+ union {
+ uint8_t sk_r; /* SRAM2 write protection key for software erase. */
+ uint32_t reserved;
+ };
+
+ uint32_t swp_r2; /* SRAM2 software protection register 2. */
+
+
+} syscfg_t;
+
+static_assert(
+ offsetof(syscfg_t, swp_r2) == 0x28, "Offset check failed");
+
+#endif /* PERIPHERALS_SYSCFG_H_ */
diff --git a/include/arch/x86_64/arch.h b/include/arch/x86_64/arch.h
index ab26d1e..1848b58 100644
--- a/include/arch/x86_64/arch.h
+++ b/include/arch/x86_64/arch.h
@@ -34,6 +34,8 @@
#define SPI3_BASE (load_fake_spi3__())
#define MPU_BASE (load_fake_mpu__())
+#define SYSCFG_BASE (load_fake_syscfg__())
+#define EXTI_BASE (load_fake_exti__())
// Pretend there's a data segement at the start of SRAM1 for more accurate
// testing.
diff --git a/include/kern/gpio/gpio_manager.h b/include/kern/gpio/gpio_manager.h
index 922a423..cb61059 100644
--- a/include/kern/gpio/gpio_manager.h
+++ b/include/kern/gpio/gpio_manager.h
@@ -1,8 +1,8 @@
#ifndef KERN_GPIO_GPIO_MANAGE_H_
#define KERN_GPIO_GPIO_MANAGE_H_
-#include "kern/common.h"
#include "arch/stm32l4xxx/peripherals/gpio.h"
+#include "kern/common.h"
#define GPIO_ERROR_IN_USE 1
#define GPIO_ERROR_INVALID_PIN_FOR_ALTERNATE_FUNCTION 2
@@ -10,8 +10,7 @@
typedef enum {
/* Creates vaules GPIO_PIN_<port><num> i.e. GPIO_PIN_A0 */
-#define PORT(p, pn) \
- GPIO_PIN_P ## p ## pn,
+#define PORT(p, pn) GPIO_PIN_P##p##pn,
#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
#undef PORT
@@ -20,16 +19,14 @@ typedef enum {
/* Alternate functions. */
typedef enum {
-#define AFN(fn, ...) \
- GPIO_ALTERNATE_FUNCTION_ ## fn,
+#define AFN(fn, ...) GPIO_ALTERNATE_FUNCTION_##fn,
#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/afn_table.inc"
#undef AFN
GPIO_ALTERNATE_FUNCTION_EVENTOUT,
} gpio_alternate_function_t;
#define gpio_pin_for_alternate_function(af) ((af) / 16)
-#define gpio_pin_out_of_range(pin) \
- ((pin) < 0 || (pin) >= N_GPIO_PINS)
+#define gpio_pin_out_of_range(pin) ((pin) < 0 || (pin) >= N_GPIO_PINS)
typedef enum {
GPIO_PORT_A,
@@ -83,41 +80,43 @@ typedef enum {
inline static gpio_port_t get_port_for_pin(gpio_pin_t pin)
{
switch (pin) {
-#define PORT(p, pn) \
- case GPIO_PIN_P ## p ## pn: return GPIO_PORT_ ## p;
+#define PORT(p, pn) \
+ case GPIO_PIN_P##p##pn: \
+ return GPIO_PORT_##p;
#include "arch/stm32l4xxx/peripherals/tables/stm32l432xx/gpio/port_table.inc"
#undef PORT
- case N_GPIO_PINS: return N_GPIO_PORTS;
+ case N_GPIO_PINS:
+ return N_GPIO_PORTS;
}
/* Should be unreachable. */
}
-#define DEFAULT_GPIO_OPTS_OUTPUT \
- (gpio_pin_opts_t) { \
- .mode = GPIO_MODE_OUTPUT, \
- .pull_dir = GPIO_PULL_DIR_DOWN, \
- .output_opts.speed = GPIO_OUTPUT_SPEED_MEDIUM, \
- .output_opts.type = GPIO_OUTPUT_TYPE_PUSH_PULL, \
+#define DEFAULT_GPIO_OPTS_OUTPUT \
+ (gpio_pin_opts_t) \
+ { \
+ .mode = GPIO_MODE_OUTPUT, .pull_dir = GPIO_PULL_DIR_DOWN, \
+ .output_opts.speed = GPIO_OUTPUT_SPEED_MEDIUM, \
+ .output_opts.type = GPIO_OUTPUT_TYPE_PUSH_PULL, \
}
-#define DEFAULT_GPIO_OPTS_INPUT \
- (gpio_pin_opts_t) { \
- .mode = GPIO_MODE_OUTPUT, \
- .pull_dir = GPIO_PULL_DIR_DOWN, \
+#define DEFAULT_GPIO_OPTS_INPUT \
+ (gpio_pin_opts_t) \
+ { \
+ .mode = GPIO_MODE_INPUT, .pull_dir = GPIO_PULL_DIR_DOWN, \
}
typedef struct {
- gpio_mode_t mode;
- gpio_pull_dir_t pull_dir;
+ gpio_mode_t mode;
+ gpio_pull_dir_t pull_dir;
union {
struct {
} input_opts;
struct {
- gpio_output_speed_t speed;
- gpio_output_type_t type;
+ gpio_output_speed_t speed;
+ gpio_output_type_t type;
} output_opts;
struct {
@@ -171,9 +170,7 @@ gpio_reserved_pin_t reserve_gpio_pin(
*
*/
gpio_reserved_pin_t gpio_enable_alternate_function(
- gpio_alternate_function_t fn,
- gpio_pin_t hint,
- int* error_out);
+ gpio_alternate_function_t fn, gpio_pin_t hint, int* error_out);
/*
* Releases the GPIO pin so it can be reserved again in the future.
@@ -184,4 +181,9 @@ gpio_reserved_pin_t gpio_enable_alternate_function(
*/
void release_gpio_pin(gpio_reserved_pin_t gpio_pin);
+/*
+ * Returns whether the GPIO pin has high or low input.
+ */
+bool get_gpio_pin_input_state(gpio_reserved_pin_t pin);
+
#endif /* KERN_GPIO_GPIO_MANAGE_H_ */
diff --git a/src/kern/gpio/gpio_manager.c b/src/kern/gpio/gpio_manager.c
index 749ae79..ea720e9 100644
--- a/src/kern/gpio/gpio_manager.c
+++ b/src/kern/gpio/gpio_manager.c
@@ -388,3 +388,12 @@ void set_gpio_pin_low(gpio_reserved_pin_t pin)
regset(portcfg->od_r, (1 << off), 0);
}
+
+bool get_gpio_pin_input_state(gpio_reserved_pin_t pin)
+{
+ int off;
+ gpio_port_config_t* portcfg;
+ get_gpio_pin_port_off(pin.v_, &portcfg, &off);
+
+ return !!regget(portcfg->id_r, (1 << off));
+}
diff --git a/src/kern/main.c b/src/kern/main.c
index fab2eb9..2b97197 100644
--- a/src/kern/main.c
+++ b/src/kern/main.c
@@ -2,9 +2,11 @@
#include "arch/arm/cortex-m4/mpu.h"
#include "arch/stm32l4xxx/peripherals/clock.h"
#include "arch/stm32l4xxx/peripherals/dma.h"
+#include "arch/stm32l4xxx/peripherals/exti.h"
#include "arch/stm32l4xxx/peripherals/irq.h"
#include "arch/stm32l4xxx/peripherals/rcc.h"
#include "arch/stm32l4xxx/peripherals/spi.h"
+#include "arch/stm32l4xxx/peripherals/syscfg.h"
#include "arch/stm32l4xxx/peripherals/system.h"
#include "drv/ws2812B/ws2812b.h"
#include "kern/delay.h"
@@ -82,68 +84,42 @@ static uint32_t bytescale(uint32_t n, uint32_t sc)
/* Main function. This gets executed from the interrupt vector defined above. */
int main()
{
- klogf("Entering main\n");
- gpio_reserved_pin_t sysled = get_sysled();
+ regset(RCC.apb2en_r, rcc_syscfgen, 1);
- systick_add_callback(on_systick, NULL);
- enable_systick(1000);
- configure_gpio();
+ klogf("Entering main\n");
int ec;
- ws2812b_t* drv = ws2812b_new(SPI_SELECT_SPI1, &ec);
-
- if (ec || !drv) {
- panic("Unable to create WS2812b driver :( (%d)\n", ec);
- }
-
-#define SIZE 256
- rgb_t rgb[SIZE];
- for (int i = 0; i < SIZE; ++i) {
- rgb[i].g = 0xff;
- rgb[i].r = 0xff;
- rgb[i].b = 0xff;
- }
+ gpio_reserved_pin_t sysled = get_sysled();
- uint32_t red = 0x40;
- uint32_t green = 0x40;
- uint32_t brightness = 255;
+ gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_INPUT;
+ opts.pull_dir = GPIO_PULL_DIR_NONE;
+ gpio_reserved_pin_t pb6 = reserve_gpio_pin(GPIO_PIN_PB6, &opts, &ec);
- for (int i = 0; i < 100; ++i) {
- ws2812b_write_rgb_sync(drv, 0, 0, 0);
+ if (ec) {
+ panic("Unable to reserve GPIO pin ec=%d\n", ec);
}
- ws2812b_latch(drv);
-
- for (;;) {
- set_gpio_pin_high(sysled);
- ws2812b_latch(drv);
-
- int i;
- for (i = 0; i < SIZE; ++i) {
- red = byte_sin(time / 1000 + i * 4);
- green = 255 - red;
-
- brightness = 3 * byte_sin(time / 5000) / 4 + 63;
-
- /* Add a little white flair that comes around every once in a while. */
- uint32_t white = time / 137 + i * 4;
- if ((white / 256) % 8 == 0) {
- white = amp(byte_sin(white));
- } else {
- white = 0;
- }
-
- ws2812b_write_rgb_sync(
- drv,
- bytescale(min(red + white, 255), brightness),
- bytescale(min(green + white, 255), brightness),
- bytescale(white, brightness));
- }
-
- set_gpio_pin_low(sysled);
-
- ws2812b_latch(drv);
- }
+ // while (1) {
+ // if (get_gpio_pin_input_state(pb6)) {
+ // set_gpio_pin_high(sysled);
+ // } else {
+ // set_gpio_pin_low(sysled);
+ // }
+ // // klogf("GPIO is set? %d\n", get_gpio_pin_input_state(pb6));
+ // }
+
+ regset(SYSCFG.extic_r2, syscfg_exti6, 1 /* Port B. */);
+ regset(EXTI.im_r1, exti_im_n(6), 1); /* Enable the EXTI interrupt. */
+ regset(EXTI.fts_r1, exti_ft_n(6), 1); /* Enable for falling edge. */
+ regset(EXTI.rts_r1, exti_rt_n(6), 1); /* Enable for rising edge. */
+ enable_interrupt(IRQ_EXTI9_5);
+ enable_interrupt(IRQ_EXTI0_IRQ);
+ enable_interrupt(IRQ_EXTI1_IRQ);
+ enable_interrupt(IRQ_EXTI2_IRQ);
+ enable_interrupt(IRQ_EXTI3_IRQ);
+ enable_interrupt(IRQ_EXTI4_IRQ);
+
+ for(;;);
}
#endif
diff --git a/test_harness/fake_env.c b/test_harness/fake_env.c
index 261e9e2..cee7246 100644
--- a/test_harness/fake_env.c
+++ b/test_harness/fake_env.c
@@ -62,3 +62,6 @@ DEFINE_MEMORY_SEGMENT(mpu, 0xE000ED90, 0xE000EDA4)
/* Serial Peripheral Interface */
DEFINE_MEMORY_SEGMENT(spi1, 0x40013000, 0x400133FF)
DEFINE_MEMORY_SEGMENT(spi3, 0x40003C00, 0x40003FFF)
+
+DEFINE_MEMORY_SEGMENT(syscfg, 0x40010000, 0x4001002F)
+DEFINE_MEMORY_SEGMENT(exti, 0x40010400, 0x40010800)
diff --git a/test_harness/fake_env.h b/test_harness/fake_env.h
index b4451df..43097ae 100644
--- a/test_harness/fake_env.h
+++ b/test_harness/fake_env.h
@@ -15,6 +15,8 @@ void* load_fake_rcc__();
void* load_fake_spi1__();
void* load_fake_spi3__();
void* load_fake_mpu__();
+void* load_fake_syscfg__();
+void* load_fake_exti__();
void wipeout_fake_env();