From b164ddc8fad786630f727d1e02cd08de4012d50d Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Sat, 4 May 2024 16:51:51 -0700 Subject: [PATCH 1/6] LPC1768: Fix I2C pins not being open drain, fix destroying and recreating I2C making transactions fail --- targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c b/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c index b7f632aeeec..51b8e833781 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c @@ -22,6 +22,14 @@ #include "cmsis.h" #include "pinmap.h" +// Change to 1 to enable debug prints. +#define LPC1768_I2C_DEBUG 0 + +#if LPC1768_I2C_DEBUG +#include +#include +#endif + static const PinMap PinMap_I2C_SDA[] = { {P0_0 , I2C_1, 3}, {P0_10, I2C_2, 2}, @@ -83,6 +91,10 @@ static int i2c_wait_SI(i2c_t *obj) { return 0; } +static inline void i2c_interface_disable(i2c_t *obj) { + I2C_CONCLR(obj) = 0x40; +} + static inline void i2c_interface_enable(i2c_t *obj) { I2C_CONSET(obj) = 0x40; } @@ -107,17 +119,30 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { // set default frequency at 100k i2c_frequency(obj, 100000); + + // Reset the I2C bus by clearing all flags, including I2EN. + // This does a software reset of sorts, which is important because the I2C::recover() + // function, which is called before initializing the bus, seems to put the I2C + // peripheral in a weird state where the next transaction will fail. + i2c_interface_disable(obj); i2c_conclr(obj, 1, 1, 1, 1); + i2c_interface_enable(obj); pinmap_pinout(sda, PinMap_I2C_SDA); + pin_mode(sda, OpenDrain); pinmap_pinout(scl, PinMap_I2C_SCL); + pin_mode(scl, OpenDrain); } inline int i2c_start(i2c_t *obj) { int status = 0; int isInterrupted = I2C_CONSET(obj) & (1 << 3); +#if LPC1768_I2C_DEBUG + printf("i2c_start(): status was originally 0x%x\n", i2c_status(obj)); +#endif + // 8.1 Before master mode can be entered, I2CON must be initialised to: // - I2EN STA STO SI AA - - // - 1 0 0 x x - - @@ -135,6 +160,10 @@ inline int i2c_start(i2c_t *obj) { i2c_wait_SI(obj); status = i2c_status(obj); +#if LPC1768_I2C_DEBUG + printf("i2c_start(): status is now 0x%x\n", status); +#endif + // Clear start bit now that it's transmitted i2c_conclr(obj, 1, 0, 0, 0); return status; @@ -303,6 +332,10 @@ int i2c_byte_read(i2c_t *obj, int last) { int i2c_byte_write(i2c_t *obj, int data) { int ack; int status = i2c_do_write(obj, (data & 0xFF), 0); + +#if LPC1768_I2C_DEBUG + printf("i2c_do_write(0x%hhx) returned 0x%x\n", data & 0xFF, status); +#endif switch(status) { case 0x18: case 0x28: // Master transmit ACKs From 034c8f68359c9c1a48ca375eaaa5da9b4e3b84b4 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Sat, 4 May 2024 17:18:38 -0700 Subject: [PATCH 2/6] bus -> peripheral --- targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c b/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c index 51b8e833781..aa3112c888d 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c @@ -120,7 +120,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { // set default frequency at 100k i2c_frequency(obj, 100000); - // Reset the I2C bus by clearing all flags, including I2EN. + // Reset the I2C peripheral by clearing all flags, including I2EN. // This does a software reset of sorts, which is important because the I2C::recover() // function, which is called before initializing the bus, seems to put the I2C // peripheral in a weird state where the next transaction will fail. From d85a56ecf230fc35d406a2f1088fd1f57732990d Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Sat, 4 May 2024 23:36:00 -0700 Subject: [PATCH 3/6] LPC1768: Support static pinmaps --- hal/include/hal/serial_api.h | 6 +- hal/include/hal/static_pinmap.h | 2 +- .../TARGET_LPC176X/PeripheralNames.h | 2 + .../TARGET_LPC176X/PeripheralPinMaps.h | 186 ++++++++++++++++++ .../TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h | 3 + .../TARGET_MBED_LPC1768/PinNames.h | 3 + .../TARGET_NXP/TARGET_LPC176X/analogin_api.c | 33 ++-- .../TARGET_NXP/TARGET_LPC176X/analogout_api.c | 25 ++- targets/TARGET_NXP/TARGET_LPC176X/can_api.c | 53 ++--- targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c | 58 +++--- .../TARGET_NXP/TARGET_LPC176X/pwmout_api.c | 40 ++-- .../TARGET_NXP/TARGET_LPC176X/serial_api.c | 141 ++++++------- targets/TARGET_NXP/TARGET_LPC176X/spi_api.c | 85 ++++---- targets/targets.json5 | 2 +- 14 files changed, 416 insertions(+), 223 deletions(-) create mode 100644 targets/TARGET_NXP/TARGET_LPC176X/PeripheralPinMaps.h diff --git a/hal/include/hal/serial_api.h b/hal/include/hal/serial_api.h index c3b16ddc4a2..cad346a995d 100644 --- a/hal/include/hal/serial_api.h +++ b/hal/include/hal/serial_api.h @@ -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); diff --git a/hal/include/hal/static_pinmap.h b/hal/include/hal/static_pinmap.h index cfa5458e318..ab53d07f3a7 100644 --- a/hal/include/hal/static_pinmap.h +++ b/hal/include/hal/static_pinmap.h @@ -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) { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h b/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h index 1eb4c625f7d..e0475301df5 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h @@ -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 diff --git a/targets/TARGET_NXP/TARGET_LPC176X/PeripheralPinMaps.h b/targets/TARGET_NXP/TARGET_LPC176X/PeripheralPinMaps.h new file mode 100644 index 00000000000..1906d31ff84 --- /dev/null +++ b/targets/TARGET_NXP/TARGET_LPC176X/PeripheralPinMaps.h @@ -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 + +#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 \ No newline at end of file diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h index 33b37d5de1a..565e14d666a 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h @@ -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 { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h index 69ce7cd7436..99ddce06fdf 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h @@ -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 { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/analogin_api.c b/targets/TARGET_NXP/TARGET_LPC176X/analogin_api.c index f3a455d1779..a9866a2d314 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/analogin_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/analogin_api.c @@ -18,7 +18,7 @@ #include "analogin_api.h" #include "cmsis.h" -#include "pinmap.h" +#include "PeripheralPinMaps.h" #define ANALOGIN_MEDIAN_FILTER 1 @@ -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); @@ -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) { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/analogout_api.c b/targets/TARGET_NXP/TARGET_LPC176X/analogout_api.c index 8bc7ab13dc0..a042574f7a1 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/analogout_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/analogout_api.c @@ -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) { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/can_api.c b/targets/TARGET_NXP/TARGET_LPC176X/can_api.c index dde466a794a..689eb574218 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/can_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/can_api.c @@ -18,7 +18,7 @@ #include "can_api.h" #include "cmsis.h" -#include "pinmap.h" +#include "PeripheralPinMaps.h" #include #include @@ -36,22 +36,6 @@ http://www.kvaser.com/can/index.htm */ -static const 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 const 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} -}; - // Type definition to hold a CAN message struct CANMsg { unsigned int reserved1 : 16; @@ -293,10 +277,8 @@ static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int } -void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) { - CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); - CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); - obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td); +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) { + obj->dev = (LPC_CAN_TypeDef *)pinmap->peripheral; MBED_ASSERT((int)obj->dev != NC); switch ((int)obj->dev) { @@ -304,8 +286,11 @@ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) { case CAN_2: LPC_SC->PCONP |= 1 << 14; break; } - pinmap_pinout(rd, PinMap_CAN_RD); - pinmap_pinout(td, PinMap_CAN_TD); + // Map pins + pin_function(pinmap->rd_pin, pinmap->rd_function); + pin_mode(pinmap->rd_pin, PullNone); + pin_function(pinmap->td_pin, pinmap->td_function); + pin_mode(pinmap->td_pin, PullNone); switch ((int)obj->dev) { case CAN_1: obj->index = 0; break; @@ -319,6 +304,28 @@ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) { LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter } +void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) { + can_pinmap_t pinmap; + pinmap.rd_pin = rd; + pinmap.td_pin = td; + + // Determine peripheral associated with these pins + CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); + CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); + pinmap.peripheral = pinmap_merge(can_rd, can_td); + MBED_ASSERT((int)pinmap.peripheral != NC); + + // Get pin functions + pinmap.rd_function = pinmap_find_function(rd, PinMap_CAN_RD); + pinmap.td_function = pinmap_find_function(td, PinMap_CAN_TD); + + can_init_freq_direct(obj, &pinmap, hz); +} + +void can_init_direct(can_t *obj, const can_pinmap_t *pinmap) { + can_init_freq_direct(obj, pinmap, 100000); +} + void can_init(can_t *obj, PinName rd, PinName td) { can_init_freq(obj, rd, td, 100000); } diff --git a/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c b/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c index aa3112c888d..f6b23369229 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c @@ -22,6 +22,8 @@ #include "cmsis.h" #include "pinmap.h" +#include "PeripheralPinMaps.h" + // Change to 1 to enable debug prints. #define LPC1768_I2C_DEBUG 0 @@ -30,22 +32,6 @@ #include #endif -static const PinMap PinMap_I2C_SDA[] = { - {P0_0 , I2C_1, 3}, - {P0_10, I2C_2, 2}, - {P0_19, I2C_1, 3}, - {P0_27, I2C_0, 1}, - {NC , NC , 0} -}; - -static const PinMap PinMap_I2C_SCL[] = { - {P0_1 , I2C_1, 3}, - {P0_11, I2C_2, 2}, - {P0_20, I2C_1, 3}, - {P0_28, I2C_0, 1}, - {NC , NC, 0} -}; - #define I2C_CONSET(x) (x->i2c->I2CONSET) #define I2C_CONCLR(x) (x->i2c->I2CONCLR) #define I2C_STAT(x) (x->i2c->I2STAT) @@ -107,13 +93,10 @@ static inline void i2c_power_enable(i2c_t *obj) { } } -void i2c_init(i2c_t *obj, PinName sda, PinName scl) { - // determine the SPI to use - I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); - I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); - obj->i2c = (LPC_I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl); - MBED_ASSERT((int)obj->i2c != NC); - +void i2c_init_direct(i2c_t *obj, const i2c_pinmap_t *pinmap) +{ + obj->i2c = (LPC_I2C_TypeDef *)pinmap->peripheral; + // enable power i2c_power_enable(obj); @@ -129,12 +112,33 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { i2c_interface_enable(obj); - pinmap_pinout(sda, PinMap_I2C_SDA); - pin_mode(sda, OpenDrain); - pinmap_pinout(scl, PinMap_I2C_SCL); - pin_mode(scl, OpenDrain); + // Map pins + pin_function(pinmap->sda_pin, pinmap->sda_function); + pin_mode(pinmap->sda_pin, OpenDrain); + pin_function(pinmap->scl_pin, pinmap->scl_function); + pin_mode(pinmap->scl_pin, OpenDrain); } +void i2c_init(i2c_t *obj, PinName sda, PinName scl) { + + i2c_pinmap_t pinmap; + pinmap.sda_pin = sda; + pinmap.scl_pin = scl; + + // Determine peripheral associated with these pins + I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); + I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); + pinmap.peripheral = pinmap_merge(i2c_sda, i2c_scl); + MBED_ASSERT((int)pinmap.peripheral != NC); + + // Get pin functions + pinmap.sda_function = pinmap_find_function(sda, PinMap_I2C_SDA); + pinmap.scl_function = pinmap_find_function(scl, PinMap_I2C_SCL); + + i2c_init_direct(obj, &pinmap); +} + + inline int i2c_start(i2c_t *obj) { int status = 0; int isInterrupted = I2C_CONSET(obj) & (1 << 3); diff --git a/targets/TARGET_NXP/TARGET_LPC176X/pwmout_api.c b/targets/TARGET_NXP/TARGET_LPC176X/pwmout_api.c index d92be8aabcf..27a679461c6 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/pwmout_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/pwmout_api.c @@ -17,7 +17,7 @@ #include "mbed_assert.h" #include "pwmout_api.h" #include "cmsis.h" -#include "pinmap.h" +#include "PeripheralPinMaps.h" #include #include @@ -34,25 +34,6 @@ #define TCR_CNT_EN 0x00000001 #define TCR_RESET 0x00000002 -// PORT ID, PWM ID, Pin function -static const 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} -}; - __IO uint32_t *PWM_MATCH[] = { &(LPC_PWM1->MR0), &(LPC_PWM1->MR1), @@ -67,11 +48,10 @@ __IO uint32_t *PWM_MATCH[] = { static unsigned int pwm_clocks_per_us; -void pwmout_init(pwmout_t *obj, PinName pin) +void pwmout_init_direct(pwmout_t *obj, const PinMap *pinmap) { // determine the channel - PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); - MBED_ASSERT(pwm != (PWMName)NC); + PWMName pwm = (PWMName)pinmap->peripheral; obj->pwm = pwm; obj->MR = PWM_MATCH[pwm]; @@ -98,7 +78,19 @@ void pwmout_init(pwmout_t *obj, PinName pin) pwmout_write(obj, 0); // Wire pinout - pinmap_pinout(pin, PinMap_PWM); + pin_function(pinmap->pin, pinmap->function); + pin_mode(pinmap->pin, PullNone); +} + +void pwmout_init(pwmout_t *obj, PinName pin) +{ + PinMap pinmap; + pinmap.pin = pin; + pinmap.function = pinmap_find_function(pin, PinMap_PWM); + pinmap.peripheral = pinmap_peripheral(pin, PinMap_PWM); + MBED_ASSERT(pinmap.peripheral != NC); + + pwmout_init_direct(obj, &pinmap); } void pwmout_free(pwmout_t *obj) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/serial_api.c b/targets/TARGET_NXP/TARGET_LPC176X/serial_api.c index 15358039f6c..45e37be415d 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/serial_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/serial_api.c @@ -24,48 +24,13 @@ #include "cmsis.h" #include "pinmap.h" #include "gpio_api.h" +#include "PeripheralPinMaps.h" /****************************************************************************** * INITIALIZATION ******************************************************************************/ #define UART_NUM 4 -static const 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 const 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} -}; - -static const PinMap PinMap_UART_RTS[] = { - {P0_22, UART_1, 1}, - {P2_7, UART_1, 2}, - {NC, NC, 0} -}; - -static const PinMap PinMap_UART_CTS[] = { - {P0_17, UART_1, 1}, - {P2_2, UART_1, 2}, - {NC, NC, 0} -}; - #define UART_MCR_RTSEN_MASK (1 << 6) #define UART_MCR_CTSEN_MASK (1 << 7) #define UART_MCR_FLOWCTRL_MASK (UART_MCR_RTSEN_MASK | UART_MCR_CTSEN_MASK) @@ -83,18 +48,12 @@ struct serial_global_data_s { static struct serial_global_data_s uart_data[UART_NUM]; -void serial_init(serial_t *obj, PinName tx, PinName rx) { - int is_stdio_uart = 0; - - // determine the UART to use - UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); - UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); - UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); - MBED_ASSERT((int)uart != NC); +void serial_init_direct(serial_t *obj, const serial_pinmap_t *pinmap) +{ + obj->uart = (LPC_UART_TypeDef *)pinmap->peripheral; - obj->uart = (LPC_UART_TypeDef *)uart; // enable power - switch (uart) { + switch ((int)obj->uart) { case UART_0: LPC_SC->PCONP |= 1 << 3; break; case UART_1: LPC_SC->PCONP |= 1 << 4; break; case UART_2: LPC_SC->PCONP |= 1 << 24; break; @@ -116,19 +75,17 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { serial_baud (obj, 9600); serial_format(obj, 8, ParityNone, 1); - // pinout the chosen uart - pinmap_pinout(tx, PinMap_UART_TX); - pinmap_pinout(rx, PinMap_UART_RX); - - // set rx/tx pins in PullUp mode - if (tx != NC) { - pin_mode(tx, PullUp); + // Map pins + if (pinmap->tx_pin != NC) { + pin_function(pinmap->tx_pin, pinmap->tx_function); + pin_mode(pinmap->tx_pin, PullUp); } - if (rx != NC) { - pin_mode(rx, PullUp); + if (pinmap->rx_pin != NC) { + pin_function(pinmap->rx_pin, pinmap->rx_function); + pin_mode(pinmap->rx_pin, PullUp); } - switch (uart) { + switch ((int)obj->uart) { case UART_0: obj->index = 0; break; case UART_1: obj->index = 1; break; case UART_2: obj->index = 2; break; @@ -138,14 +95,30 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { uart_data[obj->index].sw_cts.pin = NC; serial_set_flow_control(obj, FlowControlNone, NC, NC); - is_stdio_uart = (uart == STDIO_UART) ? (1) : (0); - - if (is_stdio_uart) { + if ((int)obj->uart == STDIO_UART) { stdio_uart_inited = 1; memcpy(&stdio_uart, obj, sizeof(serial_t)); } } +void serial_init(serial_t *obj, PinName tx, PinName rx) { + serial_pinmap_t pinmap; + pinmap.tx_pin = tx; + pinmap.rx_pin = rx; + + // determine the UART to use + UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); + UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); + pinmap.peripheral = pinmap_merge(uart_tx, uart_rx); + MBED_ASSERT(pinmap.peripheral != NC); + + // Get pin functions + pinmap.tx_function = pinmap_find_function(tx, PinMap_UART_TX); + pinmap.rx_function = pinmap_find_function(rx, PinMap_UART_RX); + + serial_init_direct(obj, &pinmap); +} + void serial_free(serial_t *obj) { uart_data[obj->index].serial_irq_id = 0; } @@ -396,7 +369,8 @@ void serial_break_clear(serial_t *obj) { obj->uart->LCR &= ~(1 << 6); } -void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { +void serial_set_flow_control_direct(serial_t *obj, FlowControl type, const serial_fc_pinmap_t *pinmap) +{ // Only UART1 has hardware flow control on LPC176x LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL; int index = obj->index; @@ -408,39 +382,66 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi serial_flow_irq_set(obj, 0); if (FlowControlNone == type) return; + // Check type(s) of flow control to use - UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS); - UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS); - if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) { + if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != pinmap->tx_flow_pin)) { // Can this be enabled in hardware? - if ((UART_1 == uart_cts) && (NULL != uart1)) { + if (pinmap->tx_flow_function) { // Enable auto-CTS mode uart1->MCR |= UART_MCR_CTSEN_MASK; - pinmap_pinout(txflow, PinMap_UART_CTS); + pin_function(pinmap->tx_flow_pin, pinmap->tx_flow_function); + pin_mode(pinmap->tx_flow_pin, PullNone); } else { // Can't enable in hardware, use software emulation - gpio_init_in(&uart_data[index].sw_cts, txflow); + gpio_init_in(&uart_data[index].sw_cts, pinmap->tx_flow_pin); } } - if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) { + if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != pinmap->rx_flow_pin)) { // Enable FIFOs, trigger level of 1 char on RX FIFO obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled | 1 << 1 // Rx Fifo Reset | 1 << 2 // Tx Fifo Reset | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars // Can this be enabled in hardware? - if ((UART_1 == uart_rts) && (NULL != uart1)) { + if (pinmap->rx_flow_function) { // Enable auto-RTS mode uart1->MCR |= UART_MCR_RTSEN_MASK; - pinmap_pinout(rxflow, PinMap_UART_RTS); + pin_function(pinmap->rx_flow_pin, pinmap->rx_flow_function); + pin_mode(pinmap->rx_flow_pin, PullNone); } else { // can't enable in hardware, use software emulation - gpio_init_out_ex(&uart_data[index].sw_rts, rxflow, 0); + gpio_init_out_ex(&uart_data[index].sw_rts, pinmap->rx_flow_pin, 0); // Enable RX interrupt serial_flow_irq_set(obj, 1); } } } +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { + serial_fc_pinmap_t pinmap; + pinmap.rx_flow_pin = rxflow; + pinmap.tx_flow_pin = txflow; + + UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS); + if((int)uart_rts == NC) { + pinmap.rx_flow_function = NC; // use SW emulation + } + else { + pinmap.rx_flow_function = pinmap_find_function(rxflow, PinMap_UART_RTS); + } + + UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS); + if((int)uart_cts == NC) { + pinmap.tx_flow_function = NC; // use SW emulation + } + else { + pinmap.tx_flow_function = pinmap_find_function(rxflow, PinMap_UART_CTS); + } + + pinmap.peripheral = pinmap_merge(uart_rts, uart_cts); + + serial_set_flow_control_direct(obj, type, &pinmap); +} + const PinMap *serial_tx_pinmap() { return PinMap_UART_TX; diff --git a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c index 6b5950777ce..d1dd5777cca 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c @@ -19,45 +19,42 @@ #include "spi_api.h" #include "cmsis.h" -#include "pinmap.h" +#include "PeripheralPinMaps.h" #include "mbed_error.h" -static const 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 const 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 const 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 const 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 inline int ssp_disable(spi_t *obj); static inline int ssp_enable(spi_t *obj); +void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap) { + obj->spi = (LPC_SSP_TypeDef*)pinmap->peripheral; + + // enable power and clocking + switch ((int)obj->spi) { + case SPI_0: LPC_SC->PCONP |= 1 << 21; break; + case SPI_1: LPC_SC->PCONP |= 1 << 10; break; + } + + // pin out the spi pins + pin_function(pinmap->mosi_pin, pinmap->mosi_function); + pin_mode(pinmap->mosi_pin, PullNone); + pin_function(pinmap->miso_pin, pinmap->miso_function); + pin_mode(pinmap->miso_pin, PullNone); + pin_function(pinmap->sclk_pin, pinmap->sclk_function); + pin_mode(pinmap->sclk_pin, PullNone); + + if (pinmap->ssel_pin != NC) { + pin_function(pinmap->ssel_pin, pinmap->ssel_function); + pin_mode(pinmap->ssel_pin, PullNone); + } +} + void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { + spi_pinmap_t pinmap; + pinmap.mosi_pin = mosi; + pinmap.miso_pin = miso; + pinmap.sclk_pin = sclk; + pinmap.ssel_pin = ssel; + // determine the SPI to use SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); @@ -65,22 +62,16 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - obj->spi = (LPC_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl); + pinmap.peripheral = pinmap_merge(spi_data, spi_cntl); MBED_ASSERT((int)obj->spi != NC); - - // enable power and clocking - switch ((int)obj->spi) { - case SPI_0: LPC_SC->PCONP |= 1 << 21; break; - case SPI_1: LPC_SC->PCONP |= 1 << 10; break; - } - // pin out the spi pins - pinmap_pinout(mosi, PinMap_SPI_MOSI); - pinmap_pinout(miso, PinMap_SPI_MISO); - pinmap_pinout(sclk, PinMap_SPI_SCLK); - if (ssel != NC) { - pinmap_pinout(ssel, PinMap_SPI_SSEL); - } + // Get pin functions + pinmap.mosi_function = pinmap_find_function(mosi, PinMap_SPI_MOSI); + pinmap.miso_function = pinmap_find_function(miso, PinMap_SPI_MISO); + pinmap.sclk_function = pinmap_find_function(sclk, PinMap_SPI_SCLK); + pinmap.ssel_function = pinmap_find_function(ssel, PinMap_SPI_SSEL); + + spi_init_direct(obj, &pinmap); } void spi_free(spi_t *obj) {} diff --git a/targets/targets.json5 b/targets/targets.json5 index 393401cb94a..8f76b1945af 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -346,7 +346,7 @@ }, "overrides": { "network-default-interface-type": "ETHERNET", - "semihosting-enabled": true // needed for LOCALFILESYSTEM + "target.default-adc-vref": 3.3 // Per "mbed-005.1" schematic, Vref is 3.3V }, "supported_c_libs": { "arm": [ From 320ffeaace5bba63bebe55ce6717e48264ccb220 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Sat, 4 May 2024 23:49:51 -0700 Subject: [PATCH 4/6] Update ARCH_PRO pin names header to pass muster --- .../TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h index 565e14d666a..c51d911b9b7 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_ARCH_PRO/PinNames.h @@ -73,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, @@ -113,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, From b29620955b17391c70cf3d847cb2fe71796f3c4d Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Mon, 6 May 2024 23:06:37 -0700 Subject: [PATCH 5/6] LPC1768: Fix SPI 16-bit transfers --- .../TARGET_LPC176X/PeripheralNames.h | 1 + targets/TARGET_NXP/TARGET_LPC176X/objects.h | 1 + targets/TARGET_NXP/TARGET_LPC176X/spi_api.c | 61 +++++++++++++++---- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h b/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h index e0475301df5..ad889d4d1e3 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h @@ -48,6 +48,7 @@ typedef enum { // 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 diff --git a/targets/TARGET_NXP/TARGET_LPC176X/objects.h b/targets/TARGET_NXP/TARGET_LPC176X/objects.h index a4774acd4db..fa52e030cc4 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/objects.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/objects.h @@ -70,6 +70,7 @@ struct i2c_s { struct spi_s { LPC_SSP_TypeDef *spi; + uint8_t bits_per_word; }; struct flash_s { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c index d1dd5777cca..b0c5e0dc569 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c @@ -48,6 +48,16 @@ void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap) { } } +SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk) +{ + SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); + SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); + SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); + SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); + SPIName spi_periph = (SPIName)pinmap_merge(spi_sclk, spi_data); + return spi_periph; +} + void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { spi_pinmap_t pinmap; pinmap.mosi_pin = mosi; @@ -56,14 +66,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel pinmap.ssel_pin = ssel; // determine the SPI to use - SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); - SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); - SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); - SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); - SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); - SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - pinmap.peripheral = pinmap_merge(spi_data, spi_cntl); - MBED_ASSERT((int)obj->spi != NC); + SPIName spi_mosi_miso_sclk_periph = spi_get_peripheral_name(mosi, miso, sclk); + SPIName spi_ssel_periph = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); + pinmap.peripheral = pinmap_merge(spi_mosi_miso_sclk_periph, spi_ssel_periph); + MBED_ASSERT(pinmap.peripheral != NC); // Get pin functions pinmap.mosi_function = pinmap_find_function(mosi, PinMap_SPI_MOSI); @@ -80,6 +86,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) { ssp_disable(obj); MBED_ASSERT(((bits >= 4) && (bits <= 16)) && (mode >= 0 && mode <= 3)); + obj->bits_per_word = bits; int polarity = (mode & 0x2) ? 1 : 0; int phase = (mode & 0x1) ? 1 : 0; @@ -186,11 +193,39 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) { int total = (tx_length > rx_length) ? tx_length : rx_length; - for (int i = 0; i < total; i++) { - char out = (i < tx_length) ? tx_buffer[i] : write_fill; - char in = spi_master_write(obj, out); - if (i < rx_length) { - rx_buffer[i] = in; + if(obj->bits_per_word > 8) { + // 2 bytes per write/read operation + MBED_ASSERT(tx_length % 2 == 0); + MBED_ASSERT(rx_length % 2 == 0); + + // Extend write fill value to 16 bits + const uint16_t write_fill_u16 = (((uint16_t)write_fill) << 8) | write_fill; + + // Access input and output arrays as 16-bit words. + // This might do unaligned access, but that's OK for integers on Cortex-M3 + uint16_t const * const tx_buffer_u16 = (uint16_t const *)tx_buffer; + uint16_t * const rx_buffer_u16 = (uint16_t *)rx_buffer; + + const int tx_length_u16 = tx_length / 2; + const int rx_length_u16 = rx_length / 2; + + for (int i = 0; i < total / 2; i++) { + uint16_t out = (i < tx_length_u16) ? tx_buffer_u16[i] : write_fill_u16; + uint16_t in = spi_master_write(obj, out); + if (i < rx_length_u16) { + rx_buffer_u16[i] = in; + printf("rx_buffer_u16[%d] <= 0x%hx\n", i, in); + } + } + } + else { + // 1 byte per read/write operation + for (int i = 0; i < total; i++) { + uint16_t out = (i < tx_length) ? tx_buffer[i] : write_fill; + uint16_t in = spi_master_write(obj, out); + if (i < rx_length) { + rx_buffer[i] = in; + } } } From ba4c1156d4ef794a83f09f2216558af8a30bd906 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Tue, 7 May 2024 00:32:04 -0700 Subject: [PATCH 6/6] Fix merge mistake --- targets/TARGET_NXP/TARGET_LPC176X/spi_api.c | 26 --------------------- 1 file changed, 26 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c index 62e72dffcf6..b0c5e0dc569 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c @@ -48,32 +48,6 @@ void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap) { } } -void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { - spi_pinmap_t pinmap; - pinmap.mosi_pin = mosi; - pinmap.miso_pin = miso; - pinmap.sclk_pin = sclk; - pinmap.ssel_pin = ssel; - - // determine the SPI to use - SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); - SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); - SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); - SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); - SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); - SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - pinmap.peripheral = pinmap_merge(spi_data, spi_cntl); - MBED_ASSERT((int)obj->spi != NC); - - // Get pin functions - pinmap.mosi_function = pinmap_find_function(mosi, PinMap_SPI_MOSI); - pinmap.miso_function = pinmap_find_function(miso, PinMap_SPI_MISO); - pinmap.sclk_function = pinmap_find_function(sclk, PinMap_SPI_SCLK); - pinmap.ssel_function = pinmap_find_function(ssel, PinMap_SPI_SSEL); - - spi_init_direct(obj, &pinmap); -} - SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk) { SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);