1 /* mbed Microcontroller Library
2 * Copyright (c) 2013 Nordic Semiconductor
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "mbed_assert.h"
21 #include "mbed_error.h"
23 #define SPIS_MESSAGE_SIZE 1
24 volatile uint8_t m_tx_buf
[SPIS_MESSAGE_SIZE
] = {0};
25 volatile uint8_t m_rx_buf
[SPIS_MESSAGE_SIZE
] = {0};
27 // nRF51822's I2C_0 and SPI_0 (I2C_1, SPI_1 and SPIS1) share the same address.
28 // They can't be used at the same time. So we use two global variable to track the usage.
29 // See nRF51822 address information at nRF51822_PS v2.0.pdf - Table 15 Peripheral instance reference
30 extern volatile i2c_spi_peripheral_t i2c0_spi0_peripheral
; // from i2c_api.c
31 extern volatile i2c_spi_peripheral_t i2c1_spi1_peripheral
;
33 void spi_init(spi_t
*obj
, PinName mosi
, PinName miso
, PinName sclk
, PinName ssel
)
37 if (ssel
== NC
&& i2c0_spi0_peripheral
.usage
== I2C_SPI_PERIPHERAL_FOR_SPI
&&
38 i2c0_spi0_peripheral
.sda_mosi
== (uint8_t)mosi
&&
39 i2c0_spi0_peripheral
.scl_miso
== (uint8_t)miso
&&
40 i2c0_spi0_peripheral
.sclk
== (uint8_t)sclk
) {
41 // The SPI with the same pins is already initialized
43 obj
->peripheral
= 0x1;
44 } else if (ssel
== NC
&& i2c1_spi1_peripheral
.usage
== I2C_SPI_PERIPHERAL_FOR_SPI
&&
45 i2c1_spi1_peripheral
.sda_mosi
== (uint8_t)mosi
&&
46 i2c1_spi1_peripheral
.scl_miso
== (uint8_t)miso
&&
47 i2c1_spi1_peripheral
.sclk
== (uint8_t)sclk
) {
48 // The SPI with the same pins is already initialized
50 obj
->peripheral
= 0x2;
51 } else if (i2c1_spi1_peripheral
.usage
== 0) {
52 i2c1_spi1_peripheral
.usage
= I2C_SPI_PERIPHERAL_FOR_SPI
;
53 i2c1_spi1_peripheral
.sda_mosi
= (uint8_t)mosi
;
54 i2c1_spi1_peripheral
.scl_miso
= (uint8_t)miso
;
55 i2c1_spi1_peripheral
.sclk
= (uint8_t)sclk
;
58 obj
->peripheral
= 0x2;
59 } else if (i2c0_spi0_peripheral
.usage
== 0) {
60 i2c0_spi0_peripheral
.usage
= I2C_SPI_PERIPHERAL_FOR_SPI
;
61 i2c0_spi0_peripheral
.sda_mosi
= (uint8_t)mosi
;
62 i2c0_spi0_peripheral
.scl_miso
= (uint8_t)miso
;
63 i2c0_spi0_peripheral
.sclk
= (uint8_t)sclk
;
66 obj
->peripheral
= 0x1;
68 // No available peripheral
69 error("No available SPI");
73 obj
->spi
= (NRF_SPI_Type
*)spi
;
74 obj
->spis
= (NRF_SPIS_Type
*)NC
;
76 obj
->spi
= (NRF_SPI_Type
*)NC
;
77 obj
->spis
= (NRF_SPIS_Type
*)spi
;
80 // pin out the spi pins
81 if (ssel
!= NC
) { //slave
85 NRF_GPIO
->PIN_CNF
[mosi
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
86 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
87 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
88 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
89 | (GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
);
90 NRF_GPIO
->PIN_CNF
[miso
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
91 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
92 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
93 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
94 | (GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
);
95 NRF_GPIO
->PIN_CNF
[sclk
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
96 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
97 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
98 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
99 | (GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
);
100 NRF_GPIO
->PIN_CNF
[ssel
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
101 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
102 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
103 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
104 | (GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
);
106 obj
->spis
->PSELMOSI
= mosi
;
107 obj
->spis
->PSELMISO
= miso
;
108 obj
->spis
->PSELSCK
= sclk
;
109 obj
->spis
->PSELCSN
= ssel
;
111 obj
->spis
->EVENTS_END
= 0;
112 obj
->spis
->EVENTS_ACQUIRED
= 0;
113 obj
->spis
->MAXRX
= SPIS_MESSAGE_SIZE
;
114 obj
->spis
->MAXTX
= SPIS_MESSAGE_SIZE
;
115 obj
->spis
->TXDPTR
= (uint32_t)&m_tx_buf
[0];
116 obj
->spis
->RXDPTR
= (uint32_t)&m_rx_buf
[0];
117 obj
->spis
->SHORTS
= (SPIS_SHORTS_END_ACQUIRE_Enabled
<< SPIS_SHORTS_END_ACQUIRE_Pos
);
119 spi_format(obj
, 8, 0, 1); // 8 bits, mode 0, slave
124 //NRF_GPIO->DIR |= (1<<mosi);
125 NRF_GPIO
->PIN_CNF
[mosi
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
126 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
127 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
128 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
129 | (GPIO_PIN_CNF_DIR_Output
<< GPIO_PIN_CNF_DIR_Pos
);
130 obj
->spi
->PSELMOSI
= mosi
;
132 NRF_GPIO
->PIN_CNF
[sclk
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
133 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
134 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
135 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
136 | (GPIO_PIN_CNF_DIR_Output
<< GPIO_PIN_CNF_DIR_Pos
);
137 obj
->spi
->PSELSCK
= sclk
;
139 //NRF_GPIO->DIR &= ~(1<<miso);
140 NRF_GPIO
->PIN_CNF
[miso
] = (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
)
141 | (GPIO_PIN_CNF_DRIVE_S0S1
<< GPIO_PIN_CNF_DRIVE_Pos
)
142 | (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
)
143 | (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
)
144 | (GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
);
146 obj
->spi
->PSELMISO
= miso
;
148 obj
->spi
->EVENTS_READY
= 0U;
150 spi_format(obj
, 8, 0, 0); // 8 bits, mode 0, master
151 spi_frequency(obj
, 1000000);
155 void spi_free(spi_t
*obj
)
159 static inline void spi_disable(spi_t
*obj
, int slave
)
162 obj
->spis
->ENABLE
= (SPIS_ENABLE_ENABLE_Disabled
<< SPIS_ENABLE_ENABLE_Pos
);
164 obj
->spi
->ENABLE
= (SPI_ENABLE_ENABLE_Disabled
<< SPI_ENABLE_ENABLE_Pos
);
168 static inline void spi_enable(spi_t
*obj
, int slave
)
171 obj
->spis
->ENABLE
= (SPIS_ENABLE_ENABLE_Enabled
<< SPIS_ENABLE_ENABLE_Pos
);
173 obj
->spi
->ENABLE
= (SPI_ENABLE_ENABLE_Enabled
<< SPI_ENABLE_ENABLE_Pos
);
177 void spi_format(spi_t
*obj
, int bits
, int mode
, int slave
)
179 uint32_t config_mode
= 0;
180 spi_disable(obj
, slave
);
183 error("Only 8bits SPI supported");
188 config_mode
= (SPI_CONFIG_CPHA_Leading
<< SPI_CONFIG_CPHA_Pos
) | (SPI_CONFIG_CPOL_ActiveHigh
<< SPI_CONFIG_CPOL_Pos
);
191 config_mode
= (SPI_CONFIG_CPHA_Trailing
<< SPI_CONFIG_CPHA_Pos
) | (SPI_CONFIG_CPOL_ActiveHigh
<< SPI_CONFIG_CPOL_Pos
);
194 config_mode
= (SPI_CONFIG_CPHA_Leading
<< SPI_CONFIG_CPHA_Pos
) | (SPI_CONFIG_CPOL_ActiveLow
<< SPI_CONFIG_CPOL_Pos
);
197 config_mode
= (SPI_CONFIG_CPHA_Trailing
<< SPI_CONFIG_CPHA_Pos
) | (SPI_CONFIG_CPOL_ActiveLow
<< SPI_CONFIG_CPOL_Pos
);
200 error("SPI format error");
203 //default to msb first
205 obj
->spis
->CONFIG
= (config_mode
| (SPI_CONFIG_ORDER_MsbFirst
<< SPI_CONFIG_ORDER_Pos
));
207 obj
->spi
->CONFIG
= (config_mode
| (SPI_CONFIG_ORDER_MsbFirst
<< SPI_CONFIG_ORDER_Pos
));
210 spi_enable(obj
, slave
);
213 void spi_frequency(spi_t
*obj
, int hz
)
215 if ((int)obj
->spi
==NC
) {
220 if (hz
<250000) { //125Kbps
221 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_K125
;
222 } else if (hz
<500000) { //250Kbps
223 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_K250
;
224 } else if (hz
<1000000) { //500Kbps
225 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_K500
;
226 } else if (hz
<2000000) { //1Mbps
227 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_M1
;
228 } else if (hz
<4000000) { //2Mbps
229 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_M2
;
230 } else if (hz
<8000000) { //4Mbps
231 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_M4
;
233 obj
->spi
->FREQUENCY
= (uint32_t) SPI_FREQUENCY_FREQUENCY_M8
;
239 static inline int spi_readable(spi_t
*obj
)
241 return (obj
->spi
->EVENTS_READY
== 1);
244 static inline int spi_writeable(spi_t
*obj
)
246 return (obj
->spi
->EVENTS_READY
== 0);
249 static inline int spi_read(spi_t
*obj
)
251 while (!spi_readable(obj
)) {
254 obj
->spi
->EVENTS_READY
= 0;
255 return (int)obj
->spi
->RXD
;
258 int spi_master_write(spi_t
*obj
, int value
)
260 while (!spi_writeable(obj
)) {
262 obj
->spi
->TXD
= (uint32_t)value
;
263 return spi_read(obj
);
266 //static inline int spis_writeable(spi_t *obj) {
267 // return (obj->spis->EVENTS_ACQUIRED==1);
270 int spi_slave_receive(spi_t
*obj
)
272 return obj
->spis
->EVENTS_END
;
275 int spi_slave_read(spi_t
*obj
)
280 void spi_slave_write(spi_t
*obj
, int value
)
282 m_tx_buf
[0] = value
& 0xFF;
283 obj
->spis
->TASKS_RELEASE
= 1;
284 obj
->spis
->EVENTS_ACQUIRED
= 0;
285 obj
->spis
->EVENTS_END
= 0;