]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Pwm.c
Re-added generic callout stubs file for Dcm (with make rule).
[arc.git] / arch / ppc / mpc55xx / drivers / Pwm.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\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
9  *\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
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 \r
18 \r
19 #include <assert.h>\r
20 #include <string.h>\r
21 \r
22 #include "Pwm.h"\r
23 #include "MemMap.h"\r
24 #include "Det.h"\r
25 \r
26 #include "mpc55xx.h"\r
27 \r
28 #include "Os.h"\r
29 #include "Mcu.h"\r
30 #if PWM_NOTIFICATION_SUPPORTED==STD_ON\r
31 #include "isr.h"\r
32 #include "irq.h"\r
33 #include "arc.h"\r
34 #endif\r
35 \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_MPC5606S)\r
40         #define PWM_RUNTIME_CHANNEL_COUNT       48\r
41     #define CHANNELS_OK (((Channel <= PWM_MAX_CHANNEL-1) && (Channel >= 40)) || ((Channel <= 23) && (Channel >= 16)))\r
42 #else\r
43         #define PWM_RUNTIME_CHANNEL_COUNT       16\r
44         #define CHANNELS_OK (Channel < 16)\r
45 #endif\r
46 \r
47 const Pwm_ConfigType* PwmConfigPtr = NULL;\r
48 \r
49 typedef enum {\r
50         PWM_STATE_UNINITIALIZED, PWM_STATE_INITIALIZED\r
51 } Pwm_ModuleStateType;\r
52 \r
53 static Pwm_ModuleStateType Pwm_ModuleState = PWM_STATE_UNINITIALIZED;\r
54 \r
55 // Run-time variables\r
56 typedef struct {\r
57         #if PWM_NOTIFICATION_SUPPORTED==STD_ON\r
58                 Pwm_EdgeNotificationType NotificationState;\r
59         #endif\r
60 } Pwm_ChannelStructType;\r
61 \r
62 // We use Pwm_ChannelType as index here\r
63 Pwm_ChannelStructType ChannelRuntimeStruct[PWM_RUNTIME_CHANNEL_COUNT];\r
64 \r
65 \r
66 /* Local functions */\r
67 Std_ReturnType Pwm_ValidateInitialized(Pwm_APIServiceIDType apiId)\r
68 {\r
69         Std_ReturnType result = E_OK;\r
70     if( Pwm_ModuleState == PWM_STATE_UNINITIALIZED )\r
71     {\r
72 #if PWM_DEV_ERROR_DETECT==STD_ON\r
73         Det_ReportError(PWM_MODULE_ID,0, apiId,PWM_E_UNINIT);\r
74         result = E_NOT_OK;\r
75 #endif\r
76     }\r
77     return result;\r
78 }\r
79 \r
80 Std_ReturnType Pwm_ValidateChannel(Pwm_ChannelType Channel,Pwm_APIServiceIDType apiId)\r
81 {\r
82         Std_ReturnType result = E_OK;\r
83     if( !CHANNELS_OK  )\r
84     {\r
85 #if PWM_DEV_ERROR_DETECT==STD_ON\r
86         Det_ReportError(PWM_MODULE_ID,0, apiId,PWM_E_PARAM_CHANNEL);\r
87         result = E_NOT_OK;\r
88 #endif\r
89     }\r
90     return result;\r
91 }\r
92 \r
93 void Pwm_InitChannel(Pwm_ChannelType Channel);\r
94 #if PWM_DE_INIT_API==STD_ON\r
95 void Pwm_DeInitChannel(Pwm_ChannelType Channel);\r
96 #endif\r
97 \r
98 #if PWM_NOTIFICATION_SUPPORTED==STD_ON\r
99 static void Pwm_Isr(void);\r
100 #endif\r
101 \r
102 static void calcPeriodTicksAndPrescaler(\r
103                                 const Pwm_ChannelConfigurationType* channelConfig,\r
104                                 uint16_t* ticks, Pwm_ChannelPrescalerType* prescaler) {\r
105 \r
106         uint32_t pre_global = 0;\r
107         uint32_t f_in = 0;\r
108 \r
109 #if defined(CFG_MPC560X)\r
110         Pwm_ChannelType channel = channelConfig->channel;\r
111 \r
112         if(channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
113                 f_in = McuE_GetPeripheralClock( PERIPHERAL_CLOCK_EMIOS_0 );\r
114                 pre_global = EMIOS_0.MCR.B.GPRE;\r
115         } else {\r
116                 f_in = McuE_GetPeripheralClock( PERIPHERAL_CLOCK_EMIOS_1 );\r
117                 pre_global = EMIOS_1.MCR.B.GPRE;\r
118         }\r
119 #else\r
120         f_in = McuE_GetPeripheralClock( PERIPHERAL_CLOCK_EMIOS );\r
121         pre_global = EMIOS.MCR.B.GPRE;\r
122 #endif\r
123 \r
124   uint32_t f_target = channelConfig->frequency;\r
125 \r
126   Pwm_ChannelPrescalerType pre;\r
127   uint32_t ticks_temp;\r
128 \r
129   if (channelConfig->prescaler == PWM_CHANNEL_PRESCALER_AUTO) {\r
130     // Go from lowest to highest prescaler\r
131     for (pre = PWM_CHANNEL_PRESCALER_1; pre < PWM_CHANNEL_PRESCALER_4; ++pre) {\r
132       ticks_temp = f_in / (f_target * (pre_global + 1) * (pre + 1)); // Calc ticks\r
133       if (ticks_temp > 0xffff) {\r
134         ticks_temp = 0xffff;  // Prescaler too low\r
135       } else {\r
136         break;                // Prescaler ok\r
137       }\r
138     }\r
139   } else {\r
140     pre = channelConfig->prescaler; // Use config setting\r
141     ticks_temp = f_in / (f_target * pre_global * (pre+1)); // Calc ticks\r
142     if (ticks_temp > 0xffff) {\r
143       ticks_temp = 0xffff;  // Prescaler too low\r
144     }\r
145   }\r
146 \r
147   (*ticks) = (uint16_t) ticks_temp;\r
148   (*prescaler) = pre;\r
149 }\r
150 \r
151 \r
152 static void configureChannel(const Pwm_ChannelConfigurationType* channelConfig){\r
153 \r
154         Pwm_ChannelType channel = channelConfig->channel;\r
155         volatile struct EMIOS_tag *emiosHw;\r
156 \r
157 #if defined(CFG_MPC560X)\r
158         if(channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
159                 emiosHw = &EMIOS_0;\r
160         } else {\r
161                 emiosHw = &EMIOS_1;\r
162                 channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
163         }\r
164 #else\r
165         emiosHw = &EMIOS;\r
166 #endif\r
167 \r
168 #if defined (CFG_MPC560X)\r
169         emiosHw->CH[channel].CCR.B.MODE = channelConfig->mode;\r
170         emiosHw->CH[channel].CCR.B.DMA = 0;\r
171         emiosHw->CH[channel].CCR.B.BSL = channelConfig->clksrc;\r
172         emiosHw->CH[channel].CCR.B.ODIS = 0;\r
173 #else\r
174         emiosHw->CH[channel].CCR.B.MODE = PWM_EMIOS_OPWM;\r
175         emiosHw->CH[channel].CCR.B.DMA = 0;\r
176         emiosHw->CH[channel].CCR.B.BSL = 3;\r
177         emiosHw->CH[channel].CCR.B.ODIS = 0;\r
178 #endif\r
179 \r
180         Pwm_ChannelPrescalerType prescaler;  uint16_t period_ticks;\r
181         calcPeriodTicksAndPrescaler( channelConfig, &period_ticks, &prescaler );\r
182 \r
183         emiosHw->CH[channel].CBDR.R = period_ticks;\r
184         emiosHw->CH[channel].CCR.B.UCPRE = prescaler;\r
185 #if defined (CFG_MPC560X)\r
186         emiosHw->CH[channel].CCR.B.UCPEN = 1;\r
187 #else\r
188         emiosHw->CH[channel].CCR.B.UCPREN = 1;\r
189 #endif\r
190 \r
191         // 0 A match on comparator A clears the output flip-flop, while a match on comparator B sets it\r
192         // 1 A match on comparator A sets the output flip-flop, while a match on comparator B clears it\r
193         // A duty cycle of X % should give a signal with state 'channelConfig->polarity' during\r
194         // X % of the period time.\r
195         emiosHw->CH[channel].CCR.B.EDPOL = (channelConfig->polarity == PWM_LOW) ? 1 : 0;\r
196 }\r
197 \r
198 void Pwm_Init(const Pwm_ConfigType* ConfigPtr) {\r
199     Pwm_ChannelType channel_iterator;\r
200 \r
201     /** @req PWM118 */\r
202     /** @req PWM121 */\r
203     if( Pwm_ModuleState == PWM_STATE_INITIALIZED ) {\r
204 #if PWM_DEV_ERROR_DETECT==STD_ON\r
205         Det_ReportError(PWM_MODULE_ID,0,PWM_INIT_ID,PWM_E_ALREADY_INITIALIZED);\r
206 #endif\r
207         return;\r
208     }\r
209 \r
210     #if defined(CFG_MPC5606S) && !defined(CFG_MPC5604B)\r
211                 CGM.AC1_SC.R = 0x03000000; /* MPC56xxS: Select aux. set 1 clock to be FMPLL0 */\r
212                 CGM.AC2_SC.R = 0x03000000; /* MPC56xxS: Select aux. set 2 clock to be FMPLL0 */\r
213         #endif\r
214         \r
215     #if PWM_DEV_ERROR_DETECT==STD_ON\r
216         /*\r
217          * PWM046: If development error detection is enabled for the Pwm module,\r
218          * the function Pwm_Init shall raise development error PWM_E_PARAM_CONFIG\r
219          * if ConfigPtr is a null pointer.\r
220          *\r
221          * PWM120: For pre-compile and link-time configuration variants, a NULL\r
222          * pointer shall be passed to the initialization routine. In this case the\r
223          * check for this NULL pointer has to be omitted.\r
224          */\r
225         #if PWM_STATICALLY_CONFIGURED==STD_OFF\r
226             if (ConfigPtr == NULL) {\r
227                 Det_ReportError(PWM_MODULE_ID,0,PWM_INIT_ID,PWM_E_PARAM_CONFIG);\r
228                 return;\r
229             }\r
230         #endif\r
231     #endif\r
232 \r
233     PwmConfigPtr = ConfigPtr;\r
234 \r
235         #if defined(CFG_MPC560X)\r
236                 /* Clock scaler uses system clock (~64MHz) as source, so prescaler 64 => 1MHz. */\r
237                 EMIOS_0.MCR.B.GPRE = PWM_PRESCALER_EMIOS_0 - 1;\r
238                 EMIOS_1.MCR.B.GPRE = PWM_PRESCALER_EMIOS_1 - 1;\r
239 \r
240                 /* Enable eMIOS clock */\r
241                 EMIOS_0.MCR.B.GPREN = 1;\r
242                 EMIOS_1.MCR.B.GPREN = 1;\r
243 \r
244                 /* Stop channels when in debug mode */\r
245                 EMIOS_0.MCR.B.FRZ = PWM_FREEZE_ENABLE;\r
246                 EMIOS_1.MCR.B.FRZ = PWM_FREEZE_ENABLE;\r
247 \r
248                 /* Use global time base */\r
249                 EMIOS_0.MCR.B.GTBE = 1;\r
250                 EMIOS_1.MCR.B.GTBE = 1;\r
251         #else\r
252                 /* Clock scaler uses system clock (~64MHz) as source, so prescaler 64 => 1MHz. */\r
253                 EMIOS.MCR.B.GPRE = PWM_PRESCALER - 1;\r
254 \r
255                 /* Enable eMIOS clock */\r
256                 EMIOS.MCR.B.GPREN = 1;\r
257 \r
258                 /* Stop channels when in debug mode */\r
259                 EMIOS.MCR.B.FRZ = PWM_FREEZE_ENABLE;\r
260 \r
261                 /* Use global time base */\r
262                 EMIOS.MCR.B.GTBE = 1;\r
263         #endif\r
264 \r
265     Pwm_ModuleState = PWM_STATE_INITIALIZED;\r
266 \r
267     for (channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++) {\r
268         const Pwm_ChannelConfigurationType* channelConfig = &ConfigPtr->Channels[channel_iterator];\r
269         Pwm_ChannelType channel = channelConfig->channel;\r
270 \r
271         configureChannel( channelConfig );\r
272 \r
273         #if PWM_NOTIFICATION_SUPPORTED==STD_ON\r
274                 /*\r
275                  * PWM052: The function Pwm_Init shall disable all notifications.\r
276                  *\r
277                  * This is now implemented in the configuration macro.\r
278                  */\r
279                 // Pwm_DisableNotification(channel);\r
280 \r
281                 // Install ISR\r
282                         #if defined(CFG_MPC5604B)\r
283                                 switch(channel)\r
284                                 {\r
285                                 case 0:\r
286                                 case 1:\r
287                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F0_F1),PWM_ISR_PRIORITY, 0);\r
288                                         break;\r
289                                 case 2:\r
290                                 case 3:\r
291                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F2_F3),PWM_ISR_PRIORITY, 0);\r
292                                         break;\r
293                                 case 4:\r
294                                 case 5:\r
295                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F4_F5),PWM_ISR_PRIORITY, 0);\r
296                                         break;\r
297                                 case 6:\r
298                                 case 7:\r
299                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F6_F7),PWM_ISR_PRIORITY, 0);\r
300                                         break;\r
301                                 case 8:\r
302                                 case 9:\r
303                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F8_F9),PWM_ISR_PRIORITY, 0);\r
304                                         break;\r
305                                 case 10:\r
306                                 case 11:\r
307                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F10_F11),PWM_ISR_PRIORITY, 0);\r
308                                         break;\r
309                                 case 12:\r
310                                 case 13:\r
311                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F12_F13),PWM_ISR_PRIORITY, 0);\r
312                                         break;\r
313                                 case 14:\r
314                                 case 15:\r
315                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F14_F15),PWM_ISR_PRIORITY, 0);\r
316                                         break;\r
317                                 case 16:\r
318                                 case 17:\r
319                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F16_F17),PWM_ISR_PRIORITY, 0);\r
320                                         break;\r
321                                 case 18:\r
322                                 case 19:\r
323                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F18_F19),PWM_ISR_PRIORITY, 0);\r
324                                         break;\r
325                                 case 20:\r
326                                 case 21:\r
327                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F20_F21),PWM_ISR_PRIORITY, 0);\r
328                                         break;\r
329                                 case 22:\r
330                                 case 23:\r
331                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F22_F23),PWM_ISR_PRIORITY, 0);\r
332                                         break;\r
333                                 case 24:\r
334                                 case 25:\r
335                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F24_F25),PWM_ISR_PRIORITY, 0);\r
336                                         break;\r
337                                 case 26:\r
338                                 case 27:\r
339                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F26_F27),PWM_ISR_PRIORITY, 0);\r
340                                         break;\r
341                                 case 28:\r
342                                 case 29:\r
343                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F0_F1),PWM_ISR_PRIORITY, 0);\r
344                                         break;\r
345                                 case 30:\r
346                                 case 31:\r
347                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F2_F3),PWM_ISR_PRIORITY, 0);\r
348                                         break;\r
349                                 case 32:\r
350                                 case 33:\r
351                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F4_F5),PWM_ISR_PRIORITY, 0);\r
352                                         break;\r
353                                 case 34:\r
354                                 case 35:\r
355                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F6_F7),PWM_ISR_PRIORITY, 0);\r
356                                         break;\r
357                                 case 36:\r
358                                 case 37:\r
359                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F8_F9),PWM_ISR_PRIORITY, 0);\r
360                                         break;\r
361                                 case 38:\r
362                                 case 39:\r
363                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F10_F11),PWM_ISR_PRIORITY, 0);\r
364                                         break;\r
365                                 case 40:\r
366                                 case 41:\r
367                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F12_F13),PWM_ISR_PRIORITY, 0);\r
368                                         break;\r
369                                 case 42:\r
370                                 case 43:\r
371                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F14_F15),PWM_ISR_PRIORITY, 0);\r
372                                         break;\r
373                                 case 44:\r
374                                 case 45:\r
375                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F16_F17),PWM_ISR_PRIORITY, 0);\r
376                                         break;\r
377                                 case 46:\r
378                                 case 47:\r
379                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F18_F19),PWM_ISR_PRIORITY, 0);\r
380                                         break;\r
381                                 case 48:\r
382                                 case 49:\r
383                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F20_F21),PWM_ISR_PRIORITY, 0);\r
384                                         break;\r
385                                 case 50:\r
386                                 case 51:\r
387                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F22_F23),PWM_ISR_PRIORITY, 0);\r
388                                         break;\r
389                                 case 52:\r
390                                 case 53:\r
391                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F24_F25),PWM_ISR_PRIORITY, 0);\r
392                                         break;\r
393                                 case 54:\r
394                                 case 55:\r
395                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F26_F27),PWM_ISR_PRIORITY, 0);\r
396                                         break;\r
397                                 default:\r
398                                         break;\r
399                                 }\r
400                         #elif defined(CFG_MPC5606S)\r
401                                 switch(channel)\r
402                                 {\r
403                                 case 16:\r
404                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F16_F17),PWM_ISR_PRIORITY, 0);\r
405                                         break;\r
406                                 case 17:\r
407                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F16_F17),PWM_ISR_PRIORITY, 0);\r
408                             break;\r
409                                 case 18:\r
410                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F18_F19),PWM_ISR_PRIORITY, 0);\r
411                                         break;\r
412                                 case 19:\r
413                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F18_F19),PWM_ISR_PRIORITY, 0);\r
414                             break;\r
415                                 case 20:\r
416                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F20_F21),PWM_ISR_PRIORITY, 0);\r
417                                         break;\r
418                                 case 21:\r
419                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F20_F21),PWM_ISR_PRIORITY, 0);\r
420                             break;\r
421                                 case 22:\r
422                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F22_F23),PWM_ISR_PRIORITY, 0);\r
423                                         break;\r
424                                 case 23:\r
425                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_0_GFR_F22_F23),PWM_ISR_PRIORITY, 0);\r
426                             break;\r
427                                 case 40:\r
428                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F16_F17),PWM_ISR_PRIORITY, 0);\r
429                                         break;\r
430                                 case 41:\r
431                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F16_F17),PWM_ISR_PRIORITY, 0);\r
432                             break;\r
433                                 case 42:\r
434                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F18_F19),PWM_ISR_PRIORITY, 0);\r
435                                         break;\r
436                                 case 43:\r
437                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F18_F19),PWM_ISR_PRIORITY, 0);\r
438                             break;\r
439                                 case 44:\r
440                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F20_F21),PWM_ISR_PRIORITY, 0);\r
441                                         break;\r
442                                 case 45:\r
443                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F20_F21),PWM_ISR_PRIORITY, 0);\r
444                             break;\r
445                                 case 46:\r
446                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F22_F23),PWM_ISR_PRIORITY, 0);\r
447                                         break;\r
448                                 case 47:\r
449                                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMIOS_1_GFR_F22_F23),PWM_ISR_PRIORITY, 0);\r
450                             break;\r
451                                 default:\r
452                                         break;\r
453                             }\r
454                         #else\r
455                                 switch(channel)\r
456                                 {\r
457                                 case 0:\r
458                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F0),PWM_ISR_PRIORITY, 0);\r
459                                         break;\r
460                                 case 1:\r
461                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F1),PWM_ISR_PRIORITY, 0);\r
462                                         break;\r
463                                 case 2:\r
464                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F2),PWM_ISR_PRIORITY, 0);\r
465                                         break;\r
466                                 case 3:\r
467                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F3),PWM_ISR_PRIORITY, 0);\r
468                                         break;\r
469                                 case 4:\r
470                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F4),PWM_ISR_PRIORITY, 0);\r
471                                         break;\r
472                                 case 5:\r
473                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F5),PWM_ISR_PRIORITY, 0);\r
474                                         break;\r
475                                 case 6:\r
476                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F6),PWM_ISR_PRIORITY, 0);\r
477                                         break;\r
478                                 case 7:\r
479                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F7),PWM_ISR_PRIORITY, 0);\r
480                                         break;\r
481                                 case 8:\r
482                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F8),PWM_ISR_PRIORITY, 0);\r
483                                         break;\r
484                                 case 9:\r
485                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F9),PWM_ISR_PRIORITY, 0);\r
486                                         break;\r
487                                 case 10:\r
488                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F10),PWM_ISR_PRIORITY, 0);\r
489                                         break;\r
490                                 case 11:\r
491                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F11),PWM_ISR_PRIORITY, 0);\r
492                                         break;\r
493                                 case 12:\r
494                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F12),PWM_ISR_PRIORITY, 0);\r
495                                         break;\r
496                                 case 13:\r
497                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F13),PWM_ISR_PRIORITY, 0);\r
498                                         break;\r
499                                 case 14:\r
500                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F14),PWM_ISR_PRIORITY, 0);\r
501                                         break;\r
502                                 case 15:\r
503                         ISR_INSTALL_ISR2("PwmIsr", Pwm_Isr, (IrqType)(EMISOS200_FLAG_F15),PWM_ISR_PRIORITY, 0);\r
504                                         break;\r
505                                 default:\r
506                                         break;\r
507                             }\r
508                 #endif\r
509 \r
510                 #endif\r
511     }\r
512 }\r
513 \r
514 #if PWM_DE_INIT_API==STD_ON\r
515 \r
516 void inline Pwm_DeInitChannel(Pwm_ChannelType Channel) {\r
517     Pwm_SetOutputToIdle(Channel);\r
518 \r
519         #if defined(CFG_MPC5516)\r
520         // Set the disable bit for this channel\r
521         EMIOS.UCDIS.R |= (1 << (31 - Channel));\r
522     #elif defined(CFG_MPC560X)\r
523         // Set the disable bit for this channel\r
524         if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1)\r
525         {\r
526                 EMIOS_0.UCDIS.R |= (1 << (Channel));\r
527         }\r
528         else\r
529         {\r
530                 EMIOS_1.UCDIS.R |= (1 << (Channel-PWM_NUMBER_OF_EACH_EMIOS));\r
531         }\r
532         #endif\r
533 \r
534     /*\r
535      * PWM052: The function Pwm_DeInit shall disable all notifications.\r
536      */\r
537     #if PWM_NOTIFICATION_SUPPORTED==STD_ON\r
538         Pwm_DisableNotification(Channel);\r
539     #endif\r
540 }\r
541 \r
542 void Pwm_DeInit() {\r
543         Pwm_ChannelType channel_iterator;\r
544 \r
545         if(E_OK != Pwm_ValidateInitialized(PWM_DEINIT_ID))\r
546         {\r
547                 return;\r
548         }\r
549 \r
550         for (channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++) {\r
551                 Pwm_ChannelType channel = PwmConfigPtr->Channels[channel_iterator].channel;\r
552                 Pwm_DeInitChannel(channel);\r
553         }\r
554 \r
555         // Disable module\r
556         #if defined(CFG_MPC5516) || defined(CFG_MPC5567)\r
557                 EMIOS.MCR.B.MDIS = 1;\r
558     #elif defined(CFG_MPC560X)\r
559                 EMIOS_0.MCR.B.MDIS = 1;\r
560                 EMIOS_1.MCR.B.MDIS = 1;\r
561         #endif\r
562 \r
563         Pwm_ModuleState = PWM_STATE_UNINITIALIZED;\r
564 }\r
565 #endif\r
566 \r
567 \r
568 /*\r
569  * PWM083: The function Pwm_SetPeriodAndDuty shall be pre compile time\r
570  * changeable ON/OFF by the configuration parameter PwmSetPeriodAndDuty.\r
571  */\r
572 #if PWM_SET_PERIOD_AND_DUTY_API==STD_ON\r
573         void Pwm_SetPeriodAndDuty(Pwm_ChannelType Channel, Pwm_PeriodType Period,\r
574                         Pwm_DutyCycleType DutyCycle) {\r
575 \r
576                 if ((E_OK != Pwm_ValidateInitialized(PWM_SETPERIODANDDUTY_ID)) ||\r
577                         (E_OK != Pwm_ValidateChannel(Channel, PWM_SETPERIODANDDUTY_ID)))\r
578                 {\r
579                         return;\r
580                 }\r
581 \r
582                 for (Pwm_ChannelType channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++)\r
583                 {\r
584                         if(Channel == PwmConfigPtr->Channels[channel_iterator].channel){\r
585                                 if(PwmConfigPtr->ChannelClass[channel_iterator] != PWM_VARIABLE_PERIOD){\r
586                 #if PWM_DEV_ERROR_DETECT==STD_ON\r
587                                         Det_ReportError(PWM_MODULE_ID,0, PWM_SETPERIODANDDUTY_ID, PWM_E_PERIOD_UNCHANGEABLE);\r
588                 #endif\r
589                                         return;\r
590                                 }\r
591                                 break;\r
592                         }\r
593                 }\r
594 \r
595                 volatile struct EMIOS_tag *emiosHw;\r
596 #if defined(CFG_MPC560X)\r
597                 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
598                         emiosHw = &EMIOS_0;\r
599                 } else {\r
600                         emiosHw = &EMIOS_1;\r
601                         Channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
602                 }\r
603 #else\r
604                 emiosHw = &EMIOS;\r
605 #endif\r
606 \r
607                 uint16 leading_edge_position = (uint16) (((uint32) Period * (uint32) DutyCycle) >> 15);\r
608 \r
609                 /* Timer instant for leading edge */\r
610                 emiosHw->CH[Channel].CADR.R = leading_edge_position;\r
611 \r
612                 /* Timer instant for the period to restart */\r
613                 emiosHw->CH[Channel].CBDR.R = Period;\r
614         }\r
615 #endif\r
616 \r
617 \r
618 /**\r
619  * PWM013: The function Pwm_SetDutyCycle shall set the duty cycle of the PWM\r
620  * channel.\r
621  *\r
622  * @param Channel PWM channel to use. 0 <= Channel < PWM_NUMBER_OF_CHANNELS <= 16\r
623  * @param DutyCycle 0 <= DutyCycle <= 0x8000\r
624  */\r
625 #if PWM_SET_DUTY_CYCLE_API==STD_ON\r
626 void Pwm_SetDutyCycle(Pwm_ChannelType Channel, Pwm_DutyCycleType DutyCycle)\r
627 {\r
628         if ((E_OK != Pwm_ValidateInitialized(PWM_SETDUTYCYCLE_ID)) ||\r
629                 (E_OK != Pwm_ValidateChannel(Channel, PWM_SETDUTYCYCLE_ID)))\r
630         {\r
631                 return;\r
632         }\r
633         volatile struct EMIOS_tag *emiosHw;\r
634 #if defined(CFG_MPC560X)\r
635         if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
636                 emiosHw = &EMIOS_0;\r
637         } else {\r
638                 emiosHw = &EMIOS_1;\r
639                 Channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
640         }\r
641 #else\r
642         emiosHw = &EMIOS;\r
643 #endif\r
644 \r
645         uint16 leading_edge_position = (uint16) ((emiosHw->CH[Channel].CBDR.R\r
646                                 * (uint32) DutyCycle) >> 15);\r
647 \r
648         /* Timer instant for leading edge */\r
649 \r
650         /*\r
651          * PWM017: The function Pwm_SetDutyCycle shall update the duty cycle at\r
652          * the end of the period if supported by the implementation and configured\r
653          * with PwmDutycycleUpdatedEndperiod. [ This is achieved in hardware since\r
654          * the A and B registers are double buffered ]\r
655          *\r
656          * PWM014: The function Pwm_SetDutyCycle shall set the output state according\r
657          * to the configured polarity parameter [which is already set from\r
658          * Pwm_InitChannel], when the duty parameter is 0% [=0] or 100% [=0x8000].\r
659          */\r
660         emiosHw->CH[Channel].CADR.R = leading_edge_position;\r
661 }\r
662 #endif\r
663 \r
664 #if  PWM_SET_OUTPUT_TO_IDLE_API == STD_ON\r
665         void Pwm_SetOutputToIdle(Pwm_ChannelType Channel)\r
666         {\r
667                 if ((E_OK != Pwm_ValidateInitialized(PWM_SETOUTPUTTOIDLE_ID)) ||\r
668                         (E_OK != Pwm_ValidateChannel(Channel, PWM_SETOUTPUTTOIDLE_ID)))\r
669                 {\r
670                         return;\r
671                 }\r
672                 volatile struct EMIOS_tag *emiosHw;\r
673         #if defined(CFG_MPC560X)\r
674                 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
675                         emiosHw = &EMIOS_0;\r
676                 } else {\r
677                         emiosHw = &EMIOS_1;\r
678                         Channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
679                 }\r
680         #else\r
681                 emiosHw = &EMIOS;\r
682         #endif\r
683 \r
684                 emiosHw->CH[Channel].CADR.R = 0;\r
685     }\r
686 #endif\r
687 /*\r
688  * PWM085: The function Pwm_GetOutputState shall be pre compile configurable\r
689  * ON/OFF by the configuration parameter PwmGetOutputState\r
690  */\r
691 #if PWM_GET_OUTPUT_STATE_API==STD_ON\r
692         /*\r
693          * PWM022: The function Pwm_GetOutputState shall read the internal state\r
694          * of the PWM output signal and return it.\r
695          */\r
696         Pwm_OutputStateType Pwm_GetOutputState(Pwm_ChannelType Channel)\r
697         {\r
698                 if ((E_OK != Pwm_ValidateInitialized(PWM_GETOUTPUTSTATE_ID)) ||\r
699                         (E_OK != Pwm_ValidateChannel(Channel, PWM_GETOUTPUTSTATE_ID)))\r
700                 {\r
701                         return PWM_LOW;\r
702                 }\r
703 \r
704                 volatile struct EMIOS_tag *emiosHw;\r
705         #if defined(CFG_MPC560X)\r
706                 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
707                         emiosHw = &EMIOS_0;\r
708                 } else {\r
709                         emiosHw = &EMIOS_1;\r
710                         Channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
711                 }\r
712         #else\r
713                 emiosHw = &EMIOS;\r
714         #endif\r
715 \r
716                 return (Pwm_OutputStateType)emiosHw->CH[Channel].CSR.B.UCOUT;\r
717         }\r
718 #endif\r
719 \r
720 #if PWM_NOTIFICATION_SUPPORTED==STD_ON\r
721 \r
722         void Pwm_DisableNotification(Pwm_ChannelType Channel)\r
723         {\r
724                 if ((E_OK != Pwm_ValidateInitialized(PWM_DISABLENOTIFICATION_ID)) ||\r
725                         (E_OK != Pwm_ValidateChannel(Channel, PWM_DISABLENOTIFICATION_ID)))\r
726                 {\r
727                         return;\r
728                 }\r
729 \r
730                 volatile struct EMIOS_tag *emiosHw;\r
731         #if defined(CFG_MPC560X)\r
732                 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
733                         emiosHw = &EMIOS_0;\r
734                 } else {\r
735                         emiosHw = &EMIOS_1;\r
736                         Channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
737                 }\r
738         #else\r
739                 emiosHw = &EMIOS;\r
740         #endif\r
741 \r
742                 // Disable flags on this channel\r
743                 emiosHw->CH[Channel].CCR.B.FEN = 0;\r
744         }\r
745 \r
746         void Pwm_EnableNotification(Pwm_ChannelType Channel,Pwm_EdgeNotificationType Notification)\r
747         {\r
748                 if ((E_OK != Pwm_ValidateInitialized(PWM_ENABLENOTIFICATION_ID)) ||\r
749                         (E_OK != Pwm_ValidateChannel(Channel, PWM_ENABLENOTIFICATION_ID)))\r
750                 {\r
751                         return;\r
752                 }\r
753 \r
754                 volatile struct EMIOS_tag *emiosHw;\r
755         #if defined(CFG_MPC560X)\r
756                 if(Channel <= PWM_NUMBER_OF_EACH_EMIOS-1) {\r
757                         emiosHw = &EMIOS_0;\r
758                 } else {\r
759                         emiosHw = &EMIOS_1;\r
760                         Channel -= PWM_NUMBER_OF_EACH_EMIOS;\r
761                 }\r
762         #else\r
763                 emiosHw = &EMIOS;\r
764         #endif\r
765 \r
766                 ChannelRuntimeStruct[Channel].NotificationState = Notification;\r
767 \r
768                 emiosHw->CH[Channel].CCR.B.FEN = 1;\r
769         }\r
770 \r
771         static void Pwm_Isr(void)\r
772         {\r
773                 // Find out which channel that triggered the interrupt\r
774                 #if defined (CFG_MPC5516)\r
775                         uint32_t flagmask = EMIOS.GFLAG.R;\r
776                 #elif defined(CFG_MPC5567)\r
777                         uint32_t flagmask = EMIOS.GFR.R;\r
778         #endif\r
779 \r
780         #if defined(CFG_MPC5516) || defined(CFG_MPC5567)\r
781                         // There are 24 channels specified in the global flag register, but\r
782                         // we only listen to the first 16 as only these support OPWfM\r
783                         for (Pwm_ChannelType channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++)\r
784                         {\r
785                                 Pwm_ChannelType emios_ch = PwmConfigPtr->Channels[channel_iterator].channel;\r
786 \r
787                                 if (flagmask & (1 << emios_ch))\r
788                                 {\r
789                                         if (PwmConfigPtr->NotificationHandlers[channel_iterator] != NULL && EMIOS.CH[emios_ch].CCR.B.FEN)\r
790                                         {\r
791                                                 Pwm_EdgeNotificationType notification = ChannelRuntimeStruct[emios_ch].NotificationState;\r
792                                                 if (notification == PWM_BOTH_EDGES ||\r
793 \r
794                                                                 notification == EMIOS.CH[emios_ch].CSR.B.UCOUT)\r
795                                                 {\r
796                                                         PwmConfigPtr->NotificationHandlers[channel_iterator]();\r
797                                                 }\r
798                                         }\r
799 \r
800                                         // Clear interrupt\r
801                                         EMIOS.CH[emios_ch].CSR.B.FLAG = 1;\r
802                                 }\r
803                         }\r
804         #elif defined(CFG_MPC560X)\r
805                         uint32_t flagmask_0 = EMIOS_0.GFR.R;\r
806                         uint32_t flagmask_1 = EMIOS_1.GFR.R;\r
807 \r
808                         for (Pwm_ChannelType channel_iterator = 0; channel_iterator < PWM_NUMBER_OF_CHANNELS; channel_iterator++)\r
809                         {\r
810 \r
811                                 Pwm_ChannelType emios_ch = PwmConfigPtr->Channels[channel_iterator].channel;\r
812 \r
813                                 if (flagmask_0 & (1 << emios_ch))\r
814                                 {\r
815                                         if (PwmConfigPtr->NotificationHandlers[channel_iterator] != NULL && EMIOS_0.CH[emios_ch].CCR.B.FEN)\r
816                                         {\r
817                                                 Pwm_EdgeNotificationType notification = ChannelRuntimeStruct[emios_ch].NotificationState;\r
818                                                 if (notification == PWM_BOTH_EDGES ||\r
819 \r
820                                                                 notification == EMIOS_0.CH[emios_ch].CSR.B.UCOUT)\r
821                                                 {\r
822                                                         PwmConfigPtr->NotificationHandlers[channel_iterator]();\r
823                                                 }\r
824                                         }\r
825 \r
826                                         // Clear interrupt\r
827                                         EMIOS_0.CH[emios_ch].CSR.B.FLAG = 1;\r
828                                 }\r
829                                 else if (flagmask_1 & (1 << emios_ch - PWM_NUMBER_OF_EACH_EMIOS ))\r
830                                 {\r
831                                         if (PwmConfigPtr->NotificationHandlers[channel_iterator] != NULL && EMIOS_1.CH[emios_ch - PWM_NUMBER_OF_EACH_EMIOS].CCR.B.FEN)\r
832                                         {\r
833                                                 Pwm_EdgeNotificationType notification = ChannelRuntimeStruct[emios_ch].NotificationState;\r
834                                                 if (notification == PWM_BOTH_EDGES ||\r
835                                                                 notification == EMIOS_1.CH[emios_ch - PWM_NUMBER_OF_EACH_EMIOS].CSR.B.UCOUT)\r
836                                                         {\r
837                                                         PwmConfigPtr->NotificationHandlers[channel_iterator]();\r
838                                                         }\r
839                                                 }\r
840 \r
841                                         // Clear interrupt\r
842                                         EMIOS_1.CH[emios_ch - PWM_NUMBER_OF_EACH_EMIOS].CSR.B.FLAG = 1;\r
843                                 }\r
844                         }\r
845 \r
846                 #endif\r
847         }\r
848 \r
849 #endif /* PWM_NOTIFICATION_SUPPORED == STD_ON */\r