foxBMS  1.6.0
The foxBMS Battery Management System API Documentation
spi.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file spi.c
44  * @author foxBMS Team
45  * @date 2019-12-12 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup DRIVERS
49  * @prefix SPI
50  *
51  * @brief Driver for the SPI module.
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "spi.h"
57 
58 #include "HL_reg_spi.h"
59 #include "HL_spi.h"
60 #include "HL_sys_common.h"
61 
62 #include "dma.h"
63 #include "fstd_types.h"
64 #include "fsystem.h"
65 #include "io.h"
66 #include "mcu.h"
67 #include "os.h"
68 #include "spi_cfg-helper.h"
69 
70 #include <stdint.h>
71 
72 /*========== Macros and Definitions =========================================*/
73 /** Bitfield to check for transmission errors in SPI FLAG register */
74 #define SPI_FLAG_REGISTER_TRANSMISSION_ERRORS (0x5Fu)
75 
76 /*========== Static Constant and Variable Definitions =======================*/
78 
79 /** Defines for hardware chip select pins @{ */
80 #define SPI_HARDWARE_CHIP_SELECT_PIN_0 (0u)
81 #define SPI_HARDWARE_CHIP_SELECT_PIN_1 (1u)
82 #define SPI_HARDWARE_CHIP_SELECT_PIN_2 (2u)
83 #define SPI_HARDWARE_CHIP_SELECT_PIN_3 (3u)
84 #define SPI_HARDWARE_CHIP_SELECT_PIN_4 (4u)
85 #define SPI_HARDWARE_CHIP_SELECT_PIN_5 (5u)
86 /**@}*/
87 
88 /*========== Extern Constant and Variable Definitions =======================*/
89 
90 /*========== Static Function Prototypes =====================================*/
91 static void SPI_InitializeChipSelects(void);
92 static uint8_t SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e chipSelectType, uint32_t chipSelectPin);
93 static uint8_t SPI_GetHardwareChipSelectPin(uint8_t chipSelectPin);
94 
95 /*========== Static Function Implementations ================================*/
96 static uint8_t SPI_GetHardwareChipSelectPin(uint8_t chipSelectPin) {
97  FAS_ASSERT(chipSelectPin < SPI_MAX_NUMBER_HW_CS);
98 
99  uint8_t mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL;
100  switch (chipSelectPin) {
102  mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_0_ACTIVE;
103  break;
105  mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_1_ACTIVE;
106  break;
108  mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_2_ACTIVE;
109  break;
111  mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_3_ACTIVE;
112  break;
114  mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_4_ACTIVE;
115  break;
117  mappedHardwareChipSelectPin = SPI_HARDWARE_CHIP_SELECT_5_ACTIVE;
118  break;
119  default: /* something went really wrong */
120  FAS_ASSERT(FAS_TRAP); /* LCOV_EXCL_LINE */
121  break; /* LCOV_EXCL_LINE */
122  }
123  return mappedHardwareChipSelectPin;
124 }
125 static uint8_t SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e chipSelectType, uint32_t chipSelectPin) {
126  FAS_ASSERT((chipSelectType == SPI_CHIP_SELECT_HARDWARE) || (chipSelectType == SPI_CHIP_SELECT_SOFTWARE));
127  FAS_ASSERT(chipSelectPin <= MCU_LARGEST_PIN_NUMBER);
128 
129  uint8_t mappedChipSelectPin = (uint8_t)chipSelectPin;
130  /* for software chips select, there is nothing more to sanitize or map, therefore it is just needed to further
131  analyze the hardware chip select setting */
132  if (chipSelectType == SPI_CHIP_SELECT_HARDWARE) {
133  mappedChipSelectPin = SPI_GetHardwareChipSelectPin(mappedChipSelectPin);
134  }
135 
136  return mappedChipSelectPin;
137 }
138 static void SPI_InitializeChipSelects(void) {
139  for (uint8_t s = 0u; s < BS_NR_OF_STRINGS; s++) {
142  spi_nxp775InterfaceTx[s].pConfig->CSNR =
144  spi_nxp775InterfaceRx[s].pConfig->CSNR =
146  }
151 }
152 
153 /*========== Extern Function Implementations ================================*/
154 extern void SPI_Initialize(void) {
155  spiInit();
157 }
158 
159 extern STD_RETURN_TYPE_e SPI_TransmitDummyByte(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint32_t delay) {
160  FAS_ASSERT(pSpiInterface != NULL_PTR);
161  /* AXIVION Routine Generic-MissingParameterAssert: delay: parameter accepts whole range */
162 
163  uint16_t txDummy[1] = {0x00};
164  STD_RETURN_TYPE_e retVal = SPI_TransmitData(pSpiInterface, txDummy, 1u);
165  MCU_Delay_us(delay);
166  return retVal;
167 }
168 
169 extern STD_RETURN_TYPE_e SPI_TransmitData(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16 *pTxBuff, uint32 frameLength) {
170  FAS_ASSERT(pSpiInterface != NULL_PTR);
171  FAS_ASSERT(pTxBuff != NULL_PTR);
172  FAS_ASSERT(frameLength > 0u);
173  STD_RETURN_TYPE_e retval = STD_NOT_OK;
174 
175  /* Lock SPI hardware to prevent concurrent read/write commands */
176  if (STD_OK == SPI_Lock(SPI_GetSpiIndex(pSpiInterface->pNode))) {
177  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
178 
179  /** SW Chip Select */
180  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
181  /** Set SPI Chip Select pins as GIOs */
182  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
183  /** Activate Chip Select */
184  IO_PinReset(pSpiInterface->pGioPort, pSpiInterface->csPin);
185  }
186  /** HW Chip Select */
187  if (pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE) {
188  /**
189  * Activate HW Chip Select according to bitmask register CSNR
190  * by setting pins as SPI functional pins
191  */
192  /** First deactivate all HW Chip Selects */
193  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
194  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
195  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
196  /** Bitmask = 0 --> HW CS active
197  * --> write to PC0 to set pin as SPI pin (and not GIO)
198  */
199  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
200  }
201  }
202  }
203  uint32_t spiRetval = spiTransmitData(pSpiInterface->pNode, pSpiInterface->pConfig, frameLength, pTxBuff);
204  /** SW Chip Select */
205  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
206  /** Deactivate Chip Select */
207  IO_PinSet(pSpiInterface->pGioPort, pSpiInterface->csPin);
208  }
209 
210  /* Unlock SPI hardware */
211  SPI_Unlock(SPI_GetSpiIndex(pSpiInterface->pNode));
212 
213  /* Transmission successful */
214  if ((spiRetval & SPI_FLAG_REGISTER_TRANSMISSION_ERRORS) == 0u) {
215  retval = STD_OK;
216  }
217  }
218  return retval;
219 }
220 
222  SPI_INTERFACE_CONFIG_s *pSpiInterface,
223  uint16 *pTxBuff,
224  uint16 *pRxBuff,
225  uint32 frameLength) {
226  FAS_ASSERT(pSpiInterface != NULL_PTR);
227  FAS_ASSERT(pTxBuff != NULL_PTR);
228  FAS_ASSERT(pRxBuff != NULL_PTR);
229  FAS_ASSERT(frameLength > 0u);
230  STD_RETURN_TYPE_e retval = STD_NOT_OK;
231 
232  /* Lock SPI hardware to prevent concurrent read/write commands */
233  if (STD_OK == SPI_Lock(SPI_GetSpiIndex(pSpiInterface->pNode))) {
234  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
235 
236  /** SW Chip Select */
237  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
238  /** Set SPI Chip Select pins as GIOs */
239  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
240  /** Activate Chip Select */
241  IO_PinReset(pSpiInterface->pGioPort, pSpiInterface->csPin);
242  }
243  /** HW Chip Select */
244  if (pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE) {
245  /**
246  * Activate HW Chip Select according to bitmask register CSNR
247  * by setting pins as SPI functional pins
248  */
249  /** First deactivate all HW Chip Selects */
250  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
251  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
252  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
253  /** Bitmask = 0 --> HW CS active
254  * --> write to PC0 to set pin as SPI pin (and not GIO)
255  */
256  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
257  }
258  }
259  }
260  uint32_t spiRetval =
261  spiTransmitAndReceiveData(pSpiInterface->pNode, pSpiInterface->pConfig, frameLength, pTxBuff, pRxBuff);
262  /** SW Chip Select */
263  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
264  /** Deactivate Chip Select */
265  IO_PinSet(pSpiInterface->pGioPort, pSpiInterface->csPin);
266  }
267 
268  /* Unlock SPI hardware */
269  SPI_Unlock(SPI_GetSpiIndex(pSpiInterface->pNode));
270 
271  /* Transmission successful */
272  if ((spiRetval & SPI_FLAG_REGISTER_TRANSMISSION_ERRORS) == 0u) {
273  retval = STD_OK;
274  }
275  }
276  return retval;
277 }
278 
280  SPI_INTERFACE_CONFIG_s *pSpiInterface,
281  uint16 *pTxBuff,
282  uint16 *pRxBuff,
283  uint32 frameLength) {
284  FAS_ASSERT(pSpiInterface != NULL_PTR);
285  FAS_ASSERT(pTxBuff != NULL_PTR);
286  FAS_ASSERT(pRxBuff != NULL_PTR);
287  FAS_ASSERT(frameLength > 0u);
288 
289  (void)spiTransmitAndReceiveData(pSpiInterface->pNode, pSpiInterface->pConfig, frameLength, pTxBuff, pRxBuff);
290 }
291 
293  SPI_INTERFACE_CONFIG_s *pSpiInterface,
294  uint16_t *pTxBuff,
295  uint16_t *pRxBuff,
296  uint32_t frameLength) {
297  FAS_ASSERT(frameLength > 2u);
298  FAS_ASSERT(pSpiInterface != NULL_PTR);
299  FAS_ASSERT(pTxBuff != NULL_PTR);
300  FAS_ASSERT(pRxBuff != NULL_PTR);
301  /** SPI over DMA currently only compatible with HW Chip Select */
302  FAS_ASSERT(pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE);
303  const uint8_t spiIndex = SPI_GetSpiIndex(pSpiInterface->pNode);
304  FAS_ASSERT(spiIndex < spi_nrBusyFlags);
305 
306  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
307 
309  /* Lock SPI hardware to prevent concurrent read/write commands */
310  if (spi_busyFlags[spiIndex] == SPI_IDLE) {
311  spi_busyFlags[spiIndex] = SPI_BUSY;
312 
313  /* Check that not SPI transmission over DMA is taking place */
314  if ((pSpiInterface->pNode->INT0 & DMAREQEN_BIT) == 0x0) {
315  /**
316  * Activate HW Chip Select according to bitmask register CSNR
317  * by setting pins as SPI functional pins
318  */
319  /** First deactivate all HW Chip Selects */
320  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
321  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
322  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
323  /** Bitmask = 0 --> HW CS active
324  * --> write to PC0 to set pin as SPI pin (and not GIO)
325  */
326  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
327  }
328  }
329 
330  /* The upper 16 bits will be written in the SPI DAT1 register where they serve as configuration */
331  uint32 Chip_Select_Hold = 0u;
332  if (pSpiInterface->pConfig->CS_HOLD == TRUE) {
333  Chip_Select_Hold = SPI_CSHOLD_BIT;
334  } else {
335  Chip_Select_Hold = 0U;
336  }
337  uint32 WDelay = 0u;
338  if (pSpiInterface->pConfig->WDEL == TRUE) {
339  WDelay = SPI_WDEL_BIT;
340  } else {
341  WDelay = 0U;
342  }
343  SPIDATAFMT_t DataFormat = pSpiInterface->pConfig->DFSEL;
344  uint8 ChipSelect = pSpiInterface->pConfig->CSNR;
345 
346  /* Go to privilege mode to write DMA config registers */
347  (void)FSYS_RaisePrivilege();
348 
349  spi_txLastWord[spiIndex] = pTxBuff[frameLength - 1u];
350  spi_txLastWord[spiIndex] |= ((uint32)DataFormat << SPI_DATA_FORMAT_FIELD_POSITION) |
351  ((uint32)ChipSelect << SPI_HARDWARE_CHIP_SELECT_FIELD_POSITION) | (WDelay);
352 
353  /* Set Tx buffer address */
354  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].txChannel].ISADDR =
355  (uint32_t)(&pTxBuff[1u]); /* First word sent manually to write configuration in SPIDAT1 register */
356  /**
357  * Set number of Tx words to send
358  * Last word sent in ISR to set CSHOLD = 0
359  */
360  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].txChannel].ITCOUNT =
361  ((frameLength - 2u) << 16U) | 1U; /* Last word sent manually to write CSHOLD in SPIDAT1 register */
362 
363  /* Set Rx buffer address */
364  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].rxChannel].IDADDR = (uint32_t)pRxBuff;
365  /* Set number of Rx words to receive */
366  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].rxChannel].ITCOUNT = (frameLength << 16U) | 1U;
367 
368  /* Re-enable channels; because auto-init is disabled */
369  /* Disable otherwise transmission is constantly ongoing */
370  dmaSetChEnable((dmaChannel_t)dma_spiDmaChannels[spiIndex].txChannel, (dmaTriggerType_t)DMA_HW);
371  dmaSetChEnable((dmaChannel_t)dma_spiDmaChannels[spiIndex].rxChannel, (dmaTriggerType_t)DMA_HW);
372 
373  /* DMA config registers written, leave privilege mode */
375 
376  /* DMA_REQ_Enable */
377  /* Starts DMA requests if SPIEN is also set to 1 */
378  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
379  uint32_t txBuffer = pTxBuff[0u];
380  txBuffer |= ((uint32)DataFormat << 24U) | ((uint32)ChipSelect << 16U) | (WDelay) | (Chip_Select_Hold);
381  /**
382  * Send first word without DMA because when writing config to DAT1
383  * the HW CS pin are asserted immediately, even if SPIEN bit in GCR1 is 0.
384  * The C2TDELAY is then taken into account before the transmission.
385  */
386  pSpiInterface->pNode->DAT1 = txBuffer;
387  uint32_t timeoutIterations = SPI_TX_EMPTY_TIMEOUT_ITERATIONS;
388  while (((pSpiInterface->pNode->FLG & (uint32)((uint32_t)1u << SPI_TX_BUFFER_EMPTY_FLAG_POSITION)) == 0u) &&
389  (timeoutIterations > 0u)) {
390  timeoutIterations--;
391  }
392  pSpiInterface->pNode->INT0 |= DMAREQEN_BIT;
393 
394  retVal = STD_OK;
395  }
396  }
398 
399  return retVal;
400 }
401 
402 extern STD_RETURN_TYPE_e SPI_Lock(uint8_t spi) {
403  /* AXIVION Routine Generic-MissingParameterAssert: spi: parameter accepts whole range */
404 
405  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
406 
408  if ((spi < spi_nrBusyFlags) && (spi_busyFlags[spi] == SPI_IDLE)) {
409  spi_busyFlags[spi] = SPI_BUSY;
410  retVal = STD_OK;
411  } else {
412  retVal = STD_NOT_OK;
413  }
415 
416  return retVal;
417 }
418 
419 extern void SPI_Unlock(uint8_t spi) {
420  /* AXIVION Routine Generic-MissingParameterAssert: spi: parameter accepts whole range */
421 
423  if (spi < spi_nrBusyFlags) {
424  spi_busyFlags[spi] = SPI_IDLE;
425  }
427 }
428 
429 extern void SPI_SetFunctional(spiBASE_t *pNode, enum spiPinSelect bit, bool hardwareControlled) {
430  FAS_ASSERT(pNode != NULL_PTR);
431  FAS_ASSERT(bit <= (enum spiPinSelect)MCU_LARGEST_PIN_NUMBER);
432 
433  /* retrieve current configuration */
434  spi_config_reg_t configRegisterBuffer = {0};
435  if (pNode == spiREG1) {
436  spi1GetConfigValue(&configRegisterBuffer, CurrentValue);
437  } else if (pNode == spiREG2) {
438  spi2GetConfigValue(&configRegisterBuffer, CurrentValue);
439  } else if (pNode == spiREG3) {
440  spi3GetConfigValue(&configRegisterBuffer, CurrentValue);
441  } else if (pNode == spiREG4) {
442  spi4GetConfigValue(&configRegisterBuffer, CurrentValue);
443  } else if (pNode == spiREG5) {
444  spi5GetConfigValue(&configRegisterBuffer, CurrentValue);
445  } else {
446  /* invalid SPI node */
448  }
449  uint32_t newPc0 = configRegisterBuffer.CONFIG_PC0;
450 
451  if (hardwareControlled == false) {
452  /* bit has to be cleared */
453  newPc0 &= ~(uint32_t)((uint32_t)1u << (uint8_t)(bit));
454  } else {
455  /* bit has to be set */
456  newPc0 |= (uint32_t)((uint32_t)1u << (uint8_t)(bit));
457  }
458 
459  /* set new port value */
460  spiSetFunctional(pNode, newPc0);
461 }
462 
464  SPI_INTERFACE_CONFIG_s *pSpiInterface,
465  uint16_t *pTxBuff,
466  uint16_t *pRxBuff,
467  uint32_t frameLength) {
468  FAS_ASSERT(pSpiInterface != NULL_PTR);
469  FAS_ASSERT(pTxBuff != NULL_PTR);
470  FAS_ASSERT(pRxBuff != NULL_PTR);
471  FAS_ASSERT(frameLength > 0u);
472  /** SPI receive works only with HW Chip Select */
473  FAS_ASSERT(pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE);
474 
475  STD_RETURN_TYPE_e retVal = STD_OK;
476 
478  /* Go to privilege mode to write DMA config registers */
479  (void)FSYS_RaisePrivilege();
480 
481  /* DMA_REQ Disable */
482  pSpiInterface->pNode->INT0 &= ~DMAREQEN_BIT;
483  pSpiInterface->pNode->GCR1 &= ~SPIEN_BIT;
484 
485  /* Write FMT configuration in DAT1; as SPI is configured as slave, this does not provoke a transmission */
486  SPIDATAFMT_t DataFormat = pSpiInterface->pConfig->DFSEL;
487  pSpiInterface->pNode->DAT1 |= ((uint32)DataFormat << SPI_DATA_FORMAT_FIELD_POSITION);
488 
489  /* Set Tx buffer address */
490  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].txChannel].ISADDR =
491  (uint32_t)pTxBuff;
492  /* Set number of Tx bytes to send */
493  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].txChannel].ITCOUNT =
494  (frameLength << 16U) | 1U;
495 
496  /* Set Rx buffer address */
497  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].rxChannel].IDADDR =
498  (uint32_t)pRxBuff;
499  /* Set number of Rx bytes to receive */
500  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].rxChannel].ITCOUNT =
501  (frameLength << 16U) | 1U;
502 
503  /* Re-enable channels; because auto-init is disabled */
504  /* Disable otherwise transmission is constantly on going */
505  dmaSetChEnable(
506  (dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].txChannel, (dmaTriggerType_t)DMA_HW);
507  dmaSetChEnable(
508  (dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].rxChannel, (dmaTriggerType_t)DMA_HW);
509 
510  /* DMA config registers written, leave privilege mode */
512 
514 
515  /* Activate chip selects according to bitmask register CSNR */
516  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
517  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
518  /* Bitmask = 0 --> HW CS active --> set pin as SPI functional pin */
519  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
520  }
521  }
522 
523  /* DMA_REQ Enable */
524  /* Starts DMA requests if SPIEN is also set to 1 */
525  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
526  pSpiInterface->pNode->INT0 |= DMAREQEN_BIT;
527 
528  return retVal;
529 }
530 
531 extern void SPI_DmaSendLastByte(uint8_t spiIndex) {
533  dma_spiInterfaces[spiIndex]->DAT1 = spi_txLastWord[spiIndex];
534 }
535 
536 /* AXIVION Next Codeline Style Linker-Multiple_Definition: TI HAL only provides a weak implementation */
537 /* Doxygen comment needs to be here, as this is from a TI generated HAL header */
538 /**
539  * @brief SPI Interrupt callback
540  * @param[in] spi spi device
541  * @param flags flags to be passed
542  */
543 void UNIT_TEST_WEAK_IMPL spiNotification(spiBASE_t *spi, uint32 flags) {
544 }
545 
547  FAS_ASSERT(pNode != NULL_PTR);
548  const SpiDataStatus_t spiStatus = SpiTxStatus(pNode);
549  STD_RETURN_TYPE_e retval = STD_OK;
550  if (spiStatus == SPI_PENDING) {
551  retval = STD_NOT_OK;
552  }
553  return retval;
554 }
555 
556 extern uint8_t SPI_GetSpiIndex(spiBASE_t *pNode) {
557  FAS_ASSERT(pNode != NULL_PTR);
558  uint8_t spiIndex = 0u;
559 
560  if (pNode == spiREG1) {
561  spiIndex = SPI_SPI1_INDEX;
562  } else if (pNode == spiREG2) {
563  spiIndex = SPI_SPI2_INDEX;
564  } else if (pNode == spiREG3) {
565  spiIndex = SPI_SPI3_INDEX;
566  } else if (pNode == spiREG4) {
567  spiIndex = SPI_SPI4_INDEX;
568  } else if (pNode == spiREG5) {
569  spiIndex = SPI_SPI5_INDEX;
570  } else {
571  /** Invalid SPI node */
573  }
574 
575  return spiIndex;
576 }
577 
578 /*========== Externalized Static Function Implementations (Unit Test) =======*/
579 #ifdef UNITY_UNIT_TEST
580 extern void TEST_SPI_InitializeChipSelects(void) {
582 }
583 extern uint8_t TEST_SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e csType, uint32_t csPin) {
584  return SPI_GetChipSelectPin(csType, csPin);
585 }
586 extern uint8_t TEST_SPI_GetHardwareChipSelectPin(uint8_t csPin) {
587  return SPI_GetHardwareChipSelectPin(csPin);
588 }
589 #endif
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
Headers for the driver for the DMA module.
spiBASE_t * dma_spiInterfaces[DMA_NUMBER_SPI_INTERFACES]
Definition: dma_cfg.c:87
DMA_CHANNEL_CONFIG_s dma_spiDmaChannels[DMA_NUMBER_SPI_INTERFACES]
Definition: dma_cfg.c:69
#define SPIEN_BIT
Definition: dma_cfg.h:119
#define DMA_NUMBER_SPI_INTERFACES
Definition: dma_cfg.h:115
#define DMAREQEN_BIT
Definition: dma_cfg.h:117
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:255
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:129
Definition of foxBMS standard types.
STD_RETURN_TYPE_e
Definition: fstd_types.h:82
@ STD_NOT_OK
Definition: fstd_types.h:84
@ STD_OK
Definition: fstd_types.h:83
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
Function to switch between user mode and privilege mode.
long FSYS_RaisePrivilege(void)
Raise privilege.
static void FSYS_SwitchToUserMode(void)
Switch back to user mode.
Definition: fsystem.h:130
#define UNIT_TEST_WEAK_IMPL
Definition: general.h:97
void IO_PinSet(volatile uint32_t *pRegisterAddress, uint32_t pin)
Set pin by writing in pin output register.
Definition: io.c:91
void IO_PinReset(volatile uint32_t *pRegisterAddress, uint32_t pin)
Reset pin by writing in pin output register.
Definition: io.c:98
Header for the driver for the IO module.
void MCU_Delay_us(uint32_t delay_us)
Wait blocking a certain time in microseconds.
Definition: mcu.c:89
Headers for the driver for the MCU module.
#define MCU_LARGEST_PIN_NUMBER
largest pin number that exists in TMS570LC4357
Definition: mcu.h:69
Declaration of the OS wrapper interface.
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:154
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:150
static void SPI_InitializeChipSelects(void)
Definition: spi.c:138
STD_RETURN_TYPE_e SPI_TransmitReceiveDataDma(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16_t *pTxBuff, uint16_t *pRxBuff, uint32_t frameLength)
Transmits and receives data on SPI with DMA.
Definition: spi.c:292
static uint8_t SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e chipSelectType, uint32_t chipSelectPin)
Definition: spi.c:125
void SPI_SetFunctional(spiBASE_t *pNode, enum spiPinSelect bit, bool hardwareControlled)
Sets the functional of a SPI pin.
Definition: spi.c:429
#define SPI_HARDWARE_CHIP_SELECT_PIN_1
Definition: spi.c:81
STD_RETURN_TYPE_e SPI_CheckInterfaceAvailable(spiBASE_t *pNode)
Returns STD_OK if the SPI interface can be used again.
Definition: spi.c:546
void SPI_DmaSendLastByte(uint8_t spiIndex)
Used to send last byte per SPI.
Definition: spi.c:531
STD_RETURN_TYPE_e SPI_TransmitDummyByte(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint32_t delay)
Sends a dummy byte to wake up the SPI interface.
Definition: spi.c:159
void SPI_FramTransmitReceiveData(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16 *pTxBuff, uint16 *pRxBuff, uint32 frameLength)
Transmits and receives data on SPI without DMA, wrapper for FRAM.
Definition: spi.c:279
#define SPI_HARDWARE_CHIP_SELECT_PIN_5
Definition: spi.c:85
STD_RETURN_TYPE_e SPI_Lock(uint8_t spi)
Locks SPI interfaces.
Definition: spi.c:402
#define SPI_HARDWARE_CHIP_SELECT_PIN_3
Definition: spi.c:83
STD_RETURN_TYPE_e SPI_SlaveSetReceiveDataDma(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16_t *pTxBuff, uint16_t *pRxBuff, uint32_t frameLength)
Transmits and receives data on SPI with DMA.
Definition: spi.c:463
#define SPI_HARDWARE_CHIP_SELECT_PIN_0
Definition: spi.c:80
void SPI_Unlock(uint8_t spi)
Unlocks SPI interfaces.
Definition: spi.c:419
STD_RETURN_TYPE_e SPI_TransmitData(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16 *pTxBuff, uint32 frameLength)
Transmits data on SPI without DMA.
Definition: spi.c:169
static uint8_t SPI_GetHardwareChipSelectPin(uint8_t chipSelectPin)
Definition: spi.c:96
void UNIT_TEST_WEAK_IMPL spiNotification(spiBASE_t *spi, uint32 flags)
SPI Interrupt callback.
Definition: spi.c:543
STD_RETURN_TYPE_e SPI_TransmitReceiveData(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16 *pTxBuff, uint16 *pRxBuff, uint32 frameLength)
Transmits and receives data on SPI without DMA.
Definition: spi.c:221
uint8_t SPI_GetSpiIndex(spiBASE_t *pNode)
Returns index of SPI node.
Definition: spi.c:556
#define SPI_HARDWARE_CHIP_SELECT_PIN_2
Definition: spi.c:82
#define SPI_HARDWARE_CHIP_SELECT_PIN_4
Definition: spi.c:84
#define SPI_FLAG_REGISTER_TRANSMISSION_ERRORS
Definition: spi.c:74
static uint32_t spi_txLastWord[DMA_NUMBER_SPI_INTERFACES]
Definition: spi.c:77
void SPI_Initialize(void)
Initializes the SPI module.
Definition: spi.c:154
Headers for the driver for the SPI module.
Headers for the configuration for the SPI module.
#define SPI_HARDWARE_CHIP_SELECT_3_ACTIVE
#define SPI_HARDWARE_CHIP_SELECT_0_ACTIVE
#define SPI_HARDWARE_CHIP_SELECT_1_ACTIVE
#define SPI_HARDWARE_CHIP_SELECT_4_ACTIVE
#define SPI_HARDWARE_CHIP_SELECT_5_ACTIVE
#define SPI_HARDWARE_CHIP_SELECT_2_ACTIVE
#define SPI_HARDWARE_CHIP_SELECT_DISABLE_ALL
SPI_INTERFACE_CONFIG_s spi_mxmInterface
Definition: spi_cfg.c:206
SPI_INTERFACE_CONFIG_s spi_adiInterface[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:181
SPI_INTERFACE_CONFIG_s spi_sbcMcuInterface
Definition: spi_cfg.c:255
SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceTx[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:215
SPI_BUSY_STATE_e spi_busyFlags[]
Definition: spi_cfg.c:264
SPI_INTERFACE_CONFIG_s spi_framInterface
Definition: spi_cfg.c:237
SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceRx[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:226
SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:195
const uint8_t spi_nrBusyFlags
Definition: spi_cfg.c:273
SPI_INTERFACE_CONFIG_s spi_spsInterface
Definition: spi_cfg.c:246
#define SPI_SPI5_INDEX
Definition: spi_cfg.h:75
#define SPI_HARDWARE_CHIP_SELECT_FIELD_POSITION
Definition: spi_cfg.h:88
#define SPI_SPI2_INDEX
Definition: spi_cfg.h:72
@ SPI_IDLE
Definition: spi_cfg.h:110
@ SPI_BUSY
Definition: spi_cfg.h:111
#define SPI_DATA_FORMAT_FIELD_POSITION
Definition: spi_cfg.h:91
#define SPI_WDEL_BIT
Definition: spi_cfg.h:85
#define SPI_TX_EMPTY_TIMEOUT_ITERATIONS
Definition: spi_cfg.h:100
#define SPI_CSHOLD_BIT
Definition: spi_cfg.h:82
#define SPI_MAX_NUMBER_HW_CS
Definition: spi_cfg.h:103
#define SPI_SPI4_INDEX
Definition: spi_cfg.h:74
#define SPI_TX_BUFFER_EMPTY_FLAG_POSITION
Definition: spi_cfg.h:94
#define SPI_SPI1_INDEX
Definition: spi_cfg.h:71
#define SPI_PC0_CLEAR_HW_CS_MASK
Definition: spi_cfg.h:97
SPI_CHIP_SELECT_TYPE_e
Definition: spi_cfg.h:116
@ SPI_CHIP_SELECT_SOFTWARE
Definition: spi_cfg.h:118
@ SPI_CHIP_SELECT_HARDWARE
Definition: spi_cfg.h:117
#define SPI_SPI3_INDEX
Definition: spi_cfg.h:73
dmaChannel_t rxChannel
Definition: dma_cfg.h:136
dmaChannel_t txChannel
Definition: dma_cfg.h:135
SPI_CHIP_SELECT_TYPE_e csType
Definition: spi_cfg.h:130
volatile uint32_t * pGioPort
Definition: spi_cfg.h:128
spiDAT1_t * pConfig
Definition: spi_cfg.h:126
spiBASE_t * pNode
Definition: spi_cfg.h:127