From de81911ef4c15a9518acf32f61ad2d7d0e2f156f Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sat, 5 Dec 2020 01:53:33 -0700 Subject: Got a very basic external interrupt to work. --- include/arch/arm/arch.h | 3 + include/arch/stm32l4xxx/peripherals/exti.h | 35 +++++++++++ include/arch/stm32l4xxx/peripherals/syscfg.h | 87 ++++++++++++++++++++++++++++ include/arch/x86_64/arch.h | 2 + include/kern/gpio/gpio_manager.h | 56 +++++++++--------- 5 files changed, 156 insertions(+), 27 deletions(-) create mode 100644 include/arch/stm32l4xxx/peripherals/exti.h create mode 100644 include/arch/stm32l4xxx/peripherals/syscfg.h (limited to 'include') 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 #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_ 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_ */ -- cgit From 23fe71639ecdc20a472130de6a2b8d71d8e5d2b0 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sat, 5 Dec 2020 16:03:09 -0700 Subject: Add array_list.h --- include/shared/array_list.h | 105 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 include/shared/array_list.h (limited to 'include') diff --git a/include/shared/array_list.h b/include/shared/array_list.h new file mode 100644 index 0000000..8b942ad --- /dev/null +++ b/include/shared/array_list.h @@ -0,0 +1,105 @@ +#ifndef SHARED_ARRAY_LIST_H_ +#define SHARED_ARRAY_LIST_H_ + +#include "kern/common.h" +#include "kern/mem.h" + +#define ALLOC kalloc +#define FREE kfree + +#define array_list_t(type) array_list_##type##_t +#define array_list_new(type) array_list_##type##_new +#define array_list_length(type) array_list_##type##_length +#define array_list_reserve(type) array_list_##type##_reserve +#define array_list_add(type) array_list_##type##_add +#define array_list_remove(type) array_list_##type##remove +#define array_list_ref(type) array_list_##type##_get +#define array_list_free(type) array_list_##type##_free + +#define array_list_foreach(ar, val) \ + typeof((ar)->elements[0]) val; \ + if ((ar)->size > 0) val = (ar)->elements[0]; \ + for (size_t _idx_ = 0; _idx_ < (ar)->size; \ + val = (++_idx_) >= (ar)->size ? val : (ar)->elements[_idx_]) + +#define ARRAY_LIST_DECL(type) \ + typedef struct { \ + size_t reserved; \ + size_t size; \ + type* elements; \ + } array_list_t(type); \ + size_t array_list_length(type)(const array_list_t(type)*); \ + array_list_t(type) * array_list_new(type)(); \ + bool array_list_reserve(type)(array_list_t(type)*, size_t len); \ + bool array_list_add(type)(array_list_t(type)*, type val); \ + bool array_list_remove(type)(array_list_t(type)*, size_t idx, type * out); \ + type* array_list_ref(type)(array_list_t(type)*, size_t idx); \ + void array_list_free(type)(array_list_t(type)*); + +#define ARRAY_LIST_IMPL(type) \ + array_list_t(type) * array_list_new(type)() \ + { \ + array_list_t(type)* ret = ALLOC(sizeof(array_list_t(type))); \ + ret->size = 0; \ + ret->reserved = 0; \ + ret->elements = NULL; \ + return ret; \ + } \ + size_t array_list_length(type)(const array_list_t(type) * lst) \ + { \ + return lst->size; \ + } \ + bool array_list_reserve(type)(array_list_t(type) * lst, size_t newlen) \ + { \ + if (lst->reserved < newlen) { \ + type* new_arr = ALLOC(sizeof(type) * newlen); \ + if (!new_arr) { \ + return 0; \ + } \ + for (size_t i = 0; i < lst->size; ++i) { \ + new_arr[i] = lst->elements[i]; \ + } \ + FREE(lst->elements); \ + lst->elements = new_arr; \ + lst->reserved = newlen; \ + } \ + return 1; \ + } \ + bool array_list_add(type)(array_list_t(type) * lst, type v) \ + { \ + if (lst->size == lst->reserved) { \ + if (!array_list_reserve(type)( \ + lst, lst->reserved == 0 ? 4 : lst->reserved * 2)) { \ + return 0; \ + } \ + } \ + lst->elements[lst->size++] = v; \ + return 1; \ + } \ + bool array_list_remove(type)( \ + array_list_t(type) * lst, size_t idx, type * out) \ + { \ + if (idx >= lst->size) { \ + return 0; \ + } \ + if (out) *out = lst->elements[idx]; \ + for (size_t i = idx; i < lst->size - 1; ++i) { \ + lst->elements[i] = lst->elements[i + 1]; \ + } \ + lst->size--; \ + return 1; \ + } \ + type* array_list_ref(type)(array_list_t(type) * lst, size_t idx) \ + { \ + if (idx >= lst->size) { \ + return NULL; \ + } \ + return &lst->elements[idx]; \ + } \ + void array_list_free(type)(array_list_t(type) * lst) \ + { \ + FREE(lst->elements); \ + FREE(lst); \ + } + +#endif /* SHARED_ARRAY_LIST_H_ */ -- cgit From d29ea8d7fb8cc6f7c3dda1cbca6266908acd4291 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sat, 5 Dec 2020 16:25:27 -0700 Subject: Add remove ability to linked list. --- include/shared/linked_list.h | 277 +++++++++++++++++++++++++++---------------- 1 file changed, 173 insertions(+), 104 deletions(-) (limited to 'include') diff --git a/include/shared/linked_list.h b/include/shared/linked_list.h index 3f8e075..ec72377 100644 --- a/include/shared/linked_list.h +++ b/include/shared/linked_list.h @@ -1,15 +1,21 @@ #ifndef SHARED_LINKED_LIST_H_ #define SHARED_LINKED_LIST_H_ -#define linked_list_t(type) linked_list_##type##_t -#define linked_list_node_t(type) linked_list_node_##type##_t -#define linked_list_push_back(type) linked_list_push_back_##type -#define linked_list_push_front(type) linked_list_push_front_##type -#define linked_list_pop_front(type) linked_list_pop_front_##type -#define linked_list_pop_back(type) linked_list_pop_back_##type -#define linked_list_front(type) linked_list_front_##type -#define linked_list_back(type) linked_list_back_##type -#define linked_list_length(type) linked_list_length_##type +#include "kern/common.h" + +#define linked_list_t(T) linked_list___##T##___t +#define linked_list_node_t(T) linked_list_node___##T##___t +#define linked_list_itr_t(T) linked_list_node_itr___##T##___t +#define linked_list_push_back(T) linked_list_push_back___##T +#define linked_list_push_front(T) linked_list_push_front___##T +#define linked_list_pop_front(T) linked_list_pop_front___##T +#define linked_list_pop_back(T) linked_list_pop_back___##T +#define linked_list_front(T) linked_list_front___##T +#define linked_list_back(T) linked_list_back___##T +#define linked_list_length(T) linked_list_length___##T +#define linked_list_find_match(T) linked_list_find_match___##T +#define linked_list_remove_first_match(T) linked_list_remove_first_match___##T +#define linked_list_remove(T) linked_list_remove___##T #define LINKED_LIST_INIT \ { \ @@ -24,108 +30,171 @@ #define NO_ATTRIBUTE -#define LINKED_LIST_DECL(type) LINKED_LIST_INTERNAL_DECL(type, NO_ATTRIBUTE) +#define LINKED_LIST_DECL(T) LINKED_LIST_INTERNAL_DECL(T, NO_ATTRIBUTE) -#define LINKED_LIST_STATIC_DECL(type) LINKED_LIST_INTERNAL_DECL(type, static) +#define LINKED_LIST_STATIC_DECL(T) LINKED_LIST_INTERNAL_DECL(T, static inline) -#define LINKED_LIST_INTERNAL_DECL(type, attr) \ - typedef struct LINKED_LIST_NODE_##type { \ - type value; \ - struct LINKED_LIST_NODE_##type* next; \ - } linked_list_node_t(type); \ +#define LINKED_LIST_INTERNAL_DECL(T, attr) \ + typedef struct LINKED_LIST_NODE_##T { \ + T value; \ + struct LINKED_LIST_NODE_##T* next; \ + } linked_list_node_t(T); \ + \ + typedef struct { \ + linked_list_node_t(T) * prev; \ + linked_list_node_t(T) * cur; \ + } linked_list_itr_t(T); \ \ typedef struct { \ - linked_list_node_t(type) * head; \ - } linked_list_t(type); \ + linked_list_node_t(T) * head; \ + } linked_list_t(T); \ \ - attr void linked_list_push_back(type)(linked_list_t(type) * ll, type value); \ - attr void linked_list_push_front(type)( \ - linked_list_t(type) * ll, type value); \ - attr void linked_list_pop_back(type)(linked_list_t(type) * ll); \ - attr void linked_list_pop_front(type)(linked_list_t(type) * ll); \ - attr type* linked_list_front(type)(linked_list_t(type) * ll); \ - attr type* linked_list_back(type)(linked_list_t(type) * ll); + attr void linked_list_push_back(T)(linked_list_t(T) * ll, T value); \ + attr void linked_list_push_front(T)(linked_list_t(T) * ll, T value); \ + attr void linked_list_pop_back(T)(linked_list_t(T) * ll); \ + attr void linked_list_pop_front(T)(linked_list_t(T) * ll); \ + attr size_t linked_list_length(T)(const linked_list_t(T) * ll); \ + attr T* linked_list_front(T)(const linked_list_t(T) * ll); \ + attr bool linked_list_find_match(T)( \ + const linked_list_t(T) * ll, \ + linked_list_itr_t(T) * itr_out, \ + bool (*match)(T, void*), \ + void* closure); \ + attr bool linked_list_remove_first_match(T)( \ + linked_list_t(T) * ll, T * out, bool (*match)(T, void*), void* closure); \ + attr T* linked_list_back(T)(const linked_list_t(T) * ll); -#define LINKED_LIST_IMPL(type) LINKED_LIST_INTERNAL_IMPL(type, NO_ATTRIBUTE) +#define LINKED_LIST_IMPL(T) LINKED_LIST_INTERNAL_IMPL(T, NO_ATTRIBUTE) -#define LINKED_LIST_STATIC_IMPL(type) LINKED_LIST_INTERNAL_IMPL(type, static) +#define LINKED_LIST_STATIC_IMPL(T) LINKED_LIST_INTERNAL_IMPL(T, static inline) -#define LINKED_LIST_INTERNAL_IMPL(type, attr) \ - attr void linked_list_push_back(type)(linked_list_t(type) * ll, type value) \ - { \ - if (!ll->head) { \ - ll->head = kalloc(sizeof(linked_list_node_t(type))); \ - ll->head->value = value; \ - ll->head->next = NULL; \ - } else { \ - linked_list_node_t(type)* c = ll->head; \ - while (c->next) c = c->next; \ - c->next = kalloc(sizeof(linked_list_node_t(type))); \ - c->next->next = NULL; \ - c->next->value = value; \ - } \ - } \ - attr void linked_list_push_front(type)(linked_list_t(type) * ll, type value) \ - { \ - if (!ll->head) { \ - ll->head = kalloc(sizeof(linked_list_node_t(type))); \ - ll->head->value = value; \ - ll->head->next = NULL; \ - } else { \ - linked_list_node_t(type)* node = \ - kalloc(sizeof(linked_list_node_t(type))); \ - node->next = ll->head; \ - node->value = value; \ - ll->head = node; \ - } \ - } \ - attr void linked_list_pop_back(type)(linked_list_t(type) * ll) \ - { \ - if (!ll->head) { \ - return; \ - } \ - if (!ll->head->next) { \ - kfree(ll->head); \ - ll->head = NULL; \ - return; \ - } \ - linked_list_node_t(type)* c = ll->head; \ - while (c->next->next) c = c->next; \ - kfree(c->next); \ - c->next = NULL; \ - return; \ - } \ - attr void linked_list_pop_front(type)(linked_list_t(type) * ll) \ - { \ - if (!ll->head) { \ - return; \ - } \ - linked_list_node_t(type)* node = ll->head; \ - ll->head = node->next; \ - kfree(node); \ - } \ - attr type* linked_list_front(type)(linked_list_t(type) * ll) \ - { \ - if (!ll->head) { \ - return NULL; \ - } \ - return &ll->head->value; \ - } \ - attr type* linked_list_back(type)(linked_list_t(type) * ll) \ - { \ - if (!ll->head) { \ - return NULL; \ - } \ - linked_list_node_t(type)* cur = ll->head; \ - while (cur->next) cur = cur->next; \ - return &cur->value; \ - } \ - attr size_t linked_list_length(type)(linked_list_t(type) * ll) \ - { \ - linked_list_node_t(type) * cur; \ - size_t ret = 0; \ - for (cur = ll->head; cur; cur = cur->next) ++ret; \ - return ret; \ - } +#define PRAGMA(x) _Pragma(#x) +#define LINKED_LIST_INTERNAL_IMPL(T, attr) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wunused-function\"") \ + attr void linked_list_push_back(T)(linked_list_t(T) * ll, T value) \ + { \ + if (!ll->head) { \ + ll->head = kalloc(sizeof(linked_list_node_t(T))); \ + ll->head->value = value; \ + ll->head->next = NULL; \ + } else { \ + linked_list_node_t(T)* c = ll->head; \ + while (c->next) c = c->next; \ + c->next = kalloc(sizeof(linked_list_node_t(T))); \ + c->next->next = NULL; \ + c->next->value = value; \ + } \ + } \ + attr void linked_list_push_front(T)(linked_list_t(T) * ll, T value) \ + { \ + if (!ll->head) { \ + ll->head = kalloc(sizeof(linked_list_node_t(T))); \ + ll->head->value = value; \ + ll->head->next = NULL; \ + } else { \ + linked_list_node_t(T)* node = kalloc(sizeof(linked_list_node_t(T))); \ + node->next = ll->head; \ + node->value = value; \ + ll->head = node; \ + } \ + } \ + attr void linked_list_pop_back(T)(linked_list_t(T) * ll) \ + { \ + if (!ll->head) { \ + return; \ + } \ + if (!ll->head->next) { \ + kfree(ll->head); \ + ll->head = NULL; \ + return; \ + } \ + linked_list_node_t(T)* c = ll->head; \ + while (c->next->next) c = c->next; \ + kfree(c->next); \ + c->next = NULL; \ + return; \ + } \ + attr void linked_list_pop_front(T)(linked_list_t(T) * ll) \ + { \ + if (!ll->head) { \ + return; \ + } \ + linked_list_node_t(T)* node = ll->head; \ + ll->head = node->next; \ + kfree(node); \ + } \ + attr T* linked_list_front(T)(const linked_list_t(T) * ll) \ + { \ + if (!ll->head) { \ + return NULL; \ + } \ + return &ll->head->value; \ + } \ + attr T* linked_list_back(T)(const linked_list_t(T) * ll) \ + { \ + if (!ll->head) { \ + return NULL; \ + } \ + linked_list_node_t(T)* cur = ll->head; \ + while (cur->next) cur = cur->next; \ + return &cur->value; \ + } \ + attr size_t linked_list_length(T)(const linked_list_t(T) * ll) \ + { \ + linked_list_node_t(T) * cur; \ + size_t ret = 0; \ + for (cur = ll->head; cur; cur = cur->next) ++ret; \ + return ret; \ + } \ + attr bool linked_list_find_match(T)( \ + const linked_list_t(T) * ll, \ + linked_list_itr_t(T) * itr_out, \ + bool (*match)(T, void*), \ + void* closure) \ + { \ + linked_list_node_t(T)* prev = NULL; \ + linked_list_node_t(T)* cur = NULL; \ + if (!ll || !ll->head) { \ + return 0; \ + } \ + for (cur = ll->head; cur != NULL; cur = (prev = cur)->next) { \ + if (match(cur->value, closure)) { \ + itr_out->prev = prev; \ + itr_out->cur = cur; \ + return 1; \ + } \ + } \ + return 0; \ + } \ + attr bool linked_list_remove_first_match(T)( \ + linked_list_t(T) * ll, T * out, bool (*match)(T, void*), void* closure) \ + { \ + linked_list_itr_t(T) ctx; \ + if (!linked_list_find_match(T)(ll, &ctx, match, closure)) { \ + return 0; \ + } \ + if (out) *out = ctx.cur->value; \ + if (!ctx.prev) { \ + ll->head = ctx.cur->next; \ + } else { \ + ctx.prev->next = ctx.cur->next; \ + } \ + kfree(ctx.cur); \ + return 1; \ + } \ + int memcmp(const void* s1, const void* s2, size_t n); \ + static inline bool linked_list___##T##___eq(T elem, void* other) \ + { \ + return memcmp(&elem, other, sizeof(T)) == 0; \ + } \ + attr bool linked_list_remove(T)(linked_list_t(T) * ll, T val) \ + { \ + bool (*fn)(T, void*) = &linked_list___##T##___eq; \ + bool ret = 0; \ + while (linked_list_remove_first_match(T)(ll, NULL, fn, &val)) ret = 1; \ + return ret; \ + } \ + _Pragma("GCC diagnostic pop") #endif /* SHARED_LINKED_LIST_H_ */ -- cgit From 1710871aa1958c2cac38e4b372964ef22032ed4a Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sun, 6 Dec 2020 02:00:43 -0700 Subject: Added header files implementing a basic AVL tree and Map based off it. These headers take inspiration from the linked list and array list headers as a way to provide primitive templates in C. This time they implement an AVL tree and Map template (which uses the AVL tree). Included are relatively robust tests, though they could be improved. --- include/arch/x86_64/arch.h | 2 +- include/kern/common.h | 1 + include/kern/mem.h | 2 + include/shared/avl_tree.h | 271 +++++++++++++++++++++++++++++++++++++++++++++ include/shared/map.h | 90 +++++++++++++++ include/shared/stdmacro.h | 7 ++ 6 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 include/shared/avl_tree.h create mode 100644 include/shared/map.h create mode 100644 include/shared/stdmacro.h (limited to 'include') diff --git a/include/arch/x86_64/arch.h b/include/arch/x86_64/arch.h index 1848b58..15ebd6d 100644 --- a/include/arch/x86_64/arch.h +++ b/include/arch/x86_64/arch.h @@ -41,6 +41,6 @@ // testing. #define GHOST_DATA_SEGMENT_SIZE 1200 #define HEAP_START (*(((unsigned char*)SRAM1_BASE) + GHOST_DATA_SEGMENT_SIZE)) -#define HEAP_STOP (*(&HEAP_START + 16384 - GHOST_DATA_SEGMENT_SIZE)) +#define HEAP_STOP (*(&HEAP_START + 49152 - GHOST_DATA_SEGMENT_SIZE)) #endif /* ARCH_H_ */ diff --git a/include/kern/common.h b/include/kern/common.h index 021229b..0acc9d3 100644 --- a/include/kern/common.h +++ b/include/kern/common.h @@ -39,6 +39,7 @@ typedef enum { ENDIANNESS_LITTLE, ENDIANNESS_BIG } endianness_t; #define ptr2reg(ptr) ((uint32_t)(ptrdiff_t)(ptr)) typedef __IO uint32_t bits_t; +typedef uint16_t msize_t; #define regset(reg, mask, val) ((reg) = ((reg) & ~mask) | (val << CTZ(mask))) diff --git a/include/kern/mem.h b/include/kern/mem.h index 20b09bb..bc6c4e2 100644 --- a/include/kern/mem.h +++ b/include/kern/mem.h @@ -22,6 +22,8 @@ int debug_kalloc_assert_consistency(char* error, size_t len); void debug_print_blocks(); +int debug_is_heap_empty(); + #endif diff --git a/include/shared/avl_tree.h b/include/shared/avl_tree.h new file mode 100644 index 0000000..98151f2 --- /dev/null +++ b/include/shared/avl_tree.h @@ -0,0 +1,271 @@ +#ifndef _SHARED_AVL_TREE_H_ +#define _SHARED_AVL_TREE_H_ + +#define ALLOC kalloc +#define FREE kfree + +#include +#include + +#include "kern/mem.h" +#include "shared/stdmacro.h" + +#define get_height(n) ((n) == NULL ? 0 : (n)->height) +#define max(a, b) ((a) < (b) ? (b) : (a)) +#define reset_height(node) \ + (node)->height = \ + (max(get_height((node)->right), get_height((node)->left)) + 1) + +#define avl_tree_t(T) CONCAT(avl_tree__, T) +#define avl_tree_node_t(T) CONCAT(avl_tree_node__, T) + +#define avl_tree_new(T) CONCAT(avl_tree_new__, T) +#define avl_tree_free(T) CONCAT(avl_tree_free__, T) +#define avl_tree_size(T) CONCAT(avl_tree_size__, T) +#define avl_tree_insert(T) CONCAT(avl_tree_insert__, T) +#define avl_tree_find(T) CONCAT(avl_tree_find__, T) +#define avl_tree_erase(T) CONCAT(avl_tree_erase__, T) +#define avl_tree_height(T) CONCAT(avl_tree_height__, T) + +#define null_dtor(a) + +typedef unsigned int bool; + +#define AVL_TREE_DECL(T) \ + typedef struct CONCAT(AVL_TREE_NODE_, T) { \ + T value; \ + size_t height; \ + struct CONCAT(AVL_TREE_NODE_, T) * left; \ + struct CONCAT(AVL_TREE_NODE_, T) * right; \ + } avl_tree_node_t(T); \ + \ + typedef struct { \ + avl_tree_node_t(T) * root; \ + } avl_tree_t(T); \ + \ + size_t avl_tree_height(T)(avl_tree_t(T) * tree); \ + avl_tree_t(T) * avl_tree_new(T)(); \ + void avl_tree_free(T)(avl_tree_t(T) * tree); \ + size_t avl_tree_size(T)(const avl_tree_t(T) * avl_tree); \ + T* avl_tree_insert(T)(avl_tree_t(T) * avl_tree, T value); \ + T* avl_tree_find(T)(const avl_tree_t(T)*, T val); \ + bool avl_tree_erase(T)(avl_tree_t(T) * tree, T val, T * out); + +#define AVL_TREE_IMPL(T, CMP, DTOR) \ + avl_tree_t(T) * avl_tree_new(T)() \ + { \ + avl_tree_t(T)* ret = ALLOC(sizeof(avl_tree_t(T))); \ + ret->root = NULL; \ + return ret; \ + } \ + static void CONCAT(avl_loose_free__, T)(avl_tree_node_t(T) * node) \ + { \ + if (!node) return; \ + CONCAT(avl_loose_free__, T)(node->right); \ + CONCAT(avl_loose_free__, T)(node->left); \ + DTOR(node->value); \ + FREE(node); \ + } \ + void avl_tree_free(T)(avl_tree_t(T) * tree) \ + { \ + CONCAT(avl_loose_free__, T)(tree->root); \ + FREE(tree); \ + } \ + static inline size_t CONCAT( \ + loose_size__, T)(const avl_tree_node_t(T) * node) \ + { \ + if (!node) return 0; \ + return 1 + CONCAT(loose_size__, T)(node->left) + \ + CONCAT(loose_size__, T)(node->right); \ + } \ + size_t avl_tree_size(T)(const avl_tree_t(T) * tree) \ + { \ + return CONCAT(loose_size__, T)(tree->root); \ + } \ + static int CONCAT(balance_factor, T)(avl_tree_node_t(T) * node) \ + { \ + return get_height(node->left) - get_height(node->right); \ + } \ + static avl_tree_node_t(T) * CONCAT(ll_rotate, T)(avl_tree_node_t(T) * node) \ + { \ + avl_tree_node_t(T)* child = node->left; \ + node->left = child->right; \ + reset_height(node); \ + child->right = node; \ + reset_height(child); \ + return child; \ + } \ + static avl_tree_node_t(T) * CONCAT(rr_rotate, T)(avl_tree_node_t(T) * node) \ + { \ + avl_tree_node_t(T)* child = node->right; \ + node->right = child->left; \ + reset_height(node); \ + child->left = node; \ + reset_height(child); \ + return child; \ + } \ + static avl_tree_node_t(T) * CONCAT(rl_rotate, T)(avl_tree_node_t(T) * node) \ + { \ + avl_tree_node_t(T)* child = node->right; \ + node->right = CONCAT(ll_rotate, T)(child); \ + reset_height(node); \ + return CONCAT(rr_rotate, T)(node); \ + } \ + static avl_tree_node_t(T) * CONCAT(lr_rotate, T)(avl_tree_node_t(T) * node) \ + { \ + avl_tree_node_t(T)* child = node->left; \ + node->left = CONCAT(rr_rotate, T)(child); \ + reset_height(node); \ + return CONCAT(ll_rotate, T)(node); \ + } \ + static avl_tree_node_t(T) * \ + CONCAT(avl_tree_balance_, T)(avl_tree_node_t(T) * node) \ + { \ + int d = CONCAT(balance_factor, T)(node); \ + if (d > 1) { \ + if (CONCAT(balance_factor, T)(node->left) > 0) { \ + return CONCAT(ll_rotate, T)(node); \ + } else { \ + return CONCAT(lr_rotate, T)(node); \ + } \ + } else if (d < -1) { \ + if (CONCAT(balance_factor, T)(node->right) > 0) { \ + return CONCAT(rl_rotate, T)(node); \ + } else { \ + return CONCAT(rr_rotate, T)(node); \ + } \ + } \ + \ + return node; \ + } \ + static avl_tree_node_t(T) * \ + CONCAT(avl_tree_loose_insert_, T)( \ + avl_tree_node_t(T) * node, T value, T * *ptr_out) \ + { \ + if (!node) { \ + node = ALLOC(sizeof(avl_tree_node_t(T))); \ + assert(node); \ + node->left = NULL; \ + node->right = NULL; \ + node->value = value; \ + node->height = 1; \ + *ptr_out = &node->value; \ + } else { \ + typeof(CMP(node->value, value)) cmp = CMP(node->value, value); \ + if (cmp < 0) { \ + node->left = \ + CONCAT(avl_tree_loose_insert_, T)(node->left, value, ptr_out); \ + reset_height(node); \ + node = CONCAT(avl_tree_balance_, T)(node); \ + } else if (cmp > 0) { \ + node->right = \ + CONCAT(avl_tree_loose_insert_, T)(node->right, value, ptr_out); \ + reset_height(node); \ + node = CONCAT(avl_tree_balance_, T)(node); \ + } \ + } \ + return node; \ + } \ + T* avl_tree_insert(T)(avl_tree_t(T) * tree, T value) \ + { \ + T* ret; \ + tree->root = CONCAT(avl_tree_loose_insert_, T)(tree->root, value, &ret); \ + return ret; \ + } \ + size_t avl_tree_height(T)(avl_tree_t(T) * tree) \ + { \ + if (!tree) return 0; \ + return get_height(tree->root); \ + } \ + static T* CONCAT(loose_avl_tree_find, T)(avl_tree_node_t(T) * node, T value) \ + { \ + if (!node) return NULL; \ + \ + typeof(CMP(node->value, value)) cmp = CMP(node->value, value); \ + if (cmp > 0) { \ + return CONCAT(loose_avl_tree_find, T)(node->right, value); \ + } else if (cmp < 0) { \ + return CONCAT(loose_avl_tree_find, T)(node->left, value); \ + } \ + return &node->value; \ + } \ + T* avl_tree_find(T)(const avl_tree_t(T) * tree, T val) \ + { \ + if (!tree) return NULL; \ + return CONCAT(loose_avl_tree_find, T)(tree->root, val); \ + } \ + static avl_tree_node_t(T) * \ + CONCAT(pluck_left, T)(avl_tree_node_t(T) * node, T * into) \ + { \ + if (node->left) { \ + node->left = CONCAT(pluck_left, T)(node->left, into); \ + reset_height(node); \ + return CONCAT(avl_tree_balance_, T)(node); \ + } else { \ + *into = node->value; \ + FREE(node); \ + return node->right; \ + } \ + } \ + static avl_tree_node_t(T) * \ + CONCAT(pluck_right, T)(avl_tree_node_t(T) * node, T * into) \ + { \ + if (node->right) { \ + node->right = CONCAT(pluck_right, T)(node->right, into); \ + reset_height(node); \ + return CONCAT(avl_tree_balance_, T)(node); \ + } else { \ + *into = node->value; \ + FREE(node); \ + return node->left; \ + } \ + } \ + avl_tree_node_t(T) * \ + CONCAT(loose_avl_tree_erase, T)( \ + avl_tree_node_t(T) * node, T value, bool* out, T* erased) \ + { \ + if (!node) { \ + *out = 0; \ + return NULL; \ + } \ + typeof(CMP(node->value, value)) cmp = CMP(node->value, value); \ + if (cmp == 0) { \ + if (erased) *erased = node->value; \ + *out = 1; \ + if (!node->right && !node->left) { \ + FREE(node); \ + return NULL; \ + } \ + if (get_height(node->right) > get_height(node->left)) { \ + node->right = CONCAT(pluck_left, T)(node->right, &node->value); \ + reset_height(node); \ + node = CONCAT(avl_tree_balance_, T)(node); \ + return node; \ + } \ + node->left = CONCAT(pluck_right, T)(node->left, &node->value); \ + reset_height(node); \ + node = CONCAT(avl_tree_balance_, T)(node); \ + return node; \ + } else if (cmp < 0) { \ + node->left = \ + CONCAT(loose_avl_tree_erase, T)(node->left, value, out, erased); \ + reset_height(node); \ + node = CONCAT(avl_tree_balance_, T)(node); \ + } else { \ + node->right = \ + CONCAT(loose_avl_tree_erase, T)(node->right, value, out, erased); \ + reset_height(node); \ + node = CONCAT(avl_tree_balance_, T)(node); \ + } \ + return node; \ + } \ + bool avl_tree_erase(T)(avl_tree_t(T) * tree, T val, T * erased) \ + { \ + if (!tree) return 0; \ + bool out; \ + tree->root = \ + CONCAT(loose_avl_tree_erase, T)(tree->root, val, &out, erased); \ + return out; \ + } + +#endif /* _SHARED_AVL_TREE_H_ */ diff --git a/include/shared/map.h b/include/shared/map.h new file mode 100644 index 0000000..c9ee6b9 --- /dev/null +++ b/include/shared/map.h @@ -0,0 +1,90 @@ +#ifndef _SHARED_MAP_H_ +#define _SHARED_MAP_H_ + +#include "shared/avl_tree.h" +#include "shared/stdmacro.h" + +#define MAP_PASTE_KV(K, V) CONCAT(CONCAT(K, ___), V) +#define map_entry_t(K, V) CONCAT(map_entry_t__, MAP_PASTE_KV(K, V)) +#define map_t(K, V) CONCAT(map_t__, MAP_PASTE_KV(K, V)) + +#define map_new(K, V) CONCAT(map_new__, MAP_PASTE_KV(K, V)) +#define map_free(K, V) CONCAT(map_free__, MAP_PASTE_KV(K, V)) +#define map_put(K, V) CONCAT(map_put__, MAP_PASTE_KV(K, V)) +#define map_get(K, V) CONCAT(map_get__, MAP_PASTE_KV(K, V)) +#define map_erase(K, V) CONCAT(map_erase__, MAP_PASTE_KV(K, V)) +#define _map_compare_(K, V) CONCAT(_map_compare__, MAP_PASTE_KV(K, V)) +#define _map_dtor_(K, V) CONCAT(_map_dtor__, MAP_PASTE_KV(K, V)) + +#define MAP_DECL(K, V) \ + typedef struct { \ + K key; \ + V value; \ + } map_entry_t(K, V); \ + AVL_TREE_DECL(map_entry_t(K, V)); \ + typedef struct { \ + avl_tree_t(map_entry_t(K, V)) * tree; \ + } map_t(K, V); \ + map_t(K, V) * map_new(K, V)(); \ + void map_free(K, V)(map_t(K, V) * map); \ + V* map_get(K, V)(map_t(K, V) * map, K key); \ + V* map_put(K, V)(map_t(K, V) * map, K key, V value); \ + bool map_erase(K, V)(map_t(K, V) * map, K key, V * out); + +#define MAP_IMPL(K, V, CMP, DTOR) \ + static inline int _map_compare_(K, V)( \ + map_entry_t(K, V) e1, map_entry_t(K, V) e2) \ + { \ + return CMP(e1.key, e2.key); \ + } \ + static inline void _map_dtor_(K, V)(map_entry_t(K, V) e1) \ + { \ + DTOR(e1.value); \ + } \ + AVL_TREE_IMPL(map_entry_t(K, V), _map_compare_(K, V), _map_dtor_(K, V)) \ + map_t(K, V) * map_new(K, V)() \ + { \ + map_t(K, V)* ret = ALLOC(sizeof(map_t(K, V))); \ + ret->tree = avl_tree_new(map_entry_t(K, V))(); \ + return ret; \ + } \ + void map_free(K, V)(map_t(K, V) * map) { \ + avl_tree_free(map_entry_t(K, V))(map->tree); \ + FREE(map); \ + }\ + V* map_get(K, V)(map_t(K, V) * map, K key) \ + { \ + map_entry_t(K, V) key_; \ + key_.key = key; \ + map_entry_t(K, V)* entry = \ + avl_tree_find(map_entry_t(K, V))(map->tree, key_); \ + \ + if (!entry) { \ + return NULL; \ + } \ + \ + return &entry->value; \ + } \ + V* map_put(K, V)(map_t(K, V) * map, K key, V val) \ + { \ + map_entry_t(K, V) entry; \ + entry.key = key; \ + entry.value = val; \ + map_entry_t(K, V)* ref = \ + avl_tree_insert(map_entry_t(K, V))(map->tree, entry); \ + return &ref->value; \ + } \ + bool map_erase(K, V)(map_t(K, V) * map, K key, V * out) \ + { \ + map_entry_t(K, V) key_; \ + key_.key = key; \ + \ + map_entry_t(K, V) entry_out; \ + bool ret = avl_tree_erase(map_entry_t(K, V))(map->tree, key_, &entry_out); \ + if (ret) { \ + *out = entry_out.value; \ + } \ + return ret; \ + } + +#endif /* _SHARED_MAP_H_ */ diff --git a/include/shared/stdmacro.h b/include/shared/stdmacro.h new file mode 100644 index 0000000..6010982 --- /dev/null +++ b/include/shared/stdmacro.h @@ -0,0 +1,7 @@ +#ifndef _SHARED_STDMACRO_H_ +#define _SHARED_STDMACRO_H_ + +#define CONCAT_(a, b) a ## b +#define CONCAT(a, b) CONCAT_(a, b) + +#endif /* _SHARED_STDMACRO_H_ */ -- cgit From a5923b21e48fcfe660c1e7d586fe0c6a5b79e421 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Wed, 9 Dec 2020 20:29:31 -0700 Subject: Got a basic timer to work. --- include/arch/arm/arch.h | 2 + include/arch/stm32l4xxx/peripherals/tim.h | 175 ++++++++++++++++++++++++++++++ include/arch/x86_64/arch.h | 2 + 3 files changed, 179 insertions(+) create mode 100644 include/arch/stm32l4xxx/peripherals/tim.h (limited to 'include') diff --git a/include/arch/arm/arch.h b/include/arch/arm/arch.h index 267621f..7dfc343 100644 --- a/include/arch/arm/arch.h +++ b/include/arch/arm/arch.h @@ -47,6 +47,8 @@ #define SYSCFG_BASE (0x40010000) #define EXTI_BASE (0x40010400) +#define TIM2_BASE (0x40000000) + #include #ifndef DRY_RUN _Static_assert(sizeof(void*) == sizeof(uint32_t), "Pointers must be 32 bits"); diff --git a/include/arch/stm32l4xxx/peripherals/tim.h b/include/arch/stm32l4xxx/peripherals/tim.h new file mode 100644 index 0000000..145622a --- /dev/null +++ b/include/arch/stm32l4xxx/peripherals/tim.h @@ -0,0 +1,175 @@ +#ifndef ARCH_STM32L4XXX_PERIPHERALS_TIM_H_ +#define ARCH_STM32L4XXX_PERIPHERALS_TIM_H_ + +#include "arch.h" +#include "kern/common.h" + +#define TIM2 (*((tim_regs_t*)TIM2_BASE)) + +typedef __IO struct { +#define tim_uifremap (1 << 11) /* UIF status bit remapping */ +#define tim_ckd (3 << 8) /* Clock Divisor */ +#define tim_arpe (1 << 7) /* Auto-reload preload enable */ +#define tim_cms (3 << 5) /* Center align mode selection */ +#define tim_dir (1 << 4) /* Direction */ +#define tim_opm (1 << 3) /* One-pulse mode */ +#define tim_urs (1 << 2) /* Update request source */ +#define tim_udis (1 << 1) /* Update disable */ +#define tim_cen (1 << 0) /* Counter enable */ + uint32_t c_r1; + +#define tim_ti1s (1 << 7) +#define tim_mms (7 << 4) +#define tim_ccds (1 << 3) + uint32_t c_r2; + +#define tim_sms_3 (1 << 16) +#define tim_etp (1 << 15) +#define tim_ece (1 << 14) +#define tim_etps (3 << 12) +#define tim_etf (0xF << 8) +#define tim_msm (1 << 7) +#define tim_ts (7 << 4) +#define tim_occs (1 << 3) +#define tim_sms_0_2 (7 << 0) + uint32_t smc_r; + +#define tim_tde (1 << 14) /* Trigger DMA request enable */ +#define tim_cc4de (1 << 12) /* Capture/Compare 4 DMA request enable */ +#define tim_cc3de (1 << 11) /* Capture/Compare 3 DMA request enable */ +#define tim_cc2de (1 << 10) /* Capture/Compare 2 DMA request enable */ +#define tim_cc1de (1 << 9) /* Capture/Compare 1 DMA request enable */ +#define tim_ude (1 << 8) /* Update DMA request enable */ +#define tim_tie (1 << 6) /* Trigger interrupt enable */ +#define tim_cc4ie (1 << 4) /* Capture/Compare 4 interrupt enable */ +#define tim_cc3ie (1 << 3) /* Capture/Compare 3 interrupt enable */ +#define tim_cc2ie (1 << 2) /* Capture/Compare 2 interrupt enable */ +#define tim_cc1ie (1 << 1) /* Capture/Compare 1 interrupt enable */ +#define tim_uie (1 << 0) /* Update interrupt enable */ + uint32_t die_r; /* Dma interrupt/enable register */ + +#define tim_cc4of (1 << 12) /* Capture/Compare 4 overcapture flag */ +#define tim_cc3of (1 << 11) /* Capture/Compare 3 overcapture flag */ +#define tim_cc2of (1 << 10) /* Capture/compare 2 overcapture flag */ +#define tim_cc1of (1 << 9) /* Capture/Compare 1 overcapture flag */ +#define tim_tif (1 << 6) /* Trigger interrupt flag */ +#define tim_cc4if (1 << 4) /* Capture/Compare 4 interrupt flag */ +#define tim_cc3if (1 << 3) /* Capture/Compare 3 interrupt flag */ +#define tim_cc2if (1 << 2) /* Capture/Compare 2 interrupt flag */ +#define tim_cc1if (1 << 1) /* Capture/compare 1 interrupt flag */ +#define tim_uif (1 << 0) /* Update interrupt flag */ + uint32_t s_r; /* Status register */ + +#define tim_tg (1 << 6) /* Trigger generation */ +#define tim_cc4g (1 << 4) /* Capture/compare 4 generation */ +#define tim_cc3g (1 << 3) /* Capture/compare 3 generation */ +#define tim_cc2g (1 << 2) /* Capture/compare 2 generation */ +#define tim_cc1g (1 << 1) /* Capture/compare 1 generation */ +#define tim_ug (1 << 0) /* Update generation */ + uint32_t eg_r; /* Event generation register. */ + +#define tim_ic2f (15 << 12) /* Input capture 2 filter */ +#define tim_ic2psc (3 << 10) /* Input capture 2 prescaler */ +#define tim_cc2s (3 << 8) /* Capture/compare 2 selection */ +#define tim_ic1f (15 << 4) /* Input capture 1 filter */ +#define tim_ic1psc (3 << 2) /* Input capture 1 prescaler */ +#define tim_cc1s (3 << 0) /* Capture/Compare 1 selection */ + /* Alternate */ +#define tim_oc2ce (1 << 15) /* Output compare 2 clear enable */ +#define tim_oc2m_3 (1 << 24) /* Output compare 2 mode, bit 3. */ +#define tim_oc2m_0_2 (7 << 12) /* Output compare 2 mode, bits 0-2 */ +#define tim_oc2pe (1 << 11) /* Output compare 2 preload enable */ +#define tim_oc2fe (1 << 10) /* Output compare 2 fast enable */ +#define tim_cc2s (3 << 8) /* Capture/Compare 2 selection */ +#define tim_oc1ce (1 << 7) /* Output compare 1 clear enable */ +#define tim_oc1m_3 (1 << 16) /* Output compare 1 mode, bit 3. */ +#define tim_oc1m_0_2 (7 << 4) /* Output compare 1 mode, bits 0-2. */ +#define tim_oc1pe (1 << 3) /* Output compare 1 preload enable */ +#define tim_oc1fe (1 << 2) /* Output compare 1 fast enable */ +#define tim_cc1s (3 << 0) /* Capture/Compare 1 selection */ + uint32_t ccm_r1; /* Capture/compare mode register 1. */ + +#define tim_ic4f (15 << 12) /* Input capture 4 filter */ +#define tim_ic4psc (3 << 10) /* Input capture 4 prescaler */ +#define tim_cc4s (3 << 8) /* Capture/Compare 4 selection */ +#define tim_ic3f (15 << 4) /* Input capture 3 filter */ +#define tim_ic3psc (3 << 2) /* Input capture 3 prescaler */ +#define tim_cc3s (3 << 0) /* Capture/Compare 3 selection */ + /* Alternate */ +#define tim_oc4ce (1 << 15) /* Output compare 4 clear enable */ +#define tim_oc4m_3 (1 << 24) /* Output compare 4 mode, bit 3. */ +#define tim_oc4m_0_2 (7 << 12) /* Output compare 4 mode, bits 0-2 */ +#define tim_oc4pe (1 << 11) /* Output compare 4 preload enable */ +#define tim_oc4fe (1 << 10) /* Output compare 4 fast enable */ +#define tim_cc4s (3 << 8) /* Capture/Compare 4 selection */ +#define tim_oc3ce (1 << 7) /* Output compare 3 clear enable */ +#define tim_oc3m_3 (1 << 16) /* Output compare 3 mode, bit 3. */ +#define tim_oc3m_0_2 (7 << 4) /* Output compare 3 mode, bits 0-2. */ +#define tim_oc3pe (1 << 3) /* Output compare 3 preload enable */ +#define tim_oc3fe (1 << 2) /* Output compare 3 fast enable */ +#define tim_cc3s (3 << 0) /* Capture/Compare 3 selection */ + uint32_t ccm_r2; /* Capture/compare mode register 2. */ + +#define tim_cc4np (1 << 15) /* Capture/Compare 4 output Polarity. */ +#define tim_cc4p (1 << 13) /* Capture/Compare 4 output Polarity. */ +#define tim_cc4e (1 << 12) /* Capture/Compare 4 output enable. */ +#define tim_cc3np (1 << 11) /* Capture/Compare 3 output Polarity. */ +#define tim_cc3p (1 << 9) /* Capture/Compare 3 output Polarity. */ +#define tim_cc3e (1 << 8) /* Capture/Compare 3 output enable. */ +#define tim_cc2np (1 << 7) /* Capture/Compare 2 output Polarity. */ +#define tim_cc2p (1 << 5) /* Capture/Compare 2 output Polarity. */ +#define tim_cc2e (1 << 4) /* Capture/Compare 2 output enable. */ +#define tim_cc1np (1 << 3) /* Capture/Compare 1 output Polarity. */ +#define tim_cc1p (1 << 1) /* Capture/Compare 1 output Polarity. */ +#define tim_cc1e (1 << 0) /* Capture/Compare 1 output enable. */ + uint32_t cce_r; /* Copture/compare enable register. */ + + /* Mapping depends on UIFREMAP. */ +#define tim_cnt (0x7fffffff << 0) /* Counter value */ +#define tim_uifcpy (1 << 31) + uint32_t cnt; + + uint16_t psc; /* Prescaler. */ + uint16_t reserved0; + + uint32_t ar_r; /* Auto reload register. */ + + uint32_t reserved1; + + uint32_t cc_r1; /* Capture compare register 1. */ + uint32_t cc_r2; /* Capture compare register 2. */ + uint32_t cc_r3; /* Capture compare register 3. */ + uint32_t cc_r4; /* Capture compare register 4. */ + + uint32_t reserved2; + +#define tim_dbl (31 << 8) /* DMA burst length */ +#define tim_dba (31 << 0) /* DMA base address */ + uint32_t dc_r; /* dma control register. */ + + uint16_t dma_r; /* dma address for full transfer. */ + uint16_t reserved3; /* dma address for full transfer. */ + + union { +#define tim_ti4_rmp (3 << 2) /* Input Capture 4 remap */ +#define tim_etr_rmp (1 << 1) /* External trigger remap */ +#define tim_itr1_rmp (1 << 0) /* Internal trigger 1 remap */ + uint32_t tim2_o_r1; +#define tim_ti1_rmp (3 << 0) + uint32_t tim3_o_r1; + }; + + uint32_t reserved4[3]; + +#define tim_etrsel (7 << 14) /* ETR source selection */ + union { + uint32_t tim2_o_r2; + uint32_t tim3_o_r2; + }; +} tim_regs_t; + +static_assert(offsetof(tim_regs_t, ar_r) == 0x2c, "Offset check failed"); +static_assert(offsetof(tim_regs_t, dc_r) == 0x48, "Offset check failed"); +static_assert(offsetof(tim_regs_t, tim3_o_r2) == 0x60, "Offset check failed"); + +#endif /* ARCH_STM32L4XXX_PERIPHERALS_TIM_H_ */ diff --git a/include/arch/x86_64/arch.h b/include/arch/x86_64/arch.h index 15ebd6d..8bd3468 100644 --- a/include/arch/x86_64/arch.h +++ b/include/arch/x86_64/arch.h @@ -37,6 +37,8 @@ #define SYSCFG_BASE (load_fake_syscfg__()) #define EXTI_BASE (load_fake_exti__()) +#define TIM2_BASE (load_fake_exti__()) + // Pretend there's a data segement at the start of SRAM1 for more accurate // testing. #define GHOST_DATA_SEGMENT_SIZE 1200 -- cgit From 5f1763ec87503527583cb1a7c6deb73604db0dfc Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Wed, 9 Dec 2020 23:15:14 -0700 Subject: Can read from the A/C remote control! --- include/drv/ir/control.h | 14 ++++++++++++++ include/drv/ir/ir.h | 34 ++++++++++++++++++++++++++++++++++ include/drv/ir/lg_remote_codes.h | 17 +++++++++++++++++ include/shared/avl_tree.h | 3 +-- 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 include/drv/ir/control.h create mode 100644 include/drv/ir/ir.h create mode 100644 include/drv/ir/lg_remote_codes.h (limited to 'include') diff --git a/include/drv/ir/control.h b/include/drv/ir/control.h new file mode 100644 index 0000000..11e3604 --- /dev/null +++ b/include/drv/ir/control.h @@ -0,0 +1,14 @@ +#ifndef _DRV_IR_CONTROL_H_ +#define _DRV_IR_CONTROL_H_ + +#include "kern/common.h" + +#define add_ir_code_callback(code, fn, closure) \ + add_ir_code_callback_(code, (void (*)(uint32_t, void*))(fn), closure) + +void add_ir_code_callback_( + uint32_t code, void (*fn)(uint32_t code, void* closure), void* closure); + +void enable_ir_control(); + +#endif /* _DRV_IR_CONTROL_H_ */ diff --git a/include/drv/ir/ir.h b/include/drv/ir/ir.h new file mode 100644 index 0000000..0a747e8 --- /dev/null +++ b/include/drv/ir/ir.h @@ -0,0 +1,34 @@ +#ifndef _DRV_IR_IR_H_ +#define _DRV_IR_IR_H_ + +#include "kern/common.h" + +typedef struct { + uint16_t ts[64]; /* Timestamps. Microseconds. */ + uint8_t n; +} ir_code_t; + +typedef struct { + uint32_t c; +} decoded_ir; + +/* + * Attempt to decode the provided ir code. + * + * The generic ir is: + * + * The frame starts out as really-long, half(ish) as long, short. If + * this basic frame header does not exist decoding cannot continue. + * + * A short code followed by a short code = 0 + * A long code followed by a short code = 1 + * + * returns non-zero on successful decode. + */ +int ir_generic_decode(const ir_code_t* code, uint32_t* out); + +void add_ir_callback(void(*callback)(const ir_code_t*)); + +void ir_begin_listen(); + +#endif /* _DRV_IR_IR_H_ */ diff --git a/include/drv/ir/lg_remote_codes.h b/include/drv/ir/lg_remote_codes.h new file mode 100644 index 0000000..77cbb45 --- /dev/null +++ b/include/drv/ir/lg_remote_codes.h @@ -0,0 +1,17 @@ +#ifndef _DRV_IR_LG_REMOTE_CODES_H_ +#define _DRV_IR_LG_REMOTE_CODES_H_ + +#define RC_HIGH 0x08e76800 +#define RC_TEMP_UP 0x08e7a800 +#define RC_DRY 0x08e72800 +#define RC_LOW 0x08e77000 +#define RC_TEMP_DOWN 0x08e7b000 +#define RC_COOL 0x08e73000 +#define RC_CONTINUOUS 0x08e75000 +#define RC_FAN 0x08e71000 +#define RC_SLEEP 0x08e76000 +#define RC_UNITS 0x08e72000 +#define RC_TIMER 0x08e78000 +#define RC_POWER 0x08e70080 + +#endif /* _DRV_IR_LG_REMOTE_CODES_H_ */ diff --git a/include/shared/avl_tree.h b/include/shared/avl_tree.h index 98151f2..2b174d3 100644 --- a/include/shared/avl_tree.h +++ b/include/shared/avl_tree.h @@ -7,6 +7,7 @@ #include #include +#include "kern/common.h" #include "kern/mem.h" #include "shared/stdmacro.h" @@ -29,8 +30,6 @@ #define null_dtor(a) -typedef unsigned int bool; - #define AVL_TREE_DECL(T) \ typedef struct CONCAT(AVL_TREE_NODE_, T) { \ T value; \ -- cgit From 90eb3a0b79bfef67c70dc545b49c48928eea05f4 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Mon, 27 Sep 2021 22:56:46 -0600 Subject: Completed ws2812b 2020 Christmas Lights. --- include/drv/ws2812B/ws2812b.h | 3 --- include/kern/exti/exti_manager.h | 32 ++++++++++++++++++++++++++++++++ include/shared/avl_tree.h.gch | Bin 0 -> 11451 bytes include/shared/math.h | 19 +++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 include/kern/exti/exti_manager.h create mode 100644 include/shared/avl_tree.h.gch create mode 100644 include/shared/math.h (limited to 'include') diff --git a/include/drv/ws2812B/ws2812b.h b/include/drv/ws2812B/ws2812b.h index 3189907..d7137a1 100644 --- a/include/drv/ws2812B/ws2812b.h +++ b/include/drv/ws2812B/ws2812b.h @@ -30,7 +30,4 @@ void ws2812b_write_rgb_arr_sync(ws2812b_t* drv, rgb_t* arr, size_t arr_len); void ws2812b_delete(ws2812b_t* drv); -/* Returns round(sin(2πn / 256) * 127.5 + 127.5). */ -uint8_t byte_sin(uint8_t n); - #endif /* WS2812B_H_ */ diff --git a/include/kern/exti/exti_manager.h b/include/kern/exti/exti_manager.h new file mode 100644 index 0000000..aa39b4f --- /dev/null +++ b/include/kern/exti/exti_manager.h @@ -0,0 +1,32 @@ +#ifndef _KERN_EXTI_EXTI_MANAGER_H_ +#define _KERN_EXTI_EXTI_MANAGER_H_ + +#include "kern/common.h" +#include "kern/gpio/gpio_manager.h" +#include "shared/linked_list.h" + +#define EXTI_ERROR_ALREADY_IN_USE 1 + +struct EXTI_HANDLE; + + +typedef struct { + void (*fn)(struct EXTI_HANDLE, void*); + void* closure; +} exti_callback_t; + +LINKED_LIST_DECL(exti_callback_t); +typedef struct EXTI_HANDLE { + uint8_t id; + linked_list_t(exti_callback_t)* callbacks; +} exti_handle_t; + +exti_handle_t* enable_exti_for_gpio(gpio_pin_t gpio_pin, int* ec); + +exti_handle_t* exti_add_callback(exti_handle_t*, exti_callback_t* callback); + +gpio_pin_t exti_gpio_pin(exti_handle_t* handle); + + + +#endif /* _KERN_EXTI_EXTI_MANAGER_H_ */ diff --git a/include/shared/avl_tree.h.gch b/include/shared/avl_tree.h.gch new file mode 100644 index 0000000..78fc043 Binary files /dev/null and b/include/shared/avl_tree.h.gch differ diff --git a/include/shared/math.h b/include/shared/math.h new file mode 100644 index 0000000..6aec0e7 --- /dev/null +++ b/include/shared/math.h @@ -0,0 +1,19 @@ +#ifndef _SHARED_MATH_H_ +#define _SHARED_MATH_H_ + +#include "kern/common.h" + +/* Returns round(sin(2πn / 256) * 127.5 + 127.5). */ +uint8_t byte_sin(uint8_t n); + +static inline uint8_t byte_scale(uint8_t n, uint8_t sc) { + return n * sc / 255; +} + +#define min(a, b) (a) < (b) ? (a) : (b) +#define max(a, b) (a) > (b) ? (a) : (b) + +/* returns (in / 256)^n * 256. */ +uint8_t amp(uint8_t in, uint8_t n); + +#endif /* _SHARED_MATH_H_ */ -- cgit