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

LPC1768: Fix SPI 16-bit transfers #277

Merged
merged 7 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
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
3 changes: 3 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,9 @@ 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.
#define DEVICE_SPI_COUNT 2
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
Loading