S32 SDK
flexio_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
19 #include "device_registers.h"
20 #include "flexio_common.h"
21 #include "interrupt_manager.h"
22 
51 /*******************************************************************************
52  * Variables
53  ******************************************************************************/
54 
55 /* Table of base addresses for FLEXIO instances. */
57 
58 /* Pointer to device state structures. This structure contains data common to all drivers on one device */
59 flexio_device_state_t *g_flexioDeviceStatePtr[FLEXIO_INSTANCE_COUNT] = {NULL};
60 
61 /* Table for FLEXIO IRQ numbers */
63 
64 /* PCC clock sources, for getting the input clock frequency */
66 
67 /* FlexIO DMA request sources */
71 
72 
73 /*******************************************************************************
74  * Code
75  ******************************************************************************/
76 
77 
78 /* Declaration of FLEXIO_IRQHandler. Needed just to avoid MISRA violation. */
79 void FLEXIO_IRQHandler(void);
80 
81 
82 /*FUNCTION**********************************************************************
83  *
84  * Function Name : FLEXIO_DRV_InitDevice
85  * Description : Initializes the FlexIO device
86  * Implements : FLEXIO_DRV_InitDevice_Activity
87  *
88  *END**************************************************************************/
89 status_t FLEXIO_DRV_InitDevice(uint32_t instance, flexio_device_state_t *deviceState)
90 {
91  FLEXIO_Type *baseAddr;
92  uint8_t count;
93  status_t osifStat;
94 
95  baseAddr = g_flexioBase[instance];
96  /* Create resource allocation mutex */
97  osifStat = OSIF_MutexCreate(&(deviceState->resourceLock));
98  DEV_ASSERT(osifStat == STATUS_SUCCESS);
99  /* Reset FlexIO module */
100  FLEXIO_HAL_Init(baseAddr);
101  /* Enable FLEXIO interrupt in the interrupt manager */
102  INT_SYS_EnableIRQ(g_flexioIrqId[instance]);
103  /* Enable module */
104  FLEXIO_HAL_SetEnable(baseAddr, true);
105  /* Initialize device structure */
106  deviceState->resourceAllocation = 0U;
107  /* Clear state structures array */
108  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
109  {
110  deviceState->flexioStatePtr[count] = NULL;
111  }
112  g_flexioDeviceStatePtr[instance] = deviceState;
113 
114  (void)osifStat;
115  return STATUS_SUCCESS;
116 }
117 
118 
119 /*FUNCTION**********************************************************************
120  *
121  * Function Name : FLEXIO_DRV_DeinitDevice
122  * Description : De-initializes the FlexIO device
123  *
124  * Implements : FLEXIO_DRV_DeinitDevice_Activity
125  *END**************************************************************************/
127 {
128  FLEXIO_Type *baseAddr;
129 
130  baseAddr = g_flexioBase[instance];
131  /* Reset FlexIO module */
132  FLEXIO_HAL_Init(baseAddr);
133  /* Disable FLEXIO interrupt in the interrupt manager */
135  /* Destroy resource allocation mutex */
136  (void)OSIF_MutexDestroy(&(g_flexioDeviceStatePtr[instance]->resourceLock));
137  /* Free resources */
138  g_flexioDeviceStatePtr[instance] = NULL;
139 
140  return STATUS_SUCCESS;
141 }
142 
143 
144 /*FUNCTION**********************************************************************
145  *
146  * Function Name : FLEXIO_DRV_Reset
147  * Description : Resets the FlexIO device
148  *
149  * Implements : FLEXIO_DRV_Reset_Activity
150  *END**************************************************************************/
151 status_t FLEXIO_DRV_Reset(uint32_t instance)
152 {
153  FLEXIO_Type *baseAddr;
154 
155  baseAddr = g_flexioBase[instance];
156  /* Reset FlexIO module */
157  FLEXIO_HAL_Init(baseAddr);
158 
159  return STATUS_SUCCESS;
160 }
161 
162 /*FUNCTION**********************************************************************
163  *
164  * Function Name : FLEXIO_DRV_Allocate
165  * Description : Allocate timers and shifters for a new driver instance
166  *
167  *END**************************************************************************/
168 static status_t FLEXIO_DRV_Allocate(uint32_t instance, flexio_common_state_t *driver)
169 {
170  uint8_t count; /* used to iterate through resources (shifters/timers) */
171  uint8_t step; /* keeps track of how many resources are needed for this driver */
172  uint8_t size; /* total number of resources */
173  uint8_t mask; /* bit-mask corresponding to current resources */
174  uint8_t resourceAllocation; /* current resource allocation map */
175  const FLEXIO_Type *baseAddr; /* base address of the FlexIO module */
176  status_t status = STATUS_ERROR; /* assume the worst: no resources found for this driver */
177 
178  /* Find free resources for a new driver. Drivers may need one or two adjacent shifters and timers */
179  baseAddr = g_flexioBase[instance];
180  resourceAllocation = g_flexioDeviceStatePtr[instance]->resourceAllocation;
181  step = driver->resourceCount;
182  size = FLEXIO_HAL_GetShifterNum(baseAddr);
183  count = 0U;
184  mask = (uint8_t)((1U << step) - 1U);
185  (void)OSIF_MutexLock(&(g_flexioDeviceStatePtr[instance]->resourceLock), OSIF_WAIT_FOREVER);
186  /* find available shifters and timers for the driver */
187  while ((status == STATUS_ERROR) && (count < size))
188  {
189  if ((resourceAllocation & mask) == 0U)
190  {
191  /* resources found */
192  driver->resourceIndex = count;
193  /* mark resources as busy */
194  g_flexioDeviceStatePtr[instance]->resourceAllocation |= mask;
195  status = STATUS_SUCCESS;
196  }
197  /* continue searching */
198  count += step;
199  mask <<= step;
200  }
201  (void)OSIF_MutexUnlock(&(g_flexioDeviceStatePtr[instance]->resourceLock));
202 
203  return status;
204 }
205 
206 
207 /*FUNCTION**********************************************************************
208  *
209  * Function Name : FLEXIO_DRV_Deallocate
210  * Description : De-allocate timers and shifters for a driver instance
211  *
212  *END**************************************************************************/
213 static void FLEXIO_DRV_Deallocate(uint32_t instance, const flexio_common_state_t *driver)
214 {
215  uint8_t mask;
216 
217  mask = (uint8_t)((1U << driver->resourceCount) - 1U);
218  mask <<= driver->resourceIndex;
219  (void)OSIF_MutexLock(&(g_flexioDeviceStatePtr[instance]->resourceLock), OSIF_WAIT_FOREVER);
220  g_flexioDeviceStatePtr[instance]->resourceAllocation &= (uint8_t)~mask;
221  (void)OSIF_MutexUnlock(&(g_flexioDeviceStatePtr[instance]->resourceLock));
222 }
223 
224 
225 /*FUNCTION**********************************************************************
226  *
227  * Function Name : FLEXIO_DRV_ResourcesInit
228  * Description : Initializes the resources for the current driver
229  *
230  *END**************************************************************************/
231 static void FLEXIO_DRV_ResourcesInit(uint32_t instance, const flexio_common_state_t *driver)
232 {
233  uint8_t resource;
234  uint8_t resourceCount;
235  uint8_t resourceIndex;
236  FLEXIO_Type *baseAddr;
237 
238  baseAddr = g_flexioBase[instance];
239  resourceCount = driver->resourceCount;
240  resourceIndex = driver->resourceIndex;
241  for (resource = resourceIndex; resource < (resourceIndex + resourceCount); resource++)
242  {
243  /* Ensure all shifters/timers are disabled */
246  /* Ensure all interrupts and DMA requests are disabled */
247  FLEXIO_HAL_SetShifterInterrupt(baseAddr, (uint8_t)(1U << resource), false);
248  FLEXIO_HAL_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << resource), false);
249  FLEXIO_HAL_SetTimerInterrupt(baseAddr, (uint8_t)(1U << resource), false);
250  FLEXIO_HAL_SetShifterDMARequest(baseAddr, (uint8_t)(1U << resource), false);
251  /* Clear any leftover flags */
252  FLEXIO_HAL_ClearShifterStatus(baseAddr, resource);
253  FLEXIO_HAL_ClearShifterErrorStatus(baseAddr, resource);
254  FLEXIO_HAL_ClearTimerStatus(baseAddr, resource);
255  }
256 }
257 
258 
259 /*FUNCTION**********************************************************************
260  *
261  * Function Name : FLEXIO_DRV_InitDriver
262  * Description : Initializes an instance of FlexIO driver
263  *
264  *END**************************************************************************/
265 status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
266 {
267  uint16_t count;
268  status_t retCode;
269  flexio_common_state_t **flexioStatePtr;
270 
271  /* allocate times and shifters for the driver */
272  retCode = FLEXIO_DRV_Allocate(instance, driver);
273  if (retCode != STATUS_SUCCESS)
274  { /* no more resources available */
275  return retCode;
276  }
277 
278  /* get driver list for this device instance */
279  flexioStatePtr = g_flexioDeviceStatePtr[instance]->flexioStatePtr;
280  /* find an empty state structure slot for the driver */
281  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
282  {
283  if (flexioStatePtr[count] == NULL)
284  {
285  /* found it, place the new driver struct here */
286  flexioStatePtr[count] = driver;
287  break;
288  }
289  }
290  /* no need to check if there was room since allocation was successful */
291  DEV_ASSERT(count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT);
292 
293  /* initialize the allocated resources */
294  FLEXIO_DRV_ResourcesInit(instance, driver);
295 
296  /* init the rest of the common state structure */
297  driver->isr = NULL;
298  driver->instance = instance;
299 
300  return STATUS_SUCCESS;
301 }
302 
303 
304 /*FUNCTION**********************************************************************
305  *
306  * Function Name : FLEXIO_DRV_DeinitDriver
307  * Description : De-initializes an instance of FlexIO driver
308  *
309  *END**************************************************************************/
310 status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
311 {
312  uint16_t count;
313  uint32_t instance;
314  flexio_common_state_t **flexioStatePtr;
315 
316  instance = driver->instance;
317  /* get driver list for this device instance */
318  flexioStatePtr = g_flexioDeviceStatePtr[instance]->flexioStatePtr;
319  /* find the driver in the list */
320  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
321  {
322  if (flexioStatePtr[count] == driver)
323  {
324  /* found it - remove it */
325  flexioStatePtr[count] = NULL;
326  break;
327  }
328  }
329  DEV_ASSERT(count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT);
330 
331  /* de-allocate timers and shifters for the driver */
332  FLEXIO_DRV_Deallocate(instance, driver);
333 
334  return STATUS_SUCCESS;
335 }
336 
337 
338 #if (FLEXIO_INSTANCE_COUNT > 0U)
339 /*FUNCTION**********************************************************************
340  *
341  * Function Name : FLEXIO_IRQHandler
342  * Description : Implementation of FLEXIO interrupt handler named in start-up code
343  *
344  *END**************************************************************************/
346 {
347  uint16_t count;
348  uint32_t instance;
349  uint32_t resourceMask;
350  uint32_t shifterEvents;
351  uint32_t shifterErrorEvents;
352  uint32_t timerEvents;
353  uint32_t enabledInterrupts;
354  const FLEXIO_Type *baseAddr;
355  flexio_common_state_t * const *driverList;
356  flexio_common_state_t *driverState;
357 
358  instance = 0U;
359  baseAddr = g_flexioBase[instance];
360  /* get masks of FlexIO events */
361  /* read enabled interrupts in a separate instruction to avoid MISRA violation */
362  enabledInterrupts = FLEXIO_HAL_GetAllShifterInterrupt(baseAddr);
363  shifterEvents = FLEXIO_HAL_GetAllShifterStatus(baseAddr) & enabledInterrupts;
364  enabledInterrupts = FLEXIO_HAL_GetAllShifterErrorInterrupt(baseAddr);
365  shifterErrorEvents = FLEXIO_HAL_GetAllShifterErrorStatus(baseAddr) & enabledInterrupts;
366  enabledInterrupts = FLEXIO_HAL_GetAllTimerInterrupt(baseAddr);
367  timerEvents = FLEXIO_HAL_GetAllTimerStatus(baseAddr) & enabledInterrupts;
368  /* get driver list for this device instance */
369  driverList = g_flexioDeviceStatePtr[instance]->flexioStatePtr;
370  /* check which driver instances need to be serviced */
371  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
372  {
373  driverState = driverList[count];
374  /* check if driver is initialized and uses interrupts */
375  if ((driverState != NULL) && (driverState->isr != NULL))
376  {
377  /* compute mask of shifters/timers used by this driver */
378  resourceMask = ((1UL << driverState->resourceCount) - 1U) << driverState->resourceIndex;
379  /* check if this instance has any pending events */
380  if (((shifterEvents & resourceMask) != 0U) ||
381  ((shifterErrorEvents & resourceMask) != 0U) ||
382  ((timerEvents & resourceMask) != 0U))
383  {
384  /* there is an event for the current instance - call the isr */
385  (driverState->isr)(driverState);
386  }
387  }
388  }
389 }
390 #endif
391 
392 /*******************************************************************************
393  * EOF
394  ******************************************************************************/
#define FLEXIO_IRQS
Definition: S32K144.h:3524
status_t OSIF_MutexDestroy(const mutex_t *const pMutex)
Destroys a previously created mutex.
static void FLEXIO_HAL_SetShifterInterrupt(FLEXIO_Type *baseAddr, uint8_t interruptMask, bool enable)
Enables or disables the shifter interrupts.
Definition: flexio_hal.h:823
static void FLEXIO_HAL_SetShifterMode(FLEXIO_Type *baseAddr, uint8_t shifter, flexio_shifter_mode_t mode)
Sets the mode of the specified shifter.
Definition: flexio_hal.h:1198
static status_t FLEXIO_DRV_Allocate(uint32_t instance, flexio_common_state_t *driver)
status_t OSIF_MutexUnlock(const mutex_t *const pMutex)
Unlocks a previously locked mutex.
static void FLEXIO_HAL_SetTimerMode(FLEXIO_Type *baseAddr, uint8_t timer, flexio_timer_mode_t mode)
Sets the mode of the specified timer.
Definition: flexio_hal.h:1658
status_t OSIF_MutexLock(const mutex_t *const pMutex, const uint32_t timeout)
Waits for a mutex and locks it.
FLEXIO_Type *const g_flexioBase[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:56
static uint32_t FLEXIO_HAL_GetAllShifterStatus(const FLEXIO_Type *baseAddr)
Returns the current status flags for all shifters.
Definition: flexio_hal.h:619
#define FLEXIO_INSTANCE_COUNT
Definition: S32K144.h:3507
static uint8_t FLEXIO_HAL_GetShifterNum(const FLEXIO_Type *baseAddr)
Returns the number of shifters of the FlexIO module.
Definition: flexio_hal.h:371
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K144.h:269
#define FLEXIO_BASE_PTRS
Definition: S32K144.h:3518
static void FLEXIO_HAL_ClearTimerStatus(FLEXIO_Type *baseAddr, uint8_t timer)
Clears the status of the specified timer.
Definition: flexio_hal.h:767
static void FLEXIO_HAL_SetTimerInterrupt(FLEXIO_Type *baseAddr, uint8_t interruptMask, bool enable)
Enables or disables the timer interrupts.
Definition: flexio_hal.h:959
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
status_t FLEXIO_DRV_Reset(uint32_t instance)
Resets the FlexIO device.
#define DEV_ASSERT(x)
Definition: devassert.h:78
static void FLEXIO_DRV_ResourcesInit(uint32_t instance, const flexio_common_state_t *driver)
status_t OSIF_MutexCreate(mutex_t *const pMutex)
Create an unlocked mutex.
const IRQn_Type g_flexioIrqId[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:62
static uint32_t FLEXIO_HAL_GetAllTimerStatus(const FLEXIO_Type *baseAddr)
Returns the current status of all timers.
Definition: flexio_hal.h:752
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:31
static uint32_t FLEXIO_HAL_GetAllShifterErrorStatus(const FLEXIO_Type *baseAddr)
Returns the current error status for all shifters.
Definition: flexio_hal.h:684
const uint8_t g_flexioDMASrc[FLEXIO_INSTANCE_COUNT][FEATURE_FLEXIO_MAX_SHIFTER_COUNT]
Definition: flexio_common.c:68
void FLEXIO_HAL_Init(FLEXIO_Type *baseAddr)
Initializes the FlexIO module to a known state.
Definition: flexio_hal.c:42
static uint32_t FLEXIO_HAL_GetAllShifterErrorInterrupt(const FLEXIO_Type *baseAddr)
Returns the current status of all the shifter error interrupts.
Definition: flexio_hal.h:874
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
clock_names_t
Clock names.
#define OSIF_WAIT_FOREVER
Definition: osif.h:65
static void FLEXIO_DRV_Deallocate(uint32_t instance, const flexio_common_state_t *driver)
void FLEXIO_IRQHandler(void)
flexio_device_state_t * g_flexioDeviceStatePtr[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:59
status_t FLEXIO_DRV_DeinitDevice(uint32_t instance)
De-initializes the FlexIO device.
#define FEATURE_FLEXIO_MAX_SHIFTER_COUNT
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
static void FLEXIO_HAL_ClearShifterErrorStatus(FLEXIO_Type *baseAddr, uint8_t shifter)
Clears the error status of the specified shifter.
Definition: flexio_hal.h:699
static void FLEXIO_HAL_SetShifterErrorInterrupt(FLEXIO_Type *baseAddr, uint8_t interruptMask, bool enable)
Enables or disables the shifter error interrupts.
Definition: flexio_hal.h:891
const clock_names_t g_flexioClock[FLEXIO_INSTANCE_COUNT]
Definition: flexio_common.c:65
status_t FLEXIO_DRV_InitDevice(uint32_t instance, flexio_device_state_t *deviceState)
Initializes the FlexIO device.
Definition: flexio_common.c:89
static void FLEXIO_HAL_SetEnable(FLEXIO_Type *baseAddr, bool enable)
Enables of disables the FlexIO module.
Definition: flexio_hal.h:551
static uint32_t FLEXIO_HAL_GetAllShifterInterrupt(const FLEXIO_Type *baseAddr)
Returns the current status of all the shifter interrupts.
Definition: flexio_hal.h:806
static void FLEXIO_HAL_ClearShifterStatus(FLEXIO_Type *baseAddr, uint8_t shifter)
Clears the status of the specified shifter.
Definition: flexio_hal.h:635
static void FLEXIO_HAL_SetShifterDMARequest(FLEXIO_Type *baseAddr, uint8_t requestMask, bool enable)
Enables or disables the shifter DMA requests.
Definition: flexio_hal.h:1010
static uint32_t FLEXIO_HAL_GetAllTimerInterrupt(const FLEXIO_Type *baseAddr)
Returns the current status of all the timer interrupts.
Definition: flexio_hal.h:942