From e82306c36f338ae2284919c186b84f58f93347d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 6 Jan 2018 16:09:54 +0100 Subject: [PATCH] added more informative error message to unit failed due to rsc not avail --- framework/resources.c | 21 ++++++++++- framework/resources.h | 75 +++----------------------------------- framework/rsc_enum.h | 77 +++++++++++++++++++++++++++++++++++++++ framework/unit.h | 8 +++- framework/unit_registry.c | 9 ++++- 5 files changed, 117 insertions(+), 73 deletions(-) create mode 100644 framework/rsc_enum.h diff --git a/framework/resources.c b/framework/resources.c index e901e81..6e7b9b6 100644 --- a/framework/resources.c +++ b/framework/resources.c @@ -24,6 +24,21 @@ const char *const rsc_names[] = { #undef X }; +/** Get rsc name */ +const char * rsc_get_name(Resource rsc) +{ + assert_param(rsc < R_RESOURCE_COUNT); + 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; +} + /** * Initialize the resources registry */ @@ -51,7 +66,11 @@ error_t rsc_claim(Unit *unit, Resource rsc) if (resources[rsc].owner) { //TODO properly report to user dbg("ERROR!! Unit %s failed to claim resource %s, already held by %s!", - unit->name, rsc_names[rsc], resources[rsc].owner->name); + unit->name, + rsc_get_name(rsc), + rsc_get_owner_name(rsc)); + + unit->failed_rsc = rsc; return E_RESOURCE_NOT_AVAILABLE; } diff --git a/framework/resources.h b/framework/resources.h index e9f6254..8290cf4 100644 --- a/framework/resources.h +++ b/framework/resources.h @@ -7,78 +7,10 @@ #include "platform.h" #include "unit.h" +#include "rsc_enum.h" #define CHECK_SUC() do { if (!suc) return false; } while (0) -// X macro: Resource name, -#define XX_RESOURCES \ - X(NONE) \ - 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) \ - X(PB8) X(PB9) X(PB10) X(PB11) X(PB12) X(PB13) X(PB14) X(PB15) \ - X(PC0) X(PC1) X(PC2) X(PC3) X(PC4) X(PC5) X(PC6) X(PC7) \ - X(PC8) X(PC9) X(PC10) X(PC11) X(PC12) X(PC13) X(PC14) X(PC15) \ - X(PD0) X(PD1) X(PD2) X(PD3) X(PD4) X(PD5) X(PD6) X(PD7) \ - X(PD8) X(PD9) X(PD10) X(PD11) X(PD12) X(PD13) X(PD14) X(PD15) \ - X(PE0) X(PE1) X(PE2) X(PE3) X(PE4) X(PE5) X(PE6) X(PE7) \ - 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) - -// Peripheral blocks (IPs) - not all chips have all blocks, usually the 1 and 2 are present as a minimum, if any. -// It doesn't really make sense to expose multiple instances of buses that support addressing - -// ADCs - some more advanced chips support differential input mode on some (not all!) inputs -// Usually only one or two instances are present - -// DAC - often only one is present, or none. - -// UARTs -// - 1 and 2 are present universally, 2 is connected to VCOM on Nucleo/Discovery boards, good for debug messages -// 4 and 5 don't support synchronous mode. - -// Timers -// - some support quadrature input, probably all support external clock / gating / clock-out/PWM generation -// Not all chips have all timers and not all timers are equal. - -// DMA - Direct memory access lines - TODO split those to channels, they can be used separately - -// The resource registry will be pre-loaded with platform-specific config of which blocks are available - the rest will be "pre-claimed" -// (i.e. unavailable to functional modules) - -typedef enum hw_resource Resource; - -enum hw_resource { -#define X(res_name) R_##res_name, - XX_RESOURCES -#undef X - R_RESOURCE_COUNT -}; - void rsc_init_registry(void); error_t rsc_claim(Unit *unit, Resource rsc); @@ -98,4 +30,9 @@ void rsc_teardown(Unit *unit); void rsc_free(Unit *unit, Resource rsc); void rsc_free_range(Unit *unit, Resource rsc0, Resource rsc1); +const char * rsc_get_name(Resource rsc); + +/** Get rsc owner name */ +const char * rsc_get_owner_name(Resource rsc); + #endif //GEX_RESOURCES_H diff --git a/framework/rsc_enum.h b/framework/rsc_enum.h new file mode 100644 index 0000000..408e531 --- /dev/null +++ b/framework/rsc_enum.h @@ -0,0 +1,77 @@ +// +// Created by MightyPork on 2018/01/06. +// + +#ifndef GEX_F072_RSC_ENUM_H +#define GEX_F072_RSC_ENUM_H + +// X macro: Resource name, +#define XX_RESOURCES \ + X(NONE) \ + 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) \ + X(PB8) X(PB9) X(PB10) X(PB11) X(PB12) X(PB13) X(PB14) X(PB15) \ + X(PC0) X(PC1) X(PC2) X(PC3) X(PC4) X(PC5) X(PC6) X(PC7) \ + X(PC8) X(PC9) X(PC10) X(PC11) X(PC12) X(PC13) X(PC14) X(PC15) \ + X(PD0) X(PD1) X(PD2) X(PD3) X(PD4) X(PD5) X(PD6) X(PD7) \ + X(PD8) X(PD9) X(PD10) X(PD11) X(PD12) X(PD13) X(PD14) X(PD15) \ + X(PE0) X(PE1) X(PE2) X(PE3) X(PE4) X(PE5) X(PE6) X(PE7) \ + 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) + +// Peripheral blocks (IPs) - not all chips have all blocks, usually the 1 and 2 are present as a minimum, if any. +// It doesn't really make sense to expose multiple instances of buses that support addressing + +// ADCs - some more advanced chips support differential input mode on some (not all!) inputs +// Usually only one or two instances are present + +// DAC - often only one is present, or none. + +// UARTs +// - 1 and 2 are present universally, 2 is connected to VCOM on Nucleo/Discovery boards, good for debug messages +// 4 and 5 don't support synchronous mode. + +// Timers +// - some support quadrature input, probably all support external clock / gating / clock-out/PWM generation +// Not all chips have all timers and not all timers are equal. + +// DMA - Direct memory access lines - TODO split those to channels, they can be used separately + +// The resource registry will be pre-loaded with platform-specific config of which blocks are available - the rest will be "pre-claimed" +// (i.e. unavailable to functional modules) + +typedef enum hw_resource Resource; + +enum hw_resource { +#define X(res_name) R_##res_name, + XX_RESOURCES +#undef X + R_RESOURCE_COUNT +}; + +#endif //GEX_F072_RSC_ENUM_H diff --git a/framework/unit.h b/framework/unit.h index 9f85696..604cdee 100644 --- a/framework/unit.h +++ b/framework/unit.h @@ -10,6 +10,7 @@ #include "utils/ini_writer.h" #include "utils/payload_builder.h" #include "utils/payload_parser.h" +#include "rsc_enum.h" #define CHECK_TYPE(_unit, _driver) do { \ if ((_unit->driver) != (_driver)) \ @@ -33,11 +34,14 @@ struct unit { */ void *data; + /** Unit call sign for messages */ + uint8_t callsign; + /** Unit init status */ error_t status; - /** Unit call sign for messages */ - uint8_t callsign; + /** If RSC not avail. error is caught, the resource is stored here. */ + Resource failed_rsc; }; /** diff --git a/framework/unit_registry.c b/framework/unit_registry.c index 575bbaa..3d6a8e1 100644 --- a/framework/unit_registry.c +++ b/framework/unit_registry.c @@ -355,7 +355,14 @@ static void export_unit_do(UlistEntry *li, IniWriter *iw) iw_section(iw, "%s:%s@%d", pUnit->driver->name, pUnit->name, (int)pUnit->callsign); if (pUnit->status != E_SUCCESS) { - iw_comment(iw, "!!! %s", error_get_message(pUnit->status)); + // special message for failed unit die to resource + if (pUnit->status == E_RESOURCE_NOT_AVAILABLE) { + iw_comment(iw, "!!! %s not available, already held by %s", + rsc_get_name(pUnit->failed_rsc), + rsc_get_owner_name(pUnit->failed_rsc)); + } else { + iw_comment(iw, "!!! %s", error_get_message(pUnit->status)); + } } pUnit->driver->cfgWriteIni(pUnit, iw); }