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 = STATUS_SUCCESS;
94 
95  if (g_flexioDeviceStatePtr[instance] == NULL)
96  {
97  baseAddr = g_flexioBase[instance];
98  /* Create resource allocation mutex */
99  osifStat = OSIF_MutexCreate(&(deviceState->resourceLock));
100  DEV_ASSERT(osifStat == STATUS_SUCCESS);
101  /* Reset FlexIO module */
102  FLEXIO_Init(baseAddr);
103  /* Enable FLEXIO interrupt in the interrupt manager */
104  INT_SYS_EnableIRQ(g_flexioIrqId[instance]);
105  /* Enable module */
106  FLEXIO_SetEnable(baseAddr, true);
107  /* Initialize device structure */
108  deviceState->resourceAllocation = 0U;
109  /* Clear state structures array */
110  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
111  {
112  deviceState->flexioStatePtr[count] = NULL;
113  }
114  g_flexioDeviceStatePtr[instance] = deviceState;
115  }
116 
117  (void)osifStat;
118  return STATUS_SUCCESS;
119 }
120 
121 /*FUNCTION**********************************************************************
122  *
123  * Function Name : FLEXIO_DRV_DeinitDevice
124  * Description : De-initializes the FlexIO device
125  *
126  * Implements : FLEXIO_DRV_DeinitDevice_Activity
127  *END**************************************************************************/
129 {
130  FLEXIO_Type *baseAddr;
131 
132  baseAddr = g_flexioBase[instance];
133  /* Reset FlexIO module */
134  FLEXIO_Init(baseAddr);
135  /* Disable FLEXIO interrupt in the interrupt manager */
137  /* Destroy resource allocation mutex */
138  (void)OSIF_MutexDestroy(&(g_flexioDeviceStatePtr[instance]->resourceLock));
139  /* Free resources */
140  g_flexioDeviceStatePtr[instance] = NULL;
141 
142  return STATUS_SUCCESS;
143 }
144 
145 
146 /*FUNCTION**********************************************************************
147  *
148  * Function Name : FLEXIO_DRV_Reset
149  * Description : Resets the FlexIO device
150  *
151  * Implements : FLEXIO_DRV_Reset_Activity
152  *END**************************************************************************/
153 status_t FLEXIO_DRV_Reset(uint32_t instance)
154 {
155  FLEXIO_Type *baseAddr;
156 
157  baseAddr = g_flexioBase[instance];
158  /* Reset FlexIO module */
159  FLEXIO_Init(baseAddr);
160 
161  return STATUS_SUCCESS;
162 }
163 
164 /*FUNCTION**********************************************************************
165  *
166  * Function Name : FLEXIO_DRV_Allocate
167  * Description : Allocate timers and shifters for a new driver instance
168  *
169  *END**************************************************************************/
170 static status_t FLEXIO_DRV_Allocate(uint32_t instance, flexio_common_state_t *driver)
171 {
172  uint8_t count; /* used to iterate through resources (shifters/timers) */
173  uint8_t step; /* keeps track of how many resources are needed for this driver */
174  uint8_t size; /* total number of resources */
175  uint8_t mask; /* bit-mask corresponding to current resources */
176  uint8_t resourceAllocation; /* current resource allocation map */
177  const FLEXIO_Type *baseAddr; /* base address of the FlexIO module */
178  status_t status = STATUS_ERROR; /* assume the worst: no resources found for this driver */
179 
180  /* Find free resources for a new driver. Drivers may need one or two adjacent shifters and timers */
181  baseAddr = g_flexioBase[instance];
182  resourceAllocation = g_flexioDeviceStatePtr[instance]->resourceAllocation;
183  step = driver->resourceCount;
184  size = FLEXIO_GetShifterNum(baseAddr);
185  count = 0U;
186  mask = (uint8_t)((1U << step) - 1U);
187  (void)OSIF_MutexLock(&(g_flexioDeviceStatePtr[instance]->resourceLock), OSIF_WAIT_FOREVER);
188  /* find available shifters and timers for the driver */
189  while ((status == STATUS_ERROR) && (count < size))
190  {
191  if ((resourceAllocation & mask) == 0U)
192  {
193  /* resources found */
194  driver->resourceIndex = count;
195  /* mark resources as busy */
196  g_flexioDeviceStatePtr[instance]->resourceAllocation |= mask;
197  status = STATUS_SUCCESS;
198  }
199  /* continue searching */
200  count += step;
201  mask <<= step;
202  }
203  (void)OSIF_MutexUnlock(&(g_flexioDeviceStatePtr[instance]->resourceLock));
204 
205  return status;
206 }
207 
208 
209 /*FUNCTION**********************************************************************
210  *
211  * Function Name : FLEXIO_DRV_Deallocate
212  * Description : De-allocate timers and shifters for a driver instance
213  *
214  *END**************************************************************************/
215 static void FLEXIO_DRV_Deallocate(uint32_t instance, const flexio_common_state_t *driver)
216 {
217  uint8_t mask;
218 
219  mask = (uint8_t)((1U << driver->resourceCount) - 1U);
220  mask <<= driver->resourceIndex;
221  (void)OSIF_MutexLock(&(g_flexioDeviceStatePtr[instance]->resourceLock), OSIF_WAIT_FOREVER);
222  g_flexioDeviceStatePtr[instance]->resourceAllocation &= (uint8_t)~mask;
223  (void)OSIF_MutexUnlock(&(g_flexioDeviceStatePtr[instance]->resourceLock));
224 }
225 
226 
227 /*FUNCTION**********************************************************************
228  *
229  * Function Name : FLEXIO_DRV_ResourcesInit
230  * Description : Initializes the resources for the current driver
231  *
232  *END**************************************************************************/
233 static void FLEXIO_DRV_ResourcesInit(uint32_t instance, const flexio_common_state_t *driver)
234 {
235  uint8_t resource;
236  uint8_t resourceCount;
237  uint8_t resourceIndex;
238  FLEXIO_Type *baseAddr;
239 
240  baseAddr = g_flexioBase[instance];
241  resourceCount = driver->resourceCount;
242  resourceIndex = driver->resourceIndex;
243  for (resource = resourceIndex; resource < (resourceIndex + resourceCount); resource++)
244  {
245  /* Ensure all shifters/timers are disabled */
246  FLEXIO_SetShifterMode(baseAddr, resource, FLEXIO_SHIFTER_MODE_DISABLED);
247  FLEXIO_SetTimerMode(baseAddr, resource, FLEXIO_TIMER_MODE_DISABLED);
248  /* Ensure all interrupts and DMA requests are disabled */
249  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << resource), false);
250  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << resource), false);
251  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << resource), false);
252  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)(1U << resource), false);
253  /* Clear any leftover flags */
254  FLEXIO_ClearShifterStatus(baseAddr, resource);
255  FLEXIO_ClearShifterErrorStatus(baseAddr, resource);
256  FLEXIO_ClearTimerStatus(baseAddr, resource);
257  }
258 }
259 
260 
261 /*FUNCTION**********************************************************************
262  *
263  * Function Name : FLEXIO_DRV_InitDriver
264  * Description : Initializes an instance of FlexIO driver
265  *
266  *END**************************************************************************/
267 status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
268 {
269  uint16_t count;
270  status_t retCode;
271  flexio_common_state_t **flexioStatePtr;
272 
273  /* allocate times and shifters for the driver */
274  retCode = FLEXIO_DRV_Allocate(instance, driver);
275  if (retCode != STATUS_SUCCESS)
276  { /* no more resources available */
277  return retCode;
278  }
279 
280  /* get driver list for this device instance */
281  flexioStatePtr = g_flexioDeviceStatePtr[instance]->flexioStatePtr;
282  /* find an empty state structure slot for the driver */
283  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
284  {
285  if (flexioStatePtr[count] == NULL)
286  {
287  /* found it, place the new driver struct here */
288  flexioStatePtr[count] = driver;
289  break;
290  }
291  }
292  /* no need to check if there was room since allocation was successful */
293  DEV_ASSERT(count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT);
294 
295  /* initialize the allocated resources */
296  FLEXIO_DRV_ResourcesInit(instance, driver);
297 
298  /* init the rest of the common state structure */
299  driver->isr = NULL;
300  driver->instance = instance;
301 
302  return STATUS_SUCCESS;
303 }
304 
305 
306 /*FUNCTION**********************************************************************
307  *
308  * Function Name : FLEXIO_DRV_DeinitDriver
309  * Description : De-initializes an instance of FlexIO driver
310  *
311  *END**************************************************************************/
312 status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
313 {
314  uint16_t count;
315  uint32_t instance;
316  flexio_common_state_t **flexioStatePtr;
317 
318  instance = driver->instance;
319  /* get driver list for this device instance */
320  flexioStatePtr = g_flexioDeviceStatePtr[instance]->flexioStatePtr;
321  /* find the driver in the list */
322  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
323  {
324  if (flexioStatePtr[count] == driver)
325  {
326  /* found it - remove it */
327  flexioStatePtr[count] = NULL;
328  break;
329  }
330  }
331  DEV_ASSERT(count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT);
332 
333  /* de-allocate timers and shifters for the driver */
334  FLEXIO_DRV_Deallocate(instance, driver);
335 
336  return STATUS_SUCCESS;
337 }
338 
339 
340 #if (FLEXIO_INSTANCE_COUNT > 0U)
341 /*FUNCTION**********************************************************************
342  *
343  * Function Name : FLEXIO_IRQHandler
344  * Description : Implementation of FLEXIO interrupt handler named in start-up code
345  *
346  *END**************************************************************************/
348 {
349  uint16_t count;
350  uint32_t instance;
351  uint32_t resourceMask;
352  uint32_t shifterEvents;
353  uint32_t shifterErrorEvents;
354  uint32_t timerEvents;
355  uint32_t enabledInterrupts;
356  const FLEXIO_Type *baseAddr;
357  flexio_common_state_t * const *driverList;
358  flexio_common_state_t *driverState;
359 
360  instance = 0U;
361  baseAddr = g_flexioBase[instance];
362  /* get masks of FlexIO events */
363  /* read enabled interrupts in a separate instruction to avoid MISRA violation */
364  enabledInterrupts = FLEXIO_GetAllShifterInterrupt(baseAddr);
365  shifterEvents = FLEXIO_GetAllShifterStatus(baseAddr) & enabledInterrupts;
366  enabledInterrupts = FLEXIO_GetAllShifterErrorInterrupt(baseAddr);
367  shifterErrorEvents = FLEXIO_GetAllShifterErrorStatus(baseAddr) & enabledInterrupts;
368  enabledInterrupts = FLEXIO_GetAllTimerInterrupt(baseAddr);
369  timerEvents = FLEXIO_GetAllTimerStatus(baseAddr) & enabledInterrupts;
370  /* get driver list for this device instance */
371  driverList = g_flexioDeviceStatePtr[instance]->flexioStatePtr;
372  /* check which driver instances need to be serviced */
373  for (count = 0U; count < FEATURE_FLEXIO_MAX_SHIFTER_COUNT; count++)
374  {
375  driverState = driverList[count];
376  /* check if driver is initialized and uses interrupts */
377  if ((driverState != NULL) && (driverState->isr != NULL))
378  {
379  /* compute mask of shifters/timers used by this driver */
380  resourceMask = ((1UL << driverState->resourceCount) - 1U) << driverState->resourceIndex;
381  /* check if this instance has any pending events */
382  if (((shifterEvents & resourceMask) != 0U) ||
383  ((shifterErrorEvents & resourceMask) != 0U) ||
384  ((timerEvents & resourceMask) != 0U))
385  {
386  /* there is an event for the current instance - call the isr */
387  (driverState->isr)(driverState);
388  }
389  }
390  }
391 }
392 #endif
393 
394 /*******************************************************************************
395  * EOF
396  ******************************************************************************/
#define FLEXIO_IRQS
Definition: S32K118.h:3367
status_t OSIF_MutexDestroy(const mutex_t *const pMutex)
Destroys a previously created mutex.
#define FEATURE_FLEXIO_DMA_REQ_3
static status_t FLEXIO_DRV_Allocate(uint32_t instance, flexio_common_state_t *driver)
#define FEATURE_FLEXIO_DMA_REQ_0
status_t OSIF_MutexUnlock(const mutex_t *const pMutex)
Unlocks a previously locked mutex.
status_t OSIF_MutexLock(const mutex_t *const pMutex, const uint32_t timeout)
Waits for a mutex and locks it.
#define FEATURE_FLEXIO_DMA_REQ_2
#define FEATURE_FLEXIO_MAX_SHIFTER_COUNT
#define FLEXIO_INSTANCE_COUNT
Definition: S32K118.h:3350
#define FLEXIO_BASE_PTRS
Definition: S32K118.h:3361
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 FEATURE_FLEXIO_DMA_REQ_1
#define DEV_ASSERT(x)
Definition: devassert.h:77
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 clock_names_t g_flexioClock[(1u)]
Definition: flexio_common.c:65
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K118.h:188
FLEXIO_Type *const g_flexioBase[(1u)]
Definition: flexio_common.c:56
const uint8_t g_flexioDMASrc[(1u)][(4U)]
Definition: flexio_common.c:68
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
flexio_device_state_t * g_flexioDeviceStatePtr[(1u)]
Definition: flexio_common.c:59
#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)
status_t FLEXIO_DRV_DeinitDevice(uint32_t instance)
De-initializes the FlexIO device.
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
clock_names_t
Clock names.
status_t FLEXIO_DRV_InitDevice(uint32_t instance, flexio_device_state_t *deviceState)
Initializes the FlexIO device.
Definition: flexio_common.c:89
const IRQn_Type g_flexioIrqId[(1u)]
Definition: flexio_common.c:62