Skip to content

Commit 8f932a4

Browse files
authored
Merge pull request #9449 from c1728p9/pinmap-extension
Pinmap extensions
2 parents 830c3ec + d5892ce commit 8f932a4

File tree

389 files changed

+8785
-6
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

389 files changed

+8785
-6
lines changed

TESTS/mbed_hal/pinmap/main.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2019 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "utest/utest.h"
18+
#include "unity/unity.h"
19+
#include "greentea-client/test_env.h"
20+
21+
using namespace utest::v1;
22+
23+
#include "analogin_api.h"
24+
#include "analogout_api.h"
25+
#include "can_api.h"
26+
#include "i2c_api.h"
27+
#include "pwmout_api.h"
28+
#include "qspi_api.h"
29+
#include "serial_api.h"
30+
#include "spi_api.h"
31+
32+
#define PINMAP_TEST_ENTRY(function) {function, #function}
33+
34+
typedef const PinMap *(*get_pinmap_func_t)(void);
35+
typedef struct {
36+
get_pinmap_func_t function;
37+
const char *name;
38+
} pinmap_info_t;
39+
40+
const pinmap_info_t pinmap_functions[] = {
41+
#if DEVICE_ANALOGIN
42+
PINMAP_TEST_ENTRY(analogin_pinmap),
43+
#endif
44+
#if DEVICE_ANALOGOUT
45+
PINMAP_TEST_ENTRY(analogout_pinmap),
46+
#endif
47+
#if DEVICE_CAN
48+
PINMAP_TEST_ENTRY(can_rd_pinmap),
49+
PINMAP_TEST_ENTRY(can_td_pinmap),
50+
#endif
51+
#if DEVICE_I2C
52+
PINMAP_TEST_ENTRY(i2c_master_sda_pinmap),
53+
PINMAP_TEST_ENTRY(i2c_master_scl_pinmap),
54+
#if DEVICE_I2CSLAVE
55+
PINMAP_TEST_ENTRY(i2c_slave_sda_pinmap),
56+
PINMAP_TEST_ENTRY(i2c_slave_scl_pinmap),
57+
#endif
58+
#endif
59+
#if DEVICE_PWMOUT
60+
PINMAP_TEST_ENTRY(pwmout_pinmap),
61+
#endif
62+
#if DEVICE_QSPI
63+
PINMAP_TEST_ENTRY(qspi_master_sclk_pinmap),
64+
PINMAP_TEST_ENTRY(qspi_master_ssel_pinmap),
65+
PINMAP_TEST_ENTRY(qspi_master_data0_pinmap),
66+
PINMAP_TEST_ENTRY(qspi_master_data1_pinmap),
67+
PINMAP_TEST_ENTRY(qspi_master_data2_pinmap),
68+
PINMAP_TEST_ENTRY(qspi_master_data3_pinmap),
69+
#endif
70+
#if DEVICE_SERIAL
71+
PINMAP_TEST_ENTRY(serial_tx_pinmap),
72+
PINMAP_TEST_ENTRY(serial_rx_pinmap),
73+
#if DEVICE_SERIAL_FC
74+
PINMAP_TEST_ENTRY(serial_cts_pinmap),
75+
PINMAP_TEST_ENTRY(serial_rts_pinmap),
76+
#endif
77+
#endif
78+
#if DEVICE_SPI
79+
PINMAP_TEST_ENTRY(spi_master_mosi_pinmap),
80+
PINMAP_TEST_ENTRY(spi_master_miso_pinmap),
81+
PINMAP_TEST_ENTRY(spi_master_clk_pinmap),
82+
PINMAP_TEST_ENTRY(spi_master_cs_pinmap),
83+
#if DEVICE_SPISLAVE
84+
PINMAP_TEST_ENTRY(spi_slave_mosi_pinmap),
85+
PINMAP_TEST_ENTRY(spi_slave_miso_pinmap),
86+
PINMAP_TEST_ENTRY(spi_slave_clk_pinmap),
87+
PINMAP_TEST_ENTRY(spi_slave_cs_pinmap),
88+
#endif
89+
#endif
90+
{NULL, NULL}
91+
};
92+
93+
void pinmap_validation()
94+
{
95+
for (size_t i = 0; i < sizeof(pinmap_functions) / sizeof(pinmap_functions[0]) - 1; i++) {
96+
printf("Testing pinmap %s\r\n", pinmap_functions[i].name);
97+
98+
get_pinmap_func_t function = pinmap_functions[i].function;
99+
TEST_ASSERT_NOT_EQUAL(NULL, function);
100+
101+
const PinMap *map = function();
102+
TEST_ASSERT_NOT_EQUAL(NULL, map);
103+
104+
while (map->pin != NC) {
105+
map++;
106+
}
107+
108+
TEST_ASSERT_EQUAL(NC, map->peripheral);
109+
}
110+
}
111+
112+
Case cases[] = {
113+
Case("pinmap - validation", pinmap_validation)
114+
};
115+
116+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
117+
{
118+
GREENTEA_SETUP(20, "default_auto");
119+
return greentea_test_setup_handler(number_of_cases);
120+
}
121+
122+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
123+
124+
int main()
125+
{
126+
Harness::run(specification);
127+
}

