Skip to content

Commit 769da09

Browse files
authored
Merge pull request #136 from particle-iot/feature/mesh/hal-drivers/gpio
Feature/mesh/hal drivers/gpio
2 parents 37eddb6 + 02834e5 commit 769da09

File tree

2 files changed

+243
-40
lines changed

2 files changed

+243
-40
lines changed

hal/src/nRF52840/gpio_hal.cpp

Lines changed: 172 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,48 @@
1-
/**
2-
******************************************************************************
3-
* @file gpio_hal.c
4-
* @authors Matthew McGowan
5-
* @version V1.0.0
6-
* @date 27-Sept-2014
7-
* @brief
8-
******************************************************************************
9-
Copyright (c) 2013-2015 Particle Industries, Inc. All rights reserved.
10-
11-
This library is free software; you can redistribute it and/or
12-
modify it under the terms of the GNU Lesser General Public
13-
License as published by the Free Software Foundation, either
14-
version 3 of the License, or (at your option) any later version.
15-
16-
This library is distributed in the hope that it will be useful,
17-
but WITHOUT ANY WARRANTY; without even the implied warranty of
18-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19-
Lesser General Public License for more details.
20-
21-
You should have received a copy of the GNU Lesser General Public
22-
License along with this library; if not, see <http://www.gnu.org/licenses/>.
23-
******************************************************************************
1+
/*
2+
* Copyright (c) 2018 Particle Industries, Inc. All rights reserved.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation, either
7+
* version 3 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
2416
*/
2517

26-
/* Includes -----------------------------------------------------------------*/
18+
#include "nrf_gpio.h"
2719
#include "gpio_hal.h"
20+
#include "pinmap_impl.h"
21+
#include "hw_ticks.h"
22+
#include <stddef.h>
2823

29-
/* Private typedef ----------------------------------------------------------*/
30-
31-
/* Private define -----------------------------------------------------------*/
32-
33-
/* Private macro ------------------------------------------------------------*/
34-
35-
/* Private variables --------------------------------------------------------*/
36-
37-
/* Extern variables ---------------------------------------------------------*/
38-
39-
/* Private function prototypes ----------------------------------------------*/
24+
inline bool is_valid_pin(pin_t pin) __attribute__((always_inline));
25+
inline bool is_valid_pin(pin_t pin)
26+
{
27+
return pin < TOTAL_PINS;
28+
}
4029

4130
PinMode HAL_Get_Pin_Mode(pin_t pin)
4231
{
43-
return PIN_MODE_NONE;
32+
return (!is_valid_pin(pin)) ? PIN_MODE_NONE : HAL_Pin_Map()[pin].pin_mode;
4433
}
4534

4635
PinFunction HAL_Validate_Pin_Function(pin_t pin, PinFunction pinFunction)
4736
{
37+
NRF5x_Pin_Info* PIN_MAP = HAL_Pin_Map();
38+
39+
if (!is_valid_pin(pin))
40+
return PF_NONE;
41+
if (pinFunction==PF_ADC && PIN_MAP[pin].adc_channel != ADC_CHANNEL_NONE)
42+
return PF_ADC;
43+
// Compatible with STM32 for wiring layer
44+
if (pinFunction==PF_TIMER && PIN_MAP[pin].pwm_instance != PWM_INSTANCE_NONE)
45+
return PF_TIMER;
4846
return PF_DIO;
4947
}
5048

@@ -54,34 +52,168 @@ PinFunction HAL_Validate_Pin_Function(pin_t pin, PinFunction pinFunction)
5452
*/
5553
void HAL_Pin_Mode(pin_t pin, PinMode setMode)
5654
{
55+
if (!is_valid_pin(pin))
56+
{
57+
return;
58+
}
59+
60+
NRF5x_Pin_Info* PIN_MAP = HAL_Pin_Map();
61+
uint32_t gpio_pin_map = NRF_GPIO_PIN_MAP(PIN_MAP[pin].gpio_port, PIN_MAP[pin].gpio_pin);
62+
63+
switch (setMode)
64+
{
65+
case OUTPUT:
66+
nrf_gpio_cfg_output(gpio_pin_map);
67+
PIN_MAP[pin].pin_mode = OUTPUT;
68+
PIN_MAP[pin].pin_func = PF_DIO;
69+
break;
70+
71+
case INPUT:
72+
nrf_gpio_cfg_input(gpio_pin_map, NRF_GPIO_PIN_NOPULL);
73+
PIN_MAP[pin].pin_mode = INPUT;
74+
PIN_MAP[pin].pin_func = PF_DIO;
75+
break;
76+
77+
case INPUT_PULLUP:
78+
nrf_gpio_cfg_input(gpio_pin_map, NRF_GPIO_PIN_PULLUP);
79+
PIN_MAP[pin].pin_mode = INPUT_PULLUP;
80+
PIN_MAP[pin].pin_func = PF_DIO;
81+
break;
82+
83+
case INPUT_PULLDOWN:
84+
nrf_gpio_cfg_input(gpio_pin_map, NRF_GPIO_PIN_PULLDOWN);
85+
PIN_MAP[pin].pin_mode = INPUT_PULLDOWN;
86+
PIN_MAP[pin].pin_func = PF_DIO;
87+
break;
88+
89+
case PIN_MODE_NONE:
90+
nrf_gpio_cfg_default(gpio_pin_map);
91+
PIN_MAP[pin].pin_func = PF_NONE;
92+
default:
93+
break;
94+
}
95+
96+
5797
}
5898

5999
/*
60100
* @brief Saves a pin mode to be recalled later.
61101
*/
62-
void HAL_GPIO_Save_Pin_Mode(PinMode mode)
102+
void HAL_GPIO_Save_Pin_Mode(uint16_t pin)
63103
{
104+
// deprecated
64105
}
65106

