blob: 436fb4f6f4295f00d579341a10f6debc0c216669 [file] [log] [blame]
Radomir Dopieralski8e7dfea2016-06-07 21:40:56 +02001/*
2* The MIT License (MIT)
3*
4* Copyright (c) 2015 David Ogilvy (MetalPhreak)
5* Modified 2016 by Radomir Dopieralski
6*
7* Permission is hereby granted, free of charge, to any person obtaining a copy
8* of this software and associated documentation files (the "Software"), to deal
9* in the Software without restriction, including without limitation the rights
10* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11* copies of the Software, and to permit persons to whom the Software is
12* furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in all
15* copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23* SOFTWARE.
24*/
25
26#include "hspi.h"
27
28/*
29Wrapper to setup HSPI/SPI GPIO pins and default SPI clock
30 spi_no - SPI (0) or HSPI (1)
31Not used in Micropython.
32*/
33void spi_init(uint8_t spi_no) {
34 spi_init_gpio(spi_no, SPI_CLK_USE_DIV);
35 spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
36 spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
37 spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
38
39 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD);
40 CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
41}
42
43
44/*
45Configures SPI mode parameters for clock edge and clock polarity.
46 spi_no - SPI (0) or HSPI (1)
47 spi_cpha - (0) Data is valid on clock leading edge
48 (1) Data is valid on clock trailing edge
49 spi_cpol - (0) Clock is low when inactive
50 (1) Clock is high when inactive
51For Micropython this version is different from original.
52*/
53void spi_mode(uint8_t spi_no, uint8_t spi_cpha, uint8_t spi_cpol) {
54 if (spi_cpol) {
55 SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
56 } else {
57 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
58 }
59 if (spi_cpha == spi_cpol) {
60 // Mode 3 - MOSI is set on falling edge of clock
61 // Mode 0 - MOSI is set on falling edge of clock
62 CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
63 SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
64 } else {
65 // Mode 2 - MOSI is set on rising edge of clock
66 // Mode 1 - MOSI is set on rising edge of clock
67 SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
68 CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
69 }
70}
71
72
73/*
74Initialise the GPIO pins for use as SPI pins.
75 spi_no - SPI (0) or HSPI (1)
76 sysclk_as_spiclk -
77 SPI_CLK_80MHZ_NODIV (1) if using 80MHz for SPI clock.
78 SPI_CLK_USE_DIV (0) if using divider for lower speed.
79*/
80void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) {
81 uint32_t clock_div_flag = 0;
82 if (sysclk_as_spiclk) {
83 clock_div_flag = 0x0001;
84 }
85 if (spi_no == SPI) {
86 // Set bit 8 if 80MHz sysclock required
87 WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8));
88 PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);
89 PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);
90 PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);
91 PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);
92 } else if (spi_no == HSPI) {
93 // Set bit 9 if 80MHz sysclock required
94 WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9));
95 // GPIO12 is HSPI MISO pin (Master Data In)
96 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
97 // GPIO13 is HSPI MOSI pin (Master Data Out)
98 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
99 // GPIO14 is HSPI CLK pin (Clock)
100 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
101 // GPIO15 is HSPI CS pin (Chip Select / Slave Select)
102 // In Micropython, we are handling CS ourself in drivers.
103 // PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
104 }
105}
106
107
108/*
109Set up the control registers for the SPI clock
110 spi_no - SPI (0) or HSPI (1)
111 prediv - predivider value (actual division value)
112 cntdiv - postdivider value (actual division value)
113Set either divider to 0 to disable all division (80MHz sysclock)
114*/
115void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) {
116 if (prediv == 0 || cntdiv == 0) {
117 WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK);
118 } else {
119 WRITE_PERI_REG(SPI_CLOCK(spi_no),
120 (((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
121 (((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
122 (((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
123 ((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)
124 );
125 }
126}
127
128
129/*
130Setup the byte order for shifting data out of buffer
131 spi_no - SPI (0) or HSPI (1)
132 byte_order -
133 SPI_BYTE_ORDER_HIGH_TO_LOW (1)
134 Data is sent out starting with Bit31 and down to Bit0
135 SPI_BYTE_ORDER_LOW_TO_HIGH (0)
136 Data is sent out starting with the lowest BYTE, from MSB to LSB,
137 followed by the second lowest BYTE, from MSB to LSB, followed by
138 the second highest BYTE, from MSB to LSB, followed by the highest
139 BYTE, from MSB to LSB 0xABCDEFGH would be sent as 0xGHEFCDAB.
140*/
141void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order) {
142 if (byte_order) {
143 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
144 } else {
145 CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
146 }
147}
148
149
150/*
151Setup the byte order for shifting data into buffer
152 spi_no - SPI (0) or HSPI (1)
153 byte_order -
154 SPI_BYTE_ORDER_HIGH_TO_LOW (1)
155 Data is read in starting with Bit31 and down to Bit0
156 SPI_BYTE_ORDER_LOW_TO_HIGH (0)
157 Data is read in starting with the lowest BYTE, from MSB to LSB,
158 followed by the second lowest BYTE, from MSB to LSB, followed by
159 the second highest BYTE, from MSB to LSB, followed by the highest
160 BYTE, from MSB to LSB 0xABCDEFGH would be read as 0xGHEFCDAB
161*/
162void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order) {
163 if (byte_order) {
164 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
165 } else {
166 CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
167 }
168}
169
170
171/*
172SPI transaction function
173 spi_no - SPI (0) or HSPI (1)
174 cmd_bits - actual number of bits to transmit
175 cmd_data - command data
176 addr_bits - actual number of bits to transmit
177 addr_data - address data
178 dout_bits - actual number of bits to transmit
179 dout_data - output data
180 din_bits - actual number of bits to receive
181Returns: read data - uint32_t containing read in data only if RX was set
182 0 - something went wrong (or actual read data was 0)
183 1 - data sent ok (or actual read data is 1)
184Note: all data is assumed to be stored in the lower bits of the data variables
185(for anything <32 bits).
186*/
187uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
188 uint32_t addr_bits, uint32_t addr_data,
189 uint32_t dout_bits, uint32_t dout_data,
190 uint32_t din_bits, uint32_t dummy_bits) {
191 while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
192
193// Enable SPI Functions
194 // Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
195 CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
196 SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
197
198 // Enable functions based on number of bits. 0 bits = disabled.
199 // This is rather inefficient but allows for a very generic function.
200 // CMD ADDR and MOSI are set below to save on an extra if statement.
201 if (din_bits) {
Radomir Dopieralski891479e2016-08-25 10:42:33 +0200202 if (dout_bits) {
203 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN);
204 } else {
205 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
206 }
Radomir Dopieralski8e7dfea2016-06-07 21:40:56 +0200207 }
208 if (dummy_bits) {
209 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);
210 }
211
212// Setup Bitlengths
213 WRITE_PERI_REG(SPI_USER1(spi_no),
214 // Number of bits in Address
215 ((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S |
216 // Number of bits to Send
217 ((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
218 // Number of bits to receive
219 ((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S |
220 // Number of Dummy bits to insert
221 ((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S);
222
223// Setup Command Data
224 if (cmd_bits) {
225 // Enable COMMAND function in SPI module
226 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);
227 // Align command data to high bits
228 uint16_t command = cmd_data << (16-cmd_bits);
229 // Swap byte order
230 command = ((command>>8)&0xff) | ((command<<8)&0xff00);
231 WRITE_PERI_REG(SPI_USER2(spi_no), (
232 (((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) |
233 (command & SPI_USR_COMMAND_VALUE)
234 ));
235 }
236
237// Setup Address Data
238 if (addr_bits) {
239 // Enable ADDRess function in SPI module
240 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);
241 // Align address data to high bits
242 WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data << (32 - addr_bits));
243 }
244
245// Setup DOUT data
246 if (dout_bits) {
247 // Enable MOSI function in SPI module
248 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
249 // Copy data to W0
250 if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) {
251 WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits));
252 } else {
253 uint8_t dout_extra_bits = dout_bits%8;
254
255 if (dout_extra_bits) {
256 // If your data isn't a byte multiple (8/16/24/32 bits) and you
257 // don't have SPI_WR_BYTE_ORDER set, you need this to move the
258 // non-8bit remainder to the MSBs. Not sure if there's even a use
259 // case for this, but it's here if you need it... For example,
260 // 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output
261 // as if it were 0x0DA4, of which 0xA4, and then 0x0 would be
262 // shifted out (first 8 bits of low byte, then 4 MSB bits of high
263 // byte - ie reverse byte order).
264 // The code below shifts it out as 0xA4 followed by 0xD as you
265 // might require.
266 WRITE_PERI_REG(SPI_W0(spi_no), (
267 (0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data)
268 << (8-dout_extra_bits) |
269 ((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits)))
270 & dout_data)
271 ));
272 } else {
273 WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
274 }
275 }
276}
277
278// Begin SPI Transaction
279 SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
280
281// Return DIN data
282 if (din_bits) {
283 while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete
284 if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) {
285 // Assuming data in is written to MSB. TBC
286 return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits);
287 } else {
288 // Read in the same way as DOUT is sent. Note existing contents of
289 // SPI_W0 remain unless overwritten!
290 return READ_PERI_REG(SPI_W0(spi_no));
291 }
292 return 0; // Something went wrong
293 }
294
295 // Transaction completed
296 return 1; // Success
297}
298
299
300/*
301Just do minimal work needed to send 8 bits.
302*/
303inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) {
304 while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
305
306// Enable SPI Functions
307 // Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
308 CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
309 SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
310
311// Setup Bitlengths
312 WRITE_PERI_REG(SPI_USER1(spi_no),
313 // Number of bits to Send
314 ((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
315 // Number of bits to receive
316 ((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S);
317
318
319// Setup DOUT data
320 // Enable MOSI function in SPI module
321 SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
322 // Copy data to W0
323 if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) {
324 WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - 8));
325 } else {
326 WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
327 }
328
329// Begin SPI Transaction
330 SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
331}