hal/analogin_api.h

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

2323
#include "device.h"
24+
#include "pinmap.h"
2425

2526
#if DEVICE_ANALOGIN
2627

@@ -59,6 +60,15 @@ float analogin_read(analogin_t *obj);
5960
*/
6061
uint16_t analogin_read_u16(analogin_t *obj);
6162

63+
/** Get the pins that support analogin
64+
*
65+
* Return a PinMap array of pins that support analogin. The
66+
* array is terminated with {NC, NC, 0}.
67+
*
68+
* @return PinMap array
69+
*/
70+
const PinMap *analogin_pinmap(void);
71+
6272
/**@}*/
6373

6474
#ifdef __cplusplus

hal/analogout_api.h

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

2323
#include "device.h"
24+
#include "pinmap.h"
2425

2526
#if DEVICE_ANALOGOUT
2627

@@ -81,6 +82,15 @@ float analogout_read(dac_t *obj);
8182
*/
8283
uint16_t analogout_read_u16(dac_t *obj);
8384

85+
/** Get the pins that support analogout
86+
*
87+
* Return a PinMap array of pins that support analogout. The
88+
* array is terminated with {NC, NC, 0}.
89+
*
90+
* @return PinMap array
91+
*/
92+
const PinMap *analogout_pinmap(void);
93+
8494
/**@}*/
8595

8696
#ifdef __cplusplus

hal/can_api.h

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

2323
#include "device.h"
24+
#include "pinmap.h"
2425

2526
#if DEVICE_CAN
2627

@@ -76,6 +77,24 @@ unsigned char can_rderror(can_t *obj);
7677
unsigned char can_tderror(can_t *obj);
7778
void can_monitor(can_t *obj, int silent);
7879

80+
/** Get the pins that support CAN RD
81+
*
82+
* Return a PinMap array of pins that support CAN RD. The
83+
* array is terminated with {NC, NC, 0}.
84+
*
85+
* @return PinMap array
86+
*/
87+
const PinMap *can_rd_pinmap(void);
88+
89+
/** Get the pins that support CAN TD
90+
*
91+
* Return a PinMap array of pins that support CAN TD. The
92+
* array is terminated with {NC, NC, 0}.
93+
*
94+
* @return PinMap array
95+
*/
96+
const PinMap *can_td_pinmap(void);
97+
7998
#ifdef __cplusplus
8099
};
81100
#endif

hal/i2c_api.h

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

2323
#include "device.h"
24+
#include "pinmap.h"
2425
#include "hal/buffer.h"
2526

2627
#if DEVICE_I2C_ASYNCH
@@ -146,6 +147,42 @@ int i2c_byte_read(i2c_t *obj, int last);
146147
*/
147148
int i2c_byte_write(i2c_t *obj, int data);
148149

150+
/** Get the pins that support I2C SDA
151+
*
152+
* Return a PinMap array of pins that support I2C SDA in
153+
* master mode. The array is terminated with {NC, NC, 0}.
154+
*
155+
* @return PinMap array
156+
*/
157+
const PinMap *i2c_master_sda_pinmap(void);
158+
159+
/** Get the pins that support I2C SCL
160+
*
161+
* Return a PinMap array of pins that support I2C SCL in
162+
* master mode. The array is terminated with {NC, NC, 0}.
163+
*
164+
* @return PinMap array
165+
*/
166+
const PinMap *i2c_master_scl_pinmap(void);
167+
168+
/** Get the pins that support I2C SDA
169+
*
170+
* Return a PinMap array of pins that support I2C SDA in
171+
* slave mode. The array is terminated with {NC, NC, 0}.
172+
*
173+
* @return PinMap array
174+
*/
175+
const PinMap *i2c_slave_sda_pinmap(void);
176+
177+
/** Get the pins that support I2C SCL
178+
*
179+
* Return a PinMap array of pins that support I2C SCL in
180+
* slave mode. The array is terminated with {NC, NC, 0}.
181+
*
182+
* @return PinMap array
183+
*/
184+
const PinMap *i2c_slave_scl_pinmap(void);
185+
149186
/**@}*/
150187

151188
#if DEVICE_I2CSLAVE

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+

0 commit comments

Comments
 (0)