1 /*!
2 * \file spi-board.c
3 *
4 * \brief Target board SPI driver implementation
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2017 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 *
21 * \author Gregory Cristian ( Semtech )
22 */
23 #include "stm32l1xx.h"
24 #include "utilities.h"
25 #include "board.h"
26 #include "gpio.h"
27 #include "spi-board.h"
28
29 static SPI_HandleTypeDef SpiHandle[2];
30
SpiInit(Spi_t * obj,SpiId_t spiId,PinNames mosi,PinNames miso,PinNames sclk,PinNames nss)31 void SpiInit( Spi_t *obj, SpiId_t spiId, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss )
32 {
33 CRITICAL_SECTION_BEGIN( );
34
35 obj->SpiId = spiId;
36
37 if( spiId == SPI_1 )
38 {
39 __HAL_RCC_SPI1_FORCE_RESET( );
40 __HAL_RCC_SPI1_RELEASE_RESET( );
41 __HAL_RCC_SPI1_CLK_ENABLE( );
42
43 SpiHandle[spiId].Instance = ( SPI_TypeDef* )SPI1_BASE;
44
45 GpioInit( &obj->Mosi, mosi, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF5_SPI1 );
46 GpioInit( &obj->Miso, miso, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF5_SPI1 );
47 GpioInit( &obj->Sclk, sclk, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF5_SPI1 );
48 GpioInit( &obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF5_SPI1 );
49 }
50 else
51 {
52 __HAL_RCC_SPI2_FORCE_RESET( );
53 __HAL_RCC_SPI2_RELEASE_RESET( );
54 __HAL_RCC_SPI2_CLK_ENABLE( );
55
56 SpiHandle[spiId].Instance = ( SPI_TypeDef* )SPI2_BASE;
57
58 GpioInit( &obj->Mosi, mosi, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF5_SPI2 );
59 GpioInit( &obj->Miso, miso, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF5_SPI2 );
60 GpioInit( &obj->Sclk, sclk, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF5_SPI2 );
61 GpioInit( &obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF5_SPI2 );
62 }
63
64 if( nss == NC )
65 {
66 SpiHandle[spiId].Init.NSS = SPI_NSS_SOFT;
67 SpiFormat( obj, SPI_DATASIZE_8BIT, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 0 );
68 }
69 else
70 {
71 SpiFormat( obj, SPI_DATASIZE_8BIT, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 1 );
72 }
73 SpiFrequency( obj, 10000000 );
74
75 HAL_SPI_Init( &SpiHandle[spiId] );
76
77 CRITICAL_SECTION_END( );
78 }
79
SpiDeInit(Spi_t * obj)80 void SpiDeInit( Spi_t *obj )
81 {
82 HAL_SPI_DeInit( &SpiHandle[obj->SpiId] );
83
84 GpioInit( &obj->Mosi, obj->Mosi.pin, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
85 GpioInit( &obj->Miso, obj->Miso.pin, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 0 );
86 GpioInit( &obj->Sclk, obj->Sclk.pin, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
87 GpioInit( &obj->Nss, obj->Nss.pin, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
88 }
89
SpiFormat(Spi_t * obj,int8_t bits,int8_t cpol,int8_t cpha,int8_t slave)90 void SpiFormat( Spi_t *obj, int8_t bits, int8_t cpol, int8_t cpha, int8_t slave )
91 {
92 SpiHandle[obj->SpiId].Init.Direction = SPI_DIRECTION_2LINES;
93 if( bits == SPI_DATASIZE_8BIT )
94 {
95 SpiHandle[obj->SpiId].Init.DataSize = SPI_DATASIZE_8BIT;
96 }
97 else
98 {
99 SpiHandle[obj->SpiId].Init.DataSize = SPI_DATASIZE_16BIT;
100 }
101 SpiHandle[obj->SpiId].Init.CLKPolarity = cpol;
102 SpiHandle[obj->SpiId].Init.CLKPhase = cpha;
103 SpiHandle[obj->SpiId].Init.FirstBit = SPI_FIRSTBIT_MSB;
104 SpiHandle[obj->SpiId].Init.TIMode = SPI_TIMODE_DISABLE;
105 SpiHandle[obj->SpiId].Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
106 SpiHandle[obj->SpiId].Init.CRCPolynomial = 7;
107
108 if( slave == 0 )
109 {
110 SpiHandle[obj->SpiId].Init.Mode = SPI_MODE_MASTER;
111 }
112 else
113 {
114 SpiHandle[obj->SpiId].Init.Mode = SPI_MODE_SLAVE;
115 }
116 }
117
SpiFrequency(Spi_t * obj,uint32_t hz)118 void SpiFrequency( Spi_t *obj, uint32_t hz )
119 {
120 uint32_t divisor = 0;
121 uint32_t sysClkTmp = SystemCoreClock;
122 uint32_t baudRate;
123
124 while( sysClkTmp > hz )
125 {
126 divisor++;
127 sysClkTmp = ( sysClkTmp >> 1 );
128
129 if( divisor >= 7 )
130 {
131 break;
132 }
133 }
134
135 baudRate =( ( ( divisor & 0x4 ) == 0 ) ? 0x0 : SPI_CR1_BR_2 ) |
136 ( ( ( divisor & 0x2 ) == 0 ) ? 0x0 : SPI_CR1_BR_1 ) |
137 ( ( ( divisor & 0x1 ) == 0 ) ? 0x0 : SPI_CR1_BR_0 );
138
139 SpiHandle[obj->SpiId].Init.BaudRatePrescaler = baudRate;
140 }
141
SpiInOut(Spi_t * obj,uint16_t outData)142 uint16_t SpiInOut( Spi_t *obj, uint16_t outData )
143 {
144 uint8_t rxData = 0;
145
146 if( ( obj == NULL ) || ( SpiHandle[obj->SpiId].Instance ) == NULL )
147 {
148 assert_param( LMN_STATUS_ERROR );
149 }
150
151 __HAL_SPI_ENABLE( &SpiHandle[obj->SpiId] );
152
153 CRITICAL_SECTION_BEGIN( );
154
155 while( __HAL_SPI_GET_FLAG( &SpiHandle[obj->SpiId], SPI_FLAG_TXE ) == RESET );
156 SpiHandle[obj->SpiId].Instance->DR = ( uint16_t ) ( outData & 0xFF );
157
158 while( __HAL_SPI_GET_FLAG( &SpiHandle[obj->SpiId], SPI_FLAG_RXNE ) == RESET );
159 rxData = ( uint16_t ) SpiHandle[obj->SpiId].Instance->DR;
160
161 CRITICAL_SECTION_END( );
162
163 return( rxData );
164 }
165
166