Skip to content

Commit 1b60dda

Browse files
author
Jamie Smith
authored
LPC1768: Fix SPI 16-bit transfers (ARMmbed#277)
* 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 * LPC1768: Fix SPI 16-bit transfers * Fix merge mistake
1 parent 94a7fbc commit 1b60dda

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

targets/TARGET_NXP/TARGET_LPC176X/PeripheralNames.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ typedef enum {
4848

4949
// Note: We only use the two SSP peripherals in Mbed, not SPI0. This is because
5050
// SPI0 is a legacy version of the SSP peripheral and cannot be used at the same time as SSP0.
51+
#define DEVICE_SPI_COUNT 2
5152
typedef enum {
5253
SPI_0 = (int)LPC_SSP0_BASE,
5354
SPI_1 = (int)LPC_SSP1_BASE

targets/TARGET_NXP/TARGET_LPC176X/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct i2c_s {
7070

7171
struct spi_s {
7272
LPC_SSP_TypeDef *spi;
73+
uint8_t bits_per_word;
7374
};
7475

7576
struct flash_s {

targets/TARGET_NXP/TARGET_LPC176X/spi_api.c

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap) {
4848
}
4949
}
5050

51+
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk)
52+
{
53+
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
54+
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
55+
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
56+
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
57+
SPIName spi_periph = (SPIName)pinmap_merge(spi_sclk, spi_data);
58+
return spi_periph;
59+
}
60+
5161
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
5262
spi_pinmap_t pinmap;
5363
pinmap.mosi_pin = mosi;
@@ -56,14 +66,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
5666
pinmap.ssel_pin = ssel;
5767

5868
// determine the SPI to use
59-
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
60-
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
61-
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
62-
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
63-
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
64-
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
65-
pinmap.peripheral = pinmap_merge(spi_data, spi_cntl);
66-
MBED_ASSERT((int)obj->spi != NC);
69+
SPIName spi_mosi_miso_sclk_periph = spi_get_peripheral_name(mosi, miso, sclk);
70+
SPIName spi_ssel_periph = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
71+
pinmap.peripheral = pinmap_merge(spi_mosi_miso_sclk_periph, spi_ssel_periph);
72+
MBED_ASSERT(pinmap.peripheral != NC);
6773

6874
// Get pin functions
6975
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) {
8086
ssp_disable(obj);
8187
MBED_ASSERT(((bits >= 4) && (bits <= 16)) && (mode >= 0 && mode <= 3));
8288

89+
obj->bits_per_word = bits;
8390
int polarity = (mode & 0x2) ? 1 : 0;
8491
int phase = (mode & 0x1) ? 1 : 0;
8592

@@ -186,11 +193,39 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
186193
char *rx_buffer, int rx_length, char write_fill) {
187194
int total = (tx_length > rx_length) ? tx_length : rx_length;
188195

189-
for (int i = 0; i < total; i++) {
190-
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
191-
char in = spi_master_write(obj, out);
192-
if (i < rx_length) {
193-
rx_buffer[i] = in;
196+
if(obj->bits_per_word > 8) {
197+
// 2 bytes per write/read operation
198+
MBED_ASSERT(tx_length % 2 == 0);
199+
MBED_ASSERT(rx_length % 2 == 0);
200+
201+
// Extend write fill value to 16 bits
202+
const uint16_t write_fill_u16 = (((uint16_t)write_fill) << 8) | write_fill;
203+
204+
// Access input and output arrays as 16-bit words.
205+
// This might do unaligned access, but that's OK for integers on Cortex-M3
206+
uint16_t const * const tx_buffer_u16 = (uint16_t const *)tx_buffer;
207+
uint16_t * const rx_buffer_u16 = (uint16_t *)rx_buffer;
208+
209+
const int tx_length_u16 = tx_length / 2;
210+
const int rx_length_u16 = rx_length / 2;
211+
212+
for (int i = 0; i < total / 2; i++) {
213+
uint16_t out = (i < tx_length_u16) ? tx_buffer_u16[i] : write_fill_u16;
214+
uint16_t in = spi_master_write(obj, out);
215+
if (i < rx_length_u16) {
216+
rx_buffer_u16[i] = in;
217+
printf("rx_buffer_u16[%d] <= 0x%hx\n", i, in);
218+
}
219+
}
220+
}
221+
else {
222+
// 1 byte per read/write operation
223+
for (int i = 0; i < total; i++) {
224+
uint16_t out = (i < tx_length) ? tx_buffer[i] : write_fill;
225+
uint16_t in = spi_master_write(obj, out);
226+
if (i < rx_length) {
227+
rx_buffer[i] = in;
228+
}
194229
}
195230
}
196231

0 commit comments

Comments
 (0)