Skip to content

Commit e8b6238

Browse files
Jamie Smithrelativityspace-jsmith
andauthored
Some fixes for Teensy4 (#272)
* Fix teensy4 build * Try and fix SCLK clock period issue for MIMXRT, add additional SPI pinmappings * Add full UART pinmapping * Make more robust to calling spi_format() after spi_frequency() * Fix style --------- Co-authored-by: Jamie Smith <[email protected]>
1 parent 04db467 commit e8b6238

File tree

9 files changed

+141
-10
lines changed

9 files changed

+141
-10
lines changed

hal/include/hal/spi_api.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,23 @@ void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap);
197197

198198
/** Initialize the SPI peripheral
199199
*
200-
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
200+
* Configures the pins used by SPI and enables the peripheral.
201+
*
202+
* After this function is called by the driver layer, spi_format() and spi_frequency() will
203+
* be called *before* the SPI bus is used.
204+
*
201205
* @param[out] obj The SPI object to initialize
202206
* @param[in] pinmap pointer to structure which holds static pinmap
203207
*/
204208
void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap);
205209

206210
/** Initialize the SPI peripheral
207211
*
208-
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
212+
* Configures the pins used by SPI and enables the peripheral
213+
*
214+
* After this function is called by the driver layer, spi_format() and spi_frequency() will
215+
* be called *before* the SPI bus is used.
216+
*
209217
* @param[out] obj The SPI object to initialize
210218
* @param[in] mosi The pin to use for MOSI
211219
* @param[in] miso The pin to use for MISO

platform/source/mbed_error.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ static inline bool mbed_error_is_hw_fault(mbed_error_status_t error_status)
116116
error_status == MBED_ERROR_HARDFAULT_EXCEPTION);
117117
}
118118

119+
#ifdef MBED_CONF_RTOS_PRESENT
119120
static bool mbed_error_is_handler(const mbed_error_ctx *ctx)
120121
{
121122
bool is_handler = false;
@@ -133,6 +134,7 @@ static bool mbed_error_is_handler(const mbed_error_ctx *ctx)
133134
}
134135
return is_handler;
135136
}
137+
#endif
136138

137139
//Set an error status with the error handling system
138140
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)

platform/source/mbed_sdk_boot.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
#include "mbed_error.h"
1819
#include "mbed_toolchain.h"
1920
#include <stdlib.h>
2021
#include <stdint.h>

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct i2c_s {
5757
struct spi_s {
5858
uint32_t instance;
5959
uint8_t bits;
60+
uint32_t frequency;
6061
};
6162

6263
struct dac_s {

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/spi_api.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,25 @@ static LPSPI_Type *const spi_address[] = LPSPI_BASE_PTRS;
3232
extern uint32_t spi_get_clock(void);
3333
extern void spi_setup_clock();
3434

35-
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
35+
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk)
3636
{
37-
// determine the SPI to use
3837
uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
3938
uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
4039
uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
41-
uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
4240
uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
43-
uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
4441

45-
obj->instance = pinmap_merge(spi_data, spi_cntl);
42+
SPIName spi_instance = pinmap_merge(spi_sclk, spi_data);
43+
return spi_instance;
44+
}
45+
46+
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
47+
{
48+
// determine the SPI to use
49+
SPIName spi_for_data_lines = spi_get_peripheral_name(mosi, miso, sclk);
50+
uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
51+
uint32_t spi_cntl = pinmap_merge(spi_for_data_lines, spi_ssel);
52+
53+
obj->instance = pinmap_merge(spi_for_data_lines, spi_cntl);
4654
MBED_ASSERT((int)obj->instance != NC);
4755

4856
// pin out the spi pins
@@ -53,6 +61,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
5361
pinmap_pinout(ssel, PinMap_SPI_SSEL);
5462
}
5563

64+
// Default frequency (just so we have something to set if spi_format() is called
65+
// before spi_frequency())
66+
obj->frequency = 1000000;
67+
5668
spi_setup_clock();
5769
}
5870

@@ -61,6 +73,30 @@ void spi_free(spi_t *obj)
6173
LPSPI_Deinit(spi_address[obj->instance]);
6274
}
6375

76+
/*
77+
* This function updates the `CCR.DBT` bitfield, which controls the length of the half
78+
* clock cycle between the end of one frame and the start of the next when in continuous mode.
79+
* It must be updated whenever the SPI clock frequency is changed.
80+
*
81+
* The MIMXRT HAL does not properly set this register so we end up with clock glitches
82+
* when doing multibyte SPI transfers.
83+
*
84+
* Note: The LPSPI must be disabled when calling this function.
85+
*/
86+
static void mimxrt_spi_update_dbt(LPSPI_Type * spibase)
87+
{
88+
// Step 1: Get the current SCLK period, in LPSPI functional clock periods, that was calculated by
89+
// LPSPI_MasterSetBaudRate(). This is given by the CCR.SCKDIV bitfield plus 2.
90+
const uint32_t sclkPeriodClocks = ((spibase->CCR & LPSPI_CCR_SCKDIV_MASK) >> LPSPI_CCR_SCKDIV_SHIFT) + 2;
91+
92+
// Step 2: Divide by 2, rounding up
93+
const uint32_t sclkLowTimeClocks = (sclkPeriodClocks + 1) / 2;
94+
95+
// Step 3: Set this value into the DBT field. The value used by HW is one higher than the value in the register
96+
// so we have to subtract.
97+
spibase->CCR = (spibase->CCR & ~LPSPI_CCR_DBT_MASK) | LPSPI_CCR_DBT(sclkLowTimeClocks - 1);
98+
}
99+
64100
void spi_format(spi_t *obj, int bits, int mode, int slave)
65101
{
66102
lpspi_master_config_t master_config;
@@ -74,14 +110,21 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
74110
slave_config.cpha = (mode & 0x1) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge;
75111
LPSPI_SlaveInit(spi_address[obj->instance], &slave_config);
76112
} else {
113+
77114
/* Master config */
78115
LPSPI_MasterGetDefaultConfig(&master_config);
79116
master_config.bitsPerFrame = (uint32_t)bits;;
80117
master_config.cpol = (mode & 0x2) ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh;
81118
master_config.cpha = (mode & 0x1) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge;
82119
master_config.direction = kLPSPI_MsbFirst;
120+
master_config.baudRate = obj->frequency;
83121

84122
LPSPI_MasterInit(spi_address[obj->instance], &master_config, spi_get_clock());
123+
124+
// Update the DBT field which gets overwritten by LPSPI_MasterInit
125+
LPSPI_Enable(spi_address[obj->instance], false);
126+
mimxrt_spi_update_dbt(spi_address[obj->instance]);
127+
LPSPI_Enable(spi_address[obj->instance], true);
85128
}
86129
}
87130

