foxBMS  1.5.0
The foxBMS Battery Management System API Documentation
pwm.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 pwm.c
44  * @author foxBMS Team
45  * @date 2021-10-07 (date of creation)
46  * @updated 2023-02-03 (date of last update)
47  * @version v1.5.0
48  * @ingroup DRIVERS
49  * @prefix PWM
50  *
51  * @brief Implementation of the PWM module.
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "pwm.h"
57 
58 #include "HL_ecap.h"
59 #include "HL_etpwm.h"
60 #include "HL_system.h"
61 
62 #include "fassert.h"
63 #include "foxmath.h"
64 #include "fsystem.h"
65 
66 #include <math.h>
67 #include <stdint.h>
68 
69 /*========== Macros and Definitions =========================================*/
70 /** lower threshold permill */
71 #define PWM_LOWER_THRESHOLD_PERM (1u)
72 
73 /** upper threshold permill */
74 #define PWM_UPPER_THRESHOLD_PERM (999u)
75 
76 /** full period in promill */
77 #define PWM_FULL_PERIOD_PERM (1000u)
78 
79 /** stores the initialization states of the different parts of the module */
80 typedef struct {
81  bool ecapInitialized; /**< initialization state of the enhanced capture module */
82  bool etpwmInitialized; /**< initialization state of the pwm module */
84 
85 /*========== Static Constant and Variable Definitions =======================*/
87  .ecapInitialized = false,
88  .etpwmInitialized = false,
89 };
90 
91 /** linear offset (through output circuit) */
92 static const int16_t pwm_kLinearOffset = 0;
93 
94 static PWM_SIGNAL_s ecap_inputPwmSignal = {.dutyCycle_perc = 0.0f, .frequency_Hz = 0.0f};
95 
96 /*========== Extern Constant and Variable Definitions =======================*/
97 
98 /*========== Static Function Prototypes =====================================*/
99 /** returns the ePWM time period (currently for ePWM1A)
100  * @returns ePWM time period in counter ticks
101  */
102 static uint16_t PWM_GetEtpwmTimePeriod(void);
103 
104 /** returns a ePWM counter value based on a duty cycle
105  * @param[in] dutyCycle_perm duty cycle in permill
106  * @returns counter value
107  */
108 static uint16_t PWM_ComputeCounterValueFromDutyCycle(uint16_t dutyCycle_perm);
109 
110 /*========== Static Function Implementations ================================*/
111 static uint16_t PWM_GetEtpwmTimePeriod(void) {
112  etpwm_config_reg_t etPwmConfig = {0};
113  etpwm1GetConfigValue(&etPwmConfig, CurrentValue); /* retrieve the current config */
114  return etPwmConfig.CONFIG_TBPRD;
115 }
116 
117 static uint16_t PWM_ComputeCounterValueFromDutyCycle(uint16_t dutyCycle_perm) {
118  FAS_ASSERT((dutyCycle_perm >= PWM_LOWER_THRESHOLD_PERM) && (dutyCycle_perm <= PWM_UPPER_THRESHOLD_PERM));
119 
120  uint16_t basePeriod = PWM_GetEtpwmTimePeriod();
121  uint32_t counterValue = (((uint32_t)basePeriod * (uint32_t)dutyCycle_perm) / PWM_FULL_PERIOD_PERM);
122 
123  FAS_ASSERT(counterValue <= (uint16_t)UINT16_MAX);
124  return (uint16_t)counterValue;
125 }
126 
127 /*========== Extern Function Implementations ================================*/
128 extern void PWM_Initialize(void) {
129  etpwmInit();
131  ecapInit();
132  pwm_state.ecapInitialized = true;
133 }
134 
135 extern void PWM_StartPwm(void) {
136  /* go to privileged mode in order to access control register */
137  const int32_t raisePrivilegeResult = FSYS_RaisePrivilege();
138  FAS_ASSERT(raisePrivilegeResult == 0);
139  etpwmStartTBCLK();
140  /* done; go back to user mode */
142 }
143 
144 extern void PWM_StopPwm(void) {
145  /* go to privileged mode in order to access control register */
146  const int32_t raisePrivilegeResult = FSYS_RaisePrivilege();
147  FAS_ASSERT(raisePrivilegeResult == 0);
148  etpwmStopTBCLK();
149  /* done; go back to user mode */
151 }
152 
153 extern void PWM_SetDutyCycle(uint16_t dutyCycle_perm) {
154  FAS_ASSERT(dutyCycle_perm <= (uint16_t)INT16_MAX);
155  int16_t intermediateDutyCycle_perm = (int16_t)dutyCycle_perm + pwm_kLinearOffset;
156  /* prevent wrap-around */
157  if (intermediateDutyCycle_perm < 0) {
158  intermediateDutyCycle_perm = 0;
159  }
160  uint16_t correctedDutyCycle_perm = (uint16_t)intermediateDutyCycle_perm;
161 
162  if (correctedDutyCycle_perm < PWM_LOWER_THRESHOLD_PERM) {
163  correctedDutyCycle_perm = PWM_LOWER_THRESHOLD_PERM;
164  }
165 
166  if (correctedDutyCycle_perm > PWM_UPPER_THRESHOLD_PERM) {
167  correctedDutyCycle_perm = PWM_UPPER_THRESHOLD_PERM;
168  }
169 
170  etpwmSetCmpA(etpwmREG1, PWM_ComputeCounterValueFromDutyCycle(correctedDutyCycle_perm));
171 }
172 
173 /** called in case of ECAP interrupt, defined as weak in HAL */
174 /* AXIVION Next Codeline Style Linker-Multiple_Definition: TI HAL only provides a weak implementation */
175 /* AXIVION Next Codeline Style MisraC2012-2.7: parameter needed by API */
176 extern void ecapNotification(ecapBASE_t *ecap, uint16 flags) {
177  FAS_ASSERT(ecap != NULL_PTR);
178  /* AXIVION Routine Generic-MissingParameterAssert: flags: parameter accept whole range */
179 
180  /* Counter value of rising edge */
181  uint32_t capture1 = ecapGetCAP1(ecapREG1);
182  /* Counter value of falling edge */
183  uint32_t capture2 = ecapGetCAP2(ecapREG1);
184  /* Counter value of next rising edge */
185  uint32_t capture3 = ecapGetCAP3(ecapREG1);
186 
187  if (capture3 != capture1) {
188  /* Counter 3 - Counter 1: Period in counter ticks */
189  /* Convert MHz to Hz */
190  ecap_inputPwmSignal.frequency_Hz = 1.0f / ((float_t)(capture3 - capture1) / (HCLK_FREQ * 1000000.0f));
191 
192  /* Counter 2 - Counter 1: Duty cycle in counter ticks */
193  ecap_inputPwmSignal.dutyCycle_perc = (float_t)(capture2 - capture1) / (float_t)(capture3 - capture1) *
195  } else {
198  }
199 }
200 
202  return pwm_state.ecapInitialized;
203 }
204 
206  /* TODO: how to ensure that values have been updated? add timestamp? Add counter?*/
207  return ecap_inputPwmSignal;
208 }
209 
210 /*========== Getter for static Variables (Unit Test) ========================*/
211 #ifdef UNITY_UNIT_TEST
212 extern int16_t TEST_PWM_GetLinearOffset(void) {
213  return pwm_kLinearOffset;
214 }
215 #endif
216 
217 /*========== Externalized Static Function Implementations (Unit Test) =======*/
218 #ifdef UNITY_UNIT_TEST
219 #endif
Assert macro implementation.
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:254
math library for often used math functions
#define UNIT_CONVERSION_FACTOR_100_FLOAT
Definition: foxmath.h:77
#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
static PWM_INITIALIZATION_STATE_s pwm_state
Definition: pwm.c:86
void PWM_SetDutyCycle(uint16_t dutyCycle_perm)
Set the duty cycle of the PWM (currently only channel 1A)
Definition: pwm.c:153
void PWM_Initialize(void)
Initializes the ETPWM and the ECAP module.
Definition: pwm.c:128
void PWM_StopPwm(void)
Stop the PWM (stops all configured ePWM channels)
Definition: pwm.c:144
static uint16_t PWM_GetEtpwmTimePeriod(void)
Definition: pwm.c:111
#define PWM_UPPER_THRESHOLD_PERM
Definition: pwm.c:74
#define PWM_FULL_PERIOD_PERM
Definition: pwm.c:77
static uint16_t PWM_ComputeCounterValueFromDutyCycle(uint16_t dutyCycle_perm)
Definition: pwm.c:117
void PWM_StartPwm(void)
Start the PWM (starts all configured ePWM channels)
Definition: pwm.c:135
void ecapNotification(ecapBASE_t *ecap, uint16 flags)
Definition: pwm.c:176
PWM_SIGNAL_s PWM_GetPwmData(void)
Get dutycycle and frequency of input PWM signal.
Definition: pwm.c:205
static PWM_SIGNAL_s ecap_inputPwmSignal
Definition: pwm.c:94
bool PWM_IsEcapModuleInitialized(void)
Get initialization state of ecap module.
Definition: pwm.c:201
#define PWM_LOWER_THRESHOLD_PERM
Definition: pwm.c:71
static const int16_t pwm_kLinearOffset
Definition: pwm.c:92
PWM driver for the TMS570LC43xx.
float_t frequency_Hz
Definition: pwm.h:73
float_t dutyCycle_perc
Definition: pwm.h:72