foxBMS  1.3.0
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-05-30 (date of last update)
47  * @version v1.3.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 "fsystem.h"
63 
64 /*========== Macros and Definitions =========================================*/
65 /** lower threshold permill */
66 #define PWM_LOWER_THRESHOLD_PERM (1u)
67 
68 /** upper threshold permill */
69 #define PWM_UPPER_THRESHOLD_PERM (999u)
70 
71 /** full period in promill */
72 #define PWM_FULL_PERIOD_PERM (1000u)
73 
74 typedef struct {
78 
79 /*========== Static Constant and Variable Definitions =======================*/
81  .ecapInitialized = false,
82  .etpwmInitialized = false,
83 };
84 
85 /** linear offset (through output circuit) */
86 static const int16_t pwm_kLinearOffset = 0;
87 
88 static PWM_SIGNAL_s ecap_inputPwmSignal = {.dutyCycle_perc = 0.0f, .frequency_Hz = 0.0f};
89 
90 /*========== Extern Constant and Variable Definitions =======================*/
91 
92 /*========== Static Function Prototypes =====================================*/
93 /** returns the ePWM time period (currently for ePWM1A)
94  * @returns ePWM time period in counter ticks
95  */
96 static uint16_t PWM_GetEtpwmTimePeriod(void);
97 
98 /** returns a ePWM counter value based on a duty cycle
99  * @param[in] dutyCycle_perm duty cycle in permill
100  * @returns counter value
101  */
102 static uint16_t PWM_ComputeCounterValueFromDutyCycle(uint16_t dutyCycle_perm);
103 
104 /*========== Static Function Implementations ================================*/
105 static uint16_t PWM_GetEtpwmTimePeriod(void) {
106  etpwm_config_reg_t etPwmConfig = {0};
107  etpwm1GetConfigValue(&etPwmConfig, CurrentValue); /* retrieve the current config */
108  return etPwmConfig.CONFIG_TBPRD;
109 }
110 
111 static uint16_t PWM_ComputeCounterValueFromDutyCycle(uint16_t dutyCycle_perm) {
112  FAS_ASSERT((dutyCycle_perm >= PWM_LOWER_THRESHOLD_PERM) && (dutyCycle_perm <= PWM_UPPER_THRESHOLD_PERM));
113 
114  uint16_t basePeriod = PWM_GetEtpwmTimePeriod();
115  uint32_t counterValue = (((uint32_t)basePeriod * (uint32_t)dutyCycle_perm) / PWM_FULL_PERIOD_PERM);
116 
117  FAS_ASSERT(counterValue <= (uint16_t)UINT16_MAX);
118  return (uint16_t)counterValue;
119 }
120 
121 /*========== Extern Function Implementations ================================*/
122 extern void PWM_Initialize(void) {
123  etpwmInit();
125  ecapInit();
126  pwm_state.ecapInitialized = true;
127 }
128 
129 extern void PWM_StartPwm(void) {
130  /* go to privileged mode in order to access control register */
131  const int32_t raisePrivilegeResult = FSYS_RaisePrivilege();
132  FAS_ASSERT(raisePrivilegeResult == 0);
133  etpwmStartTBCLK();
134  /* done; go back to user mode */
136 }
137 
138 extern void PWM_StopPwm(void) {
139  /* go to privileged mode in order to access control register */
140  const int32_t raisePrivilegeResult = FSYS_RaisePrivilege();
141  FAS_ASSERT(raisePrivilegeResult == 0);
142  etpwmStopTBCLK();
143  /* done; go back to user mode */
145 }
146 
147 extern void PWM_SetDutyCycle(uint16_t dutyCycle_perm) {
148  FAS_ASSERT(dutyCycle_perm <= (uint16_t)INT16_MAX);
149  int16_t intermediateDutyCycle_perm = (int16_t)dutyCycle_perm + pwm_kLinearOffset;
150  /* prevent wrap-around */
151  if (intermediateDutyCycle_perm < 0) {
152  intermediateDutyCycle_perm = 0;
153  }
154  uint16_t correctedDutyCycle_perm = (uint16_t)intermediateDutyCycle_perm;
155 
156  if (correctedDutyCycle_perm < PWM_LOWER_THRESHOLD_PERM) {
157  correctedDutyCycle_perm = PWM_LOWER_THRESHOLD_PERM;
158  }
159 
160  if (correctedDutyCycle_perm > PWM_UPPER_THRESHOLD_PERM) {
161  correctedDutyCycle_perm = PWM_UPPER_THRESHOLD_PERM;
162  }
163 
164  etpwmSetCmpA(etpwmREG1, PWM_ComputeCounterValueFromDutyCycle(correctedDutyCycle_perm));
165 }
166 
167 extern void ecapNotification(ecapBASE_t *ecap, uint16 flags) {
168  /* Counter value of rising edge */
169  uint32_t capture1 = ecapGetCAP1(ecapREG1);
170  /* Counter value of falling edge */
171  uint32_t capture2 = ecapGetCAP2(ecapREG1);
172  /* Counter value of next rising edge */
173  uint32_t capture3 = ecapGetCAP3(ecapREG1);
174 
175  /* Counter 3 - Counter 1: Period in counter ticks */
176  /* Convert MHz to Hz */
177  ecap_inputPwmSignal.frequency_Hz = 1.0f / ((float)(capture3 - capture1) / (HCLK_FREQ * 1000000.0f));
178 
179  /* Counter 2 - Counter 1: Duty cycle in counter ticks */
180  ecap_inputPwmSignal.dutyCycle_perc = (float)(capture2 - capture1) / (float)(capture3 - capture1) * 100.0f;
181 }
182 
184  return pwm_state.ecapInitialized;
185 }
186 
188  /* TODO: how to ensure that values have been updated? add timestamp? Add counter?*/
189  return ecap_inputPwmSignal;
190 }
191 
192 /*========== Getter for static Variables (Unit Test) ========================*/
193 #ifdef UNITY_UNIT_TEST
194 extern int16_t TEST_PWM_GetLinearOffset(void) {
195  return pwm_kLinearOffset;
196 }
197 #endif
198 
199 /*========== Externalized Static Function Implementations (Unit Test) =======*/
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:241
Function to switch between user mode and privilege mode.
#define FSYS_SwitchToUserMode()
Switch back to user mode.
Definition: fsystem.h:114
long FSYS_RaisePrivilege(void)
raise privilege
static PWM_INITIALIZATION_STATE_s pwm_state
Definition: pwm.c:80
void PWM_SetDutyCycle(uint16_t dutyCycle_perm)
Set the duty cycle of the PWM (currently only channel 1A)
Definition: pwm.c:147
void PWM_Initialize(void)
Initializes the ETPWM and the ECAP module.
Definition: pwm.c:122
void PWM_StopPwm(void)
Stop the PWM (stops all configured ePWM channels)
Definition: pwm.c:138
static uint16_t PWM_GetEtpwmTimePeriod(void)
Definition: pwm.c:105
#define PWM_UPPER_THRESHOLD_PERM
Definition: pwm.c:69
#define PWM_FULL_PERIOD_PERM
Definition: pwm.c:72
static uint16_t PWM_ComputeCounterValueFromDutyCycle(uint16_t dutyCycle_perm)
Definition: pwm.c:111
void PWM_StartPwm(void)
Start the PWM (starts all configured ePWM channels)
Definition: pwm.c:129
PWM_SIGNAL_s ECAP_GetPwmData(void)
Get dutycycle and frequency of input PWM signal.
Definition: pwm.c:187
void ecapNotification(ecapBASE_t *ecap, uint16 flags)
Definition: pwm.c:167
static PWM_SIGNAL_s ecap_inputPwmSignal
Definition: pwm.c:88
bool PWM_IsEcapModuleInitialized(void)
Get initialization state of ecap module.
Definition: pwm.c:183
#define PWM_LOWER_THRESHOLD_PERM
Definition: pwm.c:66
static const int16_t pwm_kLinearOffset
Definition: pwm.c:86
PWM driver for the TMS570LC43xx.
float dutyCycle_perc
Definition: pwm.h:70
float frequency_Hz
Definition: pwm.h:71