Skip to content

Commit d29cea0

Browse files
committed
Add support for SoftwareSerial library
Add support for SoftwareSerial library, from sandeepmistry#205
1 parent 871447f commit d29cea0

File tree

10 files changed

+752
-40
lines changed

10 files changed

+752
-40
lines changed

cores/nRF5/Arduino.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ extern "C"{
2929
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) )
3030
#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) )
3131

32-
void yield( void ) ;
32+
void yield( void );
3333

3434
/* sketch */
35-
void setup( void ) ;
36-
void loop( void ) ;
35+
void setup( void );
36+
void loop( void );
3737

3838
#include "WVariant.h"
3939

@@ -92,12 +92,12 @@ void loop( void ) ;
9292

9393
#define bit(b) (1UL << (b))
9494

95-
#define digitalPinToPort(P) ( &(NRF_GPIO[P]) )
95+
#define digitalPinToPort(P) ( NRF_GPIO ) // NRF_P0 = P0.00 - P0.31, NRF_P1 = P1.00 - P1.15 (e.g. nRF52840)
9696
#define digitalPinToBitMask(P) ( 1 << g_ADigitalPinMap[P] )
9797
//#define analogInPinToBit(P) ( )
98-
#define portOutputRegister(port) ( &(port->OUTSET) )
98+
#define portOutputRegister(port) ( &(port->OUT) )
9999
#define portInputRegister(port) ( &(port->IN) )
100-
#define portModeRegister(port) ( &(port->DIRSET) )
100+
#define portModeRegister(port) ( &(port->DIR) )
101101
#define digitalPinHasPWM(P) ( true )
102102

103103
/*

cores/nRF5/WInterrupts.c

+59-33
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,46 @@
3030
#define NUMBER_OF_GPIO_TE 4
3131
#endif
3232

33-
static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE];
34-
static int8_t channelMap[NUMBER_OF_GPIO_TE];
33+
static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE] = { NULL };
34+
static int8_t channelMap[NUMBER_OF_GPIO_TE] = { -1 };
3535
static int enabled = 0;
3636

3737
/* Configure I/O interrupt sources */
3838
static void __initialize()
3939
{
40-
memset(callbacksInt, 0, sizeof(callbacksInt));
41-
memset(channelMap, -1, sizeof(channelMap));
42-
4340
NVIC_DisableIRQ(GPIOTE_IRQn);
4441
NVIC_ClearPendingIRQ(GPIOTE_IRQn);
45-
NVIC_SetPriority(GPIOTE_IRQn, 1);
42+
NVIC_SetPriority(GPIOTE_IRQn, 3); // Same priority as Uart
4643
NVIC_EnableIRQ(GPIOTE_IRQn);
4744
}
4845

4946
/*
5047
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
5148
* Replaces any previous function that was attached to the interrupt.
5249
*/
53-
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
50+
int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
5451
{
55-
if (!enabled) {
56-
__initialize();
57-
enabled = 1;
58-
}
52+
uint32_t polarity;
53+
uint8_t ch;
5954

60-
if (pin >= PINS_COUNT) {
61-
return;
55+
if (pin >= PINS_COUNT)
56+
{
57+
return -1;
6258
}
6359

6460
pin = g_ADigitalPinMap[pin];
6561

66-
uint32_t polarity;
62+
switch (mode)
63+
{
64+
//gpiote channel does not support LOW and HIGH mode. These are mantained for compatibility
65+
case LOW:
66+
polarity = GPIOTE_CONFIG_POLARITY_HiToLo; //same as FALLING
67+
break;
68+
69+
case HIGH:
70+
polarity = GPIOTE_CONFIG_POLARITY_LoToHi; //same as RISING
71+
break;
6772

68-
switch (mode) {
6973
case CHANGE:
7074
polarity = GPIOTE_CONFIG_POLARITY_Toggle;
7175
break;
@@ -79,11 +83,13 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
7983
break;
8084

8185
default:
82-
return;
86+
return -1;
8387
}
8488

85-
for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) {
86-
if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin) {
89+
for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++)
90+
{
91+
if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin)
92+
{
8793
channelMap[ch] = pin;
8894
callbacksInt[ch] = callback;
8995

@@ -98,6 +104,16 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
98104
break;
99105
}
100106
}
107+
108+
// enable the interrupt after the first one is configured
109+
if (!enabled)
110+
{
111+
__initialize();
112+
enabled = 1;
113+
}
114+
115+
// return the interrupt mask
116+
return (1 << ch);
101117
}
102118

103119
/*
@@ -127,21 +143,31 @@ void detachInterrupt(uint32_t pin)
127143

128144
void GPIOTE_IRQHandler()
129145
{
130-
uint32_t event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]);
131-
132-
for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) {
133-
if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch))) {
134-
if (channelMap[ch] != -1 && callbacksInt[ch]) {
135-
callbacksInt[ch]();
136-
}
137-
138-
*(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0;
139-
#if __CORTEX_M == 0x04
140-
volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event));
141-
(void)dummy;
142-
#endif
146+
uint32_t event;
147+
uint8_t ch;
148+
149+
for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++)
150+
{
151+
event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[ch]);
152+
if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch)))
153+
{
154+
break;
143155
}
144-
145-
event = (uint32_t)((uint32_t)event + 4);
146156
}
157+
158+
// clear event
159+
*(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0;
160+
#if __CORTEX_M == 0x04
161+
volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event));
162+
(void)dummy;
163+
#endif
164+
165+
// disable the interrupt
166+
NRF_GPIOTE->INTENCLR = (1 << ch);
167+
168+
// initiate the callback
169+
callbacksInt[ch]();
170+
171+
// enable the interrupt
172+
NRF_GPIOTE->INTENSET = (1 << ch);
147173
}

cores/nRF5/WInterrupts.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef void (*voidFuncPtr)(void);
4040
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
4141
* Replaces any previous function that was attached to the interrupt.
4242
*/
43-
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
43+
int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
4444

4545
/*
4646
* \brief Turns off the given interrupt.

libraries/SoftwareSerial/README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
### SoftwareSerial
2+
3+
This library is based off SoftwareSerial from @arduino-org's arduino-core-nrf52 release [1.0.1](https://github.com/arduino-org/arduino-core-nrf52/releases/tag/1.0.1)
4+
5+
#### Modifications
6+
* merged SoftwareSerial.cpp into SoftwareSerial.h to allow ```_SS_MAX_RX_BUFF``` to be user-defined
7+
* added ```_SS_TX_ONLY``` user define to allow this to be used as a transmit only library (no interrupts used)
8+
9+
### License
10+
11+
I do not claim copyright on the code, license taken from SoftwareSerial.h header.
12+
13+
```
14+
SoftwareSerial.h - library for Arduino Primo
15+
Copyright (c) 2016 Arduino. All rights reserved.
16+
17+
This library is free software; you can redistribute it and/or
18+
modify it under the terms of the GNU Lesser General Public
19+
License as published by the Free Software Foundation; either
20+
version 2.1 of the License, or (at your option) any later version.
21+
22+
This library is distributed in the hope that it will be useful,
23+
but WITHOUT ANY WARRANTY; without even the implied warranty of
24+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25+
Lesser General Public License for more details.
26+
27+
You should have received a copy of the GNU Lesser General Public
28+
License along with this library; if not, write to the Free Software
29+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30+
```

0 commit comments

Comments
 (0)