ESOS32
ESOSOn32-bitProcessors
esos_stm32l4_spi.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2020 J. W. Bruce ("AUTHOR(S)")"
3  * All rights reserved.
4  * (J. W. Bruce, jwbruce_AT_tntech.edu, Tennessee Tech University)
5  *
6  * Permission to use, copy, modify, and distribute this software and its
7  * documentation for any purpose, without fee, and without written agreement is
8  * hereby granted, provided that the above copyright notice, the following
9  * two paragraphs and the authors appear in all copies of this software.
10  *
11  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
12  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
13  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
14  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15  *
16  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
19  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
20  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
21  *
22  * Please maintain this header in its entirety when copying/modifying
23  * these files.
24  *
25  *
26  */
27 
28 
36 // Documentation for this file. If the \file tag isn't present,
37 // this file won't be documented.
44 /*** I N C L U D E S *************************************************/
45 #include "esos_spi.h"
46 #include "esos_stm32l4_edub.h"
47 #include "esos_stm32l4_spi.h"
48 
49 /*** G L O B A L S *************************************************/
50 // NOTE THAT __stChildTaskSPI and __esos_spi_u16s[2] are defined
51 // in esos_spi.c and extern-ed in esos_spi.h
52 
53 
54 /*** T H E C O D E *************************************************/
55 
56 /*********************************************************
57  * Public functions intended to be called by other files *
58  *********************************************************/
59 
60 // Documentation for this file. If the \file tag is not present,
61 // this file will not be documented.
62 // Note: place this comment below the #if NUM_I2C_MODS so Doxygen
63 // will only see it once.
69 /*
70 Configure and enable the SPI module for operation at \em u32_spibps
71 bits/sec clock speed.
72  param u32_spibps specifies clock speed in bps
73  \sa ESOS_TASK_WAIT_ON_WRITE1SPI1
74  \sa ESOS_TASK_WAIT_ON_WRITE2SPI1
75  \sa ESOS_TASK_WAIT_ON_WRITENSPI1
76  \sa ESOS_TASK_WAIT_ON_XFERNSPI1
77  \sa ESOS_TASK_WAIT_ON_READ1SPI1
78  \sa ESOS_TASK_WAIT_ON_READ2SPI1
79  \sa ESOS_TASK_WAIT_ON_READNSPI1
80  \hideinitializer
81 */
82 void __esos_spi_hw_config( uint32_t u32_spibps ) {
83 
84  // enable the clocking for the SPI1 peripheral
85  rcc_periph_clock_enable(RCC_SPI1);
86  spi_reset(SPI1);
87 
88  // configure the SPI (output) pins: SPI CLK and SPI MOSI
89  gpio_mode_setup(EDUB_SPICLK_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, EDUB_SPICLK_PIN);
90 
91  gpio_mode_setup(EDUB_SPIMOSI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, EDUB_SPIMOSI_PIN);
92 
93  // configure the SPI (input) pins: SPI MISO
94  gpio_mode_setup(EDUB_SPIMISO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, EDUB_SPIMISO_PIN);
95 
96  // configure the SPI pins to alternate function (AF)
97  // set Table 17 in the STM32L453RE datasheet
98  gpio_set_af(EDUB_SPICLK_PORT, GPIO_AF5, EDUB_SPICLK_PIN);
99  gpio_set_af(EDUB_SPIMOSI_PORT, GPIO_AF5, EDUB_SPIMOSI_PIN);
100  gpio_set_af(EDUB_SPIMISO_PORT, GPIO_AF5, EDUB_SPIMISO_PIN);
101 
102  //spi_reset(SPI1);
103  // have libOpenCM3 initialize the SPI1 peripheral to
104  // the requested bitrate, (NEED TO FIX THIS!)
105  // with 0 PHASE and 0 POLARITY (aka SPI mode 0)
106  // 8bit transfers shifting MSb out first
107  // There is a single API call: spi_init_master() but we
108  // will initialize via separate calls to make it more
109  // readable.
110 
111  spi_set_master_mode( SPI1 ); // we are the SPI MASTER
112 
113  // in the libOpenCM3 call spi_set_baudrate_prescaler, the prescaler is
114  // calculated by 2^(x+1)
115  spi_set_baudrate_prescaler( SPI1, SPI_CR1_BR_FPCLK_DIV_8); // Baud prescaler DIV_BY_8
116  spi_set_standard_mode( SPI1, 0 ); // MODE 0: CPOL=0 CPHA=0
117  spi_set_full_duplex_mode( SPI1 ); // use 3-wire (SCL, MOSI, MISO) SPI
118  spi_disable_crc( SPI1 ); // not using CRC
119  spi_set_data_size ( SPI1, SPI_CR2_DS_8BIT); // byte transfers
120  spi_send_msb_first( SPI1 ); // see EduBase schematic
121 
122  /*
123  * Set NSS management to software.
124  *
125  * Note:
126  * Setting nss high is very important, even if we are controlling the GPIO
127  * ourselves this bit needs to be at least set to 1, otherwise the spi
128  * peripheral will not send any data out.
129  */
130  spi_enable_software_slave_management(SPI1);
131  spi_set_nss_high(SPI1);
132 
133  /* Enable SPI1 periph. */
134  spi_enable(SPI1);
135 
136 } // end __esos_spi_hw_config() function
137 
138 
139 /*
140 Transaction: Writes \em u16_cnt words stored in
141 buffer \em *pu16_out to SPI device, while reading \em u16_cnt words from
142 SPI device placing results into buffer \em *pu16_in
143 \note Assumes that SPI peripheral has been properly configured.
144 \note The SPI peripheral setup determines whether 8-bit or 16-bit data
145 is written.
146 \param pu16_out Pointer to buffer containing data to send. If \em pu16_out is \em NULLPTR this function will send zeroes to the SPI device and only "read"
147 \param pu16_in Pointer to buffer to catch incoming data. If \em pu16_in is \em NULLPTR this function will only "write" the SPI device
148 \param u16_cnt Number of words to send
149  */
150 ESOS_CHILD_TASK( __esos_spi_hw_xferNSPI1, uint16_t* pu16_out, uint16_t* pu16_in, uint16_t u16_cnt) {
151  static uint16_t* pu16_tempPtrIn;
152  static uint16_t* pu16_tempPtrOut;
153  static uint16_t u16_tempCnt, u16_i;
154  static uint8_t u8_isReading, u8_isWriting;
155  uint16_t u16_scratch;
156 
157  ESOS_TASK_BEGIN();
158 
159  pu16_tempPtrOut=pu16_out;
160  pu16_tempPtrIn=pu16_in;
161  u16_tempCnt=u16_cnt;
162  if (pu16_tempPtrOut == NULLPTR)
163  u8_isWriting = FALSE;
164  else
165  u8_isWriting = TRUE;
166 
167  if (pu16_tempPtrIn == NULLPTR)
168  u8_isReading = FALSE;
169  else
170  u8_isReading = TRUE;
171 
172  // wait for any previous SPI transactions to finish
173  ESOS_TASK_WAIT_WHILE( __ESOS_SPI_STM32L4_IS_BUSY() );
174 
175  // clear the overflow flag, just in case it is set
176  // the OVR flag is cleared by reading SPI_SR then reading SPI_DR
177  // see section 40.4.11 in the STM32L4xx reference manual
178  if ( __ESOS_SPI_STM32L4_IS_OVR() ) {
179  u16_scratch = SPI_SR(SPI1);
180  u16_scratch = SPI_DR(SPI1);
181  }
182 
183  for (u16_i=0; u16_i < u16_tempCnt; u16_i++) {
184  if (u8_isWriting) {
185  SPI_DR8(SPI1) = (uint8_t) (*pu16_tempPtrOut & 0x0FF);
186  pu16_tempPtrOut++;
187  } else {
188  SPI_DR(SPI1) = 0;
189  } // end isWriting
190 
191  // wait for TX word to be transfered
192  // the libOpenCM3 example omits this step.....
193  ESOS_TASK_WAIT_UNTIL( __ESOS_SPI_STM32L4_IS_TXE() );
194 
195  // wait for complete RX word to come in...
196  //ESOS_TASK_WAIT_UNTIL( __ESOS_SPI_STM32L4_IS_RXNE() );
197 
198  // read the incoming word from SPI
199  u16_scratch = SPI_DR(SPI1);
200  if (u8_isReading) {
201  *pu16_tempPtrIn = u16_scratch;
202  pu16_tempPtrIn++;
203  } // end isReading
204  } // end for()
205 
206  ESOS_TASK_END();
207 } // end __esos_spi_hw_xferNSPI1
208 
NULLPTR
#define NULLPTR
Definition: all_generic.h:435
esos_spi.h
ESOS_TASK_WAIT_UNTIL
#define ESOS_TASK_WAIT_UNTIL(condition)
Definition: esos_task.h:335
esos_stm32l4_spi.h
This file contains routines which define, configure and allow use of the SPI service on the ST Microe...
ESOS_TASK_END
#define ESOS_TASK_END()
Definition: esos_task.h:271
ESOS_CHILD_TASK
#define ESOS_CHILD_TASK(taskname,...)
Definition: esos_task.h:246
TRUE
@ TRUE
Definition: all_generic.h:410
ESOS_TASK_WAIT_WHILE
#define ESOS_TASK_WAIT_WHILE(cond)
Definition: esos_task.h:363
FALSE
@ FALSE
Definition: all_generic.h:408
ESOS_TASK_BEGIN
#define ESOS_TASK_BEGIN()
Definition: esos_task.h:259