Add untested version of clock enable manager
This commit is contained in:
		@@ -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
 | 
			
		||||
 | 
			
		||||
###################################################################################
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										137
									
								
								stm-firmware/clock-enable-manager.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								stm-firmware/clock-enable-manager.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
			
		||||
#include <clock-enable-manager.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#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<<bit_no);
 | 
			
		||||
 | 
			
		||||
	/* Check if bit is already in list */
 | 
			
		||||
	entry = search_enable_entry_in_list(rcc_enable_register, bit_no);
 | 
			
		||||
 | 
			
		||||
	if (!entry) {
 | 
			
		||||
		/* Create ne entry at first free place in list */
 | 
			
		||||
		entry = enable_entry_list_get_free_entry();
 | 
			
		||||
 | 
			
		||||
		/* Check if entry is valid. If not return */
 | 
			
		||||
		if (!entry) {
 | 
			
		||||
			ret_val = -1;
 | 
			
		||||
			goto ret_error_code;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Set entry */
 | 
			
		||||
		entry->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<<bit_no);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret_val = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret_val;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								stm-firmware/include/clock-enable-manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								stm-firmware/include/clock-enable-manager.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
#ifndef __CLOCK_ENABLE_MANAGER_H__
 | 
			
		||||
#define __CLOCK_ENABLE_MANAGER_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stm32-gpio-macros.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @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__ */
 | 
			
		||||
@@ -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__ */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user