Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In support of issue #98 (SoftwareSerial not working) #205

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions cores/nRF5/Arduino.h
Expand Up @@ -29,11 +29,11 @@ extern "C"{
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) ) #define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) )
#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) ) #define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) )


void yield( void ) ; void yield( void );


/* sketch */ /* sketch */
void setup( void ) ; void setup( void );
void loop( void ) ; void loop( void );


#include "WVariant.h" #include "WVariant.h"


Expand Down Expand Up @@ -92,12 +92,12 @@ void loop( void ) ;


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


#define digitalPinToPort(P) ( &(NRF_GPIO[P]) ) #define digitalPinToPort(P) ( NRF_GPIO ) // NRF_P0 = P0.00 - P0.31, NRF_P1 = P1.00 - P1.15 (e.g. nRF52840)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify this? Sounds like to support the nRF52840 we need to evaluate P to determine if this should be NRF_P0 or NRF_P1 (as the NRF_GPIO macro is likely to return NRF_P0).

Copy link
Contributor Author

@micooke micooke Dec 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlosperate - you are correct. For the NRF52840 this would need to be rewritten.
One issue is that the pins on port 0 are 0-31, but i didnt believe the pins on port 1 were consistently reprrsented as 32 onwards

#define digitalPinToBitMask(P) ( 1 << g_ADigitalPinMap[P] ) #define digitalPinToBitMask(P) ( 1 << g_ADigitalPinMap[P] )
//#define analogInPinToBit(P) ( ) //#define analogInPinToBit(P) ( )
#define portOutputRegister(port) ( &(port->OUTSET) ) #define portOutputRegister(port) ( &(port->OUT) )
#define portInputRegister(port) ( &(port->IN) ) #define portInputRegister(port) ( &(port->IN) )
#define portModeRegister(port) ( &(port->DIRSET) ) #define portModeRegister(port) ( &(port->DIR) )
#define digitalPinHasPWM(P) ( true ) #define digitalPinHasPWM(P) ( true )


/* /*
Expand Down
92 changes: 59 additions & 33 deletions cores/nRF5/WInterrupts.c
Expand Up @@ -30,42 +30,46 @@
#define NUMBER_OF_GPIO_TE 4 #define NUMBER_OF_GPIO_TE 4
#endif #endif


static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE]; static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE] = { NULL };
static int8_t channelMap[NUMBER_OF_GPIO_TE]; static int8_t channelMap[NUMBER_OF_GPIO_TE] = { -1 };
static int enabled = 0; static int enabled = 0;


/* Configure I/O interrupt sources */ /* Configure I/O interrupt sources */
static void __initialize() static void __initialize()
{ {
memset(callbacksInt, 0, sizeof(callbacksInt));
memset(channelMap, -1, sizeof(channelMap));

NVIC_DisableIRQ(GPIOTE_IRQn); NVIC_DisableIRQ(GPIOTE_IRQn);
NVIC_ClearPendingIRQ(GPIOTE_IRQn); NVIC_ClearPendingIRQ(GPIOTE_IRQn);
NVIC_SetPriority(GPIOTE_IRQn, 1); NVIC_SetPriority(GPIOTE_IRQn, 3); // Same priority as Uart
NVIC_EnableIRQ(GPIOTE_IRQn); NVIC_EnableIRQ(GPIOTE_IRQn);
} }


/* /*
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
* Replaces any previous function that was attached to the interrupt. * Replaces any previous function that was attached to the interrupt.
*/ */
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
{ {
if (!enabled) { uint32_t polarity;
__initialize(); uint8_t ch;
enabled = 1;
}


if (pin >= PINS_COUNT) { if (pin >= PINS_COUNT)
return; {
return -1;
} }


pin = g_ADigitalPinMap[pin]; pin = g_ADigitalPinMap[pin];


uint32_t polarity; switch (mode)
{
//gpiote channel does not support LOW and HIGH mode. These are mantained for compatibility
case LOW:
polarity = GPIOTE_CONFIG_POLARITY_HiToLo; //same as FALLING
break;

case HIGH:
polarity = GPIOTE_CONFIG_POLARITY_LoToHi; //same as RISING
break;


switch (mode) {
case CHANGE: case CHANGE:
polarity = GPIOTE_CONFIG_POLARITY_Toggle; polarity = GPIOTE_CONFIG_POLARITY_Toggle;
break; break;
Expand All @@ -79,11 +83,13 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
break; break;


default: default:
return; return -1;
} }


for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) { for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++)
if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin) { {
if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin)
{
channelMap[ch] = pin; channelMap[ch] = pin;
callbacksInt[ch] = callback; callbacksInt[ch] = callback;


Expand All @@ -98,6 +104,16 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
break; break;
} }
} }

// enable the interrupt after the first one is configured
if (!enabled)
{
__initialize();
enabled = 1;
}

// return the interrupt mask
return (1 << ch);
} }


/* /*
Expand Down Expand Up @@ -127,21 +143,31 @@ void detachInterrupt(uint32_t pin)


void GPIOTE_IRQHandler() void GPIOTE_IRQHandler()
{ {
uint32_t event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]); uint32_t event;

uint8_t ch;
for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) {
if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch))) { for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++)
if (channelMap[ch] != -1 && callbacksInt[ch]) { {
callbacksInt[ch](); event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[ch]);
} if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch)))

{
*(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0; break;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event));
(void)dummy;
#endif
} }

event = (uint32_t)((uint32_t)event + 4);
} }

// clear event
*(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event));
(void)dummy;
#endif

// disable the interrupt
NRF_GPIOTE->INTENCLR = (1 << ch);

// initiate the callback
callbacksInt[ch]();

// enable the interrupt
NRF_GPIOTE->INTENSET = (1 << ch);
} }
2 changes: 1 addition & 1 deletion cores/nRF5/WInterrupts.h
Expand Up @@ -40,7 +40,7 @@ typedef void (*voidFuncPtr)(void);
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
* Replaces any previous function that was attached to the interrupt. * Replaces any previous function that was attached to the interrupt.
*/ */
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);


/* /*
* \brief Turns off the given interrupt. * \brief Turns off the given interrupt.
Expand Down
16 changes: 16 additions & 0 deletions libraries/SoftwareSerial/LICENSE
@@ -0,0 +1,16 @@
Copyright (c) 2016 Arduino. All rights reserved.
Copyright (c) 2017 Mark Cooke All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 changes: 28 additions & 0 deletions libraries/SoftwareSerial/README.md
@@ -0,0 +1,28 @@
### SoftwareSerial

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)

#### Modifications
* merged SoftwareSerial.cpp into SoftwareSerial.h to allow ```_SS_MAX_RX_BUFF``` to be user-defined
* added ```_SS_TX_ONLY``` user define to allow this to be used as a transmit only library (no interrupts used)

### License

```
Copyright (c) 2016 Arduino. All rights reserved.
Copyright (c) 2017 Mark Cooke All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
```