diff --git a/hal/include/hal/spi_api.h b/hal/include/hal/spi_api.h index 011073a02a7..35c8b8a126a 100644 --- a/hal/include/hal/spi_api.h +++ b/hal/include/hal/spi_api.h @@ -197,7 +197,11 @@ void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap); /** Initialize the SPI peripheral * - * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral + * Configures the pins used by SPI and enables the peripheral. + * + * After this function is called by the driver layer, spi_format() and spi_frequency() will + * be called *before* the SPI bus is used. + * * @param[out] obj The SPI object to initialize * @param[in] pinmap pointer to structure which holds static pinmap */ @@ -205,7 +209,11 @@ void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap); /** Initialize the SPI peripheral * - * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral + * Configures the pins used by SPI and enables the peripheral + * + * After this function is called by the driver layer, spi_format() and spi_frequency() will + * be called *before* the SPI bus is used. + * * @param[out] obj The SPI object to initialize * @param[in] mosi The pin to use for MOSI * @param[in] miso The pin to use for MISO diff --git a/platform/source/mbed_error.c b/platform/source/mbed_error.c index 50c476f6b0e..af888012c7f 100644 --- a/platform/source/mbed_error.c +++ b/platform/source/mbed_error.c @@ -116,6 +116,7 @@ static inline bool mbed_error_is_hw_fault(mbed_error_status_t error_status) error_status == MBED_ERROR_HARDFAULT_EXCEPTION); } +#ifdef MBED_CONF_RTOS_PRESENT static bool mbed_error_is_handler(const mbed_error_ctx *ctx) { bool is_handler = false; @@ -133,6 +134,7 @@ static bool mbed_error_is_handler(const mbed_error_ctx *ctx) } return is_handler; } +#endif //Set an error status with the error handling system static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller) diff --git a/platform/source/mbed_sdk_boot.c b/platform/source/mbed_sdk_boot.c index 0d0f3b664eb..34f8005412e 100644 --- a/platform/source/mbed_sdk_boot.c +++ b/platform/source/mbed_sdk_boot.c @@ -15,6 +15,7 @@ * limitations under the License. */ +#include "mbed_error.h" #include "mbed_toolchain.h" #include #include diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h index a45ba97d7ad..574c3ba70e4 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h @@ -57,6 +57,7 @@ struct i2c_s { struct spi_s { uint32_t instance; uint8_t bits; + uint32_t frequency; }; struct dac_s { diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c index 5ad86970767..0befd785ca3 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c @@ -32,17 +32,25 @@ static LPSPI_Type *const spi_address[] = LPSPI_BASE_PTRS; extern uint32_t spi_get_clock(void); extern void spi_setup_clock(); -void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk) { - // determine the SPI to use uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI); uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO); uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK); - uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL); uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso); - uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel); - obj->instance = pinmap_merge(spi_data, spi_cntl); + SPIName spi_instance = pinmap_merge(spi_sclk, spi_data); + return spi_instance; +} + +void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +{ + // determine the SPI to use + SPIName spi_for_data_lines = spi_get_peripheral_name(mosi, miso, sclk); + uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL); + uint32_t spi_cntl = pinmap_merge(spi_for_data_lines, spi_ssel); + + obj->instance = pinmap_merge(spi_for_data_lines, spi_cntl); MBED_ASSERT((int)obj->instance != NC); // pin out the spi pins @@ -53,6 +61,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel pinmap_pinout(ssel, PinMap_SPI_SSEL); } + // Default frequency (just so we have something to set if spi_format() is called + // before spi_frequency()) + obj->frequency = 1000000; + spi_setup_clock(); } @@ -61,6 +73,30 @@ void spi_free(spi_t *obj) LPSPI_Deinit(spi_address[obj->instance]); } +/* + * This function updates the `CCR.DBT` bitfield, which controls the length of the half + * clock cycle between the end of one frame and the start of the next when in continuous mode. + * It must be updated whenever the SPI clock frequency is changed. + * + * The MIMXRT HAL does not properly set this register so we end up with clock glitches + * when doing multibyte SPI transfers. + * + * Note: The LPSPI must be disabled when calling this function. + */ +static void mimxrt_spi_update_dbt(LPSPI_Type * spibase) +{ + // Step 1: Get the current SCLK period, in LPSPI functional clock periods, that was calculated by + // LPSPI_MasterSetBaudRate(). This is given by the CCR.SCKDIV bitfield plus 2. + const uint32_t sclkPeriodClocks = ((spibase->CCR & LPSPI_CCR_SCKDIV_MASK) >> LPSPI_CCR_SCKDIV_SHIFT) + 2; + + // Step 2: Divide by 2, rounding up + const uint32_t sclkLowTimeClocks = (sclkPeriodClocks + 1) / 2; + + // Step 3: Set this value into the DBT field. The value used by HW is one higher than the value in the register + // so we have to subtract. + spibase->CCR = (spibase->CCR & ~LPSPI_CCR_DBT_MASK) | LPSPI_CCR_DBT(sclkLowTimeClocks - 1); +} + void spi_format(spi_t *obj, int bits, int mode, int slave) { lpspi_master_config_t master_config; @@ -74,14 +110,21 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) slave_config.cpha = (mode & 0x1) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge; LPSPI_SlaveInit(spi_address[obj->instance], &slave_config); } else { + /* Master config */ LPSPI_MasterGetDefaultConfig(&master_config); master_config.bitsPerFrame = (uint32_t)bits;; master_config.cpol = (mode & 0x2) ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh; master_config.cpha = (mode & 0x1) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge; master_config.direction = kLPSPI_MsbFirst; + master_config.baudRate = obj->frequency; LPSPI_MasterInit(spi_address[obj->instance], &master_config, spi_get_clock()); + + // Update the DBT field which gets overwritten by LPSPI_MasterInit + LPSPI_Enable(spi_address[obj->instance], false); + mimxrt_spi_update_dbt(spi_address[obj->instance]); + LPSPI_Enable(spi_address[obj->instance], true); } } @@ -97,8 +140,14 @@ void spi_frequency(spi_t *obj, int hz) spibase->TCR = (spibase->TCR & ~LPSPI_TCR_PRESCALE_MASK) | LPSPI_TCR_PRESCALE(tcrPrescaleValue); + // Update the DBT field which gets overwritten by LPSPI_MasterSetBaudRate + mimxrt_spi_update_dbt(spi_address[obj->instance]); + /* Enable the LPSPI module */ LPSPI_Enable(spibase, true); + + // Save frequency for later + obj->frequency = hz; } static inline int spi_readable(spi_t * obj) diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralNames.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralNames.h index fcf725a241d..9f2bf4147d8 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralNames.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralNames.h @@ -139,7 +139,7 @@ typedef enum { DAC_0 = 0 } DACName; - +#define DEVICE_SPI_COUNT 4 typedef enum { SPI_1 = 1, SPI_2 = 2, diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralPins.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralPins.c index 20c4076e44d..31211fcff89 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralPins.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralPins.c @@ -109,37 +109,107 @@ const PinMap PinMap_I2C_SCL[] = { /************UART***************/ const PinMap PinMap_UART_TX[] = { {GPIO_AD_B0_12, UART_1, 2}, + + {GPIO_SD_B1_11, UART_2, ((0 << DAISY_REG_VALUE_SHIFT) | (0x530 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B1_02, UART_2, ((1 << DAISY_REG_VALUE_SHIFT) | (0x530 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B1_06, UART_3, ((0 << DAISY_REG_VALUE_SHIFT) | (0x53C << DAISY_REG_SHIFT) | 2)}, + {GPIO_EMC_13 , UART_3, ((1 << DAISY_REG_VALUE_SHIFT) | (0x53C << DAISY_REG_SHIFT) | 2)}, + {GPIO_B0_08 , UART_3, ((2 << DAISY_REG_VALUE_SHIFT) | (0x53C << DAISY_REG_SHIFT) | 3)}, + + {GPIO_SD_B1_00, UART_4, ((0 << DAISY_REG_VALUE_SHIFT) | (0x544 << DAISY_REG_SHIFT) | 4)}, + {GPIO_EMC_19 , UART_4, ((1 << DAISY_REG_VALUE_SHIFT) | (0x544 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B1_00 , UART_4, ((2 << DAISY_REG_VALUE_SHIFT) | (0x544 << DAISY_REG_SHIFT) | 2)}, + + {GPIO_EMC_23 , UART_5, ((0 << DAISY_REG_VALUE_SHIFT) | (0x54C << DAISY_REG_SHIFT) | 2)}, + {GPIO_B1_12 , UART_5, ((1 << DAISY_REG_VALUE_SHIFT) | (0x54C << DAISY_REG_SHIFT) | 1)}, + + {GPIO_EMC_25 , UART_6, ((0 << DAISY_REG_VALUE_SHIFT) | (0x554 << DAISY_REG_SHIFT) | 2)}, {GPIO_AD_B0_02, UART_6, ((1 << DAISY_REG_VALUE_SHIFT) | (0x554 << DAISY_REG_SHIFT) | 2)}, + + {GPIO_SD_B1_08, UART_7, ((0 << DAISY_REG_VALUE_SHIFT) | (0x55C << DAISY_REG_SHIFT) | 2)}, + {GPIO_EMC_31 , UART_7, ((1 << DAISY_REG_VALUE_SHIFT) | (0x55C << DAISY_REG_SHIFT) | 2)}, + + {GPIO_SD_B0_04, UART_8, ((0 << DAISY_REG_VALUE_SHIFT) | (0x564 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B1_10, UART_8, ((1 << DAISY_REG_VALUE_SHIFT) | (0x564 << DAISY_REG_SHIFT) | 2)}, + {GPIO_EMC_38 , UART_8, ((2 << DAISY_REG_VALUE_SHIFT) | (0x564 << DAISY_REG_SHIFT) | 2)}, + {NC , NC , 0} }; const PinMap PinMap_UART_RX[] = { {GPIO_AD_B0_13, UART_1, 2}, + + {GPIO_SD_B1_10, UART_2, ((0 << DAISY_REG_VALUE_SHIFT) | (0x52C << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B1_03, UART_2, ((1 << DAISY_REG_VALUE_SHIFT) | (0x52C << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B1_07, UART_3, ((0 << DAISY_REG_VALUE_SHIFT) | (0x538 << DAISY_REG_SHIFT) | 2)}, + {GPIO_EMC_14 , UART_3, ((1 << DAISY_REG_VALUE_SHIFT) | (0x538 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B0_09 , UART_3, ((2 << DAISY_REG_VALUE_SHIFT) | (0x538 << DAISY_REG_SHIFT) | 3)}, + + {GPIO_SD_B1_01, UART_4, ((0 << DAISY_REG_VALUE_SHIFT) | (0x540 << DAISY_REG_SHIFT) | 4)}, + {GPIO_EMC_20 , UART_4, ((1 << DAISY_REG_VALUE_SHIFT) | (0x540 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B1_01 , UART_4, ((2 << DAISY_REG_VALUE_SHIFT) | (0x540 << DAISY_REG_SHIFT) | 2)}, + + {GPIO_EMC_24 , UART_5, ((0 << DAISY_REG_VALUE_SHIFT) | (0x548 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B1_13 , UART_5, ((1 << DAISY_REG_VALUE_SHIFT) | (0x548 << DAISY_REG_SHIFT) | 1)}, + + {GPIO_EMC_26 , UART_6, ((0 << DAISY_REG_VALUE_SHIFT) | (0x550 << DAISY_REG_SHIFT) | 2)}, {GPIO_AD_B0_03, UART_6, ((1 << DAISY_REG_VALUE_SHIFT) | (0x550 << DAISY_REG_SHIFT) | 2)}, + + {GPIO_SD_B1_09, UART_7, ((0 << DAISY_REG_VALUE_SHIFT) | (0x558 << DAISY_REG_SHIFT) | 2)}, + {GPIO_EMC_32 , UART_7, ((1 << DAISY_REG_VALUE_SHIFT) | (0x558 << DAISY_REG_SHIFT) | 2)}, + + {GPIO_SD_B0_05, UART_8, ((0 << DAISY_REG_VALUE_SHIFT) | (0x560 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B1_11, UART_8, ((1 << DAISY_REG_VALUE_SHIFT) | (0x560 << DAISY_REG_SHIFT) | 2)}, + {GPIO_EMC_39 , UART_8, ((2 << DAISY_REG_VALUE_SHIFT) | (0x560 << DAISY_REG_SHIFT) | 2)}, + {NC , NC , 0} }; /************SPI***************/ const PinMap PinMap_SPI_SCLK[] = { + {GPIO_EMC_27, SPI_1, ((0U << DAISY_REG_VALUE_SHIFT) | (0x4F0 << DAISY_REG_SHIFT) | 3)}, {GPIO_SD_B0_00, SPI_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x4F0 << DAISY_REG_SHIFT) | 4)}, + + {GPIO_SD_B1_07, SPI_2, ((0U << DAISY_REG_VALUE_SHIFT) | (0x500 << DAISY_REG_SHIFT) | 4)}, + {GPIO_EMC_00, SPI_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x500 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B0_00, SPI_3, ((0U << DAISY_REG_VALUE_SHIFT) | (0x510 << DAISY_REG_SHIFT) | 7)}, + {GPIO_AD_B1_15, SPI_3, ((1U << DAISY_REG_VALUE_SHIFT) | (0x510 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B0_03, SPI_4, ((0U << DAISY_REG_VALUE_SHIFT) | (0x520 << DAISY_REG_SHIFT) | 3)}, + {GPIO_B1_07, SPI_4, ((1U << DAISY_REG_VALUE_SHIFT) | (0x520 << DAISY_REG_SHIFT) | 1)}, {NC , NC , 0} }; const PinMap PinMap_SPI_MOSI[] = { + {GPIO_EMC_28, SPI_1, ((0U << DAISY_REG_VALUE_SHIFT) | (0x4F8 << DAISY_REG_SHIFT) | 3)}, {GPIO_SD_B0_02, SPI_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x4F8 << DAISY_REG_SHIFT) | 4)}, + + {GPIO_SD_B1_08, SPI_2, ((0U << DAISY_REG_VALUE_SHIFT) | (0x508 << DAISY_REG_SHIFT) | 4)}, + {GPIO_EMC_02, SPI_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x508 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B0_01, SPI_3, ((0U << DAISY_REG_VALUE_SHIFT) | (0x518 << DAISY_REG_SHIFT) | 7)}, + {GPIO_AD_B1_14, SPI_3, ((1U << DAISY_REG_VALUE_SHIFT) | (0x518 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B0_02, SPI_4, ((0U << DAISY_REG_VALUE_SHIFT) | (0x528 << DAISY_REG_SHIFT) | 3)}, + {GPIO_B1_06, SPI_4, ((1U << DAISY_REG_VALUE_SHIFT) | (0x528 << DAISY_REG_SHIFT) | 1)}, {NC , NC , 0} }; const PinMap PinMap_SPI_MISO[] = { + {GPIO_EMC_29, SPI_1, ((0U << DAISY_REG_VALUE_SHIFT) | (0x4F4 << DAISY_REG_SHIFT) | 3)}, {GPIO_SD_B0_03, SPI_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x4F4 << DAISY_REG_SHIFT) | 4)}, + + {GPIO_SD_B1_09, SPI_2, ((0U << DAISY_REG_VALUE_SHIFT) | (0x504 << DAISY_REG_SHIFT) | 4)}, + {GPIO_EMC_03, SPI_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x504 << DAISY_REG_SHIFT) | 2)}, + {GPIO_AD_B0_02, SPI_3, ((0U << DAISY_REG_VALUE_SHIFT) | (0x514 << DAISY_REG_SHIFT) | 7)}, + {GPIO_AD_B1_13, SPI_3, ((1U << DAISY_REG_VALUE_SHIFT) | (0x514 << DAISY_REG_SHIFT) | 2)}, + {GPIO_B0_01, SPI_4, ((0U << DAISY_REG_VALUE_SHIFT) | (0x524 << DAISY_REG_SHIFT) | 3)}, + {GPIO_B1_05, SPI_4, ((1U << DAISY_REG_VALUE_SHIFT) | (0x524 << DAISY_REG_SHIFT) | 1)}, {NC , NC , 0} }; diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/TARGET_TEENSY_4X/bootdata.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/TARGET_TEENSY_4X/bootdata.c index dc5c4271b67..b450ac9ad15 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/TARGET_TEENSY_4X/bootdata.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/TARGET_TEENSY_4X/bootdata.c @@ -40,7 +40,7 @@ */ #include -#include +#include extern void Reset_Handler(void); extern unsigned long _estack; diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1170/TARGET_EVK/PeripheralNames.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1170/TARGET_EVK/PeripheralNames.h index 0ee292f6caf..27eed643ee7 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1170/TARGET_EVK/PeripheralNames.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1170/TARGET_EVK/PeripheralNames.h @@ -128,7 +128,7 @@ typedef enum { DAC_0 = 0 } DACName; - +#define DEVICE_SPI_COUNT 3 typedef enum { SPI_1 = 1, SPI_2 = 2,