@@ -97,8 +140,14 @@ void spi_frequency(spi_t *obj, int hz)
97140

98141
spibase->TCR = (spibase->TCR & ~LPSPI_TCR_PRESCALE_MASK) | LPSPI_TCR_PRESCALE(tcrPrescaleValue);
99142

143+
// Update the DBT field which gets overwritten by LPSPI_MasterSetBaudRate
144+
mimxrt_spi_update_dbt(spi_address[obj->instance]);
145+
100146
/* Enable the LPSPI module */
101147
LPSPI_Enable(spibase, true);
148+
149+
// Save frequency for later
150+
obj->frequency = hz;
102151
}
103152

104153
static inline int spi_readable(spi_t * obj)

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralNames.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ typedef enum {
139139
DAC_0 = 0
140140
} DACName;
141141

142-
142+
#define DEVICE_SPI_COUNT 4
143143
typedef enum {
144144
SPI_1 = 1,
145145
SPI_2 = 2,

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/PeripheralPins.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,37 +109,107 @@ const PinMap PinMap_I2C_SCL[] = {
109109
/************UART***************/
110110
const PinMap PinMap_UART_TX[] = {
111111
{GPIO_AD_B0_12, UART_1, 2},
112+
113+
{GPIO_SD_B1_11, UART_2, ((0 << DAISY_REG_VALUE_SHIFT) | (0x530 << DAISY_REG_SHIFT) | 2)},
114+
{GPIO_AD_B1_02, UART_2, ((1 << DAISY_REG_VALUE_SHIFT) | (0x530 << DAISY_REG_SHIFT) | 2)},
115+
112116
{GPIO_AD_B1_06, UART_3, ((0 << DAISY_REG_VALUE_SHIFT) | (0x53C << DAISY_REG_SHIFT) | 2)},
117+
{GPIO_EMC_13 , UART_3, ((1 << DAISY_REG_VALUE_SHIFT) | (0x53C << DAISY_REG_SHIFT) | 2)},
118+
{GPIO_B0_08 , UART_3, ((2 << DAISY_REG_VALUE_SHIFT) | (0x53C << DAISY_REG_SHIFT) | 3)},
119+
120+
{GPIO_SD_B1_00, UART_4, ((0 << DAISY_REG_VALUE_SHIFT) | (0x544 << DAISY_REG_SHIFT) | 4)},
121+
{GPIO_EMC_19 , UART_4, ((1 << DAISY_REG_VALUE_SHIFT) | (0x544 << DAISY_REG_SHIFT) | 2)},
122+
{GPIO_B1_00 , UART_4, ((2 << DAISY_REG_VALUE_SHIFT) | (0x544 << DAISY_REG_SHIFT) | 2)},
123+
124+
{GPIO_EMC_23 , UART_5, ((0 << DAISY_REG_VALUE_SHIFT) | (0x54C << DAISY_REG_SHIFT) | 2)},
125+
{GPIO_B1_12 , UART_5, ((1 << DAISY_REG_VALUE_SHIFT) | (0x54C << DAISY_REG_SHIFT) | 1)},
126+
127+
{GPIO_EMC_25 , UART_6, ((0 << DAISY_REG_VALUE_SHIFT) | (0x554 << DAISY_REG_SHIFT) | 2)},
113128
{GPIO_AD_B0_02, UART_6, ((1 << DAISY_REG_VALUE_SHIFT) | (0x554 << DAISY_REG_SHIFT) | 2)},
129+
130+
{GPIO_SD_B1_08, UART_7, ((0 << DAISY_REG_VALUE_SHIFT) | (0x55C << DAISY_REG_SHIFT) | 2)},
131+
{GPIO_EMC_31 , UART_7, ((1 << DAISY_REG_VALUE_SHIFT) | (0x55C << DAISY_REG_SHIFT) | 2)},
132+
133+
{GPIO_SD_B0_04, UART_8, ((0 << DAISY_REG_VALUE_SHIFT) | (0x564 << DAISY_REG_SHIFT) | 2)},
134+
{GPIO_AD_B1_10, UART_8, ((1 << DAISY_REG_VALUE_SHIFT) | (0x564 << DAISY_REG_SHIFT) | 2)},
135+
{GPIO_EMC_38 , UART_8, ((2 << DAISY_REG_VALUE_SHIFT) | (0x564 << DAISY_REG_SHIFT) | 2)},
136+
114137
{NC , NC , 0}
115138
};
116139

117140
const PinMap PinMap_UART_RX[] = {
118141
{GPIO_AD_B0_13, UART_1, 2},
142+
143+
{GPIO_SD_B1_10, UART_2, ((0 << DAISY_REG_VALUE_SHIFT) | (0x52C << DAISY_REG_SHIFT) | 2)},
144+
{GPIO_AD_B1_03, UART_2, ((1 << DAISY_REG_VALUE_SHIFT) | (0x52C << DAISY_REG_SHIFT) | 2)},
145+
119146
{GPIO_AD_B1_07, UART_3, ((0 << DAISY_REG_VALUE_SHIFT) | (0x538 << DAISY_REG_SHIFT) | 2)},
147+
{GPIO_EMC_14 , UART_3, ((1 << DAISY_REG_VALUE_SHIFT) | (0x538 << DAISY_REG_SHIFT) | 2)},
148+
{GPIO_B0_09 , UART_3, ((2 << DAISY_REG_VALUE_SHIFT) | (0x538 << DAISY_REG_SHIFT) | 3)},
149+
150+
{GPIO_SD_B1_01, UART_4, ((0 << DAISY_REG_VALUE_SHIFT) | (0x540 << DAISY_REG_SHIFT) | 4)},
151+
{GPIO_EMC_20 , UART_4, ((1 << DAISY_REG_VALUE_SHIFT) | (0x540 << DAISY_REG_SHIFT) | 2)},
152+
{GPIO_B1_01 , UART_4, ((2 << DAISY_REG_VALUE_SHIFT) | (0x540 << DAISY_REG_SHIFT) | 2)},
153+
154+
{GPIO_EMC_24 , UART_5, ((0 << DAISY_REG_VALUE_SHIFT) | (0x548 << DAISY_REG_SHIFT) | 2)},
155+
{GPIO_B1_13 , UART_5, ((1 << DAISY_REG_VALUE_SHIFT) | (0x548 << DAISY_REG_SHIFT) | 1)},
156+
157+
{GPIO_EMC_26 , UART_6, ((0 << DAISY_REG_VALUE_SHIFT) | (0x550 << DAISY_REG_SHIFT) | 2)},
120158
{GPIO_AD_B0_03, UART_6, ((1 << DAISY_REG_VALUE_SHIFT) | (0x550 << DAISY_REG_SHIFT) | 2)},
159+
160+
{GPIO_SD_B1_09, UART_7, ((0 << DAISY_REG_VALUE_SHIFT) | (0x558 << DAISY_REG_SHIFT) | 2)},
161+
{GPIO_EMC_32 , UART_7, ((1 << DAISY_REG_VALUE_SHIFT) | (0x558 << DAISY_REG_SHIFT) | 2)},
162+
163+
{GPIO_SD_B0_05, UART_8, ((0 << DAISY_REG_VALUE_SHIFT) | (0x560 << DAISY_REG_SHIFT) | 2)},
164+
{GPIO_AD_B1_11, UART_8, ((1 << DAISY_REG_VALUE_SHIFT) | (0x560 << DAISY_REG_SHIFT) | 2)},
165+
{GPIO_EMC_39 , UART_8, ((2 << DAISY_REG_VALUE_SHIFT) | (0x560 << DAISY_REG_SHIFT) | 2)},
166+
121167
{NC , NC , 0}
122168
};
123169

124170
/************SPI***************/
125171
const PinMap PinMap_SPI_SCLK[] = {
172+
{GPIO_EMC_27, SPI_1, ((0U << DAISY_REG_VALUE_SHIFT) | (0x4F0 << DAISY_REG_SHIFT) | 3)},
126173
{GPIO_SD_B0_00, SPI_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x4F0 << DAISY_REG_SHIFT) | 4)},
174+
175+
{GPIO_SD_B1_07, SPI_2, ((0U << DAISY_REG_VALUE_SHIFT) | (0x500 << DAISY_REG_SHIFT) | 4)},
176+
{GPIO_EMC_00, SPI_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x500 << DAISY_REG_SHIFT) | 2)},
177+
127178
{GPIO_AD_B0_00, SPI_3, ((0U << DAISY_REG_VALUE_SHIFT) | (0x510 << DAISY_REG_SHIFT) | 7)},
179+
{GPIO_AD_B1_15, SPI_3, ((1U << DAISY_REG_VALUE_SHIFT) | (0x510 << DAISY_REG_SHIFT) | 2)},
180+
128181
{GPIO_B0_03, SPI_4, ((0U << DAISY_REG_VALUE_SHIFT) | (0x520 << DAISY_REG_SHIFT) | 3)},
182+
{GPIO_B1_07, SPI_4, ((1U << DAISY_REG_VALUE_SHIFT) | (0x520 << DAISY_REG_SHIFT) | 1)},
129183
{NC , NC , 0}
130184
};
131185

