spiSTM32F0hard.fth (6208B)
1 \ spiSTM32hard.fth - SPI for STM32F072B Discovery board 2 3 (( 4 Copyright (c) 2012, 2014 5 MicroProcessor Engineering 6 133 Hill Lane 7 Southampton SO15 5AF 8 England 9 10 tel: +44 (0)23 8063 1441 11 fax: +44 (0)23 8033 9691 12 email: mpe@mpeforth.com 13 tech-support@mpeforth.com 14 web: http://www.mpeforth.com 15 Skype: mpe_sfp 16 17 From North America, our telephone and fax numbers are: 18 011 44 23 8063 1441 19 011 44 23 8033 9691 20 901 313 4312 (North American access number to UK office) 21 22 23 To do 24 ===== 25 26 Change history 27 ============== 28 20140225 SFP002 Conversion to F072 Discovery board. 29 20121016 MPE001 Initial release. 30 )) 31 32 only forth definitions 33 decimal 34 35 \ ================= 36 \ *! drivers 37 \ *S STM32 SPI driver 38 \ ================= 39 \ *P STM32 devices and boards vary in their use of various pins. 40 \ ** Consequently the file *\i{Drivers/spiSTM32hard} is not 41 \ ** generic. The default configuration is for the STM32F072B-Disco 42 \ ** board to drive the L3GD20 MEMS Gyro as an SPI master with 43 \ ** CPOL=1 and CPHA=1. 44 45 \ *P The SPI peripheral for STM32F0 devices is not entirely 46 \ ** compatible with the SPI of other STM32 families. 47 48 49 \ *************************** 50 \ *N Setup and initialisation 51 \ *************************** 52 \ *P The board uses I/O for SPI as follows. 53 \ *E PI.0 AF5 SSEL1 pin 131 SPI2_NSS 54 \ ** PI.1 AF5 SCK1 pin 132 SPI2_SCK 55 \ ** PI.2 AF5 MISO1 pin 133 SPI2_MISO 56 \ ** PI.3 AF5 MOS11 pin 134 SPI2_MOSI 57 58 \ SPI1 - APB2 59 \ SPI2 - APB1 60 \ SPI3 - APB1 61 62 : genSPIbr \ spi-speed bus-speed -- brx 63 swap / 0 7 do \ -- divisor 64 dup 1 i lshift > 65 if drop i unloop exit endif 66 -1 +loop 67 drop 0 68 ; 69 70 interpreter 71 : genSPIbr \ spi-speed bus-speed -- brx 72 swap / 0 7 do \ -- divisor 73 dup 1 i lshift > 74 if drop i unloop exit endif 75 -1 +loop 76 drop 0 77 ; 78 target 79 80 : (initSPI) \ freq busfreq *spi -- 81 \ *G Set up the given SPI device, where *\i{freq} is the desired 82 \ ** SPI speed, *\i{busfreq} is the peripheral clock speed, and 83 \ ** *\i{*spi} is the SPI peripheral base address. The SPI bus is 84 \ ** set up in master mode, MSB first. 85 >r 86 bit6 r@ spiCR1 + bic! \ clear SPE bit 87 genSPIbr 3 lshift $0307 or \ SSM=1, SSI=1, SPE=0, MSTR=1, CPOL=1, CPHA=1 88 \ cr ." initCR1 = " dup .dword 89 r@ spiCR1 + ! \ main mode control, CPOL=0, CPHA=0 90 $1700 r@ spiCR2 + ! \ F1FO threshold 1 byte, 8 data bits 91 bit6 r> spiCR1 + or! \ set SPE bit 92 ; 93 94 95 \ ******* 96 \ *N SPI2 97 \ ******* 98 99 1 MHz equ spi2-speed \ -- hz 100 \ *G Define the SPI2 clock in Herz. 101 102 [undefined] selio-spi2 [if] 103 PC 0 pio: SPI2_NCS_MEMS \ software driven 104 PB 13 pio: SPI2_SCK 105 PB 14 pio: SPI2_MISO 106 PB 15 pio: SPI2_MOSI 107 108 : isSPIpin \ pin -- 109 \ *G Set up the pin as an SPI pin. 110 0 over isFunction HighSpeed swap isPinSpeed 111 ; 112 113 : selio-spi2 \ -- 114 \ *G Example to perform clock and pin selection for SPI2 on PC0, 115 \ ** PB13, PB14, and PB15. 116 \ Clocks and reset 117 $00C0:0000 _RCC 118 2dup rccAHBen + or! \ enable clock to GPIOB/C 119 rccAHBrst + bic! \ take it out of reset 120 bit14 _RCC 121 2dup rccAPB1en + or! \ enable clock to SPI2 122 rccAPB1rst + bic! \ take it out of reset 123 \ Default on PC0, PB13, PB14, PB15 124 SPI2_NCS_MEMS dup isOutput MediumSpeed over isPinSpeed setPin 125 SPI2_SCK isSPIpin SPI2_MISO isSPIpin SPI2_MOSI isSPIpin 126 ; 127 [then] 128 129 \ **************** 130 \ *N SPI transfers 131 \ **************** 132 \ *P These routines have been optimised for speed over space 133 \ ** considerations. For high speed use with SD cards, you will 134 \ ** get best performance using interrupt driven or DMA driven 135 \ ** operation. 136 137 (( SPI status register 138 Bit Symbol Description 139 0 RXNE Receive FIFO Not Empty. This bit is 0 if the Receive 140 FIFO is empty, 1 if not. 141 1 TXE Transmit FIFO Empty. This bit is 1 is the Transmit FIFO is 142 empty. 143 7 BSY Busy. This bit is 0 if the SSP controller is idle, 144 or 1 if it is currently sending/receiving a frame 145 and/or the Tx FIFO is not empty. 146 )) 147 148 : SPIXchg \ bout *spi -- bin 149 \ *G Write data to SPIx and return the received byte. 150 tuck spiDR + c! \ -- *spi ; starts TX/RX, must be byte 151 noop noop noop noop \ time for flags to react 152 begin \ Wait for BSY=0, TXE=1, RXNE=1 153 dup spiSR + @ $0083 and $0003 = 154 until 155 spiDR + c@ $FF and \ return received byte 156 ; 157 158 IsLeaf : spiFlush \ -- 159 \ *G Flush the SPI2 input queue. 160 _SPI2 begin 161 dup spiSR + @ bit0 and 162 while 163 dup spiDR + @ drop 164 repeat 165 drop 166 ; 167 168 : spi! \ b -- 169 \ *G Write data to SPI2 and discard the received byte. 170 _SPI2 SPIXchg drop 171 ; 172 173 : spi@ \ -- b 174 \ *G Write an idle byte to SPI2 and return the received byte. 175 $FF _SPI2 SPIXchg 176 ; 177 178 : InitSPI2 \ -- 179 \ *G Initialise SPI2. 180 selio-SPI2 181 #1000000 APB-speed _SPI2 (initSPI) 182 spiFlush 183 ; 184 185 : .spi2 \ -- 186 \ *G Display SPI2 peripheral registers. 187 _SPI2 $40 pdump 188 ; 189 190 system-speed spi2-speed / equ SPIclocks \ -- n 191 \ *G The number of CPU clocks in a bit time. 192 193 #10 equ clocksOver 194 \ *G the number of clocks needed over and above the loop itself. 195 \ ** This number may be sensitive to the compiler version and 196 \ ** switch settings. 197 198 4 equ clocksPer 199 \ *G the number of clocks needed for each iteration of the loop 200 \ ** in *\fo{spiDelay} below. This number may be sensitive to the 201 \ ** compiler version and switch settings. On most Cortex CPUs, 202 \ ** a store takes 2 cycles, a load takes 3, a branch takes 3 203 \ ** and all others take 1. Look at the core documentation from 204 \ ** ARM for clock/instruction details. 205 \ ** Look at your board schematics and setup code for details of the 206 \ ** memory bandwidth. For example, running code from a 16 bit bus 207 \ ** with two wait states and no cache may lead to six or more 208 \ ** clocks per instruction. Running code from internal buffered 209 \ ** Flash may result in no extra clocks in practice. 210 211 SPIclocks clocksOver - clocksPer / equ /SPIbit \ -- n 212 \ *G The number n for "begin 1- dup 0= until" to generate an 213 \ ** SPI bit time. 214 215 /SPIbit 1 < [if] 216 cr ." *** SPI requested rate too fast for CPU ***" abort 217 [then] 218 219 IsLeaf : SPIdelay \ -- 220 \ *G Wait one SPI bit time. 221 /SPIbit begin 1- dup 0= until drop 222 ; 223 224 : CSlo_MEMS \ -- 225 \ *G Set CS line low. 226 spidelay SPI2_NCS_MEMS clrPin spidelay 227 ; 228 229 : CShi_MEMS \ -- 230 \ *G Set CS line hi. 231 spidelay SPI2_NCS_MEMS setPin spidelay ; 232 233 234 \ ====== 235 \ *> ### 236 \ ====== 237 238 decimal