Skip to content

[feature-nrf528xx] Extended PeripheralPins and pinmap for NRF52 series #6234

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

Merged
merged 2 commits into from
Mar 5, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 32 additions & 0 deletions targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPinsDefault.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "pinmap_ex.h"
#include "mbed_toolchain.h"

/* Default mapping between I2C pins and I2C instance.
* Can be overwritten by user.
*/
MBED_WEAK const PinMapI2C PinMap_I2C[1] = {
{NC, NC, NC}
};

/* Default mapping between SPI pins and SPI instance.
* Can be overwritten by user.
*/
MBED_WEAK const PinMapSPI PinMap_SPI[1] = {
{NC, NC, NC, NC}
};
57 changes: 57 additions & 0 deletions targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "object_owners.h"

#include "nrf.h"
#include "nrf_peripherals.h"

#include <stdio.h>

#define SPI2C_INSTANCES SPI_COUNT

static void * nordic_spi2c_owners[SPI2C_INSTANCES] = { NULL, NULL, NULL };

/**
* Brief Set instance owner for the SPI/I2C peripheral.
*
* Parameter instance The instance.
* Parameter object The object.
*/
void object_owner_spi2c_set(int instance, void *object)
{
if (instance < SPI2C_INSTANCES) {
nordic_spi2c_owners[instance] = object;
}
}

/**
* Brief Get instance owner for the SPI/I2C peripheral.
*
* Parameter instance The instance.
*
* Return Pointer to the object owning the instance.
*/
void * object_owner_spi2c_get(int instance)
{
void *object = (void *) 0xFFFFFFFF;

if (instance < SPI2C_INSTANCES) {
object = nordic_spi2c_owners[instance];
}

return object;
}
45 changes: 45 additions & 0 deletions targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef OBJECT_OWNERS_H
#define OBJECT_OWNERS_H

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Set instance owner for the SPI/I2C peripheral.
*
* @param[in] instance The instance.
* @param object The object.
*/
void object_owner_spi2c_set(int instance, void *object);

/**
* @brief Get instance owner for the SPI/I2C peripheral.
*
* @param[in] instance The instance.
*
* @return Pointer to the object owning the instance.
*/
void * object_owner_spi2c_get(int instance);

#ifdef __cplusplus
}
#endif

#endif
248 changes: 248 additions & 0 deletions targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "pinmap_ex.h"

#include "mbed_toolchain.h"
#include "nrf.h"
#include "nrf_peripherals.h"

#include <stdio.h>

#if 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be wrapped around a #define (MBED_DEBUG, or something similar), or is this just for debugging in the feature branch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its really only for debugging this specific file if someone has to go back to the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not certain about leaving it here, I would remove it .

Copy link
Contributor

Choose a reason for hiding this comment

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

@marcuschangarm Ok for now, but will definitely need to be changed before coming into master.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a requirement for this? I've noticed similar logging/debug code in partner's SDKs.

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like there should be, but I'm not certain there is.
@0xc0170 @adbridge ?

Copy link
Contributor

Choose a reason for hiding this comment

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

We have no control over what partners put in their SDKs, however that doesn't mean we should do such things ourselves...

#define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
#else
#define DEBUG_PRINTF(...) {}
#endif

/* Define number of instances */
#define NORDIC_TWI_COUNT TWI_COUNT
#define NORDIC_SPI_COUNT SPI_COUNT

/* Define which instance to return when there are no free instances left.
* The Mbed HAL API doesn't provide a way for signaling initialization errors
* so we return the default value. Any instance conflicts must be handled
* by the driver implementation.
*/
#define DEFAULT_I2C_INSTANCE 0 // SPI counts down, choose instance furthest away
#define DEFAULT_SPI_INSTANCE (SPI_COUNT - 1) // I2C counts up, choose instance furthers away

/* Internal data structure shared between SPI and I2C to keep track of allocated
* instances. The data structure is shared to reflect the hardware sharing.
*/
typedef struct {
PinName locaction0;
PinName locaction1;
PinName locaction2;
} spi2c_t;

static spi2c_t nordic_internal_spi2c[3] = {
{NC, NC, NC},
{NC, NC, NC},
{NC, NC, NC},
};

