foxBMS - Unit Tests  1.5.0
The foxBMS Unit Tests 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-02-03 (date of last update)
47  * @version v1.5.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++) {
141  spi_nxp775InterfaceTx[s].pConfig->CSNR =
143  spi_nxp775InterfaceRx[s].pConfig->CSNR =
145  }
150 }
151 
152 /*========== Extern Function Implementations ================================*/
153 extern void SPI_Initialize(void) {
154  spiInit();
156 }
157 
158 extern STD_RETURN_TYPE_e SPI_TransmitDummyByte(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint32_t delay) {
159  FAS_ASSERT(pSpiInterface != NULL_PTR);
160  /* AXIVION Routine Generic-MissingParameterAssert: delay: parameter accepts whole range */
161 
162  uint16_t txDummy[1] = {0x00};
163  STD_RETURN_TYPE_e retVal = SPI_TransmitData(pSpiInterface, txDummy, 1u);
164  MCU_Delay_us(delay);
165  return retVal;
166 }
167 
168 extern STD_RETURN_TYPE_e SPI_TransmitData(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16 *pTxBuff, uint32 frameLength) {
169  FAS_ASSERT(pSpiInterface != NULL_PTR);
170  FAS_ASSERT(pTxBuff != NULL_PTR);
171  FAS_ASSERT(frameLength > 0u);
172  STD_RETURN_TYPE_e retval = STD_NOT_OK;
173 
174  /* Lock SPI hardware to prevent concurrent read/write commands */
175  if (STD_OK == SPI_Lock(SPI_GetSpiIndex(pSpiInterface->pNode))) {
176  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
177 
178  /** SW Chip Select */
179  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
180  /** Set SPI Chip Select pins as GIOs */
181  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
182  /** Activate Chip Select */
183  IO_PinReset(pSpiInterface->pGioPort, pSpiInterface->csPin);
184  }
185  /** HW Chip Select */
186  if (pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE) {
187  /**
188  * Activate HW Chip Select according to bitmask register CSNR
189  * by setting pins as SPI functional pins
190  */
191  /** First deactivate all HW Chip Selects */
192  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
193  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
194  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
195  /** Bitmask = 0 --> HW CS active
196  * --> write to PC0 to set pin as SPI pin (and not GIO)
197  */
198  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
199  }
200  }
201  }
202  uint32_t spiRetval = spiTransmitData(pSpiInterface->pNode, pSpiInterface->pConfig, frameLength, pTxBuff);
203  /** SW Chip Select */
204  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
205  /** Deactivate Chip Select */
206  IO_PinSet(pSpiInterface->pGioPort, pSpiInterface->csPin);
207  }
208 
209  /* Unlock SPI hardware */
210  SPI_Unlock(SPI_GetSpiIndex(pSpiInterface->pNode));
211 
212  /* Transmission successful */
213  if ((spiRetval & SPI_FLAG_REGISTER_TRANSMISSION_ERRORS) == 0u) {
214  retval = STD_OK;
215  }
216  }
217  return retval;
218 }
219 
221  SPI_INTERFACE_CONFIG_s *pSpiInterface,
222  uint16 *pTxBuff,
223  uint16 *pRxBuff,
224  uint32 frameLength) {
225  FAS_ASSERT(pSpiInterface != NULL_PTR);
226  FAS_ASSERT(pTxBuff != NULL_PTR);
227  FAS_ASSERT(pRxBuff != NULL_PTR);
228  FAS_ASSERT(frameLength > 0u);
229  STD_RETURN_TYPE_e retval = STD_NOT_OK;
230 
231  /* Lock SPI hardware to prevent concurrent read/write commands */
232  if (STD_OK == SPI_Lock(SPI_GetSpiIndex(pSpiInterface->pNode))) {
233  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
234 
235  /** SW Chip Select */
236  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
237  /** Set SPI Chip Select pins as GIOs */
238  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
239  /** Activate Chip Select */
240  IO_PinReset(pSpiInterface->pGioPort, pSpiInterface->csPin);
241  }
242  /** HW Chip Select */
243  if (pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE) {
244  /**
245  * Activate HW Chip Select according to bitmask register CSNR
246  * by setting pins as SPI functional pins
247  */
248  /** First deactivate all HW Chip Selects */
249  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
250  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
251  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
252  /** Bitmask = 0 --> HW CS active
253  * --> write to PC0 to set pin as SPI pin (and not GIO)
254  */
255  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
256  }
257  }
258  }
259  uint32_t spiRetval =
260  spiTransmitAndReceiveData(pSpiInterface->pNode, pSpiInterface->pConfig, frameLength, pTxBuff, pRxBuff);
261  /** SW Chip Select */
262  if (pSpiInterface->csType == SPI_CHIP_SELECT_SOFTWARE) {
263  /** Deactivate Chip Select */
264  IO_PinSet(pSpiInterface->pGioPort, pSpiInterface->csPin);
265  }
266 
267  /* Unlock SPI hardware */
268  SPI_Unlock(SPI_GetSpiIndex(pSpiInterface->pNode));
269 
270  /* Transmission successful */
271  if ((spiRetval & SPI_FLAG_REGISTER_TRANSMISSION_ERRORS) == 0u) {
272  retval = STD_OK;
273  }
274  }
275  return retval;
276 }
277 
279  SPI_INTERFACE_CONFIG_s *pSpiInterface,
280  uint16 *pTxBuff,
281  uint16 *pRxBuff,
282  uint32 frameLength) {
283  FAS_ASSERT(pSpiInterface != NULL_PTR);
284  FAS_ASSERT(pTxBuff != NULL_PTR);
285  FAS_ASSERT(pRxBuff != NULL_PTR);
286  FAS_ASSERT(frameLength > 0u);
287 
288  (void)spiTransmitAndReceiveData(pSpiInterface->pNode, pSpiInterface->pConfig, frameLength, pTxBuff, pRxBuff);
289 }
290 
292  SPI_INTERFACE_CONFIG_s *pSpiInterface,
293  uint16_t *pTxBuff,
294  uint16_t *pRxBuff,
295  uint32_t frameLength) {
296  FAS_ASSERT(frameLength > 2u);
297  FAS_ASSERT(pSpiInterface != NULL_PTR);
298  FAS_ASSERT(pTxBuff != NULL_PTR);
299  FAS_ASSERT(pRxBuff != NULL_PTR);
300  /** SPI over DMA currently only compatible with HW Chip Select */
301  FAS_ASSERT(pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE);
302  const uint8_t spiIndex = SPI_GetSpiIndex(pSpiInterface->pNode);
303  FAS_ASSERT(spiIndex < spi_nrBusyFlags);
304 
305  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
306 
308  /* Lock SPI hardware to prevent concurrent read/write commands */
309  if (spi_busyFlags[spiIndex] == SPI_IDLE) {
310  spi_busyFlags[spiIndex] = SPI_BUSY;
311 
312  /* Check that not SPI transmission over DMA is taking place */
313  if ((pSpiInterface->pNode->INT0 & DMAREQEN_BIT) == 0x0) {
314  /**
315  * Activate HW Chip Select according to bitmask register CSNR
316  * by setting pins as SPI functional pins
317  */
318  /** First deactivate all HW Chip Selects */
319  pSpiInterface->pNode->PC0 &= SPI_PC0_CLEAR_HW_CS_MASK;
320  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
321  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
322  /** Bitmask = 0 --> HW CS active
323  * --> write to PC0 to set pin as SPI pin (and not GIO)
324  */
325  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
326  }
327  }
328 
329  /* The upper 16 bits will be written in the SPI DAT1 register where they serve as configuration */
330  uint32 Chip_Select_Hold = 0u;
331  if (pSpiInterface->pConfig->CS_HOLD == TRUE) {
332  Chip_Select_Hold = SPI_CSHOLD_BIT;
333  } else {
334  Chip_Select_Hold = 0U;
335  }
336  uint32 WDelay = 0u;
337  if (pSpiInterface->pConfig->WDEL == TRUE) {
338  WDelay = SPI_WDEL_BIT;
339  } else {
340  WDelay = 0U;
341  }
342  SPIDATAFMT_t DataFormat = pSpiInterface->pConfig->DFSEL;
343  uint8 ChipSelect = pSpiInterface->pConfig->CSNR;
344 
345  /* Go to privilege mode to write DMA config registers */
346  (void)FSYS_RaisePrivilege();
347 
348  spi_txLastWord[spiIndex] = pTxBuff[frameLength - 1u];
349  spi_txLastWord[spiIndex] |= ((uint32)DataFormat << SPI_DATA_FORMAT_FIELD_POSITION) |
350  ((uint32)ChipSelect << SPI_HARDWARE_CHIP_SELECT_FIELD_POSITION) | (WDelay);
351 
352  /* Set Tx buffer address */
353  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].txChannel].ISADDR =
354  (uint32_t)(&pTxBuff[1u]); /* First word sent manually to write configuration in SPIDAT1 register */
355  /**
356  * Set number of Tx words to send
357  * Last word sent in ISR to set CSHOLD = 0
358  */
359  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].txChannel].ITCOUNT =
360  ((frameLength - 2u) << 16U) | 1U; /* Last word sent manually to write CSHOLD in SPIDAT1 register */
361 
362  /* Set Rx buffer address */
363  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].rxChannel].IDADDR = (uint32_t)pRxBuff;
364  /* Set number of Rx words to receive */
365  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[spiIndex].rxChannel].ITCOUNT = (frameLength << 16U) | 1U;
366 
367  /* Re-enable channels; because auto-init is disabled */
368  /* Disable otherwise transmission is constantly ongoing */
369  dmaSetChEnable((dmaChannel_t)dma_spiDmaChannels[spiIndex].txChannel, (dmaTriggerType_t)DMA_HW);
370  dmaSetChEnable((dmaChannel_t)dma_spiDmaChannels[spiIndex].rxChannel, (dmaTriggerType_t)DMA_HW);
371 
372  /* DMA config registers written, leave privilege mode */
374 
375  /* DMA_REQ_Enable */
376  /* Starts DMA requests if SPIEN is also set to 1 */
377  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
378  uint32_t txBuffer = pTxBuff[0u];
379  txBuffer |= ((uint32)DataFormat << 24U) | ((uint32)ChipSelect << 16U) | (WDelay) | (Chip_Select_Hold);
380  /**
381  * Send first word without DMA because when writing config to DAT1
382  * the HW CS pin are asserted immediately, even if SPIEN bit in GCR1 is 0.
383  * The C2TDELAY is then taken into account before the transmission.
384  */
385  pSpiInterface->pNode->DAT1 = txBuffer;
386  uint32_t timeoutIterations = SPI_TX_EMPTY_TIMEOUT_ITERATIONS;
387  while (((pSpiInterface->pNode->FLG & (uint32)((uint32_t)1u << SPI_TX_BUFFER_EMPTY_FLAG_POSITION)) == 0u) &&
388  (timeoutIterations > 0u)) {
389  timeoutIterations--;
390  }
391  pSpiInterface->pNode->INT0 |= DMAREQEN_BIT;
392 
393  retVal = STD_OK;
394  }
395  }
397 
398  return retVal;
399 }
400 
401 extern STD_RETURN_TYPE_e SPI_Lock(uint8_t spi) {
402  /* AXIVION Routine Generic-MissingParameterAssert: spi: parameter accepts whole range */
403 
404  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
405 
407  if ((spi < spi_nrBusyFlags) && (spi_busyFlags[spi] == SPI_IDLE)) {
408  spi_busyFlags[spi] = SPI_BUSY;
409  retVal = STD_OK;
410  } else {
411  retVal = STD_NOT_OK;
412  }
414 
415  return retVal;
416 }
417 
418 extern void SPI_Unlock(uint8_t spi) {
419  /* AXIVION Routine Generic-MissingParameterAssert: spi: parameter accepts whole range */
420 
422  if (spi < spi_nrBusyFlags) {
423  spi_busyFlags[spi] = SPI_IDLE;
424  }
426 }
427 
428 extern void SPI_SetFunctional(spiBASE_t *pNode, enum spiPinSelect bit, bool hardwareControlled) {
429  FAS_ASSERT(pNode != NULL_PTR);
430  FAS_ASSERT(bit <= (enum spiPinSelect)MCU_LARGEST_PIN_NUMBER);
431 
432  /* retrieve current configuration */
433  spi_config_reg_t configRegisterBuffer = {0};
434  if (pNode == spiREG1) {
435  spi1GetConfigValue(&configRegisterBuffer, CurrentValue);
436  } else if (pNode == spiREG2) {
437  spi2GetConfigValue(&configRegisterBuffer, CurrentValue);
438  } else if (pNode == spiREG3) {
439  spi3GetConfigValue(&configRegisterBuffer, CurrentValue);
440  } else if (pNode == spiREG4) {
441  spi4GetConfigValue(&configRegisterBuffer, CurrentValue);
442  } else if (pNode == spiREG5) {
443  spi5GetConfigValue(&configRegisterBuffer, CurrentValue);
444  } else {
445  /* invalid SPI node */
447  }
448  uint32_t newPc0 = configRegisterBuffer.CONFIG_PC0;
449 
450  if (hardwareControlled == false) {
451  /* bit has to be cleared */
452  newPc0 &= ~(uint32_t)((uint32_t)1u << (uint8_t)(bit));
453  } else {
454  /* bit has to be set */
455  newPc0 |= (uint32_t)((uint32_t)1u << (uint8_t)(bit));
456  }
457 
458  /* set new port value */
459  spiSetFunctional(pNode, newPc0);
460 }
461 
463  SPI_INTERFACE_CONFIG_s *pSpiInterface,
464  uint16_t *pTxBuff,
465  uint16_t *pRxBuff,
466  uint32_t frameLength) {
467  FAS_ASSERT(pSpiInterface != NULL_PTR);
468  FAS_ASSERT(pTxBuff != NULL_PTR);
469  FAS_ASSERT(pRxBuff != NULL_PTR);
470  FAS_ASSERT(frameLength > 0u);
471  /** SPI receive works only with HW Chip Select */
472  FAS_ASSERT(pSpiInterface->csType == SPI_CHIP_SELECT_HARDWARE);
473 
474  STD_RETURN_TYPE_e retVal = STD_OK;
475 
477  /* Go to privilege mode to write DMA config registers */
478  (void)FSYS_RaisePrivilege();
479 
480  /* DMA_REQ Disable */
481  pSpiInterface->pNode->INT0 &= ~DMAREQEN_BIT;
482  pSpiInterface->pNode->GCR1 &= ~SPIEN_BIT;
483 
484  /* Write FMT configuration in DAT1; as SPI is configured as slave, this does not provoke a transmission */
485  SPIDATAFMT_t DataFormat = pSpiInterface->pConfig->DFSEL;
486  pSpiInterface->pNode->DAT1 |= ((uint32)DataFormat << SPI_DATA_FORMAT_FIELD_POSITION);
487 
488  /* Set Tx buffer address */
489  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].txChannel].ISADDR =
490  (uint32_t)pTxBuff;
491  /* Set number of Tx bytes to send */
492  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].txChannel].ITCOUNT =
493  (frameLength << 16U) | 1U;
494 
495  /* Set Rx buffer address */
496  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].rxChannel].IDADDR =
497  (uint32_t)pRxBuff;
498  /* Set number of Rx bytes to receive */
499  dmaRAMREG->PCP[(dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].rxChannel].ITCOUNT =
500  (frameLength << 16U) | 1U;
501 
502  /* Re-enable channels; because auto-init is disabled */
503  /* Disable otherwise transmission is constantly on going */
504  dmaSetChEnable(
505  (dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].txChannel, (dmaTriggerType_t)DMA_HW);
506  dmaSetChEnable(
507  (dmaChannel_t)dma_spiDmaChannels[SPI_GetSpiIndex(pSpiInterface->pNode)].rxChannel, (dmaTriggerType_t)DMA_HW);
508 
509  /* DMA config registers written, leave privilege mode */
511 
513 
514  /* Activate chip selects according to bitmask register CSNR */
515  for (uint8_t csNumber = 0u; csNumber < SPI_MAX_NUMBER_HW_CS; csNumber++) {
516  if (((pSpiInterface->pConfig->CSNR >> csNumber) & 0x1u) == 0u) {
517  /* Bitmask = 0 --> HW CS active --> set pin as SPI functional pin */
518  pSpiInterface->pNode->PC0 |= (uint32_t)1u << csNumber;
519  }
520  }
521 
522  /* DMA_REQ Enable */
523  /* Starts DMA requests if SPIEN is also set to 1 */
524  pSpiInterface->pNode->GCR1 |= SPIEN_BIT;
525  pSpiInterface->pNode->INT0 |= DMAREQEN_BIT;
526 
527  return retVal;
528 }
529 
530 extern void SPI_DmaSendLastByte(uint8_t spiIndex) {
532  dma_spiInterfaces[spiIndex]->DAT1 = spi_txLastWord[spiIndex];
533 }
534 
535 /* AXIVION Next Codeline Style Linker-Multiple_Definition: TI HAL only provides a weak implementation */
536 /* Doxygen comment needs to be here, as this is from a TI generated HAL header */
537 /**
538  * @brief SPI Interrupt callback
539  * @param[in] spi spi device
540  * @param flags flags to be passed
541  */
542 void UNIT_TEST_WEAK_IMPL spiNotification(spiBASE_t *spi, uint32 flags) {
543 }
544 
546  FAS_ASSERT(pNode != NULL_PTR);
547  const SpiDataStatus_t spiStatus = SpiTxStatus(pNode);
548  STD_RETURN_TYPE_e retval = STD_OK;
549  if (spiStatus == SPI_PENDING) {
550  retval = STD_NOT_OK;
551  }
552  return retval;
553 }
554 
555 extern uint8_t SPI_GetSpiIndex(spiBASE_t *pNode) {
556  FAS_ASSERT(pNode != NULL_PTR);
557  uint8_t spiIndex = 0u;
558 
559  if (pNode == spiREG1) {
560  spiIndex = SPI_SPI1_INDEX;
561  } else if (pNode == spiREG2) {
562  spiIndex = SPI_SPI2_INDEX;
563  } else if (pNode == spiREG3) {
564  spiIndex = SPI_SPI3_INDEX;
565  } else if (pNode == spiREG4) {
566  spiIndex = SPI_SPI4_INDEX;
567  } else if (pNode == spiREG5) {
568  spiIndex = SPI_SPI5_INDEX;
569  } else {
570  /** Invalid SPI node */
572  }
573 
574  return spiIndex;
575 }
576 
577 /*========== Externalized Static Function Implementations (Unit Test) =======*/
578 #ifdef UNITY_UNIT_TEST
580  return SPI_InitializeChipSelects();
581 }
582 extern uint8_t TEST_SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e csType, uint32_t csPin) {
583  return SPI_GetChipSelectPin(csType, csPin);
584 }
585 extern uint8_t TEST_SPI_GetHardwareChipSelectPin(uint8_t csPin) {
586  return SPI_GetHardwareChipSelectPin(csPin);
587 }
588 #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:250
#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.
#define FSYS_SwitchToUserMode()
Switch back to user mode.
Definition: fsystem.h:135
long FSYS_RaisePrivilege(void)
Raise privilege.
Definition: test_htsensor.c:67
#define UNIT_TEST_WEAK_IMPL
Definition: general.h:95
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:138
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:134
uint8_t TEST_SPI_GetHardwareChipSelectPin(uint8_t csPin)
Definition: spi.c:585
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:291
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:428
#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:545
void SPI_DmaSendLastByte(uint8_t spiIndex)
Used to send last byte per SPI.
Definition: spi.c:530
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:158
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:278
#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:401
#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:462
#define SPI_HARDWARE_CHIP_SELECT_PIN_0
Definition: spi.c:80
void SPI_Unlock(uint8_t spi)
Unlocks SPI interfaces.
Definition: spi.c:418
STD_RETURN_TYPE_e SPI_TransmitData(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16 *pTxBuff, uint32 frameLength)
Transmits data on SPI without DMA.
Definition: spi.c:168
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:542
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:220
void TEST_SPI_InitializeChipSelects(void)
Definition: spi.c:579
uint8_t SPI_GetSpiIndex(spiBASE_t *pNode)
Returns index of SPI node.
Definition: spi.c:555
uint8_t TEST_SPI_GetChipSelectPin(SPI_CHIP_SELECT_TYPE_e csType, uint32_t csPin)
Definition: spi.c:582
#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:153
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:182
SPI_INTERFACE_CONFIG_s spi_sbcMcuInterface
Definition: spi_cfg.c:231
SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceTx[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:191
SPI_BUSY_STATE_e spi_busyFlags[]
Definition: spi_cfg.c:240
SPI_INTERFACE_CONFIG_s spi_framInterface
Definition: spi_cfg.c:213
SPI_INTERFACE_CONFIG_s spi_nxp775InterfaceRx[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:202
SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:171
const uint8_t spi_nrBusyFlags
Definition: spi_cfg.c:249
SPI_INTERFACE_CONFIG_s spi_spsInterface
Definition: spi_cfg.c:222
#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