Skip to content

Commit

Permalink
LPC1768: Support static pinmaps (#276)
Browse files Browse the repository at this point in the history
* LPC1768: Fix I2C pins not being open drain, fix destroying and recreating I2C making transactions fail

* bus -> peripheral

* LPC1768: Support static pinmaps

* Update ARCH_PRO pin names header to pass muster
  • Loading branch information
multiplemonomials authored May 7, 2024
1 parent 6ae571d commit 94a7fbc
Show file tree
Hide file tree
Showing 14 changed files with 430 additions and 245 deletions.
6 changes: 3 additions & 3 deletions hal/include/hal/serial_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,12 +324,12 @@ void serial_pinout_tx(PinName tx);

#if DEVICE_SERIAL_FC
/** Configure the serial for the flow control. It sets flow control in the hardware
* if a serial peripheral supports it, otherwise software emulation is used.
* if a serial peripheral supports it, otherwise software emulation shall be used.
*
* @param obj The serial object
* @param type The type of the flow control. Look at the available FlowControl types.
* @param rxflow The TX pin name
* @param txflow The RX pin name
* @param rxflow The TX (RTS) pin name
* @param txflow The RX (CTS) pin name
*/
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow);

Expand Down
2 changes: 1 addition & 1 deletion hal/include/hal/static_pinmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ MSTD_CONSTEXPR_FN_14 serial_fc_pinmap_t get_uart_fc_pinmap(const PinName rxflow,
#endif // DEVICE_SERIAL

#if defined(DEVICE_SPI) && defined(PINMAP_SPI_MOSI) && defined(PINMAP_SPI_MISO) && defined(PINMAP_SPI_SCLK) && defined(PINMAP_SPI_SSEL)
MSTD_CONSTEXPR_FN_14 spi_pinmap_t get_spi_pinmap(const PinName mosi, const PinName miso, const PinName sclk, const PinName ssel)
MSTD_CONSTEXPR_FN_14 spi_pinmap_t get_spi_pinmap(const PinName mosi, const PinName miso, const PinName sclk, const PinName ssel = NC)
{
const PinMap *mosi_map = nullptr;
for (const PinMap &pinmap : PINMAP_SPI_MOSI) {
Expand Down
2 changes: 2 additions & 0 deletions targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef enum {
DAC_0 = 0
} DACName;

// Note: We only use the two SSP peripherals in Mbed, not SPI0. This is because
// SPI0 is a legacy version of the SSP peripheral and cannot be used at the same time as SSP0.
typedef enum {
SPI_0 = (int)LPC_SSP0_BASE,
SPI_1 = (int)LPC_SSP1_BASE
Expand Down
186 changes: 186 additions & 0 deletions targets/TARGET_NXP/TARGET_LPC176X/PeripheralPinMaps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/* mbed Microcontroller Library
* Copyright (c) 2024 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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 PERIPHERAL_PINMAPS_H
#define PERIPHERAL_PINMAPS_H

#include <mstd_cstddef>

#include "pinmap.h"

#include "PeripheralNames.h"

// For LPC1768, PinMap entries are in the form
// (pin name, peripheral name, function number)
// where the function number is the 2-bit value that will be written into the PINSELn
// bitfield for this pin.
// See section 8.5 in the LPC1768 user manual for the source of these pinmappings.

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_UART_TX[] = {
{P0_0, UART_3, 2},
{P0_2, UART_0, 1},
{P0_10, UART_2, 1},
{P0_15, UART_1, 1},
{P0_25, UART_3, 3},
{P2_0 , UART_1, 2},
{P2_8 , UART_2, 2},
{P4_28, UART_3, 3},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_UART_RX[] = {
{P0_1 , UART_3, 2},
{P0_3 , UART_0, 1},
{P0_11, UART_2, 1},
{P0_16, UART_1, 1},
{P0_26, UART_3, 3},
{P2_1 , UART_1, 2},
{P2_9 , UART_2, 2},
{P4_29, UART_3, 3},
{NC , NC , 0}
};

// Only UART1 has hardware flow control on LPC176x
static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_UART_RTS[] = {
{P0_22, UART_1, 1},
{P2_7, UART_1, 2},
{NC, NC, 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_UART_CTS[] = {
{P0_17, UART_1, 1},
{P2_2, UART_1, 2},
{NC, NC, 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_SPI_SCLK[] = {
{P0_7 , SPI_1, 2},
{P0_15, SPI_0, 2},
{P1_20, SPI_0, 3},
{P1_31, SPI_1, 2},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_SPI_MOSI[] = {
{P0_9 , SPI_1, 2},
{P0_13, SPI_1, 2},
{P0_18, SPI_0, 2},
{P1_24, SPI_0, 3},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_SPI_MISO[] = {
{P0_8 , SPI_1, 2},
{P0_12, SPI_1, 2},
{P0_17, SPI_0, 2},
{P1_23, SPI_0, 3},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_SPI_SSEL[] = {
{P0_6 , SPI_1, 2},
{P0_11, SPI_1, 2},
{P0_16, SPI_0, 2},
{P1_21, SPI_0, 3},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_ADC[] = {
{P0_23, ADC0_0, 1},
{P0_24, ADC0_1, 1},
{P0_25, ADC0_2, 1},
{P0_26, ADC0_3, 1},
{P1_30, ADC0_4, 3},
{P1_31, ADC0_5, 3},
{P0_2, ADC0_7, 2},
{P0_3, ADC0_6, 2},
{NC, NC, 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_DAC[] = {
{P0_26, DAC_0, 2},
{NC , NC , 0}
};

// NOTE: For I2C, only the P0_27/P0_28 pinmapping is fully electrically compliant to the I2C standard.
static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_I2C_SDA[] = {
{P0_27, I2C_0, 1},
{P0_0 , I2C_1, 3},
{P0_19, I2C_1, 3},
{P0_10, I2C_2, 2},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_I2C_SCL[] = {
{P0_28, I2C_0, 1},
{P0_1 , I2C_1, 3},
{P0_20, I2C_1, 3},
{P0_11, I2C_2, 2},
{NC , NC, 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_PWM[] = {
{P1_18, PWM_1, 2},
{P1_20, PWM_2, 2},
{P1_21, PWM_3, 2},
{P1_23, PWM_4, 2},
{P1_24, PWM_5, 2},
{P1_26, PWM_6, 2},
{P2_0, PWM_1, 1},
{P2_1, PWM_2, 1},
{P2_2, PWM_3, 1},
{P2_3, PWM_4, 1},
{P2_4, PWM_5, 1},
{P2_5, PWM_6, 1},
{P3_25, PWM_2, 3},
{P3_26, PWM_3, 3},
{NC, NC, 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_CAN_RD[] = {
{P0_0 , CAN_1, 1},
{P0_4 , CAN_2, 2},
{P0_21, CAN_1, 3},
{P2_7 , CAN_2, 1},
{NC , NC , 0}
};

static MSTD_CONSTEXPR_OBJ_11 PinMap PinMap_CAN_TD[] = {
{P0_1 , CAN_1, 1},
{P0_5 , CAN_2, 2},
{P0_22, CAN_1, 3},
{P2_8 , CAN_2, 1},
{NC , NC , 0}
};

// Pinmap name macros
#define PINMAP_UART_TX PinMap_UART_TX
#define PINMAP_UART_RX PinMap_UART_RX
#define PINMAP_UART_RTS PinMap_UART_RTS
#define PINMAP_UART_CTS PinMap_UART_CTS
#define PINMAP_SPI_SCLK PinMap_SPI_SCLK
#define PINMAP_SPI_MOSI PinMap_SPI_MOSI
#define PINMAP_SPI_MISO PinMap_SPI_MISO
#define PINMAP_SPI_SSEL PinMap_SPI_SSEL
#define PINMAP_ANALOGIN PinMap_ADC
#define PINMAP_ANALOGOUT PinMap_DAC
#define PINMAP_I2C_SDA PinMap_I2C_SDA
#define PINMAP_I2C_SCL PinMap_I2C_SCL
#define PINMAP_PWM PinMap_PWM
#define PINMAP_CAN_RD PinMap_CAN_RD
#define PINMAP_CAN_TD PinMap_CAN_TD
#endif
39 changes: 18 additions & 21 deletions targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ typedef enum {
PIN_OUTPUT
} PinDirection;

/* If this macro is defined, you can use constexpr utility functions for pin map search. */
#define STATIC_PINMAP_READY 1

#define PORT_SHIFT 5

typedef enum {
Expand Down Expand Up @@ -70,18 +73,6 @@ typedef enum {
p29 = P0_5,
p30 = P0_4,

// Other mbed Pin Names
#ifdef MCB1700
LED1 = P1_28,
LED2 = P1_29,
LED3 = P1_31,
LED4 = P2_2,
#else
LED1 = P1_18,
LED2 = P1_20,
LED3 = P1_21,
LED4 = P1_23,
#endif
CONSOLE_TX = P0_2,
CONSOLE_RX = P0_3,

Expand Down Expand Up @@ -110,19 +101,25 @@ typedef enum {
A4 = P1_30,
A5 = P1_31,

I2C_SCL = D15,
I2C_SDA = D14,

//SPI Pins configuration
SPI_MOSI = P0_9,
SPI_MISO = P0_8,
SPI_SCK = P0_7,
SPI_CS = P0_6,

// Not connected
NC = (int)0xFFFFFFFF
} PinName;

// Standard buttons and LEDs
#define LED1 P1_18
#define LED2 P1_20
#define LED3 P1_21
#define LED4 P1_23

// I2C and SPI pin names
#define I2C_SCL D15
#define I2C_SDA D14

#define SPI_MOSI P0_9
#define SPI_MISO P0_8
#define SPI_SCK P0_7
#define SPI_CS P0_6

typedef enum {
PullUp = 0,
PullDown = 3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ typedef enum {
PIN_OUTPUT
} PinDirection;

/* If this macro is defined, you can use constexpr utility functions for pin map search. */
#define STATIC_PINMAP_READY 1

#define PORT_SHIFT 5

typedef enum {
Expand Down
33 changes: 16 additions & 17 deletions targets/TARGET_NXP/TARGET_LPC176X/analogin_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "analogin_api.h"

#include "cmsis.h"
#include "pinmap.h"
#include "PeripheralPinMaps.h"

#define ANALOGIN_MEDIAN_FILTER 1

Expand All @@ -29,23 +29,10 @@ static inline int div_round_up(int x, int y) {
return (x + (y - 1)) / y;
}

static const PinMap PinMap_ADC[] = {
{P0_23, ADC0_0, 1},
{P0_24, ADC0_1, 1},
{P0_25, ADC0_2, 1},
{P0_26, ADC0_3, 1},
{P1_30, ADC0_4, 3},
{P1_31, ADC0_5, 3},
{P0_2, ADC0_7, 2},
{P0_3, ADC0_6, 2},
{NC, NC, 0}
};

#define ADC_RANGE ADC_12BIT_RANGE

void analogin_init(analogin_t *obj, PinName pin) {
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
MBED_ASSERT(obj->adc != (ADCName)NC);
void analogin_init_direct(analogin_t *obj, const PinMap *pinmap) {
obj->adc = pinmap->peripheral;

// ensure power is turned on
LPC_SC->PCONP |= (1 << 12);
Expand All @@ -69,7 +56,19 @@ void analogin_init(analogin_t *obj, PinName pin) {
| (0 << 24) // START: 0 = no start
| (0 << 27); // EDGE: not applicable

pinmap_pinout(pin, PinMap_ADC);
// Map pin
pin_function(pinmap->pin, pinmap->function);
pin_mode(pinmap->pin, PullNone);
}

void analogin_init(analogin_t *obj, PinName pin) {
PinMap pinmap;
pinmap.pin = pin;
pinmap.function = pinmap_find_function(pin, PinMap_ADC);
pinmap.peripheral = pinmap_peripheral(pin, PinMap_ADC);
MBED_ASSERT(pinmap.peripheral != NC);

analogin_init_direct(obj, &pinmap);
}

static inline uint32_t adc_read(analogin_t *obj) {
Expand Down
25 changes: 15 additions & 10 deletions targets/TARGET_NXP/TARGET_LPC176X/analogout_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,31 @@
#include "analogout_api.h"

#include "cmsis.h"
#include "pinmap.h"
#include "PeripheralPinMaps.h"

static const PinMap PinMap_DAC[] = {
{P0_26, DAC_0, 2},
{NC , NC , 0}
};

void analogout_init(dac_t *obj, PinName pin) {
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
MBED_ASSERT(obj->dac != (DACName)NC);
void analogout_init_direct(dac_t *obj, const PinMap *pinmap) {
obj->dac = (DACName)pinmap->peripheral;

// power is on by default, set DAC clk divider is /4
LPC_SC->PCLKSEL0 &= ~(0x3 << 22);

// map out (must be done before accessing registers)
pinmap_pinout(pin, PinMap_DAC);
pin_function(pinmap->pin, pinmap->function);
pin_mode(pinmap->pin, PullNone);

analogout_write_u16(obj, 0);
}

void analogout_init(dac_t *obj, PinName pin) {
PinMap pinmap;
pinmap.pin = pin;
pinmap.function = pinmap_find_function(pin, PinMap_DAC);
pinmap.peripheral = pinmap_peripheral(pin, PinMap_DAC);
MBED_ASSERT(pinmap.peripheral != NC);

analogout_init_direct(obj, &pinmap);
}

void analogout_free(dac_t *obj) {}

static inline void dac_write(int value) {
Expand Down
Loading

0 comments on commit 94a7fbc

Please sign in to comment.