|
|
|
@ -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; |
|
|
|
|
|
|
|
|
|
if (unit == NULL || resources[rsc].owner == unit) { |
|
|
|
|
resources[rsc].owner = NULL; |
|
|
|
|
// 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) 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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|