66107
/*
67108
* @brief Recalls a saved pin mode.
68109
*/
69-
PinMode HAL_GPIO_Recall_Pin_Mode()
110+
PinMode HAL_GPIO_Recall_Pin_Mode(uint16_t pin)
70111
{
71-
return PIN_MODE_NONE;
112+
// deprecated
113+
return PIN_MODE_NONE;
72114
}
73115

74116
/*
75117
* @brief Sets a GPIO pin to HIGH or LOW.
76118
*/
77119
void HAL_GPIO_Write(uint16_t pin, uint8_t value)
78120
{
121+
if (!is_valid_pin(pin))
122+
{
123+
return;
124+
}
125+
126+
NRF5x_Pin_Info* PIN_MAP = HAL_Pin_Map();
127+
uint32_t gpio_pin_map = NRF_GPIO_PIN_MAP(PIN_MAP[pin].gpio_port, PIN_MAP[pin].gpio_pin);
128+
129+
if(value == 0)
130+
{
131+
nrf_gpio_pin_clear(gpio_pin_map);
132+
}
133+
else
134+
{
135+
nrf_gpio_pin_set(gpio_pin_map);
136+
}
79137
}
80138

81139
/*
82140
* @brief Reads the value of a GPIO pin. Should return either 1 (HIGH) or 0 (LOW).
83141
*/
84142
int32_t HAL_GPIO_Read(uint16_t pin)
85143
{
86-
return 0;
144+
if (!is_valid_pin(pin))
145+
{
146+
return 0;
147+
}
148+
149+
NRF5x_Pin_Info* PIN_MAP = HAL_Pin_Map();
150+
uint32_t gpio_pin_map = NRF_GPIO_PIN_MAP(PIN_MAP[pin].gpio_port, PIN_MAP[pin].gpio_pin);
151+
152+
if ((PIN_MAP[pin].pin_mode == INPUT) ||
153+
(PIN_MAP[pin].pin_mode == INPUT_PULLUP) ||
154+
(PIN_MAP[pin].pin_mode == INPUT_PULLDOWN))
155+
{
156+
return nrf_gpio_pin_read(gpio_pin_map);
157+
}
158+
else
159+
{
160+
return 0;
161+
}
162+
}
163+
164+
/*
165+
* @brief blocking call to measure a high or low pulse
166+
* @returns uint32_t pulse width in microseconds up to 3 seconds,
167+
* returns 0 on 3 second timeout error, or invalid pin.
168+
*/
169+
uint32_t HAL_Pulse_In(pin_t pin, uint16_t value)
170+
{
171+
if (!is_valid_pin(pin))
172+
{
173+
return 0;
174+
}
175+
176+
volatile uint32_t timeout_start = GetSystem1MsTick();
177+
178+
HAL_Pin_Mode(pin, INPUT);
179+
180+
/* If already on the value we want to measure, wait for the next one.
181+
* Time out after 3 seconds so we don't block the background tasks
182+
*/
183+
while (HAL_GPIO_Read(pin) == value)
184+
{
185+
if (GetSystem1MsTick() - timeout_start > 3000)
186+
{
187+
return 0;
188+
}
189+
}
190+
191+
/* Wait until the start of the pulse.
192+
* Time out after 3 seconds so we don't block the background tasks
193+
*/
194+
while (HAL_GPIO_Read(pin) != value)
195+
{
196+
if (GetSystem1MsTick() - timeout_start > 3000)
197+
{
198+
return 0;
199+
}
200+
}
201+
202+
/* Wait until this value changes, this will be our elapsed pulse width.
203+
* Time out after 3 seconds so we don't block the background tasks
204+
*/
205+
volatile uint32_t pulse_start = GetSystem1MsTick();
206+
while (HAL_GPIO_Read(pin) == value)
207+
{
208+
if (GetSystem1MsTick() - timeout_start > 3000)
209+
{
210+
return 0;
211+
}
212+
}
213+
214+
return GetSystem1MsTick() - pulse_start;
87215
}
216+
217+
218+
219+

user/tests/hal/gpio/test_gpio.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2018 Particle Industries, Inc. All rights reserved.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation, either
7+
* version 3 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
19+
#include "application.h"
20+
#include "gpio_hal.h"
21+
22+
SYSTEM_MODE(SEMI_AUTOMATIC);
23+
Serial1LogHandler logHandler(115200);
24+
25+
void test_gpio_blink(void)
26+
{
27+
HAL_Pin_Mode(D7, OUTPUT);
28+
delay(500);
29+
HAL_GPIO_Write(D7, 1);
30+
delay(500);
31+
HAL_GPIO_Write(D7, 0);
32+
}
33+
34+
void test_pulse_width(void)
35+
{
36+
uint32_t pulse_width = HAL_Pulse_In(D2, 0);
37+
if (pulse_width)
38+
{
39+
Log.info("Pulse Width: %dms", pulse_width);
40+
}
41+
}
42+
43+
void test_gpio_input(void)
44+
{
45+
HAL_Pin_Mode(D2, INPUT_PULLUP);
46+
HAL_Pin_Mode(D7, OUTPUT);
47+
48+
while (true)
49+
{
50+
if (HAL_GPIO_Read(D2))
51+
{
52+
HAL_GPIO_Write(D7, 1);
53+
}
54+
else
55+
{
56+
HAL_GPIO_Write(D7, 0);
57+
}
58+
}
59+
}
60+
/* executes once at startup */
61+
void setup() {
62+
Log.info("GPIO Test Start...");
63+
64+
}
65+
66+
/* executes continuously after setup() runs */
67+
void loop() {
68+
// test_gpio_blink();
69+
// test_pulse_width();
70+
test_gpio_input();
71+
}

0 commit comments

Comments
 (0)