132186
const PinMap PinMap_SPI_MOSI[] = {
187+
{GPIO_EMC_28, SPI_1, ((0U << DAISY_REG_VALUE_SHIFT) | (0x4F8 << DAISY_REG_SHIFT) | 3)},
133188
{GPIO_SD_B0_02, SPI_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x4F8 << DAISY_REG_SHIFT) | 4)},
189+
190+
{GPIO_SD_B1_08, SPI_2, ((0U << DAISY_REG_VALUE_SHIFT) | (0x508 << DAISY_REG_SHIFT) | 4)},
191+
{GPIO_EMC_02, SPI_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x508 << DAISY_REG_SHIFT) | 2)},
192+
134193
{GPIO_AD_B0_01, SPI_3, ((0U << DAISY_REG_VALUE_SHIFT) | (0x518 << DAISY_REG_SHIFT) | 7)},
194+
{GPIO_AD_B1_14, SPI_3, ((1U << DAISY_REG_VALUE_SHIFT) | (0x518 << DAISY_REG_SHIFT) | 2)},
195+
135196
{GPIO_B0_02, SPI_4, ((0U << DAISY_REG_VALUE_SHIFT) | (0x528 << DAISY_REG_SHIFT) | 3)},
197+
{GPIO_B1_06, SPI_4, ((1U << DAISY_REG_VALUE_SHIFT) | (0x528 << DAISY_REG_SHIFT) | 1)},
136198
{NC , NC , 0}
137199
};
138200

