Skip to content

Commit 07706f0

Browse files
committed
[LPC1549] Added SPI support
1 parent 78d4c73 commit 07706f0

File tree

3 files changed

+218
-2
lines changed

3 files changed

+218
-2
lines changed

libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_ARM_MICRO/LPC15xx.sct

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ LR_IROM1 0x00000000 0x40000 { ; load region size_region (256k)
1010
RW_IRAM1 (0x02000000+0x100) (0x9000-0x100) {
1111
.ANY (+RW +ZI)
1212
}
13+
}

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/device.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
#define DEVICE_I2C 0
3232
#define DEVICE_I2CSLAVE 0
3333

34-
#define DEVICE_SPI 0
35-
#define DEVICE_SPISLAVE 0
34+
#define DEVICE_SPI 1
35+
#define DEVICE_SPISLAVE 1
3636

3737
#define DEVICE_CAN 0
3838

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <math.h>
17+
18+
#include "spi_api.h"
19+
#include "cmsis.h"
20+
#include "pinmap.h"
21+
#include "error.h"
22+
23+
static const SWM_Map SWM_SPI_SSEL[] = {
24+
{4, 0},
25+
{5, 24},
26+
};
27+
28+
static const SWM_Map SWM_SPI_SCLK[] = {
29+
{3, 8},
30+
{5, 0},
31+
};
32+
33+
static const SWM_Map SWM_SPI_MOSI[] = {
34+
{3, 16},
35+
{5, 8},
36+
};
37+
38+
static const SWM_Map SWM_SPI_MISO[] = {
39+
{3, 24},
40+
{5, 16},
41+
};
42+
43+
// bit flags for used SPIs
44+
static unsigned char spi_used = 0;
45+
static int get_available_spi(void) {
46+
int i;
47+
for (i=0; i<2; i++) {
48+
if ((spi_used & (1 << i)) == 0)
49+
return i;
50+
}
51+
return -1;
52+
}
53+
54+
static inline void spi_disable(spi_t *obj);
55+
static inline void spi_enable(spi_t *obj);
56+
57+
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
58+
int spi_n = get_available_spi();
59+
if (spi_n == -1) {
60+
error("No available SPI");
61+
}
62+
63+
obj->spi_n = spi_n;
64+
spi_used |= (1 << spi_n);
65+
66+
obj->spi = (spi_n) ? (LPC_SPI0_Type *)(LPC_SPI1_BASE) : (LPC_SPI0_Type *)(LPC_SPI0_BASE);
67+
68+
const SWM_Map *swm;
69+
uint32_t regVal;
70+
71+
if (sclk != NC) {
72+
swm = &SWM_SPI_SCLK[obj->spi_n];
73+
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
74+
LPC_SWM->PINASSIGN[swm->n] = regVal | (sclk << swm->offset);
75+
}
76+
77+
if (mosi != NC) {
78+
swm = &SWM_SPI_MOSI[obj->spi_n];
79+
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
80+
LPC_SWM->PINASSIGN[swm->n] = regVal | (mosi << swm->offset);
81+
}
82+
83+
if (miso != NC) {
84+
swm = &SWM_SPI_MISO[obj->spi_n];
85+
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
86+
LPC_SWM->PINASSIGN[swm->n] = regVal | (miso << swm->offset);
87+
}
88+
89+
if (ssel != NC) {
90+
swm = &SWM_SPI_SSEL[obj->spi_n];
91+
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
92+
LPC_SWM->PINASSIGN[swm->n] = regVal | (ssel << swm->offset);
93+
}
94+
95+
// clear interrupts
96+
obj->spi->INTENCLR = 0x3f;
97+
98+
// enable power and clocking
99+
100+
switch (obj->spi_n) {
101+
case 0:
102+
LPC_SYSCON->SYSAHBCLKCTRL1 |= (0x1<<9);
103+
LPC_SYSCON->PRESETCTRL1 |= (0x1<<9);
104+
LPC_SYSCON->PRESETCTRL1 &= ~(0x1<<9);
105+
break;
106+
case 1:
107+
LPC_SYSCON->SYSAHBCLKCTRL1 |= (0x1<<10);
108+
LPC_SYSCON->PRESETCTRL1 |= (0x1<<10);
109+
LPC_SYSCON->PRESETCTRL1 &= ~(0x1<<10);
110+
break;
111+
}
112+
113+
// set default format and frequency
114+
if (ssel == NC) {
115+
spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
116+
} else {
117+
spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
118+
}
119+
spi_frequency(obj, 1000000);
120+
121+
// enable the spi channel
122+
spi_enable(obj);
123+
}
124+
125+
void spi_free(spi_t *obj) {}
126+
127+
void spi_format(spi_t *obj, int bits, int mode, int slave) {
128+
spi_disable(obj);
129+
130+
if (!(bits >= 1 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
131+
error("SPI format error");
132+
}
133+
134+
int polarity = (mode & 0x2) ? 1 : 0;
135+
int phase = (mode & 0x1) ? 1 : 0;
136+
137+
// set it up
138+
int LEN = bits - 1; // LEN - Data Length
139+
int CPOL = (polarity) ? 1 : 0; // CPOL - Clock Polarity select
140+
int CPHA = (phase) ? 1 : 0; // CPHA - Clock Phase select
141+
142+
uint32_t tmp = obj->spi->CFG;
143+
tmp &= ~((1 << 5) | (1 << 4) | (1 << 2));
144+
tmp |= (CPOL << 5) | (CPHA << 4) | ((slave ? 0 : 1) << 2);
145+
obj->spi->CFG = tmp;
146+
147+
// select frame length
148+
tmp = obj->spi->TXDATCTL;
149+
tmp &= ~(0xf << 24);
150+
tmp |= (LEN << 24);
151+
obj->spi->TXDATCTL = tmp;
152+
153+
spi_enable(obj);
154+
}
155+
156+
void spi_frequency(spi_t *obj, int hz) {
157+
spi_disable(obj);
158+
159+
uint32_t PCLK = SystemCoreClock;
160+
161+
obj->spi->DIV = PCLK/hz - 1;
162+
obj->spi->DLY = 0;
163+
spi_enable(obj);
164+
}
165+
166+
static inline void spi_disable(spi_t *obj) {
167+
obj->spi->CFG &= ~(1 << 0);
168+
}
169+
170+
static inline void spi_enable(spi_t *obj) {
171+
obj->spi->CFG |= (1 << 0);
172+
}
173+
174+
static inline int spi_readable(spi_t *obj) {
175+
return obj->spi->STAT & (1 << 0);
176+
}
177+
178+
static inline int spi_writeable(spi_t *obj) {
179+
return obj->spi->STAT & (1 << 1);
180+
}
181+
182+
static inline void spi_write(spi_t *obj, int value) {
183+
while (!spi_writeable(obj));
184+
// end of transfer
185+
obj->spi->TXDATCTL |= (1 << 20);
186+
obj->spi->TXDAT = value;
187+
}
188+
189+
static inline int spi_read(spi_t *obj) {
190+
while (!spi_readable(obj));
191+
return obj->spi->RXDAT;
192+
}
193+
194+
static inline int spi_busy(spi_t *obj) {
195+
// checking RXOV(Receiver Overrun interrupt flag)
196+
return obj->spi->STAT & (1 << 2);
197+
}
198+
199+
int spi_master_write(spi_t *obj, int value) {
200+
spi_write(obj, value);
201+
return spi_read(obj);
202+
}
203+
204+
int spi_slave_receive(spi_t *obj) {
205+
return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0);
206+
}
207+
208+
int spi_slave_read(spi_t *obj) {
209+
return obj->spi->RXDAT;
210+
}
211+
212+
void spi_slave_write(spi_t *obj, int value) {
213+
while (spi_writeable(obj) == 0) ;
214+
obj->spi->TXDAT = value;
215+
}

0 commit comments

Comments
 (0)