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 2 commits
Commits
File filter

Filter by extension

Filter by extension

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

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

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

#include "WVariant.h"

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

#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 analogInPinToBit(P) ( )
#define portOutputRegister(port) ( &(port->OUTSET) )
#define portOutputRegister(port) ( &(port->OUT) )
#define portInputRegister(port) ( &(port->IN) )
#define portModeRegister(port) ( &(port->DIRSET) )
#define portModeRegister(port) ( &(port->DIR) )
#define digitalPinHasPWM(P) ( true )

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

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

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

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

/*
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
* 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) {
__initialize();
enabled = 1;
}
uint32_t polarity;
uint8_t ch;

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

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:
polarity = GPIOTE_CONFIG_POLARITY_Toggle;
break;
Expand All @@ -79,11 +83,13 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
break;

default:
return;
return -1;
}

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

Expand All @@ -98,6 +104,16 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
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()
{
uint32_t event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]);

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

*(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
uint32_t event;
uint8_t ch;

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

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
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ typedef void (*voidFuncPtr)(void);
* \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
* 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.
Expand Down
30 changes: 30 additions & 0 deletions libraries/SoftwareSerial/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
### 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

I do not claim copyright on the code, license taken from SoftwareSerial.h header.
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be a bit confusing to have "I do not claim copyright..." here, as the reader cannot get any context from the source code alone.
IANAL and I honestly don't know enough about this stuff, but from what (I think) I understand, renouncing copyright can end up being problematic, as its possible that the new code doesn't fall under any software license, and so it's unclear if it can be freely modified and redistributed.

Once again, IANAL, but it should be fine to declare the original copyright for the original library, as you have done, and then say that the modifications listed are under the same license. Copyright for the changes should automatically fall under your name, but you don't have to add it if you don't want to.


```
SoftwareSerial.h - library for Arduino Primo
Copyright (c) 2016 Arduino. All rights 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
```
Loading