From 5f9bc297019c9a243a14cd4f72735336acf3495b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 3 Feb 2020 19:19:31 +0100 Subject: [PATCH] Add untested version of clock enable manager --- stm-firmware/Makefile | 4 + stm-firmware/clock-enable-manager.c | 137 ++++++++++++++++++++ stm-firmware/include/clock-enable-manager.h | 48 +++++++ stm-firmware/include/stm32-gpio-macros.h | 9 ++ 4 files changed, 198 insertions(+) create mode 100644 stm-firmware/clock-enable-manager.c create mode 100644 stm-firmware/include/clock-enable-manager.h diff --git a/stm-firmware/Makefile b/stm-firmware/Makefile index 5e9e301..027e3d2 100644 --- a/stm-firmware/Makefile +++ b/stm-firmware/Makefile @@ -24,10 +24,14 @@ endif ##Custom Files### CFILES += adc-meas.c +# Shellmatta CFILES += shellmatta/src/shellmatta.c shellmatta/src/shellmatta_autocomplete.c shellmatta/src/shellmatta_escape.c shellmatta/src/shellmatta_history.c shellmatta/src/shellmatta_utils.c INCLUDEPATH += -Ishellmatta/api DEFINES += -DSHELLMATTA_STRIP_PRINTF +# RCC Manager +CFILES += clock-enable-manager.c + #TODO ################################################################################### diff --git a/stm-firmware/clock-enable-manager.c b/stm-firmware/clock-enable-manager.c new file mode 100644 index 0000000..41dab16 --- /dev/null +++ b/stm-firmware/clock-enable-manager.c @@ -0,0 +1,137 @@ +#include +#include + +#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +struct rcc_enable_count { + uint32_t *rcc_reg_addr; + uint32_t *enable_bit_cnt; + uint8_t rcc_enable_bit_pos; +}; + +#if RCC_ENABLE_MANAGER_STATIC + +static struct rcc_enable_count enable_count_list[RCC_ENABLE_MANAGER_COUNT] = {0}; + +#else +#error "RCC manager with dynamic memory not implemented!" +#endif + +#if RCC_ENABLE_MANAGER_STATIC +static struct rcc_enable_count *search_enable_entry_in_list(uint32_t *reg_addr, uint8_t bit_pos) +{ + int i; + struct rcc_enable_count *ret_element = NULL; + struct rcc_enable_count *current_element; + + for (i = 0; i < COUNT_OF(enable_count_list); i++) { + current_element = &enable_count_list[i]; + + /* Check if register address and bit position match */ + if (reg_addr != current_element->rcc_reg_addr) + continue; + if (bit_pos != current_element->rcc_enable_bit_pos) + continue; + + /* Found entry. Wohoo! */ + ret_element = current_element; + } + + return ret_element; +} + +static struct rcc_enable_count *enable_entry_list_get_free_entry() +{ + struct rcc_enable_count *ret_ptr = NULL; + const int list_len = COUNT_OF(enable_count_list); + int i; + + for (i = 0; i < list_len; i++) { + if (enable_count_list[i].rcc_reg_addr == NULL) { + ret_ptr = &enable_count_list[i]; + + /* Clear the count value to be safe */ + ret_ptr->enable_bit_cnt = 0; + + break; + } + } + + return ret_ptr; +} + +static void enable_entry_list_remove_entry(struct rcc_enable_count *entry) +{ + if (!entry) + return; + + entry->rcc_reg_addr = NULL; + entry->enable_bit_cnt = 0; + entry->rcc_enable_bit_pos = 0; +} +#endif + +int rcc_manager_enable_clock(uint32_t *rcc_enable_register, uint8_t bit_no) +{ + int ret_val = 0; + struct rcc_enable_count *entry; + + if (!rcc_enable_register || bit_no > 31) { + return -1000; + } + + /* Enable the clock in any case, no matter what follows */ + *rcc_enable_register |= (1U<rcc_reg_addr = rcc_enable_register; + entry->rcc_enable_bit_pos = bit_no; + } + + /* Increment enable counter */ + entry->enable_bit_cnt++; + +ret_error_code: + return ret_val; +} + +int rcc_manager_disable_clock(uint32_t *rcc_enable_register, uint8_t bit_no) +{ + int ret_val = -1; + struct rcc_enable_count *entry; + + if (!rcc_enable_register || bit_no > 31) { + return -1000; + } + + entry = search_enable_entry_in_list(rcc_enable_register, bit_no); + + /* If entry is found and has a count of zero, disable clock */ + if (entry) { + /* Found entry => Decrement count and delete if zero */ + entry->enable_bit_cnt--; + if (entry->enable_bit_cnt <= 0) { + enable_entry_list_remove_entry(entry); + + /* Disable clock */ + *rcc_enable_register &= ~(1U< +#include + +/** + * @brief The RCC Enable Manager uses static memory with a fixed maximum + */ +#define RCC_ENABLE_MANAGER_STATIC 1U + +#if RCC_ENABLE_MANAGER_STATIC +#define RCC_ENABLE_MANAGER_COUNT 20U +#else +#error "RCC Enable Manager not yet implemented with dynamic memory" +#endif + +/** + * @brief Enable Clock for peripheral by setting the corresponding bit (@p bit_no) to one + * + * This function also keeps a enable count on each bit that is set, in order to allow nested enables/disables + * + * If there is no more space to track a new register bit in memory (either due to the static limit or due to no remaining heap space), + * the function still enables the peripheral clock but does not track it and returns -1 + * + * @param rcc_enable_register + * @param bit_no + * + * @return 0 if successful + */ +int rcc_manager_enable_clock(uint32_t *rcc_enable_register, uint8_t bit_no); + +/** + * @brief Disable clock for peripheral and decrement the enaböe-counter of that bit. + * + * If there is no bit entry in the counting table yet, teh peripheral clock is not disabled and error code + * -1 is returned. + * + * If the count reaches zero, the element is removed from the list to make room for new ones + * + * @param rcc_enable_register Register to disable the bit in + * @param bit_no Bit number (0 to 31) of the bit to disable + * @return 0 if successful + */ +int rcc_manager_disable_clock(uint32_t *rcc_enable_register, uint8_t bit_no); + + +#endif /* __CLOCK_ENABLE_MANAGER_H__ */ diff --git a/stm-firmware/include/stm32-gpio-macros.h b/stm-firmware/include/stm32-gpio-macros.h index 6b9b3ca..5829507 100644 --- a/stm-firmware/include/stm32-gpio-macros.h +++ b/stm-firmware/include/stm32-gpio-macros.h @@ -8,4 +8,13 @@ #define SETAF(PORT,PIN,AF) PORT->AFR[(PIN < 8 ? 0 : 1)] |= AF << ((PIN < 8 ? PIN : (PIN - 8)) * 4) #define ANALOG(pin) (0x03 << (pin * 2)) +#define BIOTMASK_TO_BITNO(x) (x&0x1?0:x&0x2?1:x&0x4?2:x&0x8?3: \ + x&0x10?4:x&0x20?5:x&0x40?6:x&0x80?7: \ + x&0x100?8:x&0x200?9:x&0x400?10:x&0x800?11: \ + x&0x1000?12:x&0x2000?13:x&0x4000?14:x&0x8000?15: \ + x&0x10000?16:x&0x20000?17:x&0x40000?18:x&0x80000?19: \ + x&0x100000?20:x&0x200000?21:x&0x400000?22:x&0x800000?23: \ + x&0x1000000?24:x&0x2000000?25:x&0x4000000?26:x&0x8000000?27: \ + x&0x10000000?28:x&0x20000000?29:x&0x40000000?30:x&0x80000000?31:32) + #endif /* __STM32GPIOMACROS_H__ */