/**
* Brief Find hardware instance for the provided I2C pins.
*
* The function will search the PeripheralPin map for a pre-allocated
* assignment. If none is found the allocation map will be searched
* to see if the same pins have been assigned an instance before.
*
* If no assignement is found and there is an empty slot left in the
* map, the pins are stored in the map and the hardware instance is
* returned.
*
* If no free instances are available, the default instance is returned.
*
* Parameter sda sda pin.
* Parameter scl scl pin.
*
* Return Hardware instance associated with provided pins.
*/
int pin_instance_i2c(PinName sda, PinName scl)
{
int instance = NC;

/* Search pin map for pre-allocated instance */
for (size_t index = 0;
!((PinMap_I2C[index].sda == NC) &&
(PinMap_I2C[index].scl == NC));
index++) {

/* Compare pins to entry. */
if ((PinMap_I2C[index].sda == sda) &&
(PinMap_I2C[index].scl == scl)) {

DEBUG_PRINTF("found: %d %d %d\r\n", sda, scl, PinMap_I2C[index].instance);

/* Instance found, save result. */
instance = PinMap_I2C[index].instance;

/* Lock out entry in map to prevent SPI from grabbing it. */
nordic_internal_spi2c[instance].locaction0 = sda;
nordic_internal_spi2c[instance].locaction1 = scl;
nordic_internal_spi2c[instance].locaction2 = NC;
break;
}
}

/* No instance was found in static map. */
if (instance == NC) {

/* Search dynamic map for entry. */
for (size_t index = 0; index < NORDIC_TWI_COUNT; index++) {

/* Pins match previous dynamic allocation, return instance. */
if ((nordic_internal_spi2c[index].locaction0 == sda) &&
(nordic_internal_spi2c[index].locaction1 == scl) &&
(nordic_internal_spi2c[index].locaction2 == NC)) {

instance = index;
break;
}
}
}

/* No instance was found in dynamic map. */
if (instance == NC) {

/* Search dynamic map for empty slot. */
for (size_t index = 0; index < NORDIC_TWI_COUNT; index++) {

/* Empty slot found, reserve slot by storing pins. */
if ((nordic_internal_spi2c[index].locaction0 == NC) &&
(nordic_internal_spi2c[index].locaction1 == NC) &&
(nordic_internal_spi2c[index].locaction2 == NC)) {

nordic_internal_spi2c[index].locaction0 = sda;
nordic_internal_spi2c[index].locaction1 = scl;

instance = index;
break;
}
}
}

#if defined(DEFAULT_I2C_INSTANCE)
/* Exhausted all options. Return default value. */
if (instance == NC) {
instance = DEFAULT_I2C_INSTANCE;
}
#endif

DEBUG_PRINTF("I2C: %d %d %d\r\n", sda, scl, instance);

return instance;
}

/**
* Brief Find hardware instance for the provided SPI pins.
*
* The function will search the PeripheralPin map for a pre-allocated
* assignment. If none is found the allocation map will be searched
* to see if the same pins have been assigned an instance before.
*
* If no assignement is found and there is an empty slot left in the
* map, the pins are stored in the map and the hardware instance is
* returned.
*
* If no free instances are available, the default instance is returned.
*
* Parameter mosi mosi pin.
* Parameter miso miso pin.
* Parameter clk clk pin.
*
* Return Hardware instance associated with provided pins.
*/
int pin_instance_spi(PinName mosi, PinName miso, PinName clk)
{
int instance = NC;

/* Search pin map for pre-allocated instance */
for (size_t index = 0;
!((PinMap_SPI[index].mosi == NC) &&
(PinMap_SPI[index].miso == NC) &&
(PinMap_SPI[index].clk == NC));
index++) {

DEBUG_PRINTF("search: %d %d %d\r\n", PinMap_SPI[index].mosi, PinMap_SPI[index].miso, PinMap_SPI[index].clk);

/* Compare pins to entry. */
if ((PinMap_SPI[index].mosi == mosi) &&
(PinMap_SPI[index].miso == miso) &&
(PinMap_SPI[index].clk == clk)) {

DEBUG_PRINTF("found: %d %d %d %d\r\n", mosi, miso, clk, PinMap_SPI[index].instance);

/* Foung instance, save result. */
instance = PinMap_SPI[index].instance;

/* Lock out entry in map to prevent I2C from grabbing it. */
nordic_internal_spi2c[instance].locaction0 = mosi;
nordic_internal_spi2c[instance].locaction1 = miso;
nordic_internal_spi2c[instance].locaction2 = clk;
break;
}
}

/* No instance was found in static map. */
if (instance == NC) {

/* Search dynamic map for entry. */
for (int index = NORDIC_SPI_COUNT - 1; index > -1; index--) {
if ((nordic_internal_spi2c[index].locaction0 == mosi) &&
(nordic_internal_spi2c[index].locaction1 == miso) &&
(nordic_internal_spi2c[index].locaction2 == clk)) {

instance = index;
break;
}
}
}

/* No instance was found in dynamic map. */
if (instance == NC) {

/* Search dynamic map for empty slot. */
for (int index = NORDIC_SPI_COUNT - 1; index > -1; index--) {

/* Empty slot found, reserve slot by storing pins. */
if ((nordic_internal_spi2c[index].locaction0 == NC) &&
(nordic_internal_spi2c[index].locaction1 == NC) &&
(nordic_internal_spi2c[index].locaction2 == NC)) {

nordic_internal_spi2c[index].locaction0 = mosi;
nordic_internal_spi2c[index].locaction1 = miso;
nordic_internal_spi2c[index].locaction2 = clk;

instance = index;
break;
}
}
}

#if defined(DEFAULT_SPI_INSTANCE)
/* Exhausted all options. Return default value. */
if (instance == NC) {
instance = DEFAULT_SPI_INSTANCE;
}
#endif

DEBUG_PRINTF("SPI: %d %d %d %d\r\n", mosi, miso, clk, instance);

return instance;
}
Loading