1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
26 #include "mpc55xx.h"
\r
30 #if PWM_NOTIFICATION_SUPPORTED==STD_ON
\r
36 #if defined(CFG_MPC5604B)
\r
37 #define PWM_RUNTIME_CHANNEL_COUNT 56
\r
38 #define CHANNELS_OK (Channel <= PWM_MAX_CHANNEL-1)
\r
39 #elif defined(CFG_MPC5606B)
\r
40 #define PWM_RUNTIME_CHANNEL_COUNT 64
\r
41 #define CHANNELS_OK (Channel <= PWM_MAX_CHANNEL-1)
\r
42 #elif defined(CFG_MPC5606S)
\r
43 #define PWM_RUNTIME_CHANNEL_COUNT 48
\r
44 #define CHANNELS_OK (((Channel <= PWM_MAX_CHANNEL-1) && (Channel >= 40)) || ((Channel <= 23) && (Channel >= 16)))
\r
46 #define PWM_RUNTIME_CHANNEL_COUNT 16
\r
47 #define CHANNELS_OK (Channel < 16)
\r
50 const Pwm_ConfigType* PwmConfigPtr = NULL;
\r
53 PWM_STATE_UNINITIALIZED, PWM_STATE_INITIALIZED
\r
54 } Pwm_ModuleStateType;
\r
56 static Pwm_ModuleStateType Pwm_ModuleState = PWM_STATE_UNINITIALIZED;
\r
58 // Run-time variables
\r
60 #if PWM_NOTIFICATION_SUPPORTED==STD_ON
\r
61 Pwm_EdgeNotificationType NotificationState;
\r
63 } Pwm_ChannelStructType;
\r
65 // We use Pwm_ChannelType as index here
\r
66 Pwm_ChannelStructType ChannelRuntimeStruct[PWM_RUNTIME_CHANNEL_COUNT];
\r
69 /* Local functions */
\r
70 Std_ReturnType Pwm_ValidateInitialized(Pwm_APIServiceIDType apiId)
\r
72 Std_ReturnType result = E_OK;
\r
73 if( Pwm_ModuleState == PWM_STATE_UNINITIALIZED )
\r
75 #if PWM_DEV_ERROR_DETECT==STD_ON
\r
76 Det_ReportError(PWM_MODULE_ID,0, apiId,PWM_E_UNINIT);
\r
83 Std_ReturnType Pwm_ValidateChannel(Pwm_ChannelType Channel,Pwm_APIServiceIDType apiId)
\r
85 Std_ReturnType result = E_OK;
\r
88 #if PWM_DEV_ERROR_DETECT==STD_ON
\r
89 Det_ReportError(PWM_MODULE_ID,0, apiId,PWM_E_PARAM_CHANNEL);
\r
96 void Pwm_InitChannel(Pwm_ChannelType Channel);
\r
97 #if PWM_DE_INIT_API==STD_ON
\r
98 void Pwm_DeInitChannel(Pwm_ChannelType Channel);
\r
101 #if PWM_NOTIFICATION_SUPPORTED==STD_ON
\r
102 static void Pwm_Isr(void);
\r
105 static void calcPeriodTicksAndPrescaler(
\r
106 const Pwm_ChannelConfigurationType* channelConfig,
\r
107 uint16_t* ticks, Pwm_ChannelPrescalerType* prescaler) {
\r
109 uint32_t pre_global = 0;
\r
112 #if defined(CFG_MPC560X)
\r
113 Pwm_ChannelType channel = channelConfig->channel;
\r
115 if(channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
116 f_in = McuE_GetPeripheralClock( PERIPHERAL_CLOCK_EMIOS_0 );
\r
117 pre_global = EMIOS_0.MCR.B.GPRE;
\r
119 f_in = McuE_GetPeripheralClock( PERIPHERAL_CLOCK_EMIOS_1 );
\r
120 pre_global = EMIOS_1.MCR.B.GPRE;
\r
123 f_in = McuE_GetPeripheralClock( PERIPHERAL_CLOCK_EMIOS );
\r
124 pre_global = EMIOS.MCR.B.GPRE;
\r
127 uint32_t f_target = channelConfig->frequency;
\r
129 Pwm_ChannelPrescalerType pre;
\r
130 uint32_t ticks_temp;
\r
132 if (channelConfig->prescaler == PWM_CHANNEL_PRESCALER_AUTO) {
\r
133 // Go from lowest to highest prescaler
\r
134 for (pre = PWM_CHANNEL_PRESCALER_1; pre < PWM_CHANNEL_PRESCALER_4; ++pre) {
\r
135 ticks_temp = f_in / (f_target * (pre_global + 1) * (pre + 1)); // Calc ticks
\r
136 if (ticks_temp > 0xffff) {
\r
137 ticks_temp = 0xffff; // Prescaler too low
\r
139 break; // Prescaler ok
\r
143 pre = channelConfig->prescaler; // Use config setting
\r
144 ticks_temp = f_in / (f_target * pre_global * (pre+1)); // Calc ticks
\r
145 if (ticks_temp > 0xffff) {
\r
146 ticks_temp = 0xffff; // Prescaler too low
\r
150 (*ticks) = (uint16_t) ticks_temp;
\r
151 (*prescaler) = pre;
\r
155 static void configureChannel(const Pwm_ChannelConfigurationType* channelConfig){
\r
157 Pwm_ChannelType channel = channelConfig->channel;
\r
158 volatile struct EMIOS_tag *emiosHw;
\r
160 #if defined(CFG_MPC560X)
\r
161 if(channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
162 emiosHw = &EMIOS_0;
\r
164 emiosHw = &EMIOS_1;
\r
165 channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
171 #if defined (CFG_MPC560X)
\r
172 emiosHw->CH[channel].CCR.B.MODE = channelConfig->mode;
\r
173 emiosHw->CH[channel].CCR.B.DMA = 0;
\r
174 emiosHw->CH[channel].CCR.B.BSL = channelConfig->clksrc;
\r
175 emiosHw->CH[channel].CCR.B.ODIS = 0;
\r
177 emiosHw->CH[channel].CCR.B.MODE = PWM_EMIOS_OPWM;
\r
178 emiosHw->CH[channel].CCR.B.DMA = 0;
\r
179 emiosHw->CH[channel].CCR.B.BSL = 3;
\r
180 emiosHw->CH[channel].CCR.B.ODIS = 0;
\r
183 Pwm_ChannelPrescalerType prescaler; uint16_t period_ticks;
\r
184 calcPeriodTicksAndPrescaler( channelConfig, &period_ticks, &prescaler );
\r
186 emiosHw->CH[channel].CBDR.R = period_ticks;
\r
187 emiosHw->CH[channel].CCR.B.UCPRE = prescaler;
\r
188 #if defined (CFG_MPC560X)
\r
189 emiosHw->CH[channel].CCR.B.UCPEN = 1;
\r
191 emiosHw->CH[channel].CCR.B.UCPREN = 1;
\r
194 // 0 A match on comparator A clears the output flip-flop, while a match on comparator B sets it
\r
195 // 1 A match on comparator A sets the output flip-flop, while a match on comparator B clears it
\r
196 // A duty cycle of X % should give a signal with state 'channelConfig->polarity' during
\r
197 // X % of the period time.
\r
198 emiosHw->CH[channel].CCR.B.EDPOL = (channelConfig->polarity == PWM_LOW) ? 1 : 0;
\r
201 void Pwm_Init(const Pwm_ConfigType* ConfigPtr) {
\r
202 Pwm_ChannelType channel_iterator;
\r
206 if( Pwm_ModuleState == PWM_STATE_INITIALIZED ) {
\r
207 #if PWM_DEV_ERROR_DETECT==STD_ON
\r
208 Det_ReportError(PWM_MODULE_ID,0,PWM_INIT_ID,PWM_E_ALREADY_INITIALIZED);
\r
213 #if defined(CFG_MPC5606S) && !defined(CFG_MPC560XB)
\r
214 CGM.AC1_SC.R = 0x03000000; /* MPC56xxS: Select aux. set 1 clock to be FMPLL0 */
\r
215 CGM.AC2_SC.R = 0x03000000; /* MPC56xxS: Select aux. set 2 clock to be FMPLL0 */
\r
218 #if PWM_DEV_ERROR_DETECT==STD_ON
\r
220 * PWM046: If development error detection is enabled for the Pwm module,
\r
221 * the function Pwm_Init shall raise development error PWM_E_PARAM_CONFIG
\r
222 * if ConfigPtr is a null pointer.
\r
224 * PWM120: For pre-compile and link-time configuration variants, a NULL
\r
225 * pointer shall be passed to the initialization routine. In this case the
\r
226 * check for this NULL pointer has to be omitted.
\r
228 #if PWM_STATICALLY_CONFIGURED==STD_OFF
\r
229 if (ConfigPtr == NULL) {
\r
230 Det_ReportError(PWM_MODULE_ID,0,PWM_INIT_ID,PWM_E_PARAM_CONFIG);
\r
236 PwmConfigPtr = ConfigPtr;
\r
238 #if defined(CFG_MPC560X)
\r
239 /* Clock scaler uses system clock (~64MHz) as source, so prescaler 64 => 1MHz. */
\r
240 EMIOS_0.MCR.B.GPRE = PWM_PRESCALER_EMIOS_0 - 1;
\r
241 EMIOS_1.MCR.B.GPRE = PWM_PRESCALER_EMIOS_1 - 1;
\r
243 /* Enable eMIOS clock */
\r
244 EMIOS_0.MCR.B.GPREN = 1;
\r
245 EMIOS_1.MCR.B.GPREN = 1;
\r
247 /* Stop channels when in debug mode */
\r
248 EMIOS_0.MCR.B.FRZ = PWM_FREEZE_ENABLE;
\r
249 EMIOS_1.MCR.B.FRZ = PWM_FREEZE_ENABLE;
\r
251 /* Use global time base */
\r
252 EMIOS_0.MCR.B.GTBE = 1;
\r
253 EMIOS_1.MCR.B.GTBE = 1;
\r
255 /* Clock scaler uses system clock (~64MHz) as source, so prescaler 64 => 1MHz. */
\r
256 EMIOS.MCR.B.GPRE = PWM_PRESCALER - 1;
\r
258 /* Enable eMIOS clock */
\r
259 EMIOS.MCR.B.GPREN = 1;
\r
261 /* Stop channels when in debug mode */
\r
262 EMIOS.MCR.B.FRZ = PWM_FREEZE_ENABLE;
\r
264 /* Use global time base */
\r
265 EMIOS.MCR.B.GTBE = 1;
\r
268 Pwm_ModuleState = PWM_STATE_INITIALIZED;
\r
270 for (channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++) {
\r
271 const Pwm_ChannelConfigurationType* channelConfig = &ConfigPtr->Channels[channel_iterator];
\r
272 Pwm_ChannelType channel = channelConfig->channel;
\r
274 configureChannel( channelConfig );
\r
276 #if PWM_NOTIFICATION_SUPPORTED==STD_ON
\r
278 * PWM052: The function Pwm_Init shall disable all notifications.
\r
280 * This is now implemented in the configuration macro.
\r
282 // Pwm_DisableNotification(channel);
\r
285 #if defined(CFG_MPC560XB)
\r
290 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F0_F1),PWM_ISR_PRIORITY, 0);
\r
294 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F2_F3),PWM_ISR_PRIORITY, 0);
\r
298 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F4_F5),PWM_ISR_PRIORITY, 0);
\r
302 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F6_F7),PWM_ISR_PRIORITY, 0);
\r
306 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F8_F9),PWM_ISR_PRIORITY, 0);
\r
310 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F10_F11),PWM_ISR_PRIORITY, 0);
\r
314 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F12_F13),PWM_ISR_PRIORITY, 0);
\r
318 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F14_F15),PWM_ISR_PRIORITY, 0);
\r
322 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F16_F17),PWM_ISR_PRIORITY, 0);
\r
326 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F18_F19),PWM_ISR_PRIORITY, 0);
\r
330 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F20_F21),PWM_ISR_PRIORITY, 0);
\r
334 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F22_F23),PWM_ISR_PRIORITY, 0);
\r
338 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F24_F25),PWM_ISR_PRIORITY, 0);
\r
342 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F26_F27),PWM_ISR_PRIORITY, 0);
\r
346 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F0_F1),PWM_ISR_PRIORITY, 0);
\r
350 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F2_F3),PWM_ISR_PRIORITY, 0);
\r
354 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F4_F5),PWM_ISR_PRIORITY, 0);
\r
358 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F6_F7),PWM_ISR_PRIORITY, 0);
\r
362 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F8_F9),PWM_ISR_PRIORITY, 0);
\r
366 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F10_F11),PWM_ISR_PRIORITY, 0);
\r
370 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F12_F13),PWM_ISR_PRIORITY, 0);
\r
374 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F14_F15),PWM_ISR_PRIORITY, 0);
\r
378 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F16_F17),PWM_ISR_PRIORITY, 0);
\r
382 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F18_F19),PWM_ISR_PRIORITY, 0);
\r
386 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F20_F21),PWM_ISR_PRIORITY, 0);
\r
390 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F22_F23),PWM_ISR_PRIORITY, 0);
\r
394 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F24_F25),PWM_ISR_PRIORITY, 0);
\r
398 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F26_F27),PWM_ISR_PRIORITY, 0);
\r
403 #elif defined(CFG_MPC5606S)
\r
407 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F16_F17),PWM_ISR_PRIORITY, 0);
\r
410 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F16_F17),PWM_ISR_PRIORITY, 0);
\r
413 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F18_F19),PWM_ISR_PRIORITY, 0);
\r
416 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F18_F19),PWM_ISR_PRIORITY, 0);
\r
419 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F20_F21),PWM_ISR_PRIORITY, 0);
\r
422 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F20_F21),PWM_ISR_PRIORITY, 0);
\r
425 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F22_F23),PWM_ISR_PRIORITY, 0);
\r
428 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F22_F23),PWM_ISR_PRIORITY, 0);
\r
431 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F16_F17),PWM_ISR_PRIORITY, 0);
\r
434 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F16_F17),PWM_ISR_PRIORITY, 0);
\r
437 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F18_F19),PWM_ISR_PRIORITY, 0);
\r
440 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F18_F19),PWM_ISR_PRIORITY, 0);
\r
443 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F20_F21),PWM_ISR_PRIORITY, 0);
\r
446 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F20_F21),PWM_ISR_PRIORITY, 0);
\r
449 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F22_F23),PWM_ISR_PRIORITY, 0);
\r
452 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F22_F23),PWM_ISR_PRIORITY, 0);
\r
461 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F0),PWM_ISR_PRIORITY, 0);
\r
464 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F1),PWM_ISR_PRIORITY, 0);
\r
467 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F2),PWM_ISR_PRIORITY, 0);
\r
470 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F3),PWM_ISR_PRIORITY, 0);
\r
473 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F4),PWM_ISR_PRIORITY, 0);
\r
476 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F5),PWM_ISR_PRIORITY, 0);
\r
479 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F6),PWM_ISR_PRIORITY, 0);
\r
482 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F7),PWM_ISR_PRIORITY, 0);
\r
485 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F8),PWM_ISR_PRIORITY, 0);
\r
488 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F9),PWM_ISR_PRIORITY, 0);
\r
491 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F10),PWM_ISR_PRIORITY, 0);
\r
494 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F11),PWM_ISR_PRIORITY, 0);
\r
497 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F12),PWM_ISR_PRIORITY, 0);
\r
500 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F13),PWM_ISR_PRIORITY, 0);
\r
503 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F14),PWM_ISR_PRIORITY, 0);
\r
506 ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F15),PWM_ISR_PRIORITY, 0);
\r
517 #if PWM_DE_INIT_API==STD_ON
\r
519 void inline Pwm_DeInitChannel(Pwm_ChannelType Channel) {
\r
520 Pwm_SetOutputToIdle(Channel);
\r
522 #if defined(CFG_MPC5516)
\r
523 // Set the disable bit for this channel
\r
524 EMIOS.UCDIS.R |= (1 << (31 - Channel));
\r
525 #elif defined(CFG_MPC560X)
\r
526 // Set the disable bit for this channel
\r
527 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1)
\r
529 EMIOS_0.UCDIS.R |= (1 << (Channel));
\r
533 EMIOS_1.UCDIS.R |= (1 << (Channel-PWM_NUMBER_OF_EACH_EMIOS));
\r
538 * PWM052: The function Pwm_DeInit shall disable all notifications.
\r
540 #if PWM_NOTIFICATION_SUPPORTED==STD_ON
\r
541 Pwm_DisableNotification(Channel);
\r
545 void Pwm_DeInit() {
\r
546 Pwm_ChannelType channel_iterator;
\r
548 if(E_OK != Pwm_ValidateInitialized(PWM_DEINIT_ID))
\r
553 for (channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++) {
\r
554 Pwm_ChannelType channel = PwmConfigPtr->Channels[channel_iterator].channel;
\r
555 Pwm_DeInitChannel(channel);
\r
559 #if defined(CFG_MPC5516) || defined(CFG_MPC5567)
\r
560 EMIOS.MCR.B.MDIS = 1;
\r
561 #elif defined(CFG_MPC560X)
\r
562 EMIOS_0.MCR.B.MDIS = 1;
\r
563 EMIOS_1.MCR.B.MDIS = 1;
\r
566 Pwm_ModuleState = PWM_STATE_UNINITIALIZED;
\r
572 * PWM083: The function Pwm_SetPeriodAndDuty shall be pre compile time
\r
573 * changeable ON/OFF by the configuration parameter PwmSetPeriodAndDuty.
\r
575 #if PWM_SET_PERIOD_AND_DUTY_API==STD_ON
\r
576 void Pwm_SetPeriodAndDuty(Pwm_ChannelType Channel, Pwm_PeriodType Period,
\r
577 Pwm_DutyCycleType DutyCycle) {
\r
579 if ((E_OK != Pwm_ValidateInitialized(PWM_SETPERIODANDDUTY_ID)) ||
\r
580 (E_OK != Pwm_ValidateChannel(Channel, PWM_SETPERIODANDDUTY_ID)))
\r
585 for (Pwm_ChannelType channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++)
\r
587 if(Channel == PwmConfigPtr->Channels[channel_iterator].channel){
\r
588 if(PwmConfigPtr->ChannelClass[channel_iterator] != PWM_VARIABLE_PERIOD){
\r
589 #if PWM_DEV_ERROR_DETECT==STD_ON
\r
590 Det_ReportError(PWM_MODULE_ID,0, PWM_SETPERIODANDDUTY_ID, PWM_E_PERIOD_UNCHANGEABLE);
\r
598 volatile struct EMIOS_tag *emiosHw;
\r
599 #if defined(CFG_MPC560X)
\r
600 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
601 emiosHw = &EMIOS_0;
\r
603 emiosHw = &EMIOS_1;
\r
604 Channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
610 uint16 leading_edge_position = (uint16) (((uint32) Period * (uint32) DutyCycle) >> 15);
\r
612 /* Timer instant for leading edge */
\r
613 emiosHw->CH[Channel].CADR.R = leading_edge_position;
\r
615 /* Timer instant for the period to restart */
\r
616 emiosHw->CH[Channel].CBDR.R = Period;
\r
622 * PWM013: The function Pwm_SetDutyCycle shall set the duty cycle of the PWM
\r
625 * @param Channel PWM channel to use. 0 <= Channel < PWM_NUMBER_OF_CHANNELS <= 16
\r
626 * @param DutyCycle 0 <= DutyCycle <= 0x8000
\r
628 #if PWM_SET_DUTY_CYCLE_API==STD_ON
\r
629 void Pwm_SetDutyCycle(Pwm_ChannelType Channel, Pwm_DutyCycleType DutyCycle)
\r
631 if ((E_OK != Pwm_ValidateInitialized(PWM_SETDUTYCYCLE_ID)) ||
\r
632 (E_OK != Pwm_ValidateChannel(Channel, PWM_SETDUTYCYCLE_ID)))
\r
636 volatile struct EMIOS_tag *emiosHw;
\r
637 #if defined(CFG_MPC560X)
\r
638 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
639 emiosHw = &EMIOS_0;
\r
641 emiosHw = &EMIOS_1;
\r
642 Channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
648 uint16 leading_edge_position = (uint16) ((emiosHw->CH[Channel].CBDR.R
\r
649 * (uint32) DutyCycle) >> 15);
\r
651 /* Timer instant for leading edge */
\r
654 * PWM017: The function Pwm_SetDutyCycle shall update the duty cycle at
\r
655 * the end of the period if supported by the implementation and configured
\r
656 * with PwmDutycycleUpdatedEndperiod. [ This is achieved in hardware since
\r
657 * the A and B registers are double buffered ]
\r
659 * PWM014: The function Pwm_SetDutyCycle shall set the output state according
\r
660 * to the configured polarity parameter [which is already set from
\r
661 * Pwm_InitChannel], when the duty parameter is 0% [=0] or 100% [=0x8000].
\r
663 emiosHw->CH[Channel].CADR.R = leading_edge_position;
\r
667 #if PWM_SET_OUTPUT_TO_IDLE_API == STD_ON
\r
668 void Pwm_SetOutputToIdle(Pwm_ChannelType Channel)
\r
670 if ((E_OK != Pwm_ValidateInitialized(PWM_SETOUTPUTTOIDLE_ID)) ||
\r
671 (E_OK != Pwm_ValidateChannel(Channel, PWM_SETOUTPUTTOIDLE_ID)))
\r
675 volatile struct EMIOS_tag *emiosHw;
\r
676 #if defined(CFG_MPC560X)
\r
677 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
678 emiosHw = &EMIOS_0;
\r
680 emiosHw = &EMIOS_1;
\r
681 Channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
687 emiosHw->CH[Channel].CADR.R = 0;
\r
691 * PWM085: The function Pwm_GetOutputState shall be pre compile configurable
\r
692 * ON/OFF by the configuration parameter PwmGetOutputState
\r
694 #if PWM_GET_OUTPUT_STATE_API==STD_ON
\r
696 * PWM022: The function Pwm_GetOutputState shall read the internal state
\r
697 * of the PWM output signal and return it.
\r
699 Pwm_OutputStateType Pwm_GetOutputState(Pwm_ChannelType Channel)
\r
701 if ((E_OK != Pwm_ValidateInitialized(PWM_GETOUTPUTSTATE_ID)) ||
\r
702 (E_OK != Pwm_ValidateChannel(Channel, PWM_GETOUTPUTSTATE_ID)))
\r
707 volatile struct EMIOS_tag *emiosHw;
\r
708 #if defined(CFG_MPC560X)
\r
709 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
710 emiosHw = &EMIOS_0;
\r
712 emiosHw = &EMIOS_1;
\r
713 Channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
719 return (Pwm_OutputStateType)emiosHw->CH[Channel].CSR.B.UCOUT;
\r
723 #if PWM_NOTIFICATION_SUPPORTED==STD_ON
\r
725 void Pwm_DisableNotification(Pwm_ChannelType Channel)
\r
727 if ((E_OK != Pwm_ValidateInitialized(PWM_DISABLENOTIFICATION_ID)) ||
\r
728 (E_OK != Pwm_ValidateChannel(Channel, PWM_DISABLENOTIFICATION_ID)))
\r
733 volatile struct EMIOS_tag *emiosHw;
\r
734 #if defined(CFG_MPC560X)
\r
735 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
736 emiosHw = &EMIOS_0;
\r
738 emiosHw = &EMIOS_1;
\r
739 Channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
745 // Disable flags on this channel
\r
746 emiosHw->CH[Channel].CCR.B.FEN = 0;
\r
749 void Pwm_EnableNotification(Pwm_ChannelType Channel,Pwm_EdgeNotificationType Notification)
\r
751 if ((E_OK != Pwm_ValidateInitialized(PWM_ENABLENOTIFICATION_ID)) ||
\r
752 (E_OK != Pwm_ValidateChannel(Channel, PWM_ENABLENOTIFICATION_ID)))
\r
757 volatile struct EMIOS_tag *emiosHw;
\r
758 #if defined(CFG_MPC560X)
\r
759 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {
\r
760 emiosHw = &EMIOS_0;
\r
762 emiosHw = &EMIOS_1;
\r
763 Channel -= PWM_NUMBER_OF_EACH_EMIOS;
\r
769 ChannelRuntimeStruct[Channel].NotificationState = Notification;
\r
771 emiosHw->CH[Channel].CCR.B.FEN = 1;
\r
774 static void Pwm_Isr(void)
\r
776 // Find out which channel that triggered the interrupt
\r
777 #if defined (CFG_MPC5516)
\r
778 uint32_t flagmask = EMIOS.GFLAG.R;
\r
779 #elif defined(CFG_MPC5567)
\r
780 uint32_t flagmask = EMIOS.GFR.R;
\r
783 #if defined(CFG_MPC5516) || defined(CFG_MPC5567)
\r
784 // There are 24 channels specified in the global flag register, but
\r
785 // we only listen to the first 16 as only these support OPWfM
\r
786 for (Pwm_ChannelType channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++)
\r
788 Pwm_ChannelType emios_ch = PwmConfigPtr->Channels[channel_iterator].channel;
\r
790 if (flagmask & (1 << emios_ch))
\r
792 if (PwmConfigPtr->NotificationHandlers[channel_iterator] != NULL && EMIOS.CH[emios_ch].CCR.B.FEN)
\r
794 Pwm_EdgeNotificationType notification = ChannelRuntimeStruct[emios_ch].NotificationState;
\r
795 if (notification == PWM_BOTH_EDGES ||
\r
797 notification == EMIOS.CH[emios_ch].CSR.B.UCOUT)
\r
799 PwmConfigPtr->NotificationHandlers[channel_iterator]();
\r
804 EMIOS.CH[emios_ch].CSR.B.FLAG = 1;
\r
807 #elif defined(CFG_MPC560X)
\r
808 uint32_t flagmask_0 = EMIOS_0.GFR.R;
\r
809 uint32_t flagmask_1 = EMIOS_1.GFR.R;
\r
811 for (Pwm_ChannelType channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++)
\r
814 Pwm_ChannelType emios_ch = PwmConfigPtr->Channels[channel_iterator].channel;
\r
816 if (flagmask_0 & (1 << emios_ch))
\r
818 if (PwmConfigPtr->NotificationHandlers[channel_iterator] != NULL && EMIOS_0.CH[emios_ch].CCR.B.FEN)
\r
820 Pwm_EdgeNotificationType notification = ChannelRuntimeStruct[emios_ch].NotificationState;
\r
821 if (notification == PWM_BOTH_EDGES ||
\r
823 notification == EMIOS_0.CH[emios_ch].CSR.B.UCOUT)
\r
825 PwmConfigPtr->NotificationHandlers[channel_iterator]();
\r
830 EMIOS_0.CH[emios_ch].CSR.B.FLAG = 1;
\r
832 else if (flagmask_1 & (1 << emios_ch - PWM_NUMBER_OF_EACH_EMIOS ))
\r
834 if (PwmConfigPtr->NotificationHandlers[channel_iterator] != NULL && EMIOS_1.CH[emios_ch - PWM_NUMBER_OF_EACH_EMIOS].CCR.B.FEN)
\r
836 Pwm_EdgeNotificationType notification = ChannelRuntimeStruct[emios_ch].NotificationState;
\r
837 if (notification == PWM_BOTH_EDGES ||
\r
838 notification == EMIOS_1.CH[emios_ch - PWM_NUMBER_OF_EACH_EMIOS].CSR.B.UCOUT)
\r
840 PwmConfigPtr->NotificationHandlers[channel_iterator]();
\r
845 EMIOS_1.CH[emios_ch - PWM_NUMBER_OF_EACH_EMIOS].CSR.B.FLAG = 1;
\r
852 #endif /* PWM_NOTIFICATION_SUPPORED == STD_ON */
\r