foxBMS  1.2.0
The foxBMS Battery Management System API Documentation
sps.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, 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 sps.c
44  * @author foxBMS Team
45  * @date 2020-10-14 (date of creation)
46  * @updated 2021-10-01 (date of last update)
47  * @ingroup DRIVERS
48  * @prefix SPS
49  *
50  * @brief Driver for the smart power switches.
51  *
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "sps.h"
56 
57 #include "database.h"
58 #include "io.h"
59 #include "mcu.h"
60 #include "os.h"
61 #include "pex.h"
62 #include "spi.h"
63 
64 /*========== Macros and Definitions =========================================*/
65 
66 /*========== Static Constant and Variable Definitions =======================*/
67 /** state indicator of the state-machine */
69 
70 /** timer for the state-machine */
71 static uint8_t sps_timer = 0;
72 
73 /** SPI buffer:
74  * Tx part used to issue a write or read register command
75  * Rx part is unused
76  * @{
77  */
80 /**@}*/
81 
82 /** SPI buffer:
83  * Tx part used to write to contactor output control register
84  * Rx part used to read answer from former read register command
85  *
86  * When a read register command was issued on the MOSI line,
87  * the answers comes during the next command (read or write)
88  * on the MISO line
89  * (datasheet figure 6 page 9 in datasheet Rev. 2 - 11 September 2019)
90  *
91  * In the SPS driver, there are always two communications with the SPS IC
92  * each time the state machine is triggered:
93  * - first a register access (read or write)
94  * - then a write access to the channel output control register
95  * This way, the channel outputs are switched each time the state machine
96  * is triggered, and during the second access, if a read access was done
97  * before, the answer comes during the second access.
98  * @{
99  */
102 /**@}*/
103 
104 /** amount of ticks to wait when toggling the reset */
105 #define SPS_RESET_WAIT_TIME_TICKS (5u)
106 
107 /*========== Extern Constant and Variable Definitions =======================*/
108 
109 /*========== Static Function Prototypes =====================================*/
110 
111 /**
112  * @brief Assemble a general command to the SPS ICs
113  * @details For each call of the #SPS_Ctrl() function two transactions are
114  * sent. For details please read the documentation of #SPS_Transmit().
115  *
116  * This function has to be called before the transaction in order to
117  * update the TX buffer with a general command to the SPS chips in the
118  * daisy-chain. The actual command (and with that registers) that
119  * shall be accessed and sent is controlled by the parameter that is
120  * passed on with this function. *
121  * @param[in] action decides which command should be used
122  */
123 static void SPS_SetCommandTxBuffer(const SPS_ACTION_e action);
124 
125 /**
126  * @brief Assemble an update to the channel state of the SPS ICs
127  * @details For each call of the #SPS_Ctrl() function two transactions are
128  * sent. For details please read the documentation of #SPS_Transmit().
129  *
130  * This function has to be called before the transaction in order to
131  * update the TX buffer with a channel configuration to the SPS chips
132  * in the daisy-chain. The actual contactor or channel state is taken
133  * from the current state of the array #sps_channelStatus.
134  */
135 static void SPS_SetContactorsTxBuffer(void);
136 
137 /**
138  * @brief Transmit all assembled messages for one timeframe
139  * @details This function leverages the fact that the SPS are connected in a
140  * "daisy-chain". This way the chain acts as a large shift register.
141  * When sending a message into the chain it is clocked in until every
142  * chip in the chain as its message. Then chip-select is released and
143  * the messages parsed. The answer is then assembled by the chip in
144  * its register and clocked out and received by the master with the
145  * next transmission.
146  *
147  * This function sends out a general command to each chip that has
148  * been assembled with #SPS_SetCommandTxBuffer(). The clocked out
149  * information that is received of this transaction is stored in a
150  * separate buffer and is the answer from the last transaction of the
151  * timeframe before the current one.
152  *
153  * After this transaction the answer to the general command is
154  * retrieved and the transmission is used to clock in an update of the
155  * state of the contactor channels. This update has been assembled
156  * before the call of this function with the function
157  * #SPS_SetContactorsTxBuffer().
158  * @returns returns STD_OK if both transactions have been successful
159  */
160 static STD_RETURN_TYPE_e SPS_Transmit(void);
161 
162 /**
163  * @brief Read the current measurements for a specific output
164  * for all SPS ICs of the daisy-chain.
165  * @details A read command must be issued for all SPS ICs in the daisy chain
166  * first. There is one register to read for each output.
167  * This funcion i used to retrieve the answer on the MISO line
168  * after the write command to the contactors output registers
169  * was made.
170  * The result is written to SPS_CoilCurrent[].
171  * @param[in] outputAllDevices Output (1 to 4) to be read. Value between
172  * 1-4 instead of 0-3 to match numbering
173  * in datasheet.
174  * @return TODO
175  */
176 static void SPS_GlobalReadCurrent(const uint8_t outputAllDevices);
177 
178 /** initialize the IO ports for the contactor driver */
179 static void SPS_InitializeIo(void);
180 
181 /** Init TX buffers with 0 */
182 static void SPS_InitializeBuffers(void);
183 /**
184  * @brief Sets the SPI Tx buffer for a register read access
185  * for all SPS ICs of the daisy-chain.
186  * @details The same command is issued for all SPS ICs in the daisy chain.
187  * This means that the same register is read
188  * to all SPS ICs in the daisy chain.
189  * @param[in] address address of register accessed
190  * @param[in] controlOrDiagnostic type of read access,
191  * #SPS_READ_DIAGNOSTIC_REGISTER for diagnostic
192  * register, #SPS_READ_CONTROL_REGISTER for
193  * control register.
194  * @param[out] pSpiTxBuffer Tx buffer used for the transmission
195  */
196 static void SPS_GlobalRegisterRead(
197  const uint16_t address,
198  const SPS_READ_TYPE_e controlOrDiagnostic,
199  uint16_t *pSpiTxBuffer);
200 
201 /**
202  * @brief Sets the SPI Tx buffer for a register write access
203  * for all SPS ICs of the daisy-chain.
204  * @details The same command is issued for all SPS ICs in the daisy chain.
205  * This means that the same value is written
206  * to all SPS ICs in the daisy chain.
207  * The current value in register is overwritten by writeData.
208  *
209  * @param[in] address address of register accessed
210  * @param[in] writeData data to write
211  * @param[out] pSpiTxBuffer Tx buffer used for the transmission
212  */
213 static void SPS_GlobalRegisterWrite(const uint16_t address, uint8_t writeData, uint16_t *pSpiTxBuffer);
214 
215 /**
216  * @brief Sets the SPI Tx buffer for a register write access
217  * for a specific single SPS ICs in the daisy-chain.
218  * @details The same command is issued for all SPS ICs in the daisy chain.
219  * This means that the same value is written
220  * to all SPS ICs in the daisy chain.
221  * This function does not set the Tx buffer to 0.
222  * This must be done manually.
223  * @param[in] device device number in the daisy-chain to be written to.
224  * @param[in] address address of register accessed
225  * @param[in] writeData data to write. In case of read access, this
226  * field is ignored and can be set to 0u.
227  * @param[in] writeType defines wether the value in register should be
228  * replaced by writeData, or or-ed with writeType,
229  * or and-ed with writeData
230  * @param[out] pSpiTxBuffer Tx buffer used for the transmission
231  */
233  uint8_t device,
234  const uint16_t address,
235  uint8_t writeData,
236  SPS_WRITE_TYPE_e writeType,
237  uint16_t *pSpiTxBuffer);
238 
239 /**
240  * @brief Request the functional state of a channel
241  * @details Pass a value of #SPS_CHANNEL_FUNCTION_e and a channel index number
242  * in order to request this state.
243  * @param[in] channelIndex number of the channel that should be accessed;
244  * do not confuse with contactor channel!
245  * @param[in] channelFunction requested functional state of the channel
246  */
247 static void SPS_RequestChannelState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction);
248 
249 /*========== Static Function Implementations ================================*/
250 static void SPS_InitializeIo(void) {
251  /** Pin to drive reset line of SPS ICs */
252  SPS_RESET_GIO_PORT_DIR |= (uint32)((uint32)1u << SPS_RESET_PIN);
253  /** Pin to drive Chip Select line of SPS ICs */
254  SPS_SPI_CS_GIOPORT_DIR |= (uint32)((uint32)1u << SPS_SPI_CS_PIN);
255 
256  /* set feedback enable as output */
258  /* enable output on feedback enable */
260 }
261 
263  const uint16_t address,
264  const SPS_READ_TYPE_e controlOrDiagnostic,
265  uint16_t *pSpiTxBuffer) {
266  FAS_ASSERT(pSpiTxBuffer != NULL_PTR);
267  if (controlOrDiagnostic == SPS_READ_DIAGNOSTIC_REGISTER) {
268  for (uint8_t i = 0u; i < SPS_SPI_BUFFERSIZE; i++) {
269  /* R/W bit = 0 to read */
270  pSpiTxBuffer[i] = (address << SPS_ADDRESS_BIT_START); /* Register address */
271  }
272  } else if (controlOrDiagnostic == SPS_READ_CONTROL_REGISTER) {
273  for (uint8_t i = 0u; i < SPS_SPI_BUFFERSIZE; i++) {
274  pSpiTxBuffer[i] = (address << SPS_ADDRESS_BIT_START) | /* Register address */
275  ((uint16_t)1u << SPS_DIAG_CTRL_BIT_POSITION); /* Select diagnostic register */
276  }
277  } else {
278  /* Invalid access type */
280  }
281 }
282 
283 static void SPS_GlobalRegisterWrite(const uint16_t address, uint8_t writeData, uint16_t *pSpiTxBuffer) {
284  FAS_ASSERT(pSpiTxBuffer != NULL_PTR);
285  for (uint8_t i = 0u; i < SPS_SPI_BUFFERSIZE; i++) {
286  pSpiTxBuffer[i] = ((uint16_t)1u << SPS_RW_BIT_POSITION) | /* R/W bit = 1 to write */
287  (address << SPS_ADDRESS_BIT_START) | /* Register address */
288  (writeData); /* Data to write */
289  }
290 }
291 
293  uint8_t device,
294  const uint16_t address,
295  uint8_t writeData,
296  SPS_WRITE_TYPE_e writeType,
297  uint16_t *pSpiTxBuffer) {
298  FAS_ASSERT(pSpiTxBuffer != NULL_PTR);
299  /* The index (SPS_SPI_BUFFERSIZE - 1 - device) is used because the devices
300  in the daisy-chain are accessed like a shift register. The first message
301  sent to the daisy-chain will arrive to the last device and the last
302  message will arrive to the first device. To communicate with
303  devices 0-1-2 in the daisy-chain, the sequence 2-1-0 has to be sent.
304  */
305  /* Keep the previous data which lies in the lower 8 bits */
306  uint8_t preceedingWriteData = (uint8_t)((pSpiTxBuffer[(SPS_SPI_BUFFERSIZE - 1u - device)]) & 0xFFu);
307  /* Clear write data which will be replaced */
308  pSpiTxBuffer[(SPS_SPI_BUFFERSIZE - 1u - device)] &= 0xFF00u;
309  /* Write R/W bit and address in the higher 8 bits */
310  pSpiTxBuffer[(SPS_SPI_BUFFERSIZE - 1u - device)] = (uint16_t)(
311  ((uint16_t)1u << SPS_RW_BIT_POSITION) | /* R/W bit = 1 to write */
312  (address << SPS_ADDRESS_BIT_START)); /* Register address */
313 
314  if (writeType == SPS_replaceCurrentValue) {
315  pSpiTxBuffer[(SPS_SPI_BUFFERSIZE - 1u - device)] |= (uint16_t)writeData; /* Data to write */
316  } else if (writeType == SPS_orWithCurrentValue) {
317  pSpiTxBuffer[(SPS_SPI_BUFFERSIZE - 1u - device)] |=
318  ((uint16_t)preceedingWriteData | (uint16_t)writeData); /* Data to write */
319  } else if (writeType == SPS_andWithCurrentValue) {
320  pSpiTxBuffer[(SPS_SPI_BUFFERSIZE - 1u - device)] |=
321  ((uint16_t)preceedingWriteData & (uint16_t)writeData); /* Data to write */
322  } else {
323  /* Invalid write type */
325  }
326 }
327 
328 static void SPS_SetCommandTxBuffer(const SPS_ACTION_e action) {
329  switch (action) {
333  /* transition to Normal mode and set drive strength to strong (This is required for high speed!) */
336  break;
337 
341  0x000F, /* Measure all four outputs for current and voltage on demand*/
343  break;
344 
348  break;
349 
353  break;
354 
358  break;
359 
363  break;
364 
368  break;
369 
370  default:
371  for (uint8_t i = 0u; i < SPS_SPI_BUFFERSIZE; i++) {
372  sps_spiTxRegisterBuffer[i] = 0x00;
373  }
374  break;
375  }
376 }
377 
378 static void SPS_InitializeBuffers(void) {
379  for (uint8_t i = 0u; i < SPS_SPI_BUFFERSIZE; i++) {
380  sps_spiTxRegisterBuffer[i] = 0u;
382  i,
384  0u, /* data to write, output control */
385  SPS_replaceCurrentValue, /* replace because we want to initialize with 0 */
387  }
388 }
389 
390 static void SPS_SetContactorsTxBuffer(void) {
391  for (SPS_CHANNEL_INDEX channel = 0u; channel < SPS_NR_OF_AVAILABLE_SPS_CHANNELS; channel++) {
392  SPS_CHANNEL_STATE_s *pChannel = &sps_channelStatus[channel];
393  /* If channel state is changed by request, process request */
394  if (pChannel->channelRequested != pChannel->channel) {
395  pChannel->channel = pChannel->channelRequested;
396 
397  /**
398  * With this computation, the contactor number is linked to the SPS IC
399  * position in the daisy-chain which is driving this contactor.
400  * Contactor 0-3: SPS IC 0
401  * Contactor 4-7: SPS IC 1
402  * Contactor 8-11: SPS IC 2
403  * ...
404  */
405  uint8_t spsDevicePositionInDaisyChain = channel / SPS_NR_CONTACTOR_PER_IC;
406 
407  if (pChannel->channelRequested == SPS_CHANNEL_ON) {
409  spsDevicePositionInDaisyChain,
411  1u << (channel % SPS_NR_CONTACTOR_PER_IC), /* data to write, output control */
412  SPS_orWithCurrentValue, /* OR because we want to set additional bits to 1 */
414  } else if (pChannel->channelRequested == SPS_CHANNEL_OFF) {
415  uint8_t writeData = (~(1u << (channel % SPS_NR_CONTACTOR_PER_IC)) & 0xFFu);
417  spsDevicePositionInDaisyChain,
419  writeData, /* data to write, output control */
420  SPS_andWithCurrentValue, /* AND because we want to set additional bits to 0 */
422  } else {
423  /* invalid entry in sps_channelStatus! */
425  }
426  }
427  }
428 }
429 
433 
434  /* The chip select has to be high for at least 300ns according to datasheet. This code delays
435  for the smallest time available in #MCU_delay_us() which is 1us. After this time we can
436  be sure that the SPI interface is able to receive again. */
437  MCU_delay_us(1u);
438 
444 
445  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
446  if ((STD_OK == retVal1) && (STD_OK == retVal2)) {
447  retVal = STD_OK;
448  }
449  return retVal;
450 }
451 
452 static void SPS_GlobalReadCurrent(const uint8_t outputAllDevices) {
453  /* outputAllDevices has to be 1, 2, 3 or 4 */
454  FAS_ASSERT((outputAllDevices > 0u) && (outputAllDevices <= SPS_NR_CONTACTOR_PER_IC));
455  for (SPS_CHANNEL_INDEX channel = 0u; channel < SPS_NR_OF_AVAILABLE_SPS_CHANNELS; channel++) {
456  if ((channel % SPS_NR_CONTACTOR_PER_IC) == (outputAllDevices - 1u)) {
457  uint8_t buffer_position = channel / SPS_NR_CONTACTOR_PER_IC;
458  uint16_t buffer = sps_spiRxReadAnswerDuringChannelControl[(SPS_SPI_BUFFERSIZE - 1u - buffer_position)] &
460  sps_channelStatus[channel].current_mA = (float)buffer * SPS_I_MEASUREMENT_LSB_mA;
461  }
462  }
463 }
464 
465 static void SPS_RequestChannelState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction) {
467  FAS_ASSERT((SPS_CHANNEL_OFF == channelFunction) || (SPS_CHANNEL_ON == channelFunction));
468 
470  sps_channelStatus[channelIndex].channelRequested = channelFunction;
472 }
473 
474 /*========== Extern Function Implementations ================================*/
475 extern void SPS_Ctrl(void) {
476  if (sps_timer > 0u) {
477  sps_timer--;
478  }
479  STD_RETURN_TYPE_e transmitRetval = STD_NOT_OK;
480 
481  if (sps_timer == 0u) {
482  switch (sps_state) {
483  case SPS_START:
484  /* set SPI speed to low speed in order to safely reach the all SPS */
488  break;
489 
490  case SPS_RESET_LOW:
494  break;
495 
496  case SPS_RESET_HIGH:
500  break;
501 
505  transmitRetval = SPS_Transmit();
506  if (STD_OK == transmitRetval) {
508  /* we have successfully configured the control registers to
509  strong drive mode and can now go to high speed communication */
511  } else {
513  }
514  break;
515 
519  transmitRetval = SPS_Transmit();
520  if (STD_OK == transmitRetval) {
522  } else {
524  }
525  break;
526 
527  case SPS_READ_EN_IRQ_PIN:
530  transmitRetval = SPS_Transmit();
531  if (STD_OK == transmitRetval) {
533  } else {
535  }
536  break;
537 
541  transmitRetval = SPS_Transmit();
542  if (STD_OK == transmitRetval) {
544  } else {
546  }
548  break;
549 
553  transmitRetval = SPS_Transmit();
554  if (STD_OK == transmitRetval) {
556  } else {
558  }
560  break;
561 
565  transmitRetval = SPS_Transmit();
566  if (STD_OK == transmitRetval) {
568  } else {
570  }
572  break;
573 
577  transmitRetval = SPS_Transmit();
578  if (STD_OK == transmitRetval) {
580  } else {
582  }
584  break;
585  default:
587  break;
588  }
589  }
590 }
591 
592 extern void SPS_Initialize(void) {
594 }
595 
596 extern void SPS_RequestContactorState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction) {
598  SPS_RequestChannelState(channelIndex, channelFunction);
599 }
600 
601 extern void SPS_RequestGeneralIOState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction) {
603  SPS_RequestChannelState(channelIndex, channelFunction);
604 }
605 
608 
610 
612  float channelCurrent_mA = sps_channelStatus[channelIndex].current_mA;
614 
615  if (channelCurrent_mA > sps_channelStatus[channelIndex].thresholdFeedbackOn_mA) {
616  channelFeedback = CONT_SWITCH_ON;
617  }
618 
619  return channelFeedback;
620 }
621 
622 extern CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelPexFeedback(const SPS_CHANNEL_INDEX channelIndex, bool normallyOpen) {
624  FAS_ASSERT((normallyOpen == true) || (normallyOpen == false));
625 
626  SPS_CHANNEL_FEEDBACK_MAPPING_s channelMapping = sps_kChannelFeedbackMapping[channelIndex];
627  uint8_t pinState = PEX_GetPin(channelMapping.pexDevice, channelMapping.pexChannel);
628 
630  if (normallyOpen == true) {
631  /* contactor is on if pinstate is high */
632  if (pinState != PEX_PIN_LOW) {
633  channelFeedback = CONT_SWITCH_ON;
634  }
635  } else {
636  /* contactor is on if pinstate is low */
637  if (pinState != PEX_PIN_HIGH) {
638  channelFeedback = CONT_SWITCH_ON;
639  }
640  }
641 
642  return channelFeedback;
643 }
644 
647  return sps_channelStatus[channelIndex].affiliation;
648 }
649 
650 /*========== Externalized Static Function Implementations (Unit Test) =======*/
651 #ifdef UNITY_UNIT_TEST
652 extern void TEST_SPS_RequestChannelState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction) {
653  SPS_RequestChannelState(channelIndex, channelFunction);
654 }
655 extern SPS_STATE_e TEST_SPS_GetSpsState(void) {
656  return sps_state;
657 }
658 extern void TEST_SPS_SetSpsState(const SPS_STATE_e newState) {
659  sps_state = newState;
660 }
661 extern uint8_t TEST_SPS_GetSpsTimer(void) {
662  return sps_timer;
663 }
664 extern void TEST_SPS_SetSpsTimer(const uint8_t newTimer) {
665  sps_timer = newTimer;
666 }
667 #endif /* UNITY_UNIT_TEST */
enum CONT_ELECTRICAL_STATE_TYPE CONT_ELECTRICAL_STATE_TYPE_e
@ CONT_SWITCH_ON
Definition: contactor_cfg.h:72
@ CONT_SWITCH_OFF
Definition: contactor_cfg.h:71
Database module header.
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:108
@ STD_NOT_OK
Definition: fstd_types.h:73
@ STD_OK
Definition: fstd_types.h:72
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:66
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
#define SETBIT(register, bit)
sets a bit to 1u
Definition: general.h:86
void IO_PinSet(volatile uint32_t *pRegisterAddress, uint32_t pin)
Set pin by writing in pin output register.
Definition: io.c:84
void IO_PinReset(volatile uint32_t *pRegisterAddress, uint32_t pin)
Reset pin by writing in pin output register.
Definition: io.c:91
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:80
Headers for the driver for the MCU module.
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os.c:178
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os.c:174
Implementation of the tasks used by the system, headers.
uint8_t PEX_GetPin(uint8_t portExpander, uint8_t pin)
get pin state of port expander pins.
Definition: pex.c:350
Header for the driver for the NXP PCA9539 port expander module.
#define PEX_PIN_LOW
Definition: pex.h:64
#define PEX_PIN_HIGH
Definition: pex.h:65
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:142
Headers for the driver for the SPI module.
void SPI_SpsInterfaceSwitchToLowSpeed(SPI_INTERFACE_CONFIG_s *pSpiSpsInterface)
Switch the SPS spi handle to low speed.
Definition: spi_cfg.c:325
void SPI_SpsInterfaceSwitchToHighSpeed(SPI_INTERFACE_CONFIG_s *pSpiSpsInterface)
Switch the SPS spi handle to high speed.
Definition: spi_cfg.c:320
SPI_INTERFACE_CONFIG_s spi_spsInterface
Definition: spi_cfg.c:213
#define SPS_SPI_CS_GIOPORT_DIR
Definition: spi_cfg.h:74
#define SPS_SPI_CS_PIN
Definition: spi_cfg.h:75
CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelPexFeedback(const SPS_CHANNEL_INDEX channelIndex, bool normallyOpen)
Get the feedback state of a channel.
Definition: sps.c:622
#define SPS_RESET_WAIT_TIME_TICKS
Definition: sps.c:105
SPS_CHANNEL_AFFILIATION_e SPS_GetChannelAffiliation(SPS_CHANNEL_INDEX channelIndex)
Returns the channel affiliation.
Definition: sps.c:645
void SPS_Initialize(void)
Initialize IOs for the SPS driver.
Definition: sps.c:592
static void SPS_InitializeIo(void)
Definition: sps.c:250
static STD_RETURN_TYPE_e SPS_Transmit(void)
Transmit all assembled messages for one timeframe.
Definition: sps.c:430
static void SPS_GlobalReadCurrent(const uint8_t outputAllDevices)
Read the current measurements for a specific output for all SPS ICs of the daisy-chain.
Definition: sps.c:452
static void SPS_GlobalRegisterRead(const uint16_t address, const SPS_READ_TYPE_e controlOrDiagnostic, uint16_t *pSpiTxBuffer)
Sets the SPI Tx buffer for a register read access for all SPS ICs of the daisy-chain.
Definition: sps.c:262
static uint16_t sps_spiRxRegisterBuffer[SPS_SPI_BUFFERSIZE]
Definition: sps.c:79
void SPS_Ctrl(void)
Control function for the CONT driver state machine.
Definition: sps.c:475
static void SPS_SingleDeviceRegisterWrite(uint8_t device, const uint16_t address, uint8_t writeData, SPS_WRITE_TYPE_e writeType, uint16_t *pSpiTxBuffer)
Sets the SPI Tx buffer for a register write access for a specific single SPS ICs in the daisy-chain.
Definition: sps.c:292
static void SPS_InitializeBuffers(void)
Definition: sps.c:378
static void SPS_GlobalRegisterWrite(const uint16_t address, uint8_t writeData, uint16_t *pSpiTxBuffer)
Sets the SPI Tx buffer for a register write access for all SPS ICs of the daisy-chain.
Definition: sps.c:283
void SPS_RequestGeneralIOState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction)
Request state of a general IO.
Definition: sps.c:601
static uint8_t sps_timer
Definition: sps.c:71
static void SPS_SetContactorsTxBuffer(void)
Assemble an update to the channel state of the SPS ICs.
Definition: sps.c:390
CONT_ELECTRICAL_STATE_TYPE_e SPS_GetChannelCurrentFeedback(const SPS_CHANNEL_INDEX channelIndex)
Get feedback value.
Definition: sps.c:606
void SPS_RequestContactorState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction)
Request state of a contactor.
Definition: sps.c:596
static uint16_t sps_spiTxRegisterBuffer[SPS_SPI_BUFFERSIZE]
Definition: sps.c:78
static SPS_STATE_e sps_state
Definition: sps.c:68
static uint16_t sps_spiTxWriteToChannelChannelControlRegister[SPS_SPI_BUFFERSIZE]
Definition: sps.c:100
static uint16_t sps_spiRxReadAnswerDuringChannelControl[SPS_SPI_BUFFERSIZE]
Definition: sps.c:101
static void SPS_RequestChannelState(SPS_CHANNEL_INDEX channelIndex, SPS_CHANNEL_FUNCTION_e channelFunction)
Request the functional state of a channel.
Definition: sps.c:465
static void SPS_SetCommandTxBuffer(const SPS_ACTION_e action)
Assemble a general command to the SPS ICs.
Definition: sps.c:328
Headers for the driver for the smart power switches.
SPS_CHANNEL_STATE_s sps_channelStatus[SPS_NR_OF_AVAILABLE_SPS_CHANNELS]
Definition: sps_cfg.c:65
const SPS_CHANNEL_FEEDBACK_MAPPING_s sps_kChannelFeedbackMapping[SPS_NR_OF_AVAILABLE_SPS_CHANNELS]
Definition: sps_cfg.c:82
#define SPS_FEEDBACK_GIO_PORT_DIR
Definition: sps_cfg.h:74
#define SPS_OUTPUT_CONTROL_REGISTER_ADDRESS
Definition: sps_cfg.h:108
#define SPS_GLOBAL_CONTROL_REGISTER_ADDRESS
Definition: sps_cfg.h:107
#define SPS_NR_OF_AVAILABLE_SPS_CHANNELS
Definition: sps_cfg.h:88
@ SPS_CHANNEL_ON
Definition: sps_cfg.h:174
@ SPS_CHANNEL_OFF
Definition: sps_cfg.h:173
#define SPS_SPI_BUFFERSIZE
Definition: sps_cfg.h:104
#define SPS_OD_IOUT1_DIAG_REGISTER_ADDRESS
Definition: sps_cfg.h:112
@ SPS_TRIGGER_CURRENT_MEASUREMENT
Definition: sps_cfg.h:203
@ SPS_CONFIGURE_CONTROL_REGISTER
Definition: sps_cfg.h:202
@ SPS_READ_MEASURED_CURRENT2
Definition: sps_cfg.h:205
@ SPS_READ_MEASURED_CURRENT1
Definition: sps_cfg.h:204
@ SPS_RESET_LOW
Definition: sps_cfg.h:200
@ SPS_READ_EN_IRQ_PIN
Definition: sps_cfg.h:208
@ SPS_READ_MEASURED_CURRENT3
Definition: sps_cfg.h:206
@ SPS_START
Definition: sps_cfg.h:199
@ SPS_READ_MEASURED_CURRENT4
Definition: sps_cfg.h:207
@ SPS_RESET_HIGH
Definition: sps_cfg.h:201
#define SPS_NORMAL_MODE
Definition: sps_cfg.h:136
enum SPS_WRITE_TYPE SPS_WRITE_TYPE_e
#define SPS_STRONG_DRIVE
Definition: sps_cfg.h:138
enum SPS_ACTION SPS_ACTION_e
#define SPS_FEEDBACK_GIO_PORT
Definition: sps_cfg.h:73
#define SPS_RESET_GIO_PORT_DIR
Definition: sps_cfg.h:68
enum SPS_STATE SPS_STATE_e
#define SPS_DRIVE_STRENGTH_BIT_START
Definition: sps_cfg.h:147
@ SPS_andWithCurrentValue
Definition: sps_cfg.h:162
@ SPS_orWithCurrentValue
Definition: sps_cfg.h:161
@ SPS_replaceCurrentValue
Definition: sps_cfg.h:160
#define SPS_MODE_BIT_START
Definition: sps_cfg.h:145
#define SPS_OD_IOUT2_DIAG_REGISTER_ADDRESS
Definition: sps_cfg.h:113
#define SPS_NR_CONTACTOR_PER_IC
Definition: sps_cfg.h:79
@ SPS_READ_DIAGNOSTIC_REGISTER
Definition: sps_cfg.h:167
@ SPS_READ_CONTROL_REGISTER
Definition: sps_cfg.h:168
enum SPS_CHANNEL_FUNCTION SPS_CHANNEL_FUNCTION_e
#define SPS_RW_BIT_POSITION
Definition: sps_cfg.h:125
#define SPS_OD_IOUT4_DIAG_REGISTER_ADDRESS
Definition: sps_cfg.h:115
#define SPS_OD_IOUT3_DIAG_REGISTER_ADDRESS
Definition: sps_cfg.h:114
enum SPS_READ_TYPE SPS_READ_TYPE_e
#define SPS_ADDRESS_BIT_START
Definition: sps_cfg.h:131
#define SPS_EN_IRQ_PIN_DIAG_REGISTER_ADDRESS
Definition: sps_cfg.h:116
#define SPS_RESET_GIO_PORT
Definition: sps_cfg.h:67
#define SPS_DIAG_CTRL_BIT_POSITION
Definition: sps_cfg.h:133
@ SPS_ACTION_READ_CURRENT_MEASUREMENT2
Definition: sps_cfg.h:216
@ SPS_ACTION_READ_CURRENT_MEASUREMENT1
Definition: sps_cfg.h:215
@ SPS_ACTION_TRIGGER_CURRENT_MEASUREMENT
Definition: sps_cfg.h:214
@ SPS_ACTION_READ_EN_IRQ_PIN
Definition: sps_cfg.h:219
@ SPS_ACTION_READ_CURRENT_MEASUREMENT4
Definition: sps_cfg.h:218
@ SPS_ACTION_CONFIGURE_CONTROL_REGISTER
Definition: sps_cfg.h:213
@ SPS_ACTION_READ_CURRENT_MEASUREMENT3
Definition: sps_cfg.h:217
#define SPS_I_MEASUREMENT_LSB_mA
Definition: sps_cfg.h:150
#define SPS_RESET_PIN
Definition: sps_cfg.h:69
#define SPS_BITMASK_DIAGNOSTIC_ONDEMAND_OUTPUT_CURRENT
Definition: sps_cfg.h:156
#define SPS_C_CONTROL_REGISTER_ADDRESS
Definition: sps_cfg.h:109
#define SPS_FEEDBACK_PIN
Definition: sps_cfg.h:75
uint8_t SPS_CHANNEL_INDEX
Definition: sps_types.h:63
@ SPS_AFF_CONTACTOR
Definition: sps_types.h:72
@ SPS_AFF_GENERAL_IO
Definition: sps_types.h:73
enum SPS_CHANNEL_AFFILIATION SPS_CHANNEL_AFFILIATION_e
affiliation type of a sps channel
const uint8_t pexChannel
Definition: sps_cfg.h:190
const uint8_t pexDevice
Definition: sps_cfg.h:189
SPS_CHANNEL_FUNCTION_e channelRequested
Definition: sps_cfg.h:179
const SPS_CHANNEL_AFFILIATION_e affiliation
Definition: sps_cfg.h:183
float current_mA
Definition: sps_cfg.h:181
SPS_CHANNEL_FUNCTION_e channel
Definition: sps_cfg.h:180