Add support for KL43Z using KSDK 2.0

Signed-off-by: Mahadevan Mahesh <Mahesh.Mahadevan@nxp.com>
pull/2499/head
Mahadevan Mahesh 2016-08-05 13:51:07 -05:00 committed by 0xc0170
parent 74de744178
commit a007d912ac
119 changed files with 50146 additions and 10936 deletions

View File

@ -475,17 +475,6 @@
"progen": {"target": "kl26z"},
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"]
},
"KL43Z": {
"supported_form_factors": ["ARDUINO"],
"core": "Cortex-M0+",
"extra_labels": ["Freescale", "KLXX"],
"is_disk_virtual": true,
"supported_toolchains": ["GCC_ARM", "ARM"],
"inherits": ["Target"],
"progen": {"target": "frdm-kl43z"},
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"release_versions": ["2"]
},
"KL46Z": {
"supported_form_factors": ["ARDUINO"],
"core": "Cortex-M0+",
@ -553,6 +542,19 @@
"default_build": "standard",
"release_versions": ["2"]
},
"KL43Z": {
"supported_form_factors": ["ARDUINO"],
"core": "Cortex-M0+",
"supported_toolchains": ["GCC_ARM", "ARM", "IAR"],
"extra_labels": ["Freescale", "KSDK2_MCUS", "FRDM"],
"macros": ["CPU_MKL43Z256VLH4", "FSL_RTOS_MBED"],
"is_disk_virtual": true,
"inherits": ["Target"],
"progen": {"target": "frdm-kl43z"},
"detect_code": ["0262"],
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
"release_versions": ["2", "5"]
},
"K64F": {
"supported_form_factors": ["ARDUINO"],
"core": "Cortex-M4F",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
#! armcc -E
/*
** ###################################################################
** Processors: MKL43Z256VLH4
** MKL43Z256VMP4
**
** Compiler: Keil ARM C/C++ Compiler
** Reference manual: KL43P64M48SF6RM, Rev.3, Aug 2014
** Version: rev. 1.6, 2015-07-29
** Build: b160406
**
** Abstract:
** Linker file for the Keil ARM C/C++ Compiler
**
** Copyright (c) 2016 Freescale Semiconductor, Inc.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of Freescale Semiconductor, Inc. nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.freescale.com
** mail: support@freescale.com
**
** ###################################################################
*/
#define __ram_vector_table__ 1
/* Heap 1/4 of ram and stack 1/8 */
#define __stack_size__ 0x1000
#define __heap_size__ 0x2800
#if (defined(__ram_vector_table__))
#define __ram_vector_table_size__ 0x00000200
#else
#define __ram_vector_table_size__ 0x00000000
#endif
#define m_interrupts_start 0x00000000
#define m_interrupts_size 0x00000200
#define m_flash_config_start 0x00000400
#define m_flash_config_size 0x00000010
#define m_text_start 0x00000410
#define m_text_size 0x0003FBF0
#define m_interrupts_ram_start 0x1FFFE000
#define m_interrupts_ram_size __ram_vector_table_size__
#define m_data_start (m_interrupts_ram_start + m_interrupts_ram_size)
#define m_data_size (0x00008000 - m_interrupts_ram_size)
/* Sizes */
#if (defined(__stack_size__))
#define Stack_Size __stack_size__
#else
#define Stack_Size 0x0400
#endif
#if (defined(__heap_size__))
#define Heap_Size __heap_size__
#else
#define Heap_Size 0x0400
#endif
LR_m_text m_interrupts_start m_text_start+m_text_size-m_interrupts_start { ; load region size_region
VECTOR_ROM m_interrupts_start m_interrupts_size { ; load address = execution address
* (RESET,+FIRST)
}
ER_m_flash_config m_flash_config_start FIXED m_flash_config_size { ; load address = execution address
* (FlashConfig)
}
ER_m_text m_text_start m_text_size { ; load address = execution address
* (InRoot$$Sections)
.ANY (+RO)
}
#if (defined(__ram_vector_table__))
VECTOR_RAM m_interrupts_ram_start EMPTY m_interrupts_ram_size {
}
#else
VECTOR_RAM m_interrupts_start EMPTY 0 {
}
#endif
RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM1 +0 EMPTY Heap_Size { ; Heap region growing up
}
}

View File

@ -2,12 +2,12 @@
; * @file: startup_MKL43Z4.s
; * @purpose: CMSIS Cortex-M0P Core Device Startup File
; * MKL43Z4
; * @version: 1.3
; * @date: 2014-8-21
; * @build: b140821
; * @version: 1.8
; * @date: 2016-6-24
; * @build: b160627
; * ---------------------------------------------------------------------------------------
; *
; * Copyright (c) 1997 - 2014 , Freescale Semiconductor, Inc.
; * Copyright (c) 1997 - 2016 , Freescale Semiconductor, Inc.
; * All rights reserved.
; *
; * Redistribution and use in source and binary forms, with or without modification,
@ -39,9 +39,7 @@
; *
; *****************************************************************************/
__initial_sp EQU 0x20006000 ; Top of RAM
__initial_sp EQU 0x20006000 ; Top of RAM
PRESERVE8
THUMB
@ -102,10 +100,10 @@ __Vectors DCD __initial_sp ; Top of Stack
DCD LPTMR0_IRQHandler ;LPTMR0 interrupt
DCD LCD_IRQHandler ;LCD interrupt
DCD PORTA_IRQHandler ;PORTA Pin detect
DCD PORTCD_IRQHandler ;Single interrupt vector for PORTC; PORTD Pin detect
DCD PORTC_PORTD_IRQHandler ;Single interrupt vector for PORTC; PORTD Pin detect
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
__Vectors_Size EQU __Vectors_End - __Vectors
; <h> Flash Configuration
; <i> 16-byte flash configuration field that stores default protection settings (loaded on reset)
@ -237,7 +235,7 @@ FSEC EQU 0xFE
; </h>
; </h>
IF :LNOT::DEF:RAM_TARGET
AREA |.ARM.__at_0x400|, DATA, READONLY
AREA FlashConfig, DATA, READONLY
__FlashConfig
DCB BackDoorK0, BackDoorK1, BackDoorK2, BackDoorK3
DCB BackDoorK4, BackDoorK5, BackDoorK6, BackDoorK7
@ -245,6 +243,7 @@ __FlashConfig
DCB FSEC , FOPT , 0xFF , 0xFF
ENDIF
AREA |.text|, CODE, READONLY
; Reset Handler
@ -253,8 +252,18 @@ Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
IF :LNOT::DEF:RAM_TARGET
REQUIRE FlashConfig
ENDIF
CPSID I ; Mask interrupts
LDR R0, =0xE000ED08
LDR R1, =__Vectors
STR R1, [R0]
LDR R0, =SystemInit
BLX R0
CPSIE i ; Unmask interrupts
LDR R0, =__main
BX R0
ENDP
@ -286,23 +295,107 @@ SysTick_Handler\
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler\
DMA0_IRQHandler\
PROC
EXPORT DMA0_IRQHandler [WEAK]
LDR R0, =DMA0_DriverIRQHandler
BX R0
ENDP
DMA1_IRQHandler\
PROC
EXPORT DMA1_IRQHandler [WEAK]
LDR R0, =DMA1_DriverIRQHandler
BX R0
ENDP
DMA2_IRQHandler\
PROC
EXPORT DMA2_IRQHandler [WEAK]
LDR R0, =DMA2_DriverIRQHandler
BX R0
ENDP
DMA3_IRQHandler\
PROC
EXPORT DMA3_IRQHandler [WEAK]
LDR R0, =DMA3_DriverIRQHandler
BX R0
ENDP
I2C0_IRQHandler\
PROC
EXPORT I2C0_IRQHandler [WEAK]
LDR R0, =I2C0_DriverIRQHandler
BX R0
ENDP
I2C1_IRQHandler\
PROC
EXPORT I2C1_IRQHandler [WEAK]
LDR R0, =I2C1_DriverIRQHandler
BX R0
ENDP
SPI0_IRQHandler\
PROC
EXPORT SPI0_IRQHandler [WEAK]
LDR R0, =SPI0_DriverIRQHandler
BX R0
ENDP
SPI1_IRQHandler\
PROC
EXPORT SPI1_IRQHandler [WEAK]
LDR R0, =SPI1_DriverIRQHandler
BX R0
ENDP
LPUART0_IRQHandler\
PROC
EXPORT LPUART0_IRQHandler [WEAK]
LDR R0, =LPUART0_DriverIRQHandler
BX R0
ENDP
LPUART1_IRQHandler\
PROC
EXPORT LPUART1_IRQHandler [WEAK]
LDR R0, =LPUART1_DriverIRQHandler
BX R0
ENDP
UART2_FLEXIO_IRQHandler\
PROC
EXPORT UART2_FLEXIO_IRQHandler [WEAK]
LDR R0, =UART2_FLEXIO_DriverIRQHandler
BX R0
ENDP
I2S0_IRQHandler\
PROC
EXPORT I2S0_IRQHandler [WEAK]
LDR R0, =I2S0_DriverIRQHandler
BX R0
ENDP
Default_Handler\
PROC
EXPORT DMA0_DriverIRQHandler [WEAK]
EXPORT DMA1_DriverIRQHandler [WEAK]
EXPORT DMA2_DriverIRQHandler [WEAK]
EXPORT DMA3_DriverIRQHandler [WEAK]
EXPORT Reserved20_IRQHandler [WEAK]
EXPORT FTFA_IRQHandler [WEAK]
EXPORT PMC_IRQHandler [WEAK]
EXPORT LLWU_IRQHandler [WEAK]
EXPORT I2C0_IRQHandler [WEAK]
EXPORT I2C1_IRQHandler [WEAK]
EXPORT SPI0_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK]
EXPORT LPUART0_IRQHandler [WEAK]
EXPORT LPUART1_IRQHandler [WEAK]
EXPORT UART2_FLEXIO_IRQHandler [WEAK]
EXPORT I2C0_DriverIRQHandler [WEAK]
EXPORT I2C1_DriverIRQHandler [WEAK]
EXPORT SPI0_DriverIRQHandler [WEAK]
EXPORT SPI1_DriverIRQHandler [WEAK]
EXPORT LPUART0_DriverIRQHandler [WEAK]
EXPORT LPUART1_DriverIRQHandler [WEAK]
EXPORT UART2_FLEXIO_DriverIRQHandler [WEAK]
EXPORT ADC0_IRQHandler [WEAK]
EXPORT CMP0_IRQHandler [WEAK]
EXPORT TPM0_IRQHandler [WEAK]
@ -311,7 +404,7 @@ Default_Handler\
EXPORT RTC_IRQHandler [WEAK]
EXPORT RTC_Seconds_IRQHandler [WEAK]
EXPORT PIT_IRQHandler [WEAK]
EXPORT I2S0_IRQHandler [WEAK]
EXPORT I2S0_DriverIRQHandler [WEAK]
EXPORT USB0_IRQHandler [WEAK]
EXPORT DAC0_IRQHandler [WEAK]
EXPORT Reserved42_IRQHandler [WEAK]
@ -319,23 +412,23 @@ Default_Handler\
EXPORT LPTMR0_IRQHandler [WEAK]
EXPORT LCD_IRQHandler [WEAK]
EXPORT PORTA_IRQHandler [WEAK]
EXPORT PORTCD_IRQHandler [WEAK]
EXPORT PORTC_PORTD_IRQHandler [WEAK]
EXPORT DefaultISR [WEAK]
DMA0_IRQHandler
DMA1_IRQHandler
DMA2_IRQHandler
DMA3_IRQHandler
DMA0_DriverIRQHandler
DMA1_DriverIRQHandler
DMA2_DriverIRQHandler
DMA3_DriverIRQHandler
Reserved20_IRQHandler
FTFA_IRQHandler
PMC_IRQHandler
LLWU_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
SPI0_IRQHandler
SPI1_IRQHandler
LPUART0_IRQHandler
LPUART1_IRQHandler
UART2_FLEXIO_IRQHandler
I2C0_DriverIRQHandler
I2C1_DriverIRQHandler
SPI0_DriverIRQHandler
SPI1_DriverIRQHandler
LPUART0_DriverIRQHandler
LPUART1_DriverIRQHandler
UART2_FLEXIO_DriverIRQHandler
ADC0_IRQHandler
CMP0_IRQHandler
TPM0_IRQHandler
@ -344,7 +437,7 @@ TPM2_IRQHandler
RTC_IRQHandler
RTC_Seconds_IRQHandler
PIT_IRQHandler
I2S0_IRQHandler
I2S0_DriverIRQHandler
USB0_IRQHandler
DAC0_IRQHandler
Reserved42_IRQHandler
@ -352,9 +445,10 @@ Reserved43_IRQHandler
LPTMR0_IRQHandler
LCD_IRQHandler
PORTA_IRQHandler
PORTCD_IRQHandler
PORTC_PORTD_IRQHandler
DefaultISR
B .
LDR R0, =DefaultISR
BX R0
ENDP
ALIGN

View File

@ -1,13 +1,13 @@
/* mbed Microcontroller Library - stackheap
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
*
* Setup a fixed single stack/heap memory model,
*
* Setup a fixed single stack/heap memory model,
* between the top of the RW/ZI region and the stackpointer
*/
#ifdef __cplusplus
extern "C" {
#endif
#endif
#include <rt_misc.h>
#include <stdint.h>
@ -28,4 +28,4 @@ extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,274 @@
/*
** ###################################################################
** Processors: MKL43Z256VLH4
** MKL43Z256VMP4
**
** Compiler: GNU C Compiler
** Reference manual: KL43P64M48SF6RM, Rev.3, Aug 2014
** Version: rev. 1.6, 2015-07-29
** Build: b160613
**
** Abstract:
** Linker file for the GNU C Compiler
**
** Copyright (c) 2016 Freescale Semiconductor, Inc.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of Freescale Semiconductor, Inc. nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.freescale.com
** mail: support@freescale.com
**
** ###################################################################
*/
/* Entry Point */
ENTRY(Reset_Handler)
__ram_vector_table__ = 1;
/* Heap 1/4 of ram and stack 1/8 */
__stack_size__ = 0x1000;
__heap_size__ = 0x2800;
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
M_VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x0200 : 0x0;
/* Specify the memory areas */
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000200
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x0003FBF0
m_data (RW) : ORIGIN = 0x1FFFE000, LENGTH = 0x00008000
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into internal flash */
.interrupts :
{
__VECTOR_TABLE = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > m_interrupts
.flash_config :
{
. = ALIGN(4);
KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_flash_config
/* The program code and other data goes into internal flash */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > m_text
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text
.ctors :
{
__CTOR_LIST__ = .;
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text
.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} > m_text
__etext = .; /* define a global symbol at end of code */
__DATA_ROM = .; /* Symbol is used by startup for data initialization */
/* reserve MTB memory at the beginning of m_data */
.mtb : /* MTB buffer address as defined by the hardware */
{
. = ALIGN(8);
_mtb_start = .;
KEEP(*(.mtb_buf)) /* need to KEEP Micro Trace Buffer as not referenced by application */
. = ALIGN(8);
_mtb_end = .;
} > m_data
.interrupts_ram :
{
. = ALIGN(4);
__VECTOR_RAM__ = .;
__interrupts_ram_start__ = .; /* Create a global symbol at data start */
*(.m_interrupts_ram) /* This is a user defined section */
. += M_VECTOR_RAM_SIZE;
. = ALIGN(4);
__interrupts_ram_end__ = .; /* Define a global symbol at data end */
} > m_data
__VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
__RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .; /* define a global symbol at data end */
} > m_data
__DATA_END = __DATA_ROM + (__data_end__ - __data_start__);
text_end = ORIGIN(m_text) + LENGTH(m_text);
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")
USB_RAM_GAP = DEFINED(__usb_ram_size__) ? __usb_ram_size__ : 0x00;
/* Uninitialized data section */
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(.bss)
*(.bss*)
. = ALIGN(512);
USB_RAM_START = .;
. += USB_RAM_GAP;
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > m_data
.stack :
{
. = ALIGN(8);
. += STACK_SIZE;
} > m_data
m_usb_bdt USB_RAM_START (NOLOAD) :
{
*(m_usb_bdt)
USB_RAM_BDT_END = .;
}
m_usb_global USB_RAM_BDT_END (NOLOAD) :
{
*(m_usb_global)
}
/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_data) + LENGTH(m_data);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
.ARM.attributes 0 : { *(.ARM.attributes) }
ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap")
}

View File

@ -0,0 +1,391 @@
/* ---------------------------------------------------------------------------------------*/
/* @file: startup_MKL43Z4.s */
/* @purpose: CMSIS Cortex-M0P Core Device Startup File */
/* MKL43Z4 */
/* @version: 1.8 */
/* @date: 2016-6-24 */
/* @build: b160627 */
/* ---------------------------------------------------------------------------------------*/
/* */
/* Copyright (c) 1997 - 2016 , Freescale Semiconductor, Inc. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without modification, */
/* are permitted provided that the following conditions are met: */
/* */
/* o Redistributions of source code must retain the above copyright notice, this list */
/* of conditions and the following disclaimer. */
/* */
/* o Redistributions in binary form must reproduce the above copyright notice, this */
/* list of conditions and the following disclaimer in the documentation and/or */
/* other materials provided with the distribution. */
/* */
/* o Neither the name of Freescale Semiconductor, Inc. nor the names of its */
/* contributors may be used to endorse or promote products derived from this */
/* software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/*****************************************************************************/
/* Version: GCC for ARM Embedded Processors */
/*****************************************************************************/
.syntax unified
.arch armv6-m
.section .isr_vector, "a"
.align 2
.globl __isr_vector
__isr_vector:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler*/
.long HardFault_Handler /* Hard Fault Handler*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long SVC_Handler /* SVCall Handler*/
.long 0 /* Reserved*/
.long 0 /* Reserved*/
.long PendSV_Handler /* PendSV Handler*/
.long SysTick_Handler /* SysTick Handler*/
/* External Interrupts*/
.long DMA0_IRQHandler /* DMA channel 0 transfer complete*/
.long DMA1_IRQHandler /* DMA channel 1 transfer complete*/
.long DMA2_IRQHandler /* DMA channel 2 transfer complete*/
.long DMA3_IRQHandler /* DMA channel 3 transfer complete*/
.long Reserved20_IRQHandler /* Reserved interrupt*/
.long FTFA_IRQHandler /* Command complete and read collision*/
.long PMC_IRQHandler /* Low-voltage detect, low-voltage warning*/
.long LLWU_IRQHandler /* Low leakage wakeup*/
.long I2C0_IRQHandler /* I2C0 interrupt*/
.long I2C1_IRQHandler /* I2C1 interrupt*/
.long SPI0_IRQHandler /* SPI0 single interrupt vector for all sources*/
.long SPI1_IRQHandler /* SPI1 single interrupt vector for all sources*/
.long LPUART0_IRQHandler /* LPUART0 status and error*/
.long LPUART1_IRQHandler /* LPUART1 status and error*/
.long UART2_FLEXIO_IRQHandler /* UART2 or FLEXIO*/
.long ADC0_IRQHandler /* ADC0 interrupt*/
.long CMP0_IRQHandler /* CMP0 interrupt*/
.long TPM0_IRQHandler /* TPM0 single interrupt vector for all sources*/
.long TPM1_IRQHandler /* TPM1 single interrupt vector for all sources*/
.long TPM2_IRQHandler /* TPM2 single interrupt vector for all sources*/
.long RTC_IRQHandler /* RTC alarm*/
.long RTC_Seconds_IRQHandler /* RTC seconds*/
.long PIT_IRQHandler /* PIT interrupt*/
.long I2S0_IRQHandler /* I2S0 interrupt*/
.long USB0_IRQHandler /* USB0 interrupt*/
.long DAC0_IRQHandler /* DAC0 interrupt*/
.long Reserved42_IRQHandler /* Reserved interrupt*/
.long Reserved43_IRQHandler /* Reserved interrupt*/
.long LPTMR0_IRQHandler /* LPTMR0 interrupt*/
.long LCD_IRQHandler /* LCD interrupt*/
.long PORTA_IRQHandler /* PORTA Pin detect*/
.long PORTC_PORTD_IRQHandler /* Single interrupt vector for PORTC; PORTD Pin detect*/
.size __isr_vector, . - __isr_vector
/* Flash Configuration */
.section .FlashConfig, "a"
.long 0xFFFFFFFF
.long 0xFFFFFFFF
.long 0xFFFFFFFF
.long 0xFFFF3FFE
.text
.thumb
/* Reset Handler */
.thumb_func
.align 2
.globl Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
cpsid i /* Mask interrupts */
.equ VTOR, 0xE000ED08
ldr r0, =VTOR
ldr r1, =__isr_vector
str r1, [r0]
#ifndef __NO_SYSTEM_INIT
ldr r0,=SystemInit
blx r0
#endif
/* Loop to copy data from read only memory to RAM. The ranges
* of copy from/to are specified by following symbols evaluated in
* linker script.
* __etext: End of code section, i.e., begin of data sections to copy from.
* __data_start__/__data_end__: RAM address range that data should be
* copied to. Both must be aligned to 4 bytes boundary. */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
subs r3, r2
ble .LC0
.LC1:
subs r3, 4
ldr r0, [r1,r3]
str r0, [r2,r3]
bgt .LC1
.LC0:
#ifdef __STARTUP_CLEAR_BSS
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* Loop to zero out BSS section, which uses following symbols
* in linker script:
* __bss_start__: start of BSS section. Must align to 4
* __bss_end__: end of BSS section. Must align to 4
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
subs r2, r1
ble .LC3
movs r0, 0
.LC2:
str r0, [r1, r2]
subs r2, 4
bge .LC2
.LC3:
#endif
cpsie i /* Unmask interrupts */
#ifndef __START
#define __START _start
#endif
#ifndef __ATOLLIC__
ldr r0,=__START
blx r0
#else
ldr r0,=__libc_init_array
blx r0
ldr r0,=main
bx r0
#endif
.pool
.size Reset_Handler, . - Reset_Handler
.align 1
.thumb_func
.weak DefaultISR
.type DefaultISR, %function
DefaultISR:
ldr r0, =DefaultISR
bx r0
.size DefaultISR, . - DefaultISR
.align 1
.thumb_func
.weak NMI_Handler
.type NMI_Handler, %function
NMI_Handler:
ldr r0,=NMI_Handler
bx r0
.size NMI_Handler, . - NMI_Handler
.align 1
.thumb_func
.weak HardFault_Handler
.type HardFault_Handler, %function
HardFault_Handler:
ldr r0,=HardFault_Handler
bx r0
.size HardFault_Handler, . - HardFault_Handler
.align 1
.thumb_func
.weak SVC_Handler
.type SVC_Handler, %function
SVC_Handler:
ldr r0,=SVC_Handler
bx r0
.size SVC_Handler, . - SVC_Handler
.align 1
.thumb_func
.weak PendSV_Handler
.type PendSV_Handler, %function
PendSV_Handler:
ldr r0,=PendSV_Handler
bx r0
.size PendSV_Handler, . - PendSV_Handler
.align 1
.thumb_func
.weak SysTick_Handler
.type SysTick_Handler, %function
SysTick_Handler:
ldr r0,=SysTick_Handler
bx r0
.size SysTick_Handler, . - SysTick_Handler
.align 1
.thumb_func
.weak DMA0_IRQHandler
.type DMA0_IRQHandler, %function
DMA0_IRQHandler:
ldr r0,=DMA0_DriverIRQHandler
bx r0
.size DMA0_IRQHandler, . - DMA0_IRQHandler
.align 1
.thumb_func
.weak DMA1_IRQHandler
.type DMA1_IRQHandler, %function
DMA1_IRQHandler:
ldr r0,=DMA1_DriverIRQHandler
bx r0
.size DMA1_IRQHandler, . - DMA1_IRQHandler
.align 1
.thumb_func
.weak DMA2_IRQHandler
.type DMA2_IRQHandler, %function
DMA2_IRQHandler:
ldr r0,=DMA2_DriverIRQHandler
bx r0
.size DMA2_IRQHandler, . - DMA2_IRQHandler
.align 1
.thumb_func
.weak DMA3_IRQHandler
.type DMA3_IRQHandler, %function
DMA3_IRQHandler:
ldr r0,=DMA3_DriverIRQHandler
bx r0
.size DMA3_IRQHandler, . - DMA3_IRQHandler
.align 1
.thumb_func
.weak I2C0_IRQHandler
.type I2C0_IRQHandler, %function
I2C0_IRQHandler:
ldr r0,=I2C0_DriverIRQHandler
bx r0
.size I2C0_IRQHandler, . - I2C0_IRQHandler
.align 1
.thumb_func
.weak I2C1_IRQHandler
.type I2C1_IRQHandler, %function
I2C1_IRQHandler:
ldr r0,=I2C1_DriverIRQHandler
bx r0
.size I2C1_IRQHandler, . - I2C1_IRQHandler
.align 1
.thumb_func
.weak SPI0_IRQHandler
.type SPI0_IRQHandler, %function
SPI0_IRQHandler:
ldr r0,=SPI0_DriverIRQHandler
bx r0
.size SPI0_IRQHandler, . - SPI0_IRQHandler
.align 1
.thumb_func
.weak SPI1_IRQHandler
.type SPI1_IRQHandler, %function
SPI1_IRQHandler:
ldr r0,=SPI1_DriverIRQHandler
bx r0
.size SPI1_IRQHandler, . - SPI1_IRQHandler
.align 1
.thumb_func
.weak LPUART0_IRQHandler
.type LPUART0_IRQHandler, %function
LPUART0_IRQHandler:
ldr r0,=LPUART0_DriverIRQHandler
bx r0
.size LPUART0_IRQHandler, . - LPUART0_IRQHandler
.align 1
.thumb_func
.weak LPUART1_IRQHandler
.type LPUART1_IRQHandler, %function
LPUART1_IRQHandler:
ldr r0,=LPUART1_DriverIRQHandler
bx r0
.size LPUART1_IRQHandler, . - LPUART1_IRQHandler
.align 1
.thumb_func
.weak UART2_FLEXIO_IRQHandler
.type UART2_FLEXIO_IRQHandler, %function
UART2_FLEXIO_IRQHandler:
ldr r0,=UART2_FLEXIO_DriverIRQHandler
bx r0
.size UART2_FLEXIO_IRQHandler, . - UART2_FLEXIO_IRQHandler
.align 1
.thumb_func
.weak I2S0_IRQHandler
.type I2S0_IRQHandler, %function
I2S0_IRQHandler:
ldr r0,=I2S0_DriverIRQHandler
bx r0
.size I2S0_IRQHandler, . - I2S0_IRQHandler
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_irq_handler handler_name
.weak \handler_name
.set \handler_name, DefaultISR
.endm
/* Exception Handlers */
def_irq_handler DMA0_DriverIRQHandler
def_irq_handler DMA1_DriverIRQHandler
def_irq_handler DMA2_DriverIRQHandler
def_irq_handler DMA3_DriverIRQHandler
def_irq_handler Reserved20_IRQHandler
def_irq_handler FTFA_IRQHandler
def_irq_handler PMC_IRQHandler
def_irq_handler LLWU_IRQHandler
def_irq_handler I2C0_DriverIRQHandler
def_irq_handler I2C1_DriverIRQHandler
def_irq_handler SPI0_DriverIRQHandler
def_irq_handler SPI1_DriverIRQHandler
def_irq_handler LPUART0_DriverIRQHandler
def_irq_handler LPUART1_DriverIRQHandler
def_irq_handler UART2_FLEXIO_DriverIRQHandler
def_irq_handler ADC0_IRQHandler
def_irq_handler CMP0_IRQHandler
def_irq_handler TPM0_IRQHandler
def_irq_handler TPM1_IRQHandler
def_irq_handler TPM2_IRQHandler
def_irq_handler RTC_IRQHandler
def_irq_handler RTC_Seconds_IRQHandler
def_irq_handler PIT_IRQHandler
def_irq_handler I2S0_DriverIRQHandler
def_irq_handler USB0_IRQHandler
def_irq_handler DAC0_IRQHandler
def_irq_handler Reserved42_IRQHandler
def_irq_handler Reserved43_IRQHandler
def_irq_handler LPTMR0_IRQHandler
def_irq_handler LCD_IRQHandler
def_irq_handler PORTA_IRQHandler
def_irq_handler PORTC_PORTD_IRQHandler
.end

View File

@ -0,0 +1,112 @@
/*
** ###################################################################
** Processors: MKL43Z256VLH4
** MKL43Z256VMP4
**
** Compiler: IAR ANSI C/C++ Compiler for ARM
** Reference manual: KL43P64M48SF6RM, Rev.3, Aug 2014
** Version: rev. 1.6, 2015-07-29
** Build: b160406
**
** Abstract:
** Linker file for the IAR ANSI C/C++ Compiler for ARM
**
** Copyright (c) 2016 Freescale Semiconductor, Inc.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of Freescale Semiconductor, Inc. nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.freescale.com
** mail: support@freescale.com
**
** ###################################################################
*/
define symbol __ram_vector_table__ = 1;
/* Heap 1/4 of ram and stack 1/8 */
define symbol __stack_size__=0x1000;
define symbol __heap_size__=0x2800;
define symbol __ram_vector_table_size__ = isdefinedsymbol(__ram_vector_table__) ? 0x00000200 : 0;
define symbol __ram_vector_table_offset__ = isdefinedsymbol(__ram_vector_table__) ? 0x000001FF : 0;
define symbol m_interrupts_start = 0x00000000;
define symbol m_interrupts_end = 0x000001FF;
define symbol m_flash_config_start = 0x00000400;
define symbol m_flash_config_end = 0x0000040F;
define symbol m_text_start = 0x00000410;
define symbol m_text_end = 0x0003FFFF;
define symbol m_interrupts_ram_start = 0x1FFFE000;
define symbol m_interrupts_ram_end = 0x1FFFE000 + __ram_vector_table_offset__;
define symbol m_data_start = m_interrupts_ram_start + __ram_vector_table_size__;
define symbol m_data_end = 0x20005FFF;
/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
define symbol __size_cstack__ = __stack_size__;
} else {
define symbol __size_cstack__ = 0x0400;
}
if (isdefinedsymbol(__heap_size__)) {
define symbol __size_heap__ = __heap_size__;
} else {
define symbol __size_heap__ = 0x0400;
}
define exported symbol __VECTOR_TABLE = m_interrupts_start;
define exported symbol __VECTOR_RAM = isdefinedsymbol(__ram_vector_table__) ? m_interrupts_ram_start : m_interrupts_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = __ram_vector_table_size__;
define memory mem with size = 4G;
define region m_flash_config_region = mem:[from m_flash_config_start to m_flash_config_end];
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
| mem:[from m_text_start to m_text_end];
define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__];
define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end];
define region m_interrupts_ram_region = mem:[from m_interrupts_ram_start to m_interrupts_ram_end];
define block CSTACK with alignment = 8, size = __size_cstack__ { };
define block HEAP with alignment = 8, size = __size_heap__ { };
define block RW { readwrite };
define block ZI { zi };
initialize by copy { readwrite, section .textrw };
do not initialize { section .noinit };
place at address mem: m_interrupts_start { readonly section .intvec };
place in m_flash_config_region { section FlashConfig };
place in TEXT_region { readonly };
place in DATA_region { block RW };
place in DATA_region { block ZI };
place in DATA_region { last block HEAP };
place in CSTACK_region { block CSTACK };
place in m_interrupts_ram_region { section m_interrupts_ram };

View File

@ -0,0 +1,323 @@
; ---------------------------------------------------------------------------------------
; @file: startup_MKL43Z4.s
; @purpose: CMSIS Cortex-M0P Core Device Startup File
; MKL43Z4
; @version: 1.8
; @date: 2016-6-24
; @build: b160627
; ---------------------------------------------------------------------------------------
;
; Copyright (c) 1997 - 2016 , Freescale Semiconductor, Inc.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without modification,
; are permitted provided that the following conditions are met:
;
; o Redistributions of source code must retain the above copyright notice, this list
; of conditions and the following disclaimer.
;
; o Redistributions in binary form must reproduce the above copyright notice, this
; list of conditions and the following disclaimer in the documentation and/or
; other materials provided with the distribution.
;
; o Neither the name of Freescale Semiconductor, Inc. nor the names of its
; contributors may be used to endorse or promote products derived from this
; software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
; ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; The modules in this file are included in the libraries, and may be replaced
; by any user-defined modules that define the PUBLIC symbol _program_start or
; a user defined start symbol.
; To override the cstartup defined in the library, simply add your modified
; version to the workbench project.
;
; The vector table is normally located at address 0.
; When debugging in RAM, it can be located in RAM, aligned to at least 2^6.
; The name "__vector_table" has special meaning for C-SPY:
; it is where the SP start value is found, and the NVIC vector
; table register (VTOR) is initialized to this address if != 0.
;
; Cortex-M version
;
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
EXTERN __iar_program_start
EXTERN SystemInit
PUBLIC __vector_table
PUBLIC __vector_table_0x1c
PUBLIC __Vectors
PUBLIC __Vectors_End
PUBLIC __Vectors_Size
DATA
__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler
DCD NMI_Handler ;NMI Handler
DCD HardFault_Handler ;Hard Fault Handler
DCD 0 ;Reserved
DCD 0 ;Reserved
DCD 0 ;Reserved
__vector_table_0x1c
DCD 0 ;Reserved
DCD 0 ;Reserved
DCD 0 ;Reserved
DCD 0 ;Reserved
DCD SVC_Handler ;SVCall Handler
DCD 0 ;Reserved
DCD 0 ;Reserved
DCD PendSV_Handler ;PendSV Handler
DCD SysTick_Handler ;SysTick Handler
;External Interrupts
DCD DMA0_IRQHandler ;DMA channel 0 transfer complete
DCD DMA1_IRQHandler ;DMA channel 1 transfer complete
DCD DMA2_IRQHandler ;DMA channel 2 transfer complete
DCD DMA3_IRQHandler ;DMA channel 3 transfer complete
DCD Reserved20_IRQHandler ;Reserved interrupt
DCD FTFA_IRQHandler ;Command complete and read collision
DCD PMC_IRQHandler ;Low-voltage detect, low-voltage warning
DCD LLWU_IRQHandler ;Low leakage wakeup
DCD I2C0_IRQHandler ;I2C0 interrupt
DCD I2C1_IRQHandler ;I2C1 interrupt
DCD SPI0_IRQHandler ;SPI0 single interrupt vector for all sources
DCD SPI1_IRQHandler ;SPI1 single interrupt vector for all sources
DCD LPUART0_IRQHandler ;LPUART0 status and error
DCD LPUART1_IRQHandler ;LPUART1 status and error
DCD UART2_FLEXIO_IRQHandler ;UART2 or FLEXIO
DCD ADC0_IRQHandler ;ADC0 interrupt
DCD CMP0_IRQHandler ;CMP0 interrupt
DCD TPM0_IRQHandler ;TPM0 single interrupt vector for all sources
DCD TPM1_IRQHandler ;TPM1 single interrupt vector for all sources
DCD TPM2_IRQHandler ;TPM2 single interrupt vector for all sources
DCD RTC_IRQHandler ;RTC alarm
DCD RTC_Seconds_IRQHandler ;RTC seconds
DCD PIT_IRQHandler ;PIT interrupt
DCD I2S0_IRQHandler ;I2S0 interrupt
DCD USB0_IRQHandler ;USB0 interrupt
DCD DAC0_IRQHandler ;DAC0 interrupt
DCD Reserved42_IRQHandler ;Reserved interrupt
DCD Reserved43_IRQHandler ;Reserved interrupt
DCD LPTMR0_IRQHandler ;LPTMR0 interrupt
DCD LCD_IRQHandler ;LCD interrupt
DCD PORTA_IRQHandler ;PORTA Pin detect
DCD PORTC_PORTD_IRQHandler ;Single interrupt vector for PORTC; PORTD Pin detect
__Vectors_End
SECTION FlashConfig:CODE
__FlashConfig
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFF3FFE
__FlashConfig_End
__Vectors EQU __vector_table
__Vectors_Size EQU __Vectors_End - __Vectors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
THUMB
PUBWEAK Reset_Handler
SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
CPSID I ; Mask interrupts
LDR R0, =0xE000ED08
LDR R1, =__vector_table
STR R1, [R0]
LDR R0, =SystemInit
BLX R0
CPSIE I ; Unmask interrupts
LDR R0, =__iar_program_start
BX R0
PUBWEAK NMI_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
NMI_Handler
B .
PUBWEAK HardFault_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
HardFault_Handler
B .
PUBWEAK SVC_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
SVC_Handler
B .
PUBWEAK PendSV_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
PendSV_Handler
B .
PUBWEAK SysTick_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
SysTick_Handler
B .
PUBWEAK DMA0_IRQHandler
PUBWEAK DMA0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
DMA0_IRQHandler
LDR R0, =DMA0_DriverIRQHandler
BX R0
PUBWEAK DMA1_IRQHandler
PUBWEAK DMA1_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
DMA1_IRQHandler
LDR R0, =DMA1_DriverIRQHandler
BX R0
PUBWEAK DMA2_IRQHandler
PUBWEAK DMA2_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
DMA2_IRQHandler
LDR R0, =DMA2_DriverIRQHandler
BX R0
PUBWEAK DMA3_IRQHandler
PUBWEAK DMA3_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
DMA3_IRQHandler
LDR R0, =DMA3_DriverIRQHandler
BX R0
PUBWEAK Reserved20_IRQHandler
PUBWEAK FTFA_IRQHandler
PUBWEAK PMC_IRQHandler
PUBWEAK LLWU_IRQHandler
PUBWEAK I2C0_IRQHandler
PUBWEAK I2C0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
I2C0_IRQHandler
LDR R0, =I2C0_DriverIRQHandler
BX R0
PUBWEAK I2C1_IRQHandler
PUBWEAK I2C1_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
I2C1_IRQHandler
LDR R0, =I2C1_DriverIRQHandler
BX R0
PUBWEAK SPI0_IRQHandler
PUBWEAK SPI0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
SPI0_IRQHandler
LDR R0, =SPI0_DriverIRQHandler
BX R0
PUBWEAK SPI1_IRQHandler
PUBWEAK SPI1_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
SPI1_IRQHandler
LDR R0, =SPI1_DriverIRQHandler
BX R0
PUBWEAK LPUART0_IRQHandler
PUBWEAK LPUART0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
LPUART0_IRQHandler
LDR R0, =LPUART0_DriverIRQHandler
BX R0
PUBWEAK LPUART1_IRQHandler
PUBWEAK LPUART1_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
LPUART1_IRQHandler
LDR R0, =LPUART1_DriverIRQHandler
BX R0
PUBWEAK UART2_FLEXIO_IRQHandler
PUBWEAK UART2_FLEXIO_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
UART2_FLEXIO_IRQHandler
LDR R0, =UART2_FLEXIO_DriverIRQHandler
BX R0
PUBWEAK ADC0_IRQHandler
PUBWEAK CMP0_IRQHandler
PUBWEAK TPM0_IRQHandler
PUBWEAK TPM1_IRQHandler
PUBWEAK TPM2_IRQHandler
PUBWEAK RTC_IRQHandler
PUBWEAK RTC_Seconds_IRQHandler
PUBWEAK PIT_IRQHandler
PUBWEAK I2S0_IRQHandler
PUBWEAK I2S0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
I2S0_IRQHandler
LDR R0, =I2S0_DriverIRQHandler
BX R0
PUBWEAK USB0_IRQHandler
PUBWEAK DAC0_IRQHandler
PUBWEAK Reserved42_IRQHandler
PUBWEAK Reserved43_IRQHandler
PUBWEAK LPTMR0_IRQHandler
PUBWEAK LCD_IRQHandler
PUBWEAK PORTA_IRQHandler
PUBWEAK PORTC_PORTD_IRQHandler
PUBWEAK DefaultISR
SECTION .text:CODE:REORDER:NOROOT(2)
DMA0_DriverIRQHandler
DMA1_DriverIRQHandler
DMA2_DriverIRQHandler
DMA3_DriverIRQHandler
Reserved20_IRQHandler
FTFA_IRQHandler
PMC_IRQHandler
LLWU_IRQHandler
I2C0_DriverIRQHandler
I2C1_DriverIRQHandler
SPI0_DriverIRQHandler
SPI1_DriverIRQHandler
LPUART0_DriverIRQHandler
LPUART1_DriverIRQHandler
UART2_FLEXIO_DriverIRQHandler
ADC0_IRQHandler
CMP0_IRQHandler
TPM0_IRQHandler
TPM1_IRQHandler
TPM2_IRQHandler
RTC_IRQHandler
RTC_Seconds_IRQHandler
PIT_IRQHandler
I2S0_DriverIRQHandler
USB0_IRQHandler
DAC0_IRQHandler
Reserved42_IRQHandler
Reserved43_IRQHandler
LPTMR0_IRQHandler
LCD_IRQHandler
PORTA_IRQHandler
PORTC_PORTD_IRQHandler
DefaultISR
LDR R0, =DefaultISR
BX R0
END

View File

@ -1,13 +1,13 @@
/* mbed Microcontroller Library - CMSIS
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
*
*
* A generic CMSIS include header, pulling in LPC11U24 specifics
*/
#ifndef MBED_CMSIS_H
#define MBED_CMSIS_H
#include "MKL43Z4.h"
#include "fsl_device_registers.h"
#include "cmsis_nvic.h"
#endif

View File

@ -0,0 +1,42 @@
/* mbed Microcontroller Library
* CMSIS-style functionality to support dynamic vectors
*******************************************************************************
* Copyright (c) 2011 ARM Limited. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of ARM Limited nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#include "cmsis_nvic.h"
extern void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
InstallIRQHandler(IRQn, vector);
}
uint32_t NVIC_GetVector(IRQn_Type IRQn) {
uint32_t *vectors = (uint32_t*)SCB->VTOR;
return vectors[IRQn + 16];
}

View File

@ -0,0 +1,51 @@
/* mbed Microcontroller Library
* CMSIS-style functionality to support dynamic vectors
*******************************************************************************
* Copyright (c) 2011 ARM Limited. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of ARM Limited nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#define NVIC_NUM_VECTORS (16 + 32) // CORE + MCU Peripherals
#define NVIC_USER_IRQ_OFFSET 16
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
uint32_t NVIC_GetVector(IRQn_Type IRQn);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FSL_DEVICE_REGISTERS_H__
#define __FSL_DEVICE_REGISTERS_H__
/*
* Include the cpu specific register header files.
*
* The CPU macro should be declared in the project or makefile.
*/
#if (defined(CPU_MKL43Z128VLH4) || defined(CPU_MKL43Z256VLH4) || defined(CPU_MKL43Z128VMP4) || \
defined(CPU_MKL43Z256VMP4))
#define KL43Z4_SERIES
/* CMSIS-style register definitions */
#include "MKL43Z4.h"
/* CPU specific feature definitions */
#include "MKL43Z4_features.h"
#else
#error "No valid CPU defined!"
#endif
#endif /* __FSL_DEVICE_REGISTERS_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -1,28 +1,25 @@
/*
** ###################################################################
** Processors: MKL43Z256VLH4
** MKL43Z128VLH4
** MKL43Z64VLH4
** MKL43Z256VMP4
** Processors: MKL43Z128VLH4
** MKL43Z128VMP4
** MKL43Z64VMP4
** MKL43Z256VLH4
** MKL43Z256VMP4
**
** Compilers: Keil ARM C/C++ Compiler
** Freescale C/C++ for Embedded ARM
** GNU C Compiler
** GNU C Compiler - CodeSourcery Sourcery G++
** IAR ANSI C/C++ Compiler for ARM
**
** Reference manual: KL43P64M48SF6RM, Rev.3, Aug 2014
** Version: rev. 1.4, 2014-09-01
** Build: b140904
** Version: rev. 1.6, 2015-07-29
** Build: b151217
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright (c) 2014 Freescale Semiconductor, Inc.
** Copyright (c) 2015 Freescale Semiconductor, Inc.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
@ -84,14 +81,18 @@
** - rev. 1.4 (2014-09-01)
** USB - USB0_CTL0 was renamed to USB0_OTGCTL register.
** USB - USB0_CTL1 was renamed to USB0_CTL register.
** - rev. 1.5 (2014-09-05)
** USB - Renamed USBEN bitfield of USB0_CTL was renamed to USBENSOFEN.
** - rev. 1.6 (2015-07-29)
** Correction of backward compatibility.
**
** ###################################################################
*/
/*!
* @file MKL43Z4
* @version 1.4
* @date 2014-09-01
* @version 1.6
* @date 2015-07-29
* @brief Device specific configuration file for MKL43Z4 (implementation file)
*
* Provides a system configuration function and a global variable that contains
@ -100,7 +101,7 @@
*/
#include <stdint.h>
#include "MKL43Z4.h"
#include "fsl_device_registers.h"
@ -127,73 +128,6 @@ void SystemInit (void) {
SIM->COPC = (uint32_t)0x00u;
#endif /* (DISABLE_WDOG) */
/* Power mode protection initialization */
#ifdef SMC_PMPROT_VALUE
SMC->PMPROT = SMC_PMPROT_VALUE;
#endif
/* System clock initialization */
/* Set system prescalers and clock sources */
SIM->CLKDIV1 = SYSTEM_SIM_CLKDIV1_VALUE; /* Set system prescalers */
SIM->SOPT1 = ((SIM->SOPT1) & (uint32_t)(~(SIM_SOPT1_OSC32KSEL_MASK))) | ((SYSTEM_SIM_SOPT1_VALUE) & (SIM_SOPT1_OSC32KSEL_MASK)); /* Set 32 kHz clock source (ERCLK32K) */
#define SOPT2_WRITE_MASK ((SIM_SOPT2_USBSRC_MASK) | (SIM_SOPT2_TPMSRC_MASK) | (SIM_SOPT2_LPUART0SRC_MASK) | (SIM_SOPT2_LPUART1SRC_MASK)) /* define mask of written bits. */
SIM->SOPT2 = ((SIM->SOPT2) & (uint32_t)(~SOPT2_WRITE_MASK)) | ((SYSTEM_SIM_SOPT2_VALUE) & SOPT2_WRITE_MASK); /* Selects the clock source for the TPM counter clock. */
#if (MCG_MODE == MCG_MODE_LIRC_2M || MCG_MODE == MCG_MODE_LIRC_8M || MCG_MODE == MCG_MODE_HIRC)
/* Set MCG and OSC0 */
#if (((OSC0_CR_VALUE) & OSC_CR_ERCLKEN_MASK) != 0x00U)
/* SIM_SCGC5: PORTA=1 */
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;
/* PORTA_PCR3: ISF=0,MUX=0 */
PORTA_PCR18 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
if (((MCG_C2_VALUE) & MCG_C2_EREFS0_MASK) != 0x00U) {
PORTA_PCR19 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
}
#endif
MCG->SC = MCG_SC_VALUE; /* Set SC (internal reference clock divider) */
MCG->MC = MCG_MC_VALUE; /* Set MC (high-frequency IRC enable, second LIRC divider) */
MCG->C1 = MCG_C1_VALUE; /* Set C1 (clock source selection, int. reference enable etc.) */
MCG->C2 = MCG_C2_VALUE; /* Set C2 (ext. and int. reference clock selection) */
OSC0->CR = OSC0_CR_VALUE; /* Set OSC0_CR (OSCERCLK enable, oscillator capacitor load) */
#else /* MCG_MODE */
/* Set MCG and OSC0 */
/* SIM_SCGC5: PORTA=1 */
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;
/* PORTA_PCR3: ISF=0,MUX=0 */
PORTA_PCR18 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
if (((MCG_C2_VALUE) & MCG_C2_EREFS0_MASK) != 0x00U) {
PORTA_PCR19 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
}
MCG->SC = MCG_SC_VALUE; /* Set SC (internal reference clock divider) */
MCG->C2 = MCG_C2_VALUE; /* Set C2 (ext. and int. reference clock selection) */
OSC0->CR = OSC0_CR_VALUE; /* Set OSC0_CR (OSCERCLK enable, oscillator capacitor load) */
MCG->C1 = MCG_C1_VALUE; /* Set C1 (clock source selection, int. reference enable etc.) */
MCG->MC = MCG_MC_VALUE; /* Set MC (high-frequency IRC enable, second LIRC divider) */
if (((MCG_C2_VALUE) & MCG_C2_EREFS0_MASK) != 0U) {
while((MCG->S & MCG_S_OSCINIT0_MASK) == 0x00U) { /* Check that the oscillator is running */
}
}
#endif /* MCG_MODE */
/* Common for all MCG modes */
#if (MCG_MODE == MCG_MODE_HIRC)
while((MCG->S & MCG_S_CLKST_MASK) != 0x00U) { /* Wait until high internal reference clock is selected as MCG_Lite output */
}
#elif (MCG_MODE == MCG_MODE_LIRC_2M || MCG_MODE == MCG_MODE_LIRC_8M)
while((MCG->S & MCG_S_CLKST_MASK) != 0x04U) { /* Wait until low internal reference clock is selected as MCG_Lite output */
}
#elif (MCG_MODE == MCG_MODE_EXT)
while((MCG->S & MCG_S_CLKST_MASK) != 0x08U) { /* Wait until external reference clock is selected as MCG_Lite output */
}
#endif
if (((SMC_PMCTRL_VALUE) & SMC_PMCTRL_RUNM_MASK) == SMC_PMCTRL_RUNM(0x02U)) {
SMC->PMCTRL = (uint8_t)((SMC_PMCTRL_VALUE) & (SMC_PMCTRL_RUNM_MASK)); /* Enable VLPR mode */
while(SMC->PMSTAT != 0x04U) { /* Wait until the system is in VLPR mode */
}
}
}
/* ----------------------------------------------------------------------------

View File

@ -0,0 +1,166 @@
/*
** ###################################################################
** Processors: MKL43Z128VLH4
** MKL43Z128VMP4
** MKL43Z256VLH4
** MKL43Z256VMP4
**
** Compilers: Keil ARM C/C++ Compiler
** Freescale C/C++ for Embedded ARM
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
**
** Reference manual: KL43P64M48SF6RM, Rev.3, Aug 2014
** Version: rev. 1.6, 2015-07-29
** Build: b151217
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright (c) 2015 Freescale Semiconductor, Inc.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of Freescale Semiconductor, Inc. nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.freescale.com
** mail: support@freescale.com
**
** Revisions:
** - rev. 1.0 (2014-03-27)
** Initial version.
** - rev. 1.1 (2014-05-26)
** I2S registers TCR2/RCR2 and others were changed.
** FLEXIO register FLEXIO_VERID has now bitfields: FEATURE, MINOR, MAJOR.
** Names of the bitfields of the FLEXIO_SHIFTBUF have been changed to the appropriate register name e.g.: FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS.
** Peripheral_BASES macros has been changed to Peripheral_BASE_PTRS, e.g.: ADC_BASES to ADC_BASE_PTRS.
** Clock configuration for high range external oscillator has been added.
** RFSYS module access has been added.
** - rev. 1.2 (2014-07-10)
** GPIO - Renamed modules PTA,PTB,PTC,PTD,PTE to GPIOA,GPIOB,GPIOC,GPIOD,GPIOE.
** UART0 - UART0 module renamed to UART2.
** I2S - removed MDR register.
** - rev. 1.3 (2014-08-21)
** UART2 - Removed ED register.
** UART2 - Removed MODEM register.
** UART2 - Removed IR register.
** UART2 - Removed PFIFO register.
** UART2 - Removed CFIFO register.
** UART2 - Removed SFIFO register.
** UART2 - Removed TWFIFO register.
** UART2 - Removed TCFIFO register.
** UART2 - Removed RWFIFO register.
** UART2 - Removed RCFIFO register.
** USB - Removed bitfield REG_EN in CLK_RECOVER_IRC_EN register.
** SIM - Changed bitfield value MCGIRCLK to LIRC_CLK of bitfield CLKOUTSEL in SOPT2 register.
** SIM - Removed bitfield DIEID in SDID register.
** - rev. 1.4 (2014-09-01)
** USB - USB0_CTL0 was renamed to USB0_OTGCTL register.
** USB - USB0_CTL1 was renamed to USB0_CTL register.
** - rev. 1.5 (2014-09-05)
** USB - Renamed USBEN bitfield of USB0_CTL was renamed to USBENSOFEN.
** - rev. 1.6 (2015-07-29)
** Correction of backward compatibility.
**
** ###################################################################
*/
/*!
* @file MKL43Z4
* @version 1.6
* @date 2015-07-29
* @brief Device specific configuration file for MKL43Z4 (header file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#ifndef _SYSTEM_MKL43Z4_H_
#define _SYSTEM_MKL43Z4_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifndef DISABLE_WDOG
#define DISABLE_WDOG 1
#endif
#define ACK_ISOLATION 1
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 32768u /* Value of the external crystal or oscillator clock frequency in Hz */
#define CPU_INT_FAST_CLK_HZ 48000000u /* Value of the fast internal oscillator clock frequency in Hz */
#define CPU_INT_IRC_CLK_HZ 48000000u /* Value of the 48M internal oscillator clock frequency in Hz */
/* Low power mode enable */
/* SMC_PMPROT: AVLP=1,AVLLS=1 */
#define SYSTEM_SMC_PMPROT_VALUE 0x2Au /* SMC_PMPROT */
#define DEFAULT_SYSTEM_CLOCK 8000000u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 8000000u /* Value of the slow internal oscillator clock frequency in Hz */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_MKL43Z4_H_ */

View File

@ -1,14 +0,0 @@
LR_IROM1 0x00000000 0x40000 { ; load region size_region (256k)
ER_IROM1 0x00000000 0x40000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0
; 0x8000 - 0xC0 = 0x7F40
RW_IRAM1 0x1FFFE0C0 0x7F40 {
.ANY (+RW +ZI)
}
}

View File

@ -1,163 +0,0 @@
/*
* KL43Z ARM GCC linker script file
*/
MEMORY
{
VECTORS (rx) : ORIGIN = 0x00000000, LENGTH = 0x00000400
FLASH_PROTECTION (rx) : ORIGIN = 0x00000400, LENGTH = 0x00000010
FLASH (rx) : ORIGIN = 0x00000410, LENGTH = 256K - 0x00000410
RAM (rwx) : ORIGIN = 0x1FFFE0C0, LENGTH = 32K - 0xC0
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* _reset_init : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.isr_vector :
{
__vector_table = .;
KEEP(*(.vector_table))
*(.text.Reset_Handler)
*(.text.System_Init)
. = ALIGN(4);
} > VECTORS
.flash_protect :
{
KEEP(*(.kinetis_flash_config_field))
. = ALIGN(4);
} > FLASH_PROTECTION
.text :
{
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
__bss_start__ = .;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > RAM
.heap :
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy :
{
*(.stack)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

View File

@ -1,243 +0,0 @@
/* KL43Z startup ARM GCC
* Purpose: startup file for Cortex-M0 devices. Should use with
* GCC for ARM Embedded Processors
* Version: V1.3
* Date: 10 Nov 2014
*
* Copyright (c) 2011, ARM Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the ARM Limited nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.syntax unified
.arch armv6-m
/* Memory Model
The HEAP starts at the end of the DATA section and grows upward.
The STACK starts at the end of the RAM and grows downward.
The HEAP and stack STACK are only checked at compile time:
(DATA_SIZE + HEAP_SIZE + STACK_SIZE) < RAM_SIZE
This is just a check for the bare minimum for the Heap+Stack area before
aborting compilation, it is not the run time limit:
Heap_Size + Stack_Size = 0x200 + 0x400 = 0x600
*/
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0x400
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0x200
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.space Heap_Size
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .vector_table,"a",%progbits
.align 2
.globl __isr_vector
__isr_vector:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* External interrupts */
.long DMA0_IRQHandler /* DMA channel 0 transfer complete interrupt */
.long DMA1_IRQHandler /* DMA channel 1 transfer complete interrupt */
.long DMA2_IRQHandler /* DMA channel 2 transfer complete interrupt */
.long DMA3_IRQHandler /* DMA channel 3 transfer complete interrupt */
.long Default_Handler /* Reserved interrupt 20 */
.long FTFA_IRQHandler /* FTFA interrupt */
.long PMC_IRQHandler /* Low-voltage detect, low-voltage warning*/
.long LLWU_IRQHandler /* Low leakage wakeup*/
.long I2C0_IRQHandler /* I2C0 interrupt*/
.long I2C1_IRQHandler /* I2C1 interrupt*/
.long SPI0_IRQHandler /* SPI0 single interrupt vector for all sources*/
.long SPI1_IRQHandler /* SPI1 single interrupt vector for all sources*/
.long LPUART0_IRQHandler /* LPUART0 status and error*/
.long LPUART1_IRQHandler /* LPUART1 status and error*/
.long UART2_FLEXIO_IRQHandler /* UART2 or FLEXIO*/
.long ADC0_IRQHandler /* ADC0 interrupt*/
.long CMP0_IRQHandler /* CMP0 interrupt*/
.long TPM0_IRQHandler /* TPM0 single interrupt vector for all sources*/
.long TPM1_IRQHandler /* TPM1 single interrupt vector for all sources*/
.long TPM2_IRQHandler /* TPM2 single interrupt vector for all sources*/
.long RTC_IRQHandler /* RTC alarm*/
.long RTC_Seconds_IRQHandler /* RTC seconds*/
.long PIT_IRQHandler /* PIT interrupt*/
.long I2S0_IRQHandler /* I2S0 interrupt*/
.long USB0_IRQHandler /* USB0 interrupt*/
.long DAC0_IRQHandler /* DAC0 interrupt*/
.long Reserved42_IRQHandler /* Reserved interrupt*/
.long Reserved43_IRQHandler /* Reserved interrupt*/
.long LPTMR0_IRQHandler /* LPTMR0 interrupt*/
.long LCD_IRQHandler /* LCD interrupt*/
.long PORTA_IRQHandler /* PORTA Pin detect*/
.long PORTCD_IRQHandler /* Single interrupt vector for PORTC; PORTD Pin detect*/
.size __isr_vector, . - __isr_vector
/* Reset Handler */
.section .text.Reset_Handler
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Loop to copy data from read only memory to RAM. The ranges
* of copy from/to are specified by following symbols evaluated in
* linker script.
* __etext: End of code section, i.e., begin of data sections to copy from.
* __data_start__/__data_end__: RAM address range that data should be
* copied to. Both must be aligned to 4 bytes boundary. */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
subs r3, r2
ble .Lflash_to_ram_loop_end
movs r4, 0
.Lflash_to_ram_loop:
ldr r0, [r1,r4]
str r0, [r2,r4]
adds r4, 4
cmp r4, r3
blt .Lflash_to_ram_loop
.Lflash_to_ram_loop_end:
ldr r0, =SystemInit
blx r0
ldr r0, =_start
bx r0
.pool
.size Reset_Handler, . - Reset_Handler
.text
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_default_handler handler_name
.align 1
.thumb_func
.weak \handler_name
.type \handler_name, %function
\handler_name :
b .
.size \handler_name, . - \handler_name
.endm
def_default_handler NMI_Handler
def_default_handler HardFault_Handler
def_default_handler SVC_Handler
def_default_handler PendSV_Handler
def_default_handler SysTick_Handler
def_default_handler Default_Handler
.macro def_irq_default_handler handler_name
.weak \handler_name
.set \handler_name, Default_Handler
.endm
def_irq_default_handler DMA0_IRQHandler
def_irq_default_handler DMA1_IRQHandler
def_irq_default_handler DMA2_IRQHandler
def_irq_default_handler DMA3_IRQHandler
def_irq_default_handler Reserved20_IRQHandler
def_irq_default_handler FTFA_IRQHandler
def_irq_default_handler PMC_IRQHandler
def_irq_default_handler LLWU_IRQHandler
def_irq_default_handler I2C0_IRQHandler
def_irq_default_handler I2C1_IRQHandler
def_irq_default_handler SPI0_IRQHandler
def_irq_default_handler SPI1_IRQHandler
def_irq_default_handler LPUART0_IRQHandler
def_irq_default_handler LPUART1_IRQHandler
def_irq_default_handler UART2_FLEXIO_IRQHandler
def_irq_default_handler ADC0_IRQHandler
def_irq_default_handler CMP0_IRQHandler
def_irq_default_handler TPM0_IRQHandler
def_irq_default_handler TPM1_IRQHandler
def_irq_default_handler TPM2_IRQHandler
def_irq_default_handler RTC_IRQHandler
def_irq_default_handler RTC_Seconds_IRQHandler
def_irq_default_handler PIT_IRQHandler
def_irq_default_handler I2S0_IRQHandler
def_irq_default_handler USB0_IRQHandler
def_irq_default_handler DAC0_IRQHandler
def_irq_default_handler Reserved42_IRQHandler
def_irq_default_handler Reserved43_IRQHandler
def_irq_default_handler LPTMR0_IRQHandler
def_irq_default_handler LCD_IRQHandler
def_irq_default_handler PORTA_IRQHandler
def_irq_default_handler PORTCD_IRQHandler
def_irq_default_handler DefaultISR
/* Flash protection region, placed at 0x400 */
.text
.thumb
.align 2
.section .kinetis_flash_config_field,"a",%progbits
kinetis_flash_config:
.long 0xFFFFFFFF
.long 0xFFFFFFFF
.long 0xFFFFFFFF
.long 0xFFFF3FFE
.end

View File

@ -1,30 +0,0 @@
/* mbed Microcontroller Library - cmsis_nvic for LPC11U24
* Copyright (c) 2011 ARM Limited. All rights reserved.
*
* CMSIS-style functionality to support dynamic vectors
*/
#include "cmsis_nvic.h"
#define NVIC_RAM_VECTOR_ADDRESS (0x1FFFE000) // Vectors positioned at start of RAM
#define NVIC_FLASH_VECTOR_ADDRESS (0x0) // Initial vector position in flash
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
uint32_t *vectors = (uint32_t*)SCB->VTOR;
uint32_t i;
// Copy and switch to dynamic vectors if the first time called
if (SCB->VTOR == NVIC_FLASH_VECTOR_ADDRESS) {
uint32_t *old_vectors = vectors;
vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;
for (i=0; i<NVIC_NUM_VECTORS; i++) {
vectors[i] = old_vectors[i];
}
SCB->VTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS;
}
vectors[IRQn + 16] = vector;
}
uint32_t NVIC_GetVector(IRQn_Type IRQn) {
uint32_t *vectors = (uint32_t*)SCB->VTOR;
return vectors[IRQn + 16];
}

View File

@ -1,26 +0,0 @@
/* mbed Microcontroller Library - cmsis_nvic
* Copyright (c) 2009-2011 ARM Limited. All rights reserved.
*
* CMSIS-style functionality to support dynamic vectors
*/
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#define NVIC_NUM_VECTORS (16 + 32) // CORE + MCU Peripherals
#define NVIC_USER_IRQ_OFFSET 16
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
uint32_t NVIC_GetVector(IRQn_Type IRQn);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,335 +0,0 @@
/*
** ###################################################################
** Processors: MKL43Z256VLH4
** MKL43Z128VLH4
** MKL43Z64VLH4
** MKL43Z256VMP4
** MKL43Z128VMP4
** MKL43Z64VMP4
**
** Compilers: Keil ARM C/C++ Compiler
** Freescale C/C++ for Embedded ARM
** GNU C Compiler
** GNU C Compiler - CodeSourcery Sourcery G++
** IAR ANSI C/C++ Compiler for ARM
**
** Reference manual: KL43P64M48SF6RM, Rev.3, Aug 2014
** Version: rev. 1.4, 2014-09-01
** Build: b140904
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright (c) 2014 Freescale Semiconductor, Inc.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of Freescale Semiconductor, Inc. nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.freescale.com
** mail: support@freescale.com
**
** Revisions:
** - rev. 1.0 (2014-03-27)
** Initial version.
** - rev. 1.1 (2014-05-26)
** I2S registers TCR2/RCR2 and others were changed.
** FLEXIO register FLEXIO_VERID has now bitfields: FEATURE, MINOR, MAJOR.
** Names of the bitfields of the FLEXIO_SHIFTBUF have been changed to the appropriate register name e.g.: FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS.
** Peripheral_BASES macros has been changed to Peripheral_BASE_PTRS, e.g.: ADC_BASES to ADC_BASE_PTRS.
** Clock configuration for high range external oscillator has been added.
** RFSYS module access has been added.
** - rev. 1.2 (2014-07-10)
** GPIO - Renamed modules PTA,PTB,PTC,PTD,PTE to GPIOA,GPIOB,GPIOC,GPIOD,GPIOE.
** UART0 - UART0 module renamed to UART2.
** I2S - removed MDR register.
** - rev. 1.3 (2014-08-21)
** UART2 - Removed ED register.
** UART2 - Removed MODEM register.
** UART2 - Removed IR register.
** UART2 - Removed PFIFO register.
** UART2 - Removed CFIFO register.
** UART2 - Removed SFIFO register.
** UART2 - Removed TWFIFO register.
** UART2 - Removed TCFIFO register.
** UART2 - Removed RWFIFO register.
** UART2 - Removed RCFIFO register.
** USB - Removed bitfield REG_EN in CLK_RECOVER_IRC_EN register.
** SIM - Changed bitfield value MCGIRCLK to LIRC_CLK of bitfield CLKOUTSEL in SOPT2 register.
** SIM - Removed bitfield DIEID in SDID register.
** - rev. 1.4 (2014-09-01)
** USB - USB0_CTL0 was renamed to USB0_OTGCTL register.
** USB - USB0_CTL1 was renamed to USB0_CTL register.
**
** ###################################################################
*/
/*!
* @file MKL43Z4
* @version 1.4
* @date 2014-09-01
* @brief Device specific configuration file for MKL43Z4 (header file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#ifndef SYSTEM_MKL43Z4_H_
#define SYSTEM_MKL43Z4_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifndef DISABLE_WDOG
#define DISABLE_WDOG 1
#endif
#define ACK_ISOLATION 1
#ifndef CLOCK_SETUP
#define CLOCK_SETUP 1
#endif
/* MCG_Lite mode constants */
#define MCG_MODE_LIRC_8M 0U
#define MCG_MODE_HIRC 1U
#define MCG_MODE_LIRC_2M 2U
#define MCG_MODE_EXT 3U
/* Predefined clock setups
0 ... Multipurpose Clock Generator Lite (MCG_Lite) in Low-frequency Internal Reference Clock 8 MHz (LIRC 8 MHz) mode
Default part configuration.
Core clock/Bus clock derived from the internal clock source 8 MHz
Core clock = 4MHz, BusClock = 2MHz, USB FS clock derived from external clock USB_CLKIN (applicable only for derivatived with USB)
1 ... Multipurpose Clock Generator Lite (MCG_Lite) in High-frequency Internal Reference Clock (HIRC) mode
Maximum achievable clock frequency configuration using internal clock.
Core clock/Bus clock derived from the internal clock source 48MHz
Core clock = 48MHz, BusClock = 24MHz, USB FS clock derived from external clock USB_CLKIN (applicable only for derivatived with USB)
2 ... Multipurpose Clock Generator Lite (MCG_Lite) in External Oscillator (EXT) mode
Core clock/Bus clock derived directly from the external crystal 32.768kHz
The clock settings is ready for Very Low Power Run mode.
Core clock = 32.768kHz, BusClock = 32.768kHz, USB FS clock derived from external clock USB_CLKIN (applicable only for derivatived with USB)
3 ... Multipurpose Clock Generator Lite (MCG_Lite) in Low-frequency Internal Reference Clock 2 MHz (LIRC 2 MHz) mode
Core clock/Bus clock derived from the internal clock source 2 MHz
The clock settings is ready for Very Low Power Run mode.
Core clock = 2MHz, BusClock = 1MHz, USB FS clock derived from external clock USB_CLKIN (applicable only for derivatived with USB)
4 ... Multipurpose Clock Generator Lite (MCG_Lite) in High-frequency Internal Reference Clock (HIRC) mode
USB clock setup - for USB to receive internal 48MHz clock derived from HIRC.
Core clock/Bus clock derived from the internal clock source 48MHz
Core clock = 48MHz, BusClock = 24MHz, USB FS clock derived from HIRC (MCGPCLK)
5 ... Multipurpose Clock Generator Lite (MCG_Lite) in External Oscillator (EXT) mode
Core clock/Bus clock derived directly from the external crystal 8 MHz
Core clock = 8MHz, BusClock = 4MHz, USB FS clock derived from external clock USB_CLKIN (applicable only for derivatived with USB)
*/
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 32768u /* Value of the external crystal or oscillator clock frequency in Hz */
#define CPU_INT_FAST_CLK_HZ 48000000u /* Value of the fast internal oscillator clock frequency in Hz */
#define CPU_INT_IRC_CLK_HZ 48000000u /* Value of the 48M internal oscillator clock frequency in Hz */
/* Low power mode enable */
/* SMC_PMPROT: AVLP=1,AVLLS=1 */
#define SMC_PMPROT_VALUE 0x22u /* SMC_PMPROT */
#if (CLOCK_SETUP == 0)
#define DEFAULT_SYSTEM_CLOCK 4000000u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 8000000u /* Value of the slow internal oscillator clock frequency in Hz */
#define MCG_MODE MCG_MODE_LIRC_8M /* Clock generator mode */
/* MCG_C1: CLKS=1,IRCLKEN=1,IREFSTEN=0 */
#define MCG_C1_VALUE 0x42u /* MCG_C1 */
/* MCG_C2: RANGE0=0,HGO0=0,EREFS0=0,IRCS=1 */
#define MCG_C2_VALUE 0x01u /* MCG_C2 */
/* MCG_SC: FCRDIV=0 */
#define MCG_SC_VALUE 0x00u /* MCG_SC */
/* MCG_MC: HIRCEN=0 LIRC_DIV2=0 */
#define MCG_MC_VALUE 0x00u /* MCG_MC */
/* OSC0_CR: ERCLKEN=0,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
#define OSC0_CR_VALUE 0x00u /* OSC0_CR */
/* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */
#define SMC_PMCTRL_VALUE 0x00u /* SMC_PMCTRL */
/* SIM_CLKDIV1: OUTDIV1=1,OUTDIV4=1 */
#define SYSTEM_SIM_CLKDIV1_VALUE 0x10010000u /* SIM_CLKDIV1 */
/* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */
#define SYSTEM_SIM_SOPT1_VALUE 0x00000000u /* SIM_SOPT1 */
/* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=3,FLEXIOSRC=0,USBSRC=0,CLKOUTSEL=0,RTCCLKOUTSEL=0 */
#define SYSTEM_SIM_SOPT2_VALUE 0x03000000u /* SIM_SOPT2 */
#elif (CLOCK_SETUP == 1)
#define DEFAULT_SYSTEM_CLOCK 48000000u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 8000000u /* Value of the slow internal oscillator clock frequency in Hz */
#define MCG_MODE MCG_MODE_HIRC /* Clock generator mode */
/* MCG_C1: CLKS=0,IRCLKEN=0,IREFSTEN=0 */
#define MCG_C1_VALUE 0x00u /* MCG_C1 */
/* MCG_C2: RANGE0=0,HGO0=0,EREFS0=0,IRCS=1 */
#define MCG_C2_VALUE 0x01u /* MCG_C2 */
/* MCG_SC: FCRDIV=0 */
#define MCG_SC_VALUE 0x00u /* MCG_SC */
/* MCG_MC: HIRCEN=1 LIRC_DIV2=0 */
#define MCG_MC_VALUE 0x80u /* MCG_MC */
/* OSC0_CR: ERCLKEN=0,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
#define OSC0_CR_VALUE 0x00u /* OSC0_CR */
/* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */
#define SMC_PMCTRL_VALUE 0x00u /* SMC_PMCTRL */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV4=1 */
#define SYSTEM_SIM_CLKDIV1_VALUE 0x10000u /* SIM_CLKDIV1 */
/* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */
#define SYSTEM_SIM_SOPT1_VALUE 0x00000000u /* SIM_SOPT1 */
/* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=3,FLEXIOSRC=0,USBSRC=0,CLKOUTSEL=0,RTCCLKOUTSEL=0 */
#define SYSTEM_SIM_SOPT2_VALUE 0x03000000U /* SIM_SOPT2 */
#elif (CLOCK_SETUP == 2)
#define DEFAULT_SYSTEM_CLOCK 32768u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 8000000u /* Value of the slow internal oscillator clock frequency in Hz */
#define MCG_MODE MCG_MODE_EXT /* Clock generator mode */
/* MCG_C1: CLKS=2,IRCLKEN=1,IREFSTEN=0 */
#define MCG_C1_VALUE 0x82u /* MCG_C1 */
/* MCG_C2: RANGE0=0,HGO0=0,EREFS0=1,IRCS=1 */
#define MCG_C2_VALUE 0x05u /* MCG_C2 */
/* MCG_SC: FCRDIV=0 */
#define MCG_SC_VALUE 0x00u /* MCG_SC */
/* MCG_MC: HIRCEN=0 LIRC_DIV2=0 */
#define MCG_MC_VALUE 0x00u /* MCG_MC */
/* OSC0_CR: ERCLKEN=1,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
#define OSC0_CR_VALUE 0x80u /* OSC0_CR */
/* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */
#define SMC_PMCTRL_VALUE 0x00u /* SMC_PMCTRL */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV4=0 */
#define SYSTEM_SIM_CLKDIV1_VALUE 0x00u /* SIM_CLKDIV1 */
/* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */
#define SYSTEM_SIM_SOPT1_VALUE 0x00000000u /* SIM_SOPT1 */
/* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=2,FLEXIOSRC=0,USBSRC=0,CLKOUTSEL=0,RTCCLKOUTSEL=0 */
#define SYSTEM_SIM_SOPT2_VALUE 0x02000000u /* SIM_SOPT2 */
#elif (CLOCK_SETUP == 3)
#define DEFAULT_SYSTEM_CLOCK 2000000u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 2000000u /* Value of the slow internal oscillator clock frequency in Hz */
#define MCG_MODE MCG_MODE_LIRC_2M /* Clock generator mode */
/* MCG_C1: CLKS=1,IRCLKEN=1,IREFSTEN=0 */
#define MCG_C1_VALUE 0x42u /* MCG_C1 */
/* MCG_C2: RANGE0=0,HGO0=0,EREFS0=0,IRCS=0 */
#define MCG_C2_VALUE 0x00u /* MCG_C2 */
/* MCG_SC: FCRDIV=0 */
#define MCG_SC_VALUE 0x00u /* MCG_SC */
/* MCG_MC: HIRCEN=0 LIRC_DIV2=0 */
#define MCG_MC_VALUE 0x00u /* MCG_MC */
/* OSC0_CR: ERCLKEN=0,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
#define OSC0_CR_VALUE 0x00u /* OSC0_CR */
/* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */
#define SMC_PMCTRL_VALUE 0x00u /* SMC_PMCTRL */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV4=1 */
#define SYSTEM_SIM_CLKDIV1_VALUE 0x10000u /* SIM_CLKDIV1 */
/* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */
#define SYSTEM_SIM_SOPT1_VALUE 0x00000000u /* SIM_SOPT1 */
/* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=3,FLEXIOSRC=0,USBSRC=0,CLKOUTSEL=0,RTCCLKOUTSEL=0 */
#define SYSTEM_SIM_SOPT2_VALUE 0x03000000u /* SIM_SOPT2 */
#elif (CLOCK_SETUP == 4)
#define DEFAULT_SYSTEM_CLOCK 2000000u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 8000000u /* Value of the slow internal oscillator clock frequency in Hz */
#define MCG_MODE MCG_MODE_LIRC_2M /* Clock generator mode */
/* MCG_C1: CLKS=0,IRCLKEN=1,IREFSTEN=0 */
#define MCG_C1_VALUE 0x02u /* MCG_C1 */
/* MCG_C2: RANGE0=0,HGO0=0,EREFS0=0,IRCS=1 */
#define MCG_C2_VALUE 0x01u /* MCG_C2 */
/* MCG_SC: FCRDIV=0 */
#define MCG_SC_VALUE 0x00u /* MCG_SC */
/* MCG_MC: HIRCEN=1 LIRC_DIV2=0 */
#define MCG_MC_VALUE 0x80u /* MCG_MC */
/* OSC0_CR: ERCLKEN=0,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
#define OSC0_CR_VALUE 0x00u /* OSC0_CR */
/* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */
#define SMC_PMCTRL_VALUE 0x00u /* SMC_PMCTRL */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV4=1 */
#define SYSTEM_SIM_CLKDIV1_VALUE 0x10000u /* SIM_CLKDIV1 */
/* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */
#define SYSTEM_SIM_SOPT1_VALUE 0x00000000u /* SIM_SOPT1 */
/* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=3,FLEXIOSRC=0,USBSRC=1,CLKOUTSEL=0,RTCCLKOUTSEL=0 */
#define SYSTEM_SIM_SOPT2_VALUE 0x03040000u /* SIM_SOPT2 */
#elif (CLOCK_SETUP == 5)
#define DEFAULT_SYSTEM_CLOCK 2000000u /* Default System clock value */
#define CPU_INT_SLOW_CLK_HZ 2000000u /* Value of the slow internal oscillator clock frequency in Hz */
#define MCG_MODE MCG_MODE_LIRC_2M /* Clock generator mode */
/* MCG_C1: CLKS=2,IRCLKEN=0,IREFSTEN=0 */
#define MCG_C1_VALUE 0x80u /* MCG_C1 */
/* MCG_C2: RANGE0=1,HGO0=0,EREFS0=1,IRCS=1 */
#define MCG_C2_VALUE 0x15u /* MCG_C2 */
/* MCG_SC: FCRDIV=0 */
#define MCG_SC_VALUE 0x00u /* MCG_SC */
/* MCG_MC: HIRCEN=0 LIRC_DIV2=0 */
#define MCG_MC_VALUE 0x00u /* MCG_MC */
/* OSC0_CR: ERCLKEN=1,EREFSTEN=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
#define OSC0_CR_VALUE 0x80u /* OSC0_CR */
/* SMC_PMCTRL: RUNM=0,STOPA=0,STOPM=0 */
#define SMC_PMCTRL_VALUE 0x00u /* SMC_PMCTRL */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV4=1 */
#define SYSTEM_SIM_CLKDIV1_VALUE 0x10000u /* SIM_CLKDIV1 */
/* SIM_SOPT1: OSC32KSEL=0,OSC32KOUT=0 */
#define SYSTEM_SIM_SOPT1_VALUE 0x00000000u /* SIM_SOPT1 */
/* SIM_SOPT2: LPUART1SRC=0,LPUART0SRC=0,TPMSRC=3,FLEXIOSRC=0,USBSRC=0,CLKOUTSEL=0,RTCCLKOUTSEL=0 */
#define SYSTEM_SIM_SOPT2_VALUE 0x03000000u /* SIM_SOPT2 */
#else
#error The selected clock setup is not supported.
#endif /* (CLOCK_SETUP == 5) */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* #if !defined(SYSTEM_MKL43Z4_H_) */

View File

@ -1,94 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
OSC32KCLK = 0,
RTC_CLKIN = 2
} RTCName;
typedef enum {
UART_0 = (int)LPUART0_BASE,
UART_1 = (int)LPUART1_BASE,
UART_2 = (int)UART2_BASE
} UARTName;
#define STDIO_UART_TX USBTX
#define STDIO_UART_RX USBRX
#define STDIO_UART UART_0
typedef enum {
I2C_0 = (int)I2C0_BASE,
I2C_1 = (int)I2C1_BASE,
} I2CName;
#define TPM_SHIFT 8
typedef enum {
PWM_1 = (0 << TPM_SHIFT) | (0), // TPM0 CH0
PWM_2 = (0 << TPM_SHIFT) | (1), // TPM0 CH1
PWM_3 = (0 << TPM_SHIFT) | (2), // TPM0 CH2
PWM_4 = (0 << TPM_SHIFT) | (3), // TPM0 CH3
PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4
PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5
PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0
PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1
PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0
PWM_10 = (2 << TPM_SHIFT) | (1) // TPM2 CH1
} PWMName;
#define CHANNELS_A_SHIFT 5
typedef enum {
ADC0_SE0 = 0,
ADC0_SE3 = 3,
ADC0_SE4a = (1 << CHANNELS_A_SHIFT) | (4),
ADC0_SE4b = 4,
ADC0_SE5b = 5,
ADC0_SE6b = 6,
ADC0_SE7a = (1 << CHANNELS_A_SHIFT) | (7),
ADC0_SE7b = 7,
ADC0_SE8 = 8,
ADC0_SE9 = 9,
ADC0_SE11 = 11,
ADC0_SE12 = 12,
ADC0_SE13 = 13,
ADC0_SE14 = 14,
ADC0_SE15 = 15,
ADC0_SE23 = 23
} ADCName;
typedef enum {
DAC_0 = 0
} DACName;
typedef enum {
SPI_0 = (int)SPI0_BASE,
SPI_1 = (int)SPI1_BASE,
} SPIName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,258 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
#define PORT_SHIFT 12
typedef enum {
PTA0 = 0x0,
PTA1 = 0x4,
PTA2 = 0x8,
PTA3 = 0xc,
PTA4 = 0x10,
PTA5 = 0x14,
PTA6 = 0x18,
PTA7 = 0x1c,
PTA8 = 0x20,
PTA9 = 0x24,
PTA10 = 0x28,
PTA11 = 0x2c,
PTA12 = 0x30,
PTA13 = 0x34,
PTA14 = 0x38,
PTA15 = 0x3c,
PTA16 = 0x40,
PTA17 = 0x44,
PTA18 = 0x48,
PTA19 = 0x4c,
PTA20 = 0x50,
PTA21 = 0x54,
PTA22 = 0x58,
PTA23 = 0x5c,
PTA24 = 0x60,
PTA25 = 0x64,
PTA26 = 0x68,
PTA27 = 0x6c,
PTA28 = 0x70,
PTA29 = 0x74,
PTA30 = 0x78,
PTA31 = 0x7c,
PTB0 = 0x1000,
PTB1 = 0x1004,
PTB2 = 0x1008,
PTB3 = 0x100c,
PTB4 = 0x1010,
PTB5 = 0x1014,
PTB6 = 0x1018,
PTB7 = 0x101c,
PTB8 = 0x1020,
PTB9 = 0x1024,
PTB10 = 0x1028,
PTB11 = 0x102c,
PTB12 = 0x1030,
PTB13 = 0x1034,
PTB14 = 0x1038,
PTB15 = 0x103c,
PTB16 = 0x1040,
PTB17 = 0x1044,
PTB18 = 0x1048,
PTB19 = 0x104c,
PTB20 = 0x1050,
PTB21 = 0x1054,
PTB22 = 0x1058,
PTB23 = 0x105c,
PTB24 = 0x1060,
PTB25 = 0x1064,
PTB26 = 0x1068,
PTB27 = 0x106c,
PTB28 = 0x1070,
PTB29 = 0x1074,
PTB30 = 0x1078,
PTB31 = 0x107c,
PTC0 = 0x2000,
PTC1 = 0x2004,
PTC2 = 0x2008,
PTC3 = 0x200c,
PTC4 = 0x2010,
PTC5 = 0x2014,
PTC6 = 0x2018,
PTC7 = 0x201c,
PTC8 = 0x2020,
PTC9 = 0x2024,
PTC10 = 0x2028,
PTC11 = 0x202c,
PTC12 = 0x2030,
PTC13 = 0x2034,
PTC14 = 0x2038,
PTC15 = 0x203c,
PTC16 = 0x2040,
PTC17 = 0x2044,
PTC18 = 0x2048,
PTC19 = 0x204c,
PTC20 = 0x2050,
PTC21 = 0x2054,
PTC22 = 0x2058,
PTC23 = 0x205c,
PTC24 = 0x2060,
PTC25 = 0x2064,
PTC26 = 0x2068,
PTC27 = 0x206c,
PTC28 = 0x2070,
PTC29 = 0x2074,
PTC30 = 0x2078,
PTC31 = 0x207c,
PTD0 = 0x3000,
PTD1 = 0x3004,
PTD2 = 0x3008,
PTD3 = 0x300c,
PTD4 = 0x3010,
PTD5 = 0x3014,
PTD6 = 0x3018,
PTD7 = 0x301c,
PTD8 = 0x3020,
PTD9 = 0x3024,
PTD10 = 0x3028,
PTD11 = 0x302c,
PTD12 = 0x3030,
PTD13 = 0x3034,
PTD14 = 0x3038,
PTD15 = 0x303c,
PTD16 = 0x3040,
PTD17 = 0x3044,
PTD18 = 0x3048,
PTD19 = 0x304c,
PTD20 = 0x3050,
PTD21 = 0x3054,
PTD22 = 0x3058,
PTD23 = 0x305c,
PTD24 = 0x3060,
PTD25 = 0x3064,
PTD26 = 0x3068,
PTD27 = 0x306c,
PTD28 = 0x3070,
PTD29 = 0x3074,
PTD30 = 0x3078,
PTD31 = 0x307c,
PTE0 = 0x4000,
PTE1 = 0x4004,
PTE2 = 0x4008,
PTE3 = 0x400c,
PTE4 = 0x4010,
PTE5 = 0x4014,
PTE6 = 0x4018,
PTE7 = 0x401c,
PTE8 = 0x4020,
PTE9 = 0x4024,
PTE10 = 0x4028,
PTE11 = 0x402c,
PTE12 = 0x4030,
PTE13 = 0x4034,
PTE14 = 0x4038,
PTE15 = 0x403c,
PTE16 = 0x4040,
PTE17 = 0x4044,
PTE18 = 0x4048,
PTE19 = 0x404c,
PTE20 = 0x4050,
PTE21 = 0x4054,
PTE22 = 0x4058,
PTE23 = 0x405c,
PTE24 = 0x4060,
PTE25 = 0x4064,
PTE26 = 0x4068,
PTE27 = 0x406c,
PTE28 = 0x4070,
PTE29 = 0x4074,
PTE30 = 0x4078,
PTE31 = 0x407c,
LED_RED = PTE31,
LED_GREEN = PTD5,
// mbed original LED naming
LED1 = LED_GREEN,
LED2 = LED_RED,
LED3 = LED_GREEN,
LED4 = LED_RED,
//Push buttons
SW1 = PTA4,
SW3 = PTC3,
// USB Pins
USBTX = PTA2,
USBRX = PTA1,
// Arduino Headers
D0 = PTA1,
D1 = PTA2,
D2 = PTD3,
D3 = PTA12,
D4 = PTA4,
D5 = PTA5,
D6 = PTE29,
D7 = PTE30,
D8 = PTA13,
D9 = PTD2,
D10 = PTD4,
D11 = PTD6,
D12 = PTD7,
D13 = PTD5,
D14 = PTE0,
D15 = PTE1,
A0 = PTB0,
A1 = PTB1,
A2 = PTB2,
A3 = PTB3,
A4 = PTC2,
A5 = PTC1,
I2C_SCL = D15,
I2C_SDA = D14,
TSI_ELEC0 = PTB16,
TSI_ELEC1 = PTB17,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
/* Pull modes for input pins */
typedef enum {
PullNone = 0,
PullDown = 2,
PullUp = 3,
PullDefault = PullUp
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,191 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include "cmsis.h"
#include "gpio_irq_api.h"
#include "gpio_api.h"
#include "mbed_error.h"
#define CHANNEL_NUM 96
static uint32_t channel_ids[CHANNEL_NUM] = {0};
static gpio_irq_handler irq_handler;
#define IRQ_DISABLED (0)
#define IRQ_RAISING_EDGE PORT_PCR_IRQC(9)
#define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
#define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
const uint32_t search_bits[] = {0x0000FFFF, 0x000000FF, 0x0000000F, 0x00000003, 0x00000001};
static void handle_interrupt_in(PORT_Type *port, int ch_base) {
uint32_t isfr;
uint8_t location;
while((isfr = port->ISFR) != 0) {
location = 0;
for (int i = 0; i < 5; i++) {
if (!(isfr & (search_bits[i] << location)))
location += 1 << (4 - i);
}
uint32_t id = channel_ids[ch_base + location];
if (id == 0) {
continue;
}
GPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[location] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
if (port == PORTA) {
gpio = GPIOA;
} else if (port == PORTC) {
gpio = GPIOC;
} else {
gpio = GPIOD;
}
event = (gpio->PDIR & (1<<location)) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
port->ISFR = 1 << location;
}
}
void gpio_irqA(void) {
handle_interrupt_in(PORTA, 0);
}
/* PORTC and PORTD share same vector */
void gpio_irqCD(void) {
if ((SIM->SCGC5 & SIM_SCGC5_PORTC_MASK) && (PORTC->ISFR)) {
handle_interrupt_in(PORTC, 32);
} else if ((SIM->SCGC5 & SIM_SCGC5_PORTD_MASK) && (PORTD->ISFR)) {
handle_interrupt_in(PORTD, 64);
}
}
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
if (pin == NC)
return -1;
irq_handler = handler;
obj->port = pin >> PORT_SHIFT;
obj->pin = (pin & 0x7F) >> 2;
uint32_t ch_base, vector;
IRQn_Type irq_n;
switch (obj->port) {
case PortA:
ch_base = 0; irq_n = PORTA_IRQn; vector = (uint32_t)gpio_irqA;
break;
case PortC:
ch_base = 32; irq_n = PORTCD_IRQn; vector = (uint32_t)gpio_irqCD;
break;
case PortD:
ch_base = 64; irq_n = PORTCD_IRQn; vector = (uint32_t)gpio_irqCD;
break;
default:
error("gpio_irq only supported on port A,C and D");
break;
}
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
obj->ch = ch_base + obj->pin;
channel_ids[obj->ch] = id;
return 0;
}
void gpio_irq_free(gpio_irq_t *obj) {
channel_ids[obj->ch] = 0;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
PORT_Type *port = (PORT_Type *)(PORTA_BASE + 0x1000 * obj->port);
uint32_t irq_settings = IRQ_DISABLED;
switch (port->PCR[obj->pin] & PORT_PCR_IRQC_MASK) {
case IRQ_DISABLED:
if (enable) {
irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_FALLING_EDGE);
}
break;
case IRQ_RAISING_EDGE:
if (enable) {
irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_EITHER_EDGE);
} else {
if (event == IRQ_FALL)
irq_settings = IRQ_RAISING_EDGE;
}
break;
case IRQ_FALLING_EDGE:
if (enable) {
irq_settings = (event == IRQ_FALL) ? (IRQ_FALLING_EDGE) : (IRQ_EITHER_EDGE);
} else {
if (event == IRQ_RISE)
irq_settings = IRQ_FALLING_EDGE;
}
break;
case IRQ_EITHER_EDGE:
if (enable) {
irq_settings = IRQ_EITHER_EDGE;
} else {
irq_settings = (event == IRQ_RISE) ? (IRQ_FALLING_EDGE) : (IRQ_RAISING_EDGE);
}
break;
}
// Interrupt configuration and clear interrupt
port->PCR[obj->pin] = (port->PCR[obj->pin] & ~PORT_PCR_IRQC_MASK) | irq_settings | PORT_PCR_ISF_MASK;
}
void gpio_irq_enable(gpio_irq_t *obj) {
if (obj->port == PortA) {
NVIC_EnableIRQ(PORTA_IRQn);
} else {
NVIC_EnableIRQ(PORTCD_IRQn);
}
}
void gpio_irq_disable(gpio_irq_t *obj) {
if (obj->port == PortA) {
NVIC_DisableIRQ(PORTA_IRQn);
} else {
NVIC_DisableIRQ(PORTCD_IRQn);
}
}

View File

@ -1,316 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "serial_api.h"
// math.h required for floating point operations for baud rate calculation
#include <math.h>
#include <string.h>
#include "cmsis.h"
#include "pinmap.h"
#include "clk_freqs.h"
#include "PeripheralPins.h"
#define UART_NUM 2
/******************************************************************************
* INITIALIZATION
******************************************************************************/
static uint32_t serial_irq_ids[UART_NUM] = {0};
static uart_irq_handler irq_handler;
int stdio_uart_inited = 0;
serial_t stdio_uart;
static inline uint32_t serial_get_src_clock(serial_t *obj) {
uint32_t mux, srcclk;
switch ((int)obj->uart) {
case UART_0:
mux = (SIM->SOPT2 & SIM_SOPT2_LPUART0SRC_MASK) >> SIM_SOPT2_LPUART0SRC_SHIFT;
break;
case UART_1:
mux = (SIM->SOPT2 & SIM_SOPT2_LPUART1SRC_MASK) >> SIM_SOPT2_LPUART1SRC_SHIFT;
break;
case UART_2: /* TODO: add UART2 support */ break;
}
switch (mux) {
case 1: srcclk = fastirc_frequency(); break;
case 2: srcclk = extosc_frequency(); break;
case 3: srcclk = mcgirc_frequency(); break;
default: srcclk = 0; break;
}
return srcclk;
}
void serial_init(serial_t *obj, PinName tx, PinName rx) {
// determine the UART to use
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
MBED_ASSERT((int)uart != NC);
obj->uart = (LPUART_Type *)uart;
// enable clk
switch (uart) {
case UART_0:
SIM->SOPT2 |= SIM_SOPT2_LPUART0SRC(1);
SIM->SCGC5 |= SIM_SCGC5_LPUART0_MASK;
break;
case UART_1:
SIM->SOPT2 |= SIM_SOPT2_LPUART1SRC(1);
SIM->SCGC5 |= SIM_SCGC5_LPUART1_MASK;
break;
case UART_2: /* TODO: add UART2 support */ break;
}
// reset UART registers
obj->uart->BAUD = 0x0F000004;
obj->uart->STAT = 0xC01FC000;
obj->uart->CTRL = 0x00000000;
obj->uart->MATCH = 0x00000000;
switch (uart) {
case UART_0: obj->index = 0; break;
case UART_1: obj->index = 1; break;
case UART_2: /* TODO: add UART2 support */ break;
}
// set default baud rate and format
serial_baud (obj, 9600);
serial_format(obj, 8, ParityNone, 1);
// pinout the chosen uart
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
// set rx/tx pins in PullUp mode
if (tx != NC) pin_mode(tx, PullUp);
if (rx != NC) pin_mode(rx, PullUp);
obj->uart->CTRL |= (LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK);
if (uart == STDIO_UART) {
stdio_uart_inited = 1;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
}
void serial_free(serial_t *obj) {
serial_irq_ids[obj->index] = 0;
}
// serial_baud
//
// set the baud rate, taking in to account the current SystemFrequency
void serial_baud(serial_t *obj, int baudrate) {
int calcBaudrate;
uint32_t i, sbr, sbrTemp, osr, temp, baud, baudDiff;
/* get value of serial source clock */
uint32_t PCLK = serial_get_src_clock(obj);
/* loop to find the best osr value possible, one that generates minimum baudDiff
* iterate through the rest of the supported values of osr */
temp = 0xFFFFFFFF;
for (i = 5; i <= 33; i++) {
/* calculate the temporary sbr value */
sbrTemp = PCLK / (baudrate * i);
/* calculate the baud rate based on the temporary osr and sbr values */
calcBaudrate = PCLK / (i * sbrTemp);
if (calcBaudrate > baudrate) {
baudDiff = calcBaudrate - baudrate;
} else {
baudDiff = baudrate - calcBaudrate;
}
if (baudDiff < temp) {
osr = i - 1; /* update and store the best osr value calculated */
sbr = sbrTemp; /* update store the best sbr value calculated */
if(baudDiff == 0) {
break; /* end for loop if founded the best osr and sbr value */
} else {
temp = baudDiff;
}
}
}
/* save C2 state */
temp = obj->uart->CTRL & (LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK);
/* disable UART before changing registers */
obj->uart->CTRL &= ~(LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK);
/* read BAUD register with clearing old baudrate settings into baud variable */
baud = obj->uart->BAUD & ~(LPUART_BAUD_SBR_MASK | LPUART_BAUD_OSR_MASK | LPUART_BAUD_BOTHEDGE_MASK);
/* write the new osr and sbr values */
baud |= (LPUART_BAUD_SBR(sbr) | LPUART_BAUD_OSR(osr));
/* Check if osr is between 4x and 7x oversampling.
* If so, then "BOTHEDGE" sampling must be turned on */
if ((osr > 3) && (osr < 8)) {
baud |= LPUART_BAUD_BOTHEDGE_MASK;
}
/* write new values into BAUD register */
obj->uart->BAUD = baud;
/* restore C2 state */
obj->uart->CTRL |= temp;
}
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
MBED_ASSERT((stop_bits == 1) || (stop_bits == 2));
MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven));
MBED_ASSERT(data_bits == 8); // TODO: Support other number of data bits (also in the write method!)
// save C2 state
uint32_t c2_state = obj->uart->CTRL & (LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK);
// disable UART before changing registers
obj->uart->CTRL &= ~(LPUART_CTRL_RE_MASK | LPUART_CTRL_TE_MASK);
uint8_t parity_enable = 0, parity_select = 0;
switch (parity) {
case ParityNone: parity_enable = 0; parity_select = 0; break;
case ParityOdd : parity_enable = 1; parity_select = 1; data_bits++; break;
case ParityEven: parity_enable = 1; parity_select = 0; data_bits++; break;
default:
break;
}
stop_bits -= 1;
// data bits, parity and parity mode
obj->uart->CTRL = ((parity_enable << 1) | (parity_select << 0));
// stop bits
obj->uart->BAUD &= ~LPUART_BAUD_SBNS_MASK;
obj->uart->BAUD |= (stop_bits << LPUART_BAUD_SBNS_SHIFT);
// restore C2 state
obj->uart->CTRL |= c2_state;
}
/******************************************************************************
* INTERRUPTS HANDLING
******************************************************************************/
static inline void uart_irq(uint32_t status, uint32_t index) {
if (serial_irq_ids[index] != 0) {
if (status & LPUART_STAT_TDRE_MASK)
irq_handler(serial_irq_ids[index], TxIrq);
if (status & LPUART_STAT_RDRF_MASK)
irq_handler(serial_irq_ids[index], RxIrq);
}
}
void uart0_irq() {uart_irq(LPUART0->STAT, 0);}
void uart1_irq() {uart_irq(LPUART1->STAT, 1);}
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
irq_handler = handler;
serial_irq_ids[obj->index] = id;
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
IRQn_Type irq_n = (IRQn_Type)0;
uint32_t vector = 0;
switch ((int)obj->uart) {
case UART_0: irq_n=LPUART0_IRQn; vector = (uint32_t)&uart0_irq; break;
case UART_1: irq_n=LPUART1_IRQn; vector = (uint32_t)&uart1_irq; break;
}
if (enable) {
switch (irq) {
case RxIrq: obj->uart->CTRL |= LPUART_CTRL_RIE_MASK; break;
case TxIrq: obj->uart->CTRL |= LPUART_CTRL_TIE_MASK; break;
}
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
} else { // disable
int all_disabled = 0;
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
switch (irq) {
case RxIrq: obj->uart->CTRL &= ~(LPUART_CTRL_RIE_MASK); break;
case TxIrq: obj->uart->CTRL &= ~(LPUART_CTRL_TIE_MASK); break;
}
switch (other_irq) {
case RxIrq: all_disabled = (obj->uart->CTRL & LPUART_CTRL_RIE_MASK) == 0; break;
case TxIrq: all_disabled = (obj->uart->CTRL & LPUART_CTRL_TIE_MASK) == 0; break;
}
if (all_disabled)
NVIC_DisableIRQ(irq_n);
}
}
/******************************************************************************
* READ/WRITE
******************************************************************************/
int serial_getc(serial_t *obj) {
while (!serial_readable(obj));
return (obj->uart->DATA & 0xFFu);
}
void serial_putc(serial_t *obj, int c) {
while (!serial_writable(obj));
obj->uart->DATA = c;
}
int serial_readable(serial_t *obj) {
// check overrun
if (obj->uart->STAT & LPUART_STAT_OR_MASK) {
obj->uart->STAT |= LPUART_STAT_OR_MASK;
}
return (obj->uart->STAT & LPUART_STAT_RDRF_MASK);
}
int serial_writable(serial_t *obj) {
// check overrun
if (obj->uart->STAT & LPUART_STAT_OR_MASK) {
obj->uart->STAT |= LPUART_STAT_OR_MASK;
}
return (obj->uart->STAT & LPUART_STAT_TDRE_MASK);
}
void serial_clear(serial_t *obj) {
}
void serial_pinout_tx(PinName tx) {
pinmap_pinout(tx, PinMap_UART_TX);
}
void serial_break_set(serial_t *obj) {
obj->uart->CTRL |= LPUART_CTRL_SBK_MASK;
}
void serial_break_clear(serial_t *obj) {
obj->uart->CTRL &= ~LPUART_CTRL_SBK_MASK;
}

View File

@ -1,210 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "spi_api.h"
#include <math.h>
#include "cmsis.h"
#include "pinmap.h"
static const PinMap PinMap_SPI_SCLK[] = {
{PTC3, SPI_1, 2},
{PTC5, SPI_0, 2},
{PTD1, SPI_0, 2},
{PTD5, SPI_1, 2},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_MOSI[] = {
{PTB16, SPI_1, 2},
{PTB17, SPI_1, 5},
{PTC6, SPI_0, 2},
{PTC7, SPI_0, 5},
{PTD2, SPI_0, 2},
{PTD3, SPI_0, 5},
{PTD6, SPI_1, 2},
{PTD7, SPI_1, 5},
{PTE1, SPI_1, 2},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_MISO[] = {
{PTB16, SPI_1, 5},
{PTB17, SPI_1, 2},
{PTC6, SPI_0, 5},
{PTC7, SPI_0, 2},
{PTD2, SPI_0, 5},
{PTD3, SPI_0, 2},
{PTD6, SPI_1, 5},
{PTD7, SPI_1, 2},
{PTE0, SPI_1, 2},
{PTE1, SPI_1, 5},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_SSEL[] = {
{PTC4, SPI_0, 2},
{PTD0, SPI_0, 2},
{PTD4, SPI_1, 2},
{NC , NC , 0}
};
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
// determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
obj->spi = (SPI_Type*)pinmap_merge(spi_data, spi_cntl);
MBED_ASSERT((int)obj->spi != NC);
// enable power and clocking
switch ((int)obj->spi) {
case SPI_0: SIM->SCGC5 |= 1 << 13; SIM->SCGC4 |= 1 << 22; break;
case SPI_1: SIM->SCGC5 |= 1 << 13; SIM->SCGC4 |= 1 << 23; break;
}
// enable SPI
obj->spi->C1 |= SPI_C1_SPE_MASK;
obj->spi->C2 &= ~SPI_C2_SPIMODE_MASK; //8bit
// pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
pinmap_pinout(sclk, PinMap_SPI_SCLK);
if (ssel != NC) {
pinmap_pinout(ssel, PinMap_SPI_SSEL);
}
}
void spi_free(spi_t *obj) {
// [TODO]
}
void spi_format(spi_t *obj, int bits, int mode, int slave) {
MBED_ASSERT((bits == 8) || (bits == 16));
MBED_ASSERT((mode >= 0) && (mode <= 3));
uint8_t polarity = (mode & 0x2) ? 1 : 0;
uint8_t phase = (mode & 0x1) ? 1 : 0;
uint8_t c1_data = ((!slave) << 4) | (polarity << 3) | (phase << 2);
// clear MSTR, CPOL and CPHA bits
obj->spi->C1 &= ~(0x7 << 2);
// write new value
obj->spi->C1 |= c1_data;
if (bits == 8) {
obj->spi->C2 &= ~SPI_C2_SPIMODE_MASK;
} else {
obj->spi->C2 |= SPI_C2_SPIMODE_MASK;
}
}
void spi_frequency(spi_t *obj, int hz) {
uint32_t error = 0;
uint32_t p_error = 0xffffffff;
uint32_t ref = 0;
uint8_t spr = 0;
uint8_t ref_spr = 0;
uint8_t ref_prescaler = 0;
// bus clk
uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
uint8_t prescaler = 1;
uint8_t divisor = 2;
for (prescaler = 1; prescaler <= 8; prescaler++) {
divisor = 2;
for (spr = 0; spr <= 8; spr++, divisor *= 2) {
ref = PCLK / (prescaler*divisor);
if (ref > (uint32_t)hz)
continue;
error = hz - ref;
if (error < p_error) {
ref_spr = spr;
ref_prescaler = prescaler - 1;
p_error = error;
}
}
}
// set SPPR and SPR
obj->spi->BR = ((ref_prescaler & 0x7) << 4) | (ref_spr & 0xf);
}
static inline int spi_writeable(spi_t * obj) {
return (obj->spi->S & SPI_S_SPTEF_MASK) ? 1 : 0;
}
static inline int spi_readable(spi_t * obj) {
return (obj->spi->S & SPI_S_SPRF_MASK) ? 1 : 0;
}
int spi_master_write(spi_t *obj, int value) {
int ret;
if (obj->spi->C2 & SPI_C2_SPIMODE_MASK) {
// 16bit
while(!spi_writeable(obj));
obj->spi->DL = (value & 0xff);
obj->spi->DH = ((value >> 8) & 0xff);
// wait rx buffer full
while (!spi_readable(obj));
ret = obj->spi->DH;
ret = (ret << 8) | obj->spi->DL;
} else {
//8bit
while(!spi_writeable(obj));
obj->spi->DL = (value & 0xff);
// wait rx buffer full
while (!spi_readable(obj));
ret = (obj->spi->DL & 0xff);
}
return ret;
}
int spi_slave_receive(spi_t *obj) {
return spi_readable(obj);
}
int spi_slave_read(spi_t *obj) {
int ret;
if (obj->spi->C2 & SPI_C2_SPIMODE_MASK) {
ret = obj->spi->DH;
ret = ((ret << 8) | obj->spi->DL);
} else {
ret = obj->spi->DL;
}
return ret;
}
void spi_slave_write(spi_t *obj, int value) {
while (!spi_writeable(obj));
if (obj->spi->C2 & SPI_C2_SPIMODE_MASK) {
obj->spi->DL = (value & 0xff);
obj->spi->DH = ((value >> 8) & 0xff);
} else {
obj->spi->DL = value;
}
}

View File

@ -0,0 +1,101 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
OSC32KCLK = 0,
} RTCName;
/* LPUART */
typedef enum {
LPUART_0 = 0,
LPUART_1 = 1,
} UARTName;
#define STDIO_UART_TX USBTX
#define STDIO_UART_RX USBRX
#define STDIO_UART LPUART_0
typedef enum {
I2C_0 = 0,
I2C_1 = 1,
} I2CName;
#define TPM_SHIFT 8
typedef enum {
PWM_1 = (0 << TPM_SHIFT) | (0), // TPM0 CH0
PWM_2 = (0 << TPM_SHIFT) | (1), // TPM0 CH1
PWM_3 = (0 << TPM_SHIFT) | (2), // TPM0 CH2
PWM_4 = (0 << TPM_SHIFT) | (3), // TPM0 CH3
PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4
PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5
PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0
PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1
PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0
PWM_10 = (2 << TPM_SHIFT) | (1), // TPM2 CH1
} PWMName;
#define ADC_INSTANCE_SHIFT 8
#define ADC_B_CHANNEL_SHIFT 5
typedef enum {
ADC0_SE0 = (0 << ADC_INSTANCE_SHIFT) | 0,
ADC0_SE1 = (0 << ADC_INSTANCE_SHIFT) | 1,
ADC0_SE2 = (0 << ADC_INSTANCE_SHIFT) | 2,
ADC0_SE3 = (0 << ADC_INSTANCE_SHIFT) | 3,
ADC0_SE4a = (0 << ADC_INSTANCE_SHIFT) | 4,
ADC0_SE5a = (0 << ADC_INSTANCE_SHIFT) | 5,
ADC0_SE6a = (0 << ADC_INSTANCE_SHIFT) | 6,
ADC0_SE7a = (0 << ADC_INSTANCE_SHIFT) | 7,
ADC0_SE4b = (0 << ADC_INSTANCE_SHIFT) | (1 << ADC_B_CHANNEL_SHIFT) | 4,
ADC0_SE5b = (0 << ADC_INSTANCE_SHIFT) | (1 << ADC_B_CHANNEL_SHIFT) | 5,
ADC0_SE6b = (0 << ADC_INSTANCE_SHIFT) | (1 << ADC_B_CHANNEL_SHIFT) | 6,
ADC0_SE7b = (0 << ADC_INSTANCE_SHIFT) | (1 << ADC_B_CHANNEL_SHIFT) | 7,
ADC0_SE8 = (0 << ADC_INSTANCE_SHIFT) | 8,
ADC0_SE9 = (0 << ADC_INSTANCE_SHIFT) | 9,
ADC0_SE11 = (0 << ADC_INSTANCE_SHIFT) | 11,
ADC0_SE12 = (0 << ADC_INSTANCE_SHIFT) | 12,
ADC0_SE13 = (0 << ADC_INSTANCE_SHIFT) | 13,
ADC0_SE14 = (0 << ADC_INSTANCE_SHIFT) | 14,
ADC0_SE15 = (0 << ADC_INSTANCE_SHIFT) | 15,
ADC0_SE16 = (0 << ADC_INSTANCE_SHIFT) | 16,
ADC0_SE17 = (0 << ADC_INSTANCE_SHIFT) | 17,
ADC0_SE18 = (0 << ADC_INSTANCE_SHIFT) | 18,
ADC0_SE21 = (0 << ADC_INSTANCE_SHIFT) | 21,
ADC0_SE22 = (0 << ADC_INSTANCE_SHIFT) | 22,
ADC0_SE23 = (0 << ADC_INSTANCE_SHIFT) | 23,
} ADCName;
typedef enum {
SPI_0 = 0,
SPI_1 = 1,
} SPIName;
typedef enum {
DAC_0 = 0
} DACName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "PeripheralPins.h"
/************RTC***************/
const PinMap PinMap_RTC[] = {
{NC, OSC32KCLK, 0},
{NC, OSC32KCLK, 0},
};
/************ADC***************/
@ -29,12 +29,12 @@ const PinMap PinMap_ADC[] = {
{PTE29, ADC0_SE4b, 0},
{PTE30, ADC0_SE23, 0},
{PTE23, ADC0_SE7a, 0},
{PTB0, ADC0_SE8, 0},
{PTB1, ADC0_SE9, 0},
{PTB2, ADC0_SE12, 0},
{PTB3, ADC0_SE13, 0},
{PTC0, ADC0_SE14, 0},
{PTC1, ADC0_SE15, 0},
{PTB0 , ADC0_SE8 , 0},
{PTB1 , ADC0_SE9 , 0},
{PTB2 , ADC0_SE12, 0},
{PTB3 , ADC0_SE13, 0},
{PTC0 , ADC0_SE14, 0},
{PTC1 , ADC0_SE15, 0},
{PTC2, ADC0_SE11, 0},
{PTD1, ADC0_SE5b, 0},
{PTD5, ADC0_SE6b, 0},
@ -45,100 +45,94 @@ const PinMap PinMap_ADC[] = {
/************DAC***************/
const PinMap PinMap_DAC[] = {
{PTE30, DAC_0, 0},
{NC , NC , 0}
{NC , NC , 0}
};
/************I2C***************/
const PinMap PinMap_I2C_SDA[] = {
{PTA4, I2C_0, 2},
{PTB1, I2C_0, 2},
{PTB3, I2C_0, 2},
{PTC2, I2C_1, 2},
{PTB1 , I2C_0 , 2},
{PTB3 , I2C_0 , 2},
{PTC2 , I2C_1 , 2},
{PTE0, I2C_1, 6},
{PTE25, I2C_0, 5},
{NC , NC , 0}
{NC , NC , 0}
};
const PinMap PinMap_I2C_SCL[] = {
{PTA3, I2C_0, 2},
{PTB0, I2C_0, 2},
{PTB2, I2C_0, 2},
{PTC1, I2C_1, 2},
{PTB0 , I2C_0 , 2},
{PTB2 , I2C_0 , 2},
{PTC1 , I2C_1 , 2},
{PTE1, I2C_1, 6},
{PTE24, I2C_0, 5},
{NC , NC, 0}
{NC , NC , 0}
};
/************UART***************/
/************LPUART***************/
const PinMap PinMap_UART_TX[] = {
{PTA2, UART_0, 2},
{PTA19, UART_1, 3},
{PTB17, UART_0, 3},
{PTD3, UART_2, 3},
{PTD5, UART_2, 3},
{PTD7, UART_0, 3},
{PTE0, UART_1, 3},
{PTE20, UART_0, 4},
{PTE22, UART_2, 4},
{PTE30, UART_1, 5},
{NC , NC , 0}
{PTA2, LPUART_0 , 2},
{PTA19, LPUART_1 , 3},
{PTB17, LPUART_0 , 3},
{PTD7, LPUART_0 , 3},
{PTE0 , LPUART_1 , 3},
{PTE20 , LPUART_0 , 4},
{PTE30 , LPUART_1 , 5},
{NC , NC , 0}
};
const PinMap PinMap_UART_RX[] = {
{PTA1, UART_0, 2},
{PTA18, UART_1, 3},
{PTB16, UART_0, 3},
{PTC3, UART_1, 3},
{PTD2, UART_2, 3},
{PTD4, UART_2, 3},
{PTD6, UART_0, 3},
{PTE1, UART_1, 3},
{PTE21, UART_0, 4},
{PTE23, UART_2, 4},
{NC , NC , 0}
{PTA1, LPUART_0, 2},
{PTA18, LPUART_1, 3},
{PTB16, LPUART_0, 3},
{PTC3, LPUART_1, 3},
{PTD6, LPUART_0, 3},
{PTE1, LPUART_1, 3},
{PTE21, LPUART_0, 4},
{NC , NC , 0}
};
/************SPI***************/
const PinMap PinMap_SPI_SCLK[] = {
{PTC3, SPI_1, 2},
{PTC5, SPI_0, 2},
{PTD1, SPI_0, 2},
{PTD5, SPI_1, 2},
{NC , NC , 0}
{PTC5 , SPI_0, 2},
{PTD1 , SPI_0, 2},
{PTD5 , SPI_1, 2},
{NC , NC , 0}
};
const PinMap PinMap_SPI_MOSI[] = {
{PTB16, SPI_1, 2},
{PTB17, SPI_1, 5},
{PTC6, SPI_0, 2},
{PTC7, SPI_0, 5},
{PTD2, SPI_0, 2},
{PTD3, SPI_0, 5},
{PTD6, SPI_1, 2},
{PTD7, SPI_1, 5},
{PTC6 , SPI_0, 2},
{PTC7 , SPI_0, 5},
{PTD2 , SPI_0, 2},
{PTD3 , SPI_0, 5},
{PTD6 , SPI_1, 2},
{PTD7 , SPI_1, 5},
{PTE1, SPI_1, 2},
{NC , NC , 0}
{NC , NC , 0}
};
const PinMap PinMap_SPI_MISO[] = {
{PTB16, SPI_1, 5},
{PTB17, SPI_1, 2},
{PTC6, SPI_0, 5},
{PTC7, SPI_0, 2},
{PTD2, SPI_0, 5},
{PTD3, SPI_0, 2},
{PTD6, SPI_1, 5},
{PTD7, SPI_1, 2},
{PTC6 , SPI_0, 5},
{PTC7 , SPI_0, 2},
{PTD2 , SPI_0, 5},
{PTD3 , SPI_0, 2},
{PTD6 , SPI_1, 5},
{PTD7 , SPI_1, 2},
{PTE0, SPI_1, 2},
{PTE1, SPI_1, 5},
{NC , NC , 0}
};
const PinMap PinMap_SPI_SSEL[] = {
{PTC4, SPI_0, 2},
{PTD0, SPI_0, 2},
{PTD4, SPI_1, 2},
{NC , NC , 0}
{PTC4 , SPI_0, 2},
{PTD0 , SPI_0, 2},
{PTD4 , SPI_1, 2},
{NC , NC , 0}
};
/************PWM***************/
@ -151,7 +145,7 @@ const PinMap PinMap_PWM[] = {
{PTA5, PWM_3 , 3}, // PTA5 , TPM0 CH2
{PTA12, PWM_7 , 3}, // PTA12, TPM1 CH0
{PTA13, PWM_8 , 3}, // PTA13, TPM1 CH1
{PTB0, PWM_7, 3}, // PTB0 , TPM1 CH0
{PTB1, PWM_8, 3}, // PTB1 , TPM1 CH1
{PTB2, PWM_9, 3}, // PTB2 , TPM2 CH0
@ -163,7 +157,7 @@ const PinMap PinMap_PWM[] = {
{PTC2, PWM_2, 4}, // PTC2 , TPM0 CH1
{PTC3, PWM_3, 4}, // PTC3 , TPM0 CH2
{PTC4, PWM_4, 4}, // PTC4 , TPM0 CH3
{PTD0, PWM_1 , 4}, // PTD0 , TPM0 CH0
{PTD1, PWM_2 , 4}, // PTD0 , TPM0 CH1
{PTD2, PWM_3 , 4}, // PTD2 , TPM0 CH2
@ -180,5 +174,6 @@ const PinMap PinMap_PWM[] = {
{PTE29, PWM_3, 3}, // PTE29, TPM0 CH2
{PTE30, PWM_4, 3}, // PTE30, TPM0 CH3
{PTE31, PWM_5, 3}, // PTE31, TPM0 CH4
{NC , NC, 0}
{NC , NC , 0}
};

View File

@ -0,0 +1,150 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
#define GPIO_PORT_SHIFT 12
typedef enum {
PTA0 = (0 << GPIO_PORT_SHIFT | 0 ),
PTA1 = (0 << GPIO_PORT_SHIFT | 1 ),
PTA2 = (0 << GPIO_PORT_SHIFT | 2 ),
PTA3 = (0 << GPIO_PORT_SHIFT | 3 ),
PTA4 = (0 << GPIO_PORT_SHIFT | 4 ),
PTA5 = (0 << GPIO_PORT_SHIFT | 5 ),
PTA12 = (0 << GPIO_PORT_SHIFT | 12),
PTA13 = (0 << GPIO_PORT_SHIFT | 13),
PTA18 = (0 << GPIO_PORT_SHIFT | 18),
PTA19 = (0 << GPIO_PORT_SHIFT | 19),
PTA20 = (0 << GPIO_PORT_SHIFT | 20),
PTB0 = (1 << GPIO_PORT_SHIFT | 0 ),
PTB1 = (1 << GPIO_PORT_SHIFT | 1 ),
PTB2 = (1 << GPIO_PORT_SHIFT | 2 ),
PTB3 = (1 << GPIO_PORT_SHIFT | 3 ),
PTB16 = (1 << GPIO_PORT_SHIFT | 16),
PTB17 = (1 << GPIO_PORT_SHIFT | 17),
PTB18 = (1 << GPIO_PORT_SHIFT | 18),
PTB19 = (1 << GPIO_PORT_SHIFT | 19),
PTC0 = (2 << GPIO_PORT_SHIFT | 0 ),
PTC1 = (2 << GPIO_PORT_SHIFT | 1 ),
PTC2 = (2 << GPIO_PORT_SHIFT | 2 ),
PTC3 = (2 << GPIO_PORT_SHIFT | 3 ),
PTC4 = (2 << GPIO_PORT_SHIFT | 4 ),
PTC5 = (2 << GPIO_PORT_SHIFT | 5 ),
PTC6 = (2 << GPIO_PORT_SHIFT | 6 ),
PTC7 = (2 << GPIO_PORT_SHIFT | 7 ),
PTC8 = (2 << GPIO_PORT_SHIFT | 8 ),
PTC9 = (2 << GPIO_PORT_SHIFT | 9 ),
PTC10 = (2 << GPIO_PORT_SHIFT | 10),
PTC11 = (2 << GPIO_PORT_SHIFT | 11),
PTD0 = (3 << GPIO_PORT_SHIFT | 0 ),
PTD1 = (3 << GPIO_PORT_SHIFT | 1 ),
PTD2 = (3 << GPIO_PORT_SHIFT | 2 ),
PTD3 = (3 << GPIO_PORT_SHIFT | 3 ),
PTD4 = (3 << GPIO_PORT_SHIFT | 4 ),
PTD5 = (3 << GPIO_PORT_SHIFT | 5 ),
PTD6 = (3 << GPIO_PORT_SHIFT | 6 ),
PTD7 = (3 << GPIO_PORT_SHIFT | 7 ),
PTE0 = (4 << GPIO_PORT_SHIFT | 0 ),
PTE1 = (4 << GPIO_PORT_SHIFT | 1 ),
PTE16 = (4 << GPIO_PORT_SHIFT | 16),
PTE17 = (4 << GPIO_PORT_SHIFT | 17),
PTE18 = (4 << GPIO_PORT_SHIFT | 18),
PTE19 = (4 << GPIO_PORT_SHIFT | 19),
PTE20 = (4 << GPIO_PORT_SHIFT | 20),
PTE21 = (4 << GPIO_PORT_SHIFT | 21),
PTE22 = (4 << GPIO_PORT_SHIFT | 22),
PTE23 = (4 << GPIO_PORT_SHIFT | 23),
PTE24 = (4 << GPIO_PORT_SHIFT | 24),
PTE25 = (4 << GPIO_PORT_SHIFT | 25),
PTE29 = (4 << GPIO_PORT_SHIFT | 29),
PTE30 = (4 << GPIO_PORT_SHIFT | 30),
PTE31 = (4 << GPIO_PORT_SHIFT | 31),
LED_RED = PTE31,
LED_GREEN = PTD5,
// mbed original LED naming
LED1 = LED_GREEN,
LED2 = LED_RED,
LED3 = LED_GREEN,
LED4 = LED_RED,
//Push buttons
SW1 = PTA4,
SW3 = PTC3,
// USB Pins
USBTX = PTA2,
USBRX = PTA1,
// Arduino Headers
D0 = PTA1,
D1 = PTA2,
D2 = PTD3,
D3 = PTA12,
D4 = PTA4,
D5 = PTA5,
D6 = PTE29,
D7 = PTE30,
D8 = PTA13,
D9 = PTD2,
D10 = PTD4,
D11 = PTD6,
D12 = PTD7,
D13 = PTD5,
D14 = PTE0,
D15 = PTE1,
I2C_SCL = D15,
I2C_SDA = D14,
A0 = PTB0,
A1 = PTB1,
A2 = PTB2,
A3 = PTB3,
A4 = PTC2,
A5 = PTC1,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
typedef enum {
PullNone = 0,
PullDown = 1,
PullUp = 2,
PullDefault = PullUp
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_common.h"
#include "fsl_smc.h"
#include "fsl_clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Clock configuration structure. */
typedef struct _clock_config
{
mcglite_config_t mcgliteConfig; /*!< MCG configuration. */
sim_clock_config_t simConfig; /*!< SIM configuration. */
osc_config_t oscConfig; /*!< OSC configuration. */
uint32_t coreClock; /*!< core clock frequency. */
} clock_config_t;
/*******************************************************************************
* Variables
******************************************************************************/
/* System clock frequency. */
extern uint32_t SystemCoreClock;
/* Configuration for enter VLPR mode. Core clock = 2MHz. */
const clock_config_t g_defaultClockConfigVlpr = {
.mcgliteConfig =
{
.outSrc = kMCGLITE_ClkSrcLirc,
.irclkEnableMode = kMCGLITE_IrclkEnable,
.ircs = kMCGLITE_Lirc2M,
.fcrdiv = kMCGLITE_LircDivBy1,
.lircDiv2 = kMCGLITE_LircDivBy1,
.hircEnableInNotHircMode = false,
},
.simConfig =
{
.clkdiv1 = 0x00010000U, /* SIM_CLKDIV1. */
},
.oscConfig = {.freq = BOARD_XTAL0_CLK_HZ,
.capLoad = 0U,
.workMode = kOSC_ModeOscLowPower,
.oscerConfig =
{
.enableMode = kOSC_ErClkEnable,
#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER)
.erclkDiv = 0U,
#endif
}},
.coreClock = 2000000U, /* Core clock frequency */
};
/* Configuration for enter RUN mode. Core clock = 48000000Hz. */
const clock_config_t g_defaultClockConfigRun = {
.mcgliteConfig =
{
.outSrc = kMCGLITE_ClkSrcHirc,
.irclkEnableMode = kMCGLITE_IrclkEnable,
.ircs = kMCGLITE_Lirc8M,
.fcrdiv = kMCGLITE_LircDivBy1,
.lircDiv2 = kMCGLITE_LircDivBy1,
.hircEnableInNotHircMode = true,
},
.simConfig =
{
.clkdiv1 = 0x00010000U, /* SIM_CLKDIV1. */
},
.oscConfig = {.freq = BOARD_XTAL0_CLK_HZ,
.capLoad = 0U,
.workMode = kOSC_ModeOscLowPower,
.oscerConfig =
{
.enableMode = kOSC_ErClkEnable,
#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER)
.erclkDiv = 0U,
#endif
}},
.coreClock = 48000000U, /* Core clock frequency */
};
/*******************************************************************************
* Code
******************************************************************************/
/*
* How to setup clock using clock driver functions:
*
* 1. CLOCK_SetSimSafeDivs, to make sure core clock, bus clock, flexbus clock
* and flash clock are in allowed range during clock mode switch.
*
* 2. Call CLOCK_SetMcgliteConfig to set MCG_Lite configuration.
*
* 3. Call CLOCK_SetSimConfig to set the clock configuration in SIM.
*/
void BOARD_BootClockVLPR(void)
{
CLOCK_SetSimSafeDivs();
CLOCK_SetMcgliteConfig(&g_defaultClockConfigVlpr.mcgliteConfig);
CLOCK_SetSimConfig(&g_defaultClockConfigVlpr.simConfig);
SystemCoreClock = g_defaultClockConfigVlpr.coreClock;
SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);
SMC_SetPowerModeVlpr(SMC);
while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr)
{
}
}
void BOARD_BootClockRUN(void)
{
CLOCK_SetSimSafeDivs();
CLOCK_SetMcgliteConfig(&g_defaultClockConfigRun.mcgliteConfig);
CLOCK_SetSimConfig(&g_defaultClockConfigRun.simConfig);
SystemCoreClock = g_defaultClockConfigRun.coreClock;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CLOCK_CONFIG_H_
#define _CLOCK_CONFIG_H_
/*******************************************************************************
* Definitions
******************************************************************************/
#define BOARD_XTAL0_CLK_HZ 32768U
#define BOARD_XTAL32K_CLK_HZ 0U
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
void BOARD_BootClockVLPR(void);
void BOARD_BootClockRUN(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
#endif /* _CLOCK_CONFIG_H_ */

View File

@ -14,15 +14,24 @@
* limitations under the License.
*/
#include "gpio_api.h"
#include "pinmap.h"
#include "fsl_clock_config.h"
// called before main - implement here if board needs it ortherwise, let
// called before main - implement here if board needs it otherwise, let
// the application override this if necessary
//void mbed_sdk_init()
//{
//
//}
void mbed_sdk_init()
{
BOARD_BootClockRUN();
}
// Change the NMI pin to an input. This allows NMI pin to
// Enable the RTC oscillator if available on the board
void rtc_setup_oscillator(RTC_Type *base)
{
/* Enable the RTC oscillator */
RTC->CR |= RTC_CR_OSCE_MASK;
}
// Change the NMI pin to an input. This allows NMI pin to
// be used as a low power mode wakeup. The application will
// need to change the pin back to NMI_b or wakeup only occurs once!
void NMI_Handler(void)

View File

@ -0,0 +1,363 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_adc16.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for ADC16 module.
*
* @param base ADC16 peripheral base address
*/
static uint32_t ADC16_GetInstance(ADC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to ADC16 bases for each instance. */
static ADC_Type *const s_adc16Bases[] = ADC_BASE_PTRS;
/*! @brief Pointers to ADC16 clocks for each instance. */
const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t ADC16_GetInstance(ADC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_ADC16_COUNT; instance++)
{
if (s_adc16Bases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_ADC16_COUNT);
return instance;
}
void ADC16_Init(ADC_Type *base, const adc16_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
/* Enable the clock. */
CLOCK_EnableClock(s_adc16Clocks[ADC16_GetInstance(base)]);
/* ADCx_CFG1. */
tmp32 = ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_MODE(config->resolution);
if (kADC16_LongSampleDisabled != config->longSampleMode)
{
tmp32 |= ADC_CFG1_ADLSMP_MASK;
}
tmp32 |= ADC_CFG1_ADIV(config->clockDivider);
if (config->enableLowPower)
{
tmp32 |= ADC_CFG1_ADLPC_MASK;
}
base->CFG1 = tmp32;
/* ADCx_CFG2. */
tmp32 = base->CFG2 & ~(ADC_CFG2_ADACKEN_MASK | ADC_CFG2_ADHSC_MASK | ADC_CFG2_ADLSTS_MASK);
if (kADC16_LongSampleDisabled != config->longSampleMode)
{
tmp32 |= ADC_CFG2_ADLSTS(config->longSampleMode);
}
if (config->enableHighSpeed)
{
tmp32 |= ADC_CFG2_ADHSC_MASK;
}
if (config->enableAsynchronousClock)
{
tmp32 |= ADC_CFG2_ADACKEN_MASK;
}
base->CFG2 = tmp32;
/* ADCx_SC2. */
tmp32 = base->SC2 & ~(ADC_SC2_REFSEL_MASK);
tmp32 |= ADC_SC2_REFSEL(config->referenceVoltageSource);
base->SC2 = tmp32;
/* ADCx_SC3. */
if (config->enableContinuousConversion)
{
base->SC3 |= ADC_SC3_ADCO_MASK;
}
else
{
base->SC3 &= ~ADC_SC3_ADCO_MASK;
}
}
void ADC16_Deinit(ADC_Type *base)
{
/* Disable the clock. */
CLOCK_DisableClock(s_adc16Clocks[ADC16_GetInstance(base)]);
}
void ADC16_GetDefaultConfig(adc16_config_t *config)
{
assert(NULL != config);
config->referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
config->clockSource = kADC16_ClockSourceAsynchronousClock;
config->enableAsynchronousClock = true;
config->clockDivider = kADC16_ClockDivider8;
config->resolution = kADC16_ResolutionSE12Bit;
config->longSampleMode = kADC16_LongSampleDisabled;
config->enableHighSpeed = false;
config->enableLowPower = false;
config->enableContinuousConversion = false;
}
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
status_t ADC16_DoAutoCalibration(ADC_Type *base)
{
bool bHWTrigger = false;
uint32_t tmp32;
status_t status = kStatus_Success;
/* The calibration would be failed when in hardwar mode.
* Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
if (0U != (ADC_SC2_ADTRG_MASK & base->SC2))
{
bHWTrigger = true;
base->SC2 &= ~ADC_SC2_ADTRG_MASK;
}
/* Clear the CALF and launch the calibration. */
base->SC3 |= ADC_SC3_CAL_MASK | ADC_SC3_CALF_MASK;
while (0U == (kADC16_ChannelConversionDoneFlag & ADC16_GetChannelStatusFlags(base, 0U)))
{
/* Check the CALF when the calibration is active. */
if (0U != (kADC16_CalibrationFailedFlag & ADC16_GetStatusFlags(base)))
{
status = kStatus_Fail;
break;
}
}
/* Restore the hardware trigger setting if it was enabled before. */
if (bHWTrigger)
{
base->SC2 |= ADC_SC2_ADTRG_MASK;
}
/* Check the CALF at the end of calibration. */
if (0U != (kADC16_CalibrationFailedFlag & ADC16_GetStatusFlags(base)))
{
status = kStatus_Fail;
}
if (kStatus_Success != status) /* Check if the calibration process is succeed. */
{
return status;
}
/* Calculate the calibration values. */
tmp32 = base->CLP0 + base->CLP1 + base->CLP2 + base->CLP3 + base->CLP4 + base->CLPS;
tmp32 = 0x8000U | (tmp32 >> 1U);
base->PG = tmp32;
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
tmp32 = base->CLM0 + base->CLM1 + base->CLM2 + base->CLM3 + base->CLM4 + base->CLMS;
tmp32 = 0x8000U | (tmp32 >> 1U);
base->MG = tmp32;
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
return kStatus_Success;
}
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
#if defined(FSL_FEATURE_ADC16_HAS_MUX_SELECT) && FSL_FEATURE_ADC16_HAS_MUX_SELECT
void ADC16_SetChannelMuxMode(ADC_Type *base, adc16_channel_mux_mode_t mode)
{
if (kADC16_ChannelMuxA == mode)
{
base->CFG2 &= ~ADC_CFG2_MUXSEL_MASK;
}
else /* kADC16_ChannelMuxB. */
{
base->CFG2 |= ADC_CFG2_MUXSEL_MASK;
}
}
#endif /* FSL_FEATURE_ADC16_HAS_MUX_SELECT */
void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare_config_t *config)
{
uint32_t tmp32 = base->SC2 & ~(ADC_SC2_ACFE_MASK | ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK);
if (!config) /* Pass "NULL" to disable the feature. */
{
base->SC2 = tmp32;
return;
}
/* Enable the feature. */
tmp32 |= ADC_SC2_ACFE_MASK;
/* Select the hardware compare working mode. */
switch (config->hardwareCompareMode)
{
case kADC16_HardwareCompareMode0:
break;
case kADC16_HardwareCompareMode1:
tmp32 |= ADC_SC2_ACFGT_MASK;
break;
case kADC16_HardwareCompareMode2:
tmp32 |= ADC_SC2_ACREN_MASK;
break;
case kADC16_HardwareCompareMode3:
tmp32 |= ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK;
break;
default:
break;
}
base->SC2 = tmp32;
/* Load the compare values. */
base->CV1 = ADC_CV1_CV(config->value1);
base->CV2 = ADC_CV2_CV(config->value2);
}
#if defined(FSL_FEATURE_ADC16_HAS_HW_AVERAGE) && FSL_FEATURE_ADC16_HAS_HW_AVERAGE
void ADC16_SetHardwareAverage(ADC_Type *base, adc16_hardware_average_mode_t mode)
{
uint32_t tmp32 = base->SC3 & ~(ADC_SC3_AVGE_MASK | ADC_SC3_AVGS_MASK);
if (kADC16_HardwareAverageDisabled != mode)
{
tmp32 |= ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(mode);
}
base->SC3 = tmp32;
}
#endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */
#if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA
void ADC16_SetPGAConfig(ADC_Type *base, const adc16_pga_config_t *config)
{
uint32_t tmp32;
if (!config) /* Passing "NULL" is to disable the feature. */
{
base->PGA = 0U;
return;
}
/* Enable the PGA and set the gain value. */
tmp32 = ADC_PGA_PGAEN_MASK | ADC_PGA_PGAG(config->pgaGain);
/* Configure the misc features for PGA. */
if (config->enableRunInNormalMode)
{
tmp32 |= ADC_PGA_PGALPb_MASK;
}
#if defined(FSL_FEATURE_ADC16_HAS_PGA_CHOPPING) && FSL_FEATURE_ADC16_HAS_PGA_CHOPPING
if (config->disablePgaChopping)
{
tmp32 |= ADC_PGA_PGACHPb_MASK;
}
#endif /* FSL_FEATURE_ADC16_HAS_PGA_CHOPPING */
#if defined(FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT) && FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT
if (config->enableRunInOffsetMeasurement)
{
tmp32 |= ADC_PGA_PGAOFSM_MASK;
}
#endif /* FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT */
base->PGA = tmp32;
}
#endif /* FSL_FEATURE_ADC16_HAS_PGA */
uint32_t ADC16_GetStatusFlags(ADC_Type *base)
{
uint32_t ret = 0;
if (0U != (base->SC2 & ADC_SC2_ADACT_MASK))
{
ret |= kADC16_ActiveFlag;
}
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
if (0U != (base->SC3 & ADC_SC3_CALF_MASK))
{
ret |= kADC16_CalibrationFailedFlag;
}
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
return ret;
}
void ADC16_ClearStatusFlags(ADC_Type *base, uint32_t mask)
{
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
if (0U != (mask & kADC16_CalibrationFailedFlag))
{
base->SC3 |= ADC_SC3_CALF_MASK;
}
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
}
void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config)
{
assert(channelGroup < ADC_SC1_COUNT);
assert(NULL != config);
uint32_t sc1 = ADC_SC1_ADCH(config->channelNumber); /* Set the channel number. */
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
/* Enable the differential conversion. */
if (config->enableDifferentialConversion)
{
sc1 |= ADC_SC1_DIFF_MASK;
}
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
/* Enable the interrupt when the conversion is done. */
if (config->enableInterruptOnConversionCompleted)
{
sc1 |= ADC_SC1_AIEN_MASK;
}
base->SC1[channelGroup] = sc1;
}
uint32_t ADC16_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
{
assert(channelGroup < ADC_SC1_COUNT);
uint32_t ret = 0U;
if (0U != (base->SC1[channelGroup] & ADC_SC1_COCO_MASK))
{
ret |= kADC16_ChannelConversionDoneFlag;
}
return ret;
}

View File

@ -0,0 +1,527 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_ADC16_H_
#define _FSL_ADC16_H_
#include "fsl_common.h"
/*!
* @addtogroup adc16
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief ADC16 driver version 2.0.0. */
#define FSL_ADC16_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief Channel status flags.
*/
enum _adc16_channel_status_flags
{
kADC16_ChannelConversionDoneFlag = ADC_SC1_COCO_MASK, /*!< Conversion done. */
};
/*!
* @brief Converter status flags.
*/
enum _adc16_status_flags
{
kADC16_ActiveFlag = ADC_SC2_ADACT_MASK, /*!< Converter is active. */
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
kADC16_CalibrationFailedFlag = ADC_SC3_CALF_MASK, /*!< Calibration is failed. */
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
};
#if defined(FSL_FEATURE_ADC16_HAS_MUX_SELECT) && FSL_FEATURE_ADC16_HAS_MUX_SELECT
/*!
* @brief Channel multiplexer mode for each channel.
*
* For some ADC16 channels, there are two pin selections in channel multiplexer. For example, ADC0_SE4a and ADC0_SE4b
* are the different channels but share the same channel number.
*/
typedef enum _adc_channel_mux_mode
{
kADC16_ChannelMuxA = 0U, /*!< For channel with channel mux a. */
kADC16_ChannelMuxB = 1U, /*!< For channel with channel mux b. */
} adc16_channel_mux_mode_t;
#endif /* FSL_FEATURE_ADC16_HAS_MUX_SELECT */
/*!
* @brief Clock divider for the converter.
*/
typedef enum _adc16_clock_divider
{
kADC16_ClockDivider1 = 0U, /*!< For divider 1 from the input clock to the module. */
kADC16_ClockDivider2 = 1U, /*!< For divider 2 from the input clock to the module. */
kADC16_ClockDivider4 = 2U, /*!< For divider 4 from the input clock to the module. */
kADC16_ClockDivider8 = 3U, /*!< For divider 8 from the input clock to the module. */
} adc16_clock_divider_t;
/*!
*@brief Converter's resolution.
*/
typedef enum _adc16_resolution
{
/* This group of enumeration is for internal use which is related to register setting. */
kADC16_Resolution8or9Bit = 0U, /*!< Single End 8-bit or Differential Sample 9-bit. */
kADC16_Resolution12or13Bit = 1U, /*!< Single End 12-bit or Differential Sample 13-bit. */
kADC16_Resolution10or11Bit = 2U, /*!< Single End 10-bit or Differential Sample 11-bit. */
/* This group of enumeration is for public user. */
kADC16_ResolutionSE8Bit = kADC16_Resolution8or9Bit, /*!< Single End 8-bit. */
kADC16_ResolutionSE12Bit = kADC16_Resolution12or13Bit, /*!< Single End 12-bit. */
kADC16_ResolutionSE10Bit = kADC16_Resolution10or11Bit, /*!< Single End 10-bit. */
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
kADC16_ResolutionDF9Bit = kADC16_Resolution8or9Bit, /*!< Differential Sample 9-bit. */
kADC16_ResolutionDF13Bit = kADC16_Resolution12or13Bit, /*!< Differential Sample 13-bit. */
kADC16_ResolutionDF11Bit = kADC16_Resolution10or11Bit, /*!< Differential Sample 11-bit. */
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
#if defined(FSL_FEATURE_ADC16_MAX_RESOLUTION) && (FSL_FEATURE_ADC16_MAX_RESOLUTION >= 16U)
/* 16-bit is supported by default. */
kADC16_Resolution16Bit = 3U, /*!< Single End 16-bit or Differential Sample 16-bit. */
kADC16_ResolutionSE16Bit = kADC16_Resolution16Bit, /*!< Single End 16-bit. */
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
kADC16_ResolutionDF16Bit = kADC16_Resolution16Bit, /*!< Differential Sample 16-bit. */
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
#endif /* FSL_FEATURE_ADC16_MAX_RESOLUTION >= 16U */
} adc16_resolution_t;
/*!
* @brief Clock source.
*/
typedef enum _adc16_clock_source
{
kADC16_ClockSourceAlt0 = 0U, /*!< Selection 0 of the clock source. */
kADC16_ClockSourceAlt1 = 1U, /*!< Selection 1 of the clock source. */
kADC16_ClockSourceAlt2 = 2U, /*!< Selection 2 of the clock source. */
kADC16_ClockSourceAlt3 = 3U, /*!< Selection 3 of the clock source. */
/* Chip defined clock source */
kADC16_ClockSourceAsynchronousClock = kADC16_ClockSourceAlt3, /*!< Using internal asynchronous clock. */
} adc16_clock_source_t;
/*!
* @brief Long sample mode.
*/
typedef enum _adc16_long_sample_mode
{
kADC16_LongSampleCycle24 = 0U, /*!< 20 extra ADCK cycles, 24 ADCK cycles total. */
kADC16_LongSampleCycle16 = 1U, /*!< 12 extra ADCK cycles, 16 ADCK cycles total. */
kADC16_LongSampleCycle10 = 2U, /*!< 6 extra ADCK cycles, 10 ADCK cycles total. */
kADC16_LongSampleCycle6 = 3U, /*!< 2 extra ADCK cycles, 6 ADCK cycles total. */
kADC16_LongSampleDisabled = 4U, /*!< Disable the long sample feature. */
} adc16_long_sample_mode_t;
/*!
* @brief Reference voltage source.
*/
typedef enum _adc16_reference_voltage_source
{
kADC16_ReferenceVoltageSourceVref = 0U, /*!< For external pins pair of VrefH and VrefL. */
kADC16_ReferenceVoltageSourceValt = 1U, /*!< For alternate reference pair of ValtH and ValtL. */
} adc16_reference_voltage_source_t;
#if defined(FSL_FEATURE_ADC16_HAS_HW_AVERAGE) && FSL_FEATURE_ADC16_HAS_HW_AVERAGE
/*!
* @brief Hardware average mode.
*/
typedef enum _adc16_hardware_average_mode
{
kADC16_HardwareAverageCount4 = 0U, /*!< For hardware average with 4 samples. */
kADC16_HardwareAverageCount8 = 1U, /*!< For hardware average with 8 samples. */
kADC16_HardwareAverageCount16 = 2U, /*!< For hardware average with 16 samples. */
kADC16_HardwareAverageCount32 = 3U, /*!< For hardware average with 32 samples. */
kADC16_HardwareAverageDisabled = 4U, /*!< Disable the hardware average feature.*/
} adc16_hardware_average_mode_t;
#endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */
/*!
* @brief Hardware compare mode.
*/
typedef enum _adc16_hardware_compare_mode
{
kADC16_HardwareCompareMode0 = 0U, /*!< x < value1. */
kADC16_HardwareCompareMode1 = 1U, /*!< x > value1. */
kADC16_HardwareCompareMode2 = 2U, /*!< if value1 <= value2, then x < value1 || x > value2;
else, value1 > x > value2. */
kADC16_HardwareCompareMode3 = 3U, /*!< if value1 <= value2, then value1 <= x <= value2;
else x >= value1 || x <= value2. */
} adc16_hardware_compare_mode_t;
#if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA
/*!
* @brief PGA's Gain mode.
*/
typedef enum _adc16_pga_gain
{
kADC16_PGAGainValueOf1 = 0U, /*!< For amplifier gain of 1. */
kADC16_PGAGainValueOf2 = 1U, /*!< For amplifier gain of 2. */
kADC16_PGAGainValueOf4 = 2U, /*!< For amplifier gain of 4. */
kADC16_PGAGainValueOf8 = 3U, /*!< For amplifier gain of 8. */
kADC16_PGAGainValueOf16 = 4U, /*!< For amplifier gain of 16. */
kADC16_PGAGainValueOf32 = 5U, /*!< For amplifier gain of 32. */
kADC16_PGAGainValueOf64 = 6U, /*!< For amplifier gain of 64. */
} adc16_pga_gain_t;
#endif /* FSL_FEATURE_ADC16_HAS_PGA */
/*!
* @brief ADC16 converter configuration .
*/
typedef struct _adc16_config
{
adc16_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */
adc16_clock_source_t clockSource; /*!< Select the input clock source to converter. */
bool enableAsynchronousClock; /*!< Enable the asynchronous clock output. */
adc16_clock_divider_t clockDivider; /*!< Select the divider of input clock source. */
adc16_resolution_t resolution; /*!< Select the sample resolution mode. */
adc16_long_sample_mode_t longSampleMode; /*!< Select the long sample mode. */
bool enableHighSpeed; /*!< Enable the high-speed mode. */
bool enableLowPower; /*!< Enable low power. */
bool enableContinuousConversion; /*!< Enable continuous conversion mode. */
} adc16_config_t;
/*!
* @brief ADC16 Hardware compare configuration.
*/
typedef struct _adc16_hardware_compare_config
{
adc16_hardware_compare_mode_t hardwareCompareMode; /*!< Select the hardware compare mode.
See "adc16_hardware_compare_mode_t". */
int16_t value1; /*!< Setting value1 for hardware compare mode. */
int16_t value2; /*!< Setting value2 for hardware compare mode. */
} adc16_hardware_compare_config_t;
/*!
* @brief ADC16 channel conversion configuration.
*/
typedef struct _adc16_channel_config
{
uint32_t channelNumber; /*!< Setting the conversion channel number. The available range is 0-31.
See channel connection information for each chip in Reference
Manual document. */
bool enableInterruptOnConversionCompleted; /*!< Generate a interrupt request once the conversion is completed. */
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
bool enableDifferentialConversion; /*!< Using Differential sample mode. */
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
} adc16_channel_config_t;
#if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA
/*!
* @brief ADC16 programmable gain amplifier configuration.
*/
typedef struct _adc16_pga_config
{
adc16_pga_gain_t pgaGain; /*!< Setting PGA gain. */
bool enableRunInNormalMode; /*!< Enable PGA working in normal mode, or low power mode by default. */
#if defined(FSL_FEATURE_ADC16_HAS_PGA_CHOPPING) && FSL_FEATURE_ADC16_HAS_PGA_CHOPPING
bool disablePgaChopping; /*!< Disable the PGA chopping function.
The PGA employs chopping to remove/reduce offset and 1/f noise and offers
an offset measurement configuration that aids the offset calibration. */
#endif /* FSL_FEATURE_ADC16_HAS_PGA_CHOPPING */
#if defined(FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT) && FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT
bool enableRunInOffsetMeasurement; /*!< Enable the PGA working in offset measurement mode.
When this feature is enabled, the PGA disconnects itself from the external
inputs and auto-configures into offset measurement mode. With this field
set, run the ADC in the recommended settings and enable the maximum hardware
averaging to get the PGA offset number. The output is the
(PGA offset * (64+1)) for the given PGA setting. */
#endif /* FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT */
} adc16_pga_config_t;
#endif /* FSL_FEATURE_ADC16_HAS_PGA */
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* API
******************************************************************************/
/*!
* @name Initialization
* @{
*/
/*!
* @brief Initializes the ADC16 module.
*
* @param base ADC16 peripheral base address.
* @param config Pointer to configuration structure. See "adc16_config_t".
*/
void ADC16_Init(ADC_Type *base, const adc16_config_t *config);
/*!
* @brief De-initializes the ADC16 module.
*
* @param base ADC16 peripheral base address.
*/
void ADC16_Deinit(ADC_Type *base);
/*!
* @brief Gets an available pre-defined settings for converter's configuration.
*
* This function initializes the converter configuration structure with an available settings. The default values are:
* @code
* config->referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
* config->clockSource = kADC16_ClockSourceAsynchronousClock;
* config->enableAsynchronousClock = true;
* config->clockDivider = kADC16_ClockDivider8;
* config->resolution = kADC16_ResolutionSE12Bit;
* config->longSampleMode = kADC16_LongSampleDisabled;
* config->enableHighSpeed = false;
* config->enableLowPower = false;
* config->enableContinuousConversion = false;
* @endcode
* @param config Pointer to configuration structure.
*/
void ADC16_GetDefaultConfig(adc16_config_t *config);
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
/*!
* @brief Automates the hardware calibration.
*
* This auto calibration helps to adjust the plus/minus side gain automatically on the converter's working situation.
* Execute the calibration before using the converter. Note that the hardware trigger should be used
* during calibration.
*
* @param base ADC16 peripheral base address.
*
* @return Execution status.
* @retval kStatus_Success Calibration is done successfully.
* @retval kStatus_Fail Calibration is failed.
*/
status_t ADC16_DoAutoCalibration(ADC_Type *base);
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
#if defined(FSL_FEATURE_ADC16_HAS_OFFSET_CORRECTION) && FSL_FEATURE_ADC16_HAS_OFFSET_CORRECTION
/*!
* @brief Sets the offset value for the conversion result.
*
* This offset value takes effect on the conversion result. If the offset value is not zero, the reading result
* is subtracted by it. Note, the hardware calibration fills the offset value automatically.
*
* @param base ADC16 peripheral base address.
* @param value Setting offset value.
*/
static inline void ADC16_SetOffsetValue(ADC_Type *base, int16_t value)
{
base->OFS = (uint32_t)(value);
}
#endif /* FSL_FEATURE_ADC16_HAS_OFFSET_CORRECTION */
/* @} */
/*!
* @name Advanced Feature
* @{
*/
#if defined(FSL_FEATURE_ADC16_HAS_DMA) && FSL_FEATURE_ADC16_HAS_DMA
/*!
* @brief Enables generating the DMA trigger when conversion is completed.
*
* @param base ADC16 peripheral base address.
* @param enable Switcher of DMA feature. "true" means to enable, "false" means not.
*/
static inline void ADC16_EnableDMA(ADC_Type *base, bool enable)
{
if (enable)
{
base->SC2 |= ADC_SC2_DMAEN_MASK;
}
else
{
base->SC2 &= ~ADC_SC2_DMAEN_MASK;
}
}
#endif /* FSL_FEATURE_ADC16_HAS_DMA */
/*!
* @brief Enables the hardware trigger mode.
*
* @param base ADC16 peripheral base address.
* @param enable Switcher of hardware trigger feature. "true" means to enable, "false" means not.
*/
static inline void ADC16_EnableHardwareTrigger(ADC_Type *base, bool enable)
{
if (enable)
{
base->SC2 |= ADC_SC2_ADTRG_MASK;
}
else
{
base->SC2 &= ~ADC_SC2_ADTRG_MASK;
}
}
#if defined(FSL_FEATURE_ADC16_HAS_MUX_SELECT) && FSL_FEATURE_ADC16_HAS_MUX_SELECT
/*!
* @brief Sets the channel mux mode.
*
* Some sample pins share the same channel index. The channel mux mode decides which pin is used for an
* indicated channel.
*
* @param base ADC16 peripheral base address.
* @param mode Setting channel mux mode. See "adc16_channel_mux_mode_t".
*/
void ADC16_SetChannelMuxMode(ADC_Type *base, adc16_channel_mux_mode_t mode);
#endif /* FSL_FEATURE_ADC16_HAS_MUX_SELECT */
/*!
* @brief Configures the hardware compare mode.
*
* The hardware compare mode provides a way to process the conversion result automatically by hardware. Only the result
* in
* compare range is available. To compare the range, see "adc16_hardware_compare_mode_t", or the reference
* manual document for more detailed information.
*
* @param base ADC16 peripheral base address.
* @param config Pointer to "adc16_hardware_compare_config_t" structure. Passing "NULL" is to disable the feature.
*/
void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare_config_t *config);
#if defined(FSL_FEATURE_ADC16_HAS_HW_AVERAGE) && FSL_FEATURE_ADC16_HAS_HW_AVERAGE
/*!
* @brief Sets the hardware average mode.
*
* Hardware average mode provides a way to process the conversion result automatically by hardware. The multiple
* conversion results are accumulated and averaged internally. This aids reading results.
*
* @param base ADC16 peripheral base address.
* @param mode Setting hardware average mode. See "adc16_hardware_average_mode_t".
*/
void ADC16_SetHardwareAverage(ADC_Type *base, adc16_hardware_average_mode_t mode);
#endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */
#if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA
/*!
* @brief Configures the PGA for converter's front end.
*
* @param base ADC16 peripheral base address.
* @param config Pointer to "adc16_pga_config_t" structure. Passing "NULL" is to disable the feature.
*/
void ADC16_SetPGAConfig(ADC_Type *base, const adc16_pga_config_t *config);
#endif /* FSL_FEATURE_ADC16_HAS_PGA */
/*!
* @brief Gets the status flags of the converter.
*
* @param base ADC16 peripheral base address.
*
* @return Flags' mask if indicated flags are asserted. See "_adc16_status_flags".
*/
uint32_t ADC16_GetStatusFlags(ADC_Type *base);
/*!
* @brief Clears the status flags of the converter.
*
* @param base ADC16 peripheral base address.
* @param mask Mask value for the cleared flags. See "_adc16_status_flags".
*/
void ADC16_ClearStatusFlags(ADC_Type *base, uint32_t mask);
/* @} */
/*!
* @name Conversion Channel
* @{
*/
/*!
* @brief Configures the conversion channel.
*
* This operation triggers the conversion if in software trigger mode. When in hardware trigger mode, this API
* configures the channel while the external trigger source helps to trigger the conversion.
*
* Note that the "Channel Group" has a detailed description.
* To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC can have more than one
* group of status and control register, one for each conversion. The channel group parameter indicates which group of
* registers are used channel group 0 is for Group A registers and channel group 1 is for Group B registers. The
* channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of
* the channel groups is actively controlling ADC conversions. Channel group 0 is used for both software and hardware
* trigger modes of operation. Channel groups 1 and greater indicate potentially multiple channel group registers for
* use only in hardware trigger mode. See the chip configuration information in the MCU reference manual about the
* number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used
* for software trigger operation and therefore writes to these channel groups do not initiate a new conversion.
* Updating channel group 0 while a different channel group is actively controlling a conversion is allowed and
* vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
* conversion aborts the current conversion.
*
* @param base ADC16 peripheral base address.
* @param channelGroup Channel group index.
* @param config Pointer to "adc16_channel_config_t" structure for conversion channel.
*/
void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config);
/*!
* @brief Gets the conversion value.
*
* @param base ADC16 peripheral base address.
* @param channelGroup Channel group index.
*
* @return Conversion value.
*/
static inline uint32_t ADC16_GetChannelConversionValue(ADC_Type *base, uint32_t channelGroup)
{
assert(channelGroup < ADC_R_COUNT);
return base->R[channelGroup];
}
/*!
* @brief Gets the status flags of channel.
*
* @param base ADC16 peripheral base address.
* @param channelGroup Channel group index.
*
* @return Flags' mask if indicated flags are asserted. See "_adc16_channel_status_flags".
*/
uint32_t ADC16_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup);
/* @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_ADC16_H_ */

View File

@ -0,0 +1,408 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_common.h"
#include "fsl_clock.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#if (defined(OSC) && !(defined(OSC0)))
#define OSC0 OSC
#endif
#define MCG_HIRC_FREQ (48000000U)
#define MCG_LIRC_FREQ1 (2000000U)
#define MCG_LIRC_FREQ2 (8000000U)
#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT)
#define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT)
#define MCG_MC_LIRC_DIV2_VAL ((MCG->MC & MCG_MC_LIRC_DIV2_MASK) >> MCG_MC_LIRC_DIV2_SHIFT)
#define MCG_C2_IRCS_VAL ((MCG->C2 & MCG_C2_IRCS_MASK) >> MCG_C2_IRCS_SHIFT)
#define SIM_CLKDIV1_OUTDIV1_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT)
#define SIM_CLKDIV1_OUTDIV4_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT)
#define SIM_SOPT1_OSC32KSEL_VAL ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT)
/*******************************************************************************
* Variables
******************************************************************************/
/* External XTAL0 (OSC0) clock frequency. */
uint32_t g_xtal0Freq;
/* External XTAL32K clock frequency. */
uint32_t g_xtal32Freq;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the current MCG_Lite LIRC_CLK frequency in Hz.
*
* This function will return the LIRC_CLK value in frequency(Hz) based
* on current MCG_Lite configurations and settings. It is an internal function.
*
* @return MCG_Lite LIRC_CLK frequency.
*/
static uint32_t CLOCK_GetLircClkFreq(void);
/*!
* @brief Get RANGE value based on OSC frequency.
*
* To setup external crystal oscillator, must set the register bits RANGE base
* on the crystal frequency. This function returns the RANGE base on the input
* frequency. This is an internal function.
*
* @return RANGE value.
*/
static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t CLOCK_GetLircClkFreq(void)
{
static const uint32_t lircFreqs[] = {MCG_LIRC_FREQ1, MCG_LIRC_FREQ2};
/* Check whether the LIRC is enabled. */
if ((MCG->C1 & MCG_C1_IRCLKEN_MASK) || (kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL))
{
return lircFreqs[MCG_C2_IRCS_VAL];
}
else
{
return 0U;
}
}
static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq)
{
uint8_t range;
if (freq <= 39063U)
{
range = 0U;
}
else if (freq <= 8000000U)
{
range = 1U;
}
else
{
range = 2U;
}
return range;
}
uint32_t CLOCK_GetOsc0ErClkFreq(void)
{
if (OSC0->CR & OSC_CR_ERCLKEN_MASK)
{
/* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
assert(g_xtal0Freq);
return g_xtal0Freq;
}
else
{
return 0U;
}
}
uint32_t CLOCK_GetEr32kClkFreq(void)
{
uint32_t freq;
switch (SIM_SOPT1_OSC32KSEL_VAL)
{
case 0U: /* OSC 32k clock */
freq = (CLOCK_GetOsc0ErClkFreq() == 32768U) ? 32768U : 0U;
break;
case 2U: /* RTC 32k clock */
/* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
assert(g_xtal32Freq);
freq = g_xtal32Freq;
break;
case 3U: /* LPO clock */
freq = LPO_CLK_FREQ;
break;
default:
freq = 0U;
break;
}
return freq;
}
uint32_t CLOCK_GetPlatClkFreq(void)
{
return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
}
uint32_t CLOCK_GetFlashClkFreq(void)
{
uint32_t freq;
freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1);
return freq;
}
uint32_t CLOCK_GetBusClkFreq(void)
{
uint32_t freq;
freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1);
return freq;
}
uint32_t CLOCK_GetCoreSysClkFreq(void)
{
return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
}
uint32_t CLOCK_GetFreq(clock_name_t clockName)
{
uint32_t freq;
switch (clockName)
{
case kCLOCK_CoreSysClk:
case kCLOCK_PlatClk:
freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
break;
case kCLOCK_BusClk:
case kCLOCK_FlashClk:
freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1);
break;
case kCLOCK_Er32kClk:
freq = CLOCK_GetEr32kClkFreq();
break;
case kCLOCK_Osc0ErClk:
freq = CLOCK_GetOsc0ErClkFreq();
break;
case kCLOCK_McgInternalRefClk:
freq = CLOCK_GetInternalRefClkFreq();
break;
case kCLOCK_McgPeriphClk:
case kCLOCK_McgIrc48MClk:
freq = CLOCK_GetPeriphClkFreq();
break;
case kCLOCK_LpoClk:
freq = LPO_CLK_FREQ;
break;
default:
freq = 0U;
break;
}
return freq;
}
void CLOCK_SetSimConfig(sim_clock_config_t const *config)
{
SIM->CLKDIV1 = config->clkdiv1;
CLOCK_SetEr32kClock(config->er32kSrc);
}
bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
{
bool ret = true;
CLOCK_DisableClock(kCLOCK_Usbfs0);
if (kCLOCK_UsbSrcExt == src)
{
SIM->SOPT2 &= ~SIM_SOPT2_USBSRC_MASK;
}
else
{
SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK;
}
CLOCK_EnableClock(kCLOCK_Usbfs0);
if (kCLOCK_UsbSrcIrc48M == src)
{
USB0->CLK_RECOVER_IRC_EN = 0x03U;
USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
}
return ret;
}
uint32_t CLOCK_GetInternalRefClkFreq(void)
{
uint8_t divider1 = MCG_SC_FCRDIV_VAL;
uint8_t divider2 = MCG_MC_LIRC_DIV2_VAL;
/* LIRC internal reference clock is selected*/
return CLOCK_GetLircClkFreq() >> (divider1 + divider2);
}
uint32_t CLOCK_GetPeriphClkFreq(void)
{
/* Check whether the HIRC is enabled. */
if ((MCG->MC & MCG_MC_HIRCEN_MASK) || (kMCGLITE_ClkSrcHirc == MCG_S_CLKST_VAL))
{
return MCG_HIRC_FREQ;
}
else
{
return 0U;
}
}
uint32_t CLOCK_GetOutClkFreq(void)
{
uint32_t freq;
switch (MCG_S_CLKST_VAL)
{
case kMCGLITE_ClkSrcHirc:
freq = MCG_HIRC_FREQ;
break;
case kMCGLITE_ClkSrcLirc:
freq = CLOCK_GetLircClkFreq() >> MCG_SC_FCRDIV_VAL;
break;
case kMCGLITE_ClkSrcExt:
/* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
assert(g_xtal0Freq);
freq = g_xtal0Freq;
break;
default:
freq = 0U;
break;
}
return freq;
}
mcglite_mode_t CLOCK_GetMode(void)
{
mcglite_mode_t mode;
switch (MCG_S_CLKST_VAL)
{
case kMCGLITE_ClkSrcHirc: /* HIRC */
mode = kMCGLITE_ModeHirc48M;
break;
case kMCGLITE_ClkSrcLirc: /* LIRC */
if (kMCGLITE_Lirc2M == MCG_C2_IRCS_VAL)
{
mode = kMCGLITE_ModeLirc2M;
}
else
{
mode = kMCGLITE_ModeLirc8M;
}
break;
case kMCGLITE_ClkSrcExt: /* EXT */
mode = kMCGLITE_ModeExt;
break;
default:
mode = kMCGLITE_ModeError;
break;
}
return mode;
}
status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig)
{
assert(targetConfig);
/*
* If switch between LIRC8M and LIRC2M, need to switch to HIRC mode first,
* because could not switch directly.
*/
if ((kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL) && (kMCGLITE_ClkSrcLirc == targetConfig->outSrc) &&
(MCG_C2_IRCS_VAL != targetConfig->ircs))
{
MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCGLITE_ClkSrcHirc);
while (kMCGLITE_ClkSrcHirc != MCG_S_CLKST_VAL)
{
}
}
/* Set configuration now. */
MCG->SC = MCG_SC_FCRDIV(targetConfig->fcrdiv);
MCG->MC = MCG_MC_HIRCEN(targetConfig->hircEnableInNotHircMode) | MCG_MC_LIRC_DIV2(targetConfig->lircDiv2);
MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | MCG_C2_IRCS(targetConfig->ircs);
MCG->C1 = MCG_C1_CLKS(targetConfig->outSrc) | targetConfig->irclkEnableMode;
/*
* If external oscillator used and MCG_Lite is set to EXT mode, need to
* wait for the OSC stable.
*/
if ((MCG->C2 & MCG_C2_EREFS0_MASK) && (kMCGLITE_ClkSrcExt == targetConfig->outSrc))
{
while (!(MCG->S & MCG_S_OSCINIT0_MASK))
{
}
}
/* Wait for clock source change completed. */
while (targetConfig->outSrc != MCG_S_CLKST_VAL)
{
}
return kStatus_Success;
}
void CLOCK_InitOsc0(osc_config_t const *config)
{
uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq);
OSC_SetCapLoad(OSC0, config->capLoad);
OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig);
MCG->C2 = ((MCG->C2 & MCG_C2_IRCS_MASK) | MCG_C2_RANGE0(range) | (uint8_t)config->workMode);
if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK))
{
/* Wait for stable. */
while (!(MCG->S & MCG_S_OSCINIT0_MASK))
{
}
}
}
void CLOCK_DeinitOsc0(void)
{
OSC0->CR = 0U;
MCG->C2 &= MCG_C2_IRCS_MASK;
}

View File

@ -0,0 +1,806 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_CLOCK_H_
#define _FSL_CLOCK_H_
#include "fsl_device_registers.h"
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
/*! @addtogroup mcglite */
/*! @{ */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Clock driver version. */
#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */
/*! @brief External XTAL0 (OSC0) clock frequency.
*
* The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the
* function CLOCK_SetXtal0Freq to set the value in to clock driver. For example,
* if XTAL0 is 8MHz,
* @code
* CLOCK_InitOsc0(...); // Setup the OSC0
* CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver.
* @endcode
*
* This is important for the multicore platforms, only one core needs to setup
* OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq
* to get valid clock frequency.
*/
extern uint32_t g_xtal0Freq;
/*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency.
*
* The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the
* function CLOCK_SetXtal32Freq to set the value in to clock driver.
*
* This is important for the multicore platforms, only one core needs to setup
* the clock, all other cores need to call CLOCK_SetXtal32Freq
* to get valid clock frequency.
*/
extern uint32_t g_xtal32Freq;
/*! @brief Clock ip name array for DMAMUX. */
#define DMAMUX_CLOCKS \
{ \
kCLOCK_Dmamux0 \
}
/*! @brief Clock ip name array for RTC. */
#define RTC_CLOCKS \
{ \
kCLOCK_Rtc0 \
}
/*! @brief Clock ip name array for SAI. */
#define SAI_CLOCKS \
{ \
kCLOCK_Sai0 \
}
/*! @brief Clock ip name array for SPI. */
#define SPI_CLOCKS \
{ \
kCLOCK_Spi0, kCLOCK_Spi1 \
}
/*! @brief Clock ip name array for SLCD. */
#define SLCD_CLOCKS \
{ \
kCLOCK_Slcd0 \
}
/*! @brief Clock ip name array for PIT. */
#define PIT_CLOCKS \
{ \
kCLOCK_Pit0 \
}
/*! @brief Clock ip name array for PORT. */
#define PORT_CLOCKS \
{ \
kCLOCK_PortA, kCLOCK_PortB, kCLOCK_PortC, kCLOCK_PortD, kCLOCK_PortE \
}
/*! @brief Clock ip name array for LPUART. */
#define LPUART_CLOCKS \
{ \
kCLOCK_Lpuart0, kCLOCK_Lpuart1 \
}
/*! @brief Clock ip name array for DAC. */
#define DAC_CLOCKS \
{ \
kCLOCK_Dac0 \
}
/*! @brief Clock ip name array for LPTMR. */
#define LPTMR_CLOCKS \
{ \
kCLOCK_Lptmr0 \
}
/*! @brief Clock ip name array for ADC16. */
#define ADC16_CLOCKS \
{ \
kCLOCK_Adc0 \
}
/*! @brief Clock ip name array for FLEXIO. */
#define FLEXIO_CLOCKS \
{ \
kCLOCK_Flexio0 \
}
/*! @brief Clock ip name array for VREF. */
#define VREF_CLOCKS \
{ \
kCLOCK_Vref0 \
}
/*! @brief Clock ip name array for DMA. */
#define DMA_CLOCKS \
{ \
kCLOCK_Dma0 \
}
/*! @brief Clock ip name array for UART. */
#define UART_CLOCKS \
{ \
kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_Uart2 \
}
/*! @brief Clock ip name array for TPM. */
#define TPM_CLOCKS \
{ \
kCLOCK_Tpm0, kCLOCK_Tpm1, kCLOCK_Tpm2 \
}
/*! @brief Clock ip name array for I2C. */
#define I2C_CLOCKS \
{ \
kCLOCK_I2c0, kCLOCK_I2c1 \
}
/*! @brief Clock ip name array for FTF. */
#define FTF_CLOCKS \
{ \
kCLOCK_Ftf0 \
}
/*! @brief Clock ip name array for CMP. */
#define CMP_CLOCKS \
{ \
kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2 \
}
/*!
* @brief LPO clock frequency.
*/
#define LPO_CLK_FREQ 1000U
/*! @brief Peripherals clock source definition. */
#define SYS_CLK kCLOCK_CoreSysClk
#define BUS_CLK kCLOCK_BusClk
#define I2C0_CLK_SRC SYS_CLK
#define I2C1_CLK_SRC SYS_CLK
#define SPI0_CLK_SRC BUS_CLK
#define SPI1_CLK_SRC SYS_CLK
#define UART2_CLK_SRC BUS_CLK
/*! @brief Clock name used to get clock frequency. */
typedef enum _clock_name
{
/* ----------------------------- System layer clock -------------------------------*/
kCLOCK_CoreSysClk, /*!< Core/system clock */
kCLOCK_PlatClk, /*!< Platform clock */
kCLOCK_BusClk, /*!< Bus clock */
kCLOCK_FlexBusClk, /*!< FlexBus clock */
kCLOCK_FlashClk, /*!< Flash clock */
kCLOCK_FastPeriphClk, /*!< Fast peripheral clock */
kCLOCK_PllFllSelClk, /*!< The clock after SIM[PLLFLLSEL]. */
/* ---------------------------------- OSC clock -----------------------------------*/
kCLOCK_Er32kClk, /*!< External reference 32K clock (ERCLK32K) */
kCLOCK_Osc0ErClk, /*!< OSC0 external reference clock (OSC0ERCLK) */
kCLOCK_Osc1ErClk, /*!< OSC1 external reference clock (OSC1ERCLK) */
kCLOCK_Osc0ErClkUndiv, /*!< OSC0 external reference undivided clock(OSC0ERCLK_UNDIV). */
/* ----------------------------- MCG and MCG-Lite clock ---------------------------*/
kCLOCK_McgFixedFreqClk, /*!< MCG fixed frequency clock (MCGFFCLK) */
kCLOCK_McgInternalRefClk, /*!< MCG internal reference clock (MCGIRCLK) */
kCLOCK_McgFllClk, /*!< MCGFLLCLK */
kCLOCK_McgPll0Clk, /*!< MCGPLL0CLK */
kCLOCK_McgPll1Clk, /*!< MCGPLL1CLK */
kCLOCK_McgExtPllClk, /*!< EXT_PLLCLK */
kCLOCK_McgPeriphClk, /*!< MCG peripheral clock (MCGPCLK) */
kCLOCK_McgIrc48MClk, /*!< MCG IRC48M clock */
/* --------------------------------- Other clock ----------------------------------*/
kCLOCK_LpoClk, /*!< LPO clock */
} clock_name_t;
/*! @brief USB clock source definition. */
typedef enum _clock_usb_src
{
kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U), /*!< Use IRC48M. */
kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */
} clock_usb_src_t;
/*------------------------------------------------------------------------------
clock_gate_t definition:
31 16 0
-----------------------------------------------------------------
| SIM_SCGC register offset | control bit offset in SCGC |
-----------------------------------------------------------------
For example, the SDHC clock gate is controlled by SIM_SCGC3[17], the
SIM_SCGC3 offset in SIM is 0x1030, then kCLOCK_GateSdhc0 is defined as
kCLOCK_GateSdhc0 = (0x1030 << 16) | 17;
------------------------------------------------------------------------------*/
#define CLK_GATE_REG_OFFSET_SHIFT 16U
#define CLK_GATE_REG_OFFSET_MASK 0xFFFF0000U
#define CLK_GATE_BIT_SHIFT_SHIFT 0U
#define CLK_GATE_BIT_SHIFT_MASK 0x0000FFFFU
#define CLK_GATE_DEFINE(reg_offset, bit_shift) \
((((reg_offset) << CLK_GATE_REG_OFFSET_SHIFT) & CLK_GATE_REG_OFFSET_MASK) | \
(((bit_shift) << CLK_GATE_BIT_SHIFT_SHIFT) & CLK_GATE_BIT_SHIFT_MASK))
#define CLK_GATE_ABSTRACT_REG_OFFSET(x) (((x)&CLK_GATE_REG_OFFSET_MASK) >> CLK_GATE_REG_OFFSET_SHIFT)
#define CLK_GATE_ABSTRACT_BITS_SHIFT(x) (((x)&CLK_GATE_BIT_SHIFT_MASK) >> CLK_GATE_BIT_SHIFT_SHIFT)
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
typedef enum _clock_ip_name
{
kCLOCK_IpInvalid = 0U,
kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U),
kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U),
kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U),
kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U),
kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U),
kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U),
kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U),
kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U),
kCLOCK_Spi0 = CLK_GATE_DEFINE(0x1034U, 22U),
kCLOCK_Spi1 = CLK_GATE_DEFINE(0x1034U, 23U),
kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U),
kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U),
kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U),
kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U),
kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U),
kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U),
kCLOCK_Slcd0 = CLK_GATE_DEFINE(0x1038U, 19U),
kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x1038U, 20U),
kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x1038U, 21U),
kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x1038U, 31U),
kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U),
kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U),
kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U),
kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U),
kCLOCK_Tpm0 = CLK_GATE_DEFINE(0x103CU, 24U),
kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x103CU, 25U),
kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x103CU, 26U),
kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U),
kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U),
kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U),
kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 8U),
} clock_ip_name_t;
/*!@brief SIM configuration structure for clock setting. */
typedef struct _sim_clock_config
{
uint8_t er32kSrc; /*!< ERCLK32K source selection. */
uint32_t clkdiv1; /*!< SIM_CLKDIV1. */
} sim_clock_config_t;
/*! @brief Oscillator capacitor load setting.*/
enum _osc_cap_load
{
kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */
kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */
kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */
kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */
};
/*! @brief OSCERCLK enable mode. */
enum _oscer_enable_mode
{
kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */
kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */
};
/*! @brief OSC configuration for OSCERCLK. */
typedef struct _oscer_config
{
uint8_t enableMode; /*!< OSCERCLK enable mode. OR'ed value of \ref _oscer_enable_mode. */
} oscer_config_t;
/*! @brief OSC work mode. */
typedef enum _osc_mode
{
kOSC_ModeExt = 0U, /*!< Use external clock. */
kOSC_ModeOscLowPower = MCG_C2_EREFS0_MASK, /*!< Oscillator low power. */
kOSC_ModeOscHighGain = MCG_C2_EREFS0_MASK | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */
} osc_mode_t;
/*!
* @brief OSC Initialization Configuration Structure
*
* Defines the configuration data structure to initialize the OSC.
* When porting to a new board, set the following members
* according to board settings:
* 1. freq: The external frequency.
* 2. workMode: The OSC module mode.
*/
typedef struct _osc_config
{
uint32_t freq; /*!< External clock frequency. */
uint8_t capLoad; /*!< Capacitor load setting. */
osc_mode_t workMode; /*!< OSC work mode setting. */
oscer_config_t oscerConfig; /*!< Configuration for OSCERCLK. */
} osc_config_t;
/*! @brief MCG_Lite clock source selection. */
typedef enum _mcglite_clkout_src
{
kMCGLITE_ClkSrcHirc, /*!< MCGOUTCLK source is HIRC */
kMCGLITE_ClkSrcLirc, /*!< MCGOUTCLK source is LIRC */
kMCGLITE_ClkSrcExt, /*!< MCGOUTCLK source is external clock source */
kMCGLITE_ClkSrcReserved
} mcglite_clkout_src_t;
/*! @brief MCG_Lite LIRC select. */
typedef enum _mcglite_lirc_mode
{
kMCGLITE_Lirc2M, /*!< Slow internal reference(LIRC) 2MHz clock selected */
kMCGLITE_Lirc8M, /*!< Slow internal reference(LIRC) 8MHz clock selected */
} mcglite_lirc_mode_t;
/*! @brief MCG_Lite divider factor selection for clock source*/
typedef enum _mcglite_lirc_div
{
kMCGLITE_LircDivBy1 = 0U, /*!< Divider is 1 */
kMCGLITE_LircDivBy2, /*!< Divider is 2 */
kMCGLITE_LircDivBy4, /*!< Divider is 4 */
kMCGLITE_LircDivBy8, /*!< Divider is 8 */
kMCGLITE_LircDivBy16, /*!< Divider is 16 */
kMCGLITE_LircDivBy32, /*!< Divider is 32 */
kMCGLITE_LircDivBy64, /*!< Divider is 64 */
kMCGLITE_LircDivBy128 /*!< Divider is 128 */
} mcglite_lirc_div_t;
/*! @brief MCG_Lite clock mode definitions */
typedef enum _mcglite_mode
{
kMCGLITE_ModeHirc48M, /*!< Clock mode is HIRC 48 M */
kMCGLITE_ModeLirc8M, /*!< Clock mode is LIRC 8 M */
kMCGLITE_ModeLirc2M, /*!< Clock mode is LIRC 2 M */
kMCGLITE_ModeExt, /*!< Clock mode is EXT */
kMCGLITE_ModeError /*!< Unknown mode */
} mcglite_mode_t;
/*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */
enum _mcglite_irclk_enable_mode
{
kMCGLITE_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */
kMCGLITE_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */
};
/*! @brief MCG_Lite configure structure for mode change. */
typedef struct _mcglite_config
{
mcglite_clkout_src_t outSrc; /*!< MCGOUT clock select. */
uint8_t irclkEnableMode; /*!< MCGIRCLK enable mode, OR'ed value of _mcglite_irclk_enable_mode. */
mcglite_lirc_mode_t ircs; /*!< MCG_C2[IRCS]. */
mcglite_lirc_div_t fcrdiv; /*!< MCG_SC[FCRDIV]. */
mcglite_lirc_div_t lircDiv2; /*!< MCG_MC[LIRC_DIV2]. */
bool hircEnableInNotHircMode; /*!< HIRC enable when not in HIRC mode. */
} mcglite_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @brief Set the XTAL0 frequency based on board setting.
*
* @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
*/
static inline void CLOCK_SetXtal0Freq(uint32_t freq)
{
g_xtal0Freq = freq;
}
/*!
* @brief Set the XTAL32/RTC_CLKIN frequency based on board setting.
*
* @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz.
*/
static inline void CLOCK_SetXtal32Freq(uint32_t freq)
{
g_xtal32Freq = freq;
}
/*!
* @brief Enable the clock for specific IP.
*
* @param name Which clock to enable, see \ref clock_ip_name_t.
*/
static inline void CLOCK_EnableClock(clock_ip_name_t name)
{
uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
(*(volatile uint32_t *)regAddr) |= (1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
}
/*!
* @brief Disable the clock for specific IP.
*
* @param name Which clock to disable, see \ref clock_ip_name_t.
*/
static inline void CLOCK_DisableClock(clock_ip_name_t name)
{
uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
(*(volatile uint32_t *)regAddr) &= ~(1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
}
/*!
* @brief Set ERCLK32K source.
*
* @param src The value to set ERCLK32K clock source.
*/
static inline void CLOCK_SetEr32kClock(uint32_t src)
{
SIM->SOPT1 = ((SIM->SOPT1 & ~SIM_SOPT1_OSC32KSEL_MASK) | SIM_SOPT1_OSC32KSEL(src));
}
/*!
* @brief Set LPUART0 clock source.
*
* @param src The value to set LPUART0 clock source.
*/
static inline void CLOCK_SetLpuart0Clock(uint32_t src)
{
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_LPUART0SRC_MASK) | SIM_SOPT2_LPUART0SRC(src));
}
/*!
* @brief Set LPUART1 clock source.
*
* @param src The value to set LPUART1 clock source.
*/
static inline void CLOCK_SetLpuart1Clock(uint32_t src)
{
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_LPUART1SRC_MASK) | SIM_SOPT2_LPUART1SRC(src));
}
/*!
* @brief Set TPM clock source.
*
* @param src The value to set TPM clock source.
*/
static inline void CLOCK_SetTpmClock(uint32_t src)
{
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TPMSRC_MASK) | SIM_SOPT2_TPMSRC(src));
}
/*!
* @brief Set FLEXIO clock source.
*
* @param src The value to set FLEXIO clock source.
*/
static inline void CLOCK_SetFlexio0Clock(uint32_t src)
{
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_FLEXIOSRC_MASK) | SIM_SOPT2_FLEXIOSRC(src));
}
/*! @brief Enable USB FS clock.
*
* @param src USB FS clock source.
* @param freq The frequency specified by src.
* @retval true The clock is set successfully.
* @retval false The clock source is invalid to get proper USB FS clock.
*/
bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq);
/*! @brief Disable USB FS clock.
*
* Disable USB FS clock.
*/
static inline void CLOCK_DisableUsbfs0Clock(void)
{
CLOCK_DisableClock(kCLOCK_Usbfs0);
}
/*!
* @brief Set CLKOUT source.
*
* @param src The value to set CLKOUT source.
*/
static inline void CLOCK_SetClkOutClock(uint32_t src)
{
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_CLKOUTSEL_MASK) | SIM_SOPT2_CLKOUTSEL(src));
}
/*!
* @brief Set RTC_CLKOUT source.
*
* @param src The value to set RTC_CLKOUT source.
*/
static inline void CLOCK_SetRtcClkOutClock(uint32_t src)
{
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_RTCCLKOUTSEL_MASK) | SIM_SOPT2_RTCCLKOUTSEL(src));
}
/*!
* @brief System clock divider
*
* Set the SIM_CLKDIV1[OUTDIV1], SIM_CLKDIV1[OUTDIV4].
*
* @param outdiv1 Clock 1 output divider value.
*
* @param outdiv4 Clock 4 output divider value.
*/
static inline void CLOCK_SetOutDiv(uint32_t outdiv1, uint32_t outdiv4)
{
SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(outdiv1) | SIM_CLKDIV1_OUTDIV4(outdiv4);
}
/*!
* @brief Gets the clock frequency for a specific clock name.
*
* This function checks the current clock configurations and then calculates
* the clock frequency for a specific clock name defined in clock_name_t.
* The MCG must be properly configured before using this function.
*
* @param clockName Clock names defined in clock_name_t
* @return Clock frequency value in Hertz
*/
uint32_t CLOCK_GetFreq(clock_name_t clockName);
/*!
* @brief Get the core clock or system clock frequency.
*
* @return Clock frequency in Hz.
*/
uint32_t CLOCK_GetCoreSysClkFreq(void);
/*!
* @brief Get the platform clock frequency.
*
* @return Clock frequency in Hz.
*/
uint32_t CLOCK_GetPlatClkFreq(void);
/*!
* @brief Get the bus clock frequency.
*
* @return Clock frequency in Hz.
*/
uint32_t CLOCK_GetBusClkFreq(void);
/*!
* @brief Get the flash clock frequency.
*
* @return Clock frequency in Hz.
*/
uint32_t CLOCK_GetFlashClkFreq(void);
/*!
* @brief Get the external reference 32K clock frequency (ERCLK32K).
*
* @return Clock frequency in Hz.
*/
uint32_t CLOCK_GetEr32kClkFreq(void);
/*!
* @brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
*
* @return Clock frequency in Hz.
*/
uint32_t CLOCK_GetOsc0ErClkFreq(void);
/*!
* @brief Set the clock configure in SIM module.
*
* This function sets system layer clock settings in SIM module.
*
* @param config Pointer to the configure structure.
*/
void CLOCK_SetSimConfig(sim_clock_config_t const *config);
/*!
* @brief Set the system clock dividers in SIM to safe value.
*
* The system level clocks (core clock, bus clock, flexbus clock and flash clock)
* must be in allowed ranges. During MCG clock mode switch, the MCG output clock
* changes then the system level clocks may be out of range. This function could
* be used before MCG mode change, to make sure system level clocks are in allowed
* range.
*
* @param config Pointer to the configure structure.
*/
static inline void CLOCK_SetSimSafeDivs(void)
{
SIM->CLKDIV1 = 0x10030000U;
}
/*!
* @name MCG_Lite clock frequency
* @{
*/
/*!
* @brief Gets the MCG_Lite output clock (MCGOUTCLK) frequency.
*
* This function gets the MCG_Lite output clock frequency (Hz) based on the current
* MCG_Lite register value.
*
* @return The frequency of MCGOUTCLK.
*/
uint32_t CLOCK_GetOutClkFreq(void);
/*!
* @brief Gets the MCG internal reference clock (MCGIRCLK) frequency.
*
* This function gets the MCG_Lite internal reference clock frequency (Hz) based
* on the current MCG register value.
*
* @return The frequency of MCGIRCLK.
*/
uint32_t CLOCK_GetInternalRefClkFreq(void);
/*!
* @brief Gets the current MCGPCLK frequency.
*
* This function gets the MCGPCLK frequency (Hertz) based on the current MCG_Lite
* register settings.
*
* @return The frequency of MCGPCLK.
*/
uint32_t CLOCK_GetPeriphClkFreq(void);
/*! @}*/
/*!
* @name MCG_Lite mode.
* @{
*/
/*!
* @brief Gets the current MCG_Lite mode.
*
* This function checks the MCG_Lite registers and determines the current MCG_Lite mode.
*
* @return Current MCG_Lite mode or error code.
*/
mcglite_mode_t CLOCK_GetMode(void);
/*!
* @brief Sets the MCG_Lite configuration.
*
* This function configures the MCG_Lite, include output clock source, MCGIRCLK
* setting, HIRC setting and so on, see @ref mcglite_config_t for details.
*
* @param targetConfig Pointer to the target MCG_Lite mode configuration structure.
* @return Error code.
*/
status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig);
/*! @}*/
/*!
* @name OSC configuration
* @{
*/
/*!
* @brief Configures the OSC external reference clock (OSCERCLK).
*
* This function configures the OSC external reference clock (OSCERCLK).
* For example, to enable the OSCERCLK in normal mode and stop mode, and also set
* the output divider to 1, as follows:
*
@code
oscer_config_t config =
{
.enableMode = kOSC_ErClkEnable | kOSC_ErClkEnableInStop,
.erclkDiv = 1U,
};
OSC_SetExtRefClkConfig(OSC, &config);
@endcode
*
* @param base OSC peripheral address.
* @param config Pointer to the configuration structure.
*/
static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const *config)
{
uint8_t reg = base->CR;
reg &= ~(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK);
reg |= config->enableMode;
base->CR = reg;
}
/*!
* @brief Sets the capacitor load configuration for the oscillator.
*
* This function sets the specified capacitors configuration for the oscillator.
* This should be done in the early system level initialization function call
* based on the system configuration.
*
* @param base OSC peripheral address.
* @param capLoad OR'ed value for the capacitor load option, see \ref _osc_cap_load.
*
* Example:
@code
// To enable only 2 pF and 8 pF capacitor load, please use like this.
OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P);
@endcode
*/
static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad)
{
uint8_t reg = base->CR;
reg &= ~(OSC_CR_SC2P_MASK | OSC_CR_SC4P_MASK | OSC_CR_SC8P_MASK | OSC_CR_SC16P_MASK);
reg |= capLoad;
base->CR = reg;
}
/*!
* @brief Initialize OSC0.
*
* This function initializes the OSC0 according to the board configuration.
*
* @param config Pointer to the OSC0 configuration structure.
*/
void CLOCK_InitOsc0(osc_config_t const *config);
/*!
* @brief Deinitializes the OSC0.
*
* This function deinitializes the OSC0.
*/
void CLOCK_DeinitOsc0(void);
/*! @}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @} */
#endif /* _FSL_CLOCK_H_ */

View File

@ -0,0 +1,279 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_cmp.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for CMP module.
*
* @param base CMP peripheral base address
*/
static uint32_t CMP_GetInstance(CMP_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to CMP bases for each instance. */
static CMP_Type *const s_cmpBases[] = CMP_BASE_PTRS;
/*! @brief Pointers to CMP clocks for each instance. */
const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS;
/*******************************************************************************
* Codes
******************************************************************************/
static uint32_t CMP_GetInstance(CMP_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_CMP_COUNT; instance++)
{
if (s_cmpBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_CMP_COUNT);
return instance;
}
void CMP_Init(CMP_Type *base, const cmp_config_t *config)
{
assert(NULL != config);
uint8_t tmp8;
/* Enable the clock. */
CLOCK_EnableClock(s_cmpClocks[CMP_GetInstance(base)]);
/* Configure. */
CMP_Enable(base, false); /* Disable the CMP module during configuring. */
/* CMPx_CR1. */
tmp8 = base->CR1 & ~(CMP_CR1_PMODE_MASK | CMP_CR1_INV_MASK | CMP_CR1_COS_MASK | CMP_CR1_OPE_MASK);
if (config->enableHighSpeed)
{
tmp8 |= CMP_CR1_PMODE_MASK;
}
if (config->enableInvertOutput)
{
tmp8 |= CMP_CR1_INV_MASK;
}
if (config->useUnfilteredOutput)
{
tmp8 |= CMP_CR1_COS_MASK;
}
if (config->enablePinOut)
{
tmp8 |= CMP_CR1_OPE_MASK;
}
#if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE
if (config->enableTriggerMode)
{
tmp8 |= CMP_CR1_TRIGM_MASK;
}
else
{
tmp8 &= ~CMP_CR1_TRIGM_MASK;
}
#endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */
base->CR1 = tmp8;
/* CMPx_CR0. */
tmp8 = base->CR0 & ~CMP_CR0_HYSTCTR_MASK;
tmp8 |= CMP_CR0_HYSTCTR(config->hysteresisMode);
base->CR0 = tmp8;
CMP_Enable(base, config->enableCmp); /* Enable the CMP module after configured or not. */
}
void CMP_Deinit(CMP_Type *base)
{
/* Disable the CMP module. */
CMP_Enable(base, false);
/* Disable the clock. */
CLOCK_DisableClock(s_cmpClocks[CMP_GetInstance(base)]);
}
void CMP_GetDefaultConfig(cmp_config_t *config)
{
assert(NULL != config);
config->enableCmp = true; /* Enable the CMP module after initialization. */
config->hysteresisMode = kCMP_HysteresisLevel0;
config->enableHighSpeed = false;
config->enableInvertOutput = false;
config->useUnfilteredOutput = false;
config->enablePinOut = false;
#if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE
config->enableTriggerMode = false;
#endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */
}
void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negativeChannel)
{
uint8_t tmp8 = base->MUXCR;
tmp8 &= ~(CMP_MUXCR_PSEL_MASK | CMP_MUXCR_MSEL_MASK);
tmp8 |= CMP_MUXCR_PSEL(positiveChannel) | CMP_MUXCR_MSEL(negativeChannel);
base->MUXCR = tmp8;
}
#if defined(FSL_FEATURE_CMP_HAS_DMA) && FSL_FEATURE_CMP_HAS_DMA
void CMP_EnableDMA(CMP_Type *base, bool enable)
{
uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
if (enable)
{
tmp8 |= CMP_SCR_DMAEN_MASK;
}
else
{
tmp8 &= ~CMP_SCR_DMAEN_MASK;
}
base->SCR = tmp8;
}
#endif /* FSL_FEATURE_CMP_HAS_DMA */
void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config)
{
assert(NULL != config);
uint8_t tmp8;
#if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT
/* Choose the clock source for sampling. */
if (config->enableSample)
{
base->CR1 |= CMP_CR1_SE_MASK; /* Choose the external SAMPLE clock. */
}
else
{
base->CR1 &= ~CMP_CR1_SE_MASK; /* Choose the internal divided bus clock. */
}
#endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */
/* Set the filter count. */
tmp8 = base->CR0 & ~CMP_CR0_FILTER_CNT_MASK;
tmp8 |= CMP_CR0_FILTER_CNT(config->filterCount);
base->CR0 = tmp8;
/* Set the filter period. It is used as the divider to bus clock. */
base->FPR = CMP_FPR_FILT_PER(config->filterPeriod);
}
void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config)
{
uint8_t tmp8 = 0U;
if (NULL == config)
{
/* Passing "NULL" as input parameter means no available configuration. So the DAC feature is disabled.*/
base->DACCR = 0U;
return;
}
/* CMPx_DACCR. */
tmp8 |= CMP_DACCR_DACEN_MASK; /* Enable the internal DAC. */
if (kCMP_VrefSourceVin2 == config->referenceVoltageSource)
{
tmp8 |= CMP_DACCR_VRSEL_MASK;
}
tmp8 |= CMP_DACCR_VOSEL(config->DACValue);
base->DACCR = tmp8;
}
void CMP_EnableInterrupts(CMP_Type *base, uint32_t mask)
{
uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
if (0U != (kCMP_OutputRisingInterruptEnable & mask))
{
tmp8 |= CMP_SCR_IER_MASK;
}
if (0U != (kCMP_OutputFallingInterruptEnable & mask))
{
tmp8 |= CMP_SCR_IEF_MASK;
}
base->SCR = tmp8;
}
void CMP_DisableInterrupts(CMP_Type *base, uint32_t mask)
{
uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
if (0U != (kCMP_OutputRisingInterruptEnable & mask))
{
tmp8 &= ~CMP_SCR_IER_MASK;
}
if (0U != (kCMP_OutputFallingInterruptEnable & mask))
{
tmp8 &= ~CMP_SCR_IEF_MASK;
}
base->SCR = tmp8;
}
uint32_t CMP_GetStatusFlags(CMP_Type *base)
{
uint32_t ret32 = 0U;
if (0U != (CMP_SCR_CFR_MASK & base->SCR))
{
ret32 |= kCMP_OutputRisingEventFlag;
}
if (0U != (CMP_SCR_CFF_MASK & base->SCR))
{
ret32 |= kCMP_OutputFallingEventFlag;
}
if (0U != (CMP_SCR_COUT_MASK & base->SCR))
{
ret32 |= kCMP_OutputAssertEventFlag;
}
return ret32;
}
void CMP_ClearStatusFlags(CMP_Type *base, uint32_t mask)
{
uint8_t tmp8 = base->SCR & ~(CMP_SCR_CFR_MASK | CMP_SCR_CFF_MASK); /* To avoid change the w1c bits. */
if (0U != (kCMP_OutputRisingEventFlag & mask))
{
tmp8 |= CMP_SCR_CFR_MASK;
}
if (0U != (kCMP_OutputFallingEventFlag & mask))
{
tmp8 |= CMP_SCR_CFF_MASK;
}
base->SCR = tmp8;
}

View File

@ -0,0 +1,346 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_CMP_H_
#define _FSL_CMP_H_
#include "fsl_common.h"
/*!
* @addtogroup cmp
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief CMP driver version 2.0.0. */
#define FSL_CMP_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief Interrupt enable/disable mask.
*/
enum _cmp_interrupt_enable
{
kCMP_OutputRisingInterruptEnable = CMP_SCR_IER_MASK, /*!< Comparator interrupt enable rising. */
kCMP_OutputFallingInterruptEnable = CMP_SCR_IEF_MASK, /*!< Comparator interrupt enable falling. */
};
/*!
* @brief Status flags' mask.
*/
enum _cmp_status_flags
{
kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on compare output has occurred. */
kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on compare output has occurred. */
kCMP_OutputAssertEventFlag = CMP_SCR_COUT_MASK, /*!< Return the current value of the analog comparator output. */
};
/*!
* @brief CMP Hysteresis mode.
*/
typedef enum _cmp_hysteresis_mode
{
kCMP_HysteresisLevel0 = 0U, /*!< Hysteresis level 0. */
kCMP_HysteresisLevel1 = 1U, /*!< Hysteresis level 1. */
kCMP_HysteresisLevel2 = 2U, /*!< Hysteresis level 2. */
kCMP_HysteresisLevel3 = 3U, /*!< Hysteresis level 3. */
} cmp_hysteresis_mode_t;
/*!
* @brief CMP Voltage Reference source.
*/
typedef enum _cmp_reference_voltage_source
{
kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as resistor ladder network supply reference Vin. */
kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as resistor ladder network supply reference Vin. */
} cmp_reference_voltage_source_t;
/*!
* @brief Configure the comparator.
*/
typedef struct _cmp_config
{
bool enableCmp; /*!< Enable the CMP module. */
cmp_hysteresis_mode_t hysteresisMode; /*!< CMP Hysteresis mode. */
bool enableHighSpeed; /*!< Enable High Speed (HS) comparison mode. */
bool enableInvertOutput; /*!< Enable inverted comparator output. */
bool useUnfilteredOutput; /*!< Set compare output(COUT) to equal COUTA(true) or COUT(false). */
bool enablePinOut; /*!< The comparator output is available on the associated pin. */
#if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE
bool enableTriggerMode; /*!< Enable the trigger mode. */
#endif /* FSL_FEATURE_CMP_HAS_TRIGGER_MODE */
} cmp_config_t;
/*!
* @brief Configure the filter.
*/
typedef struct _cmp_filter_config
{
#if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT
bool enableSample; /*!< Using external SAMPLE as sampling clock input, or using divided bus clock. */
#endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */
uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7, 0 would cause the filter disabled.*/
uint8_t filterPeriod; /*!< Filter Sample Period. The divider to bus clock. Available range is 0-255. */
} cmp_filter_config_t;
/*!
* @brief Configure the internal DAC.
*/
typedef struct _cmp_dac_config
{
cmp_reference_voltage_source_t referenceVoltageSource; /*!< Supply voltage reference source. */
uint8_t DACValue; /*!< Value for DAC Output Voltage. Available range is 0-63.*/
} cmp_dac_config_t;
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* API
******************************************************************************/
/*!
* @name Initialization
* @{
*/
/*!
* @brief Initializes the CMP.
*
* This function initializes the CMP module. The operations included are:
* - Enabling the clock for CMP module.
* - Configuring the comparator.
* - Enabling the CMP module.
* Note: For some devices, multiple CMP instance share the same clock gate. In this case, to enable the clock for
* any instance enables all the CMPs. Check the chip reference manual for the clock assignment of the CMP.
*
* @param base CMP peripheral base address.
* @param config Pointer to configuration structure.
*/
void CMP_Init(CMP_Type *base, const cmp_config_t *config);
/*!
* @brief De-initializes the CMP module.
*
* This function de-initializes the CMP module. The operations included are:
* - Disabling the CMP module.
* - Disabling the clock for CMP module.
*
* This function disables the clock for the CMP.
* Note: For some devices, multiple CMP instance shares the same clock gate. In this case, before disabling the
* clock for the CMP, ensure that all the CMP instances are not used.
*
* @param base CMP peripheral base address.
*/
void CMP_Deinit(CMP_Type *base);
/*!
* @brief Enables/disables the CMP module.
*
* @param base CMP peripheral base address.
* @param enable Enable the module or not.
*/
static inline void CMP_Enable(CMP_Type *base, bool enable)
{
if (enable)
{
base->CR1 |= CMP_CR1_EN_MASK;
}
else
{
base->CR1 &= ~CMP_CR1_EN_MASK;
}
}
/*!
* @brief Initializes the CMP user configuration structure.
*
* This function initializes the user configure structure to these default values:
* @code
* config->enableCmp = true;
* config->hysteresisMode = kCMP_HysteresisLevel0;
* config->enableHighSpeed = false;
* config->enableInvertOutput = false;
* config->useUnfilteredOutput = false;
* config->enablePinOut = false;
* config->enableTriggerMode = false;
* @endcode
* @param config Pointer to the configuration structure.
*/
void CMP_GetDefaultConfig(cmp_config_t *config);
/*!
* @brief Sets the input channels for the comparator.
*
* This function sets the input channels for the comparator.
* Note that two input channels cannot be set as same in the application. When the user selects the same input
* from the analog mux to the positive and negative port, the comparator is disabled automatically.
*
* @param base CMP peripheral base address.
* @param positiveChannel Positive side input channel number. Available range is 0-7.
* @param negativeChannel Negative side input channel number. Available range is 0-7.
*/
void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negativeChannel);
/* @} */
/*!
* @name Advanced Features
* @{
*/
#if defined(FSL_FEATURE_CMP_HAS_DMA) && FSL_FEATURE_CMP_HAS_DMA
/*!
* @brief Enables/disables the DMA request for rising/falling events.
*
* This function enables/disables the DMA request for rising/falling events. Either event triggers the generation of
* the DMA
* request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP
* if the
* DMA is disabled.
*
* @param base CMP peripheral base address.
* @param enable Enable the feature or not.
*/
void CMP_EnableDMA(CMP_Type *base, bool enable);
#endif /* FSL_FEATURE_CMP_HAS_DMA */
#if defined(FSL_FEATURE_CMP_HAS_WINDOW_MODE) && FSL_FEATURE_CMP_HAS_WINDOW_MODE
/*!
* @brief Enables/disables the window mode.
*
* @param base CMP peripheral base address.
* @param enable Enable the feature or not.
*/
static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable)
{
if (enable)
{
base->CR1 |= CMP_CR1_WE_MASK;
}
else
{
base->CR1 &= ~CMP_CR1_WE_MASK;
}
}
#endif /* FSL_FEATURE_CMP_HAS_WINDOW_MODE */
#if defined(FSL_FEATURE_CMP_HAS_PASS_THROUGH_MODE) && FSL_FEATURE_CMP_HAS_PASS_THROUGH_MODE
/*!
* @brief Enables/disables the pass through mode.
*
* @param base CMP peripheral base address.
* @param enable Enable the feature or not.
*/
static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable)
{
if (enable)
{
base->MUXCR |= CMP_MUXCR_PSTM_MASK;
}
else
{
base->MUXCR &= ~CMP_MUXCR_PSTM_MASK;
}
}
#endif /* FSL_FEATURE_CMP_HAS_PASS_THROUGH_MODE */
/*!
* @brief Configures the filter.
*
* @param base CMP peripheral base address.
* @param config Pointer to configuration structure.
*/
void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config);
/*!
* @brief Configures the internal DAC.
*
* @param base CMP peripheral base address.
* @param config Pointer to configuration structure. "NULL" is for disabling the feature.
*/
void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config);
/*!
* @brief Enables the interrupts.
*
* @param base CMP peripheral base address.
* @param mask Mask value for interrupts. See "_cmp_interrupt_enable".
*/
void CMP_EnableInterrupts(CMP_Type *base, uint32_t mask);
/*!
* @brief Disables the interrupts.
*
* @param base CMP peripheral base address.
* @param mask Mask value for interrupts. See "_cmp_interrupt_enable".
*/
void CMP_DisableInterrupts(CMP_Type *base, uint32_t mask);
/* @} */
/*!
* @name Results
* @{
*/
/*!
* @brief Gets the status flags.
*
* @param base CMP peripheral base address.
*
* @return Mask value for the asserted flags. See "_cmp_status_flags".
*/
uint32_t CMP_GetStatusFlags(CMP_Type *base);
/*!
* @brief Clears the status flags.
*
* @param base CMP peripheral base address.
* @param mask Mask value for the flags. See "_cmp_status_flags".
*/
void CMP_ClearStatusFlags(CMP_Type *base, uint32_t mask);
/* @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_CMP_H_ */

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_common.h"
/* This is not needed for mbed */
#if 0
#include "fsl_debug_console.h"
#ifndef NDEBUG
#if (defined(__CC_ARM)) || (defined(__ICCARM__))
void __aeabi_assert(const char *failedExpr, const char *file, int line)
{
PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" \n", failedExpr, file, line);
for (;;)
{
__asm("bkpt #0");
}
}
#elif(defined(__GNUC__))
void __assert_func(const char *file, int line, const char *func, const char *failedExpr)
{
PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" function name \"%s\" \n", failedExpr, file, line, func);
for (;;)
{
__asm("bkpt #0");
}
}
#endif /* (defined(__CC_ARM)) || (defined (__ICCARM__)) */
#endif /* NDEBUG */
#endif
void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM)
extern uint32_t Image$$VECTOR_ROM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$Base[];
extern uint32_t Image$$RW_m_data$$Base[];
#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
#elif defined(__ICCARM__)
extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
#elif defined(__GNUC__)
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
#endif /* defined(__CC_ARM) */
uint32_t n;
uint32_t interrupts_disabled;
interrupts_disabled = __get_PRIMASK();
__disable_irq();
if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
SCB->VTOR = (uint32_t)__VECTOR_RAM;
}
/* make sure the __VECTOR_RAM is noncachable */
__VECTOR_RAM[irq + 16] = irqHandler;
if (!interrupts_disabled) {
__enable_irq();
}
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_COMMON_H_
#define _FSL_COMMON_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "fsl_device_registers.h"
/*!
* @addtogroup ksdk_common
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/* Debug console type definition. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */
};
/*! @brief Generic status return codes. */
enum _generic_status
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#include "fsl_clock.h"
/*! @name Min/max macros */
/* @{ */
#if !defined(MIN)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#if !defined(MAX)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/* @} */
/*! @brief Computes the number of elements in an array. */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/*! @name UINT16_MAX/UINT32_MAX value */
/* @{ */
#if !defined(UINT16_MAX)
#define UINT16_MAX ((uint16_t)-1)
#endif
#if !defined(UINT32_MAX)
#define UINT32_MAX ((uint32_t)-1)
#endif
/* @} */
/*! @name Timer utilities */
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000000U / clockFreqInHz)
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)ms * clockFreqInHz / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000U / clockFreqInHz)
/* @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Enable specific interrupt.
*
* Enable the interrupt not routed from intmux.
*
* @param interrupt The IRQ number.
*/
static inline void EnableIRQ(IRQn_Type interrupt)
{
#if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0)
if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX)
#endif
{
NVIC_EnableIRQ(interrupt);
}
}
/*!
* @brief Disable specific interrupt.
*
* Disable the interrupt not routed from intmux.
*
* @param interrupt The IRQ number.
*/
static inline void DisableIRQ(IRQn_Type interrupt)
{
#if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0)
if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX)
#endif
{
NVIC_DisableIRQ(interrupt);
}
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
uint32_t regPrimask = __get_PRIMASK();
__disable_irq();
return regPrimask;
}
/*!
* @brief Enaable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convinience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
__set_PRIMASK(primask);
}
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
*/
void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_COMMON_H_ */

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_cop.h"
/*******************************************************************************
* Code
******************************************************************************/
void COP_GetDefaultConfig(cop_config_t *config)
{
assert(config);
config->enableWindowMode = false;
#if defined(FSL_FEATURE_COP_HAS_LONGTIME_MODE) && FSL_FEATURE_COP_HAS_LONGTIME_MODE
config->timeoutMode = kCOP_LongTimeoutMode;
config->enableStop = false;
config->enableDebug = false;
#endif /* FSL_FEATURE_COP_HAS_LONGTIME_MODE */
config->clockSource = kCOP_LpoClock;
config->timeoutCycles = kCOP_2Power10CyclesOr2Power18Cycles;
}
void COP_Init(SIM_Type *base, const cop_config_t *config)
{
assert(config);
uint32_t value = 0U;
#if defined(FSL_FEATURE_COP_HAS_LONGTIME_MODE) && FSL_FEATURE_COP_HAS_LONGTIME_MODE
value = SIM_COPC_COPW(config->enableWindowMode) | SIM_COPC_COPCLKS(config->timeoutMode) |
SIM_COPC_COPT(config->timeoutCycles) | SIM_COPC_COPSTPEN(config->enableStop) |
SIM_COPC_COPDBGEN(config->enableDebug) | SIM_COPC_COPCLKSEL(config->clockSource);
#else
value = SIM_COPC_COPW(config->enableWindowMode) | SIM_COPC_COPCLKS(config->clockSource) |
SIM_COPC_COPT(config->timeoutCycles);
#endif /* FSL_FEATURE_COP_HAS_LONGTIME_MODE */
base->COPC = value;
}
void COP_Refresh(SIM_Type *base)
{
uint32_t primaskValue = 0U;
/* Disable the global interrupt to protect refresh sequence */
primaskValue = DisableGlobalIRQ();
base->SRVCOP = COP_FIRST_BYTE_OF_REFRESH;
base->SRVCOP = COP_SECOND_BYTE_OF_REFRESH;
EnableGlobalIRQ(primaskValue);
}

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_COP_H_
#define _FSL_COP_H_
#include "fsl_common.h"
/*!
* @addtogroup cop_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief COP driver version 2.0.0. */
#define FSL_COP_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*! @name COP refresh sequence. */
/*@{*/
#define COP_FIRST_BYTE_OF_REFRESH (0x55U) /*!< First byte of refresh sequence */
#define COP_SECOND_BYTE_OF_REFRESH (0xAAU) /*!< Second byte of refresh sequence */
/*@}*/
/*! @brief COP clock source selection. */
typedef enum _cop_clock_source
{
kCOP_LpoClock = 0U, /*!< COP clock sourced from LPO */
#if defined(FSL_FEATURE_COP_HAS_MORE_CLKSRC) && FSL_FEATURE_COP_HAS_MORE_CLKSRC
kCOP_McgIrClock = 1U, /*!< COP clock sourced from MCGIRCLK */
kCOP_OscErClock = 2U, /*!< COP clock sourced from OSCERCLK */
#endif /* FSL_FEATURE_COP_HAS_MORE_CLKSRC */
kCOP_BusClock = 3U, /*!< COP clock sourced from Bus clock */
} cop_clock_source_t;
/*! @brief Define the COP timeout cycles. */
typedef enum _cop_timeout_cycles
{
kCOP_2Power5CyclesOr2Power13Cycles = 1U, /*!< 2^5 or 2^13 clock cycles */
kCOP_2Power8CyclesOr2Power16Cycles = 2U, /*!< 2^8 or 2^16 clock cycles */
kCOP_2Power10CyclesOr2Power18Cycles = 3U, /*!< 2^10 or 2^18 clock cycles */
} cop_timeout_cycles_t;
#if defined(FSL_FEATURE_COP_HAS_LONGTIME_MODE) && FSL_FEATURE_COP_HAS_LONGTIME_MODE
/*! @breif Define the COP timeout mode. */
typedef enum _cop_timeout_mode
{
kCOP_ShortTimeoutMode = 0U, /*!< COP selects long timeout */
kCOP_LongTimeoutMode = 1U, /*!< COP selects short timeout */
} cop_timeout_mode_t;
#endif /* FSL_FEATURE_COP_HAS_LONGTIME_MODE */
/*! @brief Describes COP configuration structure. */
typedef struct _cop_config
{
bool enableWindowMode; /*!< COP run mode: window mode or normal mode */
#if defined(FSL_FEATURE_COP_HAS_LONGTIME_MODE) && FSL_FEATURE_COP_HAS_LONGTIME_MODE
cop_timeout_mode_t timeoutMode; /*!< COP timeout mode: long timeout or short timeout */
bool enableStop; /*!< Enable or disable COP in STOP mode */
bool enableDebug; /*!< Enable or disable COP in DEBUG mode */
#endif /* FSL_FEATURE_COP_HAS_LONGTIME_MODE */
cop_clock_source_t clockSource; /*!< Set COP clock source */
cop_timeout_cycles_t timeoutCycles; /*!< Set COP timeout value */
} cop_config_t;
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @name COP Functional Operation
* @{
*/
/*!
* @brief Initializes the COP configuration structure.
*
* This function initializes the COP configuration structure to default values. The default
* values are:
* @code
* copConfig->enableWindowMode = false;
* copConfig->timeoutMode = kCOP_LongTimeoutMode;
* copConfig->enableStop = false;
* copConfig->enableDebug = false;
* copConfig->clockSource = kCOP_LpoClock;
* copConfig->timeoutCycles = kCOP_2Power10CyclesOr2Power18Cycles;
* @endcode
*
* @param config Pointer to the COP configuration structure.
* @see cop_config_t
*/
void COP_GetDefaultConfig(cop_config_t *config);
/*!
* @brief Initializes the COP module.
*
* This function configures the COP. After it is called, the COP
* starts running according to the configuration.
* Because all COP control registers are write-once only, the COP_Init function
* and the COP_Disable function can be called only once. A second call has no effect.
*
* Example:
* @code
* cop_config_t config;
* COP_GetDefaultConfig(&config);
* config.timeoutCycles = kCOP_2Power8CyclesOr2Power16Cycles;
* COP_Init(sim_base,&config);
* @endcode
*
* @param base SIM peripheral base address.
* @param config The configuration of COP.
*/
void COP_Init(SIM_Type *base, const cop_config_t *config);
/*!
* @brief De-initializes the COP module.
* This dedicated function is not provided. Instead, the COP_Disable function can be used to disable the COP.
*/
/*!
* @brief Disables the COP module.
*
* This function disables the COP Watchdog.
* Note: The COP configuration register is a write-once after reset.
* To disable the COP Watchdog, call this function first.
*
* @param base SIM peripheral base address.
*/
static inline void COP_Disable(SIM_Type *base)
{
base->COPC &= ~SIM_COPC_COPT_MASK;
}
/*!
* @brief Refreshes the COP timer
*
* This function feeds the COP.
*
* @param base SIM peripheral base address.
*/
void COP_Refresh(SIM_Type *base);
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/
#endif /* _FSL_COP_H_ */

View File

@ -0,0 +1,213 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_dac.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DAC module.
*
* @param base DAC peripheral base address
*/
static uint32_t DAC_GetInstance(DAC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to DAC bases for each instance. */
static DAC_Type *const s_dacBases[] = DAC_BASE_PTRS;
/*! @brief Pointers to DAC clocks for each instance. */
const clock_ip_name_t s_dacClocks[] = DAC_CLOCKS;
/*******************************************************************************
* Codes
******************************************************************************/
static uint32_t DAC_GetInstance(DAC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_DAC_COUNT; instance++)
{
if (s_dacBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_DAC_COUNT);
return instance;
}
void DAC_Init(DAC_Type *base, const dac_config_t *config)
{
assert(NULL != config);
uint8_t tmp8;
/* Enable the clock. */
CLOCK_EnableClock(s_dacClocks[DAC_GetInstance(base)]);
/* Configure. */
/* DACx_C0. */
tmp8 = base->C0 & ~(DAC_C0_DACRFS_MASK | DAC_C0_LPEN_MASK);
if (kDAC_ReferenceVoltageSourceVref2 == config->referenceVoltageSource)
{
tmp8 |= DAC_C0_DACRFS_MASK;
}
if (config->enableLowPowerMode)
{
tmp8 |= DAC_C0_LPEN_MASK;
}
base->C0 = tmp8;
DAC_Enable(base, true);
}
void DAC_Deinit(DAC_Type *base)
{
DAC_Enable(base, false);
/* Disable the clock. */
CLOCK_DisableClock(s_dacClocks[DAC_GetInstance(base)]);
}
void DAC_GetDefaultConfig(dac_config_t *config)
{
assert(NULL != config);
config->referenceVoltageSource = kDAC_ReferenceVoltageSourceVref2;
config->enableLowPowerMode = false;
}
void DAC_SetBufferConfig(DAC_Type *base, const dac_buffer_config_t *config)
{
assert(NULL != config);
uint8_t tmp8;
/* DACx_C0. */
tmp8 = base->C0 & ~(DAC_C0_DACTRGSEL_MASK);
if (kDAC_BufferTriggerBySoftwareMode == config->triggerMode)
{
tmp8 |= DAC_C0_DACTRGSEL_MASK;
}
base->C0 = tmp8;
/* DACx_C1. */
tmp8 = base->C1 &
~(
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION
DAC_C1_DACBFWM_MASK |
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */
DAC_C1_DACBFMD_MASK);
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION
tmp8 |= DAC_C1_DACBFWM(config->watermark);
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */
tmp8 |= DAC_C1_DACBFMD(config->workMode);
base->C1 = tmp8;
/* DACx_C2. */
tmp8 = base->C2 & ~DAC_C2_DACBFUP_MASK;
tmp8 |= DAC_C2_DACBFUP(config->upperLimit);
base->C2 = tmp8;
}
void DAC_GetDefaultBufferConfig(dac_buffer_config_t *config)
{
assert(NULL != config);
config->triggerMode = kDAC_BufferTriggerBySoftwareMode;
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION
config->watermark = kDAC_BufferWatermark1Word;
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */
config->workMode = kDAC_BufferWorkAsNormalMode;
config->upperLimit = DAC_DATL_COUNT - 1U;
}
void DAC_SetBufferValue(DAC_Type *base, uint8_t index, uint16_t value)
{
assert(index < DAC_DATL_COUNT);
base->DAT[index].DATL = (uint8_t)(0xFFU & value); /* Low 8-bit. */
base->DAT[index].DATH = (uint8_t)((0xF00U & value) >> 8); /* High 4-bit. */
}
void DAC_SetBufferReadPointer(DAC_Type *base, uint8_t index)
{
assert(index < DAC_DATL_COUNT);
uint8_t tmp8 = base->C2 & ~DAC_C2_DACBFRP_MASK;
tmp8 |= DAC_C2_DACBFRP(index);
base->C2 = tmp8;
}
void DAC_EnableBufferInterrupts(DAC_Type *base, uint32_t mask)
{
mask &= (
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION
DAC_C0_DACBWIEN_MASK |
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION */
DAC_C0_DACBTIEN_MASK | DAC_C0_DACBBIEN_MASK);
base->C0 |= ((uint8_t)mask); /* Write 1 to enable. */
}
void DAC_DisableBufferInterrupts(DAC_Type *base, uint32_t mask)
{
mask &= (
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION
DAC_C0_DACBWIEN_MASK |
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION */
DAC_C0_DACBTIEN_MASK | DAC_C0_DACBBIEN_MASK);
base->C0 &= (uint8_t)(~((uint8_t)mask)); /* Write 0 to disable. */
}
uint32_t DAC_GetBufferStatusFlags(DAC_Type *base)
{
return (uint32_t)(base->SR & (
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION
DAC_SR_DACBFWMF_MASK |
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION */
DAC_SR_DACBFRPTF_MASK | DAC_SR_DACBFRPBF_MASK));
}
void DAC_ClearBufferStatusFlags(DAC_Type *base, uint32_t mask)
{
mask &= (
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION
DAC_SR_DACBFWMF_MASK |
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION */
DAC_SR_DACBFRPTF_MASK | DAC_SR_DACBFRPBF_MASK);
base->SR &= (uint8_t)(~((uint8_t)mask)); /* Write 0 to clear flags. */
}

View File

@ -0,0 +1,379 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_DAC_H_
#define _FSL_DAC_H_
#include "fsl_common.h"
/*!
* @addtogroup dac
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief DAC driver version 2.0.0. */
#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief DAC buffer flags.
*/
enum _dac_buffer_status_flags
{
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION
kDAC_BufferWatermarkFlag = DAC_SR_DACBFWMF_MASK, /*!< DAC Buffer Watermark Flag. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION */
kDAC_BufferReadPointerTopPositionFlag = DAC_SR_DACBFRPTF_MASK, /*!< DAC Buffer Read Pointer Top Position Flag. */
kDAC_BufferReadPointerBottomPositionFlag = DAC_SR_DACBFRPBF_MASK, /*!< DAC Buffer Read Pointer Bottom Position
Flag. */
};
/*!
* @brief DAC buffer interrupts.
*/
enum _dac_buffer_interrupt_enable
{
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION
kDAC_BufferWatermarkInterruptEnable = DAC_C0_DACBWIEN_MASK, /*!< DAC Buffer Watermark Interrupt Enable. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_DETECTION */
kDAC_BufferReadPointerTopInterruptEnable = DAC_C0_DACBTIEN_MASK, /*!< DAC Buffer Read Pointer Top Flag Interrupt
Enable. */
kDAC_BufferReadPointerBottomInterruptEnable = DAC_C0_DACBBIEN_MASK, /*!< DAC Buffer Read Pointer Bottom Flag
Interrupt Enable */
};
/*!
* @brief DAC reference voltage source.
*/
typedef enum _dac_reference_voltage_source
{
kDAC_ReferenceVoltageSourceVref1 = 0U, /*!< The DAC selects DACREF_1 as the reference voltage. */
kDAC_ReferenceVoltageSourceVref2 = 1U, /*!< The DAC selects DACREF_2 as the reference voltage. */
} dac_reference_voltage_source_t;
/*!
* @brief DAC buffer trigger mode.
*/
typedef enum _dac_buffer_trigger_mode
{
kDAC_BufferTriggerByHardwareMode = 0U, /*!< The DAC hardware trigger is selected. */
kDAC_BufferTriggerBySoftwareMode = 1U, /*!< The DAC software trigger is selected. */
} dac_buffer_trigger_mode_t;
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION
/*!
* @brief DAC buffer watermark.
*/
typedef enum _dac_buffer_watermark
{
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD
kDAC_BufferWatermark1Word = 0U, /*!< 1 word away from the upper limit. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD */
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD
kDAC_BufferWatermark2Word = 1U, /*!< 2 words away from the upper limit. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD */
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD
kDAC_BufferWatermark3Word = 2U, /*!< 3 words away from the upper limit. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD */
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD
kDAC_BufferWatermark4Word = 3U, /*!< 4 words away from the upper limit. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD */
} dac_buffer_watermark_t;
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */
/*!
* @brief DAC buffer work mode.
*/
typedef enum _dac_buffer_work_mode
{
kDAC_BufferWorkAsNormalMode = 0U, /*!< Normal mode. */
#if defined(FSL_FEATURE_DAC_HAS_BUFFER_SWING_MODE) && FSL_FEATURE_DAC_HAS_BUFFER_SWING_MODE
kDAC_BufferWorkAsSwingMode, /*!< Swing mode. */
#endif /* FSL_FEATURE_DAC_HAS_BUFFER_SWING_MODE */
kDAC_BufferWorkAsOneTimeScanMode, /*!< One-Time Scan mode. */
#if defined(FSL_FEATURE_DAC_HAS_BUFFER_FIFO_MODE) && FSL_FEATURE_DAC_HAS_BUFFER_FIFO_MODE
kDAC_BufferWorkAsFIFOMode, /*!< FIFO mode. */
#endif /* FSL_FEATURE_DAC_HAS_BUFFER_FIFO_MODE */
} dac_buffer_work_mode_t;
/*!
* @brief DAC module configuration.
*/
typedef struct _dac_config
{
dac_reference_voltage_source_t referenceVoltageSource; /*!< Select the DAC reference voltage source. */
bool enableLowPowerMode; /*!< Enable the low power mode. */
} dac_config_t;
/*!
* @brief DAC buffer configuration.
*/
typedef struct _dac_buffer_config
{
dac_buffer_trigger_mode_t triggerMode; /*!< Select the buffer's trigger mode. */
#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION) && FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION
dac_buffer_watermark_t watermark; /*!< Select the buffer's watermark. */
#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */
dac_buffer_work_mode_t workMode; /*!< Select the buffer's work mode. */
uint8_t upperLimit; /*!< Set the upper limit for buffer index.
Normally, 0-15 is available for buffer with 16 item. */
} dac_buffer_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization
* @{
*/
/*!
* @brief Initializes the DAC module.
*
* This function initializes the DAC module, including:
* - Enabling the clock for DAC module.
* - Configuring the DAC converter with a user configuration.
* - Enabling the DAC module.
*
* @param base DAC peripheral base address.
* @param config Pointer to the configuration structure. See "dac_config_t".
*/
void DAC_Init(DAC_Type *base, const dac_config_t *config);
/*!
* @brief De-initializes the DAC module.
*
* This function de-initializes the DAC module, including:
* - Disabling the DAC module.
* - Disabling the clock for the DAC module.
*
* @param base DAC peripheral base address.
*/
void DAC_Deinit(DAC_Type *base);
/*!
* @brief Initializes the DAC user configuration structure.
*
* This function initializes the user configuration structure to a default value. The default values are:
* @code
* config->referenceVoltageSource = kDAC_ReferenceVoltageSourceVref2;
* config->enableLowPowerMode = false;
* @endcode
* @param config Pointer to the configuration structure. See "dac_config_t".
*/
void DAC_GetDefaultConfig(dac_config_t *config);
/*!
* @brief Enables the DAC module.
*
* @param base DAC peripheral base address.
* @param enable Enables the feature or not.
*/
static inline void DAC_Enable(DAC_Type *base, bool enable)
{
if (enable)
{
base->C0 |= DAC_C0_DACEN_MASK;
}
else
{
base->C0 &= ~DAC_C0_DACEN_MASK;
}
}
/* @} */
/*!
* @name Buffer
* @{
*/
/*!
* @brief Enables the DAC buffer.
*
* @param base DAC peripheral base address.
* @param enable Enables the feature or not.
*/
static inline void DAC_EnableBuffer(DAC_Type *base, bool enable)
{
if (enable)
{
base->C1 |= DAC_C1_DACBFEN_MASK;
}
else
{
base->C1 &= ~DAC_C1_DACBFEN_MASK;
}
}
/*!
* @brief Configures the CMP buffer.
*
* @param base DAC peripheral base address.
* @param config Pointer to the configuration structure. See "dac_buffer_config_t".
*/
void DAC_SetBufferConfig(DAC_Type *base, const dac_buffer_config_t *config);
/*!
* @brief Initializes the DAC buffer configuration structure.
*
* This function initializes the DAC buffer configuration structure to a default value. The default values are:
* @code
* config->triggerMode = kDAC_BufferTriggerBySoftwareMode;
* config->watermark = kDAC_BufferWatermark1Word;
* config->workMode = kDAC_BufferWorkAsNormalMode;
* config->upperLimit = DAC_DATL_COUNT - 1U;
* @endcode
* @param config Pointer to the configuration structure. See "dac_buffer_config_t".
*/
void DAC_GetDefaultBufferConfig(dac_buffer_config_t *config);
/*!
* @brief Enables the DMA for DAC buffer.
*
* @param base DAC peripheral base address.
* @param enable Enables the feature or not.
*/
static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable)
{
if (enable)
{
base->C1 |= DAC_C1_DMAEN_MASK;
}
else
{
base->C1 &= ~DAC_C1_DMAEN_MASK;
}
}
/*!
* @brief Sets the value for items in the buffer.
*
* @param base DAC peripheral base address.
* @param index Setting index for items in the buffer. The available index should not exceed the size of the DAC buffer.
* @param value Setting value for items in the buffer. 12-bits are available.
*/
void DAC_SetBufferValue(DAC_Type *base, uint8_t index, uint16_t value);
/*!
* @brief Triggers the buffer by software and updates the read pointer of the DAC buffer.
*
* This function triggers the function by software. The read pointer of the DAC buffer is updated with one step
* after this function is called. Changing the read pointer depends on the buffer's work mode.
*
* @param base DAC peripheral base address.
*/
static inline void DAC_DoSoftwareTriggerBuffer(DAC_Type *base)
{
base->C0 |= DAC_C0_DACSWTRG_MASK;
}
/*!
* @brief Gets the current read pointer of the DAC buffer.
*
* This function gets the current read pointer of the DAC buffer.
* The current output value depends on the item indexed by the read pointer. It is updated
* by software trigger or hardware trigger.
*
* @param base DAC peripheral base address.
*
* @return Current read pointer of DAC buffer.
*/
static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base)
{
return ((base->C2 & DAC_C2_DACBFRP_MASK) >> DAC_C2_DACBFRP_SHIFT);
}
/*!
* @brief Sets the current read pointer of the DAC buffer.
*
* This function sets the current read pointer of the DAC buffer.
* The current output value depends on the item indexed by the read pointer. It is updated by
* software trigger or hardware trigger. After the read pointer changes, the DAC output value also changes.
*
* @param base DAC peripheral base address.
* @param index Setting index value for the pointer.
*/
void DAC_SetBufferReadPointer(DAC_Type *base, uint8_t index);
/*!
* @brief Enables interrupts for the DAC buffer.
*
* @param base DAC peripheral base address.
* @param mask Mask value for interrupts. See "_dac_buffer_interrupt_enable".
*/
void DAC_EnableBufferInterrupts(DAC_Type *base, uint32_t mask);
/*!
* @brief Disables interrupts for the DAC buffer.
*
* @param base DAC peripheral base address.
* @param mask Mask value for interrupts. See "_dac_buffer_interrupt_enable".
*/
void DAC_DisableBufferInterrupts(DAC_Type *base, uint32_t mask);
/*!
* @brief Gets the flags of events for the DAC buffer.
*
* @param base DAC peripheral base address.
*
* @return Mask value for the asserted flags. See "_dac_buffer_status_flags".
*/
uint32_t DAC_GetBufferStatusFlags(DAC_Type *base);
/*!
* @brief Clears the flags of events for the DAC buffer.
*
* @param base DAC peripheral base address.
* @param mask Mask value for flags. See "_dac_buffer_status_flags_t".
*/
void DAC_ClearBufferStatusFlags(DAC_Type *base, uint32_t mask);
/* @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_DAC_H_ */

View File

@ -0,0 +1,306 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_dma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DMA.
*
* @param base DMA peripheral base address.
*/
static uint32_t DMA_GetInstance(DMA_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Array to map DMA instance number to base pointer. */
static DMA_Type *const s_dmaBases[] = DMA_BASE_PTRS;
/*! @brief Array to map DMA instance number to clock name. */
static const clock_ip_name_t s_dmaClockName[] = DMA_CLOCKS;
/*! @brief Array to map DMA instance number to IRQ number. */
static const IRQn_Type s_dmaIRQNumber[] = DMA_CHN_IRQS;
/*! @brief Pointers to transfer handle for each DMA channel. */
static dma_handle_t *s_DMAHandle[FSL_FEATURE_DMAMUX_MODULE_CHANNEL * FSL_FEATURE_SOC_DMA_COUNT];
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t DMA_GetInstance(DMA_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_DMA_COUNT; instance++)
{
if (s_dmaBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_DMA_COUNT);
return instance;
}
void DMA_Init(DMA_Type *base)
{
CLOCK_EnableClock(s_dmaClockName[DMA_GetInstance(base)]);
}
void DMA_Deinit(DMA_Type *base)
{
CLOCK_DisableClock(s_dmaClockName[DMA_GetInstance(base)]);
}
void DMA_ResetChannel(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
/* clear all status bit */
base->DMA[channel].DSR_BCR |= DMA_DSR_BCR_DONE(true);
/* clear all registers */
base->DMA[channel].SAR = 0;
base->DMA[channel].DAR = 0;
base->DMA[channel].DSR_BCR = 0;
/* enable cycle steal and enable auto disable channel request */
base->DMA[channel].DCR = DMA_DCR_D_REQ(true) | DMA_DCR_CS(true);
}
void DMA_SetTransferConfig(DMA_Type *base, uint32_t channel, const dma_transfer_config_t *config)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
assert(config != NULL);
uint32_t tmpreg;
/* Set source address */
base->DMA[channel].SAR = config->srcAddr;
/* Set destination address */
base->DMA[channel].DAR = config->destAddr;
/* Set transfer bytes */
base->DMA[channel].DSR_BCR = DMA_DSR_BCR_BCR(config->transferSize);
/* Set DMA Control Register */
tmpreg = base->DMA[channel].DCR;
tmpreg &= ~(DMA_DCR_DSIZE_MASK | DMA_DCR_DINC_MASK | DMA_DCR_SSIZE_MASK | DMA_DCR_SINC_MASK);
tmpreg |= (DMA_DCR_DSIZE(config->destSize) | DMA_DCR_DINC(config->enableDestIncrement) |
DMA_DCR_SSIZE(config->srcSize) | DMA_DCR_SINC(config->enableSrcIncrement));
base->DMA[channel].DCR = tmpreg;
}
void DMA_SetChannelLinkConfig(DMA_Type *base, uint32_t channel, const dma_channel_link_config_t *config)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
assert(config != NULL);
uint32_t tmpreg;
tmpreg = base->DMA[channel].DCR;
tmpreg &= ~(DMA_DCR_LINKCC_MASK | DMA_DCR_LCH1_MASK | DMA_DCR_LCH2_MASK);
tmpreg |= (DMA_DCR_LINKCC(config->linkType) | DMA_DCR_LCH1(config->channel1) | DMA_DCR_LCH2(config->channel2));
base->DMA[channel].DCR = tmpreg;
}
void DMA_SetModulo(DMA_Type *base, uint32_t channel, dma_modulo_t srcModulo, dma_modulo_t destModulo)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
uint32_t tmpreg;
tmpreg = base->DMA[channel].DCR;
tmpreg &= ~(DMA_DCR_SMOD_MASK | DMA_DCR_DMOD_MASK);
tmpreg |= (DMA_DCR_SMOD(srcModulo) | DMA_DCR_DMOD(destModulo));
base->DMA[channel].DCR = tmpreg;
}
void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel)
{
assert(handle != NULL);
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
uint32_t dmaInstance;
uint32_t channelIndex;
handle->base = base;
handle->channel = channel;
/* Get the DMA instance number */
dmaInstance = DMA_GetInstance(base);
channelIndex = (dmaInstance * FSL_FEATURE_DMAMUX_MODULE_CHANNEL) + channel;
/* Store handle */
s_DMAHandle[channelIndex] = handle;
/* Enable NVIC interrupt. */
EnableIRQ(s_dmaIRQNumber[channelIndex]);
}
void DMA_PrepareTransfer(dma_transfer_config_t *config,
void *srcAddr,
uint32_t srcWidth,
void *destAddr,
uint32_t destWidth,
uint32_t transferBytes,
dma_transfer_type_t type)
{
assert(config != NULL);
assert(srcAddr != NULL);
assert(destAddr != NULL);
assert(srcWidth == 1U || srcWidth == 2U || srcWidth == 4U);
assert(destWidth == 1U || destWidth == 2U || destWidth == 4U);
config->srcAddr = (uint32_t)srcAddr;
config->destAddr = (uint32_t)destAddr;
config->transferSize = transferBytes;
switch (srcWidth)
{
case 1U:
config->srcSize = kDMA_Transfersize8bits;
break;
case 2U:
config->srcSize = kDMA_Transfersize16bits;
break;
case 4U:
config->srcSize = kDMA_Transfersize32bits;
break;
default:
break;
}
switch (destWidth)
{
case 1U:
config->destSize = kDMA_Transfersize8bits;
break;
case 2U:
config->destSize = kDMA_Transfersize16bits;
break;
case 4U:
config->destSize = kDMA_Transfersize32bits;
break;
default:
break;
}
switch (type)
{
case kDMA_MemoryToMemory:
config->enableSrcIncrement = true;
config->enableDestIncrement = true;
break;
case kDMA_PeripheralToMemory:
config->enableSrcIncrement = false;
config->enableDestIncrement = true;
break;
case kDMA_MemoryToPeripheral:
config->enableSrcIncrement = true;
config->enableDestIncrement = false;
break;
default:
break;
}
}
void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData)
{
assert(handle != NULL);
handle->callback = callback;
handle->userData = userData;
}
status_t DMA_SubmitTransfer(dma_handle_t *handle, const dma_transfer_config_t *config, uint32_t options)
{
assert(handle != NULL);
assert(config != NULL);
/* Check if DMA is busy */
if (handle->base->DMA[handle->channel].DSR_BCR & DMA_DSR_BCR_BSY_MASK)
{
return kStatus_DMA_Busy;
}
DMA_ResetChannel(handle->base, handle->channel);
DMA_SetTransferConfig(handle->base, handle->channel, config);
if (options & kDMA_EnableInterrupt)
{
DMA_EnableInterrupts(handle->base, handle->channel);
}
return kStatus_Success;
}
void DMA_AbortTransfer(dma_handle_t *handle)
{
assert(handle != NULL);
handle->base->DMA[handle->channel].DCR &= ~DMA_DCR_ERQ_MASK;
/* clear all status bit */
handle->base->DMA[handle->channel].DSR_BCR |= DMA_DSR_BCR_DONE(true);
}
void DMA_HandleIRQ(dma_handle_t *handle)
{
assert(handle != NULL);
/* Clear interrupt pending bit */
DMA_ClearChannelStatusFlags(handle->base, handle->channel, kDMA_TransactionsDoneFlag);
if (handle->callback)
{
(handle->callback)(handle, handle->userData);
}
}
#if defined(FSL_FEATURE_DMAMUX_MODULE_CHANNEL) && (FSL_FEATURE_DMAMUX_MODULE_CHANNEL == 4U)
void DMA0_DriverIRQHandler(void)
{
DMA_HandleIRQ(s_DMAHandle[0]);
}
void DMA1_DriverIRQHandler(void)
{
DMA_HandleIRQ(s_DMAHandle[1]);
}
void DMA2_DriverIRQHandler(void)
{
DMA_HandleIRQ(s_DMAHandle[2]);
}
void DMA3_DriverIRQHandler(void)
{
DMA_HandleIRQ(s_DMAHandle[3]);
}
#endif /* FSL_FEATURE_DMAMUX_MODULE_CHANNEL */

View File

@ -0,0 +1,609 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_DMA_H_
#define _FSL_DMA_H_
#include "fsl_common.h"
/*!
* @addtogroup dma_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief DMA driver version 2.0.0. */
#define FSL_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*! @brief status flag for the DMA driver. */
enum _dma_channel_status_flags
{
kDMA_TransactionsBCRFlag = DMA_DSR_BCR_BCR_MASK, /*!< Contains the number of bytes yet to be
transferred for a given block */
kDMA_TransactionsDoneFlag = DMA_DSR_BCR_DONE_MASK, /*!< Transactions Done */
kDMA_TransactionsBusyFlag = DMA_DSR_BCR_BSY_MASK, /*!< Transactions Busy */
kDMA_TransactionsRequestFlag = DMA_DSR_BCR_REQ_MASK, /*!< Transactions Request */
kDMA_BusErrorOnDestinationFlag = DMA_DSR_BCR_BED_MASK, /*!< Bus Error on Destination */
kDMA_BusErrorOnSourceFlag = DMA_DSR_BCR_BES_MASK, /*!< Bus Error on Source */
kDMA_ConfigurationErrorFlag = DMA_DSR_BCR_CE_MASK, /*!< Configuration Error */
};
/*! @brief DMA transfer size type*/
typedef enum _dma_transfer_size
{
kDMA_Transfersize32bits = 0x0U, /*!< 32 bits are transferred for every read/write */
kDMA_Transfersize8bits, /*!< 8 bits are transferred for every read/write */
kDMA_Transfersize16bits, /*!< 16b its are transferred for every read/write */
} dma_transfer_size_t;
/*! @brief Configuration type for the DMA modulo */
typedef enum _dma_modulo
{
kDMA_ModuloDisable = 0x0U, /*!< Buffer disabled */
kDMA_Modulo16Bytes, /*!< Circular buffer size is 16 bytes. */
kDMA_Modulo32Bytes, /*!< Circular buffer size is 32 bytes. */
kDMA_Modulo64Bytes, /*!< Circular buffer size is 64 bytes. */
kDMA_Modulo128Bytes, /*!< Circular buffer size is 128 bytes. */
kDMA_Modulo256Bytes, /*!< Circular buffer size is 256 bytes. */
kDMA_Modulo512Bytes, /*!< Circular buffer size is 512 bytes. */
kDMA_Modulo1KBytes, /*!< Circular buffer size is 1 KB. */
kDMA_Modulo2KBytes, /*!< Circular buffer size is 2 KB. */
kDMA_Modulo4KBytes, /*!< Circular buffer size is 4 KB. */
kDMA_Modulo8KBytes, /*!< Circular buffer size is 8 KB. */
kDMA_Modulo16KBytes, /*!< Circular buffer size is 16 KB. */
kDMA_Modulo32KBytes, /*!< Circular buffer size is 32 KB. */
kDMA_Modulo64KBytes, /*!< Circular buffer size is 64 KB. */
kDMA_Modulo128KBytes, /*!< Circular buffer size is 128 KB. */
kDMA_Modulo256KBytes, /*!< Circular buffer size is 256 KB. */
} dma_modulo_t;
/*! @brief DMA channel link type */
typedef enum _dma_channel_link_type
{
kDMA_ChannelLinkDisable = 0x0U, /*!< No channel link. */
kDMA_ChannelLinkChannel1AndChannel2, /*!< Perform a link to channel LCH1 after each cycle-steal transfer.
followed by a link to LCH2 after the BCR decrements to 0. */
kDMA_ChannelLinkChannel1, /*!< Perform a link to LCH1 after each cycle-steal transfer. */
kDMA_ChannelLinkChannel1AfterBCR0, /*!< Perform a link to LCH1 after the BCR decrements. */
} dma_channel_link_type_t;
/*! @brief DMA transfer type */
typedef enum _dma_transfer_type
{
kDMA_MemoryToMemory = 0x0U, /*!< Memory to Memory transfer. */
kDMA_PeripheralToMemory, /*!< Peripheral to Memory transfer. */
kDMA_MemoryToPeripheral, /*!< Memory to Peripheral transfer. */
} dma_transfer_type_t;
/*! @brief DMA transfer options */
typedef enum _dma_transfer_options
{
kDMA_NoOptions = 0x0U, /*!< Transfer without options. */
kDMA_EnableInterrupt, /*!< Enable interrupt while transfer complete. */
} dma_transfer_options_t;
/*! @brief DMA transfer status */
enum _dma_transfer_status
{
kStatus_DMA_Busy = MAKE_STATUS(kStatusGroup_DMA, 0),
};
/*! @brief DMA transfer configuration structure */
typedef struct _dma_transfer_config
{
uint32_t srcAddr; /*!< DMA transfer source address. */
uint32_t destAddr; /*!< DMA destination address.*/
bool enableSrcIncrement; /*!< Source address increase after each transfer. */
dma_transfer_size_t srcSize; /*!< Source transfer size unit. */
bool enableDestIncrement; /*!< Destination address increase after each transfer. */
dma_transfer_size_t destSize; /*!< Destination transfer unit.*/
uint32_t transferSize; /*!< The number of bytes to be transferred. */
} dma_transfer_config_t;
/*! @brief DMA transfer configuration structure */
typedef struct _dma_channel_link_config
{
dma_channel_link_type_t linkType; /*!< Channel link type. */
uint32_t channel1; /*!< The index of channel 1. */
uint32_t channel2; /*!< The index of channel 2. */
} dma_channel_link_config_t;
struct _dma_handle;
/*! @brief Callback function prototype for the DMA driver. */
typedef void (*dma_callback)(struct _dma_handle *handle, void *userData);
/*! @brief DMA DMA handle structure */
typedef struct _dma_handle
{
DMA_Type *base; /*!< DMA peripheral address. */
uint8_t channel; /*!< DMA channel used. */
dma_callback callback; /*!< DMA callback function.*/
void *userData; /*!< Callback parameter. */
} dma_handle_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name DMA Initialization and De-initialization
* @{
*/
/*!
* @brief Initializes the DMA peripheral.
*
* This function ungates the DMA clock.
*
* @param base DMA peripheral base address.
*/
void DMA_Init(DMA_Type *base);
/*!
* @brief Deinitializes the DMA peripheral.
*
* This function gates the DMA clock.
*
* @param base DMA peripheral base address.
*/
void DMA_Deinit(DMA_Type *base);
/* @} */
/*!
* @name DMA Channel Operation
* @{
*/
/*!
* @brief Resets the DMA channel.
*
* Sets all register values to reset values and enables
* the cycle steal and auto stop channel request features.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
*/
void DMA_ResetChannel(DMA_Type *base, uint32_t channel);
/*!
* @brief Configures the DMA transfer attribute.
*
* This function configures the transfer attribute including the source address,
* destination address, transfer size, and so on.
* This example shows how to set up the the dma_transfer_config_t
* parameters and how to call the DMA_ConfigBasicTransfer function.
* @code
* dma_transfer_config_t transferConfig;
* memset(&transferConfig, 0, sizeof(transferConfig));
* transferConfig.srcAddr = (uint32_t)srcAddr;
* transferConfig.destAddr = (uint32_t)destAddr;
* transferConfig.enbaleSrcIncrement = true;
* transferConfig.enableDestIncrement = true;
* transferConfig.srcSize = kDMA_Transfersize32bits;
* transferConfig.destSize = kDMA_Transfersize32bits;
* transferConfig.transferSize = sizeof(uint32_t) * BUFF_LENGTH;
* DMA_SetTransferConfig(DMA0, 0, &transferConfig);
* @endcode
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param config Pointer to the DMA transfer configuration structure.
*/
void DMA_SetTransferConfig(DMA_Type *base, uint32_t channel, const dma_transfer_config_t *config);
/*!
* @brief Configures the DMA channel link feature.
*
* This function allows DMA channels to have their transfers linked. The current DMA channel
* triggers a DMA request to the linked channels (LCH1 or LCH2) depending on the channel link
* type.
* Perform a link to channel LCH1 after each cycle-steal transfer followed by a link to LCH2
* after the BCR decrements to 0 if the type is kDMA_ChannelLinkChannel1AndChannel2.
* Perform a link to LCH1 after each cycle-steal transfer if the type is kDMA_ChannelLinkChannel1.
* Perform a link to LCH1 after the BCR decrements to 0 if the type is kDMA_ChannelLinkChannel1AfterBCR0.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param config Pointer to the channel link configuration structure.
*/
void DMA_SetChannelLinkConfig(DMA_Type *base, uint32_t channel, const dma_channel_link_config_t *config);
/*!
* @brief Sets the DMA source address for the DMA transfer.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param srcAddr DMA source address.
*/
static inline void DMA_SetSourceAddress(DMA_Type *base, uint32_t channel, uint32_t srcAddr)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].SAR = srcAddr;
}
/*!
* @brief Sets the DMA destination address for the DMA transfer.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param destAddr DMA destination address.
*/
static inline void DMA_SetDestinationAddress(DMA_Type *base, uint32_t channel, uint32_t destAddr)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DAR = destAddr;
}
/*!
* @brief Sets the DMA transfer size for the DMA transfer.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param size The number of bytes to be transferred.
*/
static inline void DMA_SetTransferSize(DMA_Type *base, uint32_t channel, uint32_t size)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DSR_BCR = DMA_DSR_BCR_BCR(size);
}
/*!
* @brief Sets the DMA modulo for the DMA transfer.
*
* This function defines a specific address range specified to be the value after (SAR + SSIZE)/(DAR + DSIZE)
* calculation is performed or the original register value. It provides the ability to implement a circular
* data queue easily.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param srcModulo source address modulo.
* @param destModulo destination address modulo.
*/
void DMA_SetModulo(DMA_Type *base, uint32_t channel, dma_modulo_t srcModulo, dma_modulo_t destModulo);
/*!
* @brief Enables the DMA cycle steal for the DMA transfer.
*
* If the cycle steal feature is enabled (true), the DMA controller forces a single read/write transfer per request,
* or it continuously makes read/write transfers until the BCR decrements to 0.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param enable The command for enable (true) or disable (false).
*/
static inline void DMA_EnableCycleSteal(DMA_Type *base, uint32_t channel, bool enable)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR = (base->DMA[channel].DCR & (~DMA_DCR_CS_MASK)) | DMA_DCR_CS(enable);
}
/*!
* @brief Enables the DMA auto align for the DMA transfer.
*
* If the auto align feature is enabled (true), the appropriate address register increments,
* regardless of DINC or SINC.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param enable The command for enable (true) or disable (false).
*/
static inline void DMA_EnableAutoAlign(DMA_Type *base, uint32_t channel, bool enable)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR = (base->DMA[channel].DCR & (~DMA_DCR_AA_MASK)) | DMA_DCR_AA(enable);
}
/*!
* @brief Enables the DMA async request for the DMA transfer.
*
* If the async request feature is enabled (true), the DMA supports asynchronous DREQs
* while the MCU is in stop mode.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param enable The command for enable (true) or disable (false).
*/
static inline void DMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR = (base->DMA[channel].DCR & (~DMA_DCR_EADREQ_MASK)) | DMA_DCR_EADREQ(enable);
}
/*!
* @brief Enables an interrupt for the DMA transfer.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
*/
static inline void DMA_EnableInterrupts(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR |= DMA_DCR_EINT(true);
}
/*!
* @brief Disables an interrupt for the DMA transfer.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
*/
static inline void DMA_DisableInterrupts(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR &= ~DMA_DCR_EINT_MASK;
}
/* @} */
/*!
* @name DMA Channel Transfer Operation
* @{
*/
/*!
* @brief Enables the DMA hardware channel request.
*
* @param base DMA peripheral base address.
* @param channel The DMA channel number.
*/
static inline void DMA_EnableChannelRequest(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR |= DMA_DCR_ERQ_MASK;
}
/*!
* @brief Disables the DMA hardware channel request.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
*/
static inline void DMA_DisableChannelRequest(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR &= ~DMA_DCR_ERQ_MASK;
}
/*!
* @brief Starts the DMA transfer with a software trigger.
*
* This function starts only one read/write iteration.
*
* @param base DMA peripheral base address.
* @param channel The DMA channel number.
*/
static inline void DMA_TriggerChannelStart(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->DMA[channel].DCR |= DMA_DCR_START_MASK;
}
/* @} */
/*!
* @name DMA Channel Status Operation
* @{
*/
/*!
* @brief Gets the remaining bytes of the current DMA transfer.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @return The number of bytes which have not been transferred yet.
*/
static inline uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
return (base->DMA[channel].DSR_BCR & DMA_DSR_BCR_BCR_MASK) >> DMA_DSR_BCR_BCR_SHIFT;
}
/*!
* @brief Gets the DMA channel status flags.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @return The mask of the channel status. Use the _dma_channel_status_flags
* type to decode the return 32 bit variables.
*/
static inline uint32_t DMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
return base->DMA[channel].DSR_BCR;
}
/*!
* @brief Clears the DMA channel status flags.
*
* @param base DMA peripheral base address.
* @param channel DMA channel number.
* @param mask The mask of the channel status to be cleared. Use
* the defined _dma_channel_status_flags type.
*/
static inline void DMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
if (mask != 0U)
{
base->DMA[channel].DSR_BCR |= DMA_DSR_BCR_DONE(true);
}
}
/* @} */
/*!
* @name DMA Channel Transactional Operation
* @{
*/
/*!
* @brief Creates the DMA handle.
*
* This function is called first if using the transactional API for the DMA. This function
* initializes the internal state of the DMA handle.
*
* @param handle DMA handle pointer. The DMA handle stores callback function and
* parameters.
* @param base DMA peripheral base address.
* @param channel DMA channel number.
*/
void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel);
/*!
* @brief Sets the DMA callback function.
*
* This callback is called in the DMA IRQ handler. Use the callback to do something
* after the current transfer complete.
*
* @param handle DMA handle pointer.
* @param callback DMA callback function pointer.
* @param userData Parameter for callback function. If it is not needed, just set to NULL.
*/
void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData);
/*!
* @brief Prepares the DMA transfer configuration structure.
*
* This function prepares the transfer configuration structure according to the user input.
*
* @param config Pointer to the user configuration structure of type dma_transfer_config_t.
* @param srcAddr DMA transfer source address.
* @param srcWidth DMA transfer source address width (byte).
* @param destAddr DMA transfer destination address.
* @param destWidth DMA transfer destination address width (byte).
* @param transferBytes DMA transfer bytes to be transferred.
* @param type DMA transfer type.
*/
void DMA_PrepareTransfer(dma_transfer_config_t *config,
void *srcAddr,
uint32_t srcWidth,
void *destAddr,
uint32_t destWidth,
uint32_t transferBytes,
dma_transfer_type_t type);
/*!
* @brief Submits the DMA transfer request.
*
* This function submits the DMA transfer request according to the transfer configuration structure.
*
* @param handle DMA handle pointer.
* @param config Pointer to DMA transfer configuration structure.
* @param options Additional configurations for transfer. Use
* the defined dma_transfer_options_t type.
* @retval kStatus_DMA_Success It indicates that the DMA submit transfer request succeeded.
* @retval kStatus_DMA_Busy It indicates that the DMA is busy. Submit transfer request is not allowed.
* @note This function can't process multi transfer request.
*/
status_t DMA_SubmitTransfer(dma_handle_t *handle, const dma_transfer_config_t *config, uint32_t options);
/*!
* @brief DMA starts a transfer.
*
* This function enables the channel request. Call this function
* after submitting a transfer request.
*
* @param handle DMA handle pointer.
* @retval kStatus_DMA_Success It indicates that the DMA start transfer succeed.
* @retval kStatus_DMA_Busy It indicates that the DMA has started a transfer.
*/
static inline void DMA_StartTransfer(dma_handle_t *handle)
{
assert(handle != NULL);
handle->base->DMA[handle->channel].DCR |= DMA_DCR_ERQ_MASK;
}
/*!
* @brief DMA stops a transfer.
*
* This function disables the channel request to stop a DMA transfer.
* The transfer can be resumed by calling the DMA_StartTransfer.
*
* @param handle DMA handle pointer.
*/
static inline void DMA_StopTransfer(dma_handle_t *handle)
{
assert(handle != NULL);
handle->base->DMA[handle->channel].DCR &= ~DMA_DCR_ERQ_MASK;
}
/*!
* @brief DMA aborts a transfer.
*
* This function disables the channel request and clears all status bits.
* Submit another transfer after calling this API.
*
* @param handle DMA handle pointer.
*/
void DMA_AbortTransfer(dma_handle_t *handle);
/*!
* @brief DMA IRQ handler for current transfer complete.
*
* This function clears the channel interrupt flag and calls
* the callback function if it is not NULL.
*
* @param handle DMA handle pointer.
*/
void DMA_HandleIRQ(dma_handle_t *handle);
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/* @}*/
#endif /* _FSL_DMA_H_ */

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_dmamux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DMAMUX.
*
* @param base DMAMUX peripheral base address.
*/
static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Array to map DMAMUX instance number to base pointer. */
static DMAMUX_Type *const s_dmamuxBases[] = DMAMUX_BASE_PTRS;
/*! @brief Array to map DMAMUX instance number to clock name. */
static const clock_ip_name_t s_dmamuxClockName[] = DMAMUX_CLOCKS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_DMAMUX_COUNT; instance++)
{
if (s_dmamuxBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_DMAMUX_COUNT);
return instance;
}
void DMAMUX_Init(DMAMUX_Type *base)
{
CLOCK_EnableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]);
}
void DMAMUX_Deinit(DMAMUX_Type *base)
{
CLOCK_DisableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]);
}

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_DMAMUX_H_
#define _FSL_DMAMUX_H_
#include "fsl_common.h"
/*!
* @addtogroup dmamux
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief DMAMUX driver version 2.0.0. */
#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name DMAMUX Initialize and De-initialize
* @{
*/
/*!
* @brief Initializes DMAMUX peripheral.
*
* This function ungate the DMAMUX clock.
*
* @param base DMAMUX peripheral base address.
*
*/
void DMAMUX_Init(DMAMUX_Type *base);
/*!
* @brief Deinitializes DMAMUX peripheral.
*
* This function gate the DMAMUX clock.
*
* @param base DMAMUX peripheral base address.
*/
void DMAMUX_Deinit(DMAMUX_Type *base);
/* @} */
/*!
* @name DMAMUX Channel Operation
* @{
*/
/*!
* @brief Enable DMAMUX channel.
*
* This function enable DMAMUX channel to work.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] |= DMAMUX_CHCFG_ENBL_MASK;
}
/*!
* @brief Disable DMAMUX channel.
*
* This function disable DMAMUX channel.
*
* @note User must disable DMAMUX channel before configure it.
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_DisableChannel(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] &= ~DMAMUX_CHCFG_ENBL_MASK;
}
/*!
* @brief Configure DMAMUX channel source.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
* @param source Channel source which is used to trigger DMA transfer.
*/
static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint8_t source)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] = ((base->CHCFG[channel] & ~DMAMUX_CHCFG_SOURCE_MASK) | DMAMUX_CHCFG_SOURCE(source));
}
#if defined(FSL_FEATURE_DMAMUX_HAS_TRIG) && FSL_FEATURE_DMAMUX_HAS_TRIG > 0U
/*!
* @brief Enable DMAMUX period trigger.
*
* This function enable DMAMUX period trigger feature.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_EnablePeriodTrigger(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] |= DMAMUX_CHCFG_TRIG_MASK;
}
/*!
* @brief Disable DMAMUX period trigger.
*
* This function disable DMAMUX period trigger.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_DisablePeriodTrigger(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] &= ~DMAMUX_CHCFG_TRIG_MASK;
}
#endif /* FSL_FEATURE_DMAMUX_HAS_TRIG */
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/* @} */
#endif /* _FSL_DMAMUX_H_ */

View File

@ -0,0 +1,262 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*< @brief user configurable flexio handle count. */
#define FLEXIO_HANDLE_COUNT 2
/*******************************************************************************
* Variables
******************************************************************************/
/*< @brief pointer to array of FLEXIO handle. */
static void *s_flexioHandle[FLEXIO_HANDLE_COUNT];
/*< @brief pointer to array of FLEXIO IP types. */
static void *s_flexioType[FLEXIO_HANDLE_COUNT];
/*< @brief pointer to array of FLEXIO Isr. */
static flexio_isr_t s_flexioIsr[FLEXIO_HANDLE_COUNT];
/*******************************************************************************
* Codes
******************************************************************************/
void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig)
{
uint32_t ctrlReg = 0;
CLOCK_EnableClock(kCLOCK_Flexio0);
FLEXIO_Reset(base);
ctrlReg = base->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DOZEN(userConfig->enableInDoze) | FLEXIO_CTRL_DBGE(userConfig->enableInDebug) |
FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) | FLEXIO_CTRL_FLEXEN(userConfig->enableFlexio));
base->CTRL = ctrlReg;
}
void FLEXIO_Deinit(FLEXIO_Type *base)
{
FLEXIO_Enable(base, false);
CLOCK_DisableClock(kCLOCK_Flexio0);
}
void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig)
{
assert(userConfig);
userConfig->enableFlexio = true;
userConfig->enableInDoze = false;
userConfig->enableInDebug = true;
userConfig->enableFastAccess = false;
}
void FLEXIO_Reset(FLEXIO_Type *base)
{
/*do software reset, software reset operation affect all other FLEXIO registers except CTRL*/
base->CTRL |= FLEXIO_CTRL_SWRST_MASK;
base->CTRL = 0;
}
uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index)
{
assert(index < FLEXIO_SHIFTBUF_COUNT);
uint32_t address = 0;
switch (type)
{
case kFLEXIO_ShifterBuffer:
address = (uint32_t) & (base->SHIFTBUF[index]);
break;
case kFLEXIO_ShifterBufferBitSwapped:
address = (uint32_t) & (base->SHIFTBUFBIS[index]);
break;
case kFLEXIO_ShifterBufferByteSwapped:
address = (uint32_t) & (base->SHIFTBUFBYS[index]);
break;
case kFLEXIO_ShifterBufferBitByteSwapped:
address = (uint32_t) & (base->SHIFTBUFBBS[index]);
break;
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
case kFLEXIO_ShifterBufferNibbleByteSwapped:
address = (uint32_t) & (base->SHIFTBUFNBS[index]);
break;
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
case kFLEXIO_ShifterBufferHalfWordSwapped:
address = (uint32_t) & (base->SHIFTBUFHWS[index]);
break;
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
case kFLEXIO_ShifterBufferNibbleSwapped:
address = (uint32_t) & (base->SHIFTBUFNIS[index]);
break;
#endif
default:
break;
}
return address;
}
void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig)
{
base->SHIFTCFG[index] = FLEXIO_SHIFTCFG_INSRC(shifterConfig->inputSource)
#if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
| FLEXIO_SHIFTCFG_PWIDTH(shifterConfig->parallelWidth)
#endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
| FLEXIO_SHIFTCFG_SSTOP(shifterConfig->shifterStop) |
FLEXIO_SHIFTCFG_SSTART(shifterConfig->shifterStart);
base->SHIFTCTL[index] =
FLEXIO_SHIFTCTL_TIMSEL(shifterConfig->timerSelect) | FLEXIO_SHIFTCTL_TIMPOL(shifterConfig->timerPolarity) |
FLEXIO_SHIFTCTL_PINCFG(shifterConfig->pinConfig) | FLEXIO_SHIFTCTL_PINSEL(shifterConfig->pinSelect) |
FLEXIO_SHIFTCTL_PINPOL(shifterConfig->pinPolarity) | FLEXIO_SHIFTCTL_SMOD(shifterConfig->shifterMode);
}
void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig)
{
base->TIMCFG[index] =
FLEXIO_TIMCFG_TIMOUT(timerConfig->timerOutput) | FLEXIO_TIMCFG_TIMDEC(timerConfig->timerDecrement) |
FLEXIO_TIMCFG_TIMRST(timerConfig->timerReset) | FLEXIO_TIMCFG_TIMDIS(timerConfig->timerDisable) |
FLEXIO_TIMCFG_TIMENA(timerConfig->timerEnable) | FLEXIO_TIMCFG_TSTOP(timerConfig->timerStop) |
FLEXIO_TIMCFG_TSTART(timerConfig->timerStart);
base->TIMCMP[index] = FLEXIO_TIMCMP_CMP(timerConfig->timerCompare);
base->TIMCTL[index] = FLEXIO_TIMCTL_TRGSEL(timerConfig->triggerSelect) |
FLEXIO_TIMCTL_TRGPOL(timerConfig->triggerPolarity) |
FLEXIO_TIMCTL_TRGSRC(timerConfig->triggerSource) |
FLEXIO_TIMCTL_PINCFG(timerConfig->pinConfig) | FLEXIO_TIMCTL_PINSEL(timerConfig->pinSelect) |
FLEXIO_TIMCTL_PINPOL(timerConfig->pinPolarity) | FLEXIO_TIMCTL_TIMOD(timerConfig->timerMode);
}
status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr)
{
assert(base);
assert(handle);
assert(isr);
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0; index < FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioHandle[index] == NULL)
{
/* Register FLEXIO simulated driver base, handle and isr. */
s_flexioType[index] = base;
s_flexioHandle[index] = handle;
s_flexioIsr[index] = isr;
break;
}
}
if (index == FLEXIO_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
else
{
return kStatus_Success;
}
}
status_t FLEXIO_UnregisterHandleIRQ(void *base)
{
assert(base);
uint8_t index = 0;
/* Find the index from base address mappings. */
for (index = 0; index < FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioType[index] == base)
{
/* Unregister FLEXIO simulated driver handle and isr. */
s_flexioType[index] = NULL;
s_flexioHandle[index] = NULL;
s_flexioIsr[index] = NULL;
break;
}
}
if (index == FLEXIO_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
else
{
return kStatus_Success;
}
}
void FLEXIO_CommonIRQHandler(void)
{
uint8_t index;
for (index = 0; index < FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioHandle[index])
{
s_flexioIsr[index](s_flexioType[index], s_flexioHandle[index]);
}
}
}
void FLEXIO_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO0_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void UART2_FLEXIO_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}

View File

@ -0,0 +1,707 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_H_
#define _FSL_FLEXIO_H_
#include "fsl_common.h"
/*!
* @addtogroup flexio_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO driver version 2.0.0. */
#define FSL_FLEXIO_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*! @brief Calculate FlexIO timer trigger.*/
#define FLEXIO_TIMER_TRIGGER_SEL_PININPUT(x) ((uint32_t)(x) << 1U)
#define FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(x) (((uint32_t)(x) << 2U) | 0x1U)
#define FLEXIO_TIMER_TRIGGER_SEL_TIMn(x) (((uint32_t)(x) << 2U) | 0x3U)
/*! @brief Define time of timer trigger polarity.*/
typedef enum _flexio_timer_trigger_polarity
{
kFLEXIO_TimerTriggerPolarityActiveHigh = 0x0U, /*!< Active high. */
kFLEXIO_TimerTriggerPolarityActiveLow = 0x1U, /*!< Active low. */
} flexio_timer_trigger_polarity_t;
/*! @brief Define type of timer trigger source.*/
typedef enum _flexio_timer_trigger_source
{
kFLEXIO_TimerTriggerSourceExternal = 0x0U, /*!< External trigger selected. */
kFLEXIO_TimerTriggerSourceInternal = 0x1U, /*!< Internal trigger selected. */
} flexio_timer_trigger_source_t;
/*! @brief Define type of timer/shifter pin configuration.*/
typedef enum _flexio_pin_config
{
kFLEXIO_PinConfigOutputDisabled = 0x0U, /*!< Pin output disabled. */
kFLEXIO_PinConfigOpenDrainOrBidirection = 0x1U, /*!< Pin open drain or bidirectional output enable. */
kFLEXIO_PinConfigBidirectionOutputData = 0x2U, /*!< Pin bidirectional output data. */
kFLEXIO_PinConfigOutput = 0x3U, /*!< Pin output. */
} flexio_pin_config_t;
/*! @brief Definition of pin polarity.*/
typedef enum _flexio_pin_polarity
{
kFLEXIO_PinActiveHigh = 0x0U, /*!< Active high. */
kFLEXIO_PinActiveLow = 0x1U, /*!< Active low. */
} flexio_pin_polarity_t;
/*! @brief Define type of timer work mode.*/
typedef enum _flexio_timer_mode
{
kFLEXIO_TimerModeDisabled = 0x0U, /*!< Timer Disabled. */
kFLEXIO_TimerModeDual8BitBaudBit = 0x1U, /*!< Dual 8-bit counters baud/bit mode. */
kFLEXIO_TimerModeDual8BitPWM = 0x2U, /*!< Dual 8-bit counters PWM mode. */
kFLEXIO_TimerModeSingle16Bit = 0x3U, /*!< Single 16-bit counter mode. */
} flexio_timer_mode_t;
/*! @brief Define type of timer initial output or timer reset condition.*/
typedef enum _flexio_timer_output
{
kFLEXIO_TimerOutputOneNotAffectedByReset = 0x0U, /*!< Logic one when enabled and is not affected by timer
reset. */
kFLEXIO_TimerOutputZeroNotAffectedByReset = 0x1U, /*!< Logic zero when enabled and is not affected by timer
reset. */
kFLEXIO_TimerOutputOneAffectedByReset = 0x2U, /*!< Logic one when enabled and on timer reset. */
kFLEXIO_TimerOutputZeroAffectedByReset = 0x3U, /*!< Logic zero when enabled and on timer reset. */
} flexio_timer_output_t;
/*! @brief Define type of timer decrement.*/
typedef enum _flexio_timer_decrement_source
{
kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput = 0x0U, /*!< Decrement counter on FlexIO clock, Shift clock
equals Timer output. */
kFLEXIO_TimerDecSrcOnTriggerInputShiftTimerOutput = 0x1U, /*!< Decrement counter on Trigger input (both edges),
Shift clock equals Timer output. */
kFLEXIO_TimerDecSrcOnPinInputShiftPinInput = 0x2U, /*!< Decrement counter on Pin input (both edges),
Shift clock equals Pin input. */
kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput = 0x3U, /*!< Decrement counter on Trigger input (both edges),
Shift clock equals Trigger input. */
} flexio_timer_decrement_source_t;
/*! @brief Define type of timer reset condition.*/
typedef enum _flexio_timer_reset_condition
{
kFLEXIO_TimerResetNever = 0x0U, /*!< Timer never reset. */
kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput = 0x2U, /*!< Timer reset on Timer Pin equal to Timer Output. */
kFLEXIO_TimerResetOnTimerTriggerEqualToTimerOutput = 0x3U, /*!< Timer reset on Timer Trigger equal to
Timer Output. */
kFLEXIO_TimerResetOnTimerPinRisingEdge = 0x4U, /*!< Timer reset on Timer Pin rising edge. */
kFLEXIO_TimerResetOnTimerTriggerRisingEdge = 0x6U, /*!< Timer reset on Trigger rising edge. */
kFLEXIO_TimerResetOnTimerTriggerBothEdge = 0x7U, /*!< Timer reset on Trigger rising or falling edge. */
} flexio_timer_reset_condition_t;
/*! @brief Define type of timer disable condition.*/
typedef enum _flexio_timer_disable_condition
{
kFLEXIO_TimerDisableNever = 0x0U, /*!< Timer never disabled. */
kFLEXIO_TimerDisableOnPreTimerDisable = 0x1U, /*!< Timer disabled on Timer N-1 disable. */
kFLEXIO_TimerDisableOnTimerCompare = 0x2U, /*!< Timer disabled on Timer compare. */
kFLEXIO_TimerDisableOnTimerCompareTriggerLow = 0x3U, /*!< Timer disabled on Timer compare and Trigger Low. */
kFLEXIO_TimerDisableOnPinBothEdge = 0x4U, /*!< Timer disabled on Pin rising or falling edge. */
kFLEXIO_TimerDisableOnPinBothEdgeTriggerHigh = 0x5U, /*!< Timer disabled on Pin rising or falling edge provided
Trigger is high. */
kFLEXIO_TimerDisableOnTriggerFallingEdge = 0x6U, /*!< Timer disabled on Trigger falling edge. */
} flexio_timer_disable_condition_t;
/*! @brief Define type of timer enable condition.*/
typedef enum _flexio_timer_enable_condition
{
kFLEXIO_TimerEnabledAlways = 0x0U, /*!< Timer always enabled. */
kFLEXIO_TimerEnableOnPrevTimerEnable = 0x1U, /*!< Timer enabled on Timer N-1 enable. */
kFLEXIO_TimerEnableOnTriggerHigh = 0x2U, /*!< Timer enabled on Trigger high. */
kFLEXIO_TimerEnableOnTriggerHighPinHigh = 0x3U, /*!< Timer enabled on Trigger high and Pin high. */
kFLEXIO_TimerEnableOnPinRisingEdge = 0x4U, /*!< Timer enabled on Pin rising edge. */
kFLEXIO_TimerEnableOnPinRisingEdgeTriggerHigh = 0x5U, /*!< Timer enabled on Pin rising edge and Trigger high. */
kFLEXIO_TimerEnableOnTriggerRisingEdge = 0x6U, /*!< Timer enabled on Trigger rising edge. */
kFLEXIO_TimerEnableOnTriggerBothEdge = 0x7U, /*!< Timer enabled on Trigger rising or falling edge. */
} flexio_timer_enable_condition_t;
/*! @brief Define type of timer stop bit generate condition.*/
typedef enum _flexio_timer_stop_bit_condition
{
kFLEXIO_TimerStopBitDisabled = 0x0U, /*!< Stop bit disabled. */
kFLEXIO_TimerStopBitEnableOnTimerCompare = 0x1U, /*!< Stop bit is enabled on timer compare. */
kFLEXIO_TimerStopBitEnableOnTimerDisable = 0x2U, /*!< Stop bit is enabled on timer disable. */
kFLEXIO_TimerStopBitEnableOnTimerCompareDisable = 0x3U, /*!< Stop bit is enabled on timer compare and timer
disable. */
} flexio_timer_stop_bit_condition_t;
/*! @brief Define type of timer start bit generate condition.*/
typedef enum _flexio_timer_start_bit_condition
{
kFLEXIO_TimerStartBitDisabled = 0x0U, /*!< Start bit disabled. */
kFLEXIO_TimerStartBitEnabled = 0x1U, /*!< Start bit enabled. */
} flexio_timer_start_bit_condition_t;
/*! @brief Define type of timer polarity for shifter control. */
typedef enum _flexio_shifter_timer_polarity
{
kFLEXIO_ShifterTimerPolarityOnPositive = 0x0U, /* Shift on positive edge of shift clock. */
kFLEXIO_ShifterTimerPolarityOnNegitive = 0x1U, /* Shift on negative edge of shift clock. */
} flexio_shifter_timer_polarity_t;
/*! @brief Define type of shifter working mode.*/
typedef enum _flexio_shifter_mode
{
kFLEXIO_ShifterDisabled = 0x0U, /*!< Shifter is disabled. */
kFLEXIO_ShifterModeReceive = 0x1U, /*!< Receive mode. */
kFLEXIO_ShifterModeTransmit = 0x2U, /*!< Transmit mode. */
kFLEXIO_ShifterModeMatchStore = 0x4U, /*!< Match store mode. */
kFLEXIO_ShifterModeMatchContinuous = 0x5U, /*!< Match continuous mode. */
#if FSL_FEATURE_FLEXIO_HAS_STATE_MODE
kFLEXIO_ShifterModeState = 0x6U, /*!< SHIFTBUF contents are used for storing
programmable state attributes. */
#endif /* FSL_FEATURE_FLEXIO_HAS_STATE_MODE */
#if FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE
kFLEXIO_ShifterModeLogic = 0x7U, /*!< SHIFTBUF contents are used for implementing
programmable logic look up table. */
#endif /* FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE */
} flexio_shifter_mode_t;
/*! @brief Define type of shifter input source.*/
typedef enum _flexio_shifter_input_source
{
kFLEXIO_ShifterInputFromPin = 0x0U, /*!< Shifter input from pin. */
kFLEXIO_ShifterInputFromNextShifterOutput = 0x1U, /*!< Shifter input from Shifter N+1. */
} flexio_shifter_input_source_t;
/*! @brief Define of STOP bit configuration.*/
typedef enum _flexio_shifter_stop_bit
{
kFLEXIO_ShifterStopBitDisable = 0x0U, /*!< Disable shifter stop bit. */
kFLEXIO_ShifterStopBitLow = 0x2U, /*!< Set shifter stop bit to logic low level. */
kFLEXIO_ShifterStopBitHigh = 0x3U, /*!< Set shifter stop bit to logic high level. */
} flexio_shifter_stop_bit_t;
/*! @brief Define type of START bit configuration.*/
typedef enum _flexio_shifter_start_bit
{
kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable = 0x0U, /*!< Disable shifter start bit, transmitter loads
data on enable. */
kFLEXIO_ShifterStartBitDisabledLoadDataOnShift = 0x1U, /*!< Disable shifter start bit, transmitter loads
data on first shift. */
kFLEXIO_ShifterStartBitLow = 0x2U, /*!< Set shifter start bit to logic low level. */
kFLEXIO_ShifterStartBitHigh = 0x3U, /*!< Set shifter start bit to logic high level. */
} flexio_shifter_start_bit_t;
/*! @brief Define FlexIO shifter buffer type*/
typedef enum _flexio_shifter_buffer_type
{
kFLEXIO_ShifterBuffer = 0x0U, /*!< Shifter Buffer N Register. */
kFLEXIO_ShifterBufferBitSwapped = 0x1U, /*!< Shifter Buffer N Bit Byte Swapped Register. */
kFLEXIO_ShifterBufferByteSwapped = 0x2U, /*!< Shifter Buffer N Byte Swapped Register. */
kFLEXIO_ShifterBufferBitByteSwapped = 0x3U, /*!< Shifter Buffer N Bit Swapped Register. */
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
kFLEXIO_ShifterBufferNibbleByteSwapped = 0x4U, /*!< Shifter Buffer N Nibble Byte Swapped Register. */
#endif /*FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP*/
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
kFLEXIO_ShifterBufferHalfWordSwapped = 0x5U, /*!< Shifter Buffer N Half Word Swapped Register. */
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
kFLEXIO_ShifterBufferNibbleSwapped = 0x6U, /*!< Shifter Buffer N Nibble Swapped Register. */
#endif
} flexio_shifter_buffer_type_t;
/*! @brief Define FlexIO user configuration structure. */
typedef struct _flexio_config_
{
bool enableFlexio; /*!< Enable/disable FlexIO module */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
the FlexIO clock to be at least twice the frequency of the bus clock. */
} flexio_config_t;
/*! @brief Define FlexIO timer configuration structure. */
typedef struct _flexio_timer_config
{
/* Trigger. */
uint32_t triggerSelect; /*!< The internal trigger selection number using MACROs. */
flexio_timer_trigger_polarity_t triggerPolarity; /*!< Trigger Polarity. */
flexio_timer_trigger_source_t triggerSource; /*!< Trigger Source, internal (see 'trgsel') or external. */
/* Pin. */
flexio_pin_config_t pinConfig; /*!< Timer Pin Configuration. */
uint32_t pinSelect; /*!< Timer Pin number Select. */
flexio_pin_polarity_t pinPolarity; /*!< Timer Pin Polarity. */
/* Timer. */
flexio_timer_mode_t timerMode; /*!< Timer work Mode. */
flexio_timer_output_t timerOutput; /*!< Configures the initial state of the Timer Output and
whether it is affected by the Timer reset. */
flexio_timer_decrement_source_t timerDecrement; /*!< Configures the source of the Timer decrement and the
source of the Shift clock. */
flexio_timer_reset_condition_t timerReset; /*!< Configures the condition that causes the timer counter
(and optionally the timer output) to be reset. */
flexio_timer_disable_condition_t timerDisable; /*!< Configures the condition that causes the Timer to be
disabled and stop decrementing. */
flexio_timer_enable_condition_t timerEnable; /*!< Configures the condition that causes the Timer to be
enabled and start decrementing. */
flexio_timer_stop_bit_condition_t timerStop; /*!< Timer STOP Bit generation. */
flexio_timer_start_bit_condition_t timerStart; /*!< Timer STRAT Bit generation. */
uint32_t timerCompare; /*!< Value for Timer Compare N Register. */
} flexio_timer_config_t;
/*! @brief Define FlexIO shifter configuration structure. */
typedef struct _flexio_shifter_config
{
/* Timer. */
uint32_t timerSelect; /*!< Selects which Timer is used for controlling the
logic/shift register and generating the Shift clock. */
flexio_shifter_timer_polarity_t timerPolarity; /*!< Timer Polarity. */
/* Pin. */
flexio_pin_config_t pinConfig; /*!< Shifter Pin Configuration. */
uint32_t pinSelect; /*!< Shifter Pin number Select. */
flexio_pin_polarity_t pinPolarity; /*!< Shifter Pin Polarity. */
/* Shifter. */
flexio_shifter_mode_t shifterMode; /*!< Configures the mode of the Shifter. */
#if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
uint32_t parallelWidth; /*!< Configures the parallel width when using parallel mode.*/
#endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
flexio_shifter_input_source_t inputSource; /*!< Selects the input source for the shifter. */
flexio_shifter_stop_bit_t shifterStop; /*!< Shifter STOP bit. */
flexio_shifter_start_bit_t shifterStart; /*!< Shifter START bit. */
} flexio_shifter_config_t;
/*! @brief typedef for FlexIO simulated driver interrupt handler.*/
typedef void (*flexio_isr_t)(void *base, void *handle);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO Initialization and De-initialization
* @{
*/
/*!
* @brief Gets the default configuration to configure FlexIO module. The configuration
* can used directly for calling FLEXIO_Configure().
*
* Example:
@code
flexio_config_t config;
FLEXIO_GetDefaultConfig(&config);
@endcode
*
* @param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig);
/*!
* @brief Configures the FlexIO with FlexIO configuration. The configuration structure
* can be filled by the user, or be set with default values by FLEXIO_GetDefaultConfig().
*
* Example
@code
flexio_config_t config = {
.enableFlexio = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false
};
FLEXIO_Configure(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig);
/*!
* @brief Gates the FlexIO clock. Call this API to stop the FlexIO clock.
*
* @note After calling this API, call the FLEXO_Init to use the FlexIO module.
*
* @param base FlexIO peripheral base address
*/
void FLEXIO_Deinit(FLEXIO_Type *base);
/* @} */
/*!
* @name FlexIO Basic Operation
* @{
*/
/*!
* @brief Resets the FlexIO module.
*
* @param base FlexIO peripheral base address
*/
void FLEXIO_Reset(FLEXIO_Type *base);
/*!
* @brief Enables the FlexIO module operation.
*
* @param base FlexIO peripheral base address
* @param enable true to enable, false to disable.
*/
static inline void FLEXIO_Enable(FLEXIO_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
/*!
* @brief Reads the input data on each of the FlexIO pins.
*
* @param base FlexIO peripheral base address
* @return FlexIO pin input data
*/
static inline uint32_t FLEXIO_ReadPinInput(FLEXIO_Type *base)
{
return base->PIN;
}
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
#if defined(FSL_FEATURE_FLEXIO_HAS_STATE_MODE) && FSL_FEATURE_FLEXIO_HAS_STATE_MODE
/*!
* @brief Gets the current state pointer for state mode use.
*
* @param base FlexIO peripheral base address
* @return current state pointer
*/
static inline uint8_t FLEXIO_GetShifterState(FLEXIO_Type *base)
{
return ((base->SHIFTSTATE) & FLEXIO_SHIFTSTATE_STATE_MASK);
}
#endif /*FSL_FEATURE_FLEXIO_HAS_STATE_MODE*/
/*!
* @brief Configures the shifter with shifter configuration. The configuration structure
* covers both the SHIFTCTL and SHIFTCFG registers. To configure the shifter to the proper
* mode, select which timer controls the shifter to shift, whether to generate start bit/stop
* bit, and the polarity of start bit and stop bit.
*
* Example
@code
flexio_shifter_config_t config = {
.timerSelect = 0,
.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinPolarity = kFLEXIO_PinActiveLow,
.shifterMode = kFLEXIO_ShifterModeTransmit,
.inputSource = kFLEXIO_ShifterInputFromPin,
.shifterStop = kFLEXIO_ShifterStopBitHigh,
.shifterStart = kFLEXIO_ShifterStartBitLow
};
FLEXIO_SetShifterConfig(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param index shifter index
* @param shifterConfig pointer to flexio_shifter_config_t structure
*/
void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig);
/*!
* @brief Configures the timer with the timer configuration. The configuration structure
* covers both the TIMCTL and TIMCFG registers. To configure the timer to the proper
* mode, select trigger source for timer and the timer pin output and the timing for timer.
*
* Example
@code
flexio_timer_config_t config = {
.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0),
.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow,
.triggerSource = kFLEXIO_TimerTriggerSourceInternal,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinSelect = 0,
.pinPolarity = kFLEXIO_PinActiveHigh,
.timerMode = kFLEXIO_TimerModeDual8BitBaudBit,
.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset,
.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput,
.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput,
.timerDisable = kFLEXIO_TimerDisableOnTimerCompare,
.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh,
.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable,
.timerStart = kFLEXIO_TimerStartBitEnabled
};
FLEXIO_SetTimerConfig(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param index timer index
* @param timerConfig pointer to flexio_timer_config_t structure
*/
void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig);
/* @} */
/*!
* @name FlexIO Interrupt Operation
* @{
*/
/*!
* @brief Enables the shifter status interrupt. The interrupt generates when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask the shifter status mask which could be calculated by (1 << shifter index)
* @note for multiple shifter status interrupt enable, for example, two shifter status enable, could calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_EnableShifterStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSIEN |= mask;
}
/*!
* @brief Disables the shifter status interrupt. The interrupt won't generate when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask the shifter status mask which could be calculated by (1 << shifter index)
* @note for multiple shifter status interrupt enable, for example, two shifter status enable, could calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_DisableShifterStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSIEN &= ~mask;
}
/*!
* @brief Enables the shifter error interrupt. The interrupt generates when the corresponding SEF is set.
*
* @param base FlexIO peripheral base address
* @param mask the shifter error mask which could be calculated by (1 << shifter index)
* @note for multiple shifter error interrupt enable, for example, two shifter error enable, could calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_EnableShifterErrorInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTEIEN |= mask;
}
/*!
* @brief Disables the shifter error interrupt. The interrupt won't generate when the corresponding SEF is set.
*
* @param base FlexIO peripheral base address
* @param mask the shifter error mask which could be calculated by (1 << shifter index)
* @note for multiple shifter error interrupt enable, for example, two shifter error enable, could calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_DisableShifterErrorInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTEIEN &= ~mask;
}
/*!
* @brief Enables the timer status interrupt. The interrupt generates when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask the timer status mask which could be calculated by (1 << timer index)
* @note for multiple timer status interrupt enable, for example, two timer status enable, could calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_EnableTimerStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->TIMIEN |= mask;
}
/*!
* @brief Disables the timer status interrupt. The interrupt won't generate when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask the timer status mask which could be calculated by (1 << timer index)
* @note for multiple timer status interrupt enable, for example, two timer status enable, could calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_DisableTimerStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->TIMIEN &= ~mask;
}
/* @} */
/*!
* @name FlexIO Status Operation
* @{
*/
/*!
* @brief Gets the shifter status flags.
*
* @param base FlexIO peripheral base address
* @return shifter status flags
*/
static inline uint32_t FLEXIO_GetShifterStatusFlags(FLEXIO_Type *base)
{
return ((base->SHIFTSTAT) & FLEXIO_SHIFTSTAT_SSF_MASK);
}
/*!
* @brief Clears the shifter status flags.
*
* @param base FlexIO peripheral base address
* @param mask the shifter status mask which could be calculated by (1 << shifter index)
* @note for clearing multiple shifter status flags, for example, two shifter status flags, could calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_ClearShifterStatusFlags(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSTAT = mask;
}
/*!
* @brief Gets the shifter error flags.
*
* @param base FlexIO peripheral base address
* @return shifter error flags
*/
static inline uint32_t FLEXIO_GetShifterErrorFlags(FLEXIO_Type *base)
{
return ((base->SHIFTERR) & FLEXIO_SHIFTERR_SEF_MASK);
}
/*!
* @brief Clears the shifter error flags.
*
* @param base FlexIO peripheral base address
* @param mask the shifter error mask which could be calculated by (1 << shifter index)
* @note for clearing multiple shifter error flags, for example, two shifter error flags, could calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_ClearShifterErrorFlags(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTERR = mask;
}
/*!
* @brief Gets the timer status flags.
*
* @param base FlexIO peripheral base address
* @return timer status flags
*/
static inline uint32_t FLEXIO_GetTimerStatusFlags(FLEXIO_Type *base)
{
return ((base->TIMSTAT) & FLEXIO_TIMSTAT_TSF_MASK);
}
/*!
* @brief Clears the timer status flags.
*
* @param base FlexIO peripheral base address
* @param mask the timer status mask which could be calculated by (1 << timer index)
* @note for clearing multiple timer status flags, for example, two timer status flags, could calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_ClearTimerStatusFlags(FLEXIO_Type *base, uint32_t mask)
{
base->TIMSTAT = mask;
}
/* @} */
/*!
* @name FlexIO DMA Operation
* @{
*/
/*!
* @brief Enables/disables the shifter status DMA. The DMA request generates when the corresponding SSF is set.
*
* @note For multiple shifter status DMA enables, for example, calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*
* @param base FlexIO peripheral base address
* @param mask the shifter status mask which could be calculated by (1 << shifter index)
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_EnableShifterStatusDMA(FLEXIO_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->SHIFTSDEN |= mask;
}
else
{
base->SHIFTSDEN &= ~mask;
}
}
/*!
* @brief Gets the shifter buffer address for the DMA transfer usage.
*
* @param base FlexIO peripheral base address
* @param type shifter type of flexio_shifter_buffer_type_t
* @param index shifter index
* @return corresponding shifter buffer index
*/
uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index);
/*!
* @brief Registers the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* @param base pointer to FlexIO simulated peripheral type.
* @param handle pointer to handler for FlexIO simulated peripheral.
* @param isr FlexIO simulated peripheral interrupt handler.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr);
/*!
* @brief Unregisters the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* @param base pointer to FlexIO simulated peripheral type.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UnregisterHandleIRQ(void *base);
/* @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_H_*/

View File

@ -0,0 +1,732 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_i2c_master.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief FLEXIO I2C transfer state */
enum _flexio_i2c_master_transfer_states
{
kFLEXIO_I2C_Idle = 0x0U, /*!< I2C bus idle */
kFLEXIO_I2C_CheckAddress = 0x1U, /*!< 7-bit address check state */
kFLEXIO_I2C_SendCommand = 0x2U, /*!< Send command byte phase */
kFLEXIO_I2C_SendData = 0x3U, /*!< Send data transfer phase*/
kFLEXIO_I2C_ReceiveDataBegin = 0x4U, /*!< Receive data begin transfer phase*/
kFLEXIO_I2C_ReceiveData = 0x5U, /*!< Receive data transfer phase*/
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Set up master transfer, send slave address and decide the initial
* transfer state.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param transfer pointer to flexio_i2c_master_transfer_t structure
*/
static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer);
/*!
* @brief Master run transfer state machine to perform a byte of transfer.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param statusFlags flexio i2c hardware status
* @retval kStatus_Success Successfully run state machine
* @retval kStatus_FLEXIO_I2C_Nak Receive Nak during transfer
*/
static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
uint32_t statusFlags);
/*!
* @brief Complete transfer, disable interrupt and call callback.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param status flexio transfer status
*/
static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status);
/*******************************************************************************
* Codes
******************************************************************************/
static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer)
{
bool needRestart;
uint32_t byteCount;
/* Init the handle member. */
handle->transfer.slaveAddress = xfer->slaveAddress;
handle->transfer.direction = xfer->direction;
handle->transfer.subaddress = xfer->subaddress;
handle->transfer.subaddressSize = xfer->subaddressSize;
handle->transfer.data = xfer->data;
handle->transfer.dataSize = xfer->dataSize;
handle->transfer.flags = xfer->flags;
handle->transferSize = xfer->dataSize;
/* Initial state, i2c check address state. */
handle->state = kFLEXIO_I2C_CheckAddress;
/* Clear all status before transfer. */
FLEXIO_I2C_MasterClearStatusFlags(base, kFLEXIO_I2C_ReceiveNakFlag);
/* Calculate whether need to send re-start. */
needRestart = (handle->transfer.subaddressSize != 0) && (handle->transfer.direction == kFLEXIO_I2C_Read);
/* Calculate total byte count in a frame. */
byteCount = 1;
if (!needRestart)
{
byteCount += handle->transfer.dataSize;
}
if (handle->transfer.subaddressSize != 0)
{
byteCount += handle->transfer.subaddressSize;
/* Next state, send command byte. */
handle->state = kFLEXIO_I2C_SendCommand;
}
/* Configure data count. */
if (FLEXIO_I2C_MasterSetTransferCount(base, byteCount) != kStatus_Success)
{
return kStatus_InvalidArgument;
}
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
/* Send address byte first. */
if (needRestart)
{
FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write);
}
else
{
FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction);
}
return kStatus_Success;
}
static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
uint32_t statusFlags)
{
if (statusFlags & kFLEXIO_I2C_ReceiveNakFlag)
{
/* Clear receive nak flag. */
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
if ((!((handle->state == kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) &&
(!(((handle->state == kFLEXIO_I2C_ReceiveData) || (handle->state == kFLEXIO_I2C_ReceiveDataBegin)) &&
(handle->transfer.dataSize == 1U))))
{
FLEXIO_I2C_MasterReadByte(base);
FLEXIO_I2C_MasterAbortStop(base);
handle->state = kFLEXIO_I2C_Idle;
return kStatus_FLEXIO_I2C_Nak;
}
}
if (handle->state == kFLEXIO_I2C_CheckAddress)
{
if (handle->transfer.direction == kFLEXIO_I2C_Write)
{
/* Next state, send data. */
handle->state = kFLEXIO_I2C_SendData;
}
else
{
/* Next state, receive data begin. */
handle->state = kFLEXIO_I2C_ReceiveDataBegin;
}
}
if ((statusFlags & kFLEXIO_I2C_RxFullFlag) && (handle->state != kFLEXIO_I2C_ReceiveData))
{
FLEXIO_I2C_MasterReadByte(base);
}
switch (handle->state)
{
case kFLEXIO_I2C_SendCommand:
if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
if (handle->transfer.subaddressSize > 0)
{
handle->transfer.subaddressSize--;
FLEXIO_I2C_MasterWriteByte(
base, ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)));
if (handle->transfer.subaddressSize == 0)
{
/* Load re-start in advance. */
if (handle->transfer.direction == kFLEXIO_I2C_Read)
{
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
FLEXIO_I2C_MasterRepeatedStart(base);
}
}
}
else
{
if (handle->transfer.direction == kFLEXIO_I2C_Write)
{
/* Next state, send data. */
handle->state = kFLEXIO_I2C_SendData;
/* Send first byte of data. */
if (handle->transfer.dataSize > 0)
{
FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
handle->transfer.data++;
handle->transfer.dataSize--;
}
}
else
{
FLEXIO_I2C_MasterSetTransferCount(base, (handle->transfer.dataSize + 1));
FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read);
/* Next state, receive data begin. */
handle->state = kFLEXIO_I2C_ReceiveDataBegin;
}
}
}
break;
/* Send command byte. */
case kFLEXIO_I2C_SendData:
if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
/* Send one byte of data. */
if (handle->transfer.dataSize > 0)
{
FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
handle->transfer.data++;
handle->transfer.dataSize--;
}
else
{
FLEXIO_I2C_MasterStop(base);
handle->state = kFLEXIO_I2C_Idle;
}
}
break;
case kFLEXIO_I2C_ReceiveDataBegin:
if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
/* Read one byte of data. */
FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
/* Send nak at the last receive byte. */
if (handle->transfer.dataSize == 1)
{
FLEXIO_I2C_MasterEnableAck(base, false);
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
FLEXIO_I2C_MasterStop(base);
}
else
{
FLEXIO_I2C_MasterEnableAck(base, true);
}
}
else
{
handle->state = kFLEXIO_I2C_ReceiveData;
}
break;
case kFLEXIO_I2C_ReceiveData:
if (statusFlags & kFLEXIO_I2C_RxFullFlag)
{
*handle->transfer.data = FLEXIO_I2C_MasterReadByte(base);
handle->transfer.data++;
/* Receive one byte of data. */
if (handle->transfer.dataSize--)
{
if (handle->transfer.dataSize != 0)
{
FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
}
else
{
FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_RxFullInterruptEnable);
handle->state = kFLEXIO_I2C_Idle;
}
/* Send nak at the last receive byte. */
if (handle->transfer.dataSize == 1)
{
FLEXIO_I2C_MasterEnableAck(base, false);
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
FLEXIO_I2C_MasterStop(base);
}
}
}
break;
default:
break;
}
return kStatus_Success;
}
static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status)
{
FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable);
if (handle->completionCallback)
{
handle->completionCallback(base, handle, status, handle->userData);
}
}
void FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
{
assert(base && masterConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t controlVal = 0;
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
/* Ungate flexio clock. */
CLOCK_EnableClock(kCLOCK_Flexio0);
FLEXIO_Reset(base->flexioBase);
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[1];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection;
shifterConfig.pinSelect = base->SDAPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveLow;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/* 2. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[1];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->SDAPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/*3. Configure the timer 0 for generating bit clock. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection;
timerConfig.pinSelect = base->SCLPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
/* Set TIMCMP[7:0] = (baud rate divider / 2) - 1. */
timerConfig.timerCompare = (srcClock_Hz / masterConfig->baudRate_Bps) / 2 - 1;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
/* 4. Configure the timer 1 for controlling shifters. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->SCLPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerCompare;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
/* Set TIMCMP[15:0] = (number of bits x 2) - 1. */
timerConfig.timerCompare = 8 * 2 - 1;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
/* Configure FLEXIO I2C Master. */
controlVal = base->flexioBase->CTRL;
controlVal &=
~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
controlVal |=
(FLEXIO_CTRL_DOZEN(masterConfig->enableInDoze) | FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) |
FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) | FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
base->flexioBase->CTRL = controlVal;
}
void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base)
{
FLEXIO_Deinit(base->flexioBase);
}
void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig)
{
assert(masterConfig);
masterConfig->enableMaster = true;
masterConfig->enableInDoze = false;
masterConfig->enableInDebug = true;
masterConfig->enableFastAccess = false;
/* Default baud rate at 100kbps. */
masterConfig->baudRate_Bps = 100000U;
}
uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base)
{
uint32_t status = 0;
status =
((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
status |=
(((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 1U);
status |=
(((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 2U);
return status;
}
void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2C_TxEmptyFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_I2C_RxFullFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
if (mask & kFLEXIO_I2C_ReceiveNakFlag)
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2C_TxEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_I2C_RxFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2C_TxEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_I2C_RxFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
{
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
FLEXIO_Type *flexioBase = base->flexioBase;
/* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
timerDiv = srcClock_Hz / baudRate_Bps;
timerDiv = timerDiv / 2 - 1U;
timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0xFF00;
timerCmp |= timerDiv;
flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
}
status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint8_t count)
{
if (count > 14U)
{
return kStatus_InvalidArgument;
}
uint16_t timerCmp = 0;
uint32_t timerConfig = 0;
FLEXIO_Type *flexioBase = base->flexioBase;
timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0x00FFU;
timerCmp |= (count * 18 + 1U) << 8U;
flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
timerConfig = flexioBase->TIMCFG[base->timerIndex[0]];
timerConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
timerConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
flexioBase->TIMCFG[base->timerIndex[0]] = timerConfig;
return kStatus_Success;
}
void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction)
{
uint32_t data;
data = ((uint32_t)address) << 1U | ((direction == kFLEXIO_I2C_Read) ? 1U : 0U);
FLEXIO_I2C_MasterWriteByte(base, data);
}
void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base)
{
/* Prepare for RESTART condition, no stop.*/
FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
}
void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base)
{
/* Prepare normal stop. */
FLEXIO_I2C_MasterSetTransferCount(base, 0x0U);
FLEXIO_I2C_MasterWriteByte(base, 0x0U);
}
void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base)
{
uint32_t tmpConfig;
/* Prepare abort stop. */
tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[0]];
tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
base->flexioBase->TIMCFG[base->timerIndex[0]] = tmpConfig;
}
void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable)
{
uint32_t tmpConfig = 0;
tmpConfig = base->flexioBase->SHIFTCFG[base->shifterIndex[0]];
tmpConfig &= ~FLEXIO_SHIFTCFG_SSTOP_MASK;
if (enable)
{
tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitLow);
}
else
{
tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitHigh);
}
base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = tmpConfig;
}
status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize)
{
assert(txBuff);
assert(txSize);
uint32_t status;
while (txSize--)
{
FLEXIO_I2C_MasterWriteByte(base, *txBuff++);
/* Wait until data transfer complete. */
while (!((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & kFLEXIO_I2C_RxFullFlag))
{
}
if (status & kFLEXIO_I2C_ReceiveNakFlag)
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
return kStatus_FLEXIO_I2C_Nak;
}
}
return kStatus_Success;
}
void FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize)
{
assert(rxBuff);
assert(rxSize);
while (rxSize--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_I2C_MasterGetStatusFlags(base) & kFLEXIO_I2C_RxFullFlag))
{
}
*rxBuff++ = FLEXIO_I2C_MasterReadByte(base);
}
}
status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Register callback and userData. */
handle->completionCallback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[0]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2C_MasterTransferHandleIRQ);
}
status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer)
{
assert(handle);
assert(xfer);
if (handle->state != kFLEXIO_I2C_Idle)
{
return kStatus_FLEXIO_I2C_Busy;
}
else
{
/* Set up transfer machine. */
FLEXIO_I2C_MasterTransferInitStateMachine(base, handle, xfer);
/* Enable both tx empty and rxfull interrupt. */
FLEXIO_I2C_MasterEnableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable);
return kStatus_Success;
}
}
void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle)
{
assert(handle);
/* Disable interrupts. */
FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable);
/* Reset to idle state. */
handle->state = kFLEXIO_I2C_Idle;
}
status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count)
{
if (!count)
{
return kStatus_InvalidArgument;
}
*count = handle->transferSize - handle->transfer.dataSize;
return kStatus_Success;
}
void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle)
{
FLEXIO_I2C_Type *base = (FLEXIO_I2C_Type *)i2cType;
flexio_i2c_master_handle_t *handle = (flexio_i2c_master_handle_t *)i2cHandle;
uint32_t statusFlags;
status_t result;
statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base);
result = FLEXIO_I2C_MasterTransferRunStateMachine(base, handle, statusFlags);
if (handle->state == kFLEXIO_I2C_Idle)
{
FLEXIO_I2C_MasterTransferComplete(base, handle, result);
}
}

View File

@ -0,0 +1,490 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_I2C_MASTER_H_
#define _FSL_FLEXIO_I2C_MASTER_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_i2c_master
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO I2C master driver version 2.1.0. */
#define FSL_FLEXIO_I2C_MASTER_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*! @brief FlexIO I2C transfer status*/
enum _flexio_i2c_status
{
kStatus_FLEXIO_I2C_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 0), /*!< I2C is busy doing transfer. */
kStatus_FLEXIO_I2C_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 1), /*!< I2C is busy doing transfer. */
kStatus_FLEXIO_I2C_Nak = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 2), /*!< NAK received during transfer. */
};
/*! @brief Define FlexIO I2C master interrupt mask. */
enum _flexio_i2c_master_interrupt
{
kFLEXIO_I2C_TxEmptyInterruptEnable = 0x1U, /*!< Tx buffer empty interrupt enable. */
kFLEXIO_I2C_RxFullInterruptEnable = 0x2U, /*!< Rx buffer full interrupt enable. */
};
/*! @brief Define FlexIO I2C master status mask. */
enum _flexio_i2c_master_status_flags
{
kFLEXIO_I2C_TxEmptyFlag = 0x1U, /*!< Tx shifter empty flag. */
kFLEXIO_I2C_RxFullFlag = 0x2U, /*!< Rx shifter full/Transfer complete flag. */
kFLEXIO_I2C_ReceiveNakFlag = 0x4U, /*!< Receive NAK flag. */
};
/*! @brief Direction of master transfer.*/
typedef enum _flexio_i2c_direction
{
kFLEXIO_I2C_Write = 0x0U, /*!< Master send to slave. */
kFLEXIO_I2C_Read = 0x1U, /*!< Master receive from slave. */
} flexio_i2c_direction_t;
/*! @brief Define FlexIO I2C master access structure typedef. */
typedef struct _flexio_i2c_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t SDAPinIndex; /*!< Pin select for I2C SDA. */
uint8_t SCLPinIndex; /*!< Pin select for I2C SCL. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO I2C. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO I2C. */
} FLEXIO_I2C_Type;
/*! @brief Define FlexIO I2C master user configuration structure. */
typedef struct _flexio_i2c_master_config
{
bool enableMaster; /*!< Enables the FLEXIO I2C peripheral at initialization time. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
the FlexIO clock to be at least twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
} flexio_i2c_master_config_t;
/*! @brief Define FlexIO I2C master transfer structure. */
typedef struct _flexio_i2c_master_transfer
{
uint32_t flags; /*!< Transfer flag which controls the transfer, reserved for flexio i2c. */
uint8_t slaveAddress; /*!< 7-bit slave address. */
flexio_i2c_direction_t direction; /*!< Transfer direction, read or write. */
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
uint8_t subaddressSize; /*!< Size of command buffer. */
uint8_t volatile *data; /*!< Transfer buffer. */
volatile size_t dataSize; /*!< Transfer size. */
} flexio_i2c_master_transfer_t;
/*! @brief FlexIO I2C master handle typedef. */
typedef struct _flexio_i2c_master_handle flexio_i2c_master_handle_t;
/*! @brief FlexIO I2C master transfer callback typedef. */
typedef void (*flexio_i2c_master_transfer_callback_t)(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO I2C master handle structure. */
struct _flexio_i2c_master_handle
{
flexio_i2c_master_transfer_t transfer; /*!< FlexIO I2C master transfer copy. */
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t state; /*!< Transfer state maintained during transfer. */
flexio_i2c_master_transfer_callback_t completionCallback; /*!< Callback function called at transfer event. */
/*!< Callback function called at transfer event. */
void *userData; /*!< Callback parameter passed to callback function. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
* hardware configuration.
*
* Example
@code
FLEXIO_I2C_Type base = {
.flexioBase = FLEXIO,
.SDAPinIndex = 0,
.SCLPinIndex = 1,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_i2c_master_config_t config = {
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 100000
};
FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
@endcode
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param masterConfig pointer to flexio_i2c_master_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
*/
void FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief De-initializes the FlexIO I2C master peripheral. Calling this API gates the FlexIO clock,
* so the FlexIO I2C master module can't work unless call FLEXIO_I2C_MasterInit.
*
* @param base pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO module. The configuration
* can be used directly for calling FLEXIO_I2C_MasterInit().
*
* Example:
@code
flexio_i2c_master_config_t config;
FLEXIO_I2C_MasterGetDefaultConfig(&config);
@endcode
* @param masterConfig pointer to flexio_i2c_master_config_t structure.
*/
void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig);
/*!
* @brief Enables/disables the FlexIO module operation.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param enable pass true to enable module, false to disable module.
*/
static inline void FLEXIO_I2C_MasterEnable(FLEXIO_I2C_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO I2C master status flags.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @return status flag, use status flag to AND #_flexio_i2c_master_status_flags could get the related status.
*/
uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base);
/*!
* @brief Clears the FlexIO I2C master status flags.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param mask status flag.
* The parameter could be any combination of the following values:
* @arg kFLEXIO_I2C_RxFullFlag
* @arg kFLEXIO_I2C_ReceiveNakFlag
*/
void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask);
/*@}*/
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO i2c master interrupt requests.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param mask interrupt source.
* Currently only one interrupt request source:
* @arg kFLEXIO_I2C_TransferCompleteInterruptEnable
*/
void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO I2C master interrupt requests.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param mask interrupt source.
*/
void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
/*@}*/
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Sets the FlexIO I2C master transfer baudrate.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param baudRate_Bps the baud rate value in HZ
* @param srcClock_Hz source clock in HZ
*/
void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/*!
* @brief Sends START + 7-bit address to the bus.
*
* @note This is API should be called when transfer configuration is ready to send a START signal
* and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
* is put into the data register but not address transfer finished on the bus. Ensure that
* the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
* @param base pointer to FLEXIO_I2C_Type structure.
* @param address 7-bit address.
* @param direction transfer direction.
* This parameter is one of the values in flexio_i2c_direction_t:
* @arg kFLEXIO_I2C_Write: Transmit
* @arg kFLEXIO_I2C_Read: Receive
*/
void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction);
/*!
* @brief Sends the stop signal on the bus.
*
* @param base pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base);
/*!
* @brief Sends the repeated start signal on the bus.
*
* @param base pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base);
/*!
* @brief Sends the stop signal when transfer is still on-going.
*
* @param base pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base);
/*!
* @brief Configures the sent ACK/NAK for the following byte.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param enable true to configure send ACK, false configure to send NAK.
*/
void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable);
/*!
* @brief Sets the number of bytes to be transferred from a start signal to a stop signal.
*
* @note Call this API before a transfer begins because the timer generates a number of clocks according
* to the number of bytes that need to be transferred.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param count number of bytes need to be transferred from a start signal to a re-start/stop signal
* @retval kStatus_Success Successfully configured the count.
* @retval kStatus_InvalidArgument Input argument is invalid.
*/
status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint8_t count);
/*!
* @brief Writes one byte of data to the I2C bus.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register but not data transfer finished on the bus. Ensure that
* the TxEmptyFlag is asserted before calling this API.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param data a byte of data.
*/
static inline void FLEXIO_I2C_MasterWriteByte(FLEXIO_I2C_Type *base, uint32_t data)
{
base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
}
/*!
* @brief Reads one byte of data from the I2C bus.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the data is ready in the register.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @return data byte read.
*/
static inline uint8_t FLEXIO_I2C_MasterReadByte(FLEXIO_I2C_Type *base)
{
return base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]];
}
/*!
* @brief Sends a buffer of data in bytes.
*
* @note This function blocks via polling until all bytes have been sent.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param txBuff The data bytes to send.
* @param txSize The number of data bytes to send.
* @retval kStatus_Success Successfully write data.
* @retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
*/
status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks via polling until all bytes have been received.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param rxBuff The buffer to store the received bytes.
* @param rxSize The number of data bytes to be received.
*/
void FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize);
/*!
* @brief Performs a master polling transfer on the I2C bus.
*
* @note The API does not return until the transfer succeeds or fails due
* to receiving NAK.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
* @param xfer pointer to flexio_i2c_master_transfer_t structure.
* @return status of status_t.
*/
status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer);
/*@}*/
/*Transactional APIs*/
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the I2C handle which is used in transactional functions.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param handle pointer to flexio_i2c_master_handle_t structure to store the transfer state.
* @param callback pointer to user callback function.
* @param userData user param passed to the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
*/
status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Performs a master interrupt non-blocking transfer on the I2C bus.
*
* @note The API returns immediately after the transfer initiates.
* Call FLEXIO_I2C_MasterGetTransferCount to poll the transfer status to check whether
* the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
* is finished.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param xfer pointer to flexio_i2c_master_transfer_t structure
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_FLEXIO_I2C_Busy FLEXIO I2C is not idle, is running another transfer.
*/
status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer);
/*!
* @brief Gets the master transfer status during a interrupt non-blocking transfer.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count);
/*!
* @brief Aborts an interrupt non-blocking transfer early.
*
* @note This API can be called at any time when an interrupt non-blocking transfer initiates
* to abort the transfer early.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
*/
void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle);
/*!
* @brief Master interrupt handler.
*
* @param i2cType pointer to FLEXIO_I2C_Type structure
* @param i2cHandle pointer to flexio_i2c_master_transfer_t structure
*/
void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle);
/*@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_I2C_MASTER_H_*/

View File

@ -0,0 +1,637 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_i2s.h"
/*******************************************************************************
* Definitations
******************************************************************************/
enum _sai_transfer_state
{
kFLEXIO_I2S_Busy = 0x0U, /*!< FLEXIO_I2S is busy */
kFLEXIO_I2S_Idle, /*!< Transfer is done. */
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Receive a piece of data in non-blocking way.
*
* @param base FLEXIO I2S base pointer
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param buffer Pointer to the data to be read.
* @param size Bytes to be read.
*/
static void FLEXIO_I2S_ReadNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size);
/*!
* @brief sends a piece of data in non-blocking way.
*
* @param base FLEXIO I2S base pointer
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param buffer Pointer to the data to be written.
* @param size Bytes to be written.
*/
static void FLEXIO_I2S_WriteNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size);
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_I2S_WriteNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size)
{
uint32_t i = 0;
uint8_t j = 0;
uint8_t bytesPerWord = bitWidth / 8U;
uint32_t data = 0;
uint32_t temp = 0;
for (i = 0; i < size / bytesPerWord; i++)
{
for (j = 0; j < bytesPerWord; j++)
{
temp = (uint32_t)(*txData);
data |= (temp << (8U * j));
txData++;
}
base->flexioBase->SHIFTBUFBIS[base->txShifterIndex] = (data << (32U - bitWidth));
data = 0;
}
}
static void FLEXIO_I2S_ReadNonBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size)
{
uint32_t i = 0;
uint8_t j = 0;
uint8_t bytesPerWord = bitWidth / 8U;
uint32_t data = 0;
for (i = 0; i < size / bytesPerWord; i++)
{
data = base->flexioBase->SHIFTBUFBIS[base->rxShifterIndex];
for (j = 0; j < bytesPerWord; j++)
{
*rxData = (data >> (8U * j)) & 0xFF;
rxData++;
}
}
}
void FLEXIO_I2S_Init(FLEXIO_I2S_Type *base, const flexio_i2s_config_t *config)
{
assert(base && config);
flexio_shifter_config_t shifterConfig = {0};
flexio_timer_config_t timerConfig = {0};
/* Ungate flexio clock. */
CLOCK_EnableClock(kCLOCK_Flexio0);
FLEXIO_Reset(base->flexioBase);
/* Set shifter for I2S Tx data */
shifterConfig.timerSelect = base->bclkTimerIndex;
shifterConfig.pinSelect = base->txPinIndex;
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
if (config->masterSlave == kFLEXIO_I2S_Master)
{
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
}
else
{
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->txShifterIndex, &shifterConfig);
/* Set shifter for I2S Rx Data */
shifterConfig.timerSelect = base->bclkTimerIndex;
shifterConfig.pinSelect = base->rxPinIndex;
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
FLEXIO_SetShifterConfig(base->flexioBase, base->rxShifterIndex, &shifterConfig);
/* Set Timer to I2S frame sync */
if (config->masterSlave == kFLEXIO_I2S_Master)
{
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->bclkTimerIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceExternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
timerConfig.pinSelect = base->fsPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableNever;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
}
else
{
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->bclkPinIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->fsPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPinRisingEdge;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
}
FLEXIO_SetTimerConfig(base->flexioBase, base->fsTimerIndex, &timerConfig);
/* Set Timer to I2S bit clock */
if (config->masterSlave == kFLEXIO_I2S_Master)
{
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->txShifterIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinSelect = base->bclkPinIndex;
timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableNever;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
}
else
{
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->fsTimerIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinSelect = base->bclkPinIndex;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompareTriggerLow;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPinRisingEdgeTriggerHigh;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
}
FLEXIO_SetTimerConfig(base->flexioBase, base->bclkTimerIndex, &timerConfig);
/* If enable flexio I2S */
if (config->enableI2S)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
void FLEXIO_I2S_GetDefaultConfig(flexio_i2s_config_t *config)
{
config->masterSlave = kFLEXIO_I2S_Master;
config->enableI2S = true;
}
void FLEXIO_I2S_Deinit(FLEXIO_I2S_Type *base)
{
/* Disable FLEXIO I2S module. */
FLEXIO_I2S_Enable(base, false);
/* Gate flexio clock. */
CLOCK_DisableClock(kCLOCK_Flexio0);
}
void FLEXIO_I2S_EnableInterrupts(FLEXIO_I2S_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2S_TxDataRegEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->txShifterIndex);
}
if (mask & kFLEXIO_I2S_RxDataRegFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->rxShifterIndex);
}
}
uint32_t FLEXIO_I2S_GetStatusFlags(FLEXIO_I2S_Type *base)
{
uint32_t status = 0;
status = ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->txShifterIndex)) >> base->txShifterIndex);
status |=
(((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->rxShifterIndex)) >> (base->rxShifterIndex))
<< 1U);
return status;
}
void FLEXIO_I2S_DisableInterrupts(FLEXIO_I2S_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2S_TxDataRegEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->txShifterIndex);
}
if (mask & kFLEXIO_I2S_RxDataRegFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->rxShifterIndex);
}
}
void FLEXIO_I2S_MasterSetFormat(FLEXIO_I2S_Type *base, flexio_i2s_format_t *format, uint32_t srcClock_Hz)
{
uint32_t timDiv = srcClock_Hz / (format->sampleRate_Hz * 32U * 2U);
uint32_t bclkDiv = 0;
/* Set Frame sync timer cmp */
base->flexioBase->TIMCMP[base->fsTimerIndex] = FLEXIO_TIMCMP_CMP(32U * timDiv - 1U);
/* Set bit clock timer cmp */
bclkDiv = ((timDiv / 2U - 1U) | (63U << 8U));
base->flexioBase->TIMCMP[base->bclkTimerIndex] = FLEXIO_TIMCMP_CMP(bclkDiv);
}
void FLEXIO_I2S_SlaveSetFormat(FLEXIO_I2S_Type *base, flexio_i2s_format_t *format)
{
/* Set Frame sync timer cmp */
base->flexioBase->TIMCMP[base->fsTimerIndex] = FLEXIO_TIMCMP_CMP(format->bitWidth * 4U - 3U);
/* Set bit clock timer cmp */
base->flexioBase->TIMCMP[base->bclkTimerIndex] = FLEXIO_TIMCMP_CMP(format->bitWidth * 2U - 1U);
}
void FLEXIO_I2S_WriteBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size)
{
uint32_t i = 0;
uint8_t bytesPerWord = bitWidth / 8U;
for (i = 0; i < size / bytesPerWord; i++)
{
/* Wait until it can write data */
while ((FLEXIO_I2S_GetStatusFlags(base) & kFLEXIO_I2S_TxDataRegEmptyFlag) == 0)
{
}
FLEXIO_I2S_WriteNonBlocking(base, bitWidth, txData, bytesPerWord);
txData += bytesPerWord;
}
/* Wait until the last data is sent */
while ((FLEXIO_I2S_GetStatusFlags(base) & kFLEXIO_I2S_TxDataRegEmptyFlag) == 0)
{
}
}
void FLEXIO_I2S_ReadBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size)
{
uint32_t i = 0;
uint8_t bytesPerWord = bitWidth / 8U;
for (i = 0; i < size / bytesPerWord; i++)
{
/* Wait until data is received */
while (!(FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->rxShifterIndex)))
{
}
FLEXIO_I2S_ReadNonBlocking(base, bitWidth, rxData, bytesPerWord);
rxData += bytesPerWord;
}
}
void FLEXIO_I2S_TransferTxCreateHandle(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Store callback and user data. */
handle->callback = callback;
handle->userData = userData;
/* Save the context in global variables to support the double weak mechanism. */
FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2S_TransferTxHandleIRQ);
/* Set the TX/RX state. */
handle->state = kFLEXIO_I2S_Idle;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[0]);
}
void FLEXIO_I2S_TransferRxCreateHandle(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Store callback and user data. */
handle->callback = callback;
handle->userData = userData;
/* Save the context in global variables to support the double weak mechanism. */
FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2S_TransferRxHandleIRQ);
/* Set the TX/RX state. */
handle->state = kFLEXIO_I2S_Idle;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[0]);
}
void FLEXIO_I2S_TransferSetFormat(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_format_t *format,
uint32_t srcClock_Hz)
{
assert(handle && format);
/* Set the bitWidth to handle */
handle->bitWidth = format->bitWidth;
/* Set sample rate */
if (srcClock_Hz != 0)
{
/* It is master */
FLEXIO_I2S_MasterSetFormat(base, format, srcClock_Hz);
}
else
{
FLEXIO_I2S_SlaveSetFormat(base, format);
}
}
status_t FLEXIO_I2S_TransferSendNonBlocking(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_transfer_t *xfer)
{
assert(handle);
/* Check if the queue is full */
if (handle->queue[handle->queueUser].data)
{
return kStatus_FLEXIO_I2S_QueueFull;
}
if ((xfer->dataSize == 0) || (xfer->data == NULL))
{
return kStatus_InvalidArgument;
}
/* Add into queue */
handle->queue[handle->queueUser].data = xfer->data;
handle->queue[handle->queueUser].dataSize = xfer->dataSize;
handle->transferSize[handle->queueUser] = xfer->dataSize;
handle->queueUser = (handle->queueUser + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
/* Set the state to busy */
handle->state = kFLEXIO_I2S_Busy;
FLEXIO_I2S_EnableInterrupts(base, kFLEXIO_I2S_TxDataRegEmptyInterruptEnable);
/* Enable Tx transfer */
FLEXIO_I2S_Enable(base, true);
return kStatus_Success;
}
status_t FLEXIO_I2S_TransferReceiveNonBlocking(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_transfer_t *xfer)
{
assert(handle);
/* Check if the queue is full */
if (handle->queue[handle->queueUser].data)
{
return kStatus_FLEXIO_I2S_QueueFull;
}
if ((xfer->dataSize == 0) || (xfer->data == NULL))
{
return kStatus_InvalidArgument;
}
/* Add into queue */
handle->queue[handle->queueUser].data = xfer->data;
handle->queue[handle->queueUser].dataSize = xfer->dataSize;
handle->transferSize[handle->queueUser] = xfer->dataSize;
handle->queueUser = (handle->queueUser + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
/* Set state to busy */
handle->state = kFLEXIO_I2S_Busy;
/* Enable interrupt */
FLEXIO_I2S_EnableInterrupts(base, kFLEXIO_I2S_RxDataRegFullInterruptEnable);
/* Enable Rx transfer */
FLEXIO_I2S_Enable(base, true);
return kStatus_Success;
}
void FLEXIO_I2S_TransferAbortSend(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle)
{
assert(handle);
/* Stop Tx transfer and disable interrupt */
FLEXIO_I2S_Enable(base, false);
FLEXIO_I2S_DisableInterrupts(base, kFLEXIO_I2S_TxDataRegEmptyInterruptEnable);
handle->state = kFLEXIO_I2S_Idle;
/* Clear the queue */
memset(handle->queue, 0, sizeof(flexio_i2s_transfer_t) * FLEXIO_I2S_XFER_QUEUE_SIZE);
handle->queueDriver = 0;
handle->queueUser = 0;
}
void FLEXIO_I2S_TransferAbortReceive(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle)
{
assert(handle);
/* Stop Tx transfer and disable interrupt */
FLEXIO_I2S_Enable(base, false);
FLEXIO_I2S_DisableInterrupts(base, kFLEXIO_I2S_RxDataRegFullInterruptEnable);
handle->state = kFLEXIO_I2S_Idle;
/* Clear the queue */
memset(handle->queue, 0, sizeof(flexio_i2s_transfer_t) * FLEXIO_I2S_XFER_QUEUE_SIZE);
handle->queueDriver = 0;
handle->queueUser = 0;
}
status_t FLEXIO_I2S_TransferGetSendCount(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kFLEXIO_I2S_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
*count = (handle->transferSize[handle->queueDriver] - handle->queue[handle->queueDriver].dataSize);
}
return status;
}
status_t FLEXIO_I2S_TransferGetReceiveCount(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kFLEXIO_I2S_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
*count = (handle->transferSize[handle->queueDriver] - handle->queue[handle->queueDriver].dataSize);
}
return status;
}
void FLEXIO_I2S_TransferTxHandleIRQ(void *i2sBase, void *i2sHandle)
{
assert(i2sHandle);
flexio_i2s_handle_t *handle = (flexio_i2s_handle_t *)i2sHandle;
FLEXIO_I2S_Type *base = (FLEXIO_I2S_Type *)i2sBase;
uint8_t *buffer = handle->queue[handle->queueDriver].data;
uint8_t dataSize = handle->bitWidth / 8U;
/* Handle error */
if (FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->txShifterIndex))
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, (1U << base->txShifterIndex));
}
/* Handle transfer */
if ((FLEXIO_I2S_GetStatusFlags(base) & kFLEXIO_I2S_TxDataRegEmptyFlag) != 0)
{
FLEXIO_I2S_WriteNonBlocking(base, handle->bitWidth, buffer, dataSize);
/* Update internal counter */
handle->queue[handle->queueDriver].dataSize -= dataSize;
handle->queue[handle->queueDriver].data += dataSize;
}
/* If finished a blcok, call the callback function */
if (handle->queue[handle->queueDriver].dataSize == 0U)
{
memset(&handle->queue[handle->queueDriver], 0, sizeof(flexio_i2s_transfer_t));
handle->queueDriver = (handle->queueDriver + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_Success, handle->userData);
}
}
/* If all data finished, just stop the transfer */
if (handle->queue[handle->queueDriver].data == NULL)
{
FLEXIO_I2S_TransferAbortSend(base, handle);
}
}
void FLEXIO_I2S_TransferRxHandleIRQ(void *i2sBase, void *i2sHandle)
{
assert(i2sHandle);
flexio_i2s_handle_t *handle = (flexio_i2s_handle_t *)i2sHandle;
FLEXIO_I2S_Type *base = (FLEXIO_I2S_Type *)i2sBase;
uint8_t *buffer = handle->queue[handle->queueDriver].data;
uint8_t dataSize = handle->bitWidth / 8U;
/* Handle transfer */
if ((FLEXIO_I2S_GetStatusFlags(base) & kFLEXIO_I2S_RxDataRegFullFlag) != 0)
{
FLEXIO_I2S_ReadNonBlocking(base, handle->bitWidth, buffer, dataSize);
/* Update internal state */
handle->queue[handle->queueDriver].dataSize -= dataSize;
handle->queue[handle->queueDriver].data += dataSize;
}
/* If finished a blcok, call the callback function */
if (handle->queue[handle->queueDriver].dataSize == 0U)
{
memset(&handle->queue[handle->queueDriver], 0, sizeof(flexio_i2s_transfer_t));
handle->queueDriver = (handle->queueDriver + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_Success, handle->userData);
}
}
/* If all data finished, just stop the transfer */
if (handle->queue[handle->queueDriver].data == NULL)
{
FLEXIO_I2S_TransferAbortReceive(base, handle);
}
}

View File

@ -0,0 +1,570 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_I2S_H_
#define _FSL_FLEXIO_I2S_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_i2s
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO I2S driver version 2.1.0. */
#define FSL_FLEXIO_I2S_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*! @brief FlexIO I2S transfer status */
enum _flexio_i2s_status
{
kStatus_FLEXIO_I2S_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_I2S, 0), /*!< FlexIO I2S is in idle state */
kStatus_FLEXIO_I2S_TxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_I2S, 1), /*!< FlexIO I2S Tx is busy */
kStatus_FLEXIO_I2S_RxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_I2S, 2), /*!< FlexIO I2S Tx is busy */
kStatus_FLEXIO_I2S_Error = MAKE_STATUS(kStatusGroup_FLEXIO_I2S, 3), /*!< FlexIO I2S error occurred */
kStatus_FLEXIO_I2S_QueueFull = MAKE_STATUS(kStatusGroup_FLEXIO_I2S, 4), /*!< FlexIO I2S transfer queue is full. */
};
/*! @brief Define FlexIO I2S access structure typedef */
typedef struct _flexio_i2s_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer */
uint8_t txPinIndex; /*!< Tx data pin index in FlexIO pins */
uint8_t rxPinIndex; /*!< Rx data pin index */
uint8_t bclkPinIndex; /*!< Bit clock pin index */
uint8_t fsPinIndex; /*!< Frame sync pin index */
uint8_t txShifterIndex; /*!< Tx data shifter index */
uint8_t rxShifterIndex; /*!< Rx data shifter index */
uint8_t bclkTimerIndex; /*!< Bit clock timer index */
uint8_t fsTimerIndex; /*!< Frame sync timer index */
} FLEXIO_I2S_Type;
/*! @brief Master or slave mode */
typedef enum _flexio_i2s_master_slave
{
kFLEXIO_I2S_Master = 0x0U, /*!< Master mode */
kFLEXIO_I2S_Slave = 0x1U /*!< Slave mode */
} flexio_i2s_master_slave_t;
/*! @brief Define FlexIO FlexIO I2S interrupt mask. */
enum _flexio_i2s_interrupt_enable
{
kFLEXIO_I2S_TxDataRegEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_I2S_RxDataRegFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO FlexIO I2S status mask. */
enum _flexio_i2s_status_flags
{
kFLEXIO_I2S_TxDataRegEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_I2S_RxDataRegFullFlag = 0x2U, /*!< Receive buffer full flag. */
};
/*! @brief FlexIO I2S configure structure */
typedef struct _flexio_i2s_config
{
bool enableI2S; /*!< Enable FlexIO I2S */
flexio_i2s_master_slave_t masterSlave; /*!< Master or slave */
} flexio_i2s_config_t;
/*! @brief FlexIO I2S audio format, FlexIO I2S only support the same format in Tx and Rx */
typedef struct _flexio_i2s_format
{
uint8_t bitWidth; /*!< Bit width of audio data, always 8/16/24/32 bits */
uint32_t sampleRate_Hz; /*!< Sample rate of the audio data */
} flexio_i2s_format_t;
/*!@brief FlexIO I2S transfer queue size, user can refine it according to use case. */
#define FLEXIO_I2S_XFER_QUEUE_SIZE (4)
/*! @brief Audio sample rate */
typedef enum _flexio_i2s_sample_rate
{
kFLEXIO_I2S_SampleRate8KHz = 8000U, /*!< Sample rate 8000Hz */
kFLEXIO_I2S_SampleRate11025Hz = 11025U, /*!< Sample rate 11025Hz */
kFLEXIO_I2S_SampleRate12KHz = 12000U, /*!< Sample rate 12000Hz */
kFLEXIO_I2S_SampleRate16KHz = 16000U, /*!< Sample rate 16000Hz */
kFLEXIO_I2S_SampleRate22050Hz = 22050U, /*!< Sample rate 22050Hz */
kFLEXIO_I2S_SampleRate24KHz = 24000U, /*!< Sample rate 24000Hz */
kFLEXIO_I2S_SampleRate32KHz = 32000U, /*!< Sample rate 32000Hz */
kFLEXIO_I2S_SampleRate44100Hz = 44100U, /*!< Sample rate 44100Hz */
kFLEXIO_I2S_SampleRate48KHz = 48000U, /*!< Sample rate 48000Hz */
kFLEXIO_I2S_SampleRate96KHz = 96000U /*!< Sample rate 96000Hz */
} flexio_i2s_sample_rate_t;
/*! @brief Audio word width */
typedef enum _flexio_i2s_word_width
{
kFLEXIO_I2S_WordWidth8bits = 8U, /*!< Audio data width 8 bits */
kFLEXIO_I2S_WordWidth16bits = 16U, /*!< Audio data width 16 bits */
kFLEXIO_I2S_WordWidth24bits = 24U, /*!< Audio data width 24 bits */
kFLEXIO_I2S_WordWidth32bits = 32U /*!< Audio data width 32 bits */
} flexio_i2s_word_width_t;
/*! @brief Define FlexIO I2S transfer structure. */
typedef struct _flexio_i2s_transfer
{
uint8_t *data; /*!< Data buffer start pointer */
size_t dataSize; /*!< Bytes to be transferred. */
} flexio_i2s_transfer_t;
typedef struct _flexio_i2s_handle flexio_i2s_handle_t;
/*! @brief FlexIO I2S xfer callback prototype */
typedef void (*flexio_i2s_callback_t)(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO I2S handle structure. */
struct _flexio_i2s_handle
{
uint32_t state; /*!< Internal state */
flexio_i2s_callback_t callback; /*!< Callback function called at transfer event*/
void *userData; /*!< Callback parameter passed to callback function*/
uint8_t bitWidth; /*!< Bit width for transfer, 8/16/24/32bits */
flexio_i2s_transfer_t queue[FLEXIO_I2S_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
size_t transferSize[FLEXIO_I2S_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
volatile uint8_t queueUser; /*!< Index for user to queue transfer */
volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes the FlexIO I2S.
*
* This API configures FlexIO pins and shifter to I2S and configure FlexIO I2S with configuration structure.
* The configuration structure can be filled by the user, or be set with default values by
* FLEXIO_I2S_GetDefaultConfig().
*
* @note This API should be called at the beginning of the application to use
* the FlexIO I2S driver, or any access to the FlexIO I2S module could cause hard fault
* because clock is not enabled.
*
* @param base FlexIO I2S base pointer
* @param config FlexIO I2S configure structure.
*/
void FLEXIO_I2S_Init(FLEXIO_I2S_Type *base, const flexio_i2s_config_t *config);
/*!
* @brief Sets the FlexIO I2S configuration structure to default values.
*
* The purpose of this API is to get the configuration structure initialized for use in FLEXIO_I2S_Init().
* User may use the initialized structure unchanged in FLEXIO_I2S_Init(), or modify
* some fields of the structure before calling FLEXIO_I2S_Init().
*
* @param config pointer to master configuration structure
*/
void FLEXIO_I2S_GetDefaultConfig(flexio_i2s_config_t *config);
/*!
* @brief De-initializes the FlexIO I2S.
*
* Calling this API gates the FlexIO i2s clock. After calling this API, call the FLEXO_I2S_Init to use the
* FlexIO I2S module.
*
* @param base FlexIO I2S base pointer
*/
void FLEXIO_I2S_Deinit(FLEXIO_I2S_Type *base);
/*!
* @brief Enables/disables the FlexIO I2S module operation.
*
* @param base pointer to FLEXIO_I2S_Type
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_I2S_Enable(FLEXIO_I2S_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO I2S status flags.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @return Status flag, which are ORed by the enumerators in the _flexio_i2s_status_flags.
*/
uint32_t FLEXIO_I2S_GetStatusFlags(FLEXIO_I2S_Type *base);
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO I2S interrupt.
*
* This function enables the FlexIO UART interrupt.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @param mask interrupt source
*/
void FLEXIO_I2S_EnableInterrupts(FLEXIO_I2S_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO I2S interrupt.
*
* This function enables the FlexIO UART interrupt.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @param mask interrupt source
*/
void FLEXIO_I2S_DisableInterrupts(FLEXIO_I2S_Type *base, uint32_t mask);
/*! @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables/disables the FlexIO I2S Tx DMA requests.
*
* @param base FlexIO I2S base pointer
* @param enable True means enable DMA, false means disable DMA.
*/
static inline void FLEXIO_I2S_TxEnableDMA(FLEXIO_I2S_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1 << base->txShifterIndex, enable);
}
/*!
* @brief Enables/disables the FlexIO I2S Rx DMA requests.
*
* @param base FlexIO I2S base pointer
* @param enable True means enable DMA, false means disable DMA.
*/
static inline void FLEXIO_I2S_RxEnableDMA(FLEXIO_I2S_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1 << base->rxShifterIndex, enable);
}
/*!
* @brief Gets the FlexIO I2S send data register address.
*
* This function returns the I2S data register address, mainly used by DMA/eDMA.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @return FlexIO i2s send data register address.
*/
static inline uint32_t FLEXIO_I2S_TxGetDataRegisterAddress(FLEXIO_I2S_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped, base->txShifterIndex);
}
/*!
* @brief Gets the FlexIO I2S receive data register address.
*
* This function returns the I2S data register address, mainly used by DMA/eDMA.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @return FlexIO i2s receive data register address.
*/
static inline uint32_t FLEXIO_I2S_RxGetDataRegisterAddress(FLEXIO_I2S_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped, base->rxShifterIndex);
}
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Configures the FlexIO I2S audio format in master mode.
*
* Audio format can be changed in run-time of FlexIO I2S. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @param format Pointer to FlexIO I2S audio data format structure.
* @param srcClock_Hz I2S master clock source frequency in Hz.
*/
void FLEXIO_I2S_MasterSetFormat(FLEXIO_I2S_Type *base, flexio_i2s_format_t *format, uint32_t srcClock_Hz);
/*!
* @brief Configures the FlexIO I2S audio format in slave mode.
*
* Audio format can be changed in run-time of FlexIO I2S. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @param format Pointer to FlexIO I2S audio data format structure.
*/
void FLEXIO_I2S_SlaveSetFormat(FLEXIO_I2S_Type *base, flexio_i2s_format_t *format);
/*!
* @brief Sends a piece of data using a blocking method.
*
* @note This function blocks via polling until data is ready to be sent.
*
* @param base FlexIO I2S base pointer.
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param txData Pointer to the data to be written.
* @param size Bytes to be written.
*/
void FLEXIO_I2S_WriteBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *txData, size_t size);
/*!
* @brief Writes a data into data register.
*
* @param base FlexIO I2S base pointer.
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param data Data to be written.
*/
static inline void FLEXIO_I2S_WriteData(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint32_t data)
{
base->flexioBase->SHIFTBUFBIS[base->txShifterIndex] = (data << (32U - bitWidth));
}
/*!
* @brief Receives a piece of data using a blocking method.
*
* @note This function blocks via polling until data is ready to be sent.
*
* @param base FlexIO I2S base pointer
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param rxData Pointer to the data to be read.
* @param size Bytes to be read.
*/
void FLEXIO_I2S_ReadBlocking(FLEXIO_I2S_Type *base, uint8_t bitWidth, uint8_t *rxData, size_t size);
/*!
* @brief Reads a data from the data register.
*
* @param base FlexIO I2S base pointer
* @return Data read from data register.
*/
static inline uint32_t FLEXIO_I2S_ReadData(FLEXIO_I2S_Type *base)
{
return base->flexioBase->SHIFTBUFBIS[base->rxShifterIndex];
}
/*! @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO I2S handle.
*
* This function initializes the FlexIO I2S handle which can be used for other
* FlexIO I2S transactional APIs. Call this API once to get the
* initialized handle.
*
* @param base pointer to FLEXIO_I2S_Type structure
* @param handle pointer to flexio_i2s_handle_t structure to store the transfer state.
* @param callback FlexIO I2S callback function, which is called while finished a block.
* @param userData User parameter for the FlexIO I2S callback.
*/
void FLEXIO_I2S_TransferTxCreateHandle(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_callback_t callback,
void *userData);
/*!
* @brief Configures the FlexIO I2S audio format.
*
* Audio format can be changed in run-time of FlexIO i2s. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle FlexIO I2S handle pointer.
* @param format Pointer to audio data format structure.
* @param srcClock_Hz FlexIO I2S bit clock source frequency in Hz. This parameter should be 0 while in slave mode.
*/
void FLEXIO_I2S_TransferSetFormat(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_format_t *format,
uint32_t srcClock_Hz);
/*!
* @brief Initializes the FlexIO I2S receive handle.
*
* This function initializes the FlexIO I2S handle which can be used for other
* FlexIO I2S transactional APIs. Usually, user only need to call this API once to get the
* initialized handle.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure to store the transfer state.
* @param callback FlexIO I2S callback function, which is called while finished a block.
* @param userData User parameter for the FlexIO I2S callback.
*/
void FLEXIO_I2S_TransferRxCreateHandle(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_callback_t callback,
void *userData);
/*!
* @brief Performs an interrupt non-blocking send transfer on FlexIO I2S.
*
* @note Calling the API returns immediately after transfer initiates.
* Call FLEXIO_I2S_GetRemainingBytes to poll the transfer status and check whether
* the transfer is finished. If the return status is 0, the transfer is finished.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure which stores the transfer state
* @param xfer pointer to flexio_i2s_transfer_t structure
* @retval kStatus_Success Successfully start the data transmission.
* @retval kStatus_FLEXIO_I2S_TxBusy Previous transmission still not finished, data not all written to TX register yet.
* @retval kStatus_InvalidArgument The input parameter is invalid.
*/
status_t FLEXIO_I2S_TransferSendNonBlocking(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_transfer_t *xfer);
/*!
* @brief Performs an interrupt non-blocking receive transfer on FlexIO I2S.
*
* @note The API returns immediately after transfer initiates.
* Call FLEXIO_I2S_GetRemainingBytes to poll the transfer status to check whether
* the transfer is finished. If the return status is 0, the transfer is finished.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure which stores the transfer state
* @param xfer pointer to flexio_i2s_transfer_t structure
* @retval kStatus_Success Successfully start the data receive.
* @retval kStatus_FLEXIO_I2S_RxBusy Previous receive still not finished.
* @retval kStatus_InvalidArgument The input parameter is invalid.
*/
status_t FLEXIO_I2S_TransferReceiveNonBlocking(FLEXIO_I2S_Type *base,
flexio_i2s_handle_t *handle,
flexio_i2s_transfer_t *xfer);
/*!
* @brief Aborts the current send.
*
* @note This API can be called at any time when interrupt non-blocking transfer initiates
* to abort the transfer in a early time.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure which stores the transfer state
*/
void FLEXIO_I2S_TransferAbortSend(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle);
/*!
* @brief Aborts the current receive.
*
* @note This API can be called at any time when interrupt non-blocking transfer initiates
* to abort the transfer in a early time.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure which stores the transfer state
*/
void FLEXIO_I2S_TransferAbortReceive(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle);
/*!
* @brief Gets the remaining bytes to be sent.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure which stores the transfer state
* @param count Bytes sent.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t FLEXIO_I2S_TransferGetSendCount(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle, size_t *count);
/*!
* @brief Gets the remaining bytes to be received.
*
* @param base pointer to FLEXIO_I2S_Type structure.
* @param handle pointer to flexio_i2s_handle_t structure which stores the transfer state
* @return count Bytes received.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t FLEXIO_I2S_TransferGetReceiveCount(FLEXIO_I2S_Type *base, flexio_i2s_handle_t *handle, size_t *count);
/*!
* @brief Tx interrupt handler.
*
* @param i2sBase pointer to FLEXIO_I2S_Type structure.
* @param i2sHandle pointer to flexio_i2s_handle_t structure
*/
void FLEXIO_I2S_TransferTxHandleIRQ(void *i2sBase, void *i2sHandle);
/*!
* @brief Rx interrupt handler.
*
* @param i2sBase pointer to FLEXIO_I2S_Type structure.
* @param i2sHandle pointer to flexio_i2s_handle_t structure
*/
void FLEXIO_I2S_TransferRxHandleIRQ(void *i2sBase, void *i2sHandle);
/*! @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /* _FSL_FLEXIO_I2S_H_ */

View File

@ -0,0 +1,339 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_i2s_dma.h"
/*******************************************************************************
* Definitations
******************************************************************************/
/*<! Structure definition for flexio_i2s_dma_private_handle_t. The structure is private. */
typedef struct _flexio_i2s_dma_private_handle
{
FLEXIO_I2S_Type *base;
flexio_i2s_dma_handle_t *handle;
} flexio_i2s_dma_private_handle_t;
enum _flexio_i2s_dma_transfer_state
{
kFLEXIO_I2S_Busy = 0x0U, /*!< FLEXIO I2S is busy */
kFLEXIO_I2S_Idle, /*!< Transfer is done. */
};
/*<! Private handle only used for internally. */
static flexio_i2s_dma_private_handle_t s_dmaPrivateHandle[2];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief FLEXIO I2S DMA callback for send.
*
* @param handle pointer to flexio_i2s_dma_handle_t structure which stores the transfer state.
* @param userData Parameter for user callback.
*/
static void FLEXIO_I2S_TxDMACallback(dma_handle_t *handle, void *userData);
/*!
* @brief FLEXIO I2S DMA callback for receive.
*
* @param handle pointer to flexio_i2s_dma_handle_t structure which stores the transfer state.
* @param userData Parameter for user callback.
*/
static void FLEXIO_I2S_RxDMACallback(dma_handle_t *handle, void *userData);
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_I2S_TxDMACallback(dma_handle_t *handle, void *userData)
{
flexio_i2s_dma_private_handle_t *privHandle = (flexio_i2s_dma_private_handle_t *)userData;
flexio_i2s_dma_handle_t *flexio_i2sHandle = privHandle->handle;
/* If finished a blcok, call the callback function */
memset(&flexio_i2sHandle->queue[flexio_i2sHandle->queueDriver], 0, sizeof(flexio_i2s_transfer_t));
flexio_i2sHandle->queueDriver = (flexio_i2sHandle->queueDriver + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
if (flexio_i2sHandle->callback)
{
(flexio_i2sHandle->callback)(privHandle->base, flexio_i2sHandle, kStatus_Success, flexio_i2sHandle->userData);
}
/* If all data finished, just stop the transfer */
if (flexio_i2sHandle->queue[flexio_i2sHandle->queueDriver].data == NULL)
{
FLEXIO_I2S_TransferAbortSendDMA(privHandle->base, flexio_i2sHandle);
}
}
static void FLEXIO_I2S_RxDMACallback(dma_handle_t *handle, void *userData)
{
flexio_i2s_dma_private_handle_t *privHandle = (flexio_i2s_dma_private_handle_t *)userData;
flexio_i2s_dma_handle_t *flexio_i2sHandle = privHandle->handle;
/* If finished a blcok, call the callback function */
memset(&flexio_i2sHandle->queue[flexio_i2sHandle->queueDriver], 0, sizeof(flexio_i2s_transfer_t));
flexio_i2sHandle->queueDriver = (flexio_i2sHandle->queueDriver + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
if (flexio_i2sHandle->callback)
{
(flexio_i2sHandle->callback)(privHandle->base, flexio_i2sHandle, kStatus_Success, flexio_i2sHandle->userData);
}
/* If all data finished, just stop the transfer */
if (flexio_i2sHandle->queue[flexio_i2sHandle->queueDriver].data == NULL)
{
FLEXIO_I2S_TransferAbortReceiveDMA(privHandle->base, flexio_i2sHandle);
}
}
void FLEXIO_I2S_TransferTxCreateHandleDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_dma_callback_t callback,
void *userData,
dma_handle_t *dmaHandle)
{
assert(handle && dmaHandle);
/* Set flexio_i2s base to handle */
handle->dmaHandle = dmaHandle;
handle->callback = callback;
handle->userData = userData;
/* Set FLEXIO I2S state to idle */
handle->state = kFLEXIO_I2S_Idle;
s_dmaPrivateHandle[0].base = base;
s_dmaPrivateHandle[0].handle = handle;
/* Install callback for Tx dma channel */
DMA_SetCallback(dmaHandle, FLEXIO_I2S_TxDMACallback, &s_dmaPrivateHandle[0]);
}
void FLEXIO_I2S_TransferRxCreateHandleDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_dma_callback_t callback,
void *userData,
dma_handle_t *dmaHandle)
{
assert(handle && dmaHandle);
/* Set flexio_i2s base to handle */
handle->dmaHandle = dmaHandle;
handle->callback = callback;
handle->userData = userData;
/* Set FLEXIO I2S state to idle */
handle->state = kFLEXIO_I2S_Idle;
s_dmaPrivateHandle[1].base = base;
s_dmaPrivateHandle[1].handle = handle;
/* Install callback for Tx dma channel */
DMA_SetCallback(dmaHandle, FLEXIO_I2S_RxDMACallback, &s_dmaPrivateHandle[1]);
}
void FLEXIO_I2S_TransferSetFormatDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_format_t *format,
uint32_t srcClock_Hz)
{
assert(handle && format);
/* Configure the audio format to FLEXIO I2S registers */
if (srcClock_Hz != 0)
{
/* It is master */
FLEXIO_I2S_MasterSetFormat(base, format, srcClock_Hz);
}
else
{
FLEXIO_I2S_SlaveSetFormat(base, format);
}
/* Get the tranfer size from format, this should be used in DMA configuration */
handle->bytesPerFrame = format->bitWidth / 8U;
}
status_t FLEXIO_I2S_TransferSendDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle, flexio_i2s_transfer_t *xfer)
{
assert(handle && xfer);
dma_transfer_config_t config = {0};
uint32_t destAddr = FLEXIO_I2S_TxGetDataRegisterAddress(base) + (4U - handle->bytesPerFrame);
/* Check if input parameter invalid */
if ((xfer->data == NULL) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
if (handle->queue[handle->queueUser].data)
{
return kStatus_FLEXIO_I2S_QueueFull;
}
/* Change the state of handle */
handle->state = kFLEXIO_I2S_Busy;
/* Update the queue state */
handle->queue[handle->queueUser].data = xfer->data;
handle->queue[handle->queueUser].dataSize = xfer->dataSize;
handle->transferSize[handle->queueUser] = xfer->dataSize;
handle->queueUser = (handle->queueUser + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
DMA_PrepareTransfer(&config, xfer->data, handle->bytesPerFrame, (void *)destAddr, handle->bytesPerFrame,
xfer->dataSize, kDMA_MemoryToPeripheral);
/* Configure DMA channel */
DMA_SubmitTransfer(handle->dmaHandle, &config, true);
/* Start DMA transfer */
DMA_StartTransfer(handle->dmaHandle);
/* Enable DMA enable bit */
FLEXIO_I2S_TxEnableDMA(base, true);
/* Enable FLEXIO I2S Tx clock */
FLEXIO_I2S_Enable(base, true);
return kStatus_Success;
}
status_t FLEXIO_I2S_TransferReceiveDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_transfer_t *xfer)
{
assert(handle && xfer);
dma_transfer_config_t config = {0};
uint32_t srcAddr = FLEXIO_I2S_RxGetDataRegisterAddress(base) - (4U - handle->bytesPerFrame);
/* Check if input parameter invalid */
if ((xfer->data == NULL) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
if (handle->queue[handle->queueUser].data)
{
return kStatus_FLEXIO_I2S_QueueFull;
}
/* Change the state of handle */
handle->state = kFLEXIO_I2S_Busy;
/* Update queue state */
handle->queue[handle->queueUser].data = xfer->data;
handle->queue[handle->queueUser].dataSize = xfer->dataSize;
handle->transferSize[handle->queueUser] = xfer->dataSize;
handle->queueUser = (handle->queueUser + 1) % FLEXIO_I2S_XFER_QUEUE_SIZE;
/* Prepare dma configure */
DMA_PrepareTransfer(&config, (void *)srcAddr, handle->bytesPerFrame, xfer->data, handle->bytesPerFrame,
xfer->dataSize, kDMA_PeripheralToMemory);
DMA_SubmitTransfer(handle->dmaHandle, &config, true);
/* Start DMA transfer */
DMA_StartTransfer(handle->dmaHandle);
/* Enable DMA enable bit */
FLEXIO_I2S_RxEnableDMA(base, true);
/* Enable FLEXIO I2S Rx clock */
FLEXIO_I2S_Enable(base, true);
return kStatus_Success;
}
void FLEXIO_I2S_TransferAbortSendDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle)
{
assert(handle);
/* Disable dma */
DMA_AbortTransfer(handle->dmaHandle);
/* Disable DMA enable bit */
FLEXIO_I2S_TxEnableDMA(base, false);
/* Set the handle state */
handle->state = kFLEXIO_I2S_Idle;
}
void FLEXIO_I2S_TransferAbortReceiveDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle)
{
assert(handle);
/* Disable dma */
DMA_AbortTransfer(handle->dmaHandle);
/* Disable DMA enable bit */
FLEXIO_I2S_RxEnableDMA(base, false);
/* Set the handle state */
handle->state = kFLEXIO_I2S_Idle;
}
status_t FLEXIO_I2S_TransferGetSendCountDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kFLEXIO_I2S_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
*count = handle->transferSize[handle->queueDriver] -
DMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel);
}
return status;
}
status_t FLEXIO_I2S_TransferGetReceiveCountDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kFLEXIO_I2S_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
*count = handle->transferSize[handle->queueDriver] -
DMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel);
}
return status;
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_I2S_DMA_H_
#define _FSL_FLEXIO_I2S_DMA_H_
#include "fsl_flexio_i2s.h"
#include "fsl_dma.h"
/*!
* @addtogroup flexio_dma_i2s
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
typedef struct _flexio_i2s_dma_handle flexio_i2s_dma_handle_t;
/*! @brief FlexIO I2S DMA transfer callback function for finish and error */
typedef void (*flexio_i2s_dma_callback_t)(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO I2S DMA transfer handle, users should not touch the content of the handle.*/
struct _flexio_i2s_dma_handle
{
dma_handle_t *dmaHandle; /*!< DMA handler for FlexIO I2S send */
uint8_t bytesPerFrame; /*!< Bytes in a frame */
uint32_t state; /*!< Internal state for FlexIO I2S DMA transfer */
flexio_i2s_dma_callback_t callback; /*!< Callback for users while transfer finish or error occurred */
void *userData; /*!< User callback parameter */
flexio_i2s_transfer_t queue[FLEXIO_I2S_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */
size_t transferSize[FLEXIO_I2S_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
volatile uint8_t queueUser; /*!< Index for user to queue transfer. */
volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name DMA Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO I2S DMA handle.
*
* This function initializes the FlexIO I2S master DMA handle which can be used for other FlexIO I2S master
* transactional APIs.
* Usually, for a specified FlexIO I2S instance, user need only call this API once to get the initialized handle.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
* @param callback FlexIO I2S DMA callback function called while finished a block.
* @param userData User parameter for callback.
* @param dmaHandle DMA handle for FlexIO I2S. This handle shall be a static value allocated by users.
*/
void FLEXIO_I2S_TransferTxCreateHandleDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_dma_callback_t callback,
void *userData,
dma_handle_t *dmaHandle);
/*!
* @brief Initializes the FlexIO I2S Rx DMA handle.
*
* This function initializes the FlexIO I2S slave DMA handle which can be used for other FlexIO I2S master transactional
* APIs.
* Usually, for a specified FlexIO I2S instance, user need only call this API once to get the initialized handle.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
* @param callback FlexIO I2S DMA callback function called while finished a block.
* @param userData User parameter for callback.
* @param dmaHandle DMA handle for FlexIO I2S. This handle shall be a static value allocated by users.
*/
void FLEXIO_I2S_TransferRxCreateHandleDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_dma_callback_t callback,
void *userData,
dma_handle_t *dmaHandle);
/*!
* @brief Configures the FlexIO I2S Tx audio format.
*
* Audio format can be changed in run-time of FlexIO I2S. This function configures the sample rate and audio data
* format to be transferred. This function also sets DMA parameter according to format.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer
* @param format Pointer to FlexIO I2S audio data format structure.
* @param srcClock_Hz FlexIO I2S clock source frequency in Hz. It should be 0 while in slave mode.
* @retval kStatus_Success Audio format set successfully.
* @retval kStatus_InvalidArgument The input arguments is invalid.
*/
void FLEXIO_I2S_TransferSetFormatDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_format_t *format,
uint32_t srcClock_Hz);
/*!
* @brief Performs a non-blocking FlexIO I2S transfer using DMA.
*
* @note This interface returns immediately after transfer initiates. Call
* FLEXIO_I2S_GetTransferStatus to poll the transfer status and check whether FLEXIO I2S transfer finished.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
* @param xfer Pointer to DMA transfer structure.
* @retval kStatus_Success Start a FlexIO I2S DMA send successfully.
* @retval kStatus_InvalidArgument The input arguments is invalid.
* @retval kStatus_TxBusy FlexIO I2S is busy sending data.
*/
status_t FLEXIO_I2S_TransferSendDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_transfer_t *xfer);
/*!
* @brief Performs a non-blocking FlexIO I2S receive using DMA.
*
* @note This interface returns immediately after transfer initiates. Call
* FLEXIO_I2S_GetReceiveRemainingBytes to poll the transfer status to check whether the FlexIO I2S transfer is finished.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
* @param xfer Pointer to DMA transfer structure.
* @retval kStatus_Success Start a FlexIO I2S DMA receive successfully.
* @retval kStatus_InvalidArgument The input arguments is invalid.
* @retval kStatus_RxBusy FlexIO I2S is busy receiving data.
*/
status_t FLEXIO_I2S_TransferReceiveDMA(FLEXIO_I2S_Type *base,
flexio_i2s_dma_handle_t *handle,
flexio_i2s_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO I2S transfer using DMA.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
*/
void FLEXIO_I2S_TransferAbortSendDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle);
/*!
* @brief Aborts a FlexIO I2S receive using DMA.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
*/
void FLEXIO_I2S_TransferAbortReceiveDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle);
/*!
* @brief Gets the remaining bytes to be sent.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
* @param count Bytes sent.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t FLEXIO_I2S_TransferGetSendCountDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle, size_t *count);
/*!
* @brief Gets the remaining bytes to be received.
*
* @param base FlexIO I2S peripheral base address.
* @param handle FlexIO I2S DMA handle pointer.
* @param count Bytes received.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t FLEXIO_I2S_TransferGetReceiveCountDMA(FLEXIO_I2S_Type *base, flexio_i2s_dma_handle_t *handle, size_t *count);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif

View File

@ -0,0 +1,935 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_spi.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief FLEXIO SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
enum _flexio_spi_transfer_states
{
kFLEXIO_SPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver's queue. */
kFLEXIO_SPI_Busy, /*!< Transmiter/Receive's queue is not finished. */
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Send a piece of data for SPI.
*
* This function computes the number of data to be written into D register or Tx FIFO,
* and write the data into it. At the same time, this function updates the values in
* master handle structure.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param handle Pointer to SPI master handle structure.
*/
static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*!
* @brief Receive a piece of data for SPI master.
*
* This function computes the number of data to receive from D register or Rx FIFO,
* and write the data to destination address. At the same time, this function updates
* the values in master handle structure.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param handle Pointer to SPI master handle structure.
*/
static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Codes
******************************************************************************/
static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
{
uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
if (handle->txData != NULL)
{
/* Transmit data and update tx size/buff. */
if (handle->bytePerFrame == 1U)
{
tmpData = *(handle->txData);
handle->txData++;
}
else
{
tmpData = (uint32_t)(handle->txData[0]) << 8U;
tmpData += handle->txData[1];
handle->txData += 2U;
}
}
else
{
tmpData = FLEXIO_SPI_DUMMYDATA;
}
handle->txRemainingBytes -= handle->bytePerFrame;
FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
if (!handle->txRemainingBytes)
{
FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
}
}
static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
{
uint16_t tmpData;
tmpData = FLEXIO_SPI_ReadData(base, handle->direction);
if (handle->rxData != NULL)
{
if (handle->bytePerFrame == 1U)
{
*handle->rxData = tmpData;
handle->rxData++;
}
else
{
*((uint16_t *)(handle->rxData)) = tmpData;
handle->rxData += 2U;
}
}
handle->rxRemainingBytes -= handle->bytePerFrame;
}
void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz)
{
assert(base);
assert(masterConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t ctrlReg = 0;
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
/* Clear the shifterConfig & timerConfig struct. */
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
/* Ungate flexio clock. */
CLOCK_EnableClock(kCLOCK_Flexio0);
/* Configure FLEXIO SPI Master */
ctrlReg = base->flexioBase->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DOZEN(masterConfig->enableInDoze) | FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) |
FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) | FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
base->flexioBase->CTRL = ctrlReg;
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinSelect = base->SDOPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/* 2. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->SDIPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/*3. Configure the timer 0 for SCK. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
timerConfig.pinSelect = base->SCKPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerDiv = srcClock_Hz / masterConfig->baudRate_Bps;
timerDiv = timerDiv / 2 - 1;
timerCmp = ((uint32_t)(masterConfig->dataMode * 2 - 1U)) << 8U;
timerCmp |= timerDiv;
timerConfig.timerCompare = timerCmp;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
/* 4. Configure the timer 1 for CSn. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->timerIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
timerConfig.pinSelect = base->CSnPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
timerConfig.timerCompare = 0xFFFFU;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
}
void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base)
{
/* Disable FLEXIO SPI module. */
FLEXIO_SPI_Enable(base, false);
/* Gate flexio clock. */
CLOCK_DisableClock(kCLOCK_Flexio0);
}
void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig)
{
assert(masterConfig);
masterConfig->enableMaster = true;
masterConfig->enableInDoze = false;
masterConfig->enableInDebug = true;
masterConfig->enableFastAccess = false;
/* Default baud rate 500kbps. */
masterConfig->baudRate_Bps = 500000U;
/* Default CPHA = 0. */
masterConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
/* Default bit count at 8. */
masterConfig->dataMode = kFLEXIO_SPI_8BitMode;
}
void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig)
{
assert(base && slaveConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t ctrlReg = 0;
/* Clear the shifterConfig & timerConfig struct. */
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
/* Ungate flexio clock. */
CLOCK_EnableClock(kCLOCK_Flexio0);
/* Configure FLEXIO SPI Slave */
ctrlReg = base->flexioBase->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DOZEN(slaveConfig->enableInDoze) | FLEXIO_CTRL_DBGE(slaveConfig->enableInDebug) |
FLEXIO_CTRL_FASTACC(slaveConfig->enableFastAccess) | FLEXIO_CTRL_FLEXEN(slaveConfig->enableSlave));
base->flexioBase->CTRL = ctrlReg;
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinSelect = base->SDOPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/* 2. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->SDIPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/*3. Configure the timer 0 for shift clock. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->CSnPinIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->SCKPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
/* The configuration kFLEXIO_TimerDisableOnTimerCompare only support continuous
PCS access, change to kFLEXIO_TimerDisableNever to enable discontinuous PCS access. */
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
}
else
{
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTriggerFallingEdge;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
}
timerConfig.timerCompare = slaveConfig->dataMode * 2 - 1U;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
}
void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base)
{
FLEXIO_SPI_MasterDeinit(base);
}
void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig)
{
assert(slaveConfig);
slaveConfig->enableSlave = true;
slaveConfig->enableInDoze = false;
slaveConfig->enableInDebug = true;
slaveConfig->enableFastAccess = false;
/* Default CPHA = 0. */
slaveConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
/* Default bit count at 8. */
slaveConfig->dataMode = kFLEXIO_SPI_8BitMode;
}
void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
}
if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
}
}
void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
}
if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
}
}
void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable)
{
if (mask & kFLEXIO_SPI_TxDmaEnable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[0], enable);
}
if (mask & kFLEXIO_SPI_RxDmaEnable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[1], enable);
}
}
uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base)
{
uint32_t shifterStatus = FLEXIO_GetShifterStatusFlags(base->flexioBase);
uint32_t status = 0;
status = ((shifterStatus & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
status |= (((shifterStatus & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 1U);
return status;
}
void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_SPI_TxBufferEmptyFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_SPI_RxBufferFullFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz)
{
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
FLEXIO_Type *flexioBase = base->flexioBase;
/* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
timerDiv = srcClockHz / baudRate_Bps;
timerDiv = timerDiv / 2 - 1U;
timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0xFF00U;
timerCmp |= timerDiv;
flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
}
void FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
const uint8_t *buffer,
size_t size)
{
assert(buffer);
assert(size);
while (size--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
{
}
FLEXIO_SPI_WriteData(base, direction, *buffer++);
}
}
void FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
uint8_t *buffer,
size_t size)
{
assert(buffer);
assert(size);
while (size--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
{
}
*buffer++ = FLEXIO_SPI_ReadData(base, direction);
}
}
void FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer)
{
flexio_spi_shift_direction_t direction;
uint8_t bytesPerFrame;
uint32_t dataMode = 0;
uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
timerCmp &= 0x00FFU;
/* Configure the values in handle. */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
dataMode = (8 * 2 - 1U) << 8U;
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
dataMode = (8 * 2 - 1U) << 8U;
bytesPerFrame = 1;
direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
dataMode = (16 * 2 - 1U) << 8U;
bytesPerFrame = 2;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
dataMode = (16 * 2 - 1U) << 8U;
bytesPerFrame = 2;
direction = kFLEXIO_SPI_LsbFirst;
break;
default:
dataMode = (8 * 2 - 1U) << 8U;
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
dataMode |= timerCmp;
/* Configure transfer size. */
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
while (xfer->dataSize)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
{
}
if (xfer->txData != NULL)
{
/* Transmit data and update tx size/buff. */
if (bytesPerFrame == 1U)
{
tmpData = *(xfer->txData);
xfer->txData++;
}
else
{
tmpData = (uint32_t)(xfer->txData[0]) << 8U;
tmpData += xfer->txData[1];
xfer->txData += 2U;
}
}
else
{
tmpData = FLEXIO_SPI_DUMMYDATA;
}
xfer->dataSize -= bytesPerFrame;
FLEXIO_SPI_WriteData(base, direction, tmpData);
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
{
}
tmpData = FLEXIO_SPI_ReadData(base, direction);
if (xfer->rxData != NULL)
{
if (bytesPerFrame == 1U)
{
*xfer->rxData = tmpData;
xfer->rxData++;
}
else
{
*((uint16_t *)(xfer->rxData)) = tmpData;
xfer->rxData += 2U;
}
}
}
}
status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_master_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[0]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_MasterTransferHandleIRQ);
}
status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
timerCmp &= 0x00FFU;
/* Check if SPI is busy. */
if (handle->state == kFLEXIO_SPI_Busy)
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if the argument is legal. */
if ((xfer->txData == NULL) && (xfer->rxData == NULL))
{
return kStatus_InvalidArgument;
}
/* Configure the values in handle */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
dataMode = (8 * 2 - 1U) << 8U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
dataMode = (8 * 2 - 1U) << 8U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
dataMode = (16 * 2 - 1U) << 8U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
dataMode = (16 * 2 - 1U) << 8U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
default:
dataMode = (8 * 2 - 1U) << 8U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
dataMode |= timerCmp;
/* Configure transfer size. */
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
handle->state = kFLEXIO_SPI_Busy;
handle->txData = xfer->txData;
handle->rxData = xfer->rxData;
handle->rxRemainingBytes = xfer->dataSize;
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Send first byte of data to trigger the rx interrupt. */
if (handle->txData != NULL)
{
/* Transmit data and update tx size/buff. */
if (handle->bytePerFrame == 1U)
{
tmpData = *(handle->txData);
handle->txData++;
}
else
{
tmpData = (uint32_t)(handle->txData[0]) << 8U;
tmpData += handle->txData[1];
handle->txData += 2U;
}
}
else
{
tmpData = FLEXIO_SPI_DUMMYDATA;
}
handle->txRemainingBytes = xfer->dataSize - handle->bytePerFrame;
FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
/* Enable transmit and receive interrupt to handle rx. */
FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
return kStatus_Success;
}
status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_InvalidArgument;
}
/* Return remaing bytes in different cases. */
if (handle->rxData)
{
*count = handle->transferSize - handle->rxRemainingBytes;
}
else
{
*count = handle->transferSize - handle->txRemainingBytes;
}
return kStatus_Success;
}
void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
{
assert(handle);
FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
/* Transfer finished, set the state to idle. */
handle->state = kFLEXIO_SPI_Idle;
/* Clear the internal state. */
handle->rxRemainingBytes = 0;
handle->txRemainingBytes = 0;
}
void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle)
{
assert(spiHandle);
flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
FLEXIO_SPI_Type *base;
uint32_t status;
if (handle->state == kFLEXIO_SPI_Idle)
{
return;
}
base = (FLEXIO_SPI_Type *)spiType;
status = FLEXIO_SPI_GetStatusFlags(base);
/* Handle rx. */
if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
{
FLEXIO_SPI_TransferReceiveTransaction(base, handle);
}
/* Handle tx. */
if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
{
FLEXIO_SPI_TransferSendTransaction(base, handle);
}
/* All the transfer finished. */
if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
{
FLEXIO_SPI_MasterTransferAbort(base, handle);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
}
}
}
status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_slave_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[0]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_SlaveTransferHandleIRQ);
}
status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
/* Check if SPI is busy. */
if (handle->state == kFLEXIO_SPI_Busy)
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if the argument is legal. */
if ((xfer->txData == NULL) && (xfer->rxData == NULL))
{
return kStatus_InvalidArgument;
}
/* Configure the values in handle */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
dataMode = 8 * 2 - 1U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
dataMode = 8 * 2 - 1U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
dataMode = 16 * 2 - 1U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
dataMode = 16 * 2 - 1U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
default:
dataMode = 8 * 2 - 1U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
/* Configure transfer size. */
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
handle->state = kFLEXIO_SPI_Busy;
handle->txData = xfer->txData;
handle->rxData = xfer->rxData;
handle->txRemainingBytes = xfer->dataSize;
handle->rxRemainingBytes = xfer->dataSize;
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Enable transmit and receive interrupt to handle tx and rx. */
FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
return kStatus_Success;
}
void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle)
{
assert(spiHandle);
flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
FLEXIO_SPI_Type *base;
uint32_t status;
if (handle->state == kFLEXIO_SPI_Idle)
{
return;
}
base = (FLEXIO_SPI_Type *)spiType;
status = FLEXIO_SPI_GetStatusFlags(base);
/* Handle tx. */
if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
{
FLEXIO_SPI_TransferSendTransaction(base, handle);
}
/* Handle rx. */
if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
{
FLEXIO_SPI_TransferReceiveTransaction(base, handle);
}
/* All the transfer finished. */
if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
{
FLEXIO_SPI_SlaveTransferAbort(base, handle);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
}
}
}

View File

@ -0,0 +1,708 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_SPI_H_
#define _FSL_FLEXIO_SPI_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_spi
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO SPI driver version 2.1.0. */
#define FSL_FLEXIO_SPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*! @brief FlexIO SPI dummy transfer data, the data is sent while txData is NULL. */
#define FLEXIO_SPI_DUMMYDATA (0xFFFFU)
/*! @brief Error codes for the FlexIO SPI driver. */
enum _flexio_spi_status
{
kStatus_FLEXIO_SPI_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 1), /*!< FlexIO SPI is busy. */
kStatus_FLEXIO_SPI_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 2), /*!< SPI is idle */
kStatus_FLEXIO_SPI_Error = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 3), /*!< FlexIO SPI error. */
};
/*! @brief FlexIO SPI clock phase configuration. */
typedef enum _flexio_spi_clock_phase
{
kFLEXIO_SPI_ClockPhaseFirstEdge = 0x0U, /*!< First edge on SPSCK occurs at the middle of the first
* cycle of a data transfer. */
kFLEXIO_SPI_ClockPhaseSecondEdge = 0x1U, /*!< First edge on SPSCK occurs at the start of the
* first cycle of a data transfer. */
} flexio_spi_clock_phase_t;
/*! @brief FlexIO SPI data shifter direction options. */
typedef enum _flexio_spi_shift_direction
{
kFLEXIO_SPI_MsbFirst = 0, /*!< Data transfers start with most significant bit. */
kFLEXIO_SPI_LsbFirst = 1, /*!< Data transfers start with least significant bit. */
} flexio_spi_shift_direction_t;
/*! @brief FlexIO SPI data length mode options. */
typedef enum _flexio_spi_data_bitcount_mode
{
kFLEXIO_SPI_8BitMode = 0x08U, /*!< 8-bit data transmission mode. */
kFLEXIO_SPI_16BitMode = 0x10U, /*!< 16-bit data transmission mode. */
} flexio_spi_data_bitcount_mode_t;
/*! @brief Define FlexIO SPI interrupt mask. */
enum _flexio_spi_interrupt_enable
{
kFLEXIO_SPI_TxEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_SPI_RxFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO SPI status mask. */
enum _flexio_spi_status_flags
{
kFLEXIO_SPI_TxBufferEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_SPI_RxBufferFullFlag = 0x2U, /*!< Receive buffer full flag. */
};
/*! @brief Define FlexIO SPI DMA mask. */
enum _flexio_spi_dma_enable
{
kFLEXIO_SPI_TxDmaEnable = 0x1U, /*!< Tx DMA request source */
kFLEXIO_SPI_RxDmaEnable = 0x2U, /*!< Rx DMA request source */
kFLEXIO_SPI_DmaAllEnable = 0x3U, /*!< All DMA request source*/
};
/*! @brief Define FlexIO SPI transfer flags. */
enum _flexio_spi_transfer_flags
{
kFLEXIO_SPI_8bitMsb = 0x1U, /*!< FlexIO SPI 8-bit MSB first */
kFLEXIO_SPI_8bitLsb = 0x2U, /*!< FlexIO SPI 8-bit LSB first */
kFLEXIO_SPI_16bitMsb = 0x9U, /*!< FlexIO SPI 16-bit MSB first */
kFLEXIO_SPI_16bitLsb = 0xaU, /*!< FlexIO SPI 16-bit LSB first */
};
/*! @brief Define FlexIO SPI access structure typedef. */
typedef struct _flexio_spi_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t SDOPinIndex; /*!< Pin select for data output. */
uint8_t SDIPinIndex; /*!< Pin select for data input. */
uint8_t SCKPinIndex; /*!< Pin select for clock. */
uint8_t CSnPinIndex; /*!< Pin select for enable. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO SPI. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO SPI. */
} FLEXIO_SPI_Type;
/*! @brief Define FlexIO SPI master configuration structure. */
typedef struct _flexio_spi_master_config
{
bool enableMaster; /*!< Enable/disable FlexIO SPI master after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
flexio_spi_clock_phase_t phase; /*!< Clock phase. */
flexio_spi_data_bitcount_mode_t dataMode; /*!< 8bit or 16bit mode. */
} flexio_spi_master_config_t;
/*! @brief Define FlexIO SPI slave configuration structure. */
typedef struct _flexio_spi_slave_config
{
bool enableSlave; /*!< Enable/disable FlexIO SPI slave after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
flexio_spi_clock_phase_t phase; /*!< Clock phase. */
flexio_spi_data_bitcount_mode_t dataMode; /*!< 8bit or 16bit mode. */
} flexio_spi_slave_config_t;
/*! @brief Define FlexIO SPI transfer structure. */
typedef struct _flexio_spi_transfer
{
uint8_t *txData; /*!< Send buffer. */
uint8_t *rxData; /*!< Receive buffer. */
size_t dataSize; /*!< Transfer bytes. */
uint8_t flags; /*!< FlexIO SPI control flag, MSB first or LSB first. */
} flexio_spi_transfer_t;
/*! @brief typedef for flexio_spi_master_handle_t in advance. */
typedef struct _flexio_spi_master_handle flexio_spi_master_handle_t;
/*! @brief Slave handle is the same with master handle. */
typedef flexio_spi_master_handle_t flexio_spi_slave_handle_t;
/*! @brief FlexIO SPI master callback for finished transmit */
typedef void (*flexio_spi_master_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI slave callback for finished transmit */
typedef void (*flexio_spi_slave_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO SPI handle structure. */
struct _flexio_spi_master_handle
{
uint8_t *txData; /*!< Transfer buffer. */
uint8_t *rxData; /*!< Receive buffer. */
size_t transferSize; /*!< Total bytes to be transferred. */
volatile size_t txRemainingBytes; /*!< Send data remaining in bytes. */
volatile size_t rxRemainingBytes; /*!< Receive data remaining in bytes. */
volatile uint32_t state; /*!< FlexIO SPI internal state. */
uint8_t bytePerFrame; /*!< SPI mode, 2bytes or 1byte in a frame */
flexio_spi_shift_direction_t direction; /*!< Shift direction. */
flexio_spi_master_transfer_callback_t callback; /*!< FlexIO SPI callback. */
void *userData; /*!< Callback parameter. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO SPI Configuration
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module and configures the FlexIO SPI master hardware,
* and configures the FlexIO SPI with FlexIO SPI master configuration. The
* configuration structure can be filled by the user, or be set with default values
* by the FLEXIO_SPI_MasterGetDefaultConfig().
*
* @note FlexIO SPI master only support CPOL = 0, which means clock inactive low.
*
* Example
@code
FLEXIO_SPI_Type spiDev = {
.flexioBase = FLEXIO,
.SDOPinIndex = 0,
.SDIPinIndex = 1,
.SCKPinIndex = 2,
.CSnPinIndex = 3,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_spi_master_config_t config = {
.enableMaster = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 500000,
.phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
.direction = kFLEXIO_SPI_MsbFirst,
.dataMode = kFLEXIO_SPI_8BitMode
};
FLEXIO_SPI_MasterInit(&spiDev, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param masterConfig Pointer to the flexio_spi_master_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
*/
void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief Gates the FlexIO clock.
*
* @param base Pointer to the FLEXIO_SPI_Type.
*/
void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO SPI master. The configuration
* can be used directly by calling the FLEXIO_SPI_MasterConfigure().
* Example:
@code
flexio_spi_master_config_t masterConfig;
FLEXIO_SPI_MasterGetDefaultConfig(&masterConfig);
@endcode
* @param masterConfig Pointer to the flexio_spi_master_config_t structure.
*/
void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig);
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI slave hardware
* configuration, and configures the FlexIO SPI with FlexIO SPI slave configuration. The
* configuration structure can be filled by the user, or be set with default values
* by the FLEXIO_SPI_SlaveGetDefaultConfig().
*
* @note Only one timer is needed in the FlexIO SPI slave. As a result, the second timer index is ignored.
* FlexIO SPI slave only support CPOL = 0, which means clock inactive low.
* Example
@code
FLEXIO_SPI_Type spiDev = {
.flexioBase = FLEXIO,
.SDOPinIndex = 0,
.SDIPinIndex = 1,
.SCKPinIndex = 2,
.CSnPinIndex = 3,
.shifterIndex = {0,1},
.timerIndex = {0}
};
flexio_spi_slave_config_t config = {
.enableSlave = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
.direction = kFLEXIO_SPI_MsbFirst,
.dataMode = kFLEXIO_SPI_8BitMode
};
FLEXIO_SPI_SlaveInit(&spiDev, &config);
@endcode
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
*/
void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig);
/*!
* @brief Gates the FlexIO clock.
*
* @param base Pointer to the FLEXIO_SPI_Type.
*/
void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO SPI slave. The configuration
* can be used directly for calling the FLEXIO_SPI_SlaveConfigure().
* Example:
@code
flexio_spi_slave_config_t slaveConfig;
FLEXIO_SPI_SlaveGetDefaultConfig(&slaveConfig);
@endcode
* @param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
*/
void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig);
/*@}*/
/*!
* @name Status
* @{
*/
/*!
* @brief Gets FlexIO SPI status flags.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @return status flag; Use the status flag to AND the following flag mask and get the status.
* @arg kFLEXIO_SPI_TxEmptyFlag
* @arg kFLEXIO_SPI_RxEmptyFlag
*/
uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base);
/*!
* @brief Clears FlexIO SPI status flags.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask status flag
* The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_TxEmptyFlag
* @arg kFLEXIO_SPI_RxEmptyFlag
*/
void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask);
/*@}*/
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO SPI interrupt.
*
* This function enables the FlexIO SPI interrupt.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask interrupt source. The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_RxFullInterruptEnable
* @arg kFLEXIO_SPI_TxEmptyInterruptEnable
*/
void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO SPI interrupt.
*
* This function disables the FlexIO SPI interrupt.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask interrupt source The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_RxFullInterruptEnable
* @arg kFLEXIO_SPI_TxEmptyInterruptEnable
*/
void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask);
/*@}*/
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables/disables the FlexIO SPI transmit DMA. This function enables/disables the FlexIO SPI Tx DMA,
* which means that asserting the kFLEXIO_SPI_TxEmptyFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask SPI DMA source.
* @param enable True means enable DMA, false means disable DMA.
*/
void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable);
/*!
* @brief Gets the FlexIO SPI transmit data register address for MSB first transfer.
*
* This function returns the SPI data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return FlexIO SPI transmit data register address.
*/
static inline uint32_t FLEXIO_SPI_GetTxDataRegisterAddress(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped,
base->shifterIndex[0]) +
3U;
}
else
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[0]);
}
}
/*!
* @brief Gets the FlexIO SPI receive data register address for the MSB first transfer.
*
* This function returns the SPI data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return FlexIO SPI receive data register address.
*/
static inline uint32_t FLEXIO_SPI_GetRxDataRegisterAddress(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped, base->shifterIndex[1]);
}
else
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferByteSwapped,
base->shifterIndex[1]);
}
}
/*@}*/
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables/disables the FlexIO SPI module operation.
*
* @param base Pointer to the FLEXIO_SPI_Type.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_SPI_Enable(FLEXIO_SPI_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*!
* @brief Sets baud rate for the FlexIO SPI transfer, which is only used for the master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param baudRate_Bps Baud Rate needed in Hz.
* @param srcClockHz SPI source clock frequency in Hz.
*/
void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz);
/*!
* @brief Writes one byte of data, which is sent using the MSB method.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register but the data transfer is not finished on the bus. Ensure that
* the TxEmptyFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param data 8 bit/16 bit data.
*/
static inline void FLEXIO_SPI_WriteData(FLEXIO_SPI_Type *base, flexio_spi_shift_direction_t direction, uint16_t data)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
}
else
{
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = data;
}
}
/*!
* @brief Reads 8 bit/16 bit data.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the RxFullFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return 8 bit/16 bit data received.
*/
static inline uint16_t FLEXIO_SPI_ReadData(FLEXIO_SPI_Type *base, flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]];
}
else
{
return base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
}
}
/*!
* @brief Sends a buffer of data bytes.
*
* @note This function blocks using the polling method until all bytes have been sent.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param buffer The data bytes to send.
* @param size The number of data bytes to send.
*/
void FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
const uint8_t *buffer,
size_t size);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks using the polling method until all bytes have been received.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param buffer The buffer to store the received bytes.
* @param size The number of data bytes to be received.
* @param direction Shift direction of MSB first or LSB first.
*/
void FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
uint8_t *buffer,
size_t size);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks via polling until all bytes have been received.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param xfer FlexIO SPI transfer structure, see #flexio_spi_transfer_t.
*/
void FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer);
/*Transactional APIs*/
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO SPI Master handle, which is used in transactional functions.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Master transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which returns
* right away. When all data is sent out/received, the callback function is called.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts the master data transfer, which used IRQ.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*!
* @brief Gets the data transfer status which used IRQ.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count);
/*!
* @brief FlexIO SPI master IRQ handler function.
*
* @param spiType Pointer to the FLEXIO_SPI_Type structure.
* @param spiHandle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle);
/*!
* @brief Initializes the FlexIO SPI Slave handle, which is used in transactional functions.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_slave_transfer_callback_t callback,
void *userData);
/*!
* @brief Slave transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which returns
* right away. When all data is sent out/received, the callback function is called.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy SPI is not idle; it is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts the slave data transfer which used IRQ, share same API with master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*/
static inline void FLEXIO_SPI_SlaveTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_slave_handle_t *handle)
{
FLEXIO_SPI_MasterTransferAbort(base, handle);
}
/*!
* @brief Gets the data transfer status which used IRQ, share same API with master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
static inline status_t FLEXIO_SPI_SlaveTransferGetCount(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
size_t *count)
{
return FLEXIO_SPI_MasterTransferGetCount(base, handle, count);
}
/*!
* @brief FlexIO SPI slave IRQ handler function.
*
* @param spiType Pointer to the FLEXIO_SPI_Type structure.
* @param spiHandle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle);
/*@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_SPI_H_*/

View File

@ -0,0 +1,415 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_spi_dma.h"
/*******************************************************************************
* Definitons
******************************************************************************/
/*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
typedef struct _flexio_spi_master_dma_private_handle
{
FLEXIO_SPI_Type *base;
flexio_spi_master_dma_handle_t *handle;
} flexio_spi_master_dma_private_handle_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief DMA callback function for FLEXIO SPI send transfer.
*
* @param handle DMA handle pointer.
* @param param Callback function parameter.
*/
static void FLEXIO_SPI_TxDMACallback(dma_handle_t *handle, void *param);
/*!
* @brief DMA callback function for FLEXIO SPI receive transfer.
*
* @param handle DMA handle pointer.
* @param param Callback function parameter.
*/
static void FLEXIO_SPI_RxDMACallback(dma_handle_t *handle, void *param);
/*!
* @brief EDMA config for FLEXIO SPI transfer.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_master_dma_handle_t structure to store the transfer state.
* @param xfer Pointer to flexio spi transfer structure.
*/
static void FLEXIO_SPI_DMAConfig(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*******************************************************************************
* Variables
******************************************************************************/
/* Dummy data used to send */
static const uint16_t s_dummyData = FLEXIO_SPI_DUMMYDATA;
/*< @brief user configurable flexio spi handle count. */
#define FLEXIO_SPI_HANDLE_COUNT 2
/*<! Private handle only used for internally. */
static flexio_spi_master_dma_private_handle_t s_dmaPrivateHandle[FLEXIO_SPI_HANDLE_COUNT];
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_SPI_TxDMACallback(dma_handle_t *handle, void *param)
{
flexio_spi_master_dma_private_handle_t *spiPrivateHandle = (flexio_spi_master_dma_private_handle_t *)param;
/* Disable Tx DMA. */
FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, kFLEXIO_SPI_TxDmaEnable, false);
/* Disable interrupt. */
DMA_DisableInterrupts(handle->base, handle->channel);
/* change the state. */
spiPrivateHandle->handle->txInProgress = false;
/* All finished, call the callback. */
if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
{
if (spiPrivateHandle->handle->callback)
{
(spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
spiPrivateHandle->handle->userData);
}
}
}
static void FLEXIO_SPI_RxDMACallback(dma_handle_t *handle, void *param)
{
flexio_spi_master_dma_private_handle_t *spiPrivateHandle = (flexio_spi_master_dma_private_handle_t *)param;
/* Disable Rx DMA. */
FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, kFLEXIO_SPI_RxDmaEnable, false);
/* Disable interrupt. */
DMA_DisableInterrupts(handle->base, handle->channel);
/* change the state. */
spiPrivateHandle->handle->rxInProgress = false;
/* All finished, call the callback. */
if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
{
if (spiPrivateHandle->handle->callback)
{
(spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
spiPrivateHandle->handle->userData);
}
}
}
static void FLEXIO_SPI_DMAConfig(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
dma_transfer_config_t xferConfig;
flexio_spi_shift_direction_t direction;
uint8_t bytesPerFrame;
/* Configure the values in handle. */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
bytesPerFrame = 1;
direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
bytesPerFrame = 2;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
bytesPerFrame = 2;
direction = kFLEXIO_SPI_LsbFirst;
break;
default:
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Configure tx transfer DMA. */
xferConfig.destAddr = FLEXIO_SPI_GetTxDataRegisterAddress(base, direction);
xferConfig.enableDestIncrement = false;
if (bytesPerFrame == 1U)
{
xferConfig.srcSize = kDMA_Transfersize8bits;
xferConfig.destSize = kDMA_Transfersize8bits;
}
else
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
xferConfig.destAddr -= 1U;
}
xferConfig.srcSize = kDMA_Transfersize16bits;
xferConfig.destSize = kDMA_Transfersize16bits;
}
/* Configure DMA channel. */
if (xfer->txData)
{
xferConfig.enableSrcIncrement = true;
xferConfig.srcAddr = (uint32_t)(xfer->txData);
}
else
{
/* Disable the source increasement and source set to dummyData. */
xferConfig.enableSrcIncrement = false;
xferConfig.srcAddr = (uint32_t)(&s_dummyData);
}
xferConfig.transferSize = xfer->dataSize;
if (handle->txHandle)
{
DMA_SubmitTransfer(handle->txHandle, &xferConfig, kDMA_EnableInterrupt);
}
/* Configure tx transfer DMA. */
if (xfer->rxData)
{
xferConfig.srcAddr = FLEXIO_SPI_GetRxDataRegisterAddress(base, direction);
xferConfig.enableSrcIncrement = false;
xferConfig.destAddr = (uint32_t)(xfer->rxData);
xferConfig.enableDestIncrement = true;
DMA_SubmitTransfer(handle->rxHandle, &xferConfig, kDMA_EnableInterrupt);
handle->rxInProgress = true;
FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_RxDmaEnable, true);
DMA_StartTransfer(handle->rxHandle);
}
/* Always start Tx transfer. */
if (handle->txHandle)
{
handle->txInProgress = true;
FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_TxDmaEnable, true);
DMA_StartTransfer(handle->txHandle);
}
}
status_t FLEXIO_SPI_MasterTransferCreateHandleDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
flexio_spi_master_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txHandle,
dma_handle_t *rxHandle)
{
assert(handle);
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0; index < FLEXIO_SPI_HANDLE_COUNT; index++)
{
if (s_dmaPrivateHandle[index].base == NULL)
{
s_dmaPrivateHandle[index].base = base;
s_dmaPrivateHandle[index].handle = handle;
break;
}
}
if (index == FLEXIO_SPI_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
/* Set spi base to handle. */
handle->txHandle = txHandle;
handle->rxHandle = rxHandle;
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Set SPI state to idle. */
handle->txInProgress = false;
handle->rxInProgress = false;
/* Install callback for Tx/Rx dma channel. */
if (handle->txHandle)
{
DMA_SetCallback(handle->txHandle, FLEXIO_SPI_TxDMACallback, &s_dmaPrivateHandle[index]);
}
if (handle->rxHandle)
{
DMA_SetCallback(handle->rxHandle, FLEXIO_SPI_RxDMACallback, &s_dmaPrivateHandle[index]);
}
return kStatus_Success;
}
status_t FLEXIO_SPI_MasterTransferDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0x00FFU;
/* Check if the device is busy. */
if ((handle->txInProgress) || (handle->rxInProgress))
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if input parameter invalid. */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* configure data mode. */
if ((xfer->flags == kFLEXIO_SPI_8bitMsb) || (xfer->flags == kFLEXIO_SPI_8bitLsb))
{
dataMode = (8 * 2 - 1U) << 8U;
}
else if ((xfer->flags == kFLEXIO_SPI_16bitMsb) || (xfer->flags == kFLEXIO_SPI_16bitLsb))
{
dataMode = (16 * 2 - 1U) << 8U;
}
else
{
dataMode = 8 * 2 - 1U;
}
dataMode |= timerCmp;
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
FLEXIO_SPI_DMAConfig(base, handle, xfer);
return kStatus_Success;
}
status_t FLEXIO_SPI_MasterTransferGetCountDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_InvalidArgument;
}
if (handle->rxInProgress)
{
*count = (handle->transferSize - DMA_GetRemainingBytes(handle->rxHandle->base, handle->rxHandle->channel));
}
else
{
*count = (handle->transferSize - DMA_GetRemainingBytes(handle->txHandle->base, handle->txHandle->channel));
}
return kStatus_Success;
}
void FLEXIO_SPI_MasterTransferAbortDMA(FLEXIO_SPI_Type *base, flexio_spi_master_dma_handle_t *handle)
{
assert(handle);
/* Disable dma. */
DMA_AbortTransfer(handle->txHandle);
DMA_AbortTransfer(handle->rxHandle);
/* Disable DMA enable bit. */
FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_DmaAllEnable, false);
/* Set the handle state. */
handle->txInProgress = false;
handle->rxInProgress = false;
}
status_t FLEXIO_SPI_SlaveTransferDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_dma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
/* Check if the device is busy. */
if ((handle->txInProgress) || (handle->rxInProgress))
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if input parameter invalid. */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* configure data mode. */
if ((xfer->flags == kFLEXIO_SPI_8bitMsb) || (xfer->flags == kFLEXIO_SPI_8bitLsb))
{
dataMode = 8 * 2 - 1U;
}
else if ((xfer->flags == kFLEXIO_SPI_16bitMsb) || (xfer->flags == kFLEXIO_SPI_16bitLsb))
{
dataMode = 16 * 2 - 1U;
}
else
{
dataMode = 8 * 2 - 1U;
}
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
FLEXIO_SPI_DMAConfig(base, handle, xfer);
return kStatus_Success;
}

View File

@ -0,0 +1,222 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_SPI_DMA_H_
#define _FSL_FLEXIO_SPI_DMA_H_
#include "fsl_flexio_spi.h"
#include "fsl_dma.h"
/*!
* @addtogroup flexio_dma_spi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief typedef for flexio_spi_master_dma_handle_t in advance. */
typedef struct _flexio_spi_master_dma_handle flexio_spi_master_dma_handle_t;
/*! @brief Slave handle is the same with master handle. */
typedef flexio_spi_master_dma_handle_t flexio_spi_slave_dma_handle_t;
/*! @brief FlexIO SPI master callback for finished transmit */
typedef void (*flexio_spi_master_dma_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI slave callback for finished transmit */
typedef void (*flexio_spi_slave_dma_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_slave_dma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI DMA transfer handle, users should not touch the content of the handle.*/
struct _flexio_spi_master_dma_handle
{
size_t transferSize; /*!< Total bytes to be transferred. */
bool txInProgress; /*!< Send transfer in progress */
bool rxInProgress; /*!< Receive transfer in progress */
dma_handle_t *txHandle; /*!< DMA handler for SPI send */
dma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
flexio_spi_master_dma_transfer_callback_t callback; /*!< Callback for SPI DMA transfer */
void *userData; /*!< User Data for SPI DMA callback */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name DMA Transactional
* @{
*/
/*!
* @brief Initializes the FLEXO SPI master DMA handle.
*
* This function initializes the FLEXO SPI master DMA handle which can be used for other FLEXO SPI master transactional
* APIs.
* Usually, for a specified FLEXO SPI instance, user need only call this API once to get the initialized handle.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_master_dma_handle_t structure to store the transfer state.
* @param callback SPI callback, NULL means no callback.
* @param userData callback function parameter.
* @param txHandle User requested DMA handle for FlexIO SPI RX DMA transfer.
* @param rxHandle User requested DMA handle for FlexIO SPI TX DMA transfer.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO SPI DMA type/handle table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandleDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
flexio_spi_master_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txHandle,
dma_handle_t *rxHandle);
/*!
* @brief Performs a non-blocking FlexIO SPI transfer using DMA.
*
* @note This interface returned immediately after transfer initiates, users could call
* FLEXIO_SPI_MasterGetTransferCountDMA to poll the transfer status to check
* whether FlexIO SPI transfer finished.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_master_dma_handle_t structure to store the transfer state.
* @param xfer Pointer to FlexIO SPI transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO SPI transfer using DMA.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI DMA handle pointer.
*/
void FLEXIO_SPI_MasterTransferAbortDMA(FLEXIO_SPI_Type *base, flexio_spi_master_dma_handle_t *handle);
/*!
* @brief Gets the remaining bytes for FlexIO SPI DMA transfer.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI DMA handle pointer.
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
status_t FLEXIO_SPI_MasterTransferGetCountDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_dma_handle_t *handle,
size_t *count);
/*!
* @brief Initializes the FlexIO SPI slave DMA handle.
*
* This function initializes the FlexIO SPI slave DMA handle.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_slave_dma_handle_t structure to store the transfer state.
* @param callback SPI callback, NULL means no callback.
* @param userData callback function parameter.
* @param txHandle User requested DMA handle for FlexIO SPI TX DMA transfer.
* @param rxHandle User requested DMA handle for FlexIO SPI RX DMA transfer.
*/
static inline void FLEXIO_SPI_SlaveTransferCreateHandleDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_dma_handle_t *handle,
flexio_spi_slave_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txHandle,
dma_handle_t *rxHandle)
{
FLEXIO_SPI_MasterTransferCreateHandleDMA(base, handle, callback, userData, txHandle, rxHandle);
}
/*!
* @brief Performs a non-blocking FlexIO SPI transfer using DMA.
*
* @note This interface returned immediately after transfer initiates, users could call
* FLEXIO_SPI_SlaveGetTransferCountDMA to poll the transfer status to
* check whether FlexIO SPI transfer finished.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_slave_dma_handle_t structure to store the transfer state.
* @param xfer Pointer to FlexIO SPI transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_dma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO SPI transfer using DMA.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_slave_dma_handle_t structure to store the transfer state.
*/
static inline void FLEXIO_SPI_SlaveTransferAbortDMA(FLEXIO_SPI_Type *base, flexio_spi_slave_dma_handle_t *handle)
{
FLEXIO_SPI_MasterTransferAbortDMA(base, handle);
}
/*!
* @brief Gets the remaining bytes to be transferred for FlexIO SPI DMA.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI DMA handle pointer.
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
static inline status_t FLEXIO_SPI_SlaveTransferGetCountDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_dma_handle_t *handle,
size_t *count)
{
return FLEXIO_SPI_MasterTransferGetCountDMA(base, handle, count);
}
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif

View File

@ -0,0 +1,690 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_uart.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! @brief uart transfer state. */
enum _flexio_uart_transfer_states
{
kFLEXIO_UART_TxIdle, /* TX idle. */
kFLEXIO_UART_TxBusy, /* TX busy. */
kFLEXIO_UART_RxIdle, /* RX idle. */
kFLEXIO_UART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the length of received data in RX ring buffer.
*
* @param handle FLEXIO UART handle pointer.
* @return Length of received data in RX ring buffer.
*/
static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle);
/*!
* @brief Check whether the RX ring buffer is full.
*
* @param handle FLEXIO UART handle pointer.
* @retval true RX ring buffer is full.
* @retval false RX ring buffer is not full.
*/
static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle);
/*******************************************************************************
* Codes
******************************************************************************/
static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle)
{
size_t size;
if (handle->rxRingBufferTail > handle->rxRingBufferHead)
{
size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);
}
else
{
size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);
}
return size;
}
static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle)
{
bool full;
if (FLEXIO_UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
{
full = true;
}
else
{
full = false;
}
return full;
}
void FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz)
{
assert(base && userConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t ctrlReg = 0;
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
/* Clear the shifterConfig & timerConfig struct. */
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
/* Ungate flexio clock. */
CLOCK_EnableClock(kCLOCK_Flexio0);
/* Reset FLEXIO before configuration. */
FLEXIO_Reset(base->flexioBase);
/* Configure FLEXIO UART */
ctrlReg = base->flexioBase->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DOZEN(userConfig->enableInDoze) | FLEXIO_CTRL_DBGE(userConfig->enableInDebug) |
FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) | FLEXIO_CTRL_FLEXEN(userConfig->enableUart));
base->flexioBase->CTRL = ctrlReg;
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinSelect = base->TxPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/*2. Configure the timer 0 for tx. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->TxPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerDiv = srcClock_Hz / userConfig->baudRate_Bps;
timerDiv = timerDiv / 2 - 1;
timerCmp = ((uint32_t)(userConfig->bitCountPerChar * 2 - 1)) << 8U;
timerCmp |= timerDiv;
timerConfig.timerCompare = timerCmp;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
/* 3. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[1];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->RxPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/* 4. Configure the timer 1 for rx. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->RxPinIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceExternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->RxPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinRisingEdge;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPinRisingEdge;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerConfig.timerCompare = timerCmp;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
}
void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base)
{
/* Disable FLEXIO UART module. */
FLEXIO_UART_Enable(base, false);
/* Gate flexio clock. */
CLOCK_DisableClock(kCLOCK_Flexio0);
}
void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig)
{
assert(userConfig);
userConfig->enableUart = true;
userConfig->enableInDoze = false;
userConfig->enableInDebug = true;
userConfig->enableFastAccess = false;
/* Default baud rate 115200. */
userConfig->baudRate_Bps = 115200U;
/* Default bit count at 8. */
userConfig->bitCountPerChar = kFLEXIO_UART_8BitsPerChar;
}
void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_UART_TxDataRegEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_UART_RxDataRegFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_UART_TxDataRegEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_UART_RxDataRegFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base)
{
uint32_t status = 0;
status =
((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
status |=
(((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 1U);
status |=
(((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 2U);
return status;
}
void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_UART_TxDataRegEmptyFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_UART_RxDataRegFullFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
if (mask & kFLEXIO_UART_RxOverRunFlag)
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize)
{
assert(txData);
assert(txSize);
while (txSize--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))
{
}
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *txData++;
}
}
void FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize)
{
assert(rxData);
assert(rxSize);
while (rxSize--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_UART_GetStatusFlags(base) & kFLEXIO_UART_RxDataRegFullFlag))
{
}
*rxData++ = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
}
}
status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Set the TX/RX state. */
handle->rxState = kFLEXIO_UART_RxIdle;
handle->txState = kFLEXIO_UART_TxIdle;
/* Set the callback and user data. */
handle->callback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[0]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_UART_TransferHandleIRQ);
}
void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize)
{
assert(handle);
/* Setup the ringbuffer address */
if (ringBuffer)
{
handle->rxRingBuffer = ringBuffer;
handle->rxRingBufferSize = ringBufferSize;
handle->rxRingBufferHead = 0U;
handle->rxRingBufferTail = 0U;
/* Enable the interrupt to accept the data when user need the ring buffer. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
}
void FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
{
assert(handle);
if (handle->rxState == kFLEXIO_UART_RxIdle)
{
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
handle->rxRingBuffer = NULL;
handle->rxRingBufferSize = 0U;
handle->rxRingBufferHead = 0U;
handle->rxRingBufferTail = 0U;
}
status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* Return error if current TX busy. */
if (kFLEXIO_UART_TxBusy == handle->txState)
{
status = kStatus_FLEXIO_UART_TxBusy;
}
else
{
handle->txData = xfer->data;
handle->txDataSize = xfer->dataSize;
handle->txState = kFLEXIO_UART_TxBusy;
/* Enable transmiter interrupt. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
status = kStatus_Success;
}
return status;
}
void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
{
/* Disable the transmitter and disable the interrupt. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
handle->txDataSize = 0;
handle->txState = kFLEXIO_UART_TxIdle;
}
status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_Success;
}
*count = handle->txSize - handle->txDataSize;
return kStatus_Success;
}
status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer,
size_t *receivedBytes)
{
uint32_t i;
status_t status;
/* How many bytes to copy from ring buffer to user memory. */
size_t bytesToCopy = 0U;
/* How many bytes to receive. */
size_t bytesToReceive;
/* How many bytes currently have received. */
size_t bytesCurrentReceived;
uint32_t regPrimask = 0U;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* How to get data:
1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
to uart handle, enable interrupt to store received data to xfer->data. When
all data received, trigger callback.
2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
If there are enough data in ring buffer, copy them to xfer->data and return.
If there are not enough data in ring buffer, copy all of them to xfer->data,
save the xfer->data remained empty space to uart handle, receive data
to this empty space and trigger callback when finished. */
if (kFLEXIO_UART_RxBusy == handle->rxState)
{
status = kStatus_FLEXIO_UART_RxBusy;
}
else
{
bytesToReceive = xfer->dataSize;
bytesCurrentReceived = 0U;
/* If RX ring buffer is used. */
if (handle->rxRingBuffer)
{
/* Disable IRQ, protect ring buffer. */
regPrimask = __get_PRIMASK();
__disable_irq();
/* How many bytes in RX ring buffer currently. */
bytesToCopy = FLEXIO_UART_TransferGetRxRingBufferLength(handle);
if (bytesToCopy)
{
bytesToCopy = MIN(bytesToReceive, bytesToCopy);
bytesToReceive -= bytesToCopy;
/* Copy data from ring buffer to user memory. */
for (i = 0U; i < bytesToCopy; i++)
{
xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
/* Wrap to 0. Not use modulo (%) because it might be large and slow. */
if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
}
/* If ring buffer does not have enough data, still need to read more data. */
if (bytesToReceive)
{
/* No data in ring buffer, save the request to UART handle. */
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxState = kFLEXIO_UART_RxBusy;
}
/* Recover PRIMASK, enable IRQ if previously enabled. */
__set_PRIMASK(regPrimask);
}
/* Ring buffer not used. */
else
{
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxState = kFLEXIO_UART_RxBusy;
/* Enable RX interrupt. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
/* Return the how many bytes have read. */
if (receivedBytes)
{
*receivedBytes = bytesCurrentReceived;
}
status = kStatus_Success;
}
return status;
}
void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
{
/* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
if (!handle->rxRingBuffer)
{
/* Disable RX interrupt. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
handle->rxDataSize = 0U;
handle->rxState = kFLEXIO_UART_RxIdle;
}
status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_Success;
}
*count = handle->rxSize - handle->rxDataSize;
return kStatus_Success;
}
void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle)
{
uint8_t count = 1;
FLEXIO_UART_Type *base = (FLEXIO_UART_Type *)uartType;
flexio_uart_handle_t *handle = (flexio_uart_handle_t *)uartHandle;
/* Read the status back. */
uint8_t status = FLEXIO_UART_GetStatusFlags(base);
/* If RX overrun. */
if (kFLEXIO_UART_RxOverRunFlag & status)
{
/* Clear Overrun flag. */
FLEXIO_UART_ClearStatusFlags(base, kFLEXIO_UART_RxOverRunFlag);
/* Trigger callback. */
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_RxHardwareOverrun, handle->userData);
}
}
/* Receive data register full */
if ((kFLEXIO_UART_RxDataRegFullFlag & status) && (base->flexioBase->SHIFTSIEN & (1U << base->shifterIndex[1])))
{
/* If handle->rxDataSize is not 0, first save data to handle->rxData. */
if (handle->rxDataSize)
{
/* Using non block API to read the data from the registers. */
FLEXIO_UART_ReadByte(base, handle->rxData);
handle->rxDataSize--;
handle->rxData++;
count--;
/* If all the data required for upper layer is ready, trigger callback. */
if (!handle->rxDataSize)
{
handle->rxState = kFLEXIO_UART_RxIdle;
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_RxIdle, handle->userData);
}
}
}
if (handle->rxRingBuffer)
{
if (count)
{
/* If RX ring buffer is full, trigger callback to notify over run. */
if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
{
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_RxRingBufferOverrun, handle->userData);
}
}
/* If ring buffer is still full after callback function, the oldest data is overrided. */
if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
{
/* Increase handle->rxRingBufferTail to make room for new data. */
if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
/* Read data. */
handle->rxRingBuffer[handle->rxRingBufferHead] = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
/* Increase handle->rxRingBufferHead. */
if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferHead = 0U;
}
else
{
handle->rxRingBufferHead++;
}
}
}
/* If no receive requst pending, stop RX interrupt. */
else if (!handle->rxDataSize)
{
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
else
{
}
}
/* Send data register empty and the interrupt is enabled. */
if ((kFLEXIO_UART_TxDataRegEmptyFlag & status) && (base->flexioBase->SHIFTSIEN & (1U << base->shifterIndex[0])))
{
if (handle->txDataSize)
{
/* Using non block API to write the data to the registers. */
FLEXIO_UART_WriteByte(base, handle->txData);
handle->txData++;
handle->txDataSize--;
count--;
/* If all the data are written to data register, TX finished. */
if (!handle->txDataSize)
{
handle->txState = kFLEXIO_UART_TxIdle;
/* Disable TX register empty interrupt. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
/* Trigger callback. */
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_TxIdle, handle->userData);
}
}
}
}
}

View File

@ -0,0 +1,586 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_UART_H_
#define _FSL_FLEXIO_UART_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_uart
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO UART driver version 2.1.0. */
#define FSL_FLEXIO_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*! @brief Error codes for the UART driver. */
enum _flexio_uart_status
{
kStatus_FLEXIO_UART_TxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 0), /*!< Transmitter is busy. */
kStatus_FLEXIO_UART_RxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 1), /*!< Receiver is busy. */
kStatus_FLEXIO_UART_TxIdle = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 2), /*!< UART transmitter is idle. */
kStatus_FLEXIO_UART_RxIdle = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 3), /*!< UART receiver is idle. */
kStatus_FLEXIO_UART_ERROR = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 4), /*!< ERROR happens on UART. */
kStatus_FLEXIO_UART_RxRingBufferOverrun =
MAKE_STATUS(kStatusGroup_FLEXIO_UART, 5), /*!< UART RX software ring buffer overrun. */
kStatus_FLEXIO_UART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 6) /*!< UART RX receiver overrun. */
};
/*! @brief FlexIO UART bit count per char. */
typedef enum _flexio_uart_bit_count_per_char
{
kFLEXIO_UART_7BitsPerChar = 7U, /*!< 7-bit data characters */
kFLEXIO_UART_8BitsPerChar = 8U, /*!< 8-bit data characters */
kFLEXIO_UART_9BitsPerChar = 9U, /*!< 9-bit data characters */
} flexio_uart_bit_count_per_char_t;
/*! @brief Define FlexIO UART interrupt mask. */
enum _flexio_uart_interrupt_enable
{
kFLEXIO_UART_TxDataRegEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_UART_RxDataRegFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO UART status mask. */
enum _flexio_uart_status_flags
{
kFLEXIO_UART_TxDataRegEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_UART_RxDataRegFullFlag = 0x2U, /*!< Receive buffer full flag. */
kFLEXIO_UART_RxOverRunFlag = 0x4U, /*!< Receive buffer over run flag. */
};
/*! @brief Define FlexIO UART access structure typedef. */
typedef struct _flexio_uart_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t TxPinIndex; /*!< Pin select for UART_Tx. */
uint8_t RxPinIndex; /*!< Pin select for UART_Rx. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO UART. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO UART. */
} FLEXIO_UART_Type;
/*! @brief Define FlexIO UART user configuration structure. */
typedef struct _flexio_uart_config
{
bool enableUart; /*!< Enable/disable FlexIO UART TX & RX. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode*/
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode*/
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
flexio_uart_bit_count_per_char_t bitCountPerChar; /*!< number of bits, 7/8/9 -bit */
} flexio_uart_config_t;
/*! @brief Define FlexIO UART transfer structure. */
typedef struct _flexio_uart_transfer
{
uint8_t *data; /*!< Transfer buffer*/
size_t dataSize; /*!< Transfer size*/
} flexio_uart_transfer_t;
/* Forward declaration of the handle typedef. */
typedef struct _flexio_uart_handle flexio_uart_handle_t;
/*! @brief FlexIO UART transfer callback function. */
typedef void (*flexio_uart_transfer_callback_t)(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FLEXIO UART handle structure*/
struct _flexio_uart_handle
{
uint8_t *volatile txData; /*!< Address of remaining data to send. */
volatile size_t txDataSize; /*!< Size of the remaining data to send. */
uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
size_t txSize; /*!< Total bytes to be sent. */
size_t rxSize; /*!< Total bytes to be received. */
uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
size_t rxRingBufferSize; /*!< Size of the ring buffer. */
volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
flexio_uart_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< UART callback function parameter.*/
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures FlexIO UART
* hardware, and configures the FlexIO UART with FlexIO UART configuration.
* The configuration structure can be filled by the user, or be set with
* default values by FLEXIO_UART_GetDefaultConfig().
*
* Example
@code
FLEXIO_UART_Type base = {
.flexioBase = FLEXIO,
.TxPinIndex = 0,
.RxPinIndex = 1,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_uart_config_t config = {
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 115200U,
.bitCountPerChar = 8
};
FLEXIO_UART_Init(base, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param userConfig Pointer to the flexio_uart_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
*/
void FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz);
/*!
* @brief Disables the FlexIO UART and gates the FlexIO clock.
*
* @note After calling this API, call the FLEXO_UART_Init to use the FlexIO UART module.
*
* @param base pointer to FLEXIO_UART_Type structure
*/
void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO UART. The configuration
* can be used directly for calling the FLEXIO_UART_Init().
* Example:
@code
flexio_uart_config_t config;
FLEXIO_UART_GetDefaultConfig(&userConfig);
@endcode
* @param userConfig Pointer to the flexio_uart_config_t structure.
*/
void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig);
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO UART status flags.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART status flags.
*/
uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base);
/*!
* @brief Gets the FlexIO UART status flags.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Status flag.
* The parameter can be any combination of the following values:
* @arg kFLEXIO_UART_TxDataRegEmptyFlag
* @arg kFLEXIO_UART_RxEmptyFlag
* @arg kFLEXIO_UART_RxOverRunFlag
*/
void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask);
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO UART interrupt.
*
* This function enables the FlexIO UART interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO UART interrupt.
*
* This function disables the FlexIO UART interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask);
/* @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Gets the FlexIO UARt transmit data register address.
*
* This function returns the UART data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART transmit data register address.
*/
static inline uint32_t FLEXIO_UART_GetTxDataRegisterAddress(FLEXIO_UART_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[0]);
}
/*!
* @brief Gets the FlexIO UART receive data register address.
*
* This function returns the UART data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART receive data register address.
*/
static inline uint32_t FLEXIO_UART_GetRxDataRegisterAddress(FLEXIO_UART_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferByteSwapped, base->shifterIndex[1]);
}
/*!
* @brief Enables/disables the FlexIO UART transmit DMA.
* This function enables/disables the FlexIO UART Tx DMA,
* which means asserting the kFLEXIO_UART_TxDataRegEmptyFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_EnableTxDMA(FLEXIO_UART_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1 << base->shifterIndex[0], enable);
}
/*!
* @brief Enables/disables the FlexIO UART receive DMA.
* This function enables/disables the FlexIO UART Rx DMA,
* which means asserting kFLEXIO_UART_RxDataRegFullFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_EnableRxDMA(FLEXIO_UART_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1 << base->shifterIndex[1], enable);
}
/* @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables/disables the FlexIO UART module operation.
*
* @param base Pointer to the FLEXIO_UART_Type.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_Enable(FLEXIO_UART_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*!
* @brief Writes one byte of data.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register. Ensure that the TxEmptyFlag is asserted before calling
* this API.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param buffer The data bytes to send.
*/
static inline void FLEXIO_UART_WriteByte(FLEXIO_UART_Type *base, const uint8_t *buffer)
{
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *buffer;
}
/*!
* @brief Reads one byte of data.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the RxFullFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param buffer The buffer to store the received bytes.
*/
static inline void FLEXIO_UART_ReadByte(FLEXIO_UART_Type *base, uint8_t *buffer)
{
*buffer = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
}
/*!
* @brief Sends a buffer of data bytes.
*
* @note This function blocks using the polling method until all bytes have been sent.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param txData The data bytes to send.
* @param txSize The number of data bytes to send.
*/
void FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks using the polling method until all bytes have been received.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param rxData The buffer to store the received bytes.
* @param rxSize The number of data bytes to be received.
*/
void FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize);
/* @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the UART handle.
*
* This function initializes the FlexIO UART handle, which can be used for other FlexIO
* UART transactional APIs. Call this API once to get the
* initialized handle.
*
* The UART driver supports the "background" receiving, which means that user can set up
* a RX ring buffer optionally. Data received is stored into the ring buffer even when
* the user doesn't call the FLEXIO_UART_TransferReceiveNonBlocking() API. If there is already data
* received in the ring buffer, user can get the received data from the ring buffer
* directly. The ring buffer is disabled if passing NULL as @p ringBuffer.
*
* @param base to FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_callback_t callback,
void *userData);
/*!
* @brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received is stored into the ring buffer even when
* the user doesn't call the UART_ReceiveNonBlocking() API. If there are already data received
* in the ring buffer, user can get the received data from the ring buffer directly.
*
* @note When using the RX ring buffer, one byte is reserved for internal use. In other
* words, if @p ringBufferSize is 32, only 31 bytes are used for saving data.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
* @param ringBufferSize Size of the ring buffer.
*/
void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize);
/*!
* @brief Aborts the background transfer and uninstalls the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_StopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Transmits a buffer of data using the interrupt method.
*
* This function sends data using an interrupt method. This is a non-blocking function,
* which returns directly without waiting for all data to be written to the TX register. When
* all data are written to TX register in ISR, the FlexIO UART driver calls the callback
* function and passes the @ref kStatus_FLEXIO_UART_TxIdle as status parameter.
*
* @note The kStatus_FLEXIO_UART_TxIdle is passed to the upper layer when all data is written
* to the TX register. However, it does not ensure that all data is sent out.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param xfer FlexIO UART transfer structure. See #flexio_uart_transfer_t.
* @retval kStatus_Success Successfully starts the data transmission.
* @retval kStatus_UART_TxBusy Previous transmission still not finished, data not written to the TX register.
*/
status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt-driven data sending. Get the remainBytes to know
* how many bytes are still not sent out.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Gets the number of remaining bytes not sent.
*
* This function gets the number of remaining bytes not sent driven by interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param count Number of bytes sent so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count);
/*!
* @brief Receives a buffer of data using the interrupt method.
*
* This function receives data using the interrupt method. This is a non-blocking function,
* which returns without waiting for all data to be received.
* If the RX ring buffer is used and not empty, the data in ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in ring buffer is not enough to read, the receive
* request is saved by the UART driver. When new data arrives, the receive request
* is serviced first. When all data is received, the UART driver notifies the upper layer
* through a callback function and passes the status parameter @ref kStatus_UART_RxIdle.
* For example, if the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer,
* the 5 bytes are copied to xfer->data. This function returns with the
* parameter @p receivedBytes set to 5. For the last 5 bytes, newly arrived data is
* saved from the xfer->data[5]. When 5 bytes are received, the UART driver notifies upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to xfer->data. When all data is received, the upper layer is notified.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param xfer UART transfer structure. See #flexio_uart_transfer_t.
* @param receivedBytes Bytes received from the ring buffer directly.
* @retval kStatus_Success Successfully queue the transfer into the transmit queue.
* @retval kStatus_FLEXIO_UART_RxBusy Previous receive request is not finished.
*/
status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer,
size_t *receivedBytes);
/*!
* @brief Aborts the receive data which was using IRQ.
*
* This function aborts the receive data which was using IRQ.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Gets the number of remaining bytes not received.
*
* This function gets the number of remaining bytes not received driven by interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param count Number of bytes received so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count);
/*!
* @brief FlexIO UART IRQ handler function.
*
* This function processes the FlexIO UART transmit and receives the IRQ request.
*
* @param uartType Pointer to the FLEXIO_UART_Type structure.
* @param uartHandle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle);
/*@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_UART_H_*/

View File

@ -0,0 +1,358 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_flexio_uart_dma.h"
#include "fsl_dmamux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! @brief Structure definition for DMA callback param pass in. */
typedef struct _flexio_uart_dma_private_handle
{
FLEXIO_UART_Type *base;
flexio_uart_dma_handle_t *handle;
} flexio_uart_dma_private_handle_t;
/*<! @brief uart transfer state. */
enum _flexio_uart_dma_transfer_states
{
kFLEXIO_UART_TxIdle, /* TX idle. */
kFLEXIO_UART_TxBusy, /* TX busy. */
kFLEXIO_UART_RxIdle, /* RX idle. */
kFLEXIO_UART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Variables
******************************************************************************/
/*< @brief user configurable flexio uart handle count. */
#define FLEXIO_UART_HANDLE_COUNT 2
/*<! Private handle only used for internally. */
static flexio_uart_dma_private_handle_t s_dmaPrivateHandle[FLEXIO_UART_HANDLE_COUNT];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief FLEXIO UART DMA send finished callback function.
*
* This function is called when FLEXIO UART DMA send finished. It disables the UART
* TX DMA request and sends @ref kStatus_FLEXIO_UART_TxIdle to FLEXIO UART callback.
*
* @param handle The DMA handle.
* @param param Callback function parameter.
*/
static void FLEXIO_UART_TransferSendDMACallback(dma_handle_t *handle, void *param);
/*!
* @brief FLEXIO UART DMA receive finished callback function.
*
* This function is called when FLEXIO UART DMA receive finished. It disables the FLEXIO
* UART RX DMA request and sends @ref kStatus_FLEXIO_UART_RxIdle to UART callback.
*
* @param handle The DMA handle.
* @param param Callback function parameter.
*/
static void FLEXIO_UART_TransferReceiveDMACallback(dma_handle_t *handle, void *param);
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_UART_TransferSendDMACallback(dma_handle_t *handle, void *param)
{
flexio_uart_dma_private_handle_t *uartPrivateHandle = (flexio_uart_dma_private_handle_t *)param;
/* Disable UART TX DMA. */
FLEXIO_UART_EnableTxDMA(uartPrivateHandle->base, false);
/* Disable interrupt. */
DMA_DisableInterrupts(handle->base, handle->channel);
uartPrivateHandle->handle->txState = kFLEXIO_UART_TxIdle;
if (uartPrivateHandle->handle->callback)
{
uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
kStatus_FLEXIO_UART_TxIdle, uartPrivateHandle->handle->userData);
}
}
static void FLEXIO_UART_TransferReceiveDMACallback(dma_handle_t *handle, void *param)
{
flexio_uart_dma_private_handle_t *uartPrivateHandle = (flexio_uart_dma_private_handle_t *)param;
/* Disable UART RX DMA. */
FLEXIO_UART_EnableRxDMA(uartPrivateHandle->base, false);
/* Disable interrupt. */
DMA_DisableInterrupts(handle->base, handle->channel);
uartPrivateHandle->handle->rxState = kFLEXIO_UART_RxIdle;
if (uartPrivateHandle->handle->callback)
{
uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
kStatus_FLEXIO_UART_RxIdle, uartPrivateHandle->handle->userData);
}
}
status_t FLEXIO_UART_TransferCreateHandleDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
flexio_uart_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txDmaHandle,
dma_handle_t *rxDmaHandle)
{
assert(handle);
dma_transfer_config_t dmaXferConfig;
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0; index < FLEXIO_UART_HANDLE_COUNT; index++)
{
if (s_dmaPrivateHandle[index].base == NULL)
{
s_dmaPrivateHandle[index].base = base;
s_dmaPrivateHandle[index].handle = handle;
break;
}
}
if (index == FLEXIO_UART_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
memset(handle, 0, sizeof(*handle));
handle->rxState = kFLEXIO_UART_RxIdle;
handle->txState = kFLEXIO_UART_TxIdle;
handle->callback = callback;
handle->userData = userData;
handle->rxDmaHandle = rxDmaHandle;
handle->txDmaHandle = txDmaHandle;
/* Set DMA channel configuration. */
memset(&dmaXferConfig, 0, sizeof(dmaXferConfig));
dmaXferConfig.srcSize = kDMA_Transfersize8bits;
dmaXferConfig.destSize = kDMA_Transfersize8bits;
/* Configure TX. */
if (txDmaHandle)
{
DMA_SetCallback(txDmaHandle, FLEXIO_UART_TransferSendDMACallback, &s_dmaPrivateHandle[index]);
DMA_ResetChannel(txDmaHandle->base, txDmaHandle->channel);
dmaXferConfig.destAddr = FLEXIO_UART_GetTxDataRegisterAddress(base);
dmaXferConfig.enableSrcIncrement = true;
dmaXferConfig.enableDestIncrement = false;
DMA_SetTransferConfig(txDmaHandle->base, txDmaHandle->channel, &dmaXferConfig);
}
/* Configure RX. */
if (rxDmaHandle)
{
DMA_SetCallback(rxDmaHandle, FLEXIO_UART_TransferReceiveDMACallback, &s_dmaPrivateHandle[index]);
DMA_ResetChannel(rxDmaHandle->base, rxDmaHandle->channel);
dmaXferConfig.destAddr = 0U;
dmaXferConfig.srcAddr = FLEXIO_UART_GetRxDataRegisterAddress(base);
dmaXferConfig.enableSrcIncrement = false;
dmaXferConfig.enableDestIncrement = true;
DMA_SetTransferConfig(rxDmaHandle->base, rxDmaHandle->channel, &dmaXferConfig);
}
return kStatus_Success;
}
status_t FLEXIO_UART_TransferSendDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
assert(handle->txDmaHandle);
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous TX not finished. */
if (kFLEXIO_UART_TxBusy == handle->txState)
{
status = kStatus_FLEXIO_UART_TxBusy;
}
else
{
handle->txState = kFLEXIO_UART_TxBusy;
/* Set transfer data address and data size. */
DMA_SetSourceAddress(handle->txDmaHandle->base, handle->txDmaHandle->channel, (uint32_t)xfer->data);
DMA_SetTransferSize(handle->txDmaHandle->base, handle->txDmaHandle->channel, xfer->dataSize);
/* Enable FLEXIO UART TX DMA. */
FLEXIO_UART_EnableTxDMA(base, true);
/* Enable DMA transfer complete interrupt and start transfer. */
DMA_EnableInterrupts(handle->txDmaHandle->base, handle->txDmaHandle->channel);
DMA_EnableChannelRequest(handle->txDmaHandle->base, handle->txDmaHandle->channel);
status = kStatus_Success;
}
return status;
}
status_t FLEXIO_UART_TransferReceiveDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
assert(handle->rxDmaHandle);
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous RX not finished. */
if (kFLEXIO_UART_RxBusy == handle->rxState)
{
status = kStatus_FLEXIO_UART_RxBusy;
}
else
{
handle->rxState = kFLEXIO_UART_RxBusy;
/* Set transfer data address and data size. */
DMA_SetDestinationAddress(handle->rxDmaHandle->base, handle->rxDmaHandle->channel, (uint32_t)xfer->data);
DMA_SetTransferSize(handle->rxDmaHandle->base, handle->rxDmaHandle->channel, xfer->dataSize);
/* Enable FLEXIO UART RX DMA. */
FLEXIO_UART_EnableRxDMA(base, true);
/* Enable DMA transfer complete interrupt and start transfer. */
DMA_EnableInterrupts(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
DMA_EnableChannelRequest(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
status = kStatus_Success;
}
return status;
}
void FLEXIO_UART_TransferAbortSendDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle)
{
assert(handle->txDmaHandle);
/* Disable FLEXIO UART TX DMA. */
FLEXIO_UART_EnableTxDMA(base, false);
/* Stop transfer. */
DMA_StopTransfer(handle->txDmaHandle);
/* Write DMA->DSR[DONE] to abort transfer and clear status. */
DMA_ClearChannelStatusFlags(handle->txDmaHandle->base, handle->txDmaHandle->channel, kDMA_TransactionsDoneFlag);
handle->txState = kFLEXIO_UART_TxIdle;
}
void FLEXIO_UART_TransferAbortReceiveDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle)
{
assert(handle->rxDmaHandle);
/* Disable FLEXIO UART RX DMA. */
FLEXIO_UART_EnableRxDMA(base, false);
/* Stop transfer. */
DMA_StopTransfer(handle->rxDmaHandle);
/* Write DMA->DSR[DONE] to abort transfer and clear status. */
DMA_ClearChannelStatusFlags(handle->rxDmaHandle->base, handle->rxDmaHandle->channel, kDMA_TransactionsDoneFlag);
handle->rxState = kFLEXIO_UART_RxIdle;
}
status_t FLEXIO_UART_TransferGetSendCountDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle, size_t *count)
{
assert(handle->txDmaHandle);
if (!count)
{
return kStatus_InvalidArgument;
}
if (kFLEXIO_UART_TxBusy == handle->txState)
{
*count = (handle->txSize - DMA_GetRemainingBytes(handle->txDmaHandle->base, handle->txDmaHandle->channel));
}
else
{
*count = handle->txSize;
}
return kStatus_Success;
}
status_t FLEXIO_UART_TransferGetReceiveCountDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle, size_t *count)
{
assert(handle->rxDmaHandle);
if (!count)
{
return kStatus_InvalidArgument;
}
if (kFLEXIO_UART_RxBusy == handle->rxState)
{
*count = (handle->rxSize - DMA_GetRemainingBytes(handle->rxDmaHandle->base, handle->rxDmaHandle->channel));
}
else
{
*count = handle->rxSize;
}
return kStatus_Success;
}

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_FLEXIO_UART_DMA_H_
#define _FSL_FLEXIO_UART_DMA_H_
#include "fsl_flexio_uart.h"
#include "fsl_dmamux.h"
#include "fsl_dma.h"
/*!
* @addtogroup flexio_dma_uart
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Forward declaration of the handle typedef. */
typedef struct _flexio_uart_dma_handle flexio_uart_dma_handle_t;
/*! @brief UART transfer callback function. */
typedef void (*flexio_uart_dma_transfer_callback_t)(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief UART DMA handle
*/
struct _flexio_uart_dma_handle
{
flexio_uart_dma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< UART callback function parameter.*/
size_t txSize; /*!< Total bytes to be sent. */
size_t rxSize; /*!< Total bytes to be received. */
dma_handle_t *txDmaHandle; /*!< The DMA TX channel used. */
dma_handle_t *rxDmaHandle; /*!< The DMA RX channel used. */
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA transactional
* @{
*/
/*!
* @brief Initializes the FLEXIO_UART handle which is used in transactional functions
*
* @param base Pointer to FLEXIO_UART_Type structure.
* @param handle Pointer to flexio_uart_dma_handle_t structure.
* @param callback FlexIO UART callback, NULL means no callback.
* @param userData User callback function data.
* @param txDmaHandle User requested DMA handle for TX DMA transfer.
* @param rxDmaHandle User requested DMA handle for RX DMA transfer.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO UART DMA type/handle table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandleDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
flexio_uart_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txDmaHandle,
dma_handle_t *rxDmaHandle);
/*!
* @brief Sends data using DMA.
*
* This function send data using DMA, this is non-blocking function, which return
* right away. When all data have been sent out, the send callback function is called.
*
* @param base Pointer to FLEXIO_UART_Type structure
* @param handle Pointer to flexio_uart_dma_handle_t structure
* @param xfer FLEXIO_UART DMA transfer structure, refer to #flexio_uart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXIO_UART_TxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferSendDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Receives data using DMA.
*
* This function receives data using DMA. This is non-blocking function, which returns
* right away. When all data have been received, the receive callback function is called.
*
* @param base Pointer to FLEXIO_UART_Type structure
* @param handle Pointer to flexio_uart_dma_handle_t structure
* @param xfer FLEXIO_UART DMA transfer sturcture, refer to #flexio_uart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXIO_UART_RxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferReceiveDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Aborts the sent data which using DMA.
*
* This function aborts the sent data which using DMA.
*
* @param base Pointer to FLEXIO_UART_Type structure
* @param handle Pointer to flexio_uart_dma_handle_t structure
*/
void FLEXIO_UART_TransferAbortSendDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle);
/*!
* @brief Aborts the receive data which using DMA.
*
* This function aborts the receive data which using DMA.
*
* @param base Pointer to FLEXIO_UART_Type structure
* @param handle Pointer to flexio_uart_dma_handle_t structure
*/
void FLEXIO_UART_TransferAbortReceiveDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle);
/*!
* @brief Gets the number of bytes still not sent out.
*
* This function gets the number of bytes still not sent out.
*
* @param base Pointer to FLEXIO_UART_Type structure
* @param handle Pointer to flexio_uart_dma_handle_t structure
* @param count Number of bytes sent so far by the non-blocking transaction.
*/
status_t FLEXIO_UART_TransferGetSendCountDMA(FLEXIO_UART_Type *base, flexio_uart_dma_handle_t *handle, size_t *count);
/*!
* @brief Gets the number of bytes still not received.
*
* This function gets the number of bytes still not received.
*
* @param base Pointer to FLEXIO_UART_Type structure
* @param handle Pointer to flexio_uart_dma_handle_t structure
* @param count Number of bytes received so far by the non-blocking transaction.
*/
status_t FLEXIO_UART_TransferGetReceiveCountDMA(FLEXIO_UART_Type *base,
flexio_uart_dma_handle_t *handle,
size_t *count);
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_UART_DMA_H_ */

View File

@ -0,0 +1,179 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_gpio.h"
/*******************************************************************************
* Variables
******************************************************************************/
static PORT_Type *const s_portBases[] = PORT_BASE_PTRS;
static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the GPIO instance according to the GPIO base
*
* @param base GPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval GPIO instance
*/
static uint32_t GPIO_GetInstance(GPIO_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t GPIO_GetInstance(GPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_GPIO_COUNT; instance++)
{
if (s_gpioBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_GPIO_COUNT);
return instance;
}
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(config);
if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= ~(1U << pin);
}
else
{
GPIO_WritePinOutput(base, pin, config->outputLogic);
base->PDDR |= (1U << pin);
}
}
uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base)
{
uint8_t instance;
PORT_Type *portBase;
instance = GPIO_GetInstance(base);
portBase = s_portBases[instance];
return portBase->ISFR;
}
void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask)
{
uint8_t instance;
PORT_Type *portBase;
instance = GPIO_GetInstance(base);
portBase = s_portBases[instance];
portBase->ISFR = mask;
}
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
/*******************************************************************************
* Variables
******************************************************************************/
static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the FGPIO instance according to the GPIO base
*
* @param base FGPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval FGPIO instance
*/
static uint32_t FGPIO_GetInstance(FGPIO_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t FGPIO_GetInstance(FGPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_FGPIO_COUNT; instance++)
{
if (s_fgpioBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_FGPIO_COUNT);
return instance;
}
void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(config);
if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= ~(1U << pin);
}
else
{
FGPIO_WritePinOutput(base, pin, config->outputLogic);
base->PDDR |= (1U << pin);
}
}
uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base)
{
uint8_t instance;
instance = FGPIO_GetInstance(base);
PORT_Type *portBase;
portBase = s_portBases[instance];
return portBase->ISFR;
}
void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask)
{
uint8_t instance;
instance = FGPIO_GetInstance(base);
PORT_Type *portBase;
portBase = s_portBases[instance];
portBase->ISFR = mask;
}
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */

View File

@ -0,0 +1,390 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_GPIO_H_
#define _FSL_GPIO_H_
#include "fsl_common.h"
/*!
* @addtogroup gpio
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief GPIO driver version 2.1.0. */
#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*! @brief GPIO direction definition*/
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/
kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/
} gpio_pin_direction_t;
/*!
* @brief The GPIO pin configuration structure.
*
* Every pin can only be configured as either output pin or input pin at a time.
* If configured as a input pin, then leave the outputConfig unused
* Note : In some cases, the corresponding port property should be configured in advance
* with the PORT_SetPinConfig()
*/
typedef struct _gpio_pin_config
{
gpio_pin_direction_t pinDirection; /*!< gpio direction, input or output */
/* Output configurations, please ignore if configured as a input one */
uint8_t outputLogic; /*!< Set default output logic, no use in input */
} gpio_pin_config_t;
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @addtogroup gpio_driver
* @{
*/
/*! @name GPIO Configuration */
/*@{*/
/*!
* @brief Initializes a GPIO pin used by the board.
*
* To initialize the GPIO, define a pin configuration, either input or output, in the user file.
* Then, call the GPIO_PinInit() function.
*
* This is an example to define an input pin or output pin configuration:
* @code
* // Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* //Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* @endcode
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO port pin number
* @param config GPIO pin configuration pointer
*/
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config);
/*@}*/
/*! @name GPIO Output Operations */
/*@{*/
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1 or 0.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO pin's number
* @param output GPIO pin output logic level.
* - 0: corresponding pin output low logic level.
* - 1: corresponding pin output high logic level.
*/
static inline void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output)
{
if (output == 0U)
{
base->PCOR = 1 << pin;
}
else
{
base->PSOR = 1 << pin;
}
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pins' numbers macro
*/
static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
{
base->PSOR = mask;
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 0.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pins' numbers macro
*/
static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
{
base->PCOR = mask;
}
/*!
* @brief Reverses current output logic of the multiple GPIO pins.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pins' numbers macro
*/
static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask)
{
base->PTOR = mask;
}
/*@}*/
/*! @name GPIO Input Operations */
/*@{*/
/*!
* @brief Reads the current input value of the whole GPIO port.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO pin's number
* @retval GPIO port input value
* - 0: corresponding pin input low logic level.
* - 1: corresponding pin input high logic level.
*/
static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin)
{
return (((base->PDIR) >> pin) & 0x01U);
}
/*@}*/
/*! @name GPIO Interrupt */
/*@{*/
/*!
* @brief Reads whole GPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @retval Current GPIO port interrupt status flag, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base);
/*!
* @brief Clears multiple GPIO pins' interrupt status flag.
*
* @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pins' numbers macro
*/
void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask);
/*@}*/
/*! @} */
/*!
* @addtogroup fgpio_driver
* @{
*/
/*
* Introduce the FGPIO feature.
*
* The FGPIO features are only support on some of Kinetis chips. The FGPIO registers are aliased to the IOPORT
* interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and will therefore
* complete in a single cycle. This aliased Fast GPIO memory map is called FGPIO.
*/
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
/*! @name FGPIO Configuration */
/*@{*/
/*!
* @brief Initializes a FGPIO pin used by the board.
*
* To initialize the FGPIO driver, define a pin configuration, either input or output, in the user file.
* Then, call the FGPIO_PinInit() function.
*
* This is an example to define an input pin or output pin configuration:
* @code
* // Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* //Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* @endcode
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param pin FGPIO port pin number
* @param config FGPIO pin configuration pointer
*/
void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config);
/*@}*/
/*! @name FGPIO Output Operations */
/*@{*/
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param pin FGPIO pin's number
* @param output FGPIOpin output logic level.
* - 0: corresponding pin output low logic level.
* - 1: corresponding pin output high logic level.
*/
static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t output)
{
if (output == 0U)
{
base->PCOR = 1 << pin;
}
else
{
base->PSOR = 1 << pin;
}
}
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 1.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask FGPIO pins' numbers macro
*/
static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask)
{
base->PSOR = mask;
}
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 0.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask FGPIO pins' numbers macro
*/
static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask)
{
base->PCOR = mask;
}
/*!
* @brief Reverses current output logic of the multiple FGPIO pins.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask FGPIO pins' numbers macro
*/
static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask)
{
base->PTOR = mask;
}
/*@}*/
/*! @name FGPIO Input Operations */
/*@{*/
/*!
* @brief Reads the current input value of the whole FGPIO port.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param pin FGPIO pin's number
* @retval FGPIO port input value
* - 0: corresponding pin input low logic level.
* - 1: corresponding pin input high logic level.
*/
static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin)
{
return (((base->PDIR) >> pin) & 0x01U);
}
/*@}*/
/*! @name FGPIO Interrupt */
/*@{*/
/*!
* @brief Reads the whole FGPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @retval Current FGPIO port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base);
/*!
* @brief Clears the multiple FGPIO pins' interrupt status flag.
*
* @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.)
* @param mask FGPIO pins' numbers macro
*/
void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask);
/*@}*/
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_GPIO_H_*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,781 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_I2C_H_
#define _FSL_I2C_H_
#include "fsl_common.h"
/*!
* @addtogroup i2c_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief I2C driver version 2.0.0. */
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT)
#define I2C_HAS_STOP_DETECT
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT / FSL_FEATURE_I2C_HAS_STOP_DETECT */
/*! @brief I2C status return codes. */
enum _i2c_status
{
kStatus_I2C_Busy = MAKE_STATUS(kStatusGroup_I2C, 0), /*!< I2C is busy with current transfer. */
kStatus_I2C_Idle = MAKE_STATUS(kStatusGroup_I2C, 1), /*!< Bus is Idle. */
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
};
/*!
* @brief I2C peripheral flags
*
* The following status register flags can be cleared:
* - #kI2C_ArbitrationLostFlag
* - #kI2C_IntPendingFlag
* - #kI2C_StartDetectFlag
* - #kI2C_StopDetectFlag
*
* @note These enumerations are meant to be OR'd together to form a bit mask.
*
*/
enum _i2c_flags
{
kI2C_ReceiveNakFlag = I2C_S_RXAK_MASK, /*!< I2C receive NAK flag. */
kI2C_IntPendingFlag = I2C_S_IICIF_MASK, /*!< I2C interrupt pending flag. */
kI2C_TransferDirectionFlag = I2C_S_SRW_MASK, /*!< I2C transfer direction flag. */
kI2C_RangeAddressMatchFlag = I2C_S_RAM_MASK, /*!< I2C range address match flag. */
kI2C_ArbitrationLostFlag = I2C_S_ARBL_MASK, /*!< I2C arbitration lost flag. */
kI2C_BusBusyFlag = I2C_S_BUSY_MASK, /*!< I2C bus busy flag. */
kI2C_AddressMatchFlag = I2C_S_IAAS_MASK, /*!< I2C address match flag. */
kI2C_TransferCompleteFlag = I2C_S_TCF_MASK, /*!< I2C transfer complete flag. */
#ifdef I2C_HAS_STOP_DETECT
kI2C_StopDetectFlag = I2C_FLT_STOPF_MASK << 8, /*!< I2C stop detect flag. */
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT / FSL_FEATURE_I2C_HAS_STOP_DETECT */
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
kI2C_StartDetectFlag = I2C_FLT_STARTF_MASK << 8, /*!< I2C start detect flag. */
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
};
/*! @brief I2C feature interrupt source. */
enum _i2c_interrupt_enable
{
kI2C_GlobalInterruptEnable = I2C_C1_IICIE_MASK, /*!< I2C global interrupt. */
#if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
kI2C_StopDetectInterruptEnable = I2C_FLT_STOPIE_MASK, /*!< I2C stop detect interrupt. */
#endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
kI2C_StartStopDetectInterruptEnable = I2C_FLT_SSIE_MASK, /*!< I2C start&stop detect interrupt. */
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
};
/*! @brief Direction of master and slave transfers. */
typedef enum _i2c_direction
{
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
kI2C_Read = 0x1U, /*!< Master receive from slave. */
} i2c_direction_t;
/*! @brief Addressing mode. */
typedef enum _i2c_slave_address_mode
{
kI2C_Address7bit = 0x0U, /*!< 7-bit addressing mode. */
kI2C_RangeMatch = 0X2U, /*!< Range address match addressing mode. */
} i2c_slave_address_mode_t;
/*! @brief I2C transfer control flag. */
enum _i2c_master_transfer_flags
{
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
};
/*!
* @brief Set of events sent to the callback for nonblocking slave transfers.
*
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
* events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable.
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
* parameter.
*
* @note These enumerations are meant to be OR'd together to form a bit mask of events.
*/
typedef enum _i2c_slave_transfer_event
{
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit
(slave-transmitter role). */
kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received
data (slave-receiver role). */
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
kI2C_SlaveRepeatedStartEvent = 0x10U, /*!< A repeated start was detected. */
#endif
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
/*! Bit mask of all available events. */
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
kI2C_SlaveRepeatedStartEvent |
#endif
kI2C_SlaveCompletionEvent,
} i2c_slave_transfer_event_t;
/*! @brief I2C master user configuration. */
typedef struct _i2c_master_config
{
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
#endif
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
bool enableStopHold; /*!< Controls the stop hold enable. */
#endif
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
uint8_t glitchFilterWidth; /*!< Controls the width of the glitch. */
} i2c_master_config_t;
/*! @brief I2C slave user configuration. */
typedef struct _i2c_slave_config
{
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
bool enableGeneralCall; /*!< Enable general call addressing mode. */
bool enableWakeUp; /*!< Enables/disables waking up MCU from low power mode. */
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
#endif
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
uint16_t slaveAddress; /*!< Slave address configuration. */
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
} i2c_slave_config_t;
/*! @brief I2C master handle typedef. */
typedef struct _i2c_master_handle i2c_master_handle_t;
/*! @brief I2C master transfer callback typedef. */
typedef void (*i2c_master_transfer_callback_t)(I2C_Type *base,
i2c_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief I2C slave handle typedef. */
typedef struct _i2c_slave_handle i2c_slave_handle_t;
/*! @brief I2C master transfer structure. */
typedef struct _i2c_master_transfer
{
uint32_t flags; /*!< Transfer flag which controls the transfer. */
uint8_t slaveAddress; /*!< 7-bit slave address. */
i2c_direction_t direction; /*!< Transfer direction, read or write. */
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
uint8_t subaddressSize; /*!< Size of command buffer. */
uint8_t *volatile data; /*!< Transfer buffer. */
volatile size_t dataSize; /*!< Transfer size. */
} i2c_master_transfer_t;
/*! @brief I2C master handle structure. */
struct _i2c_master_handle
{
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t state; /*!< Transfer state maintained during transfer. */
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
void *userData; /*!< Callback parameter passed to callback function. */
};
/*! @brief I2C slave transfer structure. */
typedef struct _i2c_slave_transfer
{
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
uint8_t *volatile data; /*!< Transfer buffer. */
volatile size_t dataSize; /*!< Transfer size. */
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
#kI2C_SlaveCompletionEvent. */
size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */
} i2c_slave_transfer_t;
/*! @brief I2C slave transfer callback typedef. */
typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer_t *xfer, void *userData);
/*! @brief I2C slave handle structure. */
struct _i2c_slave_handle
{
bool isBusy; /*!< Whether transfer is busy. */
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
uint32_t eventMask; /*!< Mask of enabled events. */
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
void *userData; /*!< Callback parameter passed to callback. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus. */
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
* and configure the I2C with master configuration.
*
* @note This API should be called at the beginning of the application to use
* the I2C driver, or any operation to the I2C module could cause hard fault
* because clock is not enabled. The configuration structure can be filled by user
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
* After calling this API, the master is ready to transfer.
* Example:
* @code
* i2c_master_config_t config = {
* .enableMaster = true,
* .enableStopHold = false,
* .highDrive = false,
* .baudRate_Bps = 100000,
* .glitchFilterWidth = 0
* };
* I2C_MasterInit(I2C0, &config, 12000000U);
* @endcode
*
* @param base I2C base pointer
* @param masterConfig pointer to master configuration structure
* @param srcClock_Hz I2C peripheral clock frequency in Hz
*/
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
* and initializes the I2C with slave configuration.
*
* @note This API should be called at the beginning of the application to use
* the I2C driver, or any operation to the I2C module can cause a hard fault
* because the clock is not enabled. The configuration structure can partly be set
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
* Example
* @code
* i2c_slave_config_t config = {
* .enableSlave = true,
* .enableGeneralCall = false,
* .addressingMode = kI2C_Address7bit,
* .slaveAddress = 0x1DU,
* .enableWakeUp = false,
* .enablehighDrive = false,
* .enableBaudRateCtl = false
* };
* I2C_SlaveInit(I2C0, &config);
* @endcode
*
* @param base I2C base pointer
* @param slaveConfig pointer to slave configuration structure
*/
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig);
/*!
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
* The I2C master module can't work unless the I2C_MasterInit is called.
* @param base I2C base pointer
*/
void I2C_MasterDeinit(I2C_Type *base);
/*!
* @brief De-initializes the I2C slave peripheral. Calling this API gates the I2C clock.
* The I2C slave module can't work unless the I2C_SlaveInit is called to enable the clock.
* @param base I2C base pointer
*/
void I2C_SlaveDeinit(I2C_Type *base);
/*!
* @brief Sets the I2C master configuration structure to default values.
*
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
* the structure before calling I2C_MasterConfigure().
* Example:
* @code
* i2c_master_config_t config;
* I2C_MasterGetDefaultConfig(&config);
* @endcode
* @param masterConfig Pointer to the master configuration structure.
*/
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
/*!
* @brief Sets the I2C slave configuration structure to default values.
*
* The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure().
* Modify fields of the structure before calling the I2C_SlaveConfigure().
* Example:
* @code
* i2c_slave_config_t config;
* I2C_SlaveGetDefaultConfig(&config);
* @endcode
* @param slaveConfig Pointer to the slave configuration structure.
*/
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
/*!
* @brief Enables or disabless the I2C peripheral operation.
*
* @param base I2C base pointer
* @param enable pass true to enable module, false to disable module
*/
static inline void I2C_Enable(I2C_Type *base, bool enable)
{
if (enable)
{
base->C1 |= I2C_C1_IICEN_MASK;
}
else
{
base->C1 &= ~I2C_C1_IICEN_MASK;
}
}
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the I2C status flags.
*
* @param base I2C base pointer
* @return status flag, use status flag to AND #_i2c_flags could get the related status.
*/
uint32_t I2C_MasterGetStatusFlags(I2C_Type *base);
/*!
* @brief Gets the I2C status flags.
*
* @param base I2C base pointer
* @return status flag, use status flag to AND #_i2c_flags could get the related status.
*/
static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
{
return I2C_MasterGetStatusFlags(base);
}
/*!
* @brief Clears the I2C status flag state.
*
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
*
* @param base I2C base pointer
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
* The parameter could be any combination of the following values:
* @arg kI2C_StartDetectFlag (if available)
* @arg kI2C_StopDetectFlag (if available)
* @arg kI2C_ArbitrationLostFlag
* @arg kI2C_IntPendingFlagFlag
*/
static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMask)
{
/* Must clear the STARTF / STOPF bits prior to clearing IICIF */
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
if (statusMask & kI2C_StartDetectFlag)
{
/* Shift the odd-ball flags back into place. */
base->FLT |= (uint8_t)(statusMask >> 8U);
}
#endif
#ifdef I2C_HAS_STOP_DETECT
if (statusMask & kI2C_StopDetectFlag)
{
/* Shift the odd-ball flags back into place. */
base->FLT |= (uint8_t)(statusMask >> 8U);
}
#endif
base->S = (uint8_t)statusMask;
}
/*!
* @brief Clears the I2C status flag state.
*
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
*
* @param base I2C base pointer
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
* The parameter could be any combination of the following values:
* @arg kI2C_StartDetectFlag (if available)
* @arg kI2C_StopDetectFlag (if available)
* @arg kI2C_ArbitrationLostFlag
* @arg kI2C_IntPendingFlagFlag
*/
static inline void I2C_SlaveClearStatusFlags(I2C_Type *base, uint32_t statusMask)
{
I2C_MasterClearStatusFlags(base, statusMask);
}
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables I2C interrupt requests.
*
* @param base I2C base pointer
* @param mask interrupt source
* The parameter can be combination of the following source if defined:
* @arg kI2C_GlobalInterruptEnable
* @arg kI2C_StopDetectInterruptEnable/kI2C_StartDetectInterruptEnable
* @arg kI2C_SdaTimeoutInterruptEnable
*/
void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask);
/*!
* @brief Disables I2C interrupt requests.
*
* @param base I2C base pointer
* @param mask interrupt source
* The parameter can be combination of the following source if defined:
* @arg kI2C_GlobalInterruptEnable
* @arg kI2C_StopDetectInterruptEnable/kI2C_StartDetectInterruptEnable
* @arg kI2C_SdaTimeoutInterruptEnable
*/
void I2C_DisableInterrupts(I2C_Type *base, uint32_t mask);
/*!
* @name DMA Control
* @{
*/
#if defined(FSL_FEATURE_I2C_HAS_DMA_SUPPORT) && FSL_FEATURE_I2C_HAS_DMA_SUPPORT
/*!
* @brief Enables/disables the I2C DMA interrupt.
*
* @param base I2C base pointer
* @param enable true to enable, false to disable
*/
static inline void I2C_EnableDMA(I2C_Type *base, bool enable)
{
if (enable)
{
base->C1 |= I2C_C1_DMAEN_MASK;
}
else
{
base->C1 &= ~I2C_C1_DMAEN_MASK;
}
}
#endif /* FSL_FEATURE_I2C_HAS_DMA_SUPPORT */
/*!
* @brief Gets the I2C tx/rx data register address. This API is used to provide a transfer address
* for I2C DMA transfer configuration.
*
* @param base I2C base pointer
* @return data register address
*/
static inline uint32_t I2C_GetDataRegAddr(I2C_Type *base)
{
return (uint32_t)(&(base->D));
}
/* @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Sets the I2C master transfer baud rate.
*
* @param base I2C base pointer
* @param baudRate_Bps the baud rate value in bps
* @param srcClock_Hz Source clock
*/
void I2C_MasterSetBaudRate(I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/*!
* @brief Sends a START on the I2C bus.
*
* This function is used to initiate a new master mode transfer by sending the START signal.
* The slave address is sent following the I2C START signal.
*
* @param base I2C peripheral base pointer
* @param address 7-bit slave device address.
* @param direction Master transfer directions(transmit/receive).
* @retval kStatus_Success Successfully send the start signal.
* @retval kStatus_I2C_Busy Current bus is busy.
*/
status_t I2C_MasterStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
/*!
* @brief Sends a STOP signal on the I2C bus.
*
* @retval kStatus_Success Successfully send the stop signal.
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
*/
status_t I2C_MasterStop(I2C_Type *base);
/*!
* @brief Sends a REPEATED START on the I2C bus.
*
* @param base I2C peripheral base pointer
* @param address 7-bit slave device address.
* @param direction Master transfer directions(transmit/receive).
* @retval kStatus_Success Successfully send the start signal.
* @retval kStatus_I2C_Busy Current bus is busy but not occupied by current I2C master.
*/
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
/*!
* @brief Performs a polling send transaction on the I2C bus without a STOP signal.
*
* @param base The I2C peripheral base pointer.
* @param txBuff The pointer to the data to be transferred.
* @param txSize The length in bytes of the data to be transferred.
* @retval kStatus_Success Successfully complete the data transmission.
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
*/
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
/*!
* @brief Performs a polling receive transaction on the I2C bus with a STOP signal.
*
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
* Without stopping the bus prior for the final read, the bus issues another read, resulting
* in garbage data being read into the data register.
*
* @param base I2C peripheral base pointer.
* @param rxBuff The pointer to the data to store the received data.
* @param rxSize The length in bytes of the data to be received.
* @retval kStatus_Success Successfully complete the data transmission.
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
*/
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
/*!
* @brief Performs a polling send transaction on the I2C bus.
*
* @param base The I2C peripheral base pointer.
* @param txBuff The pointer to the data to be transferred.
* @param txSize The length in bytes of the data to be transferred.
* @retval kStatus_Success Successfully complete the data transmission.
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
*/
status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
/*!
* @brief Performs a polling receive transaction on the I2C bus.
*
* @param base I2C peripheral base pointer.
* @param rxBuff The pointer to the data to store the received data.
* @param rxSize The length in bytes of the data to be received.
*/
void I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
/*!
* @brief Performs a master polling transfer on the I2C bus.
*
* @note The API does not return until the transfer succeeds or fails due
* to arbitration lost or receiving a NAK.
*
* @param base I2C peripheral base address.
* @param xfer Pointer to the transfer structure.
* @retval kStatus_Success Successfully complete the data transmission.
* @retval kStatus_I2C_Busy Previous transmission still not finished.
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
*/
status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer);
/* @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the I2C handle which is used in transactional functions.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_master_handle_t structure to store the transfer state.
* @param callback pointer to user callback function.
* @param userData user paramater passed to the callback function.
*/
void I2C_MasterTransferCreateHandle(I2C_Type *base,
i2c_master_handle_t *handle,
i2c_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Performs a master interrupt non-blocking transfer on the I2C bus.
*
* @note Calling the API will return immediately after transfer initiates, user needs
* to call I2C_MasterGetTransferCount to poll the transfer status to check whether
* the transfer is finished, if the return status is not kStatus_I2C_Busy, the transfer
* is finished.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_master_handle_t structure which stores the transfer state.
* @param xfer pointer to i2c_master_transfer_t structure.
* @retval kStatus_Success Sucessully start the data transmission.
* @retval kStatus_I2C_Busy Previous transmission still not finished.
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
*/
status_t I2C_MasterTransferNonBlocking(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer);
/*!
* @brief Gets the master transfer status during a interrupt non-blocking transfer.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_master_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count);
/*!
* @brief Aborts an interrupt non-blocking transfer early.
*
* @note This API can be called at any time when an interrupt non-blocking transfer initiates
* to abort the transfer early.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_master_handle_t structure which stores the transfer state
*/
void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle);
/*!
* @brief Master interrupt handler.
*
* @param base I2C base pointer.
* @param i2cHandle pointer to i2c_master_handle_t structure.
*/
void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle);
/*!
* @brief Initializes the I2C handle which is used in transactional functions.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_slave_handle_t structure to store the transfer state.
* @param callback pointer to user callback function.
* @param userData user parameter passed to the callback function.
*/
void I2C_SlaveTransferCreateHandle(I2C_Type *base,
i2c_slave_handle_t *handle,
i2c_slave_transfer_callback_t callback,
void *userData);
/*!
* @brief Starts accepting slave transfers.
*
* Call this API after calling the I2C_SlaveInit() and I2C_SlaveTransferCreateHandle() to start processing
* transactions driven by an I2C master. The slave monitors the I2C bus and passes events to the
* callback that was passed into the call to I2C_SlaveTransferCreateHandle(). The callback is always invoked
* from the interrupt context.
*
* The set of events received by the callback is customizable. To do so, set the @a eventMask parameter to
* the OR'd combination of #i2c_slave_transfer_event_t enumerators for the events you wish to receive.
* The #kI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
* to be included in the mask. Alternatively, pass 0 to get a default set of only the transmit and
* receive events that are always enabled. In addition, the #kI2C_SlaveAllEvents constant is provided as
* a convenient way to enable all events.
*
* @param base The I2C peripheral base address.
* @param handle Pointer to #i2c_slave_handle_t structure which stores the transfer state.
* @param eventMask Bit mask formed by OR'ing together #i2c_slave_transfer_event_t enumerators to specify
* which events to send to the callback. Other accepted values are 0 to get a default set of
* only the transmit and receive events, and #kI2C_SlaveAllEvents to enable all events.
*
* @retval #kStatus_Success Slave transfers were successfully started.
* @retval #kStatus_I2C_Busy Slave transfers have already been started on this handle.
*/
status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle, uint32_t eventMask);
/*!
* @brief Aborts the slave transfer.
*
* @note This API can be called at any time to stop slave for handling the bus events.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_slave_handle_t structure which stores the transfer state.
*/
void I2C_SlaveTransferAbort(I2C_Type *base, i2c_slave_handle_t *handle);
/*!
* @brief Gets the slave transfer remaining bytes during a interrupt non-blocking transfer.
*
* @param base I2C base pointer.
* @param handle pointer to i2c_slave_handle_t structure.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t I2C_SlaveTransferGetCount(I2C_Type *base, i2c_slave_handle_t *handle, size_t *count);
/*!
* @brief Slave interrupt handler.
*
* @param base I2C base pointer.
* @param i2cHandle pointer to i2c_slave_handle_t structure which stores the transfer state
*/
void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle);
/* @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus. */
/*@}*/
#endif /* _FSL_I2C_H_*/

View File

@ -0,0 +1,523 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_i2c_dma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! @brief Structure definition for i2c_master_dma_handle_t. The structure is private. */
typedef struct _i2c_master_dma_private_handle
{
I2C_Type *base;
i2c_master_dma_handle_t *handle;
} i2c_master_dma_private_handle_t;
/*! @brief i2c master DMA transfer state. */
enum _i2c_master_dma_transfer_states
{
kIdleState = 0x0U, /*!< I2C bus idle. */
kTransferDataState = 0x1U, /*!< 7-bit address check state. */
};
/*! @brief Common sets of flags used by the driver. */
enum _i2c_flag_constants
{
/*! All flags which are cleared by the driver upon starting a transfer. */
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StartDetectFlag | kI2C_StopDetectFlag,
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StopDetectFlag,
#else
kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag,
#endif
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief DMA callback for I2C master DMA driver.
*
* @param handle DMA handler for I2C master DMA driver
* @param userData user param passed to the callback function
*/
static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData);
/*!
* @brief Check and clear status operation.
*
* @param base I2C peripheral base address.
* @param status current i2c hardware status
* @retval kStatus_Success No error found.
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
* @retval kStatus_I2C_Nak Received Nak error.
*/
static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status);
/*!
* @brief DMA config for I2C master driver.
*
* @param base I2C peripheral base address.
* @param handle pointer to i2c_master_dma_handle_t structure which stores the transfer state.
*/
static void I2C_MasterTransferDMAConfig(I2C_Type *base, i2c_master_dma_handle_t *handle);
/*!
* @brief Set up master transfer, send slave address and sub address(if any), wait until the
* wait until address sent status return.
*
* @param base I2C peripheral base address.
* @param handle pointer to i2c_master_dma_handle_t structure which stores the transfer state.
* @param xfer pointer to i2c_master_transfer_t structure.
*/
static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
i2c_master_dma_handle_t *handle,
i2c_master_transfer_t *xfer);
/*!
* @brief Get the I2C instance from peripheral base address.
*
* @param base I2C peripheral base address.
* @return I2C instance.
*/
extern uint32_t I2C_GetInstance(I2C_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*<! Private handle only used for internally. */
static i2c_master_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_I2C_COUNT];
/*******************************************************************************
* Codes
******************************************************************************/
static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData)
{
i2c_master_dma_private_handle_t *i2cPrivateHandle = (i2c_master_dma_private_handle_t *)userData;
status_t result = kStatus_Success;
/* Disable DMA. */
I2C_EnableDMA(i2cPrivateHandle->base, false);
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
if (!(i2cPrivateHandle->handle->transfer.flags & kI2C_TransferNoStopFlag))
{
if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
{
/* Change to send NAK at the last byte. */
i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
/* Wait the last data to be received. */
while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag))
{
}
/* Send stop signal. */
result = I2C_MasterStop(i2cPrivateHandle->base);
/* Read the last data byte. */
*(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) =
i2cPrivateHandle->base->D;
}
else
{
/* Wait the last data to be sent. */
while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag))
{
}
/* Send stop signal. */
result = I2C_MasterStop(i2cPrivateHandle->base);
}
}
i2cPrivateHandle->handle->state = kIdleState;
if (i2cPrivateHandle->handle->completionCallback)
{
i2cPrivateHandle->handle->completionCallback(i2cPrivateHandle->base, i2cPrivateHandle->handle, result,
i2cPrivateHandle->handle->userData);
}
}
static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status)
{
status_t result = kStatus_Success;
/* Check arbitration lost. */
if (status & kI2C_ArbitrationLostFlag)
{
/* Clear arbitration lost flag. */
base->S = kI2C_ArbitrationLostFlag;
result = kStatus_I2C_ArbitrationLost;
}
/* Check NAK */
else if (status & kI2C_ReceiveNakFlag)
{
result = kStatus_I2C_Nak;
}
else
{
}
return result;
}
static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
i2c_master_dma_handle_t *handle,
i2c_master_transfer_t *xfer)
{
assert(handle);
assert(xfer);
/* Set up transfer first. */
i2c_direction_t direction = xfer->direction;
status_t result = kStatus_Success;
uint16_t timeout = UINT16_MAX;
if (handle->state != kIdleState)
{
return kStatus_I2C_Busy;
}
else
{
/* Init the handle member. */
handle->transfer = *xfer;
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
handle->state = kTransferDataState;
/* Wait until ready to complete. */
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
{
}
/* Failed to start the transfer. */
if (timeout == 0)
{
return kStatus_I2C_Timeout;
}
/* Clear all status before transfer. */
I2C_MasterClearStatusFlags(base, kClearFlags);
/* Change to send write address when it's a read operation with command. */
if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
{
direction = kI2C_Write;
}
/* If repeated start is requested, send repeated start. */
if (handle->transfer.flags & kI2C_TransferRepeatedStartFlag)
{
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, direction);
}
else /* For normal transfer, send start. */
{
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
}
/* Send subaddress. */
if (handle->transfer.subaddressSize)
{
do
{
/* Wait until data transfer complete. */
while (!(base->S & kI2C_IntPendingFlag))
{
}
/* Clear interrupt pending flag. */
base->S = kI2C_IntPendingFlag;
handle->transfer.subaddressSize--;
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
/* Check if there's transfer error. */
result = I2C_CheckAndClearError(base, base->S);
if (result)
{
return result;
}
} while ((handle->transfer.subaddressSize > 0) && (result == kStatus_Success));
if (handle->transfer.direction == kI2C_Read)
{
/* Wait until data transfer complete. */
while (!(base->S & kI2C_IntPendingFlag))
{
}
/* Clear pending flag. */
base->S = kI2C_IntPendingFlag;
/* Send repeated start and slave address. */
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
}
}
if (result)
{
return result;
}
/* Wait until data transfer complete. */
while (!(base->S & kI2C_IntPendingFlag))
{
}
/* Clear pending flag. */
base->S = kI2C_IntPendingFlag;
/* Check if there's transfer error. */
result = I2C_CheckAndClearError(base, base->S);
}
return result;
}
static void I2C_MasterTransferDMAConfig(I2C_Type *base, i2c_master_dma_handle_t *handle)
{
dma_transfer_config_t transfer_config;
dma_transfer_options_t transfer_options = kDMA_EnableInterrupt;
if (handle->transfer.direction == kI2C_Read)
{
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
if (!(handle->transfer.flags & kI2C_TransferNoStopFlag))
{
transfer_config.transferSize = (handle->transfer.dataSize - 1);
}
else
{
transfer_config.transferSize = handle->transfer.dataSize;
}
transfer_config.srcSize = kDMA_Transfersize8bits;
transfer_config.enableSrcIncrement = false;
transfer_config.destSize = kDMA_Transfersize8bits;
transfer_config.enableDestIncrement = true;
}
else
{
transfer_config.srcAddr = (uint32_t)(handle->transfer.data + 1);
transfer_config.destAddr = (uint32_t)I2C_GetDataRegAddr(base);
transfer_config.transferSize = (handle->transfer.dataSize - 1);
transfer_config.srcSize = kDMA_Transfersize8bits;
transfer_config.enableSrcIncrement = true;
transfer_config.destSize = kDMA_Transfersize8bits;
transfer_config.enableDestIncrement = false;
}
DMA_SubmitTransfer(handle->dmaHandle, &transfer_config, transfer_options);
DMA_StartTransfer(handle->dmaHandle);
}
void I2C_MasterTransferCreateHandleDMA(I2C_Type *base,
i2c_master_dma_handle_t *handle,
i2c_master_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *dmaHandle)
{
assert(handle);
assert(dmaHandle);
uint32_t instance = I2C_GetInstance(base);
/* Zero handle. */
memset(handle, 0, sizeof(*handle));
/* Set the user callback and userData. */
handle->completionCallback = callback;
handle->userData = userData;
/* Set the handle for DMA. */
handle->dmaHandle = dmaHandle;
s_dmaPrivateHandle[instance].base = base;
s_dmaPrivateHandle[instance].handle = handle;
DMA_SetCallback(dmaHandle, (dma_callback)I2C_MasterTransferCallbackDMA, &s_dmaPrivateHandle[instance]);
}
status_t I2C_MasterTransferDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer)
{
assert(handle);
assert(xfer);
status_t result;
uint8_t tmpReg;
volatile uint8_t dummy = 0;
/* Add this to avoid build warning. */
dummy++;
/* Disable dma transfer. */
I2C_EnableDMA(base, false);
/* Send address and command buffer(if there is), until senddata phase or receive data phase. */
result = I2C_InitTransferStateMachineDMA(base, handle, xfer);
if (result != kStatus_Success)
{
/* Send stop if received Nak. */
if (result == kStatus_I2C_Nak)
{
if (I2C_MasterStop(base) != kStatus_Success)
{
result = kStatus_I2C_Timeout;
}
}
/* Reset the state to idle state. */
handle->state = kIdleState;
return result;
}
/* Configure dma transfer. */
/* For i2c send, need to send 1 byte first to trigger the dma, for i2c read,
need to send stop before reading the last byte, so the dma transfer size should
be (xSize - 1). */
if (handle->transfer.dataSize > 1)
{
I2C_MasterTransferDMAConfig(base, handle);
if (handle->transfer.direction == kI2C_Read)
{
/* Change direction for receive. */
base->C1 &= ~I2C_C1_TX_MASK;
/* Read dummy to release the bus. */
dummy = base->D;
/* Enabe dma transfer. */
I2C_EnableDMA(base, true);
}
else
{
/* Enabe dma transfer. */
I2C_EnableDMA(base, true);
/* Send the first data. */
base->D = *handle->transfer.data;
}
}
else /* If transfer size is 1, use polling method. */
{
if (handle->transfer.direction == kI2C_Read)
{
tmpReg = base->C1;
/* Change direction to Rx. */
tmpReg &= ~I2C_C1_TX_MASK;
/* Configure send NAK */
tmpReg |= I2C_C1_TXAK_MASK;
base->C1 = tmpReg;
/* Read dummy to release the bus. */
dummy = base->D;
}
else
{
base->D = *handle->transfer.data;
}
/* Wait until data transfer complete. */
while (!(base->S & kI2C_IntPendingFlag))
{
}
/* Clear pending flag. */
base->S = kI2C_IntPendingFlag;
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
if (!(handle->transfer.flags & kI2C_TransferNoStopFlag))
{
result = I2C_MasterStop(base);
}
/* Read the last byte of data. */
if (handle->transfer.direction == kI2C_Read)
{
*handle->transfer.data = base->D;
}
/* Reset the state to idle. */
handle->state = kIdleState;
}
return result;
}
status_t I2C_MasterTransferGetCountDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_InvalidArgument;
}
if (kIdleState != handle->state)
{
*count = (handle->transferSize - DMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel));
}
else
{
*count = handle->transferSize;
}
return kStatus_Success;
}
void I2C_MasterTransferAbortDMA(I2C_Type *base, i2c_master_dma_handle_t *handle)
{
DMA_AbortTransfer(handle->dmaHandle);
/* Disable dma transfer. */
I2C_EnableDMA(base, false);
/* Reset the state to idle. */
handle->state = kIdleState;
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_I2C_DMA_H_
#define _FSL_I2C_DMA_H_
#include "fsl_i2c.h"
#include "fsl_dmamux.h"
#include "fsl_dma.h"
/*!
* @addtogroup i2c_dma_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief I2C master dma handle typedef. */
typedef struct _i2c_master_dma_handle i2c_master_dma_handle_t;
/*! @brief I2C master dma transfer callback typedef. */
typedef void (*i2c_master_dma_transfer_callback_t)(I2C_Type *base,
i2c_master_dma_handle_t *handle,
status_t status,
void *userData);
/*! @brief I2C master dma transfer structure. */
struct _i2c_master_dma_handle
{
i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t state; /*!< I2C master transfer status. */
dma_handle_t *dmaHandle; /*!< The DMA handler used. */
i2c_master_dma_transfer_callback_t completionCallback; /*!< Callback function called after dma transfer finished. */
void *userData; /*!< Callback parameter passed to callback function. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus. */
/*!
* @name I2C Block DMA Transfer Operation
* @{
*/
/*!
* @brief Init the I2C handle which is used in transcational functions
*
* @param base I2C peripheral base address
* @param handle pointer to i2c_master_dma_handle_t structure
* @param callback pointer to user callback function
* @param userData user param passed to the callback function
* @param dmaHandle DMA handle pointer
*/
void I2C_MasterTransferCreateHandleDMA(I2C_Type *base,
i2c_master_dma_handle_t *handle,
i2c_master_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *dmaHandle);
/*!
* @brief Performs a master dma non-blocking transfer on the I2C bus
*
* @param base I2C peripheral base address
* @param handle pointer to i2c_master_dma_handle_t structure
* @param xfer pointer to transfer structure of i2c_master_transfer_t
* @retval kStatus_Success Sucessully complete the data transmission.
* @retval kStatus_I2C_Busy Previous transmission still not finished.
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
* @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer.
*/
status_t I2C_MasterTransferDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer);
/*!
* @brief Get master transfer status during a dma non-blocking transfer
*
* @param base I2C peripheral base address
* @param handle pointer to i2c_master_dma_handle_t structure
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
status_t I2C_MasterTransferGetCountDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, size_t *count);
/*!
* @brief Abort a master dma non-blocking transfer in a early time
*
* @param base I2C peripheral base address
* @param handle pointer to i2c_master_dma_handle_t structure
*/
void I2C_MasterTransferAbortDMA(I2C_Type *base, i2c_master_dma_handle_t *handle);
/* @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus. */
/*@}*/
#endif /*_FSL_I2C_DMA_H_*/

View File

@ -0,0 +1,404 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_llwu.h"
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN)
void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
volatile uint32_t *regBase;
uint32_t regOffset;
uint32_t reg;
switch (pinIndex >> 4U)
{
case 0U:
regBase = &base->PE1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 1U:
regBase = &base->PE2;
break;
#endif
default:
regBase = NULL;
break;
}
#else
volatile uint8_t *regBase;
uint8_t regOffset;
uint8_t reg;
switch (pinIndex >> 2U)
{
case 0U:
regBase = &base->PE1;
break;
case 1U:
regBase = &base->PE2;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 2U:
regBase = &base->PE3;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 12))
case 3U:
regBase = &base->PE4;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 4U:
regBase = &base->PE5;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 20))
case 5U:
regBase = &base->PE6;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 6U:
regBase = &base->PE7;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 28))
case 7U:
regBase = &base->PE8;
break;
#endif
default:
regBase = NULL;
break;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH == 32 */
if (regBase)
{
reg = *regBase;
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
regOffset = ((pinIndex & 0x0FU) << 1U);
#else
regOffset = ((pinIndex & 0x03U) << 1U);
#endif
reg &= ~(0x3U << regOffset);
reg |= ((uint32_t)pinMode << regOffset);
*regBase = reg;
}
}
bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
return (bool)(base->PF & (1U << pinIndex));
#else
volatile uint8_t *regBase;
switch (pinIndex >> 3U)
{
#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
case 0U:
regBase = &base->PF1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->PF2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->PF3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->PF4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#else
case 0U:
regBase = &base->F1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->F2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->F3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->F4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#endif /* FSL_FEATURE_LLWU_HAS_PF */
default:
regBase = NULL;
break;
}
if (regBase)
{
return (bool)(*regBase & (1U << pinIndex % 8));
}
else
{
return false;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
base->PF = (1U << pinIndex);
#else
volatile uint8_t *regBase;
switch (pinIndex >> 3U)
{
#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
case 0U:
regBase = &base->PF1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->PF2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->PF3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->PF4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#else
case 0U:
regBase = &base->F1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->F2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->F3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->F4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#endif /* FSL_FEATURE_LLWU_HAS_PF */
default:
regBase = NULL;
break;
}
if (regBase)
{
*regBase = (1U << pinIndex % 8U);
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
uint32_t reg;
reg = base->FILT;
reg &= ~((LLWU_FILT_FILTSEL1_MASK | LLWU_FILT_FILTE1_MASK) << (filterIndex * 8U - 1U));
reg |= (((filterMode.pinIndex << LLWU_FILT_FILTSEL1_SHIFT) | (filterMode.filterMode << LLWU_FILT_FILTE1_SHIFT)
/* Clear the Filter Detect Flag */
| LLWU_FILT_FILTF1_MASK)
<< (filterIndex * 8U - 1U));
base->FILT = reg;
#else
volatile uint8_t *regBase;
uint8_t reg;
switch (filterIndex)
{
case 1:
regBase = &base->FILT1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2:
regBase = &base->FILT2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3:
regBase = &base->FILT3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4:
regBase = &base->FILT4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
default:
regBase = NULL;
break;
}
if (regBase)
{
reg = *regBase;
reg &= ~(LLWU_FILT1_FILTSEL_MASK | LLWU_FILT1_FILTE_MASK);
reg |= ((uint32_t)filterMode.pinIndex << LLWU_FILT1_FILTSEL_SHIFT);
reg |= ((uint32_t)filterMode.filterMode << LLWU_FILT1_FILTE_SHIFT);
/* Clear the Filter Detect Flag */
reg |= LLWU_FILT1_FILTF_MASK;
*regBase = reg;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
return (bool)(base->FILT & (1U << (filterIndex * 8U - 1)));
#else
bool status = false;
switch (filterIndex)
{
case 1:
status = (base->FILT1 & LLWU_FILT1_FILTF_MASK);
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2:
status = (base->FILT2 & LLWU_FILT2_FILTF_MASK);
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3:
status = (base->FILT3 & LLWU_FILT3_FILTF_MASK);
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4:
status = (base->FILT4 & LLWU_FILT4_FILTF_MASK);
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
default:
break;
}
return status;
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
uint32_t reg;
reg = base->FILT;
switch (filterIndex)
{
case 1:
reg |= LLWU_FILT_FILTF1_MASK;
break;
case 2:
reg |= LLWU_FILT_FILTF2_MASK;
break;
case 3:
reg |= LLWU_FILT_FILTF3_MASK;
break;
case 4:
reg |= LLWU_FILT_FILTF4_MASK;
break;
default:
break;
}
base->FILT = reg;
#else
volatile uint8_t *regBase;
uint8_t reg;
switch (filterIndex)
{
case 1:
regBase = &base->FILT1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2:
regBase = &base->FILT2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3:
regBase = &base->FILT3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4:
regBase = &base->FILT4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
default:
regBase = NULL;
break;
}
if (regBase)
{
reg = *regBase;
reg |= LLWU_FILT1_FILTF_MASK;
*regBase = reg;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_RESET_ENABLE) && FSL_FEATURE_LLWU_HAS_RESET_ENABLE)
void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode)
{
uint8_t reg;
reg = base->RST;
reg &= ~(LLWU_RST_LLRSTE_MASK | LLWU_RST_RSTFILT_MASK);
reg |=
(((uint32_t)pinEnable << LLWU_RST_LLRSTE_SHIFT) | ((uint32_t)enableInLowLeakageMode << LLWU_RST_RSTFILT_SHIFT));
base->RST = reg;
}
#endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */

View File

@ -0,0 +1,321 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_LLWU_H_
#define _FSL_LLWU_H_
#include "fsl_common.h"
/*! @addtogroup llwu */
/*! @{ */
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LLWU driver version 2.0.1. */
#define FSL_LLWU_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*!
* @brief External input pin control modes
*/
typedef enum _llwu_external_pin_mode
{
kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as wakeup input. */
kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with rising edge detection. */
kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with falling edge detection.*/
kLLWU_ExternalPinAnyEdge = 3U /*!< Pin enabled with any change detection. */
} llwu_external_pin_mode_t;
/*!
* @brief Digital filter control modes
*/
typedef enum _llwu_pin_filter_mode
{
kLLWU_PinFilterDisable = 0U, /*!< Filter disabled. */
kLLWU_PinFilterRisingEdge = 1U, /*!< Filter positive edge detection.*/
kLLWU_PinFilterFallingEdge = 2U, /*!< Filter negative edge detection.*/
kLLWU_PinFilterAnyEdge = 3U /*!< Filter any edge detection. */
} llwu_pin_filter_mode_t;
#if (defined(FSL_FEATURE_LLWU_HAS_VERID) && FSL_FEATURE_LLWU_HAS_VERID)
/*!
* @brief IP version ID definition.
*/
typedef struct _llwu_version_id
{
uint16_t feature; /*!< Feature Specification Number. */
uint8_t minor; /*!< Minor version number. */
uint8_t major; /*!< Major version number. */
} llwu_version_id_t;
#endif /* FSL_FEATURE_LLWU_HAS_VERID */
#if (defined(FSL_FEATURE_LLWU_HAS_PARAM) && FSL_FEATURE_LLWU_HAS_PARAM)
/*!
* @brief IP parameter definition.
*/
typedef struct _llwu_param
{
uint8_t filters; /*!< Number of pin filter. */
uint8_t dmas; /*!< Number of wakeup DMA. */
uint8_t modules; /*!< Number of wakeup module. */
uint8_t pins; /*!< Number of wake up pin. */
} llwu_param_t;
#endif /* FSL_FEATURE_LLWU_HAS_PARAM */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
/*!
* @brief External input pin filter control structure
*/
typedef struct _llwu_external_pin_filter_mode
{
uint32_t pinIndex; /*!< Pin number */
llwu_pin_filter_mode_t filterMode; /*!< Filter mode */
} llwu_external_pin_filter_mode_t;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Low-Leakage Wakeup Unit Control APIs
* @{
*/
#if (defined(FSL_FEATURE_LLWU_HAS_VERID) && FSL_FEATURE_LLWU_HAS_VERID)
/*!
* @brief Gets the LLWU version ID.
*
* This function gets the LLWU version ID, including major version number,
* minor version number, and feature specification number.
*
* @param base LLWU peripheral base address.
* @param versionId Pointer to version ID structure.
*/
static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *versionId)
{
*((uint32_t *)versionId) = base->VERID;
}
#endif /* FSL_FEATURE_LLWU_HAS_VERID */
#if (defined(FSL_FEATURE_LLWU_HAS_PARAM) && FSL_FEATURE_LLWU_HAS_PARAM)
/*!
* @brief Gets the LLWU parameter.
*
* This function gets the LLWU parameter, including wakeup pin number, module
* number, DMA number, and pin filter number.
*
* @param base LLWU peripheral base address.
* @param param Pointer to LLWU param structure.
*/
static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param)
{
*((uint32_t *)param) = base->PARAM;
}
#endif /* FSL_FEATURE_LLWU_HAS_PARAM */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN)
/*!
* @brief Sets the external input pin source mode.
*
* This function sets the external input pin source mode that is used
* as a wake up source.
*
* @param base LLWU peripheral base address.
* @param pinIndex pin index which to be enabled as external wakeup source, start from 1.
* @param pinMode pin configuration mode defined in llwu_external_pin_modes_t
*/
void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode);
/*!
* @brief Gets the external wakeup source flag.
*
* This function checks the external pin flag to detect whether the MCU is
* woke up by the specific pin.
*
* @param base LLWU peripheral base address.
* @param pinIndex pin index, start from 1.
* @return true if the specific pin is wake up source.
*/
bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex);
/*!
* @brief Clears the external wakeup source flag.
*
* This function clears the external wakeup source flag for a specific pin.
*
* @param base LLWU peripheral base address.
* @param pinIndex pin index, start from 1.
*/
void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex);
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE) && FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE)
/*!
* @brief Enables/disables the internal module source.
*
* This function enables/disables the internal module source mode that is used
* as a wake up source.
*
* @param base LLWU peripheral base address.
* @param moduleIndex module index which to be enabled as internal wakeup source, start from 1.
* @param enable enable or disable setting
*/
static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable)
{
if (enable)
{
base->ME |= 1U << moduleIndex;
}
else
{
base->ME &= ~(1U << moduleIndex);
}
}
/*!
* @brief Gets the external wakeup source flag.
*
* This function checks the external pin flag to detect whether the system is
* woke up by the specific pin.
*
* @param base LLWU peripheral base address.
* @param moduleIndex module index, start from 1.
* @return true if the specific pin is wake up source.
*/
static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t moduleIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
return (bool)(base->MF & (1U << moduleIndex));
#else
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
return (bool)(base->MF5 & (1U << moduleIndex));
#else
return (bool)(base->F5 & (1U << moduleIndex));
#endif /* FSL_FEATURE_LLWU_HAS_PF */
#else
#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
return (bool)(base->PF3 & (1U << moduleIndex));
#else
return (bool)(base->F3 & (1U << moduleIndex));
#endif
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
#endif /* FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE */
#if (defined(FSL_FEATURE_LLWU_HAS_DMA_ENABLE_REG) && FSL_FEATURE_LLWU_HAS_DMA_ENABLE_REG)
/*!
* @brief Enables/disables the internal module DMA wakeup source.
*
* This function enables/disables the internal DMA that is used as a wake up source.
*
* @param base LLWU peripheral base address.
* @param moduleIndex Internal module index which used as DMA request source, start from 1.
* @param enable Enable or disable DMA request source
*/
static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable)
{
if (enable)
{
base->DE |= 1U << moduleIndex;
}
else
{
base->DE &= ~(1U << moduleIndex);
}
}
#endif /* FSL_FEATURE_LLWU_HAS_DMA_ENABLE_REG */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
/*!
* @brief Sets the pin filter configuration.
*
* This function sets the pin filter configuration.
*
* @param base LLWU peripheral base address.
* @param filterIndex pin filter index which used to enable/disable the digital filter, start from 1.
* @param filterMode filter mode configuration
*/
void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode);
/*!
* @brief Gets the pin filter configuration.
*
* This function gets the pin filter flag.
*
* @param base LLWU peripheral base address.
* @param filterIndex pin filter index, start from 1.
* @return true if the flag is a source of existing a low-leakage power mode.
*/
bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex);
/*!
* @brief Clear the pin filter configuration.
*
* This function clear the pin filter flag.
*
* @param base LLWU peripheral base address.
* @param filterIndex pin filter index which to be clear the flag, start from 1.
*/
void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex);
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_RESET_ENABLE) && FSL_FEATURE_LLWU_HAS_RESET_ENABLE)
/*!
* @brief Sets the reset pin mode.
*
* This function sets how the reset pin is used as a low leakage mode exit source.
*
* @param pinEnable Enable reset pin filter
* @param pinFilterEnable Specify whether pin filter is enabled in Low-Leakage power mode.
*/
void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode);
#endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LLWU_H_*/

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_lptmr.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the instance from the base address to be used to gate or ungate the module clock
*
* @param base LPTMR peripheral base address
*
* @return The LPTMR instance
*/
static uint32_t LPTMR_GetInstance(LPTMR_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to LPTMR bases for each instance. */
static LPTMR_Type *const s_lptmrBases[] = LPTMR_BASE_PTRS;
/*! @brief Pointers to LPTMR clocks for each instance. */
static const clock_ip_name_t s_lptmrClocks[] = LPTMR_CLOCKS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t LPTMR_GetInstance(LPTMR_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_LPTMR_COUNT; instance++)
{
if (s_lptmrBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_LPTMR_COUNT);
return instance;
}
void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config)
{
assert(config);
/* Ungate the LPTMR clock*/
CLOCK_EnableClock(s_lptmrClocks[LPTMR_GetInstance(base)]);
/* Configure the timers operation mode and input pin setup */
base->CSR = (LPTMR_CSR_TMS(config->timerMode) | LPTMR_CSR_TFC(config->enableFreeRunning) |
LPTMR_CSR_TPP(config->pinPolarity) | LPTMR_CSR_TPS(config->pinSelect));
/* Configure the prescale value and clock source */
base->PSR = (LPTMR_PSR_PRESCALE(config->value) | LPTMR_PSR_PBYP(config->bypassPrescaler) |
LPTMR_PSR_PCS(config->prescalerClockSource));
}
void LPTMR_Deinit(LPTMR_Type *base)
{
/* Disable the LPTMR and reset the internal logic */
base->CSR &= ~LPTMR_CSR_TEN_MASK;
/* Gate the LPTMR clock*/
CLOCK_DisableClock(s_lptmrClocks[LPTMR_GetInstance(base)]);
}
void LPTMR_GetDefaultConfig(lptmr_config_t *config)
{
assert(config);
/* Use time counter mode */
config->timerMode = kLPTMR_TimerModeTimeCounter;
/* Use input 0 as source in pulse counter mode */
config->pinSelect = kLPTMR_PinSelectInput_0;
/* Pulse input pin polarity is active-high */
config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
/* Counter resets whenever TCF flag is set */
config->enableFreeRunning = false;
/* Bypass the prescaler */
config->bypassPrescaler = true;
/* LPTMR clock source */
config->prescalerClockSource = kLPTMR_PrescalerClock_1;
/* Divide the prescaler clock by 2 */
config->value = kLPTMR_Prescale_Glitch_0;
}

View File

@ -0,0 +1,351 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_LPTMR_H_
#define _FSL_LPTMR_H_
#include "fsl_common.h"
/*!
* @addtogroup lptmr_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@}*/
/*! @brief LPTMR pin selection, used in pulse counter mode.*/
typedef enum _lptmr_pin_select
{
kLPTMR_PinSelectInput_0 = 0x0U, /*!< Pulse counter input 0 is selected */
kLPTMR_PinSelectInput_1 = 0x1U, /*!< Pulse counter input 1 is selected */
kLPTMR_PinSelectInput_2 = 0x2U, /*!< Pulse counter input 2 is selected */
kLPTMR_PinSelectInput_3 = 0x3U /*!< Pulse counter input 3 is selected */
} lptmr_pin_select_t;
/*! @brief LPTMR pin polarity, used in pulse counter mode.*/
typedef enum _lptmr_pin_polarity
{
kLPTMR_PinPolarityActiveHigh = 0x0U, /*!< Pulse Counter input source is active-high */
kLPTMR_PinPolarityActiveLow = 0x1U /*!< Pulse Counter input source is active-low */
} lptmr_pin_polarity_t;
/*! @brief LPTMR timer mode selection.*/
typedef enum _lptmr_timer_mode
{
kLPTMR_TimerModeTimeCounter = 0x0U, /*!< Time Counter mode */
kLPTMR_TimerModePulseCounter = 0x1U /*!< Pulse Counter mode */
} lptmr_timer_mode_t;
/*! @brief LPTMR prescaler/glitch filter values*/
typedef enum _lptmr_prescaler_glitch_value
{
kLPTMR_Prescale_Glitch_0 = 0x0U, /*!< Prescaler divide 2, glitch filter does not support this setting */
kLPTMR_Prescale_Glitch_1 = 0x1U, /*!< Prescaler divide 4, glitch filter 2 */
kLPTMR_Prescale_Glitch_2 = 0x2U, /*!< Prescaler divide 8, glitch filter 4 */
kLPTMR_Prescale_Glitch_3 = 0x3U, /*!< Prescaler divide 16, glitch filter 8 */
kLPTMR_Prescale_Glitch_4 = 0x4U, /*!< Prescaler divide 32, glitch filter 16 */
kLPTMR_Prescale_Glitch_5 = 0x5U, /*!< Prescaler divide 64, glitch filter 32 */
kLPTMR_Prescale_Glitch_6 = 0x6U, /*!< Prescaler divide 128, glitch filter 64 */
kLPTMR_Prescale_Glitch_7 = 0x7U, /*!< Prescaler divide 256, glitch filter 128 */
kLPTMR_Prescale_Glitch_8 = 0x8U, /*!< Prescaler divide 512, glitch filter 256 */
kLPTMR_Prescale_Glitch_9 = 0x9U, /*!< Prescaler divide 1024, glitch filter 512*/
kLPTMR_Prescale_Glitch_10 = 0xAU, /*!< Prescaler divide 2048 glitch filter 1024 */
kLPTMR_Prescale_Glitch_11 = 0xBU, /*!< Prescaler divide 4096, glitch filter 2048 */
kLPTMR_Prescale_Glitch_12 = 0xCU, /*!< Prescaler divide 8192, glitch filter 4096 */
kLPTMR_Prescale_Glitch_13 = 0xDU, /*!< Prescaler divide 16384, glitch filter 8192 */
kLPTMR_Prescale_Glitch_14 = 0xEU, /*!< Prescaler divide 32768, glitch filter 16384 */
kLPTMR_Prescale_Glitch_15 = 0xFU /*!< Prescaler divide 65536, glitch filter 32768 */
} lptmr_prescaler_glitch_value_t;
/*!
* @brief LPTMR prescaler/glitch filter clock select.
* @note Clock connections are SoC-specific
*/
typedef enum _lptmr_prescaler_clock_select
{
kLPTMR_PrescalerClock_0 = 0x0U, /*!< Prescaler/glitch filter clock 0 selected. */
kLPTMR_PrescalerClock_1 = 0x1U, /*!< Prescaler/glitch filter clock 1 selected. */
kLPTMR_PrescalerClock_2 = 0x2U, /*!< Prescaler/glitch filter clock 2 selected. */
kLPTMR_PrescalerClock_3 = 0x3U, /*!< Prescaler/glitch filter clock 3 selected. */
} lptmr_prescaler_clock_select_t;
/*! @brief List of LPTMR interrupts */
typedef enum _lptmr_interrupt_enable
{
kLPTMR_TimerInterruptEnable = LPTMR_CSR_TIE_MASK, /*!< Timer interrupt enable */
} lptmr_interrupt_enable_t;
/*! @brief List of LPTMR status flags */
typedef enum _lptmr_status_flags
{
kLPTMR_TimerCompareFlag = LPTMR_CSR_TCF_MASK, /*!< Timer compare flag */
} lptmr_status_flags_t;
/*!
* @brief LPTMR config structure
*
* This structure holds the configuration settings for the LPTMR peripheral. To initialize this
* structure to reasonable defaults, call the LPTMR_GetDefaultConfig() function and pass a
* pointer to your config structure instance.
*
* The config struct can be made const so it resides in flash
*/
typedef struct _lptmr_config
{
lptmr_timer_mode_t timerMode; /*!< Time counter mode or pulse counter mode */
lptmr_pin_select_t pinSelect; /*!< LPTMR pulse input pin select; used only in pulse counter mode */
lptmr_pin_polarity_t pinPolarity; /*!< LPTMR pulse input pin polarity; used only in pulse counter mode */
bool enableFreeRunning; /*!< true: enable free running, counter is reset on overflow
false: counter is reset when the compare flag is set */
bool bypassPrescaler; /*!< true: bypass prescaler; false: use clock from prescaler */
lptmr_prescaler_clock_select_t prescalerClockSource; /*!< LPTMR clock source */
lptmr_prescaler_glitch_value_t value; /*!< Prescaler or glitch filter value */
} lptmr_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungate the LPTMR clock and configures the peripheral for basic operation.
*
* @note This API should be called at the beginning of the application using the LPTMR driver.
*
* @param base LPTMR peripheral base address
* @param config Pointer to user's LPTMR config structure.
*/
void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config);
/*!
* @brief Gate the LPTMR clock
*
* @param base LPTMR peripheral base address
*/
void LPTMR_Deinit(LPTMR_Type *base);
/*!
* @brief Fill in the LPTMR config struct with the default settings
*
* The default values are:
* @code
* config->timerMode = kLPTMR_TimerModeTimeCounter;
* config->pinSelect = kLPTMR_PinSelectInput_0;
* config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
* config->enableFreeRunning = false;
* config->bypassPrescaler = true;
* config->prescalerClockSource = kLPTMR_PrescalerClock_1;
* config->value = kLPTMR_Prescale_Glitch_0;
* @endcode
* @param config Pointer to user's LPTMR config structure.
*/
void LPTMR_GetDefaultConfig(lptmr_config_t *config);
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected LPTMR interrupts.
*
* @param base LPTMR peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask)
{
base->CSR |= mask;
}
/*!
* @brief Disables the selected LPTMR interrupts.
*
* @param base LPTMR peripheral base address
* @param mask The interrupts to disable. This is a logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline void LPTMR_DisableInterrupts(LPTMR_Type *base, uint32_t mask)
{
base->CSR &= ~mask;
}
/*!
* @brief Gets the enabled LPTMR interrupts.
*
* @param base LPTMR peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline uint32_t LPTMR_GetEnabledInterrupts(LPTMR_Type *base)
{
return (base->CSR & LPTMR_CSR_TIE_MASK);
}
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the LPTMR status flags
*
* @param base LPTMR peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::lptmr_status_flags_t
*/
static inline uint32_t LPTMR_GetStatusFlags(LPTMR_Type *base)
{
return (base->CSR & LPTMR_CSR_TCF_MASK);
}
/*!
* @brief Clears the LPTMR status flags
*
* @param base LPTMR peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::lptmr_status_flags_t
*/
static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask)
{
base->CSR |= mask;
}
/*! @}*/
/*!
* @name Read and Write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of count.
*
* Timers counts from 0 till it equals the count value set here. The count value is written to
* the CMR register.
*
* @note
* 1. The TCF flag is set with the CNR equals the count provided here and then increments.
* 2. User can call the utility macros provided in fsl_common.h to convert to ticks
*
* @param base LPTMR peripheral base address
* @param ticks Timer period in units of ticks
*/
static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint16_t ticks)
{
base->CMR = ticks;
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value, in a range from 0 to a
* timer period.
*
* @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec
*
* @param base LPTMR peripheral base address
*
* @return Current counter value in ticks
*/
static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base)
{
/* Must first write any value to the CNR. This will synchronize and register the current value
* of the CNR into a temporary register which can then be read
*/
base->CNR = 0U;
return (uint16_t)base->CNR;
}
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the timer counting.
*
* After calling this function, the timer counts up to the CMR register value.
* Each time the timer reaches CMR value and then increments, it generates a
* trigger pulse and sets the timeout interrupt flag. An interrupt will also be
* triggered if the timer interrupt is enabled.
*
* @param base LPTMR peripheral base address
*/
static inline void LPTMR_StartTimer(LPTMR_Type *base)
{
base->CSR |= LPTMR_CSR_TEN_MASK;
}
/*!
* @brief Stops the timer counting.
*
* This function stops the timer counting and resets the timer's counter register
*
* @param base LPTMR peripheral base address
*/
static inline void LPTMR_StopTimer(LPTMR_Type *base)
{
base->CSR &= ~LPTMR_CSR_TEN_MASK;
}
/*! @}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPTMR_H_ */

View File

@ -0,0 +1,753 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_LPUART_H_
#define _FSL_LPUART_H_
#include "fsl_common.h"
/*!
* @addtogroup lpuart_driver
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LPUART driver version 2.1.0. */
#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*! @brief Error codes for the LPUART driver. */
enum _lpuart_status
{
kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */
kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */
kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */
kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */
kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */
kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */
kStatus_LPUART_FlagCannotClearManually =
MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */
kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */
kStatus_LPUART_RxRingBufferOverrun =
MAKE_STATUS(kStatusGroup_LPUART, 8), /*!< LPUART RX software ring buffer overrun. */
kStatus_LPUART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_LPUART, 9), /*!< LPUART RX receiver overrun. */
kStatus_LPUART_NoiseError = MAKE_STATUS(kStatusGroup_LPUART, 10), /*!< LPUART noise error. */
kStatus_LPUART_FramingError = MAKE_STATUS(kStatusGroup_LPUART, 11), /*!< LPUART framing error. */
kStatus_LPUART_ParityError = MAKE_STATUS(kStatusGroup_LPUART, 12), /*!< LPUART parity error. */
};
/*! @brief LPUART parity mode. */
typedef enum _lpuart_parity_mode
{
kLPUART_ParityDisabled = 0x0U, /*!< Parity disabled */
kLPUART_ParityEven = 0x2U, /*!< Parity enabled, type even, bit setting: PE|PT = 10 */
kLPUART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */
} lpuart_parity_mode_t;
/*! @brief LPUART stop bit count. */
typedef enum _lpuart_stop_bit_count
{
kLPUART_OneStopBit = 0U, /*!< One stop bit */
kLPUART_TwoStopBit = 1U, /*!< Two stop bits */
} lpuart_stop_bit_count_t;
/*!
* @brief LPUART interrupt configuration structure, default settings all disabled.
*
* This structure contains the settings for all LPUART interrupt configurations.
*/
enum _lpuart_interrupt_enable
{
#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
kLPUART_LinBreakInterruptEnable = (LPUART_BAUD_LBKDIE_MASK >> 8), /*!< LIN break detect. */
#endif
kLPUART_RxActiveEdgeInterruptEnable = (LPUART_BAUD_RXEDGIE_MASK >> 8), /*!< Receive Active Edge. */
kLPUART_TxDataRegEmptyInterruptEnable = (LPUART_CTRL_TIE_MASK), /*!< Transmit data register empty. */
kLPUART_TransmissionCompleteInterruptEnable = (LPUART_CTRL_TCIE_MASK), /*!< Transmission complete. */
kLPUART_RxDataRegFullInterruptEnable = (LPUART_CTRL_RIE_MASK), /*!< Receiver data register full. */
kLPUART_IdleLineInterruptEnable = (LPUART_CTRL_ILIE_MASK), /*!< Idle line. */
kLPUART_RxOverrunInterruptEnable = (LPUART_CTRL_ORIE_MASK), /*!< Receiver Overrun. */
kLPUART_NoiseErrorInterruptEnable = (LPUART_CTRL_NEIE_MASK), /*!< Noise error flag. */
kLPUART_FramingErrorInterruptEnable = (LPUART_CTRL_FEIE_MASK), /*!< Framing error flag. */
kLPUART_ParityErrorInterruptEnable = (LPUART_CTRL_PEIE_MASK), /*!< Parity error flag. */
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
kLPUART_TxFifoOverflowInterruptEnable = (LPUART_FIFO_TXOFE_MASK >> 8), /*!< Transmit FIFO Overflow. */
kLPUART_RxFifoUnderflowInterruptEnable = (LPUART_FIFO_RXUFE_MASK >> 8), /*!< Receive FIFO Underflow. */
#endif
};
/*!
* @brief LPUART status flags.
*
* This provides constants for the LPUART status flags for use in the LPUART functions.
*/
enum _lpuart_flags
{
kLPUART_TxDataRegEmptyFlag =
(LPUART_STAT_TDRE_MASK), /*!< Transmit data register empty flag, sets when transmit buffer is empty */
kLPUART_TransmissionCompleteFlag =
(LPUART_STAT_TC_MASK), /*!< Transmission complete flag, sets when transmission activity complete */
kLPUART_RxDataRegFullFlag =
(LPUART_STAT_RDRF_MASK), /*!< Receive data register full flag, sets when the receive data buffer is full */
kLPUART_IdleLineFlag = (LPUART_STAT_IDLE_MASK), /*!< Idle line detect flag, sets when idle line detected */
kLPUART_RxOverrunFlag = (LPUART_STAT_OR_MASK), /*!< Receive Overrun, sets when new data is received before data is
read from receive register */
kLPUART_NoiseErrorFlag = (LPUART_STAT_NF_MASK), /*!< Receive takes 3 samples of each received bit. If any of these
samples differ, noise flag sets */
kLPUART_FramingErrorFlag =
(LPUART_STAT_FE_MASK), /*!< Frame error flag, sets if logic 0 was detected where stop bit expected */
kLPUART_ParityErrorFlag = (LPUART_STAT_PF_MASK), /*!< If parity enabled, sets upon parity error detection */
#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
kLPUART_LinBreakFlag = (LPUART_STAT_LBKDIF_MASK), /*!< LIN break detect interrupt flag, sets when LIN break char
detected and LIN circuit enabled */
#endif
kLPUART_RxActiveEdgeFlag =
(LPUART_STAT_RXEDGIF_MASK), /*!< Receive pin active edge interrupt flag, sets when active edge detected */
kLPUART_RxActiveFlag =
(LPUART_STAT_RAF_MASK), /*!< Receiver Active Flag (RAF), sets at beginning of valid start bit */
#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
kLPUART_DataMatch1Flag = LPUART_STAT_MA1F_MASK, /*!< The next character to be read from LPUART_DATA matches MA1*/
kLPUART_DataMatch2Flag = LPUART_STAT_MA2F_MASK, /*!< The next character to be read from LPUART_DATA matches MA2*/
#endif
#if defined(FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS
kLPUART_NoiseErrorInRxDataRegFlag =
(LPUART_DATA_NOISY_MASK >> 10), /*!< NOISY bit, sets if noise detected in current data word */
kLPUART_ParityErrorInRxDataRegFlag =
(LPUART_DATA_PARITYE_MASK >> 10), /*!< PARITYE bit, sets if noise detected in current data word */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
kLPUART_TxFifoEmptyFlag = (LPUART_FIFO_TXEMPT_MASK >> 16), /*!< TXEMPT bit, sets if transmit buffer is empty */
kLPUART_RxFifoEmptyFlag = (LPUART_FIFO_RXEMPT_MASK >> 16), /*!< RXEMPT bit, sets if receive buffer is empty */
kLPUART_TxFifoOverflowFlag =
(LPUART_FIFO_TXOF_MASK >> 16), /*!< TXOF bit, sets if transmit buffer overflow occurred */
kLPUART_RxFifoUnderflowFlag =
(LPUART_FIFO_RXUF_MASK >> 16), /*!< RXUF bit, sets if receive buffer underflow occurred */
#endif
};
/*! @brief LPUART configure structure. */
typedef struct _lpuart_config
{
uint32_t baudRate_Bps; /*!< LPUART baud rate */
lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */
#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
uint8_t txFifoWatermark; /*!< TX FIFO watermark */
uint8_t rxFifoWatermark; /*!< RX FIFO watermark */
#endif
bool enableTx; /*!< Enable TX */
bool enableRx; /*!< Enable RX */
} lpuart_config_t;
/*! @brief LPUART transfer structure. */
typedef struct _lpuart_transfer
{
uint8_t *data; /*!< The buffer of data to be transfer.*/
size_t dataSize; /*!< The byte count to be transfer. */
} lpuart_transfer_t;
/* Forward declaration of the handle typedef. */
typedef struct _lpuart_handle lpuart_handle_t;
/*! @brief LPUART transfer callback function. */
typedef void (*lpuart_transfer_callback_t)(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData);
/*! @brief LPUART handle structure. */
struct _lpuart_handle
{
uint8_t *volatile txData; /*!< Address of remaining data to send. */
volatile size_t txDataSize; /*!< Size of the remaining data to send. */
size_t txDataSizeAll; /*!< Size of the data to send out. */
uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
size_t rxDataSizeAll; /*!< Size of the data to receive. */
uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
size_t rxRingBufferSize; /*!< Size of the ring buffer. */
volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
lpuart_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< LPUART callback function parameter.*/
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock.
*
* This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function
* to configure the configuration structure and get the default configuration.
* The example below shows how to use this API to configure the LPUART.
* @code
* lpuart_config_t lpuartConfig;
* lpuartConfig.baudRate_Bps = 115200U;
* lpuartConfig.parityMode = kLPUART_ParityDisabled;
* lpuartConfig.stopBitCount = kLPUART_OneStopBit;
* lpuartConfig.txFifoWatermark = 0;
* lpuartConfig.rxFifoWatermark = 1;
* LPUART_Init(LPUART1, &lpuartConfig, 20000000U);
* @endcode
*
* @param base LPUART peripheral base address.
* @param config Pointer to a user-defined configuration structure.
* @param srcClock_Hz LPUART clock source frequency in HZ.
*/
void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz);
/*!
* @brief Deinitializes a LPUART instance.
*
* This function waits for transmit to complete, disables TX and RX, and disables the LPUART clock.
*
* @param base LPUART peripheral base address.
*/
void LPUART_Deinit(LPUART_Type *base);
/*!
* @brief Gets the default configuration structure.
*
* This function initializes the LPUART configuration structure to a default value. The default
* values are:
* lpuartConfig->baudRate_Bps = 115200U;
* lpuartConfig->parityMode = kLPUART_ParityDisabled;
* lpuartConfig->stopBitCount = kLPUART_OneStopBit;
* lpuartConfig->txFifoWatermark = 0;
* lpuartConfig->rxFifoWatermark = 1;
* lpuartConfig->enableTx = false;
* lpuartConfig->enableRx = false;
*
* @param config Pointer to a configuration structure.
*/
void LPUART_GetDefaultConfig(lpuart_config_t *config);
/*!
* @brief Sets the LPUART instance baudrate.
*
* This function configures the LPUART module baudrate. This function is used to update
* the LPUART module baudrate after the LPUART module is initialized by the LPUART_Init.
* @code
* LPUART_SetBaudRate(LPUART1, 115200U, 20000000U);
* @endcode
*
* @param base LPUART peripheral base address.
* @param baudRate_Bps LPUART baudrate to be set.
* @param srcClock_Hz LPUART clock source frequency in HZ.
*/
void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets LPUART status flags.
*
* This function gets all LPUART status flags. The flags are returned as the logical
* OR value of the enumerators @ref _lpuart_flags. To check for a specific status,
* compare the return value with enumerators in the @ref _lpuart_flags.
* For example, to check whether the TX is empty:
* @code
* if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1))
* {
* ...
* }
* @endcode
*
* @param base LPUART peripheral base address.
* @return LPUART status flags which are ORed by the enumerators in the _lpuart_flags.
*/
uint32_t LPUART_GetStatusFlags(LPUART_Type *base);
/*!
* @brief Clears status flags with a provided mask.
*
* This function clears LPUART status flags with a provided mask. Automatically cleared flags
* can't be cleared by this function.
* Flags that can only cleared or set by hardware are:
* kLPUART_TxDataRegEmptyFlag, kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag,
* kLPUART_RxActiveFlag, kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
* kLPUART_TxFifoEmptyFlag,kLPUART_RxFifoEmptyFlag
* Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects.
*
* @param base LPUART peripheral base address.
* @param mask the status flags to be cleared. The user can use the enumerators in the
* _lpuart_status_flag_t to do the OR operation and get the mask.
* @return 0 succeed, others failed.
* @retval kStatus_LPUART_FlagCannotClearManually The flag can't be cleared by this function but
* it is cleared automatically by hardware.
* @retval kStatus_Success Status in the mask are cleared.
*/
status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask);
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables LPUART interrupts according to a provided mask.
*
* This function enables the LPUART interrupts according to a provided mask. The mask
* is a logical OR of enumeration members. See the @ref _lpuart_interrupt_enable.
* This examples shows how to enable TX empty interrupt and RX full interrupt:
* @code
* LPUART_EnableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
* @endcode
*
* @param base LPUART peripheral base address.
* @param mask The interrupts to enable. Logical OR of @ref _uart_interrupt_enable.
*/
void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask);
/*!
* @brief Disables LPUART interrupts according to a provided mask.
*
* This function disables the LPUART interrupts according to a provided mask. The mask
* is a logical OR of enumeration members. See @ref _lpuart_interrupt_enable.
* This example shows how to disable the TX empty interrupt and RX full interrupt:
* @code
* LPUART_DisableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
* @endcode
*
* @param base LPUART peripheral base address.
* @param mask The interrupts to disable. Logical OR of @ref _lpuart_interrupt_enable.
*/
void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask);
/*!
* @brief Gets enabled LPUART interrupts.
*
* This function gets the enabled LPUART interrupts. The enabled interrupts are returned
* as the logical OR value of the enumerators @ref _lpuart_interrupt_enable. To check
* a specific interrupt enable status, compare the return value with enumerators
* in @ref _lpuart_interrupt_enable.
* For example, to check whether the TX empty interrupt is enabled:
* @code
* uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART1);
*
* if (kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts)
* {
* ...
* }
* @endcode
*
* @param base LPUART peripheral base address.
* @return LPUART interrupt flags which are logical OR of the enumerators in @ref _lpuart_interrupt_enable.
*/
uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base);
#if defined(FSL_FEATURE_LPUART_HAS_DMA_ENABLE) && FSL_FEATURE_LPUART_HAS_DMA_ENABLE
/*!
* @brief Gets the LPUART data register address.
*
* This function returns the LPUART data register address, which is mainly used by the DMA/eDMA.
*
* @param base LPUART peripheral base address.
* @return LPUART data register addresses which are used both by the transmitter and receiver.
*/
static inline uint32_t LPUART_GetDataRegisterAddress(LPUART_Type *base)
{
return (uint32_t) & (base->DATA);
}
/*!
* @brief Enables or disables the LPUART transmitter DMA request.
*
* This function enables or disables the transmit data register empty flag, STAT[TDRE], to generate DMA requests.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableTxDMA(LPUART_Type *base, bool enable)
{
if (enable)
{
base->BAUD |= LPUART_BAUD_TDMAE_MASK;
base->CTRL |= LPUART_CTRL_TIE_MASK;
}
else
{
base->BAUD &= ~LPUART_BAUD_TDMAE_MASK;
base->CTRL &= ~LPUART_CTRL_TIE_MASK;
}
}
/*!
* @brief Enables or disables the LPUART receiver DMA.
*
* This function enables or disables the receiver data register full flag, STAT[RDRF], to generate DMA requests.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableRxDMA(LPUART_Type *base, bool enable)
{
if (enable)
{
base->BAUD |= LPUART_BAUD_RDMAE_MASK;
base->CTRL |= LPUART_CTRL_RIE_MASK;
}
else
{
base->BAUD &= ~LPUART_BAUD_RDMAE_MASK;
base->CTRL &= ~LPUART_CTRL_RIE_MASK;
}
}
/* @} */
#endif /* FSL_FEATURE_LPUART_HAS_DMA_ENABLE */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables or disables the LPUART transmitter.
*
* This function enables or disables the LPUART transmitter.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableTx(LPUART_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= LPUART_CTRL_TE_MASK;
}
else
{
base->CTRL &= ~LPUART_CTRL_TE_MASK;
}
}
/*!
* @brief Enables or disables the LPUART receiver.
*
* This function enables or disables the LPUART receiver.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableRx(LPUART_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= LPUART_CTRL_RE_MASK;
}
else
{
base->CTRL &= ~LPUART_CTRL_RE_MASK;
}
}
/*!
* @brief Writes to the transmitter register.
*
* This function writes data to the transmitter register directly. The upper layer must
* ensure that the TX register is empty or that the TX FIFO has room before calling this function.
*
* @param base LPUART peripheral base address.
* @param data Data write to the TX register.
*/
static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data)
{
base->DATA = data;
}
/*!
* @brief Reads the RX register.
*
* This function reads data from the TX register directly. The upper layer must
* ensure that the RX register is full or that the TX FIFO has data before calling this function.
*
* @param base LPUART peripheral base address.
* @return Data read from data register.
*/
static inline uint8_t LPUART_ReadByte(LPUART_Type *base)
{
return base->DATA;
}
/*!
* @brief Writes to transmitter register using a blocking method.
*
* This function polls the transmitter register, waits for the register to be empty or for TX FIFO to have
* room and then writes data to the transmitter buffer.
*
* @note This function does not check whether all data has been sent out to the bus.
* Before disabling the transmitter, check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is
* finished.
*
* @param base LPUART peripheral base address.
* @param data Start address of the data to write.
* @param length Size of the data to write.
*/
void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
/*!
* @brief Reads the RX data register using a blocking method.
*
* This function polls the RX register, waits for the RX register full or RX FIFO
* has data then reads data from the TX register.
*
* @param base LPUART peripheral base address.
* @param data Start address of the buffer to store the received data.
* @param length Size of the buffer.
* @retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data.
* @retval kStatus_LPUART_NoiseError Noise error happened while receiving data.
* @retval kStatus_LPUART_FramingError Framing error happened while receiving data.
* @retval kStatus_LPUART_ParityError Parity error happened while receiving data.
* @retval kStatus_Success Successfully received all data.
*/
status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length);
/* @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the LPUART handle.
*
* This function initializes the LPUART handle, which can be used for other LPUART
* transactional APIs. Usually, for a specified LPUART instance,
* call this API once to get the initialized handle.
*
* The LPUART driver supports the "background" receiving, which means that user can set up
* an RX ring buffer optionally. Data received is stored into the ring buffer even when the
* user doesn't call the LPUART_TransferReceiveNonBlocking() API. If there is already data received
* in the ring buffer, the user can get the received data from the ring buffer directly.
* The ring buffer is disabled if passing NULL as @p ringBuffer.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param callback Callback function.
* @param userData User data.
*/
void LPUART_TransferCreateHandle(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_callback_t callback,
void *userData);
/*!
* @brief Transmits a buffer of data using the interrupt method.
*
* This function send data using an interrupt method. This is a non-blocking function, which
* returns directly without waiting for all data written to the transmitter register. When
* all data is written to the TX register in the ISR, the LPUART driver calls the callback
* function and passes the @ref kStatus_LPUART_TxIdle as status parameter.
*
* @note The kStatus_LPUART_TxIdle is passed to the upper layer when all data are written
* to the TX register. However, there is no check to ensure that all the data sent out. Before disabling the TX,
* check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is finished.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART transfer structure, refer to #lpuart_transfer_t.
* @retval kStatus_Success Successfully start the data transmission.
* @retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received is stored into the ring buffer even when
* the user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received
* in the ring buffer, the user can get the received data from the ring buffer directly.
*
* @note When using RX ring buffer, one byte is reserved for internal use. In other
* words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
* @param ringBufferSize size of the ring buffer.
*/
void LPUART_TransferStartRingBuffer(LPUART_Type *base,
lpuart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize);
/*!
* @brief Abort the background transfer and uninstall the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
* how many bytes are still not sent out.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Get the number of bytes that have been written to LPUART TX register.
*
* This function gets the number of bytes that have been written to LPUART TX
* register by interrupt method.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Send bytes count.
* @retval kStatus_NoTransferInProgress No send in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count);
/*!
* @brief Receives a buffer of data using the interrupt method.
*
* This function receives data using an interrupt method. This is a non-blocking function
* which returns without waiting to ensure that all data are received.
* If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in the ring buffer is not enough for read, the receive
* request is saved by the LPUART driver. When the new data arrives, the receive request
* is serviced first. When all data is received, the LPUART driver notifies the upper layer
* through a callback function and passes a status parameter @ref kStatus_UART_RxIdle.
* For example, the upper layer needs 10 bytes but there are only 5 bytes in ring buffer.
* The 5 bytes are copied to xfer->data, which returns with the
* parameter @p receivedBytes set to 5. For the remaining 5 bytes, the newly arrived data is
* saved from xfer->data[5]. When 5 bytes are received, the LPUART driver notifies the upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to xfer->data. When all data is received, the upper layer is notified.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART transfer structure, refer to #uart_transfer_t.
* @param receivedBytes Bytes received from the ring buffer directly.
* @retval kStatus_Success Successfully queue the transfer into the transmit queue.
* @retval kStatus_LPUART_RxBusy Previous receive request is not finished.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_t *xfer,
size_t *receivedBytes);
/*!
* @brief Aborts the interrupt-driven data receiving.
*
* This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
* how many bytes not received yet.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Get the number of bytes that have been received.
*
* This function gets the number of bytes that have been received.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Receive bytes count.
* @retval kStatus_NoTransferInProgress No receive in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count);
/*!
* @brief LPUART IRQ handle function.
*
* This function handles the LPUART transmit and receive IRQ request.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief LPUART Error IRQ handle function.
*
* This function handles the LPUART error IRQ request.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPUART_H_ */

View File

@ -0,0 +1,339 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_lpuart_dma.h"
#include "fsl_dmamux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! Structure definition for lpuart_dma_handle_t. The structure is private. */
typedef struct _lpuart_dma_private_handle
{
LPUART_Type *base;
lpuart_dma_handle_t *handle;
} lpuart_dma_private_handle_t;
/* LPUART DMA transfer handle. */
enum _uart_dma_tansfer_states
{
kLPUART_TxIdle, /* TX idle. */
kLPUART_TxBusy, /* TX busy. */
kLPUART_RxIdle, /* RX idle. */
kLPUART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Variables
******************************************************************************/
/*<! Private handle only used for internally. */
static lpuart_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_LPUART_COUNT];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief LPUART DMA send finished callback function.
*
* This function is called when LPUART DMA send finished. It disables the LPUART
* TX DMA request and sends @ref kStatus_LPUART_TxIdle to LPUART callback.
*
* @param handle The DMA handle.
* @param param Callback function parameter.
*/
static void LPUART_TransferSendDMACallback(dma_handle_t *handle, void *param);
/*!
* @brief LPUART DMA receive finished callback function.
*
* This function is called when LPUART DMA receive finished. It disables the LPUART
* RX DMA request and sends @ref kStatus_LPUART_RxIdle to LPUART callback.
*
* @param handle The DMA handle.
* @param param Callback function parameter.
*/
static void LPUART_TransferReceiveDMACallback(dma_handle_t *handle, void *param);
/*!
* @brief Get the LPUART instance from peripheral base address.
*
* @param base LPUART peripheral base address.
* @return LPUART instance.
*/
extern uint32_t LPUART_GetInstance(LPUART_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static void LPUART_TransferSendDMACallback(dma_handle_t *handle, void *param)
{
lpuart_dma_private_handle_t *lpuartPrivateHandle = (lpuart_dma_private_handle_t *)param;
/* Disable LPUART TX DMA. */
LPUART_EnableTxDMA(lpuartPrivateHandle->base, false);
/* Disable interrupt. */
DMA_DisableInterrupts(lpuartPrivateHandle->handle->txDmaHandle->base,
lpuartPrivateHandle->handle->txDmaHandle->channel);
lpuartPrivateHandle->handle->txState = kLPUART_TxIdle;
if (lpuartPrivateHandle->handle->callback)
{
lpuartPrivateHandle->handle->callback(lpuartPrivateHandle->base, lpuartPrivateHandle->handle,
kStatus_LPUART_TxIdle, lpuartPrivateHandle->handle->userData);
}
}
static void LPUART_TransferReceiveDMACallback(dma_handle_t *handle, void *param)
{
lpuart_dma_private_handle_t *lpuartPrivateHandle = (lpuart_dma_private_handle_t *)param;
/* Disable LPUART RX DMA. */
LPUART_EnableRxDMA(lpuartPrivateHandle->base, false);
/* Disable interrupt. */
DMA_DisableInterrupts(lpuartPrivateHandle->handle->rxDmaHandle->base,
lpuartPrivateHandle->handle->rxDmaHandle->channel);
lpuartPrivateHandle->handle->rxState = kLPUART_RxIdle;
if (lpuartPrivateHandle->handle->callback)
{
lpuartPrivateHandle->handle->callback(lpuartPrivateHandle->base, lpuartPrivateHandle->handle,
kStatus_LPUART_RxIdle, lpuartPrivateHandle->handle->userData);
}
}
void LPUART_TransferCreateHandleDMA(LPUART_Type *base,
lpuart_dma_handle_t *handle,
lpuart_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txDmaHandle,
dma_handle_t *rxDmaHandle)
{
assert(handle);
uint32_t instance = LPUART_GetInstance(base);
memset(handle, 0, sizeof(lpuart_dma_handle_t));
s_dmaPrivateHandle[instance].base = base;
s_dmaPrivateHandle[instance].handle = handle;
handle->rxState = kLPUART_RxIdle;
handle->txState = kLPUART_TxIdle;
handle->callback = callback;
handle->userData = userData;
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
/* Note:
Take care of the RX FIFO, DMA request only assert when received bytes
equal or more than RX water mark, there is potential issue if RX water
mark larger than 1.
For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
5 bytes are received. the last byte will be saved in FIFO but not trigger
DMA transfer because the water mark is 2.
*/
if (rxDmaHandle)
{
base->WATER &= (~LPUART_WATER_RXWATER_MASK);
}
#endif
handle->rxDmaHandle = rxDmaHandle;
handle->txDmaHandle = txDmaHandle;
/* Configure TX. */
if (txDmaHandle)
{
DMA_SetCallback(txDmaHandle, LPUART_TransferSendDMACallback, &s_dmaPrivateHandle[instance]);
}
/* Configure RX. */
if (rxDmaHandle)
{
DMA_SetCallback(rxDmaHandle, LPUART_TransferReceiveDMACallback, &s_dmaPrivateHandle[instance]);
}
}
status_t LPUART_TransferSendDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_transfer_t *xfer)
{
assert(handle->txDmaHandle);
status_t status;
dma_transfer_config_t xferConfig;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous TX not finished. */
if (kLPUART_TxBusy == handle->txState)
{
status = kStatus_LPUART_TxBusy;
}
else
{
handle->txState = kLPUART_TxBusy;
handle->txDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
DMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)LPUART_GetDataRegisterAddress(base),
sizeof(uint8_t), xfer->dataSize, kDMA_MemoryToPeripheral);
/* Submit transfer. */
DMA_SubmitTransfer(handle->txDmaHandle, &xferConfig, kDMA_EnableInterrupt);
DMA_StartTransfer(handle->txDmaHandle);
/* Enable LPUART TX DMA. */
LPUART_EnableTxDMA(base, true);
status = kStatus_Success;
}
return status;
}
status_t LPUART_TransferReceiveDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_transfer_t *xfer)
{
assert(handle->rxDmaHandle);
status_t status;
dma_transfer_config_t xferConfig;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous RX not finished. */
if (kLPUART_RxBusy == handle->rxState)
{
status = kStatus_LPUART_RxBusy;
}
else
{
handle->rxState = kLPUART_RxBusy;
handle->rxDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
DMA_PrepareTransfer(&xferConfig, (void *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data,
sizeof(uint8_t), xfer->dataSize, kDMA_PeripheralToMemory);
/* Submit transfer. */
DMA_SubmitTransfer(handle->rxDmaHandle, &xferConfig, kDMA_EnableInterrupt);
DMA_StartTransfer(handle->rxDmaHandle);
/* Enable LPUART RX DMA. */
LPUART_EnableRxDMA(base, true);
status = kStatus_Success;
}
return status;
}
void LPUART_TransferAbortSendDMA(LPUART_Type *base, lpuart_dma_handle_t *handle)
{
assert(handle->txDmaHandle);
/* Disable LPUART TX DMA. */
LPUART_EnableTxDMA(base, false);
/* Stop transfer. */
DMA_AbortTransfer(handle->txDmaHandle);
/* Write DMA->DSR[DONE] to abort transfer and clear status. */
DMA_ClearChannelStatusFlags(handle->txDmaHandle->base, handle->txDmaHandle->channel, kDMA_TransactionsDoneFlag);
handle->txState = kLPUART_TxIdle;
}
void LPUART_TransferAbortReceiveDMA(LPUART_Type *base, lpuart_dma_handle_t *handle)
{
assert(handle->rxDmaHandle);
/* Disable LPUART RX DMA. */
LPUART_EnableRxDMA(base, false);
/* Stop transfer. */
DMA_AbortTransfer(handle->rxDmaHandle);
/* Write DMA->DSR[DONE] to abort transfer and clear status. */
DMA_ClearChannelStatusFlags(handle->rxDmaHandle->base, handle->rxDmaHandle->channel, kDMA_TransactionsDoneFlag);
handle->rxState = kLPUART_RxIdle;
}
status_t LPUART_TransferGetSendCountDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, uint32_t *count)
{
assert(handle->txDmaHandle);
if (kLPUART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
if (!count)
{
return kStatus_InvalidArgument;
}
*count = handle->txDataSizeAll - DMA_GetRemainingBytes(handle->txDmaHandle->base, handle->txDmaHandle->channel);
return kStatus_Success;
}
status_t LPUART_TransferGetReceiveCountDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, uint32_t *count)
{
assert(handle->rxDmaHandle);
if (kLPUART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
if (!count)
{
return kStatus_InvalidArgument;
}
*count = handle->rxDataSizeAll - DMA_GetRemainingBytes(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
return kStatus_Success;
}

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_LPUART_DMA_H_
#define _FSL_LPUART_DMA_H_
#include "fsl_lpuart.h"
#include "fsl_dma.h"
/*!
* @addtogroup lpuart_dma_driver
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Forward declaration of the handle typedef. */
typedef struct _lpuart_dma_handle lpuart_dma_handle_t;
/*! @brief LPUART transfer callback function. */
typedef void (*lpuart_dma_transfer_callback_t)(LPUART_Type *base,
lpuart_dma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief LPUART DMA handle
*/
struct _lpuart_dma_handle
{
lpuart_dma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< LPUART callback function parameter.*/
size_t rxDataSizeAll; /*!< Size of the data to receive. */
size_t txDataSizeAll; /*!< Size of the data to send out. */
dma_handle_t *txDmaHandle; /*!< The DMA TX channel used. */
dma_handle_t *rxDmaHandle; /*!< The DMA RX channel used. */
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name EDMA transactional
* @{
*/
/*!
* @brief Initializes the LPUART handle which is used in transactional functions.
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_dma_handle_t structure.
* @param callback Callback function.
* @param userData User data.
* @param txDmaHandle User-requested DMA handle for TX DMA transfer.
* @param rxDmaHandle User-requested DMA handle for RX DMA transfer.
*/
void LPUART_TransferCreateHandleDMA(LPUART_Type *base,
lpuart_dma_handle_t *handle,
lpuart_dma_transfer_callback_t callback,
void *userData,
dma_handle_t *txDmaHandle,
dma_handle_t *rxDmaHandle);
/*!
* @brief Sends data using DMA.
*
* This function sends data using DMA. This is a non-blocking function, which returns
* right away. When all data is sent, the send callback function is called.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART DMA transfer structure. See #lpuart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_LPUART_TxBusy Previous transfer on going.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferSendDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Receives data using DMA.
*
* This function receives data using DMA. This is a non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_dma_handle_t structure.
* @param xfer LPUART DMA transfer structure. See #lpuart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_LPUART_RxBusy Previous transfer on going.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferReceiveDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Aborts the sent data using DMA.
*
* This function aborts send data using DMA.
*
* @param base LPUART peripheral base address
* @param handle Pointer to lpuart_dma_handle_t structure
*/
void LPUART_TransferAbortSendDMA(LPUART_Type *base, lpuart_dma_handle_t *handle);
/*!
* @brief Aborts the received data using DMA.
*
* This function aborts the received data using DMA.
*
* @param base LPUART peripheral base address
* @param handle Pointer to lpuart_dma_handle_t structure
*/
void LPUART_TransferAbortReceiveDMA(LPUART_Type *base, lpuart_dma_handle_t *handle);
/*!
* @brief Get the number of bytes that have been written to LPUART TX register.
*
* This function gets the number of bytes that have been written to LPUART TX
* register by DMA.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Send bytes count.
* @retval kStatus_NoTransferInProgress No send in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCountDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, uint32_t *count);
/*!
* @brief Get the number of bytes that have been received.
*
* This function gets the number of bytes that have been received.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Receive bytes count.
* @retval kStatus_NoTransferInProgress No receive in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCountDMA(LPUART_Type *base, lpuart_dma_handle_t *handle, uint32_t *count);
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPUART_DMA_H_ */

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_pit.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the instance from the base address to be used to gate or ungate the module clock
*
* @param base PIT peripheral base address
*
* @return The PIT instance
*/
static uint32_t PIT_GetInstance(PIT_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to PIT bases for each instance. */
static PIT_Type *const s_pitBases[] = PIT_BASE_PTRS;
/*! @brief Pointers to PIT clocks for each instance. */
static const clock_ip_name_t s_pitClocks[] = PIT_CLOCKS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t PIT_GetInstance(PIT_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_PIT_COUNT; instance++)
{
if (s_pitBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_PIT_COUNT);
return instance;
}
void PIT_Init(PIT_Type *base, const pit_config_t *config)
{
assert(config);
/* Ungate the PIT clock*/
CLOCK_EnableClock(s_pitClocks[PIT_GetInstance(base)]);
/* Enable PIT timers */
base->MCR &= ~PIT_MCR_MDIS_MASK;
/* Config timer operation when in debug mode */
if (config->enableRunInDebug)
{
base->MCR &= ~PIT_MCR_FRZ_MASK;
}
else
{
base->MCR |= PIT_MCR_FRZ_MASK;
}
}
void PIT_Deinit(PIT_Type *base)
{
/* Disable PIT timers */
base->MCR |= PIT_MCR_MDIS_MASK;
/* Gate the PIT clock*/
CLOCK_DisableClock(s_pitClocks[PIT_GetInstance(base)]);
}
#if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && FSL_FEATURE_PIT_HAS_LIFETIME_TIMER
uint64_t PIT_GetLifetimeTimerCount(PIT_Type *base)
{
uint32_t valueH = 0U;
uint32_t valueL = 0U;
/* LTMR64H should be read before LTMR64L */
valueH = base->LTMR64H;
valueL = base->LTMR64L;
return (((uint64_t)valueH << 32U) + (uint64_t)(valueL));
}
#endif /* FSL_FEATURE_PIT_HAS_LIFETIME_TIMER */

View File

@ -0,0 +1,355 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_PIT_H_
#define _FSL_PIT_H_
#include "fsl_common.h"
/*!
* @addtogroup pit_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_PIT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@}*/
/*!
* @brief List of PIT channels
* @note Actual number of available channels is SoC dependent
*/
typedef enum _pit_chnl
{
kPIT_Chnl_0 = 0U, /*!< PIT channel number 0*/
kPIT_Chnl_1, /*!< PIT channel number 1 */
kPIT_Chnl_2, /*!< PIT channel number 2 */
kPIT_Chnl_3, /*!< PIT channel number 3 */
} pit_chnl_t;
/*! @brief List of PIT interrupts */
typedef enum _pit_interrupt_enable
{
kPIT_TimerInterruptEnable = PIT_TCTRL_TIE_MASK, /*!< Timer interrupt enable*/
} pit_interrupt_enable_t;
/*! @brief List of PIT status flags */
typedef enum _pit_status_flags
{
kPIT_TimerFlag = PIT_TFLG_TIF_MASK, /*!< Timer flag */
} pit_status_flags_t;
/*!
* @brief PIT config structure
*
* This structure holds the configuration settings for the PIT peripheral. To initialize this
* structure to reasonable defaults, call the PIT_GetDefaultConfig() function and pass a
* pointer to your config structure instance.
*
* The config struct can be made const so it resides in flash
*/
typedef struct _pit_config
{
bool enableRunInDebug; /*!< true: Timers run in debug mode; false: Timers stop in debug mode */
} pit_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the PIT clock, enables the PIT module and configures the peripheral for basic operation.
*
* @note This API should be called at the beginning of the application using the PIT driver.
*
* @param base PIT peripheral base address
* @param config Pointer to user's PIT config structure
*/
void PIT_Init(PIT_Type *base, const pit_config_t *config);
/*!
* @brief Gate the PIT clock and disable the PIT module
*
* @param base PIT peripheral base address
*/
void PIT_Deinit(PIT_Type *base);
/*!
* @brief Fill in the PIT config struct with the default settings
*
* The default values are:
* @code
* config->enableRunInDebug = false;
* @endcode
* @param config Pointer to user's PIT config structure.
*/
static inline void PIT_GetDefaultConfig(pit_config_t *config)
{
assert(config);
/* Timers are stopped in Debug mode */
config->enableRunInDebug = false;
}
#if defined(FSL_FEATURE_PIT_HAS_CHAIN_MODE) && FSL_FEATURE_PIT_HAS_CHAIN_MODE
/*!
* @brief Enables or disables chaining a timer with the previous timer.
*
* When a timer has a chain mode enabled, it only counts after the previous
* timer has expired. If the timer n-1 has counted down to 0, counter n
* decrements the value by one. Each timer is 32-bits, this allows the developers
* to chain timers together and form a longer timer (64-bits and larger). The first timer
* (timer 0) cannot be chained to any other timer.
*
* @param base PIT peripheral base address
* @param channel Timer channel number which is chained with the previous timer
* @param enable Enable or disable chain.
* true: Current timer is chained with the previous timer.
* false: Timer doesn't chain with other timers.
*/
static inline void PIT_SetTimerChainMode(PIT_Type *base, pit_chnl_t channel, bool enable)
{
if (enable)
{
base->CHANNEL[channel].TCTRL |= PIT_TCTRL_CHN_MASK;
}
else
{
base->CHANNEL[channel].TCTRL &= ~PIT_TCTRL_CHN_MASK;
}
}
#endif /* FSL_FEATURE_PIT_HAS_CHAIN_MODE */
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected PIT interrupts.
*
* @param base PIT peripheral base address
* @param channel Timer channel number
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::pit_interrupt_enable_t
*/
static inline void PIT_EnableInterrupts(PIT_Type *base, pit_chnl_t channel, uint32_t mask)
{
base->CHANNEL[channel].TCTRL |= mask;
}
/*!
* @brief Disables the selected PIT interrupts.
*
* @param base PIT peripheral base address
* @param channel Timer channel number
* @param mask The interrupts to disable. This is a logical OR of members of the
* enumeration ::pit_interrupt_enable_t
*/
static inline void PIT_DisableInterrupts(PIT_Type *base, pit_chnl_t channel, uint32_t mask)
{
base->CHANNEL[channel].TCTRL &= ~mask;
}
/*!
* @brief Gets the enabled PIT interrupts.
*
* @param base PIT peripheral base address
* @param channel Timer channel number
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::pit_interrupt_enable_t
*/
static inline uint32_t PIT_GetEnabledInterrupts(PIT_Type *base, pit_chnl_t channel)
{
return (base->CHANNEL[channel].TCTRL & PIT_TCTRL_TIE_MASK);
}
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the PIT status flags
*
* @param base PIT peripheral base address
* @param channel Timer channel number
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::pit_status_flags_t
*/
static inline uint32_t PIT_GetStatusFlags(PIT_Type *base, pit_chnl_t channel)
{
return (base->CHANNEL[channel].TFLG & PIT_TFLG_TIF_MASK);
}
/*!
* @brief Clears the PIT status flags.
*
* @param base PIT peripheral base address
* @param channel Timer channel number
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::pit_status_flags_t
*/
static inline void PIT_ClearStatusFlags(PIT_Type *base, pit_chnl_t channel, uint32_t mask)
{
base->CHANNEL[channel].TFLG = mask;
}
/*! @}*/
/*!
* @name Read and Write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of count.
*
* Timers begin counting from the value set by this function until it reaches 0,
* then it will generate an interrupt and load this regiter value again.
* Writing a new value to this register will not restart the timer; instead the value
* will be loaded after the timer expires.
*
* @note User can call the utility macros provided in fsl_common.h to convert to ticks
*
* @param base PIT peripheral base address
* @param channel Timer channel number
* @param count Timer period in units of ticks
*/
static inline void PIT_SetTimerPeriod(PIT_Type *base, pit_chnl_t channel, uint32_t count)
{
base->CHANNEL[channel].LDVAL = count;
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value, in a range from 0 to a
* timer period.
*
* @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec
*
* @param base PIT peripheral base address
* @param channel Timer channel number
*
* @return Current timer counting value in ticks
*/
static inline uint32_t PIT_GetCurrentTimerCount(PIT_Type *base, pit_chnl_t channel)
{
return base->CHANNEL[channel].CVAL;
}
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the timer counting.
*
* After calling this function, timers load period value, count down to 0 and
* then load the respective start value again. Each time a timer reaches 0,
* it generates a trigger pulse and sets the timeout interrupt flag.
*
* @param base PIT peripheral base address
* @param channel Timer channel number.
*/
static inline void PIT_StartTimer(PIT_Type *base, pit_chnl_t channel)
{
base->CHANNEL[channel].TCTRL |= PIT_TCTRL_TEN_MASK;
}
/*!
* @brief Stops the timer counting.
*
* This function stops every timer counting. Timers reload their periods
* respectively after the next time they call the PIT_DRV_StartTimer.
*
* @param base PIT peripheral base address
* @param channel Timer channel number.
*/
static inline void PIT_StopTimer(PIT_Type *base, pit_chnl_t channel)
{
base->CHANNEL[channel].TCTRL &= ~PIT_TCTRL_TEN_MASK;
}
/*! @}*/
#if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && FSL_FEATURE_PIT_HAS_LIFETIME_TIMER
/*!
* @brief Reads the current lifetime counter value.
*
* The lifetime timer is a 64-bit timer which chains timer 0 and timer 1 together.
* Timer 0 and 1 are chained by calling the PIT_SetTimerChainMode before using this timer.
* The period of lifetime timer is equal to the "period of timer 0 * period of timer 1".
* For the 64-bit value, the higher 32-bit has the value of timer 1, and the lower 32-bit
* has the value of timer 0.
*
* @param base PIT peripheral base address
*
* @return Current lifetime timer value
*/
uint64_t PIT_GetLifetimeTimerCount(PIT_Type *base);
#endif /* FSL_FEATURE_PIT_HAS_LIFETIME_TIMER */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_PIT_H_ */

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_pmc.h"
#if (defined(FSL_FEATURE_PMC_HAS_PARAM) && FSL_FEATURE_PMC_HAS_PARAM)
void PMC_GetParam(PMC_Type *base, pmc_param_t *param)
{
uint32_t reg = base->PARAM;
;
param->vlpoEnable = (bool)(reg & PMC_PARAM_VLPOE_MASK);
param->hvdEnable = (bool)(reg & PMC_PARAM_HVDE_MASK);
}
#endif /* FSL_FEATURE_PMC_HAS_PARAM */
void PMC_ConfigureLowVoltDetect(PMC_Type *base, const pmc_low_volt_detect_config_t *config)
{
base->LVDSC1 = (0U |
#if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV)
((uint32_t)config->voltSelect << PMC_LVDSC1_LVDV_SHIFT) |
#endif
((uint32_t)config->enableInt << PMC_LVDSC1_LVDIE_SHIFT) |
((uint32_t)config->enableReset << PMC_LVDSC1_LVDRE_SHIFT)
/* Clear the Low Voltage Detect Flag with previouse power detect setting */
| PMC_LVDSC1_LVDACK_MASK);
}
void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_config_t *config)
{
base->LVDSC2 = (0U |
#if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV)
((uint32_t)config->voltSelect << PMC_LVDSC2_LVWV_SHIFT) |
#endif
((uint32_t)config->enableInt << PMC_LVDSC2_LVWIE_SHIFT)
/* Clear the Low Voltage Warning Flag with previouse power detect setting */
| PMC_LVDSC2_LVWACK_MASK);
}
#if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1)
void PMC_ConfigureHighVoltDetect(PMC_Type *base, const pmc_high_volt_detect_config_t *config)
{
base->HVDSC1 = (((uint32_t)config->voltSelect << PMC_HVDSC1_HVDV_SHIFT) |
((uint32_t)config->enableInt << PMC_HVDSC1_HVDIE_SHIFT) |
((uint32_t)config->enableReset << PMC_HVDSC1_HVDRE_SHIFT)
/* Clear the High Voltage Detect Flag with previouse power detect setting */
| PMC_HVDSC1_HVDACK_MASK);
}
#endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */
#if ((defined(FSL_FEATURE_PMC_HAS_BGBE) && FSL_FEATURE_PMC_HAS_BGBE) || \
(defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) || \
(defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS))
void PMC_ConfigureBandgapBuffer(PMC_Type *base, const pmc_bandgap_buffer_config_t *config)
{
base->REGSC = (0U
#if (defined(FSL_FEATURE_PMC_HAS_BGBE) && FSL_FEATURE_PMC_HAS_BGBE)
| ((uint32_t)config->enable << PMC_REGSC_BGBE_SHIFT)
#endif /* FSL_FEATURE_PMC_HAS_BGBE */
#if (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN)
| (((uint32_t)config->enableInLowPowerMode << PMC_REGSC_BGEN_SHIFT))
#endif /* FSL_FEATURE_PMC_HAS_BGEN */
#if (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS)
| ((uint32_t)config->drive << PMC_REGSC_BGBDS_SHIFT)
#endif /* FSL_FEATURE_PMC_HAS_BGBDS */
);
}
#endif

View File

@ -0,0 +1,423 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_PMC_H_
#define _FSL_PMC_H_
#include "fsl_common.h"
/*! @addtogroup pmc */
/*! @{ */
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief PMC driver version */
#define FSL_PMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
/*@}*/
#if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV)
/*!
* @brief Low-Voltage Detect Voltage Select
*/
typedef enum _pmc_low_volt_detect_volt_select
{
kPMC_LowVoltDetectLowTrip = 0U, /*!< Low trip point selected (VLVD = VLVDL )*/
kPMC_LowVoltDetectHighTrip = 1U /*!< High trip point selected (VLVD = VLVDH )*/
} pmc_low_volt_detect_volt_select_t;
#endif
#if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV)
/*!
* @brief Low-Voltage Warning Voltage Select
*/
typedef enum _pmc_low_volt_warning_volt_select
{
kPMC_LowVoltWarningLowTrip = 0U, /*!< Low trip point selected (VLVW = VLVW1)*/
kPMC_LowVoltWarningMid1Trip = 1U, /*!< Mid 1 trip point selected (VLVW = VLVW2)*/
kPMC_LowVoltWarningMid2Trip = 2U, /*!< Mid 2 trip point selected (VLVW = VLVW3)*/
kPMC_LowVoltWarningHighTrip = 3U /*!< High trip point selected (VLVW = VLVW4)*/
} pmc_low_volt_warning_volt_select_t;
#endif
#if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1)
/*!
* @brief High-Voltage Detect Voltage Select
*/
typedef enum _pmc_high_volt_detect_volt_select
{
kPMC_HighVoltDetectLowTrip = 0U, /*!< Low trip point selected (VHVD = VHVDL )*/
kPMC_HighVoltDetectHighTrip = 1U /*!< High trip point selected (VHVD = VHVDH )*/
} pmc_high_volt_detect_volt_select_t;
#endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */
#if (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS)
/*!
* @brief Bandgap Buffer Drive Select.
*/
typedef enum _pmc_bandgap_buffer_drive_select
{
kPMC_BandgapBufferDriveLow = 0U, /*!< Low drive. */
kPMC_BandgapBufferDriveHigh = 1U /*!< High drive. */
} pmc_bandgap_buffer_drive_select_t;
#endif /* FSL_FEATURE_PMC_HAS_BGBDS */
#if (defined(FSL_FEATURE_PMC_HAS_VLPO) && FSL_FEATURE_PMC_HAS_VLPO)
/*!
* @brief VLPx Option
*/
typedef enum _pmc_vlp_freq_option
{
kPMC_FreqRestrict = 0U, /*!< Frequency is restricted in VLPx mode. */
kPMC_FreqUnrestrict = 1U /*!< Frequency is unrestricted in VLPx mode. */
} pmc_vlp_freq_mode_t;
#endif /* FSL_FEATURE_PMC_HAS_VLPO */
#if (defined(FSL_FEATURE_PMC_HAS_VERID) && FSL_FEATURE_PMC_HAS_VERID)
/*!
@brief IP version ID definition.
*/
typedef struct _pmc_version_id
{
uint16_t feature; /*!< Feature Specification Number. */
uint8_t minor; /*!< Minor version number. */
uint8_t major; /*!< Major version number. */
} pmc_version_id_t;
#endif /* FSL_FEATURE_PMC_HAS_VERID */
#if (defined(FSL_FEATURE_PMC_HAS_PARAM) && FSL_FEATURE_PMC_HAS_PARAM)
/*! @brief IP parameter definition. */
typedef struct _pmc_param
{
bool vlpoEnable; /*!< VLPO enable. */
bool hvdEnable; /*!< HVD enable. */
} pmc_param_t;
#endif /* FSL_FEATURE_PMC_HAS_PARAM */
/*!
* @brief Low-Voltage Detect Configuration Structure
*/
typedef struct _pmc_low_volt_detect_config
{
bool enableInt; /*!< Enable interrupt when low voltage detect*/
bool enableReset; /*!< Enable system reset when low voltage detect*/
#if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV)
pmc_low_volt_detect_volt_select_t voltSelect; /*!< Low voltage detect trip point voltage selection*/
#endif
} pmc_low_volt_detect_config_t;
/*!
* @brief Low-Voltage Warning Configuration Structure
*/
typedef struct _pmc_low_volt_warning_config
{
bool enableInt; /*!< Enable interrupt when low voltage warning*/
#if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV)
pmc_low_volt_warning_volt_select_t voltSelect; /*!< Low voltage warning trip point voltage selection*/
#endif
} pmc_low_volt_warning_config_t;
#if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1)
/*!
* @brief High-Voltage Detect Configuration Structure
*/
typedef struct _pmc_high_volt_detect_config
{
bool enableInt; /*!< Enable interrupt when high voltage detect*/
bool enableReset; /*!< Enable system reset when high voltage detect*/
pmc_high_volt_detect_volt_select_t voltSelect; /*!< High voltage detect trip point voltage selection*/
} pmc_high_volt_detect_config_t;
#endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */
#if ((defined(FSL_FEATURE_PMC_HAS_BGBE) && FSL_FEATURE_PMC_HAS_BGBE) || \
(defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) || \
(defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS))
/*!
* @brief Bandgap Buffer configuration.
*/
typedef struct _pmc_bandgap_buffer_config
{
#if (defined(FSL_FEATURE_PMC_HAS_BGBE) && FSL_FEATURE_PMC_HAS_BGBE)
bool enable; /*!< Enable bandgap buffer. */
#endif
#if (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN)
bool enableInLowPowerMode; /*!< Enable bandgap buffer in low power mode. */
#endif /* FSL_FEATURE_PMC_HAS_BGEN */
#if (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS)
pmc_bandgap_buffer_drive_select_t drive; /*!< Bandgap buffer drive select. */
#endif /* FSL_FEATURE_PMC_HAS_BGBDS */
} pmc_bandgap_buffer_config_t;
#endif
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*! @name Power Management Controller Control APIs*/
/*@{*/
#if (defined(FSL_FEATURE_PMC_HAS_VERID) && FSL_FEATURE_PMC_HAS_VERID)
/*!
* @brief Gets the PMC version ID.
*
* This function gets the PMC version ID, including major version number,
* minor version number and feature specification number.
*
* @param base PMC peripheral base address.
* @param versionId Pointer to version ID structure.
*/
static inline void PMC_GetVersionId(PMC_Type *base, pmc_version_id_t *versionId)
{
*((uint32_t *)versionId) = base->VERID;
}
#endif /* FSL_FEATURE_PMC_HAS_VERID */
#if (defined(FSL_FEATURE_PMC_HAS_PARAM) && FSL_FEATURE_PMC_HAS_PARAM)
/*!
* @brief Gets the PMC parameter.
*
* This function gets the PMC parameter, including VLPO enable and HVD enable.
*
* @param base PMC peripheral base address.
* @param param Pointer to PMC param structure.
*/
void PMC_GetParam(PMC_Type *base, pmc_param_t *param);
#endif
/*!
* @brief Configure the low voltage detect setting.
*
* This function configures the low voltage detect setting, including the trip
* point voltage setting, enable interrupt or not, enable system reset or not.
*
* @param base PMC peripheral base address.
* @param config Low-Voltage detect configuration structure.
*/
void PMC_ConfigureLowVoltDetect(PMC_Type *base, const pmc_low_volt_detect_config_t *config);
/*!
* @brief Get Low-Voltage Detect Flag status
*
* This function reads the current LVDF status. If it returns 1, a low
* voltage event is detected.
*
* @param base PMC peripheral base address.
* @return Current low voltage detect flag
* - true: Low-Voltage detected
* - false: Low-Voltage not detected
*/
static inline bool PMC_GetLowVoltDetectFlag(PMC_Type *base)
{
return (bool)(base->LVDSC1 & PMC_LVDSC1_LVDF_MASK);
}
/*!
* @brief Acknowledge to clear the Low-Voltage Detect flag
*
* This function acknowledges the low voltage detection errors (write 1 to
* clear LVDF).
*
* @param base PMC peripheral base address.
*/
static inline void PMC_ClearLowVoltDetectFlag(PMC_Type *base)
{
base->LVDSC1 |= PMC_LVDSC1_LVDACK_MASK;
}
/*!
* @brief Configure the low voltage warning setting.
*
* This function configures the low voltage warning setting, including the trip
* point voltage setting and enable interrupt or not.
*
* @param base PMC peripheral base address.
* @param config Low-Voltage warning configuration structure.
*/
void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_config_t *config);
/*!
* @brief Get Low-Voltage Warning Flag status
*
* This function polls the current LVWF status. When 1 is returned, it
* indicates a low-voltage warning event. LVWF is set when V Supply transitions
* below the trip point or after reset and V Supply is already below the V LVW.
*
* @param base PMC peripheral base address.
* @return Current LVWF status
* - true: Low-Voltage Warning Flag is set.
* - false: the Low-Voltage Warning does not happen.
*/
static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base)
{
return (bool)(base->LVDSC2 & PMC_LVDSC2_LVWF_MASK);
}
/*!
* @brief Acknowledge to Low-Voltage Warning flag
*
* This function acknowledges the low voltage warning errors (write 1 to
* clear LVWF).
*
* @param base PMC peripheral base address.
*/
static inline void PMC_ClearLowVoltWarningFlag(PMC_Type *base)
{
base->LVDSC2 |= PMC_LVDSC2_LVWACK_MASK;
}
#if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1)
/*!
* @brief Configure the high voltage detect setting.
*
* This function configures the high voltage detect setting, including the trip
* point voltage setting, enable interrupt or not, enable system reset or not.
*
* @param base PMC peripheral base address.
* @param config High-Voltage detect configuration structure.
*/
void PMC_ConfigureHighVoltDetect(PMC_Type *base, const pmc_high_volt_detect_config_t *config);
/*!
* @brief Get High-Voltage Detect Flag status
*
* This function reads the current HVDF status. If it returns 1, a low
* voltage event is detected.
*
* @param base PMC peripheral base address.
* @return Current high voltage detect flag
* - true: High-Voltage detected
* - false: High-Voltage not detected
*/
static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base)
{
return (bool)(base->HVDSC1 & PMC_HVDSC1_HVDF_MASK);
}
/*!
* @brief Acknowledge to clear the High-Voltage Detect flag
*
* This function acknowledges the high voltage detection errors (write 1 to
* clear HVDF).
*
* @param base PMC peripheral base address.
*/
static inline void PMC_ClearHighVoltDetectFlag(PMC_Type *base)
{
base->HVDSC1 |= PMC_HVDSC1_HVDACK_MASK;
}
#endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */
#if ((defined(FSL_FEATURE_PMC_HAS_BGBE) && FSL_FEATURE_PMC_HAS_BGBE) || \
(defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) || \
(defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS))
/*!
* @brief Configure the PMC bandgap
*
* This function configures the PMC bandgap, including the drive select and
* behavior in low power mode.
*
* @param base PMC peripheral base address.
* @param config Pointer to the configuration structure
*/
void PMC_ConfigureBandgapBuffer(PMC_Type *base, const pmc_bandgap_buffer_config_t *config);
#endif
#if (defined(FSL_FEATURE_PMC_HAS_ACKISO) && FSL_FEATURE_PMC_HAS_ACKISO)
/*!
* @brief Gets the acknowledge Peripherals and I/O pads isolation flag.
*
* This function reads the Acknowledge Isolation setting that indicates
* whether certain peripherals and the I/O pads are in a latched state as
* a result of having been in the VLLS mode.
*
* @param base PMC peripheral base address.
* @param base Base address for current PMC instance.
* @return ACK isolation
* 0 - Peripherals and I/O pads are in a normal run state.
* 1 - Certain peripherals and I/O pads are in an isolated and
* latched state.
*/
static inline bool PMC_GetPeriphIOIsolationFlag(PMC_Type *base)
{
return (bool)(base->REGSC & PMC_REGSC_ACKISO_MASK);
}
/*!
* @brief Acknowledge to Peripherals and I/O pads isolation flag.
*
* This function clears the ACK Isolation flag. Writing one to this setting
* when it is set releases the I/O pads and certain peripherals to their normal
* run mode state.
*
* @param base PMC peripheral base address.
*/
static inline void PMC_ClearPeriphIOIsolationFlag(PMC_Type *base)
{
base->REGSC |= PMC_REGSC_ACKISO_MASK;
}
#endif /* FSL_FEATURE_PMC_HAS_ACKISO */
#if (defined(FSL_FEATURE_PMC_HAS_REGONS) && FSL_FEATURE_PMC_HAS_REGONS)
/*!
* @brief Gets the Regulator regulation status.
*
* This function returns the regulator to a run regulation status. It provides
* the current status of the internal voltage regulator.
*
* @param base PMC peripheral base address.
* @param base Base address for current PMC instance.
* @return Regulation status
* 0 - Regulator is in a stop regulation or in transition to/from the regulation.
* 1 - Regulator is in a run regulation.
*
*/
static inline bool PMC_IsRegulatorInRunRegulation(PMC_Type *base)
{
return (bool)(base->REGSC & PMC_REGSC_REGONS_MASK);
}
#endif /* FSL_FEATURE_PMC_HAS_REGONS */
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_PMC_H_*/

View File

@ -0,0 +1,382 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_PORT_H_
#define _FSL_PORT_H_
#include "fsl_common.h"
/*!
* @addtogroup port_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! Version 2.0.1. */
#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*! @brief Internal resistor pull feature selection */
enum _port_pull
{
kPORT_PullDisable = 0U, /*!< internal pull-up/down resistor is disabled. */
kPORT_PullDown = 2U, /*!< internal pull-down resistor is enabled. */
kPORT_PullUp = 3U, /*!< internal pull-up resistor is enabled. */
};
/*! @brief Slew rate selection */
enum _port_slew_rate
{
kPORT_FastSlewRate = 0U, /*!< fast slew rate is configured. */
kPORT_SlowSlewRate = 1U, /*!< slow slew rate is configured. */
};
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
/*! @brief Internal resistor pull feature enable/disable */
enum _port_open_drain_enable
{
kPORT_OpenDrainDisable = 0U, /*!< internal pull-down resistor is disabled. */
kPORT_OpenDrainEnable = 1U, /*!< internal pull-up resistor is enabled. */
};
#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
/*! @brief Passive filter feature enable/disable */
enum _port_passive_filter_enable
{
kPORT_PassiveFilterDisable = 0U, /*!< fast slew rate is configured. */
kPORT_PassiveFilterEnable = 1U, /*!< slow slew rate is configured. */
};
/*! @brief Configures the drive strength. */
enum _port_drive_strength
{
kPORT_LowDriveStrength = 0U, /*!< low drive strength is configured. */
kPORT_HighDriveStrength = 1U, /*!< high drive strength is configured. */
};
#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
/*! @brief Unlock/lock the pin control register field[15:0] */
enum _port_lock_register
{
kPORT_UnlockRegister = 0U, /*!< Pin Control Register fields [15:0] are not locked. */
kPORT_LockRegister = 1U, /*!< Pin Control Register fields [15:0] are locked. */
};
#endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
/*! @brief Pin mux selection */
typedef enum _port_mux
{
kPORT_PinDisabledOrAnalog = 0U, /*!< corresponding pin is disabled, but is used as an analog pin. */
kPORT_MuxAsGpio = 1U, /*!< corresponding pin is configured as GPIO. */
kPORT_MuxAlt2 = 2U, /*!< chip-specific */
kPORT_MuxAlt3 = 3U, /*!< chip-specific */
kPORT_MuxAlt4 = 4U, /*!< chip-specific */
kPORT_MuxAlt5 = 5U, /*!< chip-specific */
kPORT_MuxAlt6 = 6U, /*!< chip-specific */
kPORT_MuxAlt7 = 7U, /*!< chip-specific */
} port_mux_t;
/*! @brief Configures the interrupt generation condition. */
typedef enum _port_interrupt
{
kPORT_InterruptOrDMADisabled = 0x0U, /*!< Interrupt/DMA request is disabled. */
#if defined(FSL_FEATURE_PORT_HAS_DMA_REQUEST) && FSL_FEATURE_PORT_HAS_DMA_REQUEST
kPORT_DMARisingEdge = 0x1U, /*!< DMA request on rising edge. */
kPORT_DMAFallingEdge = 0x2U, /*!< DMA request on falling edge. */
kPORT_DMAEitherEdge = 0x3U, /*!< DMA request on either edge. */
#endif
#if defined(FSL_FEATURE_PORT_HAS_IRQC_FLAG) && FSL_FEATURE_PORT_HAS_IRQC_FLAG
kPORT_FlagRisingEdge = 0x05U, /*!< Flag sets on rising edge. */
kPORT_FlagFallingEdge = 0x06U, /*!< Flag sets on falling edge. */
kPORT_FlagEitherEdge = 0x07U, /*!< Flag sets on either edge. */
#endif
kPORT_InterruptLogicZero = 0x8U, /*!< Interrupt when logic zero. */
kPORT_InterruptRisingEdge = 0x9U, /*!< Interrupt on rising edge. */
kPORT_InterruptFallingEdge = 0xAU, /*!< Interrupt on falling edge. */
kPORT_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */
kPORT_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */
#if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER
kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high trigger output. */
kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low trigger output. */
#endif
} port_interrupt_t;
#if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
/*! @brief Digital filter clock source selection */
typedef enum _port_digital_filter_clock_source
{
kPORT_BusClock = 0U, /*!< Digital filters are clocked by the bus clock. */
kPORT_LpoClock = 1U, /*!< Digital filters are clocked by the 1 kHz LPO clock. */
} port_digital_filter_clock_source_t;
/*! @brief PORT digital filter feature configuration definition */
typedef struct _port_digital_filter_config
{
uint32_t digitalFilterWidth; /*!< Set digital filter width */
port_digital_filter_clock_source_t clockSource; /*!< Set digital filter clockSource */
} port_digital_filter_config_t;
#endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
/*! @brief PORT pin config structure */
typedef struct _port_pin_config
{
uint16_t pullSelect : 2; /*!< no-pull/pull-down/pull-up select */
uint16_t slewRate : 1; /*!< fast/slow slew rate Configure */
uint16_t : 1;
uint16_t passiveFilterEnable : 1; /*!< passive filter enable/disable */
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
uint16_t openDrainEnable : 1; /*!< open drain enable/disable */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
uint16_t driveStrength : 1; /*!< fast/slow drive strength configure */
uint16_t : 1;
uint16_t mux : 3; /*!< pin mux Configure */
uint16_t : 4;
#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
uint16_t lockRegister : 1; /*!< lock/unlock the pcr field[15:0] */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
} port_pin_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*! @name Configuration */
/*@{*/
/*!
* @brief Sets the port PCR register.
*
* This is an example to define an input pin or output pin PCR configuration:
* @code
* // Define a digital input pin PCR configuration
* port_pin_config_t config = {
* kPORT_PullUp,
* kPORT_FastSlewRate,
* kPORT_PassiveFilterDisable,
* kPORT_OpenDrainDisable,
* kPORT_LowDriveStrength,
* kPORT_MuxAsGpio,
* kPORT_UnLockRegister,
* };
* @endcode
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT PCR register configure structure.
*/
static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
{
assert(config);
uint32_t addr = (uint32_t)&base->PCR[pin];
*(volatile uint16_t *)(addr) = *((const uint16_t *)config);
}
/*!
* @brief Sets the port PCR register for multiple pins.
*
* This is an example to define input pins or output pins PCR configuration:
* @code
* // Define a digital input pin PCR configuration
* port_pin_config_t config = {
* kPORT_PullUp ,
* kPORT_PullEnable,
* kPORT_FastSlewRate,
* kPORT_PassiveFilterDisable,
* kPORT_OpenDrainDisable,
* kPORT_LowDriveStrength,
* kPORT_MuxAsGpio,
* kPORT_UnlockRegister,
* };
* @endcode
*
* @param base PORT peripheral base pointer.
* @param mask PORT pins' numbers macro.
* @param config PORT PCR register configure structure.
*/
static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config)
{
assert(config);
uint16_t pcrl = *((const uint16_t *)config);
if (mask & 0xffffU)
{
base->GPCLR = ((mask & 0xffffU) << 16) | pcrl;
}
if (mask >> 16)
{
base->GPCHR = (mask & 0xffff0000U) | pcrl;
}
}
/*!
* @brief Configures the pin muxing.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param mux pin muxing slot selection.
* - #kPORT_PinDisabledOrAnalog: Pin disabled or work in analog function.
* - #kPORT_MuxAsGpio : Set as GPIO.
* - #kPORT_MuxAlt2 : chip-specific.
* - #kPORT_MuxAlt3 : chip-specific.
* - #kPORT_MuxAlt4 : chip-specific.
* - #kPORT_MuxAlt5 : chip-specific.
* - #kPORT_MuxAlt6 : chip-specific.
* - #kPORT_MuxAlt7 : chip-specific.
* @Note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because
* the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux will
* be reset to zero : kPORT_PinDisabledOrAnalog).
* This function is recommended to use in the case you just need to reset the pin mux
*
*/
static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux);
}
#if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
/*!
* @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pins' numbers macro.
*/
static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable)
{
if (enable == true)
{
base->DFER |= mask;
}
else
{
base->DFER &= ~mask;
}
}
/*!
* @brief Sets the digital filter in one port, each bit of the 32-bit register represents one pin.
*
* @param base PORT peripheral base pointer.
* @param config PORT digital filter configuration structure.
*/
static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digital_filter_config_t *config)
{
assert(config);
base->DFCR = PORT_DFCR_CS(config->clockSource);
base->DFWR = PORT_DFWR_FILT(config->digitalFilterWidth);
}
#endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
/*@}*/
/*! @name Interrupt */
/*@{*/
/*!
* @brief Configures the port pin interrupt/DMA request.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT pin interrupt configuration.
* - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
* - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kPORT_InterruptLogicZero : Interrupt when logic zero.
* - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
* - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
* - #kPORT_InterruptEitherEdge : Interrupt on either edge.
* - #kPORT_InterruptLogicOne : Interrupt when logic one.
* - #kPORT_ActiveHighTriggerOutputEnable : Enable active high trigger output(if the trigger states exit).
* - #kPORT_ActiveLowTriggerOutputEnable : Enable active low trigger output(if the trigger states exit).
*/
static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(config);
}
/*!
* @brief Reads the whole port status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base PORT peripheral base pointer.
* @return Current port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base)
{
return base->ISFR;
}
/*!
* @brief Clears the multiple pins' interrupt status flag.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pins' numbers macro.
*/
static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask)
{
base->ISFR = mask;
}
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_PORT_H_ */

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_rcm.h"
void RCM_ConfigureResetPinFilter(RCM_Type *base, const rcm_reset_pin_filter_config_t *config)
{
#if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32))
uint32_t reg;
reg = (((uint32_t)config->enableFilterInStop << RCM_RPC_RSTFLTSS_SHIFT) | (uint32_t)config->filterInRunWait);
if (config->filterInRunWait == kRCM_FilterBusClock)
{
reg |= ((uint32_t)config->busClockFilterCount << RCM_RPC_RSTFLTSEL_SHIFT);
}
base->RPC = reg;
#else
base->RPFC = ((uint8_t)(config->enableFilterInStop << RCM_RPFC_RSTFLTSS_SHIFT) | (uint8_t)config->filterInRunWait);
if (config->filterInRunWait == kRCM_FilterBusClock)
{
base->RPFW = config->busClockFilterCount;
}
#endif /* FSL_FEATURE_RCM_REG_WIDTH */
}
#if (defined(FSL_FEATURE_RCM_HAS_BOOTROM) && FSL_FEATURE_RCM_HAS_BOOTROM)
void RCM_SetForceBootRomSource(RCM_Type *base, rcm_boot_rom_config_t config)
{
uint32_t reg;
reg = base->FM;
reg &= ~RCM_FM_FORCEROM_MASK;
reg |= ((uint32_t)config << RCM_FM_FORCEROM_SHIFT);
base->FM = reg;
}
#endif /* #if FSL_FEATURE_RCM_HAS_BOOTROM */

View File

@ -0,0 +1,432 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_RCM_H_
#define _FSL_RCM_H_
#include "fsl_common.h"
/*! @addtogroup rcm */
/*! @{*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief RCM driver version 2.0.0. */
#define FSL_RCM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief System Reset Source Name definitions
*/
typedef enum _rcm_reset_source
{
#if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32))
/* RCM register bit width is 32. */
#if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP)
kRCM_SourceWakeup = RCM_SRS_WAKEUP_MASK, /*!< Low-leakage wakeup reset */
#endif
kRCM_SourceLvd = RCM_SRS_LVD_MASK, /*!< low voltage detect reset */
#if (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC)
kRCM_SourceLoc = RCM_SRS_LOC_MASK, /*!< Loss of clock reset */
#endif /* FSL_FEATURE_RCM_HAS_LOC */
#if (defined(FSL_FEATURE_RCM_HAS_LOL) && FSL_FEATURE_RCM_HAS_LOL)
kRCM_SourceLol = RCM_SRS_LOL_MASK, /*!< Loss of lock reset */
#endif /* FSL_FEATURE_RCM_HAS_LOL */
kRCM_SourceWdog = RCM_SRS_WDOG_MASK, /*!< Watchdog reset */
kRCM_SourcePin = RCM_SRS_PIN_MASK, /*!< External pin reset */
kRCM_SourcePor = RCM_SRS_POR_MASK, /*!< Power on reset */
#if (defined(FSL_FEATURE_RCM_HAS_JTAG) && FSL_FEATURE_RCM_HAS_JTAG)
kRCM_SourceJtag = RCM_SRS_JTAG_MASK, /*!< JTAG generated reset */
#endif /* FSL_FEATURE_RCM_HAS_JTAG */
kRCM_SourceLockup = RCM_SRS_LOCKUP_MASK, /*!< Core lock up reset */
kRCM_SourceSw = RCM_SRS_SW_MASK, /*!< Software reset */
#if (defined(FSL_FEATURE_RCM_HAS_MDM_AP) && FSL_FEATURE_RCM_HAS_MDM_AP)
kRCM_SourceMdmap = RCM_SRS_MDM_AP_MASK, /*!< MDM-AP system reset */
#endif /* FSL_FEATURE_RCM_HAS_MDM_AP */
#if (defined(FSL_FEATURE_RCM_HAS_EZPORT) && FSL_FEATURE_RCM_HAS_EZPORT)
kRCM_SourceEzpt = RCM_SRS_EZPT_MASK, /*!< EzPort reset */
#endif /* FSL_FEATURE_RCM_HAS_EZPORT */
kRCM_SourceSackerr = RCM_SRS_SACKERR_MASK, /*!< Parameter could get all reset flags */
#else /* (FSL_FEATURE_RCM_REG_WIDTH == 32) */
/* RCM register bit width is 8. */
#if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP)
kRCM_SourceWakeup = RCM_SRS0_WAKEUP_MASK, /*!< Low-leakage wakeup reset */
#endif
kRCM_SourceLvd = RCM_SRS0_LVD_MASK, /*!< low voltage detect reset */
#if (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC)
kRCM_SourceLoc = RCM_SRS0_LOC_MASK, /*!< Loss of clock reset */
#endif /* FSL_FEATURE_RCM_HAS_LOC */
#if (defined(FSL_FEATURE_RCM_HAS_LOL) && FSL_FEATURE_RCM_HAS_LOL)
kRCM_SourceLol = RCM_SRS0_LOL_MASK, /*!< Loss of lock reset */
#endif /* FSL_FEATURE_RCM_HAS_LOL */
kRCM_SourceWdog = RCM_SRS0_WDOG_MASK, /*!< Watchdog reset */
kRCM_SourcePin = RCM_SRS0_PIN_MASK, /*!< External pin reset */
kRCM_SourcePor = RCM_SRS0_POR_MASK, /*!< Power on reset */
#if (defined(FSL_FEATURE_RCM_HAS_JTAG) && FSL_FEATURE_RCM_HAS_JTAG)
kRCM_SourceJtag = RCM_SRS1_JTAG_MASK << 8U, /*!< JTAG generated reset */
#endif /* FSL_FEATURE_RCM_HAS_JTAG */
kRCM_SourceLockup = RCM_SRS1_LOCKUP_MASK << 8U, /*!< Core lock up reset */
kRCM_SourceSw = RCM_SRS1_SW_MASK, /*!< Software reset */
#if (defined(FSL_FEATURE_RCM_HAS_MDM_AP) && FSL_FEATURE_RCM_HAS_MDM_AP)
kRCM_SourceMdmap = RCM_SRS1_MDM_AP_MASK << 8U, /*!< MDM-AP system reset */
#endif /* FSL_FEATURE_RCM_HAS_MDM_AP */
#if (defined(FSL_FEATURE_RCM_HAS_EZPORT) && FSL_FEATURE_RCM_HAS_EZPORT)
kRCM_SourceEzpt = RCM_SRS1_EZPT_MASK << 8U, /*!< EzPort reset */
#endif /* FSL_FEATURE_RCM_HAS_EZPORT */
kRCM_SourceSackerr = RCM_SRS1_SACKERR_MASK << 8U, /*!< Parameter could get all reset flags */
#endif /* (FSL_FEATURE_RCM_REG_WIDTH == 32) */
kRCM_SourceAll = 0xffffffffU,
} rcm_reset_source_t;
/*!
* @brief Reset pin filter select in Run and Wait modes
*/
typedef enum _rcm_run_wait_filter_mode
{
kRCM_FilterDisable = 0U, /*!< All filtering disabled */
kRCM_FilterBusClock = 1U, /*!< Bus clock filter enabled */
kRCM_FilterLpoClock = 2U /*!< LPO clock filter enabled */
} rcm_run_wait_filter_mode_t;
#if (defined(FSL_FEATURE_RCM_HAS_BOOTROM) && FSL_FEATURE_RCM_HAS_BOOTROM)
/*!
* @brief Boot from ROM configuration.
*/
typedef enum _rcm_boot_rom_config
{
kRCM_BootFlash = 0U, /*!< Boot from flash */
kRCM_BootRomCfg0 = 1U, /*!< Boot from boot ROM due to BOOTCFG0 */
kRCM_BootRomFopt = 2U, /*!< Boot from boot ROM due to FOPT[7] */
kRCM_BootRomBoth = 3U /*!< Boot from boot ROM due to both BOOTCFG0 and FOPT[7] */
} rcm_boot_rom_config_t;
#endif /* FSL_FEATURE_RCM_HAS_BOOTROM */
#if (defined(FSL_FEATURE_RCM_HAS_SRIE) && FSL_FEATURE_RCM_HAS_SRIE)
/*!
* @brief Max delay time from interrupt asserts to system reset.
*/
typedef enum _rcm_reset_delay
{
kRCM_ResetDelay8Lpo = 0U, /*!< Delay 8 LPO cycles. */
kRCM_ResetDelay32Lpo = 1U, /*!< Delay 32 LPO cycles. */
kRCM_ResetDelay128Lpo = 2U, /*!< Delay 128 LPO cycles. */
kRCM_ResetDelay512Lpo = 3U /*!< Delay 512 LPO cycles. */
} rcm_reset_delay_t;
/*!
* @brief System reset interrupt enable bit definitions.
*/
typedef enum _rcm_interrupt_enable
{
kRCM_IntNone = 0U, /*!< No interrupt enabled. */
kRCM_IntLossOfClk = RCM_SRIE_LOC_MASK, /*!< Loss of clock interrupt. */
kRCM_IntLossOfLock = RCM_SRIE_LOL_MASK, /*!< Loss of lock interrupt. */
kRCM_IntWatchDog = RCM_SRIE_WDOG_MASK, /*!< Watch dog interrupt. */
kRCM_IntExternalPin = RCM_SRIE_PIN_MASK, /*!< External pin interrupt. */
kRCM_IntGlobal = RCM_SRIE_GIE_MASK, /*!< Global interrupts. */
kRCM_IntCoreLockup = RCM_SRIE_LOCKUP_MASK, /*!< Core lock up interrupt */
kRCM_IntSoftware = RCM_SRIE_SW_MASK, /*!< software interrupt */
kRCM_IntStopModeAckErr = RCM_SRIE_SACKERR_MASK, /*!< Stop mode ACK error interrupt. */
#if (defined(FSL_FEATURE_RCM_HAS_CORE1) && FSL_FEATURE_RCM_HAS_CORE1)
kRCM_IntCore1 = RCM_SRIE_CORE1_MASK, /*!< Core 1 interrupt. */
#endif
kRCM_IntAll = RCM_SRIE_LOC_MASK /*!< Enable all interrupts. */
|
RCM_SRIE_LOL_MASK | RCM_SRIE_WDOG_MASK | RCM_SRIE_PIN_MASK | RCM_SRIE_GIE_MASK |
RCM_SRIE_LOCKUP_MASK | RCM_SRIE_SW_MASK | RCM_SRIE_SACKERR_MASK
#if (defined(FSL_FEATURE_RCM_HAS_CORE1) && FSL_FEATURE_RCM_HAS_CORE1)
|
RCM_SRIE_CORE1_MASK
#endif
} rcm_interrupt_enable_t;
#endif /* FSL_FEATURE_RCM_HAS_SRIE */
#if (defined(FSL_FEATURE_RCM_HAS_VERID) && FSL_FEATURE_RCM_HAS_VERID)
/*!
* @brief IP version ID definition.
*/
typedef struct _rcm_version_id
{
uint16_t feature; /*!< Feature Specification Number. */
uint8_t minor; /*!< Minor version number. */
uint8_t major; /*!< Major version number. */
} rcm_version_id_t;
#endif
/*!
* @brief Reset pin filter configuration
*/
typedef struct _rcm_reset_pin_filter_config
{
bool enableFilterInStop; /*!< Reset pin filter select in stop mode. */
rcm_run_wait_filter_mode_t filterInRunWait; /*!< Reset pin filter in run/wait mode. */
uint8_t busClockFilterCount; /*!< Reset pin bus clock filter width. */
} rcm_reset_pin_filter_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*! @name Reset Control Module APIs*/
/*@{*/
#if (defined(FSL_FEATURE_RCM_HAS_VERID) && FSL_FEATURE_RCM_HAS_VERID)
/*!
* @brief Gets the RCM version ID.
*
* This function gets the RCM version ID including the major version number,
* the minor version number, and the feature specification number.
*
* @param base RCM peripheral base address.
* @param versionId Pointer to version ID structure.
*/
static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId)
{
*((uint32_t *)versionId) = base->VERID;
}
#endif
#if (defined(FSL_FEATURE_RCM_HAS_PARAM) && FSL_FEATURE_RCM_HAS_PARAM)
/*!
* @brief Gets the reset source implemented status.
*
* This function gets the RCM parameter that indicates whether the corresponding reset source is implemented.
* Use source masks defined in the rcm_reset_source_t to get the desired source status.
*
* Example:
@code
uint32_t status;
// To test whether the MCU is reset using Watchdog.
status = RCM_GetResetSourceImplementedStatus(RCM) & (kRCM_SourceWdog | kRCM_SourcePin);
@endcode
*
* @param base RCM peripheral base address.
* @return All reset source implemented status bit map.
*/
static inline uint32_t RCM_GetResetSourceImplementedStatus(RCM_Type *base)
{
return base->PARAM;
}
#endif /* FSL_FEATURE_RCM_HAS_PARAM */
/*!
* @brief Gets the reset source status which caused a previous reset.
*
* This function gets the current reset source status. Use source masks
* defined in the rcm_reset_source_t to get the desired source status.
*
* Example:
@code
uint32_t resetStatus;
// To get all reset source statuses.
resetStatus = RCM_GetPreviousResetSources(RCM) & kRCM_SourceAll;
// To test whether the MCU is reset using Watchdog.
resetStatus = RCM_GetPreviousResetSources(RCM) & kRCM_SourceWdog;
// To test multiple reset sources.
resetStatus = RCM_GetPreviousResetSources(RCM) & (kRCM_SourceWdog | kRCM_SourcePin);
@endcode
*
* @param base RCM peripheral base address.
* @return All reset source status bit map.
*/
static inline uint32_t RCM_GetPreviousResetSources(RCM_Type *base)
{
#if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32))
return base->SRS;
#else
return (uint32_t)((uint32_t)base->SRS0 | ((uint32_t)base->SRS1 << 8U));
#endif /* (FSL_FEATURE_RCM_REG_WIDTH == 32) */
}
#if (defined(FSL_FEATURE_RCM_HAS_SSRS) && FSL_FEATURE_RCM_HAS_SSRS)
/*!
* @brief Gets the sticky reset source status.
*
* This function gets the current reset source status that has not been cleared
* by software for some specific source.
*
* Example:
@code
uint32_t resetStatus;
// To get all reset source statuses.
resetStatus = RCM_GetStickyResetSources(RCM) & kRCM_SourceAll;
// To test whether the MCU is reset using Watchdog.
resetStatus = RCM_GetStickyResetSources(RCM) & kRCM_SourceWdog;
// To test multiple reset sources.
resetStatus = RCM_GetStickyResetSources(RCM) & (kRCM_SourceWdog | kRCM_SourcePin);
@endcode
*
* @param base RCM peripheral base address.
* @return All reset source status bit map.
*/
static inline uint32_t RCM_GetStickyResetSources(RCM_Type *base)
{
#if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32))
return base->SSRS;
#else
return (base->SSRS0 | ((uint32_t)base->SSRS1 << 8U));
#endif /* (FSL_FEATURE_RCM_REG_WIDTH == 32) */
}
/*!
* @brief Clears the sticky reset source status.
*
* This function clears the sticky system reset flags indicated by source masks.
*
* Example:
@code
// Clears multiple reset sources.
RCM_ClearStickyResetSources(kRCM_SourceWdog | kRCM_SourcePin);
@endcode
*
* @param base RCM peripheral base address.
* @param sourceMasks reset source status bit map
*/
static inline void RCM_ClearStickyResetSources(RCM_Type *base, uint32_t sourceMasks)
{
#if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32))
base->SSRS = sourceMasks;
#else
base->SSRS0 = (sourceMasks & 0xffU);
base->SSRS1 = ((sourceMasks >> 8U) & 0xffU);
#endif /* (FSL_FEATURE_RCM_REG_WIDTH == 32) */
}
#endif /* FSL_FEATURE_RCM_HAS_SSRS */
/*!
* @brief Configures the reset pin filter.
*
* This function sets the reset pin filter including the filter source, filter
* width, and so on.
*
* @param base RCM peripheral base address.
* @param config Pointer to the configuration structure.
*/
void RCM_ConfigureResetPinFilter(RCM_Type *base, const rcm_reset_pin_filter_config_t *config);
#if (defined(FSL_FEATURE_RCM_HAS_EZPMS) && FSL_FEATURE_RCM_HAS_EZPMS)
/*!
* @brief Gets the EZP_MS_B pin assert status.
*
* This function gets the easy port mode status (EZP_MS_B) pin assert status.
*
* @param base RCM peripheral base address.
* @return status true - asserted, false - reasserted
*/
static inline bool RCM_GetEasyPortModePinStatus(RCM_Type *base)
{
return (bool)(base->MR & RCM_MR_EZP_MS_MASK);
}
#endif /* FSL_FEATURE_RCM_HAS_EZPMS */
#if (defined(FSL_FEATURE_RCM_HAS_BOOTROM) && FSL_FEATURE_RCM_HAS_BOOTROM)
/*!
* @brief Gets the ROM boot source.
*
* This function gets the ROM boot source during the last chip reset.
*
* @param base RCM peripheral base address.
* @return The ROM boot source.
*/
static inline rcm_boot_rom_config_t RCM_GetBootRomSource(RCM_Type *base)
{
return (rcm_boot_rom_config_t)((base->MR & RCM_MR_BOOTROM_MASK) >> RCM_MR_BOOTROM_SHIFT);
}
/*!
* @brief Clears the ROM boot source flag.
*
* This function clears the ROM boot source flag.
*
* @param base Register base address of RCM
*/
static inline void RCM_ClearBootRomSource(RCM_Type *base)
{
base->MR |= RCM_MR_BOOTROM_MASK;
}
/*!
* @brief Forces the boot from ROM.
*
* This function forces booting from ROM during all subsequent system resets.
*
* @param base RCM peripheral base address.
* @param config Boot configuration.
*/
void RCM_SetForceBootRomSource(RCM_Type *base, rcm_boot_rom_config_t config);
#endif /* FSL_FEATURE_RCM_HAS_BOOTROM */
#if (defined(FSL_FEATURE_RCM_HAS_SRIE) && FSL_FEATURE_RCM_HAS_SRIE)
/*!
* @brief Sets the system reset interrupt configuration.
*
* For graceful shutdown, the RCM supports delaying the assertion of the system
* reset for a period of time when the reset interrupt is generated. This function
* can be used to enable the interrupt and the delay period. The interrupts
* are passed in as bit mask. See rcm_int_t for details. For example, to
* delay a reset for 512 LPO cycles after the WDOG timeout or loss-of-clock occurs,
* configure as follows:
* RCM_SetSystemResetInterruptConfig(kRCM_IntWatchDog | kRCM_IntLossOfClk, kRCM_ResetDelay512Lpo);
*
* @param base RCM peripheral base address.
* @param intMask Bit mask of the system reset interrupts to enable. See
* rcm_interrupt_enable_t for details.
* @param Delay Bit mask of the system reset interrupts to enable.
*/
static inline void RCM_SetSystemResetInterruptConfig(RCM_Type *base, uint32_t intMask, rcm_reset_delay_t delay)
{
base->SRIE = (intMask | delay);
}
#endif /* FSL_FEATURE_RCM_HAS_SRIE */
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_RCM_H_ */

View File

@ -0,0 +1,370 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_rtc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define SECONDS_IN_A_DAY (86400U)
#define SECONDS_IN_A_HOUR (3600U)
#define SECONDS_IN_A_MINUTE (60U)
#define DAYS_IN_A_YEAR (365U)
#define YEAR_RANGE_START (1970U)
#define YEAR_RANGE_END (2099U)
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Checks whether the date and time passed in is valid
*
* @param datetime Pointer to structure where the date and time details are stored
*
* @return Returns false if the date & time details are out of range; true if in range
*/
static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime);
/*!
* @brief Converts time data from datetime to seconds
*
* @param datetime Pointer to datetime structure where the date and time details are stored
*
* @return The result of the conversion in seconds
*/
static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime);
/*!
* @brief Converts time data from seconds to a datetime structure
*
* @param seconds Seconds value that needs to be converted to datetime format
* @param datetime Pointer to the datetime structure where the result of the conversion is stored
*/
static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime);
/*******************************************************************************
* Code
******************************************************************************/
static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime)
{
/* Table of days in a month for a non leap year. First entry in the table is not used,
* valid months start from 1
*/
uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
/* Check year, month, hour, minute, seconds */
if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
(datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
{
/* If not correct then error*/
return false;
}
/* Adjust the days in February for a leap year */
if (!(datetime->year & 3U))
{
daysPerMonth[2] = 29U;
}
/* Check the validity of the day */
if (datetime->day > daysPerMonth[datetime->month])
{
return false;
}
return true;
}
static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime)
{
/* Number of days from begin of the non Leap-year*/
uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
uint32_t seconds;
/* Compute number of days from 1970 till given year*/
seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
/* Add leap year days */
seconds += ((datetime->year / 4) - (1970U / 4));
/* Add number of days till given month*/
seconds += monthDays[datetime->month];
/* Add days in given month. We subtract the current day as it is
* represented in the hours, minutes and seconds field*/
seconds += (datetime->day - 1);
/* For leap year if month less than or equal to Febraury, decrement day counter*/
if ((!(datetime->year & 3U)) && (datetime->month <= 2U))
{
seconds--;
}
seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
(datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;
return seconds;
}
static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime)
{
uint32_t x;
uint32_t secondsRemaining, days;
uint16_t daysInYear;
/* Table of days in a month for a non leap year. First entry in the table is not used,
* valid months start from 1
*/
uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
/* Start with the seconds value that is passed in to be converted to date time format */
secondsRemaining = seconds;
/* Calcuate the number of days, we add 1 for the current day which is represented in the
* hours and seconds field
*/
days = secondsRemaining / SECONDS_IN_A_DAY + 1;
/* Update seconds left*/
secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;
/* Calculate the datetime hour, minute and second fields */
datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
datetime->minute = secondsRemaining / 60U;
datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
/* Calculate year */
daysInYear = DAYS_IN_A_YEAR;
datetime->year = YEAR_RANGE_START;
while (days > daysInYear)
{
/* Decrease day count by a year and increment year by 1 */
days -= daysInYear;
datetime->year++;
/* Adjust the number of days for a leap year */
if (datetime->year & 3U)
{
daysInYear = DAYS_IN_A_YEAR;
}
else
{
daysInYear = DAYS_IN_A_YEAR + 1;
}
}
/* Adjust the days in February for a leap year */
if (!(datetime->year & 3U))
{
daysPerMonth[2] = 29U;
}
for (x = 1U; x <= 12U; x++)
{
if (days <= daysPerMonth[x])
{
datetime->month = x;
break;
}
else
{
days -= daysPerMonth[x];
}
}
datetime->day = days;
}
void RTC_Init(RTC_Type *base, const rtc_config_t *config)
{
assert(config);
uint32_t reg;
CLOCK_EnableClock(kCLOCK_Rtc0);
/* Issue a software reset if timer is invalid */
if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag)
{
RTC_Reset(RTC);
}
reg = base->CR;
/* Setup the update mode and supervisor access mode */
reg &= ~(RTC_CR_UM_MASK | RTC_CR_SUP_MASK);
reg |= RTC_CR_UM(config->updateMode) | RTC_CR_SUP(config->supervisorAccess);
#if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN
/* Setup the wakeup pin select */
reg &= ~(RTC_CR_WPS_MASK);
reg |= RTC_CR_WPS(config->wakeupSelect);
#endif /* FSL_FEATURE_RTC_HAS_WAKEUP_PIN */
base->CR = reg;
/* Configure the RTC time compensation register */
base->TCR = (RTC_TCR_CIR(config->compensationInterval) | RTC_TCR_TCR(config->compensationTime));
}
void RTC_GetDefaultConfig(rtc_config_t *config)
{
assert(config);
/* Wakeup pin will assert if the RTC interrupt asserts or if the wakeup pin is turned on */
config->wakeupSelect = false;
/* Registers cannot be written when locked */
config->updateMode = false;
/* Non-supervisor mode write accesses are not supported and will generate a bus error */
config->supervisorAccess = false;
/* Compensation interval used by the crystal compensation logic */
config->compensationInterval = 0;
/* Compensation time used by the crystal compensation logic */
config->compensationTime = 0;
}
status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime)
{
assert(datetime);
/* Return error if the time provided is not valid */
if (!(RTC_CheckDatetimeFormat(datetime)))
{
return kStatus_InvalidArgument;
}
/* Set time in seconds */
base->TSR = RTC_ConvertDatetimeToSeconds(datetime);
return kStatus_Success;
}
void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime)
{
assert(datetime);
uint32_t seconds = 0;
seconds = base->TSR;
RTC_ConvertSecondsToDatetime(seconds, datetime);
}
status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime)
{
assert(alarmTime);
uint32_t alarmSeconds = 0;
uint32_t currSeconds = 0;
/* Return error if the alarm time provided is not valid */
if (!(RTC_CheckDatetimeFormat(alarmTime)))
{
return kStatus_InvalidArgument;
}
alarmSeconds = RTC_ConvertDatetimeToSeconds(alarmTime);
/* Get the current time */
currSeconds = base->TSR;
/* Return error if the alarm time has passed */
if (alarmSeconds < currSeconds)
{
return kStatus_Fail;
}
/* Set alarm in seconds*/
base->TAR = alarmSeconds;
return kStatus_Success;
}
void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime)
{
assert(datetime);
uint32_t alarmSeconds = 0;
/* Get alarm in seconds */
alarmSeconds = base->TAR;
RTC_ConvertSecondsToDatetime(alarmSeconds, datetime);
}
void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask)
{
/* The alarm flag is cleared by writing to the TAR register */
if (mask & kRTC_AlarmFlag)
{
base->TAR = 0U;
}
/* The timer overflow flag is cleared by initializing the TSR register.
* The time counter should be disabled for this write to be successful
*/
if (mask & kRTC_TimeOverflowFlag)
{
base->TSR = 1U;
}
/* The timer overflow flag is cleared by initializing the TSR register.
* The time counter should be disabled for this write to be successful
*/
if (mask & kRTC_TimeInvalidFlag)
{
base->TSR = 1U;
}
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter)
{
*counter = (((uint64_t)base->MCHR << 32) | ((uint64_t)base->MCLR));
}
void RTC_SetMonotonicCounter(RTC_Type *base, uint64_t counter)
{
/* Prepare to initialize the register with the new value written */
base->MER &= ~RTC_MER_MCE_MASK;
base->MCHR = (uint32_t)((counter) >> 32);
base->MCLR = (uint32_t)(counter);
}
status_t RTC_IncrementMonotonicCounter(RTC_Type *base)
{
if (base->SR & (RTC_SR_MOF_MASK | RTC_SR_TIF_MASK))
{
return kStatus_Fail;
}
/* Prepare to switch to increment mode */
base->MER |= RTC_MER_MCE_MASK;
/* Write anything so the counter increments*/
base->MCLR = 1U;
return kStatus_Success;
}
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */

View File

@ -0,0 +1,405 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_RTC_H_
#define _FSL_RTC_H_
#include "fsl_common.h"
/*!
* @addtogroup rtc_driver
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_RTC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@}*/
/*! @brief List of RTC interrupts */
typedef enum _rtc_interrupt_enable
{
kRTC_TimeInvalidInterruptEnable = RTC_IER_TIIE_MASK, /*!< Time invalid interrupt.*/
kRTC_TimeOverflowInterruptEnable = RTC_IER_TOIE_MASK, /*!< Time overflow interrupt.*/
kRTC_AlarmInterruptEnable = RTC_IER_TAIE_MASK, /*!< Alarm interrupt.*/
kRTC_SecondsInterruptEnable = RTC_IER_TSIE_MASK /*!< Seconds interrupt.*/
} rtc_interrupt_enable_t;
/*! @brief List of RTC flags */
typedef enum _rtc_status_flags
{
kRTC_TimeInvalidFlag = RTC_SR_TIF_MASK, /*!< Time invalid flag */
kRTC_TimeOverflowFlag = RTC_SR_TOF_MASK, /*!< Time overflow flag */
kRTC_AlarmFlag = RTC_SR_TAF_MASK /*!< Alarm flag*/
} rtc_status_flags_t;
/*! @brief List of RTC Oscillator capacitor load settings */
typedef enum _rtc_osc_cap_load
{
kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2pF capacitor load */
kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4pF capacitor load */
kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8pF capacitor load */
kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16pF capacitor load */
} rtc_osc_cap_load_t;
/*! @brief Structure is used to hold the date and time */
typedef struct _rtc_datetime
{
uint16_t year; /*!< Range from 1970 to 2099.*/
uint8_t month; /*!< Range from 1 to 12.*/
uint8_t day; /*!< Range from 1 to 31 (depending on month).*/
uint8_t hour; /*!< Range from 0 to 23.*/
uint8_t minute; /*!< Range from 0 to 59.*/
uint8_t second; /*!< Range from 0 to 59.*/
} rtc_datetime_t;
/*!
* @brief RTC config structure
*
* This structure holds the configuration settings for the RTC peripheral. To initialize this
* structure to reasonable defaults, call the RTC_GetDefaultConfig() function and pass a
* pointer to your config structure instance.
*
* The config struct can be made const so it resides in flash
*/
typedef struct _rtc_config
{
bool wakeupSelect; /*!< true: Wakeup pin outputs the 32KHz clock;
false:Wakeup pin used to wakeup the chip */
bool updateMode; /*!< true: Registers can be written even when locked under certain
conditions, false: No writes allowed when registers are locked */
bool supervisorAccess; /*!< true: Non-supervisor accesses are allowed;
false: Non-supervisor accesses are not supported */
uint32_t compensationInterval; /*!< Compensation interval that is written to the CIR field in RTC TCR Register */
uint32_t compensationTime; /*!< Compensation time that is written to the TCR field in RTC TCR Register */
} rtc_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the RTC clock and configures the peripheral for basic operation.
*
* This function will issue a software reset if the timer invalid flag is set.
*
* @note This API should be called at the beginning of the application using the RTC driver.
*
* @param base RTC peripheral base address
* @param config Pointer to user's RTC config structure.
*/
void RTC_Init(RTC_Type *base, const rtc_config_t *config);
/*!
* @brief Stop the timer and gate the RTC clock
*
* @param base RTC peripheral base address
*/
static inline void RTC_Deinit(RTC_Type *base)
{
/* Stop the RTC timer */
base->SR &= ~RTC_SR_TCE_MASK;
/* Gate the module clock */
CLOCK_DisableClock(kCLOCK_Rtc0);
}
/*!
* @brief Fill in the RTC config struct with the default settings
*
* The default values are:
* @code
* config->wakeupSelect = false;
* config->updateMode = false;
* config->supervisorAccess = false;
* config->compensationInterval = 0;
* config->compensationTime = 0;
* @endcode
* @param config Pointer to user's RTC config structure.
*/
void RTC_GetDefaultConfig(rtc_config_t *config);
/*! @}*/
/*!
* @name Current Time & Alarm
* @{
*/
/*!
* @brief Sets the RTC date and time according to the given time structure.
*
* The RTC counter must be stopped prior to calling this function as writes to the RTC
* seconds register will fail if the RTC counter is running.
*
* @param base RTC peripheral base address
* @param datetime Pointer to structure where the date and time details to set are stored
*
* @return kStatus_Success: Success in setting the time and starting the RTC
* kStatus_InvalidArgument: Error because the datetime format is incorrect
*/
status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime);
/*!
* @brief Gets the RTC time and stores it in the given time structure.
*
* @param base RTC peripheral base address
* @param datetime Pointer to structure where the date and time details are stored.
*/
void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime);
/*!
* @brief Sets the RTC alarm time
*
* The function checks whether the specified alarm time is greater than the present
* time. If not, the function does not set the alarm and returns an error.
*
* @param base RTC peripheral base address
* @param alarmTime Pointer to structure where the alarm time is stored.
*
* @return kStatus_Success: success in setting the RTC alarm
* kStatus_InvalidArgument: Error because the alarm datetime format is incorrect
* kStatus_Fail: Error because the alarm time has already passed
*/
status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime);
/*!
* @brief Returns the RTC alarm time.
*
* @param base RTC peripheral base address
* @param datetime Pointer to structure where the alarm date and time details are stored.
*/
void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime);
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected RTC interrupts.
*
* @param base RTC peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::rtc_interrupt_enable_t
*/
static inline void RTC_EnableInterrupts(RTC_Type *base, uint32_t mask)
{
base->IER |= mask;
}
/*!
* @brief Disables the selected RTC interrupts.
*
* @param base RTC peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::rtc_interrupt_enable_t
*/
static inline void RTC_DisableInterrupts(RTC_Type *base, uint32_t mask)
{
base->IER &= ~mask;
}
/*!
* @brief Gets the enabled RTC interrupts.
*
* @param base RTC peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::rtc_interrupt_enable_t
*/
static inline uint32_t RTC_GetEnabledInterrupts(RTC_Type *base)
{
return (base->IER & (RTC_IER_TIIE_MASK | RTC_IER_TOIE_MASK | RTC_IER_TAIE_MASK | RTC_IER_TSIE_MASK));
}
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the RTC status flags
*
* @param base RTC peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::rtc_status_flags_t
*/
static inline uint32_t RTC_GetStatusFlags(RTC_Type *base)
{
return (base->SR & (RTC_SR_TIF_MASK | RTC_SR_TOF_MASK | RTC_SR_TAF_MASK));
}
/*!
* @brief Clears the RTC status flags.
*
* @param base RTC peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::rtc_status_flags_t
*/
void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask);
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the RTC time counter.
*
* After calling this function, the timer counter increments once a second provided SR[TOF] or
* SR[TIF] are not set.
*
* @param base RTC peripheral base address
*/
static inline void RTC_StartTimer(RTC_Type *base)
{
base->SR |= RTC_SR_TCE_MASK;
}
/*!
* @brief Stops the RTC time counter.
*
* RTC's seconds register can be written to only when the timer is stopped.
*
* @param base RTC peripheral base address
*/
static inline void RTC_StopTimer(RTC_Type *base)
{
base->SR &= ~RTC_SR_TCE_MASK;
}
/*! @}*/
/*!
* @brief This function sets the specified capacitor configuration for the RTC oscillator.
*
* @param base RTC peripheral base address
* @param capLoad Oscillator loads to enable. This is a logical OR of members of the
* enumeration ::rtc_osc_cap_load_t
*/
static inline void RTC_SetOscCapLoad(RTC_Type *base, uint32_t capLoad)
{
uint32_t reg = base->CR;
reg &= ~(RTC_CR_SC2P_MASK | RTC_CR_SC4P_MASK | RTC_CR_SC8P_MASK | RTC_CR_SC16P_MASK);
reg |= capLoad;
base->CR = reg;
}
/*!
* @brief Performs a software reset on the RTC module.
*
* This resets all RTC registers except for the SWR bit and the RTC_WAR and RTC_RAR
* registers. The SWR bit is cleared by software explicitly clearing it.
*
* @param base RTC peripheral base address
*/
static inline void RTC_Reset(RTC_Type *base)
{
base->CR |= RTC_CR_SWR_MASK;
base->CR &= ~RTC_CR_SWR_MASK;
/* Set TSR register to 0x1 to avoid the timer invalid (TIF) bit being set in the SR register */
base->TSR = 1U;
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
/*!
* @name Monotonic counter functions
* @{
*/
/*!
* @brief Reads the values of the Monotonic Counter High and Monotonic Counter Low and returns
* them as a single value.
*
* @param base RTC peripheral base address
* @param counter Pointer to variable where the value is stored.
*/
void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter);
/*!
* @brief Writes values Monotonic Counter High and Monotonic Counter Low by decomposing
* the given single value.
*
* @param base RTC peripheral base address
* @param counter Counter value
*/
void RTC_SetMonotonicCounter(RTC_Type *base, uint64_t counter);
/*!
* @brief Increments the Monotonic Counter by one.
*
* Increments the Monotonic Counter (registers RTC_MCLR and RTC_MCHR accordingly) by setting
* the monotonic counter enable (MER[MCE]) and then writing to the RTC_MCLR register. A write to the
* monotonic counter low that causes it to overflow also increments the monotonic counter high.
*
* @param base RTC peripheral base address
*
* @return kStatus_Success: success
* kStatus_Fail: error occurred, either time invalid or monotonic overflow flag was found
*/
status_t RTC_IncrementMonotonicCounter(RTC_Type *base);
/*! @}*/
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_RTC_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,850 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_SAI_H_
#define _FSL_SAI_H_
#include "fsl_common.h"
/*!
* @addtogroup sai
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_SAI_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0 */
/*@}*/
/*! @brief SAI return status*/
enum _sai_status_t
{
kStatus_SAI_TxBusy = MAKE_STATUS(kStatusGroup_SAI, 0), /*!< SAI Tx is busy. */
kStatus_SAI_RxBusy = MAKE_STATUS(kStatusGroup_SAI, 1), /*!< SAI Rx is busy. */
kStatus_SAI_TxError = MAKE_STATUS(kStatusGroup_SAI, 2), /*!< SAI Tx FIFO error. */
kStatus_SAI_RxError = MAKE_STATUS(kStatusGroup_SAI, 3), /*!< SAI Rx FIFO error. */
kStatus_SAI_QueueFull = MAKE_STATUS(kStatusGroup_SAI, 4), /*!< SAI transfer queue is full. */
kStatus_SAI_TxIdle = MAKE_STATUS(kStatusGroup_SAI, 5), /*!< SAI Tx is idle */
kStatus_SAI_RxIdle = MAKE_STATUS(kStatusGroup_SAI, 6) /*!< SAI Rx is idle */
};
/*! @brief Define the SAI bus type */
typedef enum _sai_protocol
{
kSAI_BusLeftJustified = 0x0U, /*!< Uses left justified format.*/
kSAI_BusRightJustified, /*!< Uses right justified format. */
kSAI_BusI2S, /*!< Uses I2S format. */
kSAI_BusPCMA, /*!< Uses I2S PCM A format.*/
kSAI_BusPCMB /*!< Uses I2S PCM B format. */
} sai_protocol_t;
/*! @brief Master or slave mode */
typedef enum _sai_master_slave
{
kSAI_Master = 0x0U, /*!< Master mode */
kSAI_Slave = 0x1U /*!< Slave mode */
} sai_master_slave_t;
/*! @brief Mono or stereo audio format */
typedef enum _sai_mono_stereo
{
kSAI_Stereo = 0x0U, /*!< Stereo sound. */
kSAI_MonoLeft, /*!< Only left channel have sound. */
kSAI_MonoRight /*!< Only Right channel have sound. */
} sai_mono_stereo_t;
/*! @brief Synchronous or asynchronous mode */
typedef enum _sai_sync_mode
{
kSAI_ModeAsync = 0x0U, /*!< Asynchronous mode */
kSAI_ModeSync, /*!< Synchronous mode (with receiver or transmit) */
kSAI_ModeSyncWithOtherTx, /*!< Synchronous with another SAI transmit */
kSAI_ModeSyncWithOtherRx /*!< Synchronous with another SAI receiver */
} sai_sync_mode_t;
/*! @brief Mater clock source */
typedef enum _sai_mclk_source
{
kSAI_MclkSourceSysclk = 0x0U, /*!< Master clock from the system clock */
kSAI_MclkSourceSelect1, /*!< Master clock from source 1 */
kSAI_MclkSourceSelect2, /*!< Master clock from source 2 */
kSAI_MclkSourceSelect3 /*!< Master clock from source 3 */
} sai_mclk_source_t;
/*! @brief Bit clock source */
typedef enum _sai_bclk_source
{
kSAI_BclkSourceBusclk = 0x0U, /*!< Bit clock using bus clock */
kSAI_BclkSourceMclkDiv, /*!< Bit clock using master clock divider */
kSAI_BclkSourceOtherSai0, /*!< Bit clock from other SAI device */
kSAI_BclkSourceOtherSai1 /*!< Bit clock from other SAI device */
} sai_bclk_source_t;
/*! @brief The SAI interrupt enable flag */
enum _sai_interrupt_enable_t
{
kSAI_WordStartInterruptEnable =
I2S_TCSR_WSIE_MASK, /*!< Word start flag, means the first word in a frame detected */
kSAI_SyncErrorInterruptEnable = I2S_TCSR_SEIE_MASK, /*!< Sync error flag, means the sync error is detected */
kSAI_FIFOWarningInterruptEnable = I2S_TCSR_FWIE_MASK, /*!< FIFO warning flag, means the FIFO is empty */
kSAI_FIFOErrorInterruptEnable = I2S_TCSR_FEIE_MASK, /*!< FIFO error flag */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
kSAI_FIFORequestInterruptEnable = I2S_TCSR_FRIE_MASK, /*!< FIFO request, means reached watermark */
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
};
/*! @brief The DMA request sources */
enum _sai_dma_enable_t
{
kSAI_FIFOWarningDMAEnable = I2S_TCSR_FWDE_MASK, /*!< FIFO warning caused by the DMA request */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
kSAI_FIFORequestDMAEnable = I2S_TCSR_FRDE_MASK, /*!< FIFO request caused by the DMA request */
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
};
/*! @brief The SAI status flag */
enum _sai_flags
{
kSAI_WordStartFlag = I2S_TCSR_WSF_MASK, /*!< Word start flag, means the first word in a frame detected */
kSAI_SyncErrorFlag = I2S_TCSR_SEF_MASK, /*!< Sync error flag, means the sync error is detected */
kSAI_FIFOErrorFlag = I2S_TCSR_FEF_MASK, /*!< FIFO error flag */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
kSAI_FIFORequestFlag = I2S_TCSR_FRF_MASK, /*!< FIFO request flag. */
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
kSAI_FIFOWarningFlag = I2S_TCSR_FWF_MASK, /*!< FIFO warning flag */
};
/*! @brief The reset type */
typedef enum _sai_reset_type
{
kSAI_ResetTypeSoftware = I2S_TCSR_SR_MASK, /*!< Software reset, reset the logic state */
kSAI_ResetTypeFIFO = I2S_TCSR_FR_MASK, /*!< FIFO reset, reset the FIFO read and write pointer */
kSAI_ResetAll = I2S_TCSR_SR_MASK | I2S_TCSR_FR_MASK /*!< All reset. */
} sai_reset_type_t;
#if defined(FSL_FEATURE_SAI_HAS_FIFO_PACKING) && FSL_FEATURE_SAI_HAS_FIFO_PACKING
/*!
* @brief The SAI packing mode
* The mode includes 8 bit and 16 bit packing.
*/
typedef enum _sai_fifo_packing
{
kSAI_FifoPackingDisabled = 0x0U, /*!< Packing disabled */
kSAI_FifoPacking8bit = 0x2U, /*!< 8 bit packing enabled */
kSAI_FifoPacking16bit = 0x3U /*!< 16bit packing enabled */
} sai_fifo_packing_t;
#endif /* FSL_FEATURE_SAI_HAS_FIFO_PACKING */
/*! @brief SAI user configure structure */
typedef struct _sai_config
{
sai_protocol_t protocol; /*!< Audio bus protocol in SAI */
sai_sync_mode_t syncMode; /*!< SAI sync mode, control Tx/Rx clock sync */
#if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
bool mclkOutputEnable; /*!< Master clock output enable, true means master clock divider enabled */
#endif /* FSL_FEATURE_SAI_HAS_MCR */
sai_mclk_source_t mclkSource; /*!< Master Clock source */
sai_bclk_source_t bclkSource; /*!< Bit Clock source */
sai_master_slave_t masterSlave; /*!< Master or slave */
} sai_config_t;
/*!@brief SAI transfer queue size, user can refine it according to use case. */
#define SAI_XFER_QUEUE_SIZE (4)
/*! @brief Audio sample rate */
typedef enum _sai_sample_rate
{
kSAI_SampleRate8KHz = 8000U, /*!< Sample rate 8000Hz */
kSAI_SampleRate11025Hz = 11025U, /*!< Sample rate 11025Hz */
kSAI_SampleRate12KHz = 12000U, /*!< Sample rate 12000Hz */
kSAI_SampleRate16KHz = 16000U, /*!< Sample rate 16000Hz */
kSAI_SampleRate22050Hz = 22050U, /*!< Sample rate 22050Hz */
kSAI_SampleRate24KHz = 24000U, /*!< Sample rate 24000Hz */
kSAI_SampleRate32KHz = 32000U, /*!< Sample rate 32000Hz */
kSAI_SampleRate44100Hz = 44100U, /*!< Sample rate 44100Hz */
kSAI_SampleRate48KHz = 48000U, /*!< Sample rate 48000Hz */
kSAI_SampleRate96KHz = 96000U /*!< Sample rate 96000Hz */
} sai_sample_rate_t;
/*! @brief Audio word width */
typedef enum _sai_word_width
{
kSAI_WordWidth8bits = 8U, /*!< Audio data width 8 bits */
kSAI_WordWidth16bits = 16U, /*!< Audio data width 16 bits */
kSAI_WordWidth24bits = 24U, /*!< Audio data width 24 bits */
kSAI_WordWidth32bits = 32U /*!< Audio data width 32 bits */
} sai_word_width_t;
/*! @brief sai transfer format */
typedef struct _sai_transfer_format
{
uint32_t sampleRate_Hz; /*!< Sample rate of audio data */
uint32_t bitWidth; /*!< Data length of audio data, usually 8/16/24/32bits */
sai_mono_stereo_t stereo; /*!< Mono or stereo */
uint32_t masterClockHz; /*!< Master clock frequency in Hz */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
uint8_t watermark; /*!< Watermark value */
#endif /* FSL_FEATURE_SAI_FIFO_COUNT */
uint8_t channel; /*!< Data channel used in transfer.*/
sai_protocol_t protocol; /*!< Which audio protocol used */
} sai_transfer_format_t;
/*! @brief SAI transfer structure */
typedef struct _sai_transfer
{
uint8_t *data; /*!< Data start address to transfer. */
size_t dataSize; /*!< Transfer size. */
} sai_transfer_t;
typedef struct _sai_handle sai_handle_t;
/*! @brief SAI transfer callback prototype */
typedef void (*sai_transfer_callback_t)(I2S_Type *base, sai_handle_t *handle, status_t status, void *userData);
/*! @brief SAI handle structure */
struct _sai_handle
{
uint32_t state; /*!< Transfer status */
sai_transfer_callback_t callback; /*!< Callback function called at transfer event*/
void *userData; /*!< Callback parameter passed to callback function*/
uint8_t bitWidth; /*!< Bit width for transfer, 8/16/24/32bits */
uint8_t channel; /*!< Transfer channel */
sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */
size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
volatile uint8_t queueUser; /*!< Index for user to queue transfer */
volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
uint8_t watermark; /*!< Watermark value */
#endif
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes the SAI Tx peripheral.
*
* Ungates the SAI clock, resets the module, and configures SAI Tx with a configuration structure.
* The configuration structure can be custom filled or set with default values by
* SAI_TxGetDefaultConfig().
*
* @note This API should be called at the beginning of the application to use
* the SAI driver. Otherwise, accessing the SAIM module can cause a hard fault
* because the clock is not enabled.
*
* @param base SAI base pointer
* @param config SAI configure structure.
*/
void SAI_TxInit(I2S_Type *base, const sai_config_t *config);
/*!
* @brief Initializes the the SAI Rx peripheral.
*
* Ungates the SAI clock, resets the module, and configures the SAI Rx with a configuration structure.
* The configuration structure can be custom filled or set with default values by
* SAI_RxGetDefaultConfig().
*
* @note This API should be called at the beginning of the application to use
* the SAI driver. Otherwise, accessing the SAI module can cause a hard fault
* because the clock is not enabled.
*
* @param base SAI base pointer
* @param config SAI configure structure.
*/
void SAI_RxInit(I2S_Type *base, const sai_config_t *config);
/*!
* @brief Sets the SAI Tx configuration structure to default values.
*
* This API initializes the configuration structure for use in SAI_TxConfig().
* The initialized structure can remain unchanged in SAI_TxConfig(), or it can be modified
* before calling SAI_TxConfig().
* Example:
@code
sai_config_t config;
SAI_TxGetDefaultConfig(&config);
@endcode
*
* @param config pointer to master configuration structure
*/
void SAI_TxGetDefaultConfig(sai_config_t *config);
/*!
* @brief Sets the SAI Rx configuration structure to default values.
*
* This API initializes the configuration structure for use in SAI_RxConfig().
* The initialized structure can remain unchanged in SAI_RxConfig() or it can be modified
* before calling SAI_RxConfig().
* Example:
@code
sai_config_t config;
SAI_RxGetDefaultConfig(&config);
@endcode
*
* @param config pointer to master configuration structure
*/
void SAI_RxGetDefaultConfig(sai_config_t *config);
/*!
* @brief De-initializes the SAI peripheral.
*
* This API gates the SAI clock. The SAI module can't operate unless SAI_TxInit
* or SAI_RxInit is called to enable the clock.
*
* @param base SAI base pointer
*/
void SAI_Deinit(I2S_Type *base);
/*!
* @brief Resets the SAI Tx.
*
* This function enables the software reset and FIFO reset of SAI Tx. After reset, clear the reset bit.
*
* @param base SAI base pointer
*/
void SAI_TxReset(I2S_Type *base);
/*!
* @brief Resets the SAI Rx.
*
* This function enables the software reset and FIFO reset of SAI Rx. After reset, clear the reset bit.
*
* @param base SAI base pointer
*/
void SAI_RxReset(I2S_Type *base);
/*!
* @brief Enables/disables SAI Tx.
*
* @param base SAI base pointer
* @param enable True means enable SAI Tx, false means disable.
*/
void SAI_TxEnable(I2S_Type *base, bool enable);
/*!
* @brief Enables/disables SAI Rx.
*
* @param base SAI base pointer
* @param enable True means enable SAI Rx, false means disable.
*/
void SAI_RxEnable(I2S_Type *base, bool enable);
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the SAI Tx status flag state.
*
* @param base SAI base pointer
* @return SAI Tx status flag value. Use the Status Mask to get the status value needed.
*/
static inline uint32_t SAI_TxGetStatusFlag(I2S_Type *base)
{
return base->TCSR;
}
/*!
* @brief Clears the SAI Tx status flag state.
*
* @param base SAI base pointer
* @param mask State mask. It can be a combination of the following source if defined:
* @arg kSAI_WordStartFlag
* @arg kSAI_SyncErrorFlag
* @arg kSAI_FIFOErrorFlag
*/
static inline void SAI_TxClearStatusFlags(I2S_Type *base, uint32_t mask)
{
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | mask);
}
/*!
* @brief Gets the SAI Tx status flag state.
*
* @param base SAI base pointer
* @return SAI Rx status flag value. Use the Status Mask to get the status value needed.
*/
static inline uint32_t SAI_RxGetStatusFlag(I2S_Type *base)
{
return base->RCSR;
}
/*!
* @brief Clears the SAI Rx status flag state.
*
* @param base SAI base pointer
* @param mask State mask. It can be a combination of the following source if defined:
* @arg kSAI_WordStartFlag
* @arg kSAI_SyncErrorFlag
* @arg kSAI_FIFOErrorFlag
*/
static inline void SAI_RxClearStatusFlags(I2S_Type *base, uint32_t mask)
{
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | mask);
}
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables SAI Tx interrupt requests.
*
* @param base SAI base pointer
* @param mask interrupt source
* The parameter can be a combination of the following source if defined:
* @arg kSAI_WordStartInterruptEnable
* @arg kSAI_SyncErrorInterruptEnable
* @arg kSAI_FIFOWarningInterruptEnable
* @arg kSAI_FIFORequestInterruptEnable
* @arg kSAI_FIFOErrorInterruptEnable
*/
static inline void SAI_TxEnableInterrupts(I2S_Type *base, uint32_t mask)
{
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | mask);
}
/*!
* @brief Enables SAI Rx interrupt requests.
*
* @param base SAI base pointer
* @param mask interrupt source
* The parameter can be a combination of the following source if defined:
* @arg kSAI_WordStartInterruptEnable
* @arg kSAI_SyncErrorInterruptEnable
* @arg kSAI_FIFOWarningInterruptEnable
* @arg kSAI_FIFORequestInterruptEnable
* @arg kSAI_FIFOErrorInterruptEnable
*/
static inline void SAI_RxEnableInterrupts(I2S_Type *base, uint32_t mask)
{
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | mask);
}
/*!
* @brief Disables SAI Tx interrupt requests.
*
* @param base SAI base pointer
* @param mask interrupt source
* The parameter can be a combination of the following source if defined:
* @arg kSAI_WordStartInterruptEnable
* @arg kSAI_SyncErrorInterruptEnable
* @arg kSAI_FIFOWarningInterruptEnable
* @arg kSAI_FIFORequestInterruptEnable
* @arg kSAI_FIFOErrorInterruptEnable
*/
static inline void SAI_TxDisableInterrupts(I2S_Type *base, uint32_t mask)
{
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~mask));
}
/*!
* @brief Disables SAI Rx interrupt requests.
*
* @param base SAI base pointer
* @param mask interrupt source
* The parameter can be a combination of the following source if defined:
* @arg kSAI_WordStartInterruptEnable
* @arg kSAI_SyncErrorInterruptEnable
* @arg kSAI_FIFOWarningInterruptEnable
* @arg kSAI_FIFORequestInterruptEnable
* @arg kSAI_FIFOErrorInterruptEnable
*/
static inline void SAI_RxDisableInterrupts(I2S_Type *base, uint32_t mask)
{
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~mask));
}
/*! @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables/disables SAI Tx DMA requests.
* @param base SAI base pointer
* @param mask DMA source
* The parameter can be combination of the following source if defined:
* @arg kSAI_FIFOWarningDMAEnable
* @arg kSAI_FIFORequestDMAEnable
* @param enable True means enable DMA, false means disable DMA.
*/
static inline void SAI_TxEnableDMA(I2S_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | mask);
}
else
{
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~mask));
}
}
/*!
* @brief Enables/disables SAI Rx DMA requests.
* @param base SAI base pointer
* @param mask DMA source
* The parameter can be a combination of the following source if defined:
* @arg kSAI_FIFOWarningDMAEnable
* @arg kSAI_FIFORequestDMAEnable
* @param enable True means enable DMA, false means disable DMA.
*/
static inline void SAI_RxEnableDMA(I2S_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | mask);
}
else
{
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~mask));
}
}
/*!
* @brief Gets the SAI Tx data register address.
*
* This API is used to provide a transfer address for SAI DMA transfer configuration.
*
* @param base SAI base pointer.
* @param channel Which data channel used.
* @return data register address.
*/
static inline uint32_t SAI_TxGetDataRegisterAddress(I2S_Type *base, uint32_t channel)
{
return (uint32_t)(&(base->TDR)[channel]);
}
/*!
* @brief Gets the SAI Rx data register address.
*
* This API is used to provide a transfer address for SAI DMA transfer configuration.
*
* @param base SAI base pointer.
* @param channel Which data channel used.
* @return data register address.
*/
static inline uint32_t SAI_RxGetDataRegisterAddress(I2S_Type *base, uint32_t channel)
{
return (uint32_t)(&(base->RDR)[channel]);
}
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Configures the SAI Tx audio format.
*
* The audio format can be changed at run-time. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base SAI base pointer.
* @param format Pointer to SAI audio data format structure.
* @param mclkSourceClockHz SAI master clock source frequency in Hz.
* @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master
* clock, this value should equals to masterClockHz in format.
*/
void SAI_TxSetFormat(I2S_Type *base,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz);
/*!
* @brief Configures the SAI Rx audio format.
*
* The audio format can be changed at run-time. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base SAI base pointer.
* @param format Pointer to SAI audio data format structure.
* @param mclkSourceClockHz SAI master clock source frequency in Hz.
* @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master
* clock, this value should equals to masterClockHz in format.
*/
void SAI_RxSetFormat(I2S_Type *base,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz);
/*!
* @brief Sends data using a blocking method.
*
* @note This function blocks by polling until data is ready to be sent.
*
* @param base SAI base pointer.
* @param channel Data channel used.
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param buffer Pointer to the data to be written.
* @param size Bytes to be written.
*/
void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size);
/*!
* @brief Writes data into SAI FIFO.
*
* @param base SAI base pointer.
* @param channel Data channel used.
* @param data Data needs to be written.
*/
static inline void SAI_WriteData(I2S_Type *base, uint32_t channel, uint32_t data)
{
base->TDR[channel] = data;
}
/*!
* @brief Receives data using a blocking method.
*
* @note This function blocks by polling until data is ready to be sent.
*
* @param base SAI base pointer.
* @param channel Data channel used.
* @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
* @param buffer Pointer to the data to be read.
* @param size Bytes to be read.
*/
void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size);
/*!
* @brief Reads data from SAI FIFO.
*
* @param base SAI base pointer.
* @param channel Data channel used.
* @return Data in SAI FIFO.
*/
static inline uint32_t SAI_ReadData(I2S_Type *base, uint32_t channel)
{
return base->RDR[channel];
}
/*! @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the SAI Tx handle.
*
* This function initializes the Tx handle for SAI Tx transactional APIs. Call
* this function one time to get the handle initialized.
*
* @param base SAI base pointer
* @param handle SAI handle pointer.
* @param callback pointer to user callback function
* @param userData user parameter passed to the callback function
*/
void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData);
/*!
* @brief Initializes the SAI Rx handle.
*
* This function initializes the Rx handle for SAI Rx transactional APIs. Call
* this function one time to get the handle initialized.
*
* @param base SAI base pointer.
* @param handle SAI handle pointer.
* @param callback pointer to user callback function
* @param userData user parameter passed to the callback function
*/
void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData);
/*!
* @brief Configures the SAI Tx audio format.
*
* The audio format can be changed at run-time. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base SAI base pointer.
* @param handle SAI handle pointer.
* @param format Pointer to SAI audio data format structure.
* @param mclkSourceClockHz SAI master clock source frequency in Hz.
* @param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master
* clock, this value should equal to masterClockHz in format.
* @return Status of this function. Return value is one of status_t.
*/
status_t SAI_TransferTxSetFormat(I2S_Type *base,
sai_handle_t *handle,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz);
/*!
* @brief Configures the SAI Rx audio format.
*
* The audio format can be changed at run-time. This function configures the sample rate and audio data
* format to be transferred.
*
* @param base SAI base pointer.
* @param handle SAI handle pointer.
* @param format Pointer to SAI audio data format structure.
* @param mclkSourceClockHz SAI master clock source frequency in Hz.
* @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master
* clock, this value should equals to masterClockHz in format.
* @return Status of this function. Return value is one of status_t.
*/
status_t SAI_TransferRxSetFormat(I2S_Type *base,
sai_handle_t *handle,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz);
/*!
* @brief Performs an interrupt non-blocking send transfer on SAI.
*
* @note This API returns immediately after the transfer initiates.
* Call the SAI_TxGetTransferStatusIRQ to poll the transfer status and check whether
* the transfer is finished. If the return status is not kStatus_SAI_Busy, the transfer
* is finished.
*
* @param base SAI base pointer
* @param handle pointer to sai_handle_t structure which stores the transfer state
* @param xfer pointer to sai_transfer_t structure
* @retval kStatus_Success Successfully started the data receive.
* @retval kStatus_SAI_TxBusy Previous receive still not finished.
* @retval kStatus_InvalidArgument The input parameter is invalid.
*/
status_t SAI_TransferSendNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer);
/*!
* @brief Performs an interrupt non-blocking receive transfer on SAI.
*
* @note This API returns immediately after the transfer initiates.
* Call the SAI_RxGetTransferStatusIRQ to poll the transfer status and check whether
* the transfer is finished. If the return status is not kStatus_SAI_Busy, the transfer
* is finished.
*
* @param base SAI base pointer
* @param handle pointer to sai_handle_t structure which stores the transfer state
* @param xfer pointer to sai_transfer_t structure
* @retval kStatus_Success Successfully started the data receive.
* @retval kStatus_SAI_RxBusy Previous receive still not finished.
* @retval kStatus_InvalidArgument The input parameter is invalid.
*/
status_t SAI_TransferReceiveNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer);
/*!
* @brief Gets a set byte count.
*
* @param base SAI base pointer.
* @param handle pointer to sai_handle_t structure which stores the transfer state.
* @param count Bytes count sent.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t SAI_TransferGetSendCount(I2S_Type *base, sai_handle_t *handle, size_t *count);
/*!
* @brief Gets a received byte count.
*
* @param base SAI base pointer.
* @param handle pointer to sai_handle_t structure which stores the transfer state.
* @param count Bytes count received.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t SAI_TransferGetReceiveCount(I2S_Type *base, sai_handle_t *handle, size_t *count);
/*!
* @brief Aborts the current send.
*
* @note This API can be called any time when an interrupt non-blocking transfer initiates
* to abort the transfer early.
*
* @param base SAI base pointer.
* @param handle pointer to sai_handle_t structure which stores the transfer state.
*/
void SAI_TransferAbortSend(I2S_Type *base, sai_handle_t *handle);
/*!
* @brief Aborts the the current IRQ receive.
*
* @note This API can be called any time when an interrupt non-blocking transfer initiates
* to abort the transfer early.
*
* @param base SAI base pointer
* @param handle pointer to sai_handle_t structure which stores the transfer state.
*/
void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle);
/*!
* @brief Tx interrupt handler.
*
* @param base SAI base pointer.
* @param handle pointer to sai_handle_t structure.
*/
void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle);
/*!
* @brief Tx interrupt handler.
*
* @param base SAI base pointer.
* @param handle pointer to sai_handle_t structure.
*/
void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle);
/*! @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /* _FSL_SAI_H_ */

View File

@ -0,0 +1,431 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_sai_dma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! Structure definition for sai_dma_private_handle_t. The structure is private. */
typedef struct _sai_dma_private_handle
{
I2S_Type *base;
sai_dma_handle_t *handle;
} sai_dma_private_handle_t;
enum _sai_dma_states
{
kSAI_Idle = 0x0U,
kSAI_Busy = 0x1U,
};
/*<! Private handle only used for internally. */
static sai_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_I2S_COUNT][2];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the instance number for SAI.
*
* @param base SAI base pointer.
*/
extern uint32_t SAI_GetInstance(I2S_Type *base);
/*!
* @brief SAI EDMA callback for send.
*
* @param handle pointer to sai_dma_handle_t structure which stores the transfer state.
* @param userData Parameter for user callback.
*/
static void SAI_TxDMACallback(dma_handle_t *handle, void *userData);
/*!
* @brief SAI EDMA callback for receive.
*
* @param handle pointer to sai_dma_handle_t structure which stores the transfer state.
* @param userData Parameter for user callback.
*/
static void SAI_RxDMACallback(dma_handle_t *handle, void *userData);
/*******************************************************************************
* Code
******************************************************************************/
static void SAI_TxDMACallback(dma_handle_t *handle, void *userData)
{
sai_dma_private_handle_t *privHandle = (sai_dma_private_handle_t *)userData;
sai_dma_handle_t *saiHandle = privHandle->handle;
/* Update queue counter */
memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0, sizeof(sai_transfer_t));
saiHandle->queueDriver = (saiHandle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE;
/* Call callback function */
if (saiHandle->callback)
{
(saiHandle->callback)(privHandle->base, saiHandle, kStatus_SAI_TxIdle, saiHandle->userData);
}
/* If all data finished, just stop the transfer */
if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL)
{
SAI_TransferAbortSendDMA(privHandle->base, saiHandle);
}
}
static void SAI_RxDMACallback(dma_handle_t *handle, void *userData)
{
sai_dma_private_handle_t *privHandle = (sai_dma_private_handle_t *)userData;
sai_dma_handle_t *saiHandle = privHandle->handle;
/* Update queue counter */
memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0, sizeof(sai_transfer_t));
saiHandle->queueDriver = (saiHandle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE;
/* Call callback function */
if (saiHandle->callback)
{
(saiHandle->callback)(privHandle->base, saiHandle, kStatus_SAI_RxIdle, saiHandle->userData);
}
/* If all data finished, just stop the transfer */
if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL)
{
SAI_TransferAbortReceiveDMA(privHandle->base, saiHandle);
}
}
void SAI_TransferTxCreateHandleDMA(
I2S_Type *base, sai_dma_handle_t *handle, sai_dma_callback_t callback, void *userData, dma_handle_t *dmaHandle)
{
assert(handle && dmaHandle);
uint32_t instance = SAI_GetInstance(base);
/* Set sai base to handle */
handle->dmaHandle = dmaHandle;
handle->callback = callback;
handle->userData = userData;
/* Set SAI state to idle */
handle->state = kSAI_Idle;
s_dmaPrivateHandle[instance][0].base = base;
s_dmaPrivateHandle[instance][0].handle = handle;
/* Use FIFO error continue nstead of using interrupt to handle error */
#if defined(FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR) && (FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR)
base->TCR4 |= I2S_TCR4_FCONT_MASK;
#endif
/* Install callback for Tx dma channel */
DMA_SetCallback(dmaHandle, SAI_TxDMACallback, &s_dmaPrivateHandle[instance][0]);
}
void SAI_TransferRxCreateHandleDMA(
I2S_Type *base, sai_dma_handle_t *handle, sai_dma_callback_t callback, void *userData, dma_handle_t *dmaHandle)
{
assert(handle && dmaHandle);
uint32_t instance = SAI_GetInstance(base);
/* Set sai base to handle */
handle->dmaHandle = dmaHandle;
handle->callback = callback;
handle->userData = userData;
/* Set SAI state to idle */
handle->state = kSAI_Idle;
s_dmaPrivateHandle[instance][1].base = base;
s_dmaPrivateHandle[instance][1].handle = handle;
/* Use FIFO error continue nstead of using interrupt to handle error */
#if defined(FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR) && (FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR)
base->RCR4 |= I2S_RCR4_FCONT_MASK;
#endif
/* Install callback for Tx dma channel */
DMA_SetCallback(dmaHandle, SAI_RxDMACallback, &s_dmaPrivateHandle[instance][1]);
}
void SAI_TransferTxSetFormatDMA(I2S_Type *base,
sai_dma_handle_t *handle,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz)
{
assert(handle && format);
dma_transfer_config_t config = {0};
/* Configure the audio format to SAI registers */
SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
/* Update the information in handle */
handle->channel = format->channel;
/* Configure the data format into DMA register */
config.destAddr = SAI_TxGetDataRegisterAddress(base, format->channel);
config.enableDestIncrement = false;
config.enableSrcIncrement = true;
switch (format->bitWidth)
{
case 8:
config.srcSize = kDMA_Transfersize8bits;
config.destSize = kDMA_Transfersize8bits;
handle->bytesPerFrame = 1U;
break;
case 16:
config.srcSize = kDMA_Transfersize16bits;
config.destSize = kDMA_Transfersize16bits;
handle->bytesPerFrame = 2U;
break;
default:
config.srcSize = kDMA_Transfersize32bits;
config.destSize = kDMA_Transfersize32bits;
handle->bytesPerFrame = 4U;
break;
}
/* Configure DMA channel */
DMA_SubmitTransfer(handle->dmaHandle, &config, true);
}
void SAI_TransferRxSetFormatDMA(I2S_Type *base,
sai_dma_handle_t *handle,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz)
{
assert(handle && format);
dma_transfer_config_t config = {0};
/* Configure the audio format to SAI registers */
SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
handle->channel = format->channel;
/* Configure the data format into DMA register */
config.srcAddr = SAI_RxGetDataRegisterAddress(base, format->channel);
config.enableDestIncrement = true;
config.enableSrcIncrement = false;
switch (format->bitWidth)
{
case 8:
config.srcSize = kDMA_Transfersize8bits;
config.destSize = kDMA_Transfersize8bits;
handle->bytesPerFrame = 1U;
break;
case 16:
config.srcSize = kDMA_Transfersize16bits;
config.destSize = kDMA_Transfersize16bits;
handle->bytesPerFrame = 2U;
break;
default:
config.srcSize = kDMA_Transfersize32bits;
config.destSize = kDMA_Transfersize32bits;
handle->bytesPerFrame = 4U;
break;
}
/* Configure DMA channel */
DMA_SubmitTransfer(handle->dmaHandle, &config, true);
}
status_t SAI_TransferSendDMA(I2S_Type *base, sai_dma_handle_t *handle, sai_transfer_t *xfer)
{
assert(handle && xfer);
/* Check if input parameter invalid */
if ((xfer->data == NULL) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
if (handle->saiQueue[handle->queueUser].data)
{
return kStatus_SAI_QueueFull;
}
handle->transferSize[handle->queueUser] = xfer->dataSize;
handle->saiQueue[handle->queueUser].data = xfer->data;
handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE;
/* Set the source address */
DMA_SetSourceAddress(handle->dmaHandle->base, handle->dmaHandle->channel, (uint32_t)(xfer->data));
/* Set the transfer size */
DMA_SetTransferSize(handle->dmaHandle->base, handle->dmaHandle->channel, xfer->dataSize);
/* Change the state of handle */
handle->state = kSAI_Busy;
/* Start DMA transfer */
DMA_StartTransfer(handle->dmaHandle);
/* Enable DMA request and start SAI */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
#else
SAI_TxEnableDMA(base, kSAI_FIFOWarningDMAEnable, true);
#endif
SAI_TxEnable(base, true);
return kStatus_Success;
}
status_t SAI_TransferReceiveDMA(I2S_Type *base, sai_dma_handle_t *handle, sai_transfer_t *xfer)
{
assert(handle && xfer);
/* Check if input parameter invalid */
if ((xfer->data == NULL) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
if (handle->saiQueue[handle->queueUser].data)
{
return kStatus_SAI_QueueFull;
}
/* Add into queue */
handle->transferSize[handle->queueUser] = xfer->dataSize;
handle->saiQueue[handle->queueUser].data = xfer->data;
handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE;
/* Set the source address */
DMA_SetDestinationAddress(handle->dmaHandle->base, handle->dmaHandle->channel, (uint32_t)(xfer->data));
/* Set the transfer size */
DMA_SetTransferSize(handle->dmaHandle->base, handle->dmaHandle->channel, xfer->dataSize);
/* Change the state of handle */
handle->state = kSAI_Busy;
/* Start DMA transfer */
DMA_StartTransfer(handle->dmaHandle);
/* Enable DMA request and start SAI */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
#else
SAI_RxEnableDMA(base, kSAI_FIFOWarningDMAEnable, true);
#endif
SAI_RxEnable(base, true);
return kStatus_Success;
}
void SAI_TransferAbortSendDMA(I2S_Type *base, sai_dma_handle_t *handle)
{
assert(handle);
/* Disable dma */
DMA_AbortTransfer(handle->dmaHandle);
/* Disable DMA enable bit */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false);
#else
SAI_TxEnableDMA(base, kSAI_FIFOWarningDMAEnable, false);
#endif
/* Set the handle state */
handle->state = kSAI_Idle;
/* Clear the queue */
memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE);
handle->queueDriver = 0;
handle->queueUser = 0;
}
void SAI_TransferAbortReceiveDMA(I2S_Type *base, sai_dma_handle_t *handle)
{
assert(handle);
/* Disable dma */
DMA_AbortTransfer(handle->dmaHandle);
/* Disable DMA enable bit */
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false);
#else
SAI_RxEnableDMA(base, kSAI_FIFOWarningDMAEnable, false);
#endif
/* Set the handle state */
handle->state = kSAI_Idle;
/* Clear the queue */
memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE);
handle->queueDriver = 0;
handle->queueUser = 0;
}
status_t SAI_TransferGetSendCountDMA(I2S_Type *base, sai_dma_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kSAI_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
*count = handle->transferSize[handle->queueDriver] -
DMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel);
}
return status;
}
status_t SAI_TransferGetReceiveCountDMA(I2S_Type *base, sai_dma_handle_t *handle, size_t *count)
{
assert(handle);
status_t status = kStatus_Success;
if (handle->state != kSAI_Busy)
{
status = kStatus_NoTransferInProgress;
}
else
{
*count = handle->transferSize[handle->queueDriver] -
DMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel);
}
return status;
}

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_SAI_DMA_H_
#define _FSL_SAI_DMA_H_
#include "fsl_sai.h"
#include "fsl_dma.h"
/*!
* @addtogroup sai_dma
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
typedef struct _sai_dma_handle sai_dma_handle_t;
/*! @brief Define SAI DMA callback */
typedef void (*sai_dma_callback_t)(I2S_Type *base, sai_dma_handle_t *handle, status_t status, void *userData);
/*! @brief SAI DMA transfer handle, users should not touch the content of the handle.*/
struct _sai_dma_handle
{
dma_handle_t *dmaHandle; /*!< DMA handler for SAI send */
uint8_t bytesPerFrame; /*!< Bytes in a frame */
uint8_t channel; /*!< Which Data channel SAI use */
uint32_t state; /*!< SAI DMA transfer internal state */
sai_dma_callback_t callback; /*!< Callback for users while transfer finish or error occured */
void *userData; /*!< User callback parameter */
sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */
size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
volatile uint8_t queueUser; /*!< Index for user to queue transfer. */
volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name DMA Transactional
* @{
*/
/*!
* @brief Initializes the SAI master DMA handle.
*
* This function initializes the SAI master DMA handle, which can be used for other SAI master transactional APIs.
* Usually, for a specified SAI instance, call this API once to get the initialized handle.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param base SAI peripheral base address.
* @param callback Pointer to user callback function.
* @param userData User parameter passed to the callback function.
* @param dmaHandle DMA handle pointer, this handle shall be static allocated by users.
*/
void SAI_TransferTxCreateHandleDMA(
I2S_Type *base, sai_dma_handle_t *handle, sai_dma_callback_t callback, void *userData, dma_handle_t *dmaHandle);
/*!
* @brief Initializes the SAI slave DMA handle.
*
* This function initializes the SAI slave DMA handle, which can be used for other SAI master transactional APIs.
* Usually, for a specified SAI instance, call this API once to get the initialized handle.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param base SAI peripheral base address.
* @param callback Pointer to user callback function.
* @param userData User parameter passed to the callback function.
* @param dmaHandle DMA handle pointer, this handle shall be static allocated by users.
*/
void SAI_TransferRxCreateHandleDMA(
I2S_Type *base, sai_dma_handle_t *handle, sai_dma_callback_t callback, void *userData, dma_handle_t *dmaHandle);
/*!
* @brief Configures the SAI Tx audio format.
*
* The audio format can be changed at run-time. This function configures the sample rate and audio data
* format to be transferred. This function also sets the eDMA parameter according to the format.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param format Pointer to SAI audio data format structure.
* @param mclkSourceClockHz SAI master clock source frequency in Hz.
* @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master.
* clock, this value should equals to masterClockHz in format.
* @retval kStatus_Success Audio format set successfully.
* @retval kStatus_InvalidArgument The input arguments is invalid.
*/
void SAI_TransferTxSetFormatDMA(I2S_Type *base,
sai_dma_handle_t *handle,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz);
/*!
* @brief Configures the SAI Rx audio format.
*
* The audio format can be changed at run-time. This function configures the sample rate and audio data
* format to be transferred. This function also sets EDMA parameter according to format.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param format Pointer to SAI audio data format structure.
* @param mclkSourceClockHz SAI master clock source frequency in Hz.
* @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master.
* clock, this value should equals to masterClockHz in format.
* @retval kStatus_Success Audio format set successfully.
* @retval kStatus_InvalidArgument The input arguments is invalid.
*/
void SAI_TransferRxSetFormatDMA(I2S_Type *base,
sai_dma_handle_t *handle,
sai_transfer_format_t *format,
uint32_t mclkSourceClockHz,
uint32_t bclkSourceClockHz);
/*!
* @brief Performs a non-blocking SAI transfer using DMA.
*
* @note This interface returns immediately after the transfer initiates. Call
* the SAI_GetTransferStatus to poll the transfer status to check whether the SAI transfer finished.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param xfer Pointer to DMA transfer structure.
* @retval kStatus_Success Successfully start the data receive.
* @retval kStatus_SAI_TxBusy Previous receive still not finished.
* @retval kStatus_InvalidArgument The input parameter is invalid.
*/
status_t SAI_TransferSendDMA(I2S_Type *base, sai_dma_handle_t *handle, sai_transfer_t *xfer);
/*!
* @brief Performs a non-blocking SAI transfer using DMA.
*
* @note This interface returns immediately after transfer initiates. Call
* SAI_GetTransferStatus to poll the transfer status to check whether the SAI transfer is finished.
*
* @param base SAI base pointer
* @param handle SAI DMA handle pointer.
* @param xfer Pointer to DMA transfer structure.
* @retval kStatus_Success Successfully start the data receive.
* @retval kStatus_SAI_RxBusy Previous receive still not finished.
* @retval kStatus_InvalidArgument The input parameter is invalid.
*/
status_t SAI_TransferReceiveDMA(I2S_Type *base, sai_dma_handle_t *handle, sai_transfer_t *xfer);
/*!
* @brief Aborts a SAI transfer using DMA.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
*/
void SAI_TransferAbortSendDMA(I2S_Type *base, sai_dma_handle_t *handle);
/*!
* @brief Aborts a SAI transfer using DMA.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
*/
void SAI_TransferAbortReceiveDMA(I2S_Type *base, sai_dma_handle_t *handle);
/*!
* @brief Gets byte count sent by SAI.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param count Bytes count sent by SAI.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t SAI_TransferGetSendCountDMA(I2S_Type *base, sai_dma_handle_t *handle, size_t *count);
/*!
* @brief Gets byte count received by SAI.
*
* @param base SAI base pointer.
* @param handle SAI DMA handle pointer.
* @param count Bytes count received by SAI.
* @retval kStatus_Success Succeed get the transfer count.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
*/
status_t SAI_TransferGetReceiveCountDMA(I2S_Type *base, sai_dma_handle_t *handle, size_t *count);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_sim.h"
/*******************************************************************************
* Codes
******************************************************************************/
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR)
void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask)
{
SIM->SOPT1CFG |= (SIM_SOPT1CFG_URWE_MASK | SIM_SOPT1CFG_UVSWE_MASK | SIM_SOPT1CFG_USSWE_MASK);
SIM->SOPT1 = (SIM->SOPT1 & ~kSIM_UsbVoltRegEnableInAllModes) | mask;
}
#endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */
void SIM_GetUniqueId(sim_uid_t *uid)
{
#if defined(SIM_UIDH)
uid->H = SIM->UIDH;
#endif
uid->MH = SIM->UIDMH;
uid->ML = SIM->UIDML;
uid->L = SIM->UIDL;
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_SIM_H_
#define _FSL_SIM_H_
#include "fsl_common.h"
/*! @addtogroup sim */
/*! @{*/
/*! @file */
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_SIM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Driver version 2.0.0 */
/*@}*/
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR)
/*!@brief USB voltage regulator enable setting. */
enum _sim_usb_volt_reg_enable_mode
{
kSIM_UsbVoltRegEnable = SIM_SOPT1_USBREGEN_MASK, /*!< Enable voltage regulator. */
kSIM_UsbVoltRegEnableInLowPower = SIM_SOPT1_USBVSTBY_MASK, /*!< Enable voltage regulator in VLPR/VLPW modes. */
kSIM_UsbVoltRegEnableInStop = SIM_SOPT1_USBSSTBY_MASK, /*!< Enable voltage regulator in STOP/VLPS/LLS/VLLS modes. */
kSIM_UsbVoltRegEnableInAllModes = SIM_SOPT1_USBREGEN_MASK | SIM_SOPT1_USBSSTBY_MASK |
SIM_SOPT1_USBVSTBY_MASK /*!< Enable voltage regulator in all power modes. */
};
#endif /* (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) */
/*!@brief Unique ID. */
typedef struct _sim_uid
{
#if defined(SIM_UIDH)
uint32_t H; /*!< UIDH. */
#endif
uint32_t MH; /*!< UIDMH. */
uint32_t ML; /*!< UIDML. */
uint32_t L; /*!< UIDL. */
} sim_uid_t;
/*!@brief Flash enable mode. */
enum _sim_flash_mode
{
kSIM_FlashDisableInWait = SIM_FCFG1_FLASHDOZE_MASK, /*!< Disable flash in wait mode. */
kSIM_FlashDisable = SIM_FCFG1_FLASHDIS_MASK /*!< Disable flash in normal mode. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR)
/*!
* @brief Sets the USB voltage regulator setting.
*
* This function configures whether the USB voltage regulator is enabled in
* normal RUN mode, STOP/VLPS/LLS/VLLS modes and VLPR/VLPW modes. The configurations
* are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, enable
* USB voltage regulator in RUN/VLPR/VLPW modes and disable in STOP/VLPS/LLS/VLLS mode,
* please use:
*
* SIM_SetUsbVoltRegulatorEnableMode(kSIM_UsbVoltRegEnable | kSIM_UsbVoltRegEnableInLowPower);
*
* @param mask USB voltage regulator enable setting.
*/
void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask);
#endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */
/*!
* @brief Get the unique identification register value.
*
* @param uid Pointer to the structure to save the UID value.
*/
void SIM_GetUniqueId(sim_uid_t *uid);
/*!
* @brief Set the flash enable mode.
*
* @param mode The mode to set, see \ref _sim_flash_mode for mode details.
*/
static inline void SIM_SetFlashMode(uint8_t mode)
{
SIM->FCFG1 = mode;
}
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_SIM_H_ */

View File

@ -0,0 +1,278 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_slcd.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define SLCD_WAVEFORM_CONFIG_NUM 16
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the SLCD instance from peripheral base address.
*
* @param base SLCD peripheral base address.
* @return SLCD instance.
*/
static uint32_t SLCD_GetInstance(LCD_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to slcd clocks for each instance. */
const clock_ip_name_t s_slcdClock[FSL_FEATURE_SOC_SLCD_COUNT] = SLCD_CLOCKS;
/*! @brief Pointers to slcd bases for each instance. */
static LCD_Type *const s_slcdBases[] = LCD_BASE_PTRS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t SLCD_GetInstance(LCD_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < FSL_FEATURE_SOC_SLCD_COUNT; instance++)
{
if (s_slcdBases[instance] == base)
{
break;
}
}
assert(instance < FSL_FEATURE_SOC_SLCD_COUNT);
return instance;
}
void SLCD_Init(LCD_Type *base, slcd_config_t *configure)
{
assert(configure);
assert(configure->clkConfig);
uint32_t gcrReg = 0;
bool intEnabled = false;
uint32_t regNum = 0;
uint32_t instance = SLCD_GetInstance(base);
/* Un-gate the SLCD clock. */
CLOCK_EnableClock(s_slcdClock[instance]);
/* Configure general setting: power supply. */
gcrReg = LCD_GCR_RVEN(configure->powerSupply & 0x1U) | LCD_GCR_CPSEL((configure->powerSupply >> 1U) & 0x1U) |
LCD_GCR_VSUPPLY((configure->powerSupply >> 2U) & 0x1U) | LCD_GCR_LADJ(configure->loadAdjust);
/* Configure general setting: clock source. */
gcrReg |= LCD_GCR_SOURCE((configure->clkConfig->clkSource) & 0x1U) |
LCD_GCR_LCLK(configure->clkConfig->clkPrescaler) | LCD_GCR_ALTDIV(configure->clkConfig->altClkDivider);
/* Configure the duty and set the work for low power wait and stop mode. */
gcrReg |= LCD_GCR_DUTY(configure->dutyCycle) | LCD_GCR_LCDSTP(configure->lowPowerBehavior & 0x1U);
#if FSL_FEATURE_SLCD_HAS_LCD_WAIT
gcrReg |= LCD_GCR_LCDWAIT((configure->lowPowerBehavior >> 1U) & 0x1U);
#endif
#if FSL_FEATURE_SLCD_HAS_LCD_DOZE_ENABLE
gcrReg |= LCD_GCR_LCDDOZE((configure->lowPowerBehavior >> 1U) & 0x1U);
#endif
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
/* Configure for frame frequency interrupt. */
gcrReg |= LCD_GCR_LCDIEN(configure->frameFreqIntEnable);
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
#if FSL_FEATURE_SLCD_HAS_MULTI_ALTERNATE_CLOCK_SOURCE
/* Select the alternate clock for alternate clock source. */
gcrReg |= LCD_GCR_ALTSOURCE(((configure->clkConfig->clkSource) >> 1U) & 0x1U);
#endif /* FSL_FEATURE_SLCD_HAS_MULTI_ALTERNATE_CLOCK_SOURCE */
#if FSL_FEATURE_SLCD_HAS_FAST_FRAME_RATE
/* Configure the for fast frame rate. */
gcrReg |= LCD_GCR_FFR(configure->clkConfig->fastFrameRateEnable ? 1U : 0U);
#endif /* FSL_FEATURE_SLCD_HAS_FAST_FRAME_RATE */
if (configure->powerSupply & 0x1U)
{
gcrReg |= LCD_GCR_RVTRIM(configure->voltageTrim);
}
base->GCR = gcrReg;
/* Set display mode. */
base->AR = LCD_AR_ALT(configure->displayMode & 0x1U) | LCD_AR_BLANK((configure->displayMode >> 1U) & 0x1U);
/* Configure the front plane and back plane pin setting. */
base->BPEN[0] = configure->backPlaneLowPin;
base->BPEN[1] = configure->backPlaneHighPin;
base->PEN[0] = configure->slcdLowPinEnabled;
base->PEN[1] = configure->slcdHighPinEnabled;
/* Set the fault frame detection. */
base->FDCR = 0;
if (configure->faultConfig)
{
/* If fault configure structure is not NULL, the fault detection is enabled. */
base->FDCR = LCD_FDCR_FDPRS(configure->faultConfig->faultPrescaler) |
LCD_FDCR_FDSWW(configure->faultConfig->width) |
LCD_FDCR_FDBPEN(configure->faultConfig->faultDetectBackPlaneEnable ? 1U : 0U) |
LCD_FDCR_FDPINID(configure->faultConfig->faultDetectPinIndex) | LCD_FDCR_FDEN_MASK;
if (configure->faultConfig->faultDetectIntEnable)
{
base->GCR |= LCD_GCR_FDCIEN_MASK;
intEnabled = true;
}
}
/* Initialize the Waveform. */
for (regNum = 0; regNum < SLCD_WAVEFORM_CONFIG_NUM; regNum++)
{
base->WF[regNum] = 0;
}
/* Enable the NVIC. */
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
if (configure->frameFreqIntEnable)
{
intEnabled = true;
}
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
if (intEnabled)
{
EnableIRQ(LCD_IRQn);
}
}
void SLCD_Deinit(LCD_Type *base)
{
uint32_t instance = SLCD_GetInstance(base);
/* Stop SLCD display. */
SLCD_StopDisplay(base);
/* Gate the SLCD clock. */
CLOCK_DisableClock(s_slcdClock[instance]);
/* Disable NVIC. */
DisableIRQ(LCD_IRQn);
}
void SLCD_GetDefaultConfig(slcd_config_t *configure)
{
assert(configure);
/* Get Default parameters for the configuration structure. */
/* SLCD in normal mode. */
configure->displayMode = kSLCD_NormalMode;
/* Power supply default: use charge pump to generate VLL1 and VLL2, VLL3 connected to VDD internally. */
configure->powerSupply = kSLCD_InternalVll3UseChargePump;
configure->voltageTrim = kSLCD_RegulatedVolatgeTrim00;
/* Work in low power mode. */
configure->lowPowerBehavior = kSLCD_EnabledInWaitStop;
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
/* No interrupt source is enabled. */
configure->frameFreqIntEnable = false;
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
/* Fault detection is disabled. */
configure->faultConfig = NULL;
}
void SLCD_StartBlinkMode(LCD_Type *base, slcd_blink_mode_t mode, slcd_blink_rate_t rate)
{
base->AR &= ~(LCD_AR_BMODE_MASK | LCD_AR_BRATE_MASK);
/* Set blink mode and blink rate. */
base->AR |= LCD_AR_BMODE(mode) | LCD_AR_BRATE(rate);
/* Enable Blink mode. */
base->AR |= LCD_AR_BLINK_MASK;
}
void SLCD_EnableInterrupts(LCD_Type *base, uint32_t mask)
{
uint32_t gcReg = base->GCR;
gcReg |= LCD_GCR_FDCIEN(mask & 0x1U);
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
gcReg |= LCD_GCR_LCDEN((mask >> 1U) & 0x1U);
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
base->GCR = gcReg;
}
void SLCD_DisableInterrupts(LCD_Type *base, uint32_t mask)
{
uint32_t gcrReg = base->GCR;
/*!< SLCD fault detection complete interrupt source. */
if (mask & kSLCD_FaultDetectCompleteInterrupt)
{
gcrReg &= ~LCD_GCR_FDCIEN_MASK;
}
/*!< SLCD frame frequency interrupt source. */
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
if (mask & kSLCD_FrameFreqInterrupt)
{
gcrReg &= ~LCD_GCR_LCDIEN_MASK;
}
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
base->GCR = gcrReg;
}
void SLCD_ClearInterruptStatus(LCD_Type *base, uint32_t mask)
{
/*!< SLCD fault detection complete interrupt source. */
if (mask & kSLCD_FaultDetectCompleteInterrupt)
{
base->FDSR |= LCD_FDSR_FDCF_MASK;
}
/*!< SLCD frame frequency interrupt source. */
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
if (mask & kSLCD_FrameFreqInterrupt)
{
base->AR |= LCD_AR_LCDIF_MASK;
}
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
}
uint32_t SLCD_GetInterruptStatus(LCD_Type *base)
{
uint32_t status = 0;
/* Get the frame detect complete interrupt status. */
status = ((base->FDSR & LCD_FDSR_FDCF_MASK) >> LCD_FDSR_FDCF_SHIFT);
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
/* Get the frame frequency interrupt status. */
status |= ((base->AR & LCD_AR_LCDIF_MASK) >> (LCD_AR_LCDIF_SHIFT - 1));
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
return status;
}

View File

@ -0,0 +1,586 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_SLCD_H_
#define _FSL_SLCD_H_
#include "fsl_common.h"
/*!
* @addtogroup slcd
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief SLCD driver version 2.0.0. */
#define FSL_SLCD_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*! @brief SLCD power supply option. */
typedef enum _slcd_power_supply_option
{
kSLCD_InternalVll3UseChargePump =
2U, /*!< VLL3 connected to VDD internally, charge pump is used to generate VLL1 and VLL2. */
kSLCD_ExternalVll3UseResistorBiasNetwork =
4U, /*!< VLL3 is driven externally and resistor bias network is used to generate VLL1 and VLL2. */
kSLCD_ExteranlVll3UseChargePump =
6U, /*!< VLL3 is driven externally and charge pump is used to generate VLL1 and VLL2. */
kSLCD_InternalVll1UseChargePump =
7U /*!< VIREG is connected to VLL1 internally and charge pump is used to generate VLL2 and VLL3. */
} slcd_power_supply_option_t;
/*! @brief SLCD regulated voltage trim parameter, be used to meet the desired contrast. */
typedef enum _slcd_regulated_voltage_trim
{
kSLCD_RegulatedVolatgeTrim00 = 0U, /*!< Increase the voltage to 0.91 V. */
kSLCD_RegulatedVolatgeTrim01, /*!< Increase the voltage to 1.01 V. */
kSLCD_RegulatedVolatgeTrim02, /*!< Increase the voltage to 0.96 V. */
kSLCD_RegulatedVolatgeTrim03, /*!< Increase the voltage to 1.06 V. */
kSLCD_RegulatedVolatgeTrim04, /*!< Increase the voltage to 0.93 V. */
kSLCD_RegulatedVolatgeTrim05, /*!< Increase the voltage to 1.02 V. */
kSLCD_RegulatedVolatgeTrim06, /*!< Increase the voltage to 0.98 V. */
kSLCD_RegulatedVolatgeTrim07, /*!< Increase the voltage to 1.08 V. */
kSLCD_RegulatedVolatgeTrim08, /*!< Increase the voltage to 0.92 V. */
kSLCD_RegulatedVolatgeTrim09, /*!< Increase the voltage to 1.02 V. */
kSLCD_RegulatedVolatgeTrim10, /*!< Increase the voltage to 0.97 V. */
kSLCD_RegulatedVolatgeTrim11, /*!< Increase the voltage to 1.07 V. */
kSLCD_RegulatedVolatgeTrim12, /*!< Increase the voltage to 0.94 V. */
kSLCD_RegulatedVolatgeTrim13, /*!< Increase the voltage to 1.05 V. */
kSLCD_RegulatedVolatgeTrim14, /*!< Increase the voltage to 0.99 V. */
kSLCD_RegulatedVolatgeTrim15 /*!< Increase the voltage to 1.09 V. */
} slcd_regulated_voltage_trim_t;
/*! @brief SLCD load adjust to handle different LCD glass capacitance or
* configure the LCD charge pump clock source.
* Adjust the LCD glass capacitance if resistor bias network is enabled:
* kSLCD_LowLoadOrFastestClkSrc - Low load (LCD glass capacitance 2000pF or lower.
* LCD or GPIO function can be used on VLL1,VLL2,Vcap1 and Vcap2 pins)
* kSLCD_LowLoadOrIntermediateClkSrc - low load (LCD glass capacitance 2000pF or lower.
* LCD or GPIO function can be used on VLL1,VLL2,Vcap1 and Vcap2 pins)
* kSLCD_HighLoadOrIntermediateClkSrc - high load (LCD glass capacitance 8000pF or lower.
* LCD or GPIO function can be used on Vcap1 and Vcap2 pins)
* kSLCD_HighLoadOrSlowestClkSrc - high load (LCD glass capacitance 8000pF or lower
* LCD or GPIO function can be used on Vcap1 and Vcap2 pins)
* Adjust clock for charge pump if charge pump is enabled:
* kSLCD_LowLoadOrFastestClkSrc - Fasten clock source (LCD glass capacitance
* 8000pF or 4000pF or lower if Fast Frame Rate is set)
* kSLCD_LowLoadOrIntermediateClkSrc - Intermediate clock source (LCD glass
* capacitance 4000pF or 2000pF or lower if Fast Frame Rate is set)
* kSLCD_HighLoadOrIntermediateClkSrc - Intermediate clock source (LCD glass
* capacitance 2000pF or 1000pF or lower if Fast Frame Rate is set)
* kSLCD_HighLoadOrSlowestClkSrc - slowest clock source (LCD glass capacitance
* 1000pF or 500pF or lower if Fast Frame Rate is set)
*/
typedef enum _slcd_load_adjust
{
kSLCD_LowLoadOrFastestClkSrc = 0U, /*!< Adjust in low load or selects fastest clock. */
kSLCD_LowLoadOrIntermediateClkSrc, /*!< Adjust in low load or selects intermediate clock. */
kSLCD_HighLoadOrIntermediateClkSrc, /*!< Adjust in high load or selects intermediate clock. */
kSLCD_HighLoadOrSlowestClkSrc /*!< Adjust in high load or selects slowest clock. */
} slcd_load_adjust_t;
/*! @brief SLCD clock source. */
typedef enum _slcd_clock_src
{
kSLCD_DefaultClk = 0U, /*!< Select default clock ERCLK32K. */
kSLCD_AlternateClk1 = 1U, /*!< Select alternate clock source 1 : MCGIRCLK. */
#if FSL_FEATURE_SLCD_HAS_MULTI_ALTERNATE_CLOCK_SOURCE
kSLCD_AlternateClk2 = 3U /*!< Select alternate clock source 2 : OSCERCLK. */
#endif /* FSL_FEATURE_SLCD_HAS_MULTI_ALTERNATE_CLOCK_SOURCE */
} slcd_clock_src_t;
/*! @brief SLCD alternate clock divider. */
typedef enum _slcd_alt_clock_div
{
kSLCD_AltClkDivFactor1 = 0U, /*!< No divide for alternate clock. */
kSLCD_AltClkDivFactor64, /*!< Divide alternate clock with factor 64. */
kSLCD_AltClkDivFactor256, /*!< Divide alternate clock with factor 256. */
kSLCD_AltClkDivFactor512 /*!< Divide alternate clock with factor 512. */
} slcd_alt_clock_div_t;
/*! @brief SLCD clock prescaler to generate frame frequency. */
typedef enum _slcd_clock_prescaler
{
kSLCD_ClkPrescaler00 = 0U, /*!< Prescaler 0. */
kSLCD_ClkPrescaler01, /*!< Prescaler 1. */
kSLCD_ClkPrescaler02, /*!< Prescaler 2. */
kSLCD_ClkPrescaler03, /*!< Prescaler 3. */
kSLCD_ClkPrescaler04, /*!< Prescaler 4. */
kSLCD_ClkPrescaler05, /*!< Prescaler 5. */
kSLCD_ClkPrescaler06, /*!< Prescaler 6. */
kSLCD_ClkPrescaler07 /*!< Prescaler 7. */
} slcd_clock_prescaler_t;
/*! @brief SLCD duty cycle. */
typedef enum _slcd_duty_cycle
{
kSLCD_1Div1DutyCycle = 0U, /*!< LCD use 1 BP 1/1 duty cycle. */
kSLCD_1Div2DutyCycle, /*!< LCD use 2 BP 1/2 duty cycle. */
kSLCD_1Div3DutyCycle, /*!< LCD use 3 BP 1/3 duty cycle. */
kSLCD_1Div4DutyCycle, /*!< LCD use 4 BP 1/4 duty cycle. */
kSLCD_1Div5DutyCycle, /*!< LCD use 5 BP 1/5 duty cycle. */
kSLCD_1Div6DutyCycle, /*!< LCD use 6 BP 1/6 duty cycle. */
kSLCD_1Div7DutyCycle, /*!< LCD use 7 BP 1/7 duty cycle. */
kSLCD_1Div8DutyCycle /*!< LCD use 8 BP 1/8 duty cycle. */
} slcd_duty_cycle_t;
/*! @brief SLCD segment phase type. */
typedef enum _slcd_phase_type
{
kSLCD_NoPhaseActivate = 0x00U, /*!< LCD wareform no phase activates. */
kSLCD_PhaseAActivate = 0x01U, /*!< LCD waveform phase A activates. */
kSLCD_PhaseBActivate = 0x02U, /*!< LCD waveform phase B activates. */
kSLCD_PhaseCActivate = 0x04U, /*!< LCD waveform phase C activates. */
kSLCD_PhaseDActivate = 0x08U, /*!< LCD waveform phase D activates. */
kSLCD_PhaseEActivate = 0x10U, /*!< LCD waveform phase E activates. */
kSLCD_PhaseFActivate = 0x20U, /*!< LCD waveform phase F activates. */
kSLCD_PhaseGActivate = 0x40U, /*!< LCD waveform phase G activates. */
kSLCD_PhaseHActivate = 0x80U /*!< LCD waveform phase H activates. */
} slcd_phase_type_t;
/*! @brief SLCD segment phase bit index. */
typedef enum _slcd_phase_index
{
kSLCD_PhaseAIndex = 0x0U, /*!< LCD phase A bit index. */
kSLCD_PhaseBIndex = 0x1U, /*!< LCD phase B bit index. */
kSLCD_PhaseCIndex = 0x2U, /*!< LCD phase C bit index. */
kSLCD_PhaseDIndex = 0x3U, /*!< LCD phase D bit index. */
kSLCD_PhaseEIndex = 0x4U, /*!< LCD phase E bit index. */
kSLCD_PhaseFIndex = 0x5U, /*!< LCD phase F bit index. */
kSLCD_PhaseGIndex = 0x6U, /*!< LCD phase G bit index. */
kSLCD_PhaseHIndex = 0x7U /*!< LCD phase H bit index. */
} slcd_phase_index_t;
/*! @brief SLCD display mode. */
typedef enum _slcd_display_mode
{
kSLCD_NormalMode = 0U, /*!< LCD Normal display mode. */
kSLCD_AlternateMode, /*!< LCD Alternate display mode. For four back planes or less. */
kSLCD_BlankMode /*!< LCD Blank display mode. */
} slcd_display_mode_t;
/*! @brief SLCD blink mode. */
typedef enum _slcd_blink_mode
{
kSLCD_BlankDisplayBlink = 0U, /*!< Display blank during the blink period. */
kSLCD_AltDisplayBlink /*!< Display alternate display during the blink period if duty cycle is lower than 5. */
} slcd_blink_mode_t;
/*! @brief SLCD blink rate. */
typedef enum _slcd_blink_rate
{
kSLCD_BlinkRate00 = 0U, /*!< SLCD blink rate is LCD clock/((2^12)). */
kSLCD_BlinkRate01, /*!< SLCD blink rate is LCD clock/((2^13)). */
kSLCD_BlinkRate02, /*!< SLCD blink rate is LCD clock/((2^14)). */
kSLCD_BlinkRate03, /*!< SLCD blink rate is LCD clock/((2^15)). */
kSLCD_BlinkRate04, /*!< SLCD blink rate is LCD clock/((2^16)). */
kSLCD_BlinkRate05, /*!< SLCD blink rate is LCD clock/((2^17)). */
kSLCD_BlinkRate06, /*!< SLCD blink rate is LCD clock/((2^18)). */
kSLCD_BlinkRate07 /*!< SLCD blink rate is LCD clock/((2^19)). */
} slcd_blink_rate_t;
/*! @brief SLCD fault detect clock prescaler. */
typedef enum _slcd_fault_detect_clock_prescaler
{
kSLCD_FaultSampleFreqDivider1 = 0U, /*!< Fault detect sample clock frequency is 1/1 bus clock. */
kSLCD_FaultSampleFreqDivider2, /*!< Fault detect sample clock frequency is 1/2 bus clock. */
kSLCD_FaultSampleFreqDivider4, /*!< Fault detect sample clock frequency is 1/4 bus clock. */
kSLCD_FaultSampleFreqDivider8, /*!< Fault detect sample clock frequency is 1/8 bus clock. */
kSLCD_FaultSampleFreqDivider16, /*!< Fault detect sample clock frequency is 1/16 bus clock. */
kSLCD_FaultSampleFreqDivider32, /*!< Fault detect sample clock frequency is 1/32 bus clock. */
kSLCD_FaultSampleFreqDivider64, /*!< Fault detect sample clock frequency is 1/64 bus clock. */
kSLCD_FaultSampleFreqDivider128 /*!< Fault detect sample clock frequency is 1/128 bus clock. */
} slcd_fault_detect_clock_prescaler_t;
/*! @brief SLCD fault detect sample window width. */
typedef enum _slcd_fault_detect_sample_window_width
{
kSLCD_FaultDetectWindowWidth4SampleClk = 0U, /*!< Sample window width is 4 sample clock cycles. */
kSLCD_FaultDetectWindowWidth8SampleClk, /*!< Sample window width is 8 sample clock cycles. */
kSLCD_FaultDetectWindowWidth16SampleClk, /*!< Sample window width is 16 sample clock cycles. */
kSLCD_FaultDetectWindowWidth32SampleClk, /*!< Sample window width is 32 sample clock cycles. */
kSLCD_FaultDetectWindowWidth64SampleClk, /*!< Sample window width is 64 sample clock cycles. */
kSLCD_FaultDetectWindowWidth128SampleClk, /*!< Sample window width is 128 sample clock cycles. */
kSLCD_FaultDetectWindowWidth256SampleClk, /*!< Sample window width is 256 sample clock cycles. */
kSLCD_FaultDetectWindowWidth512SampleClk /*!< Sample window width is 512 sample clock cycles. */
} slcd_fault_detect_sample_window_width_t;
/*! @brief SLCD interrupt source. */
typedef enum _slcd_interrupt_enable
{
kSLCD_FaultDetectCompleteInterrupt = 1U, /*!< SLCD fault detection complete interrupt source. */
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
kSLCD_FrameFreqInterrupt = 2U /*!< SLCD frame frequency interrupt source. Not available in all low-power modes. */
#endif /* FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT */
} slcd_interrupt_enable_t;
/*! @brief SLCD behavior in low power mode. */
typedef enum _slcd_lowpower_behavior
{
kSLCD_EnabledInWaitStop = 0, /*!< SLCD works in wait and stop mode. */
kSLCD_EnabledInWaitOnly, /*!< SLCD works in wait mode and is disabled in stop mode. */
kSLCD_EnabledInStopOnly, /*!< SLCD works in stop mode and is disabled in wait mode. */
kSLCD_DisabledInWaitStop /*!< SLCD is disabled in stop mode and wait mode. */
} slcd_lowpower_behavior;
/*! @brief SLCD fault frame detection configure structure. */
typedef struct _slcd_fault_detect_config
{
bool faultDetectIntEnable; /*!< Fault frame detection interrupt enable flag.*/
bool faultDetectBackPlaneEnable; /*!< True means the pin id fault detected is back plane otherwise front plane. */
uint8_t faultDetectPinIndex; /*!< Fault detected pin id from 0 to 63. */
slcd_fault_detect_clock_prescaler_t faultPrescaler; /*!< Fault detect clock prescaler. */
slcd_fault_detect_sample_window_width_t width; /*!< Fault detect sample window width. */
} slcd_fault_detect_config_t;
/*! @brief SLCD clock configure structure. */
typedef struct _slcd_clock_config
{
slcd_clock_src_t clkSource; /*!< Clock source. "slcd_clock_src_t" is recommended to be used.
The SLCD is optimized to operate using a 32.768kHz clock input. */
slcd_alt_clock_div_t
altClkDivider; /*!< The divider to divide the alternate clock used for alternate clock source. */
slcd_clock_prescaler_t clkPrescaler; /*!< Clock prescaler. */
#if FSL_FEATURE_SLCD_HAS_FAST_FRAME_RATE
bool fastFrameRateEnable; /*!< Fast frame rate enable flag. */
#endif /* FSL_FEATURE_SLCD_HAS_FAST_FRAME_RATE */
} slcd_clock_config_t;
/*! @brief SLCD configure structure. */
typedef struct _slcd_config
{
slcd_power_supply_option_t powerSupply; /*!< Power supply option. */
slcd_regulated_voltage_trim_t voltageTrim; /*!< Regulated voltage trim used for the internal regulator VIREG to
adjust to facilitate contrast control. */
slcd_clock_config_t *clkConfig; /*!< Clock configure. */
slcd_display_mode_t displayMode; /*!< SLCD display mode. */
slcd_load_adjust_t loadAdjust; /*!< Load adjust to handle glass capacitance. */
slcd_duty_cycle_t dutyCycle; /*!< Duty cycle. */
slcd_lowpower_behavior lowPowerBehavior; /*!< SLCD behavior in low power mode. */
#if FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT
bool frameFreqIntEnable; /*!< Frame frequency interrupt enable flag.*/
#endif /* FSL_FEATURE_SLCD_HAS_FAST_FRAME_RATE */
uint32_t slcdLowPinEnabled; /*!< Setting enabled SLCD pin 0 ~ pin 31. Setting bit n to 1 means enable pin n. */
uint32_t
slcdHighPinEnabled; /*!< Setting enabled SLCD pin 32 ~ pin 63. Setting bit n to 1 means enable pin (n + 32). */
uint32_t backPlaneLowPin; /*!< Setting back plane pin 0 ~ pin 31. Setting bit n to 1 means setting pin n as back
plane. It should never have the same bit setting as the frontPlane Pin. */
uint32_t backPlaneHighPin; /*!< Setting back plane pin 32 ~ pin 63. Setting bit n to 1 means setting pin (n + 32) as
back plane. It should never have the same bit setting as the frontPlane Pin. */
slcd_fault_detect_config_t *faultConfig; /*!< Fault frame detection configure. If not requirement, set to NULL. */
} slcd_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes the SLCD, ungates the module clock, initializes the power
* setting, enables all used plane pins, and sets with interrupt and work mode
* with configuration.
*
* @param base SLCD peripheral base address.
* @param configure SLCD configuration pointer.
* For the configuration structure, many parameters have the default setting
* and the SLCD_Getdefaultconfig() is provided to get them. Use it
* verified for their applications.
* The others have no default settings such as "clkConfig" and must be provided
* by the application before calling the SLCD_Init() API.
*/
void SLCD_Init(LCD_Type *base, slcd_config_t *configure);
/*!
* @brief Deinitializes the SLCD module, gates the module clock, disables an interrupt,
* and displays the SLCD.
*
* @param base SLCD peripheral base address.
*/
void SLCD_Deinit(LCD_Type *base);
/*!
* @brief Gets the SLCD default configuration structure. The
* purpose of this API is to get default parameters of the configuration structure
* for the SLCD_Init(). Use these initialized parameters unchanged in SLCD_Init(),
* or modify some fields of the structure before the calling SLCD_Init().
* All default parameters of the configure structure are listed:
* @code
config.displayMode = kSLCD_NormalMode; // SLCD normal mode
config.powerSupply = kSLCD_InternalVll3UseChargePump; // Use charge pump internal VLL3
config.voltageTrim = kSLCD_RegulatedVolatgeTrim00;
config.lowPowerBehavior = kSLCD_EnabledInWaitStop; // Work on low power mode
config.interruptSrc = 0; // No interrupt source is enabled
config.faultConfig = NULL; // Fault detection is disabled
config.frameFreqIntEnable = false;
@endcode
* @param configure The SLCD configuration structure pointer.
*/
void SLCD_GetDefaultConfig(slcd_config_t *configure);
/* @}*/
/*!
* @name Plane Setting and Display Control
* @{
*/
/*!
* @brief Enables the SLCD controller, starts generate, and displays the front plane and back plane waveform.
*
* @param base SLCD peripheral base address.
*/
static inline void SLCD_StartDisplay(LCD_Type *base)
{
base->GCR |= LCD_GCR_LCDEN_MASK;
}
/*!
* @brief Stops the SLCD controller. There is no waveform generator and all enabled pins
* only output a low value.
*
* @param base SLCD peripheral base address.
*/
static inline void SLCD_StopDisplay(LCD_Type *base)
{
base->GCR &= ~LCD_GCR_LCDEN_MASK;
}
/*!
* @brief Starts the SLCD blink mode.
*
* @param base SLCD peripheral base address.
* @param mode SLCD blink mode.
* @param rate SLCD blink rate.
*/
void SLCD_StartBlinkMode(LCD_Type *base, slcd_blink_mode_t mode, slcd_blink_rate_t rate);
/*!
* @brief Stops the SLCD blink mode.
*
* @param base SLCD peripheral base address.
*/
static inline void SLCD_StopBlinkMode(LCD_Type *base)
{
base->AR &= ~LCD_AR_BLINK_MASK;
}
/*!
* @brief Sets the SLCD back plane pin phase.
*
* This function sets the SLCD back plane pin phase. "kSLCD_PhaseXActivate" setting
* means the phase X is active for the back plane pin. "kSLCD_NoPhaseActivate" setting
* means there is no phase active for the back plane pin.
* register value.
* For example, set the back plane pin 20 for phase A:
* @code
* SLCD_SetBackPlanePhase(LCD, 20, kSLCD_PhaseAActivate);
* @endcode
*
* @param base SLCD peripheral base address.
* @param pinIndx SLCD back plane pin index. Range from 0 to 63.
* @param phase The phase activates for the back plane pin.
*/
static inline void SLCD_SetBackPlanePhase(LCD_Type *base, uint32_t pinIndx, slcd_phase_type_t phase)
{
base->WF8B[pinIndx] = phase;
}
/*!
* @brief Sets the SLCD front plane segment operation for a front plane pin.
*
* This function sets the SLCD front plane segment on or off operation.
* Each bit turns on or off the segments associated with the front plane pin in
* the following pattern: HGFEDCBA (most significant bit controls segment H and
* least significant bit controls segment A).
* For example, turn on the front plane pin 20 for phase B and phase C:
* @code
* SLCD_SetFrontPlaneSegments(LCD, 20, (kSLCD_PhaseBActivate | kSLCD_PhaseCActivate));
* @endcode
*
* @param base SLCD peripheral base address.
* @param pinIndx SLCD back plane pin index. Range from 0 to 63.
* @param operation The operation for the segment on the front plane pin.
* This is a logical OR of the enumeration :: slcd_phase_type_t.
*/
static inline void SLCD_SetFrontPlaneSegments(LCD_Type *base, uint32_t pinIndx, uint8_t operation)
{
base->WF8B[pinIndx] = operation;
}
/*!
* @brief Sets one SLCD front plane pin for one phase.
*
* This function can be used to set one phase on or off for the front plane pin.
* It can be call many times to set the plane pin for different phase indexes.
* For example, turn on the front plane pin 20 for phase B and phase C:
* @code
* SLCD_SetFrontPlaneOnePhase(LCD, 20, kSLCD_PhaseBIndex, true);
* SLCD_SetFrontPlaneOnePhase(LCD, 20, kSLCD_PhaseCIndex, true);
* @endcode
*
* @param base SLCD peripheral base address.
* @param pinIndx SLCD back plane pin index. Range from 0 to 63.
* @param phaseIndx The phase bit index @ref slcd_phase_index_t.
* @param enable True to turn on the segment for phaseIndx phase
* false to turn off the segment for phaseIndx phase.
*/
static inline void SLCD_SetFrontPlaneOnePhase(LCD_Type *base,
uint32_t pinIndx,
slcd_phase_index_t phaseIndx,
bool enable)
{
uint8_t reg = base->WF8B[pinIndx];
if (enable)
{
base->WF8B[pinIndx] = (reg | (1U << phaseIndx));
}
else
{
base->WF8B[pinIndx] = (reg & ~(1U << phaseIndx));
}
}
#if FSL_FEATURE_SLCD_HAS_PAD_SAFE
/*!
* @brief Enables/disables the SLCD pad safe state.
*
* Forces the safe state on the LCD pad controls. All LCD front plane
* and backplane functions are disabled.
*
* @param base SLCD peripheral base address.
* @param enable True enable, false disable.
*/
static inline void SLCD_EnablePadSafeState(LCD_Type *base, bool enable)
{
if (enable)
{ /* Enable. */
base->GCR |= LCD_GCR_PADSAFE_MASK;
}
else
{ /* Disable. */
base->GCR &= ~LCD_GCR_PADSAFE_MASK;
}
}
#endif /* FSL_FEATURE_SLCD_HAS_PAD_SAFE */
/*!
* @brief Gets the SLCD fault detect counter.
*
* This function gets the number of samples inside the
* fault detection sample window.
*
* @param base SLCD peripheral base address.
* @return The fault detect counter. The maximum return value is 255.
* If the maximum 255 returns, the overflow may happen.
* Reconfigure the fault detect sample window and fault detect clock prescaler
* for proper sampling.
*/
static inline uint32_t SLCD_GetFaultDetectCounter(LCD_Type *base)
{
return base->FDSR & LCD_FDSR_FDCNT_MASK;
}
/* @} */
/*!
* @name Interrupts.
* @{
*/
/*!
* @brief Enables the SLCD interrupt.
* For example, to enable fault detect complete interrupt and frame frequency interrupt,
* for FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT enabled case, do the following.
* @code
* SLCD_EnableInterrupts(LCD,kSLCD_FaultDetectCompleteInterrupt | kSLCD_FrameFreqInterrupt);
* @endcode
*
* @param base SLCD peripheral base address.
* @param mask SLCD interrupts to enable. This is a logical OR of the
* enumeration :: slcd_interrupt_enable_t.
*/
void SLCD_EnableInterrupts(LCD_Type *base, uint32_t mask);
/*!
* @brief Disables the SLCD interrupt.
* For example, to disable fault detect complete interrupt and frame frequency interrupt,
* for FSL_FEATURE_SLCD_HAS_FRAME_FREQUENCY_INTERRUPT enabled case, do the following.
* @code
* SLCD_DisableInterrupts(LCD,kSLCD_FaultDetectCompleteInterrupt | kSLCD_FrameFreqInterrupt);
* @endcode
*
* @param base SLCD peripheral base address.
* @param mask SLCD interrupts to disable. This is a logical OR of the
* enumeration :: slcd_interrupt_enable_t.
*/
void SLCD_DisableInterrupts(LCD_Type *base, uint32_t mask);
/*!
* @brief Gets the SLCD interrupt status flag.
*
* @param base SLCD peripheral base address.
* @return The event status of the interrupt source. This is the logical OR of members
* of the enumeration :: slcd_interrupt_enable_t.
*/
uint32_t SLCD_GetInterruptStatus(LCD_Type *base);
/*!
* @brief Clears the SLCD interrupt events status flag.
*
* @param base SLCD peripheral base address.
* @param mask SLCD interrupt source to be cleared.
* This is the logical OR of members of the enumeration :: slcd_interrupt_enable_t.
*/
void SLCD_ClearInterruptStatus(LCD_Type *base, uint32_t mask);
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_SLCD_H_*/

Some files were not shown because too many files have changed in this diff Show More