Skip to content

Commit 928b206

Browse files
committed
Merge pull request #413 from lindvalla/fix_spi_on_lpc1549
Fixed three issues with the SPI driver for the LPC1549 platform:
2 parents 7a5896c + ea510ce commit 928b206

File tree

1 file changed

+68
-12
lines changed
  • libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX

1 file changed

+68
-12
lines changed

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/spi_api.c

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,69 @@ static const SWM_Map SWM_SPI_MISO[] = {
4343

4444
// bit flags for used SPIs
4545
static unsigned char spi_used = 0;
46-
static int get_available_spi(void)
46+
static int get_available_spi(PinName mosi, PinName miso, PinName sclk, PinName ssel)
4747
{
48-
int i;
49-
for (i=0; i<2; i++) {
50-
if ((spi_used & (1 << i)) == 0)
51-
return i;
48+
if (spi_used == 0) {
49+
return 0; // The first user
5250
}
51+
52+
const SWM_Map *swm;
53+
uint32_t regVal;
54+
55+
// Investigate if same pins as the used SPI0/1 - to be able to reuse it
56+
for (int spi_n = 0; spi_n < 2; spi_n++) {
57+
if (spi_used & (1<<spi_n)) {
58+
if (sclk != NC) {
59+
swm = &SWM_SPI_SCLK[spi_n];
60+
regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
61+
if (regVal != (sclk << swm->offset)) {
62+
// Existing pin is not the same as the one we want
63+
continue;
64+
}
65+
}
66+
67+
if (mosi != NC) {
68+
swm = &SWM_SPI_MOSI[spi_n];
69+
regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
70+
if (regVal != (mosi << swm->offset)) {
71+
// Existing pin is not the same as the one we want
72+
continue;
73+
}
74+
}
75+
76+
if (miso != NC) {
77+
swm = &SWM_SPI_MISO[spi_n];
78+
regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
79+
if (regVal != (miso << swm->offset)) {
80+
// Existing pin is not the same as the one we want
81+
continue;
82+
}
83+
}
84+
85+
if (ssel != NC) {
86+
swm = &SWM_SPI_SSEL[spi_n];
87+
regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset);
88+
if (regVal != (ssel << swm->offset)) {
89+
// Existing pin is not the same as the one we want
90+
continue;
91+
}
92+
}
93+
94+
// The pins for the currently used SPIx are the same as the
95+
// ones we want so we will reuse it
96+
return spi_n;
97+
}
98+
}
99+
100+
// None of the existing SPIx pin setups match the pins we want
101+
// so the last hope is to select one unused SPIx
102+
if ((spi_used & 1) == 0) {
103+
return 0;
104+
} else if ((spi_used & 2) == 0) {
105+
return 1;
106+
}
107+
108+
// No matching setup and no free SPIx
53109
return -1;
54110
}
55111

@@ -58,7 +114,7 @@ static inline void spi_enable(spi_t *obj);
58114

59115
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
60116
{
61-
int spi_n = get_available_spi();
117+
int spi_n = get_available_spi(mosi, miso, sclk, ssel);
62118
if (spi_n == -1) {
63119
error("No available SPI");
64120
}
@@ -138,10 +194,10 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
138194
obj->spi->CFG = tmp;
139195

140196
// select frame length
141-
tmp = obj->spi->TXDATCTL;
197+
tmp = obj->spi->TXCTL;
142198
tmp &= ~(0xf << 24);
143199
tmp |= (LEN << 24);
144-
obj->spi->TXDATCTL = tmp;
200+
obj->spi->TXCTL = tmp;
145201

146202
spi_enable(obj);
147203
}
@@ -181,14 +237,14 @@ static inline void spi_write(spi_t *obj, int value)
181237
{
182238
while (!spi_writeable(obj));
183239
// end of transfer
184-
obj->spi->TXDATCTL |= (1 << 20);
185-
obj->spi->TXDAT = value;
240+
obj->spi->TXCTL |= (1 << 20);
241+
obj->spi->TXDAT = (value & 0xffff);
186242
}
187243

188244
static inline int spi_read(spi_t *obj)
189245
{
190246
while (!spi_readable(obj));
191-
return obj->spi->RXDAT;
247+
return obj->spi->RXDAT & 0xffff; // Only the lower 16 bits contain data
192248
}
193249

194250
int spi_busy(spi_t *obj)
@@ -210,7 +266,7 @@ int spi_slave_receive(spi_t *obj)
210266

211267
int spi_slave_read(spi_t *obj)
212268
{
213-
return obj->spi->RXDAT;
269+
return obj->spi->RXDAT & 0xffff; // Only the lower 16 bits contain data
214270
}
215271

216272
void spi_slave_write(spi_t *obj, int value)

0 commit comments

Comments
 (0)