From 05a568a27cdba1617182813b8323aefc4e2b2102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 6 Jan 2018 17:32:37 +0100 Subject: [PATCH] ram savings by using new bitfield-based rsc alloc --- framework/resources.c | 107 ++++++++++++++++++++++++++------------ framework/rsc_enum.h | 59 +++++++++++++-------- framework/unit.h | 3 ++ framework/unit_registry.c | 12 +++++ framework/unit_registry.h | 8 +++ gex.mk | 2 +- platform/pin_utils.c | 8 +-- platform/platform.c | 32 ++++++------ utils/error.h | 2 +- 9 files changed, 157 insertions(+), 76 deletions(-) diff --git a/framework/resources.c b/framework/resources.c index 6e7b9b6..2ff7035 100644 --- a/framework/resources.c +++ b/framework/resources.c @@ -6,18 +6,15 @@ #include "unit.h" #include "resources.h" #include "pin_utils.h" +#include "unit_registry.h" static bool rsc_initialized = false; -// This takes quite a lot of space, we could use u8 and IDs instead if needed -struct resouce_slot { - const char *name; - Unit *owner; -} __attribute__((packed)); +static ResourceMap global_rscmap; -static struct resouce_slot resources[R_RESOURCE_COUNT]; +// here are the resource names for better debugging -// here are the resource names for better debugging (could also be removed if absolutely necessary) +// this list doesn't include GPIO names, they can be easily generated const char *const rsc_names[] = { #define X(res_name) #res_name, XX_RESOURCES @@ -27,16 +24,28 @@ const char *const rsc_names[] = { /** Get rsc name */ const char * rsc_get_name(Resource rsc) { - assert_param(rsc < R_RESOURCE_COUNT); + assert_param(rsc < RESOURCE_COUNT); + + static char gpionamebuf[4]; + if (rsc >= R_PA0) { + // we assume the returned value is not stored anywhere + // and is directly used in a sprintf call. + uint8_t index = rsc - R_PA0; + SNPRINTF(gpionamebuf, 4, "%c%d", 'A'+(index/16), index%16); + return gpionamebuf; + } + return rsc_names[rsc]; } /** Get rsc owner name */ const char * rsc_get_owner_name(Resource rsc) { - assert_param(rsc < R_RESOURCE_COUNT); - if (resources[rsc].owner == NULL) return "NULL"; - return resources[rsc].owner->name; + assert_param(rsc < RESOURCE_COUNT); + + Unit *pUnit = ureg_get_rsc_owner(rsc); + if (pUnit == NULL) return "NULL"; + return pUnit->name; } /** @@ -44,9 +53,10 @@ const char * rsc_get_owner_name(Resource rsc) */ void rsc_init_registry(void) { - for (int i = 0; i < R_RESOURCE_COUNT; i++) { - resources[i].owner = &UNIT_PLATFORM; + for(uint32_t i = 0; i < RSCMAP_LEN; i++) { + UNIT_PLATFORM.resources[i] = global_rscmap[i] = 0xFF; } + rsc_initialized = true; } @@ -60,22 +70,38 @@ void rsc_init_registry(void) error_t rsc_claim(Unit *unit, Resource rsc) { assert_param(rsc_initialized); - assert_param(rsc > R_NONE && rsc < R_RESOURCE_COUNT); + assert_param(rsc < RESOURCE_COUNT); assert_param(unit != NULL); - if (resources[rsc].owner) { - //TODO properly report to user + if (RSC_IS_HELD(global_rscmap, rsc)) { + // this whole branch is just reporting the error + + Unit *holder = ureg_get_rsc_owner(rsc); + + if (holder == NULL) { + // It must be one of the dummy built-in units + if (RSC_IS_HELD(UNIT_SYSTEM.resources, rsc)) + holder = &UNIT_SYSTEM; + else if (RSC_IS_HELD(UNIT_PLATFORM.resources, rsc)) + holder = &UNIT_SYSTEM; + } + + assert_param(holder != NULL); + dbg("ERROR!! Unit %s failed to claim resource %s, already held by %s!", unit->name, rsc_get_name(rsc), - rsc_get_owner_name(rsc)); + holder->name); unit->failed_rsc = rsc; return E_RESOURCE_NOT_AVAILABLE; } - resources[rsc].owner = unit; + // must claim both in global and in unit + RSC_CLAIM(global_rscmap, rsc); + RSC_CLAIM(unit->resources, rsc); + return E_SUCCESS; } @@ -90,8 +116,9 @@ error_t rsc_claim(Unit *unit, Resource rsc) error_t rsc_claim_range(Unit *unit, Resource rsc0, Resource rsc1) { assert_param(rsc_initialized); - assert_param(rsc0 > R_NONE && rsc0 < R_RESOURCE_COUNT); - assert_param(rsc1 > R_NONE && rsc1 < R_RESOURCE_COUNT); + assert_param(rsc0 < RESOURCE_COUNT); + assert_param(rsc1 < RESOURCE_COUNT); + assert_param(rsc0 <= rsc1); assert_param(unit != NULL); for (int i = rsc0; i <= rsc1; i++) { @@ -125,11 +152,29 @@ error_t rsc_claim_gpios(Unit *unit, char port_name, uint16_t pins) void rsc_free(Unit *unit, Resource rsc) { assert_param(rsc_initialized); - assert_param(rsc > R_NONE && rsc < R_RESOURCE_COUNT); + assert_param(rsc < RESOURCE_COUNT); + + if (RSC_IS_FREE(global_rscmap, rsc)) return; + + // free it in any unit that holds it + if (unit) { + if (RSC_IS_HELD(unit->resources, rsc)) { + RSC_FREE(unit->resources, rsc); + } + } else { + // Try to free it in any unit that may hold it + unit = ureg_get_rsc_owner(rsc); + if (unit == NULL) { + // try one of the built-in ones + if (RSC_IS_HELD(UNIT_SYSTEM.resources, rsc)) unit = &UNIT_SYSTEM; + else if (RSC_IS_HELD(UNIT_PLATFORM.resources, rsc)) unit = &UNIT_PLATFORM; + } - if (unit == NULL || resources[rsc].owner == unit) { - resources[rsc].owner = NULL; + if (unit != NULL) RSC_FREE(unit->resources, rsc); } + + // also free it in the global map + RSC_FREE(global_rscmap, rsc); } /** @@ -142,13 +187,12 @@ void rsc_free(Unit *unit, Resource rsc) void rsc_free_range(Unit *unit, Resource rsc0, Resource rsc1) { assert_param(rsc_initialized); - assert_param(rsc0 > R_NONE && rsc0 < R_RESOURCE_COUNT); - assert_param(rsc1 > R_NONE && rsc1 < R_RESOURCE_COUNT); + assert_param(rsc0 < RESOURCE_COUNT); + assert_param(rsc1 < RESOURCE_COUNT); + assert_param(rsc0 <= rsc1); for (int i = rsc0; i <= rsc1; i++) { - if (unit == NULL || resources[i].owner == unit) { - resources[i].owner = NULL; - } + rsc_free(unit, (Resource) i); } } @@ -162,9 +206,8 @@ void rsc_teardown(Unit *unit) assert_param(rsc_initialized); assert_param(unit != NULL); - for (int i = R_NONE+1; i < R_RESOURCE_COUNT; i++) { - if (resources[i].owner == unit) { - resources[i].owner = NULL; - } + for (uint32_t i = 0; i < RSCMAP_LEN; i++) { + global_rscmap[i] &= ~unit->resources[i]; + unit->resources[i] = 0; } } diff --git a/framework/rsc_enum.h b/framework/rsc_enum.h index 408e531..8344de4 100644 --- a/framework/rsc_enum.h +++ b/framework/rsc_enum.h @@ -7,7 +7,30 @@ // X macro: Resource name, #define XX_RESOURCES \ - X(NONE) \ + X(SPI1) X(SPI2) X(SPI3) \ + X(I2C1) X(I2C2) X(I2C3) \ + X(ADC1) X(ADC2) X(ADC3) X(ADC4) \ + X(DAC1) X(DAC2) \ + X(USART1) X(USART2) X(USART3) X(USART4) X(USART5) X(USART6) \ + X(TIM1) X(TIM2) X(TIM3) X(TIM4) X(TIM5) \ + X(TIM6) X(TIM7) X(TIM8) X(TIM9) X(TIM10) X(TIM11) X(TIM12) X(TIM13) X(TIM14) \ + X(TIM15) X(TIM16) X(TIM17) \ + X(DMA1) X(DMA2) + +// Resources not used anywhere: +// X(I2S1) X(I2S2) X(I2S3) +// X(OPAMP1) X(OPAMP2) X(OPAMP3) X(OPAMP4) +// X(CAN1) X(CAN2) +// X(TSC) +// X(DCMI) +// X(ETH) +// X(FSMC) +// X(SDIO) +// X(RNG) X(LCD) +// X(HDMI_CEC) +// X(COMP1) X(COMP2) X(COMP3) X(COMP4) X(COMP5) X(COMP6) X(COMP7) + +#define XX_RESOURCES_GPIO \ X(PA0) X(PA1) X(PA2) X(PA3) X(PA4) X(PA5) X(PA6) X(PA7) \ X(PA8) X(PA9) X(PA10) X(PA11) X(PA12) X(PA13) X(PA14) X(PA15) \ X(PB0) X(PB1) X(PB2) X(PB3) X(PB4) X(PB5) X(PB6) X(PB7) \ @@ -20,26 +43,6 @@ X(PE8) X(PE9) X(PE10) X(PE11) X(PE12) X(PE13) X(PE14) X(PE15) \ X(PF0) X(PF1) X(PF2) X(PF3) X(PF4) X(PF5) X(PF6) X(PF7) \ X(PF8) X(PF9) X(PF10) X(PF11) X(PF12) X(PF13) X(PF14) X(PF15) \ - X(SPI1) X(SPI2) X(SPI3) \ - X(I2C1) X(I2C2) X(I2C3) \ - X(I2S1) X(I2S2) X(I2S3) \ - X(ADC1) X(ADC2) X(ADC3) X(ADC4) \ - X(OPAMP1) X(OPAMP2) X(OPAMP3) X(OPAMP4) \ - X(DAC1) X(DAC2) \ - X(CAN1) X(CAN2) \ - X(TSC) \ - X(DCMI) \ - X(ETH) \ - X(FSMC) \ - X(SDIO) \ - X(COMP1) X(COMP2) X(COMP3) X(COMP4) X(COMP5) X(COMP6) X(COMP7) \ - X(HDMI_CEC) \ - X(USART1) X(USART2) X(USART3) X(USART4) X(USART5) X(USART6) \ - X(TIM1) X(TIM2) X(TIM3) X(TIM4) X(TIM5) \ - X(TIM6) X(TIM7) X(TIM8) X(TIM9) X(TIM10) X(TIM11) X(TIM12) X(TIM13) X(TIM14) \ - X(TIM15) X(TIM16) X(TIM17) \ - X(DMA1) X(DMA2) \ - X(RNG) X(LCD) // GPIOs are allocated whenever the pin is needed // (e.g. when used for SPI, the R_SPI resource as well as the corresponding R_GPIO resources must be claimed) @@ -70,8 +73,20 @@ typedef enum hw_resource Resource; enum hw_resource { #define X(res_name) R_##res_name, XX_RESOURCES + XX_RESOURCES_GPIO #undef X - R_RESOURCE_COUNT + R_NONE, + RESOURCE_COUNT = R_NONE, }; +#define RSCMAP_LEN ((RESOURCE_COUNT/8)+1) + +typedef uint8_t ResourceMap[RSCMAP_LEN]; + +#define RSC_IS_FREE(rscmap, rsc) (0 == (rscmap[((rsc)>>3)&0xFF] & (1<<((rsc)&0x7)))) +#define RSC_IS_HELD(rscmap, rsc) (!RSC_IS_FREE(rscmap, rsc)) +#define RSC_CLAIM(rscmap, rsc) do { rscmap[((rsc)>>3)&0xFF] |= (1<<((rsc)&0x7)); } while(0) +#define RSC_FREE(rscmap, rsc) do { rscmap[((rsc)>>3)&0xFF] &= ~(1<<((rsc)&0x7)); } while(0) + + #endif //GEX_F072_RSC_ENUM_H diff --git a/framework/unit.h b/framework/unit.h index 604cdee..3b530b1 100644 --- a/framework/unit.h +++ b/framework/unit.h @@ -42,6 +42,9 @@ struct unit { /** If RSC not avail. error is caught, the resource is stored here. */ Resource failed_rsc; + + /** Bit-map of held resources */ + ResourceMap resources; }; /** diff --git a/framework/unit_registry.c b/framework/unit_registry.c index 3d6a8e1..79d7710 100644 --- a/framework/unit_registry.c +++ b/framework/unit_registry.c @@ -530,3 +530,15 @@ void ureg_report_active_units(TF_ID frame_id) } free(buff); } + +Unit *ureg_get_rsc_owner(Resource resource) +{ + UlistEntry *li = ulist_head; + while (li != NULL) { + if (RSC_IS_HELD(li->unit.resources, resource)) { + return &li->unit; + } + li = li->next; + } + return NULL; +} diff --git a/framework/unit_registry.h b/framework/unit_registry.h index c9c17e9..bb4ecbb 100644 --- a/framework/unit_registry.h +++ b/framework/unit_registry.h @@ -127,4 +127,12 @@ void ureg_deliver_unit_request(TF_Msg *msg); */ void ureg_report_active_units(TF_ID frame_id); +/** + * Get unit holding a resource, or NULL. + * + * @param resource + * @return unit + */ +Unit *ureg_get_rsc_owner(Resource resource); + #endif //GEX_UNIT_REGISTRY_H diff --git a/gex.mk b/gex.mk index 8eb9e9a..7bb2042 100644 --- a/gex.mk +++ b/gex.mk @@ -83,7 +83,7 @@ GEX_CDEFS = $(GEX_CDEFS_BASE) \ -DVERBOSE_ASSERT=1 \ -DDEBUG_VFS=0 \ -DDEBUG_FLASH_WRITE=0 \ - -DVERBOSE_HARDFAULT=1 \ + -DVERBOSE_HARDFAULT=0 \ -DUSE_STACK_MONITOR=0 \ -DUSE_DEBUG_UART=1 diff --git a/platform/pin_utils.c b/platform/pin_utils.c index 5a25cb2..db1a50d 100644 --- a/platform/pin_utils.c +++ b/platform/pin_utils.c @@ -208,17 +208,17 @@ char * str_pinmask(uint16_t pins, char *buffer) } else { if (on) { if (!first) { - b += sprintf(b, ","); + b += SPRINTF(b, ","); } if (start == (uint32_t)(i+1)) { - b += sprintf(b, "%"PRIu32, start); + b += SPRINTF(b, "%"PRIu32, start); } else if (start == (uint32_t)(i+2)) { // exception for 2-long ranges - don't show as range - b += sprintf(b, "%"PRIu32",%"PRIu32, start, i + 1); + b += SPRINTF(b, "%"PRIu32",%"PRIu32, start, i + 1); } else { - b += sprintf(b, "%"PRIu32"-%"PRIu32, start, i + 1); + b += SPRINTF(b, "%"PRIu32"-%"PRIu32, start, i + 1); } first = false; on = false; diff --git a/platform/platform.c b/platform/platform.c index bfd439f..56ca9a3 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -83,13 +83,13 @@ void plat_init_resources(void) // Free all present resources { rsc_free(NULL, R_ADC1); - rsc_free(NULL, R_CAN1); - rsc_free_range(NULL, R_COMP1, R_COMP2); +// rsc_free(NULL, R_CAN1); +// rsc_free_range(NULL, R_COMP1, R_COMP2); rsc_free(NULL, R_DAC1); - rsc_free(NULL, R_HDMI_CEC); - rsc_free(NULL, R_TSC); +// rsc_free(NULL, R_HDMI_CEC); +// rsc_free(NULL, R_TSC); rsc_free_range(NULL, R_I2C1, R_I2C2); - rsc_free_range(NULL, R_I2S1, R_I2S2); +// rsc_free_range(NULL, R_I2S1, R_I2S2); rsc_free_range(NULL, R_SPI1, R_SPI2); rsc_free_range(NULL, R_TIM1, R_TIM3); rsc_free_range(NULL, R_TIM6, R_TIM7); @@ -131,18 +131,18 @@ void plat_init_resources(void) // Free all present resources { rsc_free_range(NULL, R_ADC1, R_ADC4); - rsc_free(NULL, R_CAN1); - rsc_free_range(NULL, R_COMP1, R_COMP7); - rsc_free(NULL, R_HDMI_CEC); +// rsc_free(NULL, R_CAN1); +// rsc_free_range(NULL, R_COMP1, R_COMP7); +// rsc_free(NULL, R_HDMI_CEC); rsc_free(NULL, R_DAC1); rsc_free_range(NULL, R_I2C1, R_I2C2); rsc_free_range(NULL, R_I2S2, R_I2S3); - rsc_free_range(NULL, R_OPAMP1, R_OPAMP4); +// rsc_free_range(NULL, R_OPAMP1, R_OPAMP4); rsc_free_range(NULL, R_SPI1, R_SPI3); rsc_free_range(NULL, R_TIM1, R_TIM4); rsc_free_range(NULL, R_TIM6, R_TIM8); rsc_free_range(NULL, R_TIM15, R_TIM17); - rsc_free(NULL, R_TSC); +// rsc_free(NULL, R_TSC); rsc_free_range(NULL, R_USART1, R_USART5); rsc_free_range(NULL, R_PA0, R_PA15); @@ -184,15 +184,15 @@ void plat_init_resources(void) // Free all present resources { rsc_free_range(NULL, R_ADC1, R_ADC3); - rsc_free_range(NULL, R_CAN1, R_CAN2); - rsc_free_range(NULL, R_COMP1, R_COMP7); +// rsc_free_range(NULL, R_CAN1, R_CAN2); +// rsc_free_range(NULL, R_COMP1, R_COMP7); rsc_free(NULL, R_DAC1); - rsc_free(NULL, R_DCMI); - rsc_free(NULL, R_ETH); - rsc_free(NULL, R_FSMC); +// rsc_free(NULL, R_DCMI); +// rsc_free(NULL, R_ETH); +// rsc_free(NULL, R_FSMC); rsc_free_range(NULL, R_I2C1, R_I2C3); rsc_free_range(NULL, R_I2S2, R_I2S3); - rsc_free(NULL, R_SDIO); +// rsc_free(NULL, R_SDIO); rsc_free_range(NULL, R_SPI1, R_SPI3); rsc_free_range(NULL, R_TIM1, R_TIM14); rsc_free_range(NULL, R_USART1, R_USART3); diff --git a/utils/error.h b/utils/error.h index 9b52727..1b294a5 100644 --- a/utils/error.h +++ b/utils/error.h @@ -58,7 +58,7 @@ X(BAD_KEY, "Unexpected config key") \ X(BAD_VALUE, "Bad config value") \ X(OUT_OF_MEM, "Not enough RAM") \ - X(RESOURCE_NOT_AVAILABLE, "Required pin / peripheral not available") + X(RESOURCE_NOT_AVAILABLE, NULL) // Keep in sync with the list error_message typedef enum {