Add pinmap utility functions

Add 2 new pinmap utility functions:
-pinmap_find_peripheral_pins
-pinmap_list_has_pin

Also add the new type PinList which contains a list of pins allowing
for NC and duplicate entries.
pull/9449/head
Russ Butler 2019-01-21 16:30:48 -06:00
parent 8669417e7b
commit 0dee05a843
2 changed files with 155 additions and 0 deletions

View File

@ -104,3 +104,77 @@ uint32_t pinmap_function(PinName pin, const PinMap *map)
}
return function;
}
bool pinmap_find_peripheral_pins(const PinList *whitelist, const PinList *blacklist, int per, const PinMap *const *maps, PinName **pins, uint32_t count)
{
/*
* This function uses recursion to find a suitable set of pins which meet the requirements.
* Recursion is at max the number of pinmaps passed in - the 'count' parameter. Because of this
* there is no risk of a stack overflow due to unbounded recursion.
*
* Below is a psuedo code example of this function's operation when finding a set of 4 pins.
* The recursion depth is indicated by the number in front.
*
* 1. Given 4 maps and a peripheral find 4 suitable pins
* 2. Given 4 maps, a peripheral and 1 pin find 3 suitable pins
* 3. Given 4 maps, a peripheral and 2 pins find 2 suitable pins
* 4. Given 4 maps, a peripheral and 3 pins find 1 suitable pin
* 4. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
* 3. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
* 2. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
* 1. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
*
*/
for (uint32_t i = 0; i < count; i++) {
const PinMap *map = maps[i];
PinName *pin = pins[i];
if (*pin == NC) {
for (; map->pin != NC; map++) {
if (map->peripheral != per) {
continue;
}
if (!pinmap_list_has_pin(whitelist, map->pin)) {
// Not part of this form factor
continue;
}
if (pinmap_list_has_pin(blacklist, map->pin)) {
// Restricted pin
continue;
}
bool already_in_use = false;
for (uint32_t j = 0; j < count; j++) {
if (j == i) {
// Don't compare with self
continue;
}
if (map->pin == *pins[j]) {
already_in_use = true;
break;
}
}
if (already_in_use) {
continue;
}
*pin = map->pin;
if (pinmap_find_peripheral_pins(whitelist, blacklist, per, maps, pins, count)) {
return true;
}
}
*pin = NC;
return false;
}
}
return true;
}
bool pinmap_list_has_pin(const PinList *list, PinName pin)
{
for (uint32_t i = 0; i < list->count; i++) {
if (list->pins[i] == pin) {
return true;
}
}
return false;
}

View File

@ -21,6 +21,7 @@
#define MBED_PINMAP_H
#include "PinNames.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@ -32,6 +33,11 @@ typedef struct {
int function;
} PinMap;
typedef struct {
uint32_t count;
const PinName *pins;
} PinList;
void pin_function(PinName pin, int function);
void pin_mode(PinName pin, PinMode mode);
@ -42,6 +48,81 @@ void pinmap_pinout(PinName pin, const PinMap *map);
uint32_t pinmap_find_peripheral(PinName pin, const PinMap *map);
uint32_t pinmap_find_function(PinName pin, const PinMap *map);
/**
* Find a combination of pins suitable for use given the constraints
*
* This function finds pins which meet these specific properties:
* - The pin is part of the form factor
* - The pin is not in the restricted list
* - The pin is contained within the respective pinmap
* - The pin belongs to the given peripheral
* - Each pin found is distinct; in the example below
* mosi and miso will never be assigned the same pin
*
* Example:
* @code
* #include "mbed.h"
* #include "pinmap.h"
*
* int main()
* {
* int per = spi_master_cs_pinmap()->peripheral;
* const PinList *pins_ff = pinmap_ff_default_pins();
* const PinList *pins_avoid = pinmap_restricted_pins();
* PinName mosi = NC;
* PinName miso = NC;
* PinName sclk = NC;
* PinName ssel = NC;
* const PinMap *maps[] = {
* spi_master_mosi_pinmap(),
* spi_master_miso_pinmap(),
* spi_master_clk_pinmap(),
* spi_master_cs_pinmap()
* };
* PinName *pins[] = {
* &mosi,
* &miso,
* &sclk,
* &ssel
* };
* if (pinmap_find_peripheral_pins(pins_ff, pins_avoid, per, maps, pins, sizeof(maps) / sizeof(maps[0]))) {
* printf("Found SPI pins to test instance %i with:\n"
* " mosi=%s\n"
* " miso=%s\n"
* " sclk=%s\n"
* " ssel=%s\n", per,
* pinmap_ff_default_pin_to_string(mosi),
* pinmap_ff_default_pin_to_string(miso),
* pinmap_ff_default_pin_to_string(sclk),
* pinmap_ff_default_pin_to_string(ssel));
* } else {
* printf("Could not find SPI combination to test %i\n", per);
* }
* return 0;
* }
* @endcode
*
* @param whitelist List of pins to choose from
* @param blacklist List of pins which cannot be used
* @param per Peripheral to which the pins belong
* @param maps An array of pin maps to select from
* @param pins An array of pins to find. Pins already set to a value will be
* left unchanged. Only pins initialized to NC will be updated by this function
* @param count The size of maps and pins
* @return true if a suitable combination of pins was found and
* written to the pins array, otherwise false
*/
bool pinmap_find_peripheral_pins(const PinList *whitelist, const PinList *blacklist, int per, const PinMap *const *maps, PinName **pins, uint32_t count);
/**
* Check if the pin is in the list
*
* @param list pin list to check
* @param pin pin to check for in the list
* @return true if the pin is in the list, false otherwise
*/
bool pinmap_list_has_pin(const PinList *list, PinName pin);
#ifdef __cplusplus
}
#endif