Skip to content

Commit 0dee05a

Browse files
committed
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.
1 parent 8669417 commit 0dee05a

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

hal/mbed_pinmap_common.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,77 @@ uint32_t pinmap_function(PinName pin, const PinMap *map)
104104
}
105105
return function;
106106
}
107+
108+
bool pinmap_find_peripheral_pins(const PinList *whitelist, const PinList *blacklist, int per, const PinMap *const *maps, PinName **pins, uint32_t count)
109+
{
110+
/*
111+
* This function uses recursion to find a suitable set of pins which meet the requirements.
112+
* Recursion is at max the number of pinmaps passed in - the 'count' parameter. Because of this
113+
* there is no risk of a stack overflow due to unbounded recursion.
114+
*
115+
* Below is a psuedo code example of this function's operation when finding a set of 4 pins.
116+
* The recursion depth is indicated by the number in front.
117+
*
118+
* 1. Given 4 maps and a peripheral find 4 suitable pins
119+
* 2. Given 4 maps, a peripheral and 1 pin find 3 suitable pins
120+
* 3. Given 4 maps, a peripheral and 2 pins find 2 suitable pins
121+
* 4. Given 4 maps, a peripheral and 3 pins find 1 suitable pin
122+
* 4. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
123+
* 3. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
124+
* 2. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
125+
* 1. Return success if all pins are found, return failure if there are no suitable pins, otherwise choose the next pin and retry
126+
*
127+
*/
128+
129+
for (uint32_t i = 0; i < count; i++) {
130+
const PinMap *map = maps[i];
131+
PinName *pin = pins[i];
132+
if (*pin == NC) {
133+
for (; map->pin != NC; map++) {
134+
if (map->peripheral != per) {
135+
continue;
136+
}
137+
if (!pinmap_list_has_pin(whitelist, map->pin)) {
138+
// Not part of this form factor
139+
continue;
140+
}
141+
if (pinmap_list_has_pin(blacklist, map->pin)) {
142+
// Restricted pin
143+
continue;
144+
}
145+
bool already_in_use = false;
146+
for (uint32_t j = 0; j < count; j++) {
147+
if (j == i) {
148+
// Don't compare with self
149+
continue;
150+
}
151+
if (map->pin == *pins[j]) {
152+
already_in_use = true;
153+
break;
154+
}
155+
}
156+
if (already_in_use) {
157+
continue;
158+
}
159+
*pin = map->pin;
160+
if (pinmap_find_peripheral_pins(whitelist, blacklist, per, maps, pins, count)) {
161+
return true;
162+
}
163+
}
164+
*pin = NC;
165+
return false;
166+
}
167+
}
168+
return true;
169+
}
170+
171+
bool pinmap_list_has_pin(const PinList *list, PinName pin)
172+
{
173+
for (uint32_t i = 0; i < list->count; i++) {
174+
if (list->pins[i] == pin) {
175+
return true;
176+
}
177+
}
178+
return false;
179+
}
180+

hal/pinmap.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define MBED_PINMAP_H
2222

2323
#include "PinNames.h"
24+
#include <stdbool.h>
2425

2526
#ifdef __cplusplus
2627
extern "C" {
@@ -32,6 +33,11 @@ typedef struct {
3233
int function;
3334
} PinMap;
3435

36+
typedef struct {
37+
uint32_t count;
38+
const PinName *pins;
39+
} PinList;
40+
3541
void pin_function(PinName pin, int function);
3642
void pin_mode(PinName pin, PinMode mode);
3743

@@ -42,6 +48,81 @@ void pinmap_pinout(PinName pin, const PinMap *map);
4248
uint32_t pinmap_find_peripheral(PinName pin, const PinMap *map);
4349
uint32_t pinmap_find_function(PinName pin, const PinMap *map);
4450

51+
/**
52+
* Find a combination of pins suitable for use given the constraints
53+
*
54+
* This function finds pins which meet these specific properties:
55+
* - The pin is part of the form factor
56+
* - The pin is not in the restricted list
57+
* - The pin is contained within the respective pinmap
58+
* - The pin belongs to the given peripheral
59+
* - Each pin found is distinct; in the example below
60+
* mosi and miso will never be assigned the same pin
61+
*
62+
* Example:
63+
* @code
64+
* #include "mbed.h"
65+
* #include "pinmap.h"
66+
*
67+
* int main()
68+
* {
69+
* int per = spi_master_cs_pinmap()->peripheral;
70+
* const PinList *pins_ff = pinmap_ff_default_pins();
71+
* const PinList *pins_avoid = pinmap_restricted_pins();
72+
* PinName mosi = NC;
73+
* PinName miso = NC;
74+
* PinName sclk = NC;
75+
* PinName ssel = NC;
76+
* const PinMap *maps[] = {
77+
* spi_master_mosi_pinmap(),
78+
* spi_master_miso_pinmap(),
79+
* spi_master_clk_pinmap(),
80+
* spi_master_cs_pinmap()
81+
* };
82+
* PinName *pins[] = {
83+
* &mosi,
84+
* &miso,
85+
* &sclk,
86+
* &ssel
87+
* };
88+
* if (pinmap_find_peripheral_pins(pins_ff, pins_avoid, per, maps, pins, sizeof(maps) / sizeof(maps[0]))) {
89+
* printf("Found SPI pins to test instance %i with:\n"
90+
* " mosi=%s\n"
91+
* " miso=%s\n"
92+
* " sclk=%s\n"
93+
* " ssel=%s\n", per,
94+
* pinmap_ff_default_pin_to_string(mosi),
95+
* pinmap_ff_default_pin_to_string(miso),
96+
* pinmap_ff_default_pin_to_string(sclk),
97+
* pinmap_ff_default_pin_to_string(ssel));
98+
* } else {
99+
* printf("Could not find SPI combination to test %i\n", per);
100+
* }
101+
* return 0;
102+
* }
103+
* @endcode
104+
*
105+
* @param whitelist List of pins to choose from
106+
* @param blacklist List of pins which cannot be used
107+
* @param per Peripheral to which the pins belong
108+
* @param maps An array of pin maps to select from
109+
* @param pins An array of pins to find. Pins already set to a value will be
110+
* left unchanged. Only pins initialized to NC will be updated by this function
111+
* @param count The size of maps and pins
112+
* @return true if a suitable combination of pins was found and
113+
* written to the pins array, otherwise false
114+
*/
115+
bool pinmap_find_peripheral_pins(const PinList *whitelist, const PinList *blacklist, int per, const PinMap *const *maps, PinName **pins, uint32_t count);
116+
117+
/**
118+
* Check if the pin is in the list
119+
*
120+
* @param list pin list to check
121+
* @param pin pin to check for in the list
122+
* @return true if the pin is in the list, false otherwise
123+
*/
124+
bool pinmap_list_has_pin(const PinList *list, PinName pin);
125+
45126
#ifdef __cplusplus
46127
}
47128
#endif

0 commit comments

Comments
 (0)