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 "stm32l4xx.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, 8, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 0 );
68     }
69     else
70     {
71         SpiFormat( obj, 8, 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 == 8 )
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     HAL_SPI_TransmitReceive( &SpiHandle[obj->SpiId], ( uint8_t* )&outData, &rxData, 1, HAL_MAX_DELAY );
156 
157     CRITICAL_SECTION_END( );
158 
159     return( rxData );
160 }
161 
162