umouse

umouse.git
git clone git://git.lenczewski.org/umouse.git
Log | Files | Refs | Submodules | README

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