139201
const PinMap PinMap_SPI_MISO[] = {
202+
{GPIO_EMC_29, SPI_1, ((0U << DAISY_REG_VALUE_SHIFT) | (0x4F4 << DAISY_REG_SHIFT) | 3)},
140203
{GPIO_SD_B0_03, SPI_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x4F4 << DAISY_REG_SHIFT) | 4)},
204+
205+
{GPIO_SD_B1_09, SPI_2, ((0U << DAISY_REG_VALUE_SHIFT) | (0x504 << DAISY_REG_SHIFT) | 4)},
206+
{GPIO_EMC_03, SPI_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x504 << DAISY_REG_SHIFT) | 2)},
207+
141208
{GPIO_AD_B0_02, SPI_3, ((0U << DAISY_REG_VALUE_SHIFT) | (0x514 << DAISY_REG_SHIFT) | 7)},
209+
{GPIO_AD_B1_13, SPI_3, ((1U << DAISY_REG_VALUE_SHIFT) | (0x514 << DAISY_REG_SHIFT) | 2)},
210+
142211
{GPIO_B0_01, SPI_4, ((0U << DAISY_REG_VALUE_SHIFT) | (0x524 << DAISY_REG_SHIFT) | 3)},
212+
{GPIO_B1_05, SPI_4, ((1U << DAISY_REG_VALUE_SHIFT) | (0x524 << DAISY_REG_SHIFT) | 1)},
143213
{NC , NC , 0}
144214
};
145215

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT105x/TARGET_TEENSY_4X/bootdata.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
*/
4141

4242
#include <stdint.h>
43-
#include <mimxrt_flash_info.h>
43+
#include <mimxrt_memory_info.h>
4444

4545
extern void Reset_Handler(void);
4646
extern unsigned long _estack;

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1170/TARGET_EVK/PeripheralNames.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ typedef enum {
128128
DAC_0 = 0
129129
} DACName;
130130

131-
131+
#define DEVICE_SPI_COUNT 3
132132
typedef enum {
133133
SPI_1 = 1,
134134
SPI_2 = 2,

0 commit comments

Comments
 (0)