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