mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #4290 from NXPmicro/Add_LPC54114_Support
Add mbed support for LPCXpresso54114 & LPCXpresso54608 boardspull/4803/head
commit
93ae6f99aa
|
@ -0,0 +1,107 @@
|
|||
/* 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"
|
||||
#include "PortNames.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
OSC32KCLK = 0,
|
||||
} RTCName;
|
||||
|
||||
typedef enum {
|
||||
UART_0 = Flexcomm0,
|
||||
UART_1 = Flexcomm2
|
||||
} UARTName;
|
||||
|
||||
#define STDIO_UART_TX USBTX
|
||||
#define STDIO_UART_RX USBRX
|
||||
#define STDIO_UART UART_0
|
||||
|
||||
typedef enum {
|
||||
I2C_0 = Flexcomm1,
|
||||
I2C_1 = Flexcomm4
|
||||
} I2CName;
|
||||
|
||||
#define TPM_SHIFT 8
|
||||
typedef enum {
|
||||
PWM_1 = (0 << TPM_SHIFT) | (0), // FTM0 CH0
|
||||
PWM_2 = (0 << TPM_SHIFT) | (1), // FTM0 CH1
|
||||
PWM_3 = (0 << TPM_SHIFT) | (2), // FTM0 CH2
|
||||
PWM_4 = (0 << TPM_SHIFT) | (3), // FTM0 CH3
|
||||
PWM_5 = (0 << TPM_SHIFT) | (4), // FTM0 CH4
|
||||
PWM_6 = (0 << TPM_SHIFT) | (5), // FTM0 CH5
|
||||
PWM_7 = (0 << TPM_SHIFT) | (6), // FTM0 CH6
|
||||
PWM_8 = (0 << TPM_SHIFT) | (7), // FTM0 CH7
|
||||
PWM_9 = (1 << TPM_SHIFT) | (0), // FTM1 CH0
|
||||
PWM_10 = (1 << TPM_SHIFT) | (1), // FTM1 CH1
|
||||
PWM_11 = (1 << TPM_SHIFT) | (2), // FTM1 CH2
|
||||
PWM_12 = (1 << TPM_SHIFT) | (3), // FTM1 CH3
|
||||
PWM_13 = (1 << TPM_SHIFT) | (4), // FTM1 CH4
|
||||
PWM_14 = (1 << TPM_SHIFT) | (5), // FTM1 CH5
|
||||
PWM_15 = (1 << TPM_SHIFT) | (6), // FTM1 CH6
|
||||
PWM_16 = (1 << TPM_SHIFT) | (7), // FTM1 CH7
|
||||
PWM_17 = (2 << TPM_SHIFT) | (0), // FTM2 CH0
|
||||
PWM_18 = (2 << TPM_SHIFT) | (1), // FTM2 CH1
|
||||
PWM_19 = (2 << TPM_SHIFT) | (2), // FTM2 CH2
|
||||
PWM_20 = (2 << TPM_SHIFT) | (3), // FTM2 CH3
|
||||
PWM_21 = (2 << TPM_SHIFT) | (4), // FTM2 CH4
|
||||
PWM_22 = (2 << TPM_SHIFT) | (5), // FTM2 CH5
|
||||
PWM_23 = (2 << TPM_SHIFT) | (6), // FTM2 CH6
|
||||
PWM_24 = (2 << TPM_SHIFT) | (7), // FTM2 CH7
|
||||
PWM_25 = (3 << TPM_SHIFT) | (0), // FTM3 CH0
|
||||
PWM_26 = (3 << TPM_SHIFT) | (1), // FTM3 CH1
|
||||
PWM_27 = (3 << TPM_SHIFT) | (2), // FTM3 CH2
|
||||
PWM_28 = (3 << TPM_SHIFT) | (3), // FTM3 CH3
|
||||
PWM_29 = (3 << TPM_SHIFT) | (4), // FTM3 CH4
|
||||
PWM_30 = (3 << TPM_SHIFT) | (5), // FTM3 CH5
|
||||
PWM_31 = (3 << TPM_SHIFT) | (6), // FTM3 CH6
|
||||
PWM_32 = (3 << TPM_SHIFT) | (7), // FTM3 CH7
|
||||
} PWMName;
|
||||
|
||||
#define ADC_INSTANCE_SHIFT 8
|
||||
#define ADC_B_CHANNEL_SHIFT 5
|
||||
typedef enum {
|
||||
ADC0_SE0 = 0,
|
||||
ADC0_SE1 = 1,
|
||||
ADC0_SE2 = 2,
|
||||
ADC0_SE3 = 3,
|
||||
ADC0_SE4 = 4,
|
||||
ADC0_SE5 = 5,
|
||||
ADC0_SE6 = 6,
|
||||
ADC0_SE7 = 7,
|
||||
ADC0_SE8 = 8,
|
||||
ADC0_SE9 = 9,
|
||||
ADC0_SE10 = 10,
|
||||
ADC0_SE11 = 11,
|
||||
} ADCName;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SPI_0 = Flexcomm3,
|
||||
SPI_1 = Flexcomm5
|
||||
} SPIName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#include "PeripheralPins.h"
|
||||
|
||||
/************RTC***************/
|
||||
const PinMap PinMap_RTC[] = {
|
||||
{NC, OSC32KCLK, 0},
|
||||
};
|
||||
|
||||
/************ADC***************/
|
||||
const PinMap PinMap_ADC[] = {
|
||||
{P0_30, ADC0_SE1, 0},
|
||||
{P1_4, ADC0_SE7, 0},
|
||||
{P1_5, ADC0_SE8, 0},
|
||||
{P1_8, ADC0_SE11, 0},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************DAC***************/
|
||||
const PinMap PinMap_DAC[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************I2C***************/
|
||||
const PinMap PinMap_I2C_SDA[] = {
|
||||
{P0_24, I2C_0, 1},
|
||||
{P0_26, I2C_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_I2C_SCL[] = {
|
||||
{P0_23, I2C_0, 1},
|
||||
{P0_25, I2C_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************UART***************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
{P0_1, UART_0, 1},
|
||||
{P0_9, UART_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
{P0_0, UART_0, 1},
|
||||
{P0_8, UART_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_CTS[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RTS[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************SPI***************/
|
||||
const PinMap PinMap_SPI_SCLK[] = {
|
||||
{P0_11, SPI_0, 1},
|
||||
{P0_19, SPI_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
{P0_12, SPI_0, 1},
|
||||
{P0_20, SPI_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
{P0_13, SPI_0, 1},
|
||||
{P0_18, SPI_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_SSEL[] = {
|
||||
{P0_14, SPI_0, 1},
|
||||
{P1_1, SPI_1, 4},
|
||||
{P1_2, SPI_1, 4},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************PWM***************/
|
||||
const PinMap PinMap_PWM[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
|
@ -0,0 +1,146 @@
|
|||
/* 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 5
|
||||
|
||||
typedef enum {
|
||||
P0_0 = 0,
|
||||
P0_1 = 1,
|
||||
P0_2 = 2,
|
||||
P0_3 = 3,
|
||||
P0_4 = 4,
|
||||
P0_5 = 5,
|
||||
P0_6 = 6,
|
||||
P0_7 = 7,
|
||||
P0_8 = 8,
|
||||
P0_9 = 9,
|
||||
P0_10 = 10,
|
||||
P0_11 = 11,
|
||||
P0_12 = 12,
|
||||
P0_13 = 13,
|
||||
P0_14 = 14,
|
||||
P0_15 = 15,
|
||||
P0_16 = 16,
|
||||
P0_17 = 17,
|
||||
P0_18 = 18,
|
||||
P0_19 = 19,
|
||||
P0_20 = 20,
|
||||
P0_21 = 21,
|
||||
P0_22 = 22,
|
||||
P0_23 = 23,
|
||||
P0_24 = 24,
|
||||
P0_25 = 25,
|
||||
P0_26 = 26,
|
||||
P0_29 = 29,
|
||||
P0_30 = 30,
|
||||
P0_31 = 31,
|
||||
|
||||
P1_0 = 32,
|
||||
P1_1 = 33,
|
||||
P1_2 = 34,
|
||||
P1_3 = 35,
|
||||
P1_4 = 36,
|
||||
P1_5 = 37,
|
||||
P1_6 = 38,
|
||||
P1_7 = 39,
|
||||
P1_8 = 40,
|
||||
P1_9 = 41,
|
||||
P1_10 = 42,
|
||||
P1_11 = 43,
|
||||
P1_12 = 44,
|
||||
P1_13 = 45,
|
||||
P1_14 = 46,
|
||||
P1_15 = 47,
|
||||
P1_16 = 48,
|
||||
P1_17 = 49,
|
||||
|
||||
LED_RED = P0_29,
|
||||
LED_GREEN = P1_10,
|
||||
LED_BLUE = P1_9,
|
||||
|
||||
// mbed original LED naming
|
||||
LED1 = LED_RED,
|
||||
LED2 = LED_GREEN,
|
||||
LED3 = LED_BLUE,
|
||||
LED4 = LED_RED,
|
||||
|
||||
//Push buttons
|
||||
SW1 = P0_24,
|
||||
SW2 = P0_31,
|
||||
SW3 = P0_4,
|
||||
|
||||
// USB Pins
|
||||
USBTX = P0_1,
|
||||
USBRX = P0_0,
|
||||
|
||||
// Arduino Headers
|
||||
D0 = P0_8,
|
||||
D1 = P0_9,
|
||||
D2 = P0_10,
|
||||
D3 = P1_12,
|
||||
D4 = P1_13,
|
||||
D5 = P0_29,
|
||||
D6 = P1_0,
|
||||
D7 = P1_14,
|
||||
D8 = P1_16,
|
||||
D9 = P1_15,
|
||||
D10 = P1_1,
|
||||
D11 = P0_20,
|
||||
D12 = P0_18,
|
||||
D13 = P0_19,
|
||||
D14 = P0_26,
|
||||
D15 = P0_25,
|
||||
|
||||
I2C_SCL = D15,
|
||||
I2C_SDA = D14,
|
||||
|
||||
// Not connected
|
||||
NC = (int)0xFFFFFFFF,
|
||||
|
||||
A0 = P0_30,
|
||||
A1 = NC,
|
||||
A2 = P1_8,
|
||||
A3 = P1_10,
|
||||
A4 = P1_4,
|
||||
A5 = P1_5
|
||||
} PinName;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PullNone = 0,
|
||||
PullDown = 1,
|
||||
PullUp = 2,
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* 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 the copyright holder 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* How to set up clock using clock driver functions:
|
||||
*
|
||||
* 1. Setup clock sources.
|
||||
*
|
||||
* 2. Setup voltage for the fastest of the clock outputs
|
||||
*
|
||||
* 3. Set up wait states of the flash.
|
||||
*
|
||||
* 4. Set up all dividers.
|
||||
*
|
||||
* 5. Set up all selectors to provide selected clocks.
|
||||
*/
|
||||
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!ClocksProfile
|
||||
product: Clocks v1.0
|
||||
processor: LPC54114J256
|
||||
package_id: LPC54114J256BD64
|
||||
mcu_data: ksdk2_0
|
||||
processor_version: 1.1.0
|
||||
board: LPCXpresso54114
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
#include "fsl_power.h"
|
||||
#include "fsl_clock.h"
|
||||
#include "clock_config.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/* System clock frequency. */
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFRO12M ***********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockFRO12M
|
||||
outputs:
|
||||
- {id: System_clock.outFreq, value: 12 MHz}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockFRO12M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
CLOCK_SetupFROClocking(12000000U); /*!< Set up FRO to the 12 MHz, just for sure */
|
||||
POWER_SetVoltageForFreq(12000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(12000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
/*!< Set up dividers */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /*!< Set AHBCLKDIV divider to value 1 */
|
||||
|
||||
/*!< Set up clock selectors - Attach clocks to the peripheries */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO12M */
|
||||
/*!< Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BOOTCLOCKFRO12M_CORE_CLOCK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************** Configuration BOARD_BootClockFROHF48M ***********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockFROHF48M
|
||||
outputs:
|
||||
- {id: System_clock.outFreq, value: 48 MHz}
|
||||
settings:
|
||||
- {id: SYSCON.MAINCLKSELA.sel, value: SYSCON.fro_hf}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockFROHF48M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
POWER_SetVoltageForFreq(48000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(48000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
CLOCK_SetupFROClocking(48000000U); /*!< Set up high frequency FRO output to selected frequency */
|
||||
|
||||
/*!< Set up dividers */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /*!< Set AHBCLKDIV divider to value 1 */
|
||||
|
||||
/*!< Set up clock selectors - Attach clocks to the peripheries */
|
||||
CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */
|
||||
/*!< Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFROHF96M **********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockFROHF96M
|
||||
outputs:
|
||||
- {id: System_clock.outFreq, value: 96 MHz}
|
||||
settings:
|
||||
- {id: SYSCON.MAINCLKSELA.sel, value: SYSCON.fro_hf}
|
||||
sources:
|
||||
- {id: SYSCON.fro_hf.outFreq, value: 96 MHz}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockFROHF96M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
POWER_SetVoltageForFreq(96000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(96000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
CLOCK_SetupFROClocking(96000000U); /*!< Set up high frequency FRO output to selected frequency */
|
||||
|
||||
/*!< Set up dividers */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /*!< Set AHBCLKDIV divider to value 1 */
|
||||
|
||||
/*!< Set up clock selectors - Attach clocks to the peripheries */
|
||||
CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */
|
||||
/*!< Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BOOTCLOCKFROHF96M_CORE_CLOCK;
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* 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 the copyright holder 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_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
#define BOARD_XTAL0_CLK_HZ 12000000U /*!< Board xtal0 frequency in Hz */
|
||||
#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32K frequency in Hz */
|
||||
#define BOARD_BootClockRUN BOARD_BootClockFROHF48M
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFRO12M ***********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency: 12000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockFRO12M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*******************************************************************************
|
||||
********************** Configuration BOARD_BootClockFROHF48M ***********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockFROHF48M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFROHF96M **********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BOOTCLOCKFROHF96M_CORE_CLOCK 96000000U /*!< Core clock frequency: 96000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockFROHF96M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
#endif /* _CLOCK_CONFIG_H_ */
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// The 'features' section in 'target.json' is now used to create the device's hardware preprocessor switches.
|
||||
// Check the 'features' section of the target description in 'targets.json' for more details.
|
||||
/* 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_DEVICE_H
|
||||
#define MBED_DEVICE_H
|
||||
|
||||
#if defined(TARGET_LPC54114_M4)
|
||||
#define NUMBER_OF_GPIO_INTS 8
|
||||
#elif defined(TARGET_LPC54114_M0)
|
||||
#define NUMBER_OF_GPIO_INTS 4
|
||||
#endif
|
||||
|
||||
#define APP_EXCLUDE_FROM_DEEPSLEEP \
|
||||
(SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK | SYSCON_PDRUNCFG_PDEN_SRAMX_MASK | \
|
||||
SYSCON_PDRUNCFG_PDEN_SRAM0_MASK | SYSCON_PDRUNCFG_PDEN_SRAM1_MASK | SYSCON_PDRUNCFG_PDEN_SRAM2_MASK)
|
||||
|
||||
/* Defines used by the sleep code */
|
||||
#define LPC_CLOCK_INTERNAL_IRC BOARD_BootClockFRO12M
|
||||
#define LPC_CLOCK_RUN BOARD_BootClockFROHF48M
|
||||
|
||||
#define DEVICE_ID_LENGTH 24
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "objects.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
/* 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 "gpio_api.h"
|
||||
#include "clock_config.h"
|
||||
#include "fsl_power.h"
|
||||
|
||||
// called before main
|
||||
void mbed_sdk_init()
|
||||
{
|
||||
BOARD_BootClockFROHF48M();
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
//gpio_t gpio;
|
||||
//gpio_init_in(&gpio, PTA4);
|
||||
}
|
||||
|
||||
void ADC_ClockPower_Configuration(void)
|
||||
{
|
||||
/* SYSCON power. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_ADC0); /* Power on the ADC converter. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_VD7_ENA); /* Power on the analog power supply. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_VREFP_SW); /* Power on the reference voltage source. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_TEMPS); /* Power on the temperature sensor. */
|
||||
|
||||
/* Enable the clock. */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK);
|
||||
CLOCK_EnableClock(kCLOCK_Adc0);
|
||||
}
|
||||
|
||||
// Enable the RTC oscillator if available on the board
|
||||
void rtc_setup_oscillator(void)
|
||||
{
|
||||
/* Enable the RTC 32K Oscillator */
|
||||
SYSCON->RTCOSCCTRL |= SYSCON_RTCOSCCTRL_EN_MASK;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
** ###################################################################
|
||||
** Version: rev. 1.0, 2016-05-09
|
||||
** Build: b160802
|
||||
**
|
||||
** Abstract:
|
||||
** Chip specific module features.
|
||||
**
|
||||
** 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
|
||||
**
|
||||
** Revisions:
|
||||
** - rev. 1.0 (2016-05-09)
|
||||
** Initial version.
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
|
||||
#ifndef _LPC54114_cm4_FEATURES_H_
|
||||
#define _LPC54114_cm4_FEATURES_H_
|
||||
|
||||
/* SOC module features */
|
||||
|
||||
/* @brief ADC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_ADC_COUNT (1)
|
||||
/* @brief ASYNC_SYSCON availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT (1)
|
||||
/* @brief CRC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_CRC_COUNT (1)
|
||||
/* @brief DMA availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_DMA_COUNT (1)
|
||||
/* @brief DMIC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_DMIC_COUNT (1)
|
||||
/* @brief FLEXCOMM availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_FLEXCOMM_COUNT (8)
|
||||
/* @brief GINT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_GINT_COUNT (2)
|
||||
/* @brief GPIO availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_GPIO_COUNT (1)
|
||||
/* @brief I2C availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_I2C_COUNT (8)
|
||||
/* @brief I2S availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_I2S_COUNT (2)
|
||||
/* @brief INPUTMUX availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_INPUTMUX_COUNT (1)
|
||||
/* @brief IOCON availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_IOCON_COUNT (1)
|
||||
/* @brief MAILBOX availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_MAILBOX_COUNT (1)
|
||||
/* @brief MRT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_MRT_COUNT (1)
|
||||
/* @brief PINT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_PINT_COUNT (1)
|
||||
/* @brief RTC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_RTC_COUNT (1)
|
||||
/* @brief SCT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SCT_COUNT (1)
|
||||
/* @brief SPI availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SPI_COUNT (8)
|
||||
/* @brief SPIFI availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SPIFI_COUNT (1)
|
||||
/* @brief SYSCON availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SYSCON_COUNT (1)
|
||||
/* @brief CTIMER availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_CTIMER_COUNT (5)
|
||||
/* @brief USART availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USART_COUNT (8)
|
||||
/* @brief USB availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USB_COUNT (1)
|
||||
/* @brief UTICK availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_UTICK_COUNT (1)
|
||||
/* @brief WWDT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_WWDT_COUNT (1)
|
||||
|
||||
/* DMA module features */
|
||||
|
||||
/* @brief Number of channels */
|
||||
#define FSL_FEATURE_DMA_NUMBER_OF_CHANNELS (20)
|
||||
|
||||
/* PINT module features */
|
||||
|
||||
/* @brief Number of connected outputs */
|
||||
#define FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS (8)
|
||||
|
||||
/* SCT module features */
|
||||
|
||||
/* @brief Number of events */
|
||||
#define FSL_FEATURE_SCT_NUMBER_OF_EVENTS (10)
|
||||
/* @brief Number of states */
|
||||
#define FSL_FEATURE_SCT_NUMBER_OF_STATES (10)
|
||||
/* @brief Number of match capture */
|
||||
#define FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE (10)
|
||||
|
||||
/* SYSCON module features */
|
||||
|
||||
/* @brief Pointer to ROM IAP entry functions */
|
||||
#define FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION (0x03000205)
|
||||
/* @brief Flash page size in bytes */
|
||||
#define FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES (256)
|
||||
/* @brief Flash sector size in bytes */
|
||||
#define FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES (32768)
|
||||
/* @brief Flash size in bytes */
|
||||
#define FSL_FEATURE_SYSCON_FLASH_SIZE_BYTES (262144)
|
||||
|
||||
#endif /* _LPC54114_cm4_FEATURES_H_ */
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
#! armcc -E
|
||||
/*
|
||||
** ###################################################################
|
||||
** Processors: LPC54114J256BD64_cm4
|
||||
** LPC54114J256UK49_cm4
|
||||
**
|
||||
** Compiler: Keil ARM C/C++ Compiler
|
||||
** Reference manual: LPC5411x User manual Rev. 1.0 16 February 2016
|
||||
** Version: rev. 1.0, 2016-04-29
|
||||
** Build: b160526
|
||||
**
|
||||
** Abstract:
|
||||
** Linker file for the Keil ARM C/C++ Compiler
|
||||
**
|
||||
** Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
** Copyright (c) 2016 NXP
|
||||
** 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 copyright holder 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.nxp.com
|
||||
** mail: support@nxp.com
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
#define __ram_vector_table__ 1
|
||||
|
||||
#if (defined(__ram_vector_table__))
|
||||
#define __ram_vector_table_size__ 0x000000E0
|
||||
#else
|
||||
#define __ram_vector_table_size__ 0x00000000
|
||||
#endif
|
||||
|
||||
#define m_interrupts_start 0x00000000
|
||||
#define m_interrupts_size 0x000000E0
|
||||
|
||||
#define m_text_start 0x000000E0
|
||||
#define m_text_size 0x0002FF20
|
||||
|
||||
#define m_core1_image_start 0x00030000
|
||||
#define m_core1_image_size 0x00010000
|
||||
|
||||
#define m_interrupts_ram_start 0x20000000
|
||||
#define m_interrupts_ram_size __ram_vector_table_size__
|
||||
|
||||
#define m_rpmsg_sh_mem_start 0x20026800
|
||||
#define m_rpmsg_sh_mem_size 0x00001800
|
||||
|
||||
#define m_data_start (m_interrupts_ram_start + m_interrupts_ram_size)
|
||||
#define m_data_size (0x00010000 - m_interrupts_ram_size)
|
||||
|
||||
#define m_sramx_start 0x04000000
|
||||
#define m_sramx_size 0x00008000
|
||||
|
||||
/* 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_text m_text_start m_text_size { ; load address = execution address
|
||||
* (InRoot$$Sections)
|
||||
.ANY (+RO)
|
||||
}
|
||||
ER_m_sramx m_sramx_start m_sramx_size { ; SRAMX memory
|
||||
* (sramx)
|
||||
}
|
||||
|
||||
#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 { ; RW data
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
RW_IRAM1 ((ImageLimit(RW_m_data) == m_data_start) ? ImageLimit(RW_m_data) : +0) EMPTY Heap_Size { ; Heap region growing up
|
||||
}
|
||||
ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down
|
||||
}
|
||||
|
||||
RPMSG_SH_MEM m_rpmsg_sh_mem_start UNINIT m_rpmsg_sh_mem_size { ; Shared memory used by RPMSG
|
||||
* (rpmsg_sh_mem_section)
|
||||
}
|
||||
}
|
||||
|
||||
LR_CORE1_IMAGE m_core1_image_start {
|
||||
CORE1_REGION m_core1_image_start m_core1_image_size {
|
||||
*(M0CODE)
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
|
@ -0,0 +1,625 @@
|
|||
;/*****************************************************************************
|
||||
; * @file: startup_LPC54114_cm4.s
|
||||
; * @purpose: CMSIS Cortex-M4 Core Device Startup File for the
|
||||
; * LPC54114_cm4
|
||||
; * @version: 1.0
|
||||
; * @date: 2016-4-29
|
||||
; *
|
||||
; * Copyright: 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.
|
||||
; *
|
||||
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
|
||||
; *
|
||||
; *****************************************************************************/
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; Vector Table Mapped to Address 0 at Reset
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
IMPORT |Image$$ARM_LIB_STACK$$ZI$$Limit|
|
||||
|
||||
__Vectors DCD |Image$$ARM_LIB_STACK$$ZI$$Limit| ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
|
||||
DCD NMI_Handler
|
||||
DCD HardFault_Handler
|
||||
DCD MemManage_Handler
|
||||
DCD BusFault_Handler
|
||||
DCD UsageFault_Handler
|
||||
__vector_table_0x1c
|
||||
DCD 0 ; Checksum of the first 7 words
|
||||
DCD 0
|
||||
DCD 0 ; Enhanced image marker, set to 0x0 for legacy boot
|
||||
DCD 0 ; Pointer to enhanced boot block, set to 0x0 for legacy boot
|
||||
DCD SVC_Handler
|
||||
DCD DebugMon_Handler
|
||||
DCD 0
|
||||
DCD PendSV_Handler
|
||||
DCD SysTick_Handler
|
||||
|
||||
; External Interrupts
|
||||
DCD WDT_BOD_IRQHandler ; Windowed watchdog timer, Brownout detect
|
||||
DCD DMA0_IRQHandler ; DMA controller
|
||||
DCD GINT0_IRQHandler ; GPIO group 0
|
||||
DCD GINT1_IRQHandler ; GPIO group 1
|
||||
DCD PIN_INT0_IRQHandler ; Pin interrupt 0 or pattern match engine slice 0
|
||||
DCD PIN_INT1_IRQHandler ; Pin interrupt 1or pattern match engine slice 1
|
||||
DCD PIN_INT2_IRQHandler ; Pin interrupt 2 or pattern match engine slice 2
|
||||
DCD PIN_INT3_IRQHandler ; Pin interrupt 3 or pattern match engine slice 3
|
||||
DCD UTICK0_IRQHandler ; Micro-tick Timer
|
||||
DCD MRT0_IRQHandler ; Multi-rate timer
|
||||
DCD CTIMER0_IRQHandler ; Standard counter/timer CTIMER0
|
||||
DCD CTIMER1_IRQHandler ; Standard counter/timer CTIMER1
|
||||
DCD SCT0_IRQHandler ; SCTimer/PWM
|
||||
DCD CTIMER3_IRQHandler ; Standard counter/timer CTIMER3
|
||||
DCD FLEXCOMM0_IRQHandler ; Flexcomm Interface 0 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM1_IRQHandler ; Flexcomm Interface 1 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM2_IRQHandler ; Flexcomm Interface 2 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM3_IRQHandler ; Flexcomm Interface 3 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM4_IRQHandler ; Flexcomm Interface 4 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM5_IRQHandler ; Flexcomm Interface 5 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM6_IRQHandler ; Flexcomm Interface 6 (USART, SPI, I2C, I2S)
|
||||
DCD FLEXCOMM7_IRQHandler ; Flexcomm Interface 7 (USART, SPI, I2C, I2S)
|
||||
DCD ADC0_SEQA_IRQHandler ; ADC0 sequence A completion.
|
||||
DCD ADC0_SEQB_IRQHandler ; ADC0 sequence B completion.
|
||||
DCD ADC0_THCMP_IRQHandler ; ADC0 threshold compare and error.
|
||||
DCD DMIC0_IRQHandler ; Digital microphone and DMIC subsystem
|
||||
DCD HWVAD0_IRQHandler ; Hardware Voice Activity Detector
|
||||
DCD USB0_NEEDCLK_IRQHandler ; USB Activity Wake-up Interrupt
|
||||
DCD USB0_IRQHandler ; USB device
|
||||
DCD RTC_IRQHandler ; RTC alarm and wake-up interrupts
|
||||
DCD IOH_IRQHandler ; IOH
|
||||
DCD MAILBOX_IRQHandler ; Mailbox interrupt (present on selected devices)
|
||||
DCD PIN_INT4_IRQHandler ; Pin interrupt 4 or pattern match engine slice 4 int
|
||||
DCD PIN_INT5_IRQHandler ; Pin interrupt 5 or pattern match engine slice 5 int
|
||||
DCD PIN_INT6_IRQHandler ; Pin interrupt 6 or pattern match engine slice 6 int
|
||||
DCD PIN_INT7_IRQHandler ; Pin interrupt 7 or pattern match engine slice 7 int
|
||||
DCD CTIMER2_IRQHandler ; Standard counter/timer CTIMER2
|
||||
DCD CTIMER4_IRQHandler ; Standard counter/timer CTIMER4
|
||||
DCD Reserved54_IRQHandler ; Reserved interrupt
|
||||
DCD SPIFI0_IRQHandler ; SPI flash interface
|
||||
|
||||
; <h> Code Read Protection level (CRP)
|
||||
; <o> CRP_Level:
|
||||
; <0xFFFFFFFF=> Disabled
|
||||
; <0x4E697370=> NO_ISP
|
||||
; <0x12345678=> CRP1
|
||||
; <0x87654321=> CRP2
|
||||
; <0x43218765=> CRP3 (Are you sure?)
|
||||
; </h>
|
||||
CRP_Level EQU 0xFFFFFFFF
|
||||
|
||||
IF :LNOT::DEF:NO_CRP
|
||||
AREA |.ARM.__at_0x02FC|, CODE, READONLY
|
||||
CRP_Key DCD 0xFFFFFFFF
|
||||
ENDIF
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
cpu_id EQU 0xE000ED00
|
||||
cpu_ctrl EQU 0x40000800
|
||||
coproc_boot EQU 0x40000804
|
||||
coproc_stack EQU 0x40000808
|
||||
|
||||
rel_vals
|
||||
DCD cpu_id, cpu_ctrl, coproc_boot, coproc_stack
|
||||
DCW 0xFFF, 0xC24
|
||||
|
||||
; Reset Handler - shared for both cores
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
|
||||
IF :LNOT::DEF:SLAVEBOOT
|
||||
; Both the M0+ and M4 core come via this shared startup code,
|
||||
; but the M0+ and M4 core have different vector tables.
|
||||
; Determine if the core executing this code is the master or
|
||||
; the slave and handle each core state individually.
|
||||
shared_boot_entry
|
||||
LDR r6, =rel_vals
|
||||
MOVS r4, #0 ; Flag for slave core (0)
|
||||
MOVS r5, #1
|
||||
|
||||
; Determine which core (M0+ or M4) this code is running on
|
||||
; r2 = (((*cpu_id) >> 4) & 0xFFF); (M4 core == 0xC24)
|
||||
get_current_core_id
|
||||
LDR r0, [r6, #0]
|
||||
LDR r1, [r0] ; r1 = CPU ID status
|
||||
LSRS r1, r1, #4 ; Right justify 12 CPU ID bits
|
||||
LDRH r2, [r6, #16] ; Mask for CPU ID bits
|
||||
ANDS r2, r1, r2 ; r2 = ARM COrtex CPU ID
|
||||
LDRH r3, [r6, #18] ; Mask for CPU ID bits
|
||||
CMP r3, r2 ; Core ID matches M4 identifier
|
||||
BNE get_master_status
|
||||
MOV r4, r5 ; Set flag for master core (1)
|
||||
|
||||
; Determine if M4 core is the master or slave
|
||||
; r3 = ((*cpu_ctrl) & 1); (0 == m0+, 1 == M4)
|
||||
get_master_status
|
||||
LDR r0, [r6, #4]
|
||||
LDR r3, [r0] ; r3 = SYSCON co-processor CPU control status
|
||||
ANDS r3, r3, r5 ; r3 = (Bit 0: 1 = M4 is master, 0 = M4 is slave)
|
||||
|
||||
; Select boot based on selected master core and core ID
|
||||
select_boot
|
||||
EORS r3, r3, r4 ; r4 = (Bit 0: 0 = master, 1 = slave)
|
||||
BNE slave_boot
|
||||
B normal_boot
|
||||
|
||||
; Slave boot
|
||||
slave_boot
|
||||
LDR r0, [r6, #8]
|
||||
LDR r2, [r0] ; r1 = SYSCON co-processor boot address
|
||||
CMP r2, #0 ; Slave boot address = 0 (not set up)?
|
||||
BEQ cpu_sleep
|
||||
LDR r0, [r6, #12]
|
||||
LDR r1, [r0] ; r5 = SYSCON co-processor stack address
|
||||
MOV sp, r1 ; Update slave CPU stack pointer
|
||||
; Be sure to update VTOR for the slave MCU to point to the
|
||||
; slave vector table in boot memory
|
||||
BX r2 ; Jump to slave boot address
|
||||
|
||||
; Slave isn't yet setup for system boot from the master
|
||||
; so sleep until the master sets it up and then reboots it
|
||||
cpu_sleep
|
||||
MOV sp, r5 ; Will force exception if something happens
|
||||
cpu_sleep_wfi
|
||||
WFI ; Sleep forever until master reboots
|
||||
B cpu_sleep_wfi
|
||||
ENDIF
|
||||
|
||||
; Normal boot for master/slave
|
||||
normal_boot
|
||||
LDR r0, =SystemInit
|
||||
BLX r0
|
||||
LDR r0, =__main
|
||||
BX r0
|
||||
ENDP
|
||||
|
||||
; Dummy Exception Handlers (infinite loops which can be modified)
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
HardFault_Handler \
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
MemManage_Handler PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
BusFault_Handler PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
UsageFault_Handler PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
DebugMon_Handler PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
PendSV_Handler PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
SysTick_Handler PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
WDT_BOD_IRQHandler\
|
||||
PROC
|
||||
EXPORT WDT_BOD_IRQHandler [WEAK]
|
||||
LDR R0, =WDT_BOD_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
DMA0_IRQHandler\
|
||||
PROC
|
||||
EXPORT DMA0_IRQHandler [WEAK]
|
||||
LDR R0, =DMA0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
GINT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT GINT0_IRQHandler [WEAK]
|
||||
LDR R0, =GINT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
GINT1_IRQHandler\
|
||||
PROC
|
||||
EXPORT GINT1_IRQHandler [WEAK]
|
||||
LDR R0, =GINT1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT0_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT1_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT1_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT2_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT2_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT2_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT3_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT3_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT3_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
UTICK0_IRQHandler\
|
||||
PROC
|
||||
EXPORT UTICK0_IRQHandler [WEAK]
|
||||
LDR R0, =UTICK0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
MRT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT MRT0_IRQHandler [WEAK]
|
||||
LDR R0, =MRT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER0_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER0_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER1_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER1_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SCT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT SCT0_IRQHandler [WEAK]
|
||||
LDR R0, =SCT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER3_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER3_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER3_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM0_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM0_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM1_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM1_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM2_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM2_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM2_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM3_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM3_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM3_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM4_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM4_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM4_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM5_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM5_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM5_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM6_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM6_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM6_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM7_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM7_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM7_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ADC0_SEQA_IRQHandler\
|
||||
PROC
|
||||
EXPORT ADC0_SEQA_IRQHandler [WEAK]
|
||||
LDR R0, =ADC0_SEQA_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ADC0_SEQB_IRQHandler\
|
||||
PROC
|
||||
EXPORT ADC0_SEQB_IRQHandler [WEAK]
|
||||
LDR R0, =ADC0_SEQB_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ADC0_THCMP_IRQHandler\
|
||||
PROC
|
||||
EXPORT ADC0_THCMP_IRQHandler [WEAK]
|
||||
LDR R0, =ADC0_THCMP_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
DMIC0_IRQHandler\
|
||||
PROC
|
||||
EXPORT DMIC0_IRQHandler [WEAK]
|
||||
LDR R0, =DMIC0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
HWVAD0_IRQHandler\
|
||||
PROC
|
||||
EXPORT HWVAD0_IRQHandler [WEAK]
|
||||
LDR R0, =HWVAD0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
USB0_NEEDCLK_IRQHandler\
|
||||
PROC
|
||||
EXPORT USB0_NEEDCLK_IRQHandler [WEAK]
|
||||
LDR R0, =USB0_NEEDCLK_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
USB0_IRQHandler\
|
||||
PROC
|
||||
EXPORT USB0_IRQHandler [WEAK]
|
||||
LDR R0, =USB0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
RTC_IRQHandler\
|
||||
PROC
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
LDR R0, =RTC_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
IOH_IRQHandler\
|
||||
PROC
|
||||
EXPORT IOH_IRQHandler [WEAK]
|
||||
LDR R0, =IOH_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
MAILBOX_IRQHandler\
|
||||
PROC
|
||||
EXPORT MAILBOX_IRQHandler [WEAK]
|
||||
LDR R0, =MAILBOX_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT4_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT4_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT4_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT5_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT5_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT5_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT6_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT6_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT6_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT7_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT7_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT7_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER2_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER2_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER2_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER4_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER4_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER4_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
Reserved54_IRQHandler\
|
||||
PROC
|
||||
EXPORT Reserved54_IRQHandler [WEAK]
|
||||
LDR R0, =Reserved54_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SPIFI0_IRQHandler\
|
||||
PROC
|
||||
EXPORT SPIFI0_IRQHandler [WEAK]
|
||||
LDR R0, =SPIFI0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
EXPORT WDT_BOD_DriverIRQHandler [WEAK]
|
||||
EXPORT DMA0_DriverIRQHandler [WEAK]
|
||||
EXPORT GINT0_DriverIRQHandler [WEAK]
|
||||
EXPORT GINT1_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT0_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT1_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT2_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT3_DriverIRQHandler [WEAK]
|
||||
EXPORT UTICK0_DriverIRQHandler [WEAK]
|
||||
EXPORT MRT0_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER0_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER1_DriverIRQHandler [WEAK]
|
||||
EXPORT SCT0_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER3_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM0_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM1_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM2_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM3_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM4_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM5_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM6_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM7_DriverIRQHandler [WEAK]
|
||||
EXPORT ADC0_SEQA_DriverIRQHandler [WEAK]
|
||||
EXPORT ADC0_SEQB_DriverIRQHandler [WEAK]
|
||||
EXPORT ADC0_THCMP_DriverIRQHandler [WEAK]
|
||||
EXPORT DMIC0_DriverIRQHandler [WEAK]
|
||||
EXPORT HWVAD0_DriverIRQHandler [WEAK]
|
||||
EXPORT USB0_NEEDCLK_DriverIRQHandler [WEAK]
|
||||
EXPORT USB0_DriverIRQHandler [WEAK]
|
||||
EXPORT RTC_DriverIRQHandler [WEAK]
|
||||
EXPORT IOH_DriverIRQHandler [WEAK]
|
||||
EXPORT MAILBOX_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT4_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT5_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT6_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT7_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER2_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER4_DriverIRQHandler [WEAK]
|
||||
EXPORT Reserved54_DriverIRQHandler [WEAK]
|
||||
EXPORT SPIFI0_DriverIRQHandler [WEAK]
|
||||
|
||||
WDT_BOD_DriverIRQHandler
|
||||
DMA0_DriverIRQHandler
|
||||
GINT0_DriverIRQHandler
|
||||
GINT1_DriverIRQHandler
|
||||
PIN_INT0_DriverIRQHandler
|
||||
PIN_INT1_DriverIRQHandler
|
||||
PIN_INT2_DriverIRQHandler
|
||||
PIN_INT3_DriverIRQHandler
|
||||
UTICK0_DriverIRQHandler
|
||||
MRT0_DriverIRQHandler
|
||||
CTIMER0_DriverIRQHandler
|
||||
CTIMER1_DriverIRQHandler
|
||||
SCT0_DriverIRQHandler
|
||||
CTIMER3_DriverIRQHandler
|
||||
FLEXCOMM0_DriverIRQHandler
|
||||
FLEXCOMM1_DriverIRQHandler
|
||||
FLEXCOMM2_DriverIRQHandler
|
||||
FLEXCOMM3_DriverIRQHandler
|
||||
FLEXCOMM4_DriverIRQHandler
|
||||
FLEXCOMM5_DriverIRQHandler
|
||||
FLEXCOMM6_DriverIRQHandler
|
||||
FLEXCOMM7_DriverIRQHandler
|
||||
ADC0_SEQA_DriverIRQHandler
|
||||
ADC0_SEQB_DriverIRQHandler
|
||||
ADC0_THCMP_DriverIRQHandler
|
||||
DMIC0_DriverIRQHandler
|
||||
HWVAD0_DriverIRQHandler
|
||||
USB0_NEEDCLK_DriverIRQHandler
|
||||
USB0_DriverIRQHandler
|
||||
RTC_DriverIRQHandler
|
||||
IOH_DriverIRQHandler
|
||||
MAILBOX_DriverIRQHandler
|
||||
PIN_INT4_DriverIRQHandler
|
||||
PIN_INT5_DriverIRQHandler
|
||||
PIN_INT6_DriverIRQHandler
|
||||
PIN_INT7_DriverIRQHandler
|
||||
CTIMER2_DriverIRQHandler
|
||||
CTIMER4_DriverIRQHandler
|
||||
Reserved54_DriverIRQHandler
|
||||
SPIFI0_DriverIRQHandler
|
||||
|
||||
B .
|
||||
|
||||
ENDP
|
||||
|
||||
|
||||
ALIGN
|
||||
|
||||
|
||||
END
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* mbed Microcontroller Library - stackheap
|
||||
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
|
||||
*
|
||||
* Setup a fixed single stack/heap memory model,
|
||||
* between the top of the RW/ZI region and the stackpointer
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rt_misc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern char Image$$RW_IRAM1$$ZI$$Limit[];
|
||||
|
||||
extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
|
||||
uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
|
||||
uint32_t sp_limit = __current_sp();
|
||||
|
||||
zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
|
||||
|
||||
struct __initial_stackheap r;
|
||||
r.heap_base = zi_limit;
|
||||
r.heap_limit = sp_limit;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
** ###################################################################
|
||||
** Processors: LPC54114J256_cm4
|
||||
**
|
||||
** Compiler: GNU C Compiler
|
||||
** Reference manual: LPC54114 Series Reference Manual, Rev. 0 , 11/2016
|
||||
** Version: rev. 1.0, 2016-11-02
|
||||
** Build: b161214
|
||||
**
|
||||
** Abstract:
|
||||
** Linker file for the GNU C Compiler
|
||||
**
|
||||
** Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
** Copyright (c) 2016 - 2017 , NXP
|
||||
** 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 copyright holder 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
|
||||
**
|
||||
** Copyright (c) 2016 NXP Semiconductors, 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 NXP Semiconductors, 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.nxp.com
|
||||
** mail: support@nxp.com
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
__ram_vector_table__ = 1;
|
||||
|
||||
__stack_size__ = 0x2000;
|
||||
__heap_size__ = 0x4000;
|
||||
|
||||
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400;
|
||||
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0800;
|
||||
M_VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0xE4 : 0x0;
|
||||
RPMSG_SHMEM_SIZE = DEFINED(__use_shmem__) ? 0x1800 : 0;
|
||||
|
||||
|
||||
/* Specify the memory areas */
|
||||
MEMORY
|
||||
{
|
||||
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000E4
|
||||
m_text (RX) : ORIGIN = 0x000000E4, LENGTH = 0x0002FF1C
|
||||
m_core1_image (RX) : ORIGIN = 0x00030000, LENGTH = 0x00010000
|
||||
m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00010000
|
||||
rpmsg_sh_mem (RW) : ORIGIN = 0x20026800, LENGTH = RPMSG_SHMEM_SIZE
|
||||
|
||||
}
|
||||
|
||||
/* Define output sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* section for storing the secondary core image */
|
||||
.m0code :
|
||||
{
|
||||
. = ALIGN(4) ;
|
||||
KEEP (*(.m0code))
|
||||
*(.m0code*)
|
||||
. = ALIGN(4) ;
|
||||
} > m_core1_image
|
||||
|
||||
/* NOINIT section for rpmsg_sh_mem */
|
||||
.noinit_rpmsg_sh_mem (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
*(.noinit.$rpmsg_sh_mem*)
|
||||
. = ALIGN(4) ;
|
||||
} > rpmsg_sh_mem
|
||||
|
||||
/* The startup code goes first into internal flash */
|
||||
.interrupts :
|
||||
{
|
||||
__VECTOR_TABLE = .;
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} > m_interrupts
|
||||
|
||||
/* 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 */
|
||||
|
||||
.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 */
|
||||
*(.ramfunc*) /* for functions in ram */
|
||||
*(.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")
|
||||
|
||||
/* 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*)
|
||||
*(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
|
||||
|
||||
/* 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")
|
||||
}
|
||||
|
Binary file not shown.
|
@ -0,0 +1,791 @@
|
|||
/* ---------------------------------------------------------------------------------------*/
|
||||
/* @file: startup_LPC54114_cm4.S */
|
||||
/* @purpose: CMSIS Cortex-M4 Core Device Startup File */
|
||||
/* LPC54114_cm4 */
|
||||
/* @version: 1.0 */
|
||||
/* @date: 2016-11-2 */
|
||||
/* @build: b161214 */
|
||||
/* ---------------------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* Copyright (c) 1997 - 2016 , Freescale Semiconductor, Inc. */
|
||||
/* Copyright (c) 2016 - 2017 , NXP */
|
||||
/* */
|
||||
/* 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 copyright holder 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. */
|
||||
/* */
|
||||
/* Copyright (c) 2016 , NXP Semiconductors, 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 NXP Semiconductors, 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 armv7-m
|
||||
|
||||
.section .isr_vector, "a"
|
||||
.align 2
|
||||
.globl __Vectors
|
||||
__Vectors:
|
||||
.long __StackTop /* Top of Stack */
|
||||
.long Reset_Handler /* Reset Handler */
|
||||
.long NMI_Handler /* NMI Handler*/
|
||||
.long HardFault_Handler /* Hard Fault Handler*/
|
||||
.long MemManage_Handler /* MPU Fault Handler*/
|
||||
.long BusFault_Handler /* Bus Fault Handler*/
|
||||
.long UsageFault_Handler /* Usage Fault Handler*/
|
||||
.long 0 /* Reserved*/
|
||||
.long 0 /* Reserved*/
|
||||
.long 0 /* Reserved*/
|
||||
.long 0 /* Reserved*/
|
||||
.long SVC_Handler /* SVCall Handler*/
|
||||
.long DebugMon_Handler /* Debug Monitor Handler*/
|
||||
.long 0 /* Reserved*/
|
||||
.long PendSV_Handler /* PendSV Handler*/
|
||||
.long SysTick_Handler /* SysTick Handler*/
|
||||
|
||||
/* External Interrupts*/
|
||||
.long WDT_BOD_IRQHandler /* Watchdog Timer, Brownout detect */
|
||||
.long DMA0_IRQHandler /* DMA controller interrupt */
|
||||
.long GINT0_IRQHandler /* GPIO group 0 */
|
||||
.long GINT1_IRQHandler /* GPIO group 1 */
|
||||
.long PIN_INT0_IRQHandler /* Pin interrupt 0 or pattern match engine slice 0 */
|
||||
.long PIN_INT1_IRQHandler /* Pin interrupt 1 or pattern match engine slice 1 */
|
||||
.long PIN_INT2_IRQHandler /* Pin interrupt 2 or pattern match engine slice 2 */
|
||||
.long PIN_INT3_IRQHandler /* Pin interrupt 3 or pattern match engine slice 3 */
|
||||
.long UTICK0_IRQHandler /* Micro-tick Timer */
|
||||
.long MRT0_IRQHandler /* Multi-rate timer */
|
||||
.long CTIMER0_IRQHandler /* Standard counter/timer CTIMER0 */
|
||||
.long CTIMER1_IRQHandler /* Standard counter/timer CTIMER1 */
|
||||
.long SCT0_IRQHandler /* SCTimer/PWM */
|
||||
.long CTIMER3_IRQHandler /* Standard counter/timer CTIMER3 */
|
||||
.long FLEXCOMM0_IRQHandler /* Flexcomm Interface 0 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM1_IRQHandler /* Flexcomm Interface 1 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM2_IRQHandler /* Flexcomm Interface 2 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM3_IRQHandler /* Flexcomm Interface 3 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM4_IRQHandler /* Flexcomm Interface 4 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM5_IRQHandler /* Flexcomm Interface 5 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM6_IRQHandler /* Flexcomm Interface 6 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long FLEXCOMM7_IRQHandler /* Flexcomm Interface 7 (USART, SPI, I2C, FLEXCOMM) */
|
||||
.long ADC0_SEQA_IRQHandler /* ADC0 sequence A completion */
|
||||
.long ADC0_SEQB_IRQHandler /* ADC0 sequence B completion */
|
||||
.long ADC0_THCMP_IRQHandler /* ADC0 threshold compare and error. */
|
||||
.long DMIC0_IRQHandler /* RTC alarm and wake-up interrupts */
|
||||
.long HWVAD0_IRQHandler /* Hardware Voice Activity Detector */
|
||||
.long USB0_NEEDCLK_IRQHandler /* USB Activity Wake-up Interrupt */
|
||||
.long USB0_IRQHandler /* USB device */
|
||||
.long RTC_IRQHandler /* RTC alarm and wake-up interrupts */
|
||||
.long IOH_IRQHandler /* IOH interrupt */
|
||||
.long MAILBOX_IRQHandler /* Mailbox interrupt */
|
||||
.long PIN_INT4_IRQHandler /* Pin interrupt 4 or pattern match engine slice 4 int */
|
||||
.long PIN_INT5_IRQHandler /* Pin interrupt 5 or pattern match engine slice 5 int */
|
||||
.long PIN_INT6_IRQHandler /* Pin interrupt 6 or pattern match engine slice 6 int */
|
||||
.long PIN_INT7_IRQHandler /* Pin interrupt 7 or pattern match engine slice 7 int */
|
||||
.long CTIMER2_IRQHandler /* Standard counter/timer CTIMER2 */
|
||||
.long CTIMER4_IRQHandler /* Standard counter/timer CTIMER4 */
|
||||
.long 0 /* Reserved interrupt */
|
||||
.long SPIFI0_IRQHandler /* SPI flash interface */
|
||||
.size __Vectors, . - __Vectors
|
||||
|
||||
|
||||
|
||||
.text
|
||||
.thumb
|
||||
#ifndef SLAVEBOOT
|
||||
rel_vals:
|
||||
.long 0xE000ED00 /* cpu_id */
|
||||
.long 0x40000800 /* cpu_ctrl */
|
||||
.long 0x40000804 /* coproc_boot */
|
||||
.long 0x40000808 /* coproc_stack */
|
||||
.short 0x0FFF
|
||||
.short 0x0C24
|
||||
#endif
|
||||
/* Reset Handler */
|
||||
|
||||
.thumb_func
|
||||
.align 2
|
||||
.globl Reset_Handler
|
||||
.weak Reset_Handler
|
||||
.type Reset_Handler, %function
|
||||
|
||||
Reset_Handler:
|
||||
#ifndef SLAVEBOOT
|
||||
/* Both the M0+ and M4 core come via this shared startup code,
|
||||
* but the M0+ and M4 core have different vector tables.
|
||||
* Determine if the core executing this code is the master or
|
||||
* the slave and handle each core state individually. */
|
||||
|
||||
shared_boot_entry:
|
||||
ldr r6, =rel_vals
|
||||
|
||||
/* Flag for slave core (0) */
|
||||
movs r4, 0
|
||||
movs r5, 1
|
||||
|
||||
/* Determine which core (M0+ or M4) this code is running on */
|
||||
/* r2 = (((*cpu_id) >> 4) & 0xFFF); (M4 core == 0xC24) */
|
||||
get_current_core_id:
|
||||
ldr r0, [r6, #0]
|
||||
ldr r1, [r0] /* r1 = CPU ID status */
|
||||
lsrs r1, r1, #4 /* Right justify 12 CPU ID bits */
|
||||
ldrh r2, [r6, #16] /* Mask for CPU ID bits */
|
||||
ands r2, r1, r2 /* r2 = ARM COrtex CPU ID */
|
||||
ldrh r3, [r6, #18] /* Mask for CPU ID bits */
|
||||
cmp r3, r2 /* Core ID matches M4 identifier */
|
||||
bne get_master_status
|
||||
mov r4, r5 /* Set flag for master core (1) */
|
||||
|
||||
/* Determine if M4 core is the master or slave */
|
||||
/* r3 = ((*cpu_ctrl) & 1); (0 == m0+, 1 == M4) */
|
||||
get_master_status:
|
||||
ldr r0, [r6, #4]
|
||||
ldr r3, [r0] /* r3 = SYSCON co-processor CPU control status */
|
||||
|
||||
ands r3, r3, r5 /* r3 = (Bit 0: 1 = M4 is master, 0 = M4 is slave) */
|
||||
|
||||
/* Select boot based on selected master core and core ID */
|
||||
|
||||
select_boot:
|
||||
eors r3, r3, r4 /* r4 = (Bit 0: 0 = master, 1 = slave) */
|
||||
|
||||
bne slave_boot
|
||||
b normal_boot
|
||||
|
||||
/* Slave boot */
|
||||
slave_boot:
|
||||
ldr r0, [r6, #8]
|
||||
ldr r2, [r0] /* r1 = SYSCON co-processor boot address */
|
||||
|
||||
cmp r2, #0 /* Slave boot address = 0 (not set up)? */
|
||||
|
||||
beq cpu_sleep
|
||||
ldr r0, [r6, #12]
|
||||
ldr r1, [r0] /* r5 = SYSCON co-processor stack address */
|
||||
|
||||
mov sp, r1 /* Update slave CPU stack pointer */
|
||||
|
||||
/* Be sure to update VTOR for the slave MCU to point to the */
|
||||
/* slave vector table in boot memory */
|
||||
bx r2 /* Jump to slave boot address */
|
||||
|
||||
/* Slave isn't yet setup for system boot from the master */
|
||||
/* so sleep until the master sets it up and then reboots it */
|
||||
cpu_sleep:
|
||||
mov sp, r5 /* Will force exception if something happens */
|
||||
cpu_sleep_wfi:
|
||||
wfi /* Sleep forever until master reboots */
|
||||
b cpu_sleep_wfi
|
||||
#endif /* defined(SLAVEBOOT) */
|
||||
|
||||
#ifndef __START
|
||||
#define __START _start
|
||||
#endif
|
||||
#ifndef __ATOLLIC__
|
||||
normal_boot:
|
||||
#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__
|
||||
|
||||
#if 1
|
||||
/* Here are two copies of loop implemenations. First one favors code size
|
||||
* and the second one favors performance. Default uses the first one.
|
||||
* Change to "#if 0" to use the second one */
|
||||
.LC0:
|
||||
cmp r2, r3
|
||||
ittt lt
|
||||
ldrlt r0, [r1], #4
|
||||
strlt r0, [r2], #4
|
||||
blt .LC0
|
||||
#else
|
||||
subs r3, r2
|
||||
ble .LC1
|
||||
.LC0:
|
||||
subs r3, #4
|
||||
ldr r0, [r1, r3]
|
||||
str r0, [r2, r3]
|
||||
bgt .LC0
|
||||
.LC1:
|
||||
#endif
|
||||
|
||||
#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__
|
||||
|
||||
movs r0, 0
|
||||
.LC2:
|
||||
cmp r1, r2
|
||||
itt lt
|
||||
strlt r0, [r1], #4
|
||||
blt .LC2
|
||||
#endif /* __STARTUP_CLEAR_BSS */
|
||||
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:
|
||||
b DefaultISR
|
||||
.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 MemManage_Handler
|
||||
.type MemManage_Handler, %function
|
||||
MemManage_Handler:
|
||||
ldr r0,=MemManage_Handler
|
||||
bx r0
|
||||
.size MemManage_Handler, . - MemManage_Handler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak BusFault_Handler
|
||||
.type BusFault_Handler, %function
|
||||
BusFault_Handler:
|
||||
ldr r0,=BusFault_Handler
|
||||
bx r0
|
||||
.size BusFault_Handler, . - BusFault_Handler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak UsageFault_Handler
|
||||
.type UsageFault_Handler, %function
|
||||
UsageFault_Handler:
|
||||
ldr r0,=UsageFault_Handler
|
||||
bx r0
|
||||
.size UsageFault_Handler, . - UsageFault_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 DebugMon_Handler
|
||||
.type DebugMon_Handler, %function
|
||||
DebugMon_Handler:
|
||||
ldr r0,=DebugMon_Handler
|
||||
bx r0
|
||||
.size DebugMon_Handler, . - DebugMon_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 WDT_BOD_IRQHandler
|
||||
.type WDT_BOD_IRQHandler, %function
|
||||
WDT_BOD_IRQHandler:
|
||||
ldr r0,=WDT_BOD_DriverIRQHandler
|
||||
bx r0
|
||||
.size WDT_BOD_IRQHandler, . - WDT_BOD_IRQHandler
|
||||
|
||||
|
||||
.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 GINT0_IRQHandler
|
||||
.type GINT0_IRQHandler, %function
|
||||
GINT0_IRQHandler:
|
||||
ldr r0,=GINT0_DriverIRQHandler
|
||||
bx r0
|
||||
.size GINT0_IRQHandler, . - GINT0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak GINT1_IRQHandler
|
||||
.type GINT1_IRQHandler, %function
|
||||
GINT1_IRQHandler:
|
||||
ldr r0,=GINT1_DriverIRQHandler
|
||||
bx r0
|
||||
.size GINT1_IRQHandler, . - GINT1_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT0_IRQHandler
|
||||
.type PIN_INT0_IRQHandler, %function
|
||||
PIN_INT0_IRQHandler:
|
||||
ldr r0,=PIN_INT0_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT0_IRQHandler, . - PIN_INT0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT1_IRQHandler
|
||||
.type PIN_INT1_IRQHandler, %function
|
||||
PIN_INT1_IRQHandler:
|
||||
ldr r0,=PIN_INT1_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT1_IRQHandler, . - PIN_INT1_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT2_IRQHandler
|
||||
.type PIN_INT2_IRQHandler, %function
|
||||
PIN_INT2_IRQHandler:
|
||||
ldr r0,=PIN_INT2_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT2_IRQHandler, . - PIN_INT2_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT3_IRQHandler
|
||||
.type PIN_INT3_IRQHandler, %function
|
||||
PIN_INT3_IRQHandler:
|
||||
ldr r0,=PIN_INT3_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT3_IRQHandler, . - PIN_INT3_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak UTICK0_IRQHandler
|
||||
.type UTICK0_IRQHandler, %function
|
||||
UTICK0_IRQHandler:
|
||||
ldr r0,=UTICK0_DriverIRQHandler
|
||||
bx r0
|
||||
.size UTICK0_IRQHandler, . - UTICK0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak MRT0_IRQHandler
|
||||
.type MRT0_IRQHandler, %function
|
||||
MRT0_IRQHandler:
|
||||
ldr r0,=MRT0_DriverIRQHandler
|
||||
bx r0
|
||||
.size MRT0_IRQHandler, . - MRT0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak CTIMER0_IRQHandler
|
||||
.type CTIMER0_IRQHandler, %function
|
||||
CTIMER0_IRQHandler:
|
||||
ldr r0,=CTIMER0_DriverIRQHandler
|
||||
bx r0
|
||||
.size CTIMER0_IRQHandler, . - CTIMER0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak CTIMER1_IRQHandler
|
||||
.type CTIMER1_IRQHandler, %function
|
||||
CTIMER1_IRQHandler:
|
||||
ldr r0,=CTIMER1_DriverIRQHandler
|
||||
bx r0
|
||||
.size CTIMER1_IRQHandler, . - CTIMER1_IRQHandler
|
||||
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak SCT0_IRQHandler
|
||||
.type SCT0_IRQHandler, %function
|
||||
SCT0_IRQHandler:
|
||||
ldr r0,=SCT0_DriverIRQHandler
|
||||
bx r0
|
||||
.size SCT0_IRQHandler, . - SCT0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak CTIMER3_IRQHandler
|
||||
.type CTIMER3_IRQHandler, %function
|
||||
CTIMER3_IRQHandler:
|
||||
ldr r0,=CTIMER3_DriverIRQHandler
|
||||
bx r0
|
||||
.size CTIMER3_IRQHandler, . - CTIMER3_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM0_IRQHandler
|
||||
.type FLEXCOMM0_IRQHandler, %function
|
||||
FLEXCOMM0_IRQHandler:
|
||||
ldr r0,=FLEXCOMM0_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM0_IRQHandler, . - FLEXCOMM0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM1_IRQHandler
|
||||
.type FLEXCOMM1_IRQHandler, %function
|
||||
FLEXCOMM1_IRQHandler:
|
||||
ldr r0,=FLEXCOMM1_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM1_IRQHandler, . - FLEXCOMM1_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM2_IRQHandler
|
||||
.type FLEXCOMM2_IRQHandler, %function
|
||||
FLEXCOMM2_IRQHandler:
|
||||
ldr r0,=FLEXCOMM2_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM2_IRQHandler, . - FLEXCOMM2_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM3_IRQHandler
|
||||
.type FLEXCOMM3_IRQHandler, %function
|
||||
FLEXCOMM3_IRQHandler:
|
||||
ldr r0,=FLEXCOMM3_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM3_IRQHandler, . - FLEXCOMM3_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM4_IRQHandler
|
||||
.type FLEXCOMM4_IRQHandler, %function
|
||||
FLEXCOMM4_IRQHandler:
|
||||
ldr r0,=FLEXCOMM4_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM4_IRQHandler, . - FLEXCOMM4_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM5_IRQHandler
|
||||
.type FLEXCOMM5_IRQHandler, %function
|
||||
FLEXCOMM5_IRQHandler:
|
||||
ldr r0,=FLEXCOMM5_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM5_IRQHandler, . - FLEXCOMM5_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM6_IRQHandler
|
||||
.type FLEXCOMM6_IRQHandler, %function
|
||||
FLEXCOMM6_IRQHandler:
|
||||
ldr r0,=FLEXCOMM6_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM6_IRQHandler, . - FLEXCOMM6_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak FLEXCOMM7_IRQHandler
|
||||
.type FLEXCOMM7_IRQHandler, %function
|
||||
FLEXCOMM7_IRQHandler:
|
||||
ldr r0,=FLEXCOMM7_DriverIRQHandler
|
||||
bx r0
|
||||
.size FLEXCOMM7_IRQHandler, . - FLEXCOMM7_IRQHandler
|
||||
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak ADC0_SEQA_IRQHandler
|
||||
.type ADC0_SEQA_IRQHandler, %function
|
||||
ADC0_SEQA_IRQHandler:
|
||||
ldr r0,=ADC0_SEQA_DriverIRQHandler
|
||||
bx r0
|
||||
.size ADC0_SEQA_IRQHandler, . - ADC0_SEQA_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak ADC0_SEQB_IRQHandler
|
||||
.type ADC0_SEQB_IRQHandler, %function
|
||||
ADC0_SEQB_IRQHandler:
|
||||
ldr r0,=ADC0_SEQB_DriverIRQHandler
|
||||
bx r0
|
||||
.size ADC0_SEQB_IRQHandler, . - ADC0_SEQB_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak ADC0_THCMP_IRQHandler
|
||||
.type ADC0_THCMP_IRQHandler, %function
|
||||
ADC0_THCMP_IRQHandler:
|
||||
ldr r0,=ADC0_THCMP_DriverIRQHandler
|
||||
bx r0
|
||||
.size ADC0_THCMP_IRQHandler, . - ADC0_THCMP_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak DMIC0_IRQHandler
|
||||
.type DMIC0_IRQHandler, %function
|
||||
DMIC0_IRQHandler:
|
||||
ldr r0,=DMIC0_DriverIRQHandler
|
||||
bx r0
|
||||
.size DMIC0_IRQHandler, . - DMIC0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak HWVAD0_IRQHandler
|
||||
.type HWVAD0_IRQHandler, %function
|
||||
HWVAD0_IRQHandler:
|
||||
ldr r0,=HWVAD0_DriverIRQHandler
|
||||
bx r0
|
||||
.size HWVAD0_IRQHandler, . - HWVAD0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak USB0_NEEDCLK_IRQHandler
|
||||
.type USB0_NEEDCLK_IRQHandler, %function
|
||||
USB0_NEEDCLK_IRQHandler:
|
||||
ldr r0,=USB0_NEEDCLK_DriverIRQHandler
|
||||
bx r0
|
||||
.size USB0_NEEDCLK_IRQHandler, . - USB0_NEEDCLK_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak USB0_IRQHandler
|
||||
.type USB0_IRQHandler, %function
|
||||
USB0_IRQHandler:
|
||||
ldr r0,=USB0_DriverIRQHandler
|
||||
bx r0
|
||||
.size USB0_IRQHandler, . - USB0_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak RTC_IRQHandler
|
||||
.type RTC_IRQHandler, %function
|
||||
RTC_IRQHandler:
|
||||
ldr r0,=RTC_DriverIRQHandler
|
||||
bx r0
|
||||
.size RTC_IRQHandler, . - RTC_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak IOH_IRQHandler
|
||||
.type IOH_IRQHandler, %function
|
||||
IOH_IRQHandler:
|
||||
ldr r0,=IOH_DriverIRQHandler
|
||||
bx r0
|
||||
.size IOH_IRQHandler, . - IOH_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak MAILBOX_IRQHandler
|
||||
.type MAILBOX_IRQHandler, %function
|
||||
MAILBOX_IRQHandler:
|
||||
ldr r0,=MAILBOX_DriverIRQHandler
|
||||
bx r0
|
||||
.size MAILBOX_IRQHandler, . - MAILBOX_IRQHandler
|
||||
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT4_IRQHandler
|
||||
.type PIN_INT4_IRQHandler, %function
|
||||
PIN_INT4_IRQHandler:
|
||||
ldr r0,=PIN_INT4_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT4_IRQHandler, . - PIN_INT4_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT5_IRQHandler
|
||||
.type PIN_INT5_IRQHandler, %function
|
||||
PIN_INT5_IRQHandler:
|
||||
ldr r0,=PIN_INT5_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT5_IRQHandler, . - PIN_INT5_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT6_IRQHandler
|
||||
.type PIN_INT6_IRQHandler, %function
|
||||
PIN_INT6_IRQHandler:
|
||||
ldr r0,=PIN_INT6_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT6_IRQHandler, . - PIN_INT6_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak PIN_INT7_IRQHandler
|
||||
.type PIN_INT7_IRQHandler, %function
|
||||
PIN_INT7_IRQHandler:
|
||||
ldr r0,=PIN_INT7_DriverIRQHandler
|
||||
bx r0
|
||||
.size PIN_INT7_IRQHandler, . - PIN_INT7_IRQHandler
|
||||
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak CTIMER2_IRQHandler
|
||||
.type CTIMER2_IRQHandler, %function
|
||||
CTIMER2_IRQHandler:
|
||||
ldr r0,=CTIMER2_DriverIRQHandler
|
||||
bx r0
|
||||
.size CTIMER2_IRQHandler, . - CTIMER2_IRQHandler
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak CTIMER4_IRQHandler
|
||||
.type CTIMER4_IRQHandler, %function
|
||||
CTIMER4_IRQHandler:
|
||||
ldr r0,=CTIMER4_DriverIRQHandler
|
||||
bx r0
|
||||
.size CTIMER4_IRQHandler, . - CTIMER4_IRQHandler
|
||||
|
||||
|
||||
.align 1
|
||||
.thumb_func
|
||||
.weak SPIFI0_IRQHandler
|
||||
.type SPIFI0_IRQHandler, %function
|
||||
SPIFI0_IRQHandler:
|
||||
ldr r0,=SPIFI0_DriverIRQHandler
|
||||
bx r0
|
||||
.size SPIFI0_IRQHandler, . - SPIFI0_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 WDT_BOD_DriverIRQHandler /* Windowed watchdog timer, Brownout detect */
|
||||
def_irq_handler DMA0_DriverIRQHandler /* DMA controller */
|
||||
def_irq_handler GINT0_DriverIRQHandler /* GPIO group 0 */
|
||||
def_irq_handler GINT1_DriverIRQHandler /* GPIO group 1 */
|
||||
def_irq_handler PIN_INT0_DriverIRQHandler /* Pin interrupt 0 or pattern match engine slice 0 */
|
||||
def_irq_handler PIN_INT1_DriverIRQHandler /* Pin interrupt 1or pattern match engine slice 1 */
|
||||
def_irq_handler PIN_INT2_DriverIRQHandler /* Pin interrupt 2 or pattern match engine slice 2 */
|
||||
def_irq_handler PIN_INT3_DriverIRQHandler /* Pin interrupt 3 or pattern match engine slice 3 */
|
||||
def_irq_handler UTICK0_DriverIRQHandler /* Micro-tick Timer */
|
||||
def_irq_handler MRT0_DriverIRQHandler /* Multi-rate timer */
|
||||
def_irq_handler CTIMER0_DriverIRQHandler /* Standard counter/timer CTIMER0 */
|
||||
def_irq_handler CTIMER1_DriverIRQHandler /* Standard counter/timer CTIMER1 */
|
||||
def_irq_handler SCT0_DriverIRQHandler /* SCTimer/PWM */
|
||||
def_irq_handler CTIMER3_DriverIRQHandler /* Standard counter/timer CTIMER3 */
|
||||
def_irq_handler FLEXCOMM0_DriverIRQHandler /* Flexcomm Interface 0 (USART, SPI, I2C) */
|
||||
def_irq_handler FLEXCOMM1_DriverIRQHandler /* Flexcomm Interface 1 (USART, SPI, I2C) */
|
||||
def_irq_handler FLEXCOMM2_DriverIRQHandler /* Flexcomm Interface 2 (USART, SPI, I2C) */
|
||||
def_irq_handler FLEXCOMM3_DriverIRQHandler /* Flexcomm Interface 3 (USART, SPI, I2C) */
|
||||
def_irq_handler FLEXCOMM4_DriverIRQHandler /* Flexcomm Interface 4 (USART, SPI, I2C) */
|
||||
def_irq_handler FLEXCOMM5_DriverIRQHandler /* Flexcomm Interface 5 (USART, SPI, I2C) */
|
||||
def_irq_handler FLEXCOMM6_DriverIRQHandler /* Flexcomm Interface 6 (USART, SPI, I2C, I2S) */
|
||||
def_irq_handler FLEXCOMM7_DriverIRQHandler /* Flexcomm Interface 7 (USART, SPI, I2C, I2S) */
|
||||
def_irq_handler ADC0_SEQA_DriverIRQHandler /* ADC0 sequence A completion. */
|
||||
def_irq_handler ADC0_SEQB_DriverIRQHandler /* ADC0 sequence B completion. */
|
||||
def_irq_handler ADC0_THCMP_DriverIRQHandler /* ADC0 threshold compare and error. */
|
||||
def_irq_handler DMIC0_DriverIRQHandler /* Digital microphone and DMIC subsystem */
|
||||
def_irq_handler HWVAD0_DriverIRQHandler /* Hardware Voice Activity Detector */
|
||||
def_irq_handler USB0_NEEDCLK_DriverIRQHandler /* USB Activity Wake-up Interrupt */
|
||||
def_irq_handler USB0_DriverIRQHandler /* USB device */
|
||||
def_irq_handler RTC_DriverIRQHandler /* RTC alarm and wake-up interrupts */
|
||||
def_irq_handler IOH_DriverIRQHandler /* IOH */
|
||||
def_irq_handler MAILBOX_DriverIRQHandler /* Mailbox interrupt (present on selected devices) */
|
||||
def_irq_handler PIN_INT4_DriverIRQHandler /* Pin interrupt 4 or pattern match engine slice 4 int */
|
||||
def_irq_handler PIN_INT5_DriverIRQHandler /* Pin interrupt 5 or pattern match engine slice 5 int */
|
||||
def_irq_handler PIN_INT6_DriverIRQHandler /* Pin interrupt 6 or pattern match engine slice 6 int */
|
||||
def_irq_handler PIN_INT7_DriverIRQHandler /* Pin interrupt 7 or pattern match engine slice 7 int */
|
||||
def_irq_handler CTIMER2_DriverIRQHandler /* Standard counter/timer CTIMER2 */
|
||||
def_irq_handler CTIMER4_DriverIRQHandler /* Standard counter/timer CTIMER4 */
|
||||
def_irq_handler SPIFI0_DriverIRQHandler /* SPI flash interface */
|
||||
|
||||
.end
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
** ###################################################################
|
||||
** Processors: LPC54114J256BD64_M4
|
||||
** LPC54114J256UK49_M4
|
||||
**
|
||||
** Compiler: IAR ANSI C/C++ Compiler for ARM
|
||||
** Reference manual: LPC5411x User manual Rev. 1.1 25 May 2016
|
||||
** Version: rev. 1.0, 2016-04-29
|
||||
** Build: b161227
|
||||
**
|
||||
** Abstract:
|
||||
** Linker file for the IAR ANSI C/C++ Compiler for ARM
|
||||
**
|
||||
** Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
** Copyright 2016 - 2017 NXP
|
||||
** 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 the copyright holder 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.nxp.com
|
||||
** mail: support@nxp.com
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
define symbol __ram_vector_table__ = 1;
|
||||
|
||||
/* Heap 1/4 of ram and stack 1/8 */
|
||||
define symbol __stack_size__=0x2000;
|
||||
define symbol __heap_size__=0x4000;
|
||||
|
||||
define symbol __ram_vector_table_size__ = isdefinedsymbol(__ram_vector_table__) ? 0x000000E0 : 0;
|
||||
define symbol __ram_vector_table_offset__ = isdefinedsymbol(__ram_vector_table__) ? 0x000000DF : 0;
|
||||
|
||||
define symbol m_interrupts_start = 0x00000000;
|
||||
define symbol m_interrupts_end = 0x000000DF;
|
||||
|
||||
define symbol m_text_start = 0x000000E0;
|
||||
define symbol m_text_end = 0x0002FFFF;
|
||||
|
||||
define symbol m_interrupts_ram_start = 0x20000000;
|
||||
define symbol m_interrupts_ram_end = 0x20000000 + __ram_vector_table_offset__;
|
||||
|
||||
define symbol m_data_start = m_interrupts_ram_start + __ram_vector_table_size__;
|
||||
define symbol m_data_end = 0x2000FFFF;
|
||||
|
||||
define exported symbol rpmsg_sh_mem_start = 0x20026800;
|
||||
define exported symbol rpmsg_sh_mem_end = 0x20027FFF;
|
||||
|
||||
define symbol m_sramx_start = 0x04000000;
|
||||
define symbol m_sramx_end = 0x04007FFF;
|
||||
|
||||
define exported symbol core1_image_start = 0x00030000;
|
||||
define exported symbol core1_image_end = 0x0003FFFF;
|
||||
|
||||
define symbol __crp_start__ = 0x000002FC;
|
||||
define symbol __crp_end__ = 0x000002FF;
|
||||
|
||||
define symbol __ram_iap_start__ = 0x2000FFE0;
|
||||
define symbol __ram_iap_end__ = 0x2000FFFF;
|
||||
|
||||
/* 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__ = 0x0800;
|
||||
}
|
||||
|
||||
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 TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
|
||||
| mem:[from m_text_start to m_text_end]
|
||||
- mem:[from __crp_start__ to __crp_end__];
|
||||
define region DATA_region = mem:[from m_data_start to m_data_end]
|
||||
- mem:[from __ram_iap_start__-__size_cstack__ to __ram_iap_end__];
|
||||
define region CSTACK_region = mem:[from __ram_iap_start__-__size_cstack__ to __ram_iap_start__-1];
|
||||
define region SRAMX_region = mem:[from m_sramx_start to m_sramx_end];
|
||||
define region CRP_region = mem:[from __crp_start__ to __crp_end__];
|
||||
define region m_interrupts_ram_region = mem:[from m_interrupts_ram_start to m_interrupts_ram_end];
|
||||
|
||||
define region rpmsg_sh_mem_region = mem:[from rpmsg_sh_mem_start to rpmsg_sh_mem_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 };
|
||||
|
||||
define region core1_region = mem:[from core1_image_start to core1_image_end];
|
||||
define block SEC_CORE_IMAGE_WBLOCK { section __sec_core };
|
||||
|
||||
initialize by copy { readwrite };
|
||||
|
||||
if (isdefinedsymbol(__USE_DLIB_PERTHREAD))
|
||||
{
|
||||
// Required in a multi-threaded application
|
||||
initialize by copy with packing = none { section __DLIB_PERTHREAD };
|
||||
}
|
||||
|
||||
do not initialize { section .noinit };
|
||||
do not initialize { section rpmsg_sh_mem_section };
|
||||
|
||||
place at address mem: m_interrupts_start { readonly section .intvec };
|
||||
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 SRAMX_region { section sramx };
|
||||
place in CSTACK_region { block CSTACK };
|
||||
place in CRP_region { section .crp };
|
||||
place in m_interrupts_ram_region { section m_interrupts_ram };
|
||||
place in rpmsg_sh_mem_region { section rpmsg_sh_mem_section };
|
||||
|
||||
place in core1_region { block SEC_CORE_IMAGE_WBLOCK };
|
Binary file not shown.
|
@ -0,0 +1,567 @@
|
|||
;/*****************************************************************************
|
||||
; * @file: startup_LPC54114_cm4.s
|
||||
; * @purpose: CMSIS Cortex-M4 Core Device Startup File
|
||||
; * LPC54114_cm4
|
||||
; * @version: 1.0
|
||||
; * @date: 2016-4-29
|
||||
; *----------------------------------------------------------------------------
|
||||
; *
|
||||
; * Copyright: 1997 - 2016 Freescale Semiconductor,
|
||||
; *
|
||||
; 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
|
||||
DCD HardFault_Handler
|
||||
DCD MemManage_Handler
|
||||
DCD BusFault_Handler
|
||||
DCD UsageFault_Handler
|
||||
__vector_table_0x1c
|
||||
DCD 0
|
||||
DCD 0
|
||||
DCD 0
|
||||
DCD 0
|
||||
DCD SVC_Handler
|
||||
DCD DebugMon_Handler
|
||||
DCD 0
|
||||
DCD PendSV_Handler
|
||||
DCD SysTick_Handler
|
||||
|
||||
; External Interrupts
|
||||
DCD WDT_BOD_IRQHandler ; Windowed watchdog timer, Brownout detect
|
||||
DCD DMA0_IRQHandler ; DMA controller
|
||||
DCD GINT0_IRQHandler ; GPIO group 0
|
||||
DCD GINT1_IRQHandler ; GPIO group 1
|
||||
DCD PIN_INT0_IRQHandler ; Pin interrupt 0 or pattern match engine slice 0
|
||||
DCD PIN_INT1_IRQHandler ; Pin interrupt 1or pattern match engine slice 1
|
||||
DCD PIN_INT2_IRQHandler ; Pin interrupt 2 or pattern match engine slice 2
|
||||
DCD PIN_INT3_IRQHandler ; Pin interrupt 3 or pattern match engine slice 3
|
||||
DCD UTICK0_IRQHandler ; Micro-tick Timer
|
||||
DCD MRT0_IRQHandler ; Multi-rate timer
|
||||
DCD CTIMER0_IRQHandler ; Standard counter/timer CTIMER0
|
||||
DCD CTIMER1_IRQHandler ; Standard counter/timer CTIMER1
|
||||
DCD SCT0_IRQHandler ; SCTimer/PWM
|
||||
DCD CTIMER3_IRQHandler ; Standard counter/timer CTIMER3
|
||||
DCD FLEXCOMM0_IRQHandler ; Flexcomm Interface 0 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM1_IRQHandler ; Flexcomm Interface 1 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM2_IRQHandler ; Flexcomm Interface 2 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM3_IRQHandler ; Flexcomm Interface 3 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM4_IRQHandler ; Flexcomm Interface 4 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM5_IRQHandler ; Flexcomm Interface 5 (USART, SPI, I2C)
|
||||
DCD FLEXCOMM6_IRQHandler ; Flexcomm Interface 6 (USART, SPI, I2C, I2S)
|
||||
DCD FLEXCOMM7_IRQHandler ; Flexcomm Interface 7 (USART, SPI, I2C, I2S)
|
||||
DCD ADC0_SEQA_IRQHandler ; ADC0 sequence A completion.
|
||||
DCD ADC0_SEQB_IRQHandler ; ADC0 sequence B completion.
|
||||
DCD ADC0_THCMP_IRQHandler ; ADC0 threshold compare and error.
|
||||
DCD DMIC0_IRQHandler ; Digital microphone and DMIC subsystem
|
||||
DCD HWVAD0_IRQHandler ; Hardware Voice Activity Detector
|
||||
DCD USB0_NEEDCLK_IRQHandler ; USB Activity Wake-up Interrupt
|
||||
DCD USB0_IRQHandler ; USB device
|
||||
DCD RTC_IRQHandler ; RTC alarm and wake-up interrupts
|
||||
DCD IOH_IRQHandler ; IOH
|
||||
DCD MAILBOX_IRQHandler ; Mailbox interrupt (present on selected devices)
|
||||
DCD PIN_INT4_IRQHandler ; Pin interrupt 4 or pattern match engine slice 4 int
|
||||
DCD PIN_INT5_IRQHandler ; Pin interrupt 5 or pattern match engine slice 5 int
|
||||
DCD PIN_INT6_IRQHandler ; Pin interrupt 6 or pattern match engine slice 6 int
|
||||
DCD PIN_INT7_IRQHandler ; Pin interrupt 7 or pattern match engine slice 7 int
|
||||
DCD CTIMER2_IRQHandler ; Standard counter/timer CTIMER2
|
||||
DCD CTIMER4_IRQHandler ; Standard counter/timer CTIMER4
|
||||
DCD Reserved54_IRQHandler ; Reserved interrupt
|
||||
DCD SPIFI0_IRQHandler ; SPI flash interface
|
||||
__Vectors_End
|
||||
|
||||
; Code Read Protection Level (CRP)
|
||||
; <0xFFFFFFFF=> Disabled
|
||||
; <0x4E697370=> NO_ISP
|
||||
; <0x12345678=> CRP1
|
||||
; <0x87654321=> CRP2
|
||||
; <0x43218765=> CRP3
|
||||
|
||||
#if !defined NO_CRP
|
||||
SECTION .crp:CODE
|
||||
__CRP
|
||||
DCD 0xFFFFFFFF
|
||||
__CRP_End
|
||||
#endif
|
||||
|
||||
__Vectors EQU __vector_table
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Default interrupt handlers.
|
||||
;;
|
||||
SECTION .intvec:CODE:NOROOT(2)
|
||||
#if !defined(SLAVEBOOT)
|
||||
DATA
|
||||
cpu_id EQU 0xE000ED00 ; CPUID Base Register (System control block register)
|
||||
cpu_ctrl EQU 0x40000800
|
||||
coproc_boot EQU 0x40000804
|
||||
coproc_stack EQU 0x40000808
|
||||
rel_vals
|
||||
DC32 cpu_id, cpu_ctrl, coproc_boot, coproc_stack
|
||||
DC16 0xFFF, 0xC24
|
||||
#endif
|
||||
|
||||
THUMB
|
||||
|
||||
PUBWEAK Reset_Handler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
; Reset Handler - shared for both cores
|
||||
Reset_Handler
|
||||
|
||||
#if !defined(SLAVEBOOT)
|
||||
; Both the M0+ and M4 core come via this shared startup code,
|
||||
; but the M0+ and M4 core have different vector tables.
|
||||
; Determine if the core executing this code is the master or
|
||||
; the slave and handle each core state individually.
|
||||
shared_boot_entry
|
||||
LDR r6, =rel_vals
|
||||
MOVS r4, #0 ; Flag for slave core (0)
|
||||
MOVS r5, #1
|
||||
|
||||
; Determine which core (M0+ or M4) this code is running on
|
||||
; r2 = (((*cpu_id) >> 4) & 0xFFF); (M4 core == 0xC24)
|
||||
get_current_core_id
|
||||
LDR r0, [r6, #0]
|
||||
LDR r1, [r0] ; r1 = CPU ID status
|
||||
LSRS r1, r1, #4 ; Right justify 12 CPU ID bits
|
||||
LDRH r2, [r6, #16] ; Mask for CPU ID bits
|
||||
ANDS r2, r1, r2 ; r2 = ARM COrtex CPU ID
|
||||
LDRH r3, [r6, #18] ; Mask for CPU ID bits
|
||||
CMP r3, r2 ; Core ID matches M4 identifier
|
||||
BNE get_master_status
|
||||
MOV r4, r5 ; Set flag for master core (1)
|
||||
|
||||
; Determine if M4 core is the master or slave
|
||||
; r3 = ((*cpu_ctrl) & 1); (0 == m0+, 1 == M4)
|
||||
get_master_status
|
||||
LDR r0, [r6, #4]
|
||||
LDR r3, [r0] ; r3 = SYSCON co-processor CPU control status
|
||||
ANDS r3, r3, r5 ; r3 = (Bit 0: 1 = M4 is master, 0 = M4 is slave)
|
||||
|
||||
; Select boot based on selected master core and core ID
|
||||
select_boot
|
||||
EORS r3, r3, r4 ; r4 = (Bit 0: 0 = master, 1 = slave)
|
||||
BNE slave_boot
|
||||
B normal_boot
|
||||
|
||||
; Slave boot
|
||||
slave_boot
|
||||
LDR r0, [r6, #8]
|
||||
LDR r2, [r0] ; r1 = SYSCON co-processor boot address
|
||||
CMP r2, #0 ; Slave boot address = 0 (not set up)?
|
||||
BEQ cpu_sleep
|
||||
LDR r0, [r6, #12]
|
||||
LDR r1, [r0] ; r5 = SYSCON co-processor stack address
|
||||
MOV sp, r1 ; Update slave CPU stack pointer
|
||||
; Be sure to update VTOR for the slave MCU to point to the
|
||||
; slave vector table in boot memory
|
||||
BX r2 ; Jump to slave boot address
|
||||
|
||||
; Slave isn't yet setup for system boot from the master
|
||||
; so sleep until the master sets it up and then reboots it
|
||||
cpu_sleep
|
||||
MOV sp, r5 ; Will force exception if something happens
|
||||
cpu_sleep_wfi
|
||||
WFI ; Sleep forever until master reboots
|
||||
B cpu_sleep_wfi
|
||||
#endif ; defined(SLAVEBOOT)
|
||||
|
||||
; Normal boot for master/slave
|
||||
normal_boot
|
||||
LDR r0, =SystemInit
|
||||
BLX r0
|
||||
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 MemManage_Handler
|
||||
SECTION .text:CODE:REORDER:NOROOT(1)
|
||||
MemManage_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK BusFault_Handler
|
||||
SECTION .text:CODE:REORDER:NOROOT(1)
|
||||
BusFault_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK UsageFault_Handler
|
||||
SECTION .text:CODE:REORDER:NOROOT(1)
|
||||
UsageFault_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK SVC_Handler
|
||||
SECTION .text:CODE:REORDER:NOROOT(1)
|
||||
SVC_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK DebugMon_Handler
|
||||
SECTION .text:CODE:REORDER:NOROOT(1)
|
||||
DebugMon_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 WDT_BOD_IRQHandler
|
||||
PUBWEAK WDT_BOD_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
WDT_BOD_IRQHandler
|
||||
LDR R0, =WDT_BOD_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK DMA0_IRQHandler
|
||||
PUBWEAK DMA0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
DMA0_IRQHandler
|
||||
LDR R0, =DMA0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK GINT0_IRQHandler
|
||||
PUBWEAK GINT0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
GINT0_IRQHandler
|
||||
LDR R0, =GINT0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK GINT1_IRQHandler
|
||||
PUBWEAK GINT1_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
GINT1_IRQHandler
|
||||
LDR R0, =GINT1_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT0_IRQHandler
|
||||
PUBWEAK PIN_INT0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT0_IRQHandler
|
||||
LDR R0, =PIN_INT0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT1_IRQHandler
|
||||
PUBWEAK PIN_INT1_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT1_IRQHandler
|
||||
LDR R0, =PIN_INT1_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT2_IRQHandler
|
||||
PUBWEAK PIN_INT2_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT2_IRQHandler
|
||||
LDR R0, =PIN_INT2_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT3_IRQHandler
|
||||
PUBWEAK PIN_INT3_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT3_IRQHandler
|
||||
LDR R0, =PIN_INT3_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK UTICK0_IRQHandler
|
||||
PUBWEAK UTICK0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
UTICK0_IRQHandler
|
||||
LDR R0, =UTICK0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK MRT0_IRQHandler
|
||||
PUBWEAK MRT0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
MRT0_IRQHandler
|
||||
LDR R0, =MRT0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK CTIMER0_IRQHandler
|
||||
PUBWEAK CTIMER0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
CTIMER0_IRQHandler
|
||||
LDR R0, =CTIMER0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK CTIMER1_IRQHandler
|
||||
PUBWEAK CTIMER1_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
CTIMER1_IRQHandler
|
||||
LDR R0, =CTIMER1_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK SCT0_IRQHandler
|
||||
PUBWEAK SCT0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
SCT0_IRQHandler
|
||||
LDR R0, =SCT0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK CTIMER3_IRQHandler
|
||||
PUBWEAK CTIMER3_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
CTIMER3_IRQHandler
|
||||
LDR R0, =CTIMER3_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM0_IRQHandler
|
||||
PUBWEAK FLEXCOMM0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM0_IRQHandler
|
||||
LDR R0, =FLEXCOMM0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM1_IRQHandler
|
||||
PUBWEAK FLEXCOMM1_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM1_IRQHandler
|
||||
LDR R0, =FLEXCOMM1_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM2_IRQHandler
|
||||
PUBWEAK FLEXCOMM2_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM2_IRQHandler
|
||||
LDR R0, =FLEXCOMM2_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM3_IRQHandler
|
||||
PUBWEAK FLEXCOMM3_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM3_IRQHandler
|
||||
LDR R0, =FLEXCOMM3_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM4_IRQHandler
|
||||
PUBWEAK FLEXCOMM4_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM4_IRQHandler
|
||||
LDR R0, =FLEXCOMM4_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM5_IRQHandler
|
||||
PUBWEAK FLEXCOMM5_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM5_IRQHandler
|
||||
LDR R0, =FLEXCOMM5_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM6_IRQHandler
|
||||
PUBWEAK FLEXCOMM6_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM6_IRQHandler
|
||||
LDR R0, =FLEXCOMM6_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK FLEXCOMM7_IRQHandler
|
||||
PUBWEAK FLEXCOMM7_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
FLEXCOMM7_IRQHandler
|
||||
LDR R0, =FLEXCOMM7_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK ADC0_SEQA_IRQHandler
|
||||
PUBWEAK ADC0_SEQA_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
ADC0_SEQA_IRQHandler
|
||||
LDR R0, =ADC0_SEQA_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK ADC0_SEQB_IRQHandler
|
||||
PUBWEAK ADC0_SEQB_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
ADC0_SEQB_IRQHandler
|
||||
LDR R0, =ADC0_SEQB_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK ADC0_THCMP_IRQHandler
|
||||
PUBWEAK ADC0_THCMP_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
ADC0_THCMP_IRQHandler
|
||||
LDR R0, =ADC0_THCMP_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK DMIC0_IRQHandler
|
||||
PUBWEAK DMIC0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
DMIC0_IRQHandler
|
||||
LDR R0, =DMIC0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK HWVAD0_IRQHandler
|
||||
PUBWEAK HWVAD0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
HWVAD0_IRQHandler
|
||||
LDR R0, =HWVAD0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK USB0_NEEDCLK_IRQHandler
|
||||
PUBWEAK USB0_NEEDCLK_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
USB0_NEEDCLK_IRQHandler
|
||||
LDR R0, =USB0_NEEDCLK_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK USB0_IRQHandler
|
||||
PUBWEAK USB0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
USB0_IRQHandler
|
||||
LDR R0, =USB0_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK RTC_IRQHandler
|
||||
PUBWEAK RTC_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
RTC_IRQHandler
|
||||
LDR R0, =RTC_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK IOH_IRQHandler
|
||||
PUBWEAK IOH_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
IOH_IRQHandler
|
||||
LDR R0, =IOH_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK MAILBOX_IRQHandler
|
||||
PUBWEAK MAILBOX_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
MAILBOX_IRQHandler
|
||||
LDR R0, =MAILBOX_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT4_IRQHandler
|
||||
PUBWEAK PIN_INT4_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT4_IRQHandler
|
||||
LDR R0, =PIN_INT4_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT5_IRQHandler
|
||||
PUBWEAK PIN_INT5_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT5_IRQHandler
|
||||
LDR R0, =PIN_INT5_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT6_IRQHandler
|
||||
PUBWEAK PIN_INT6_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT6_IRQHandler
|
||||
LDR R0, =PIN_INT6_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK PIN_INT7_IRQHandler
|
||||
PUBWEAK PIN_INT7_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
PIN_INT7_IRQHandler
|
||||
LDR R0, =PIN_INT7_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK CTIMER2_IRQHandler
|
||||
PUBWEAK CTIMER2_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
CTIMER2_IRQHandler
|
||||
LDR R0, =CTIMER2_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK CTIMER4_IRQHandler
|
||||
PUBWEAK CTIMER4_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
CTIMER4_IRQHandler
|
||||
LDR R0, =CTIMER4_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK Reserved54_IRQHandler
|
||||
PUBWEAK Reserved54_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
Reserved54_IRQHandler
|
||||
LDR R0, =Reserved54_DriverIRQHandler
|
||||
BX R0
|
||||
PUBWEAK SPIFI0_IRQHandler
|
||||
PUBWEAK SPIFI0_DriverIRQHandler
|
||||
SECTION .text:CODE:REORDER:NOROOT(2)
|
||||
SPIFI0_IRQHandler
|
||||
LDR R0, =SPIFI0_DriverIRQHandler
|
||||
BX R0
|
||||
WDT_BOD_DriverIRQHandler
|
||||
DMA0_DriverIRQHandler
|
||||
GINT0_DriverIRQHandler
|
||||
GINT1_DriverIRQHandler
|
||||
PIN_INT0_DriverIRQHandler
|
||||
PIN_INT1_DriverIRQHandler
|
||||
PIN_INT2_DriverIRQHandler
|
||||
PIN_INT3_DriverIRQHandler
|
||||
UTICK0_DriverIRQHandler
|
||||
MRT0_DriverIRQHandler
|
||||
CTIMER0_DriverIRQHandler
|
||||
CTIMER1_DriverIRQHandler
|
||||
SCT0_DriverIRQHandler
|
||||
CTIMER3_DriverIRQHandler
|
||||
FLEXCOMM0_DriverIRQHandler
|
||||
FLEXCOMM1_DriverIRQHandler
|
||||
FLEXCOMM2_DriverIRQHandler
|
||||
FLEXCOMM3_DriverIRQHandler
|
||||
FLEXCOMM4_DriverIRQHandler
|
||||
FLEXCOMM5_DriverIRQHandler
|
||||
FLEXCOMM6_DriverIRQHandler
|
||||
FLEXCOMM7_DriverIRQHandler
|
||||
ADC0_SEQA_DriverIRQHandler
|
||||
ADC0_SEQB_DriverIRQHandler
|
||||
ADC0_THCMP_DriverIRQHandler
|
||||
DMIC0_DriverIRQHandler
|
||||
HWVAD0_DriverIRQHandler
|
||||
USB0_NEEDCLK_DriverIRQHandler
|
||||
USB0_DriverIRQHandler
|
||||
RTC_DriverIRQHandler
|
||||
IOH_DriverIRQHandler
|
||||
MAILBOX_DriverIRQHandler
|
||||
PIN_INT4_DriverIRQHandler
|
||||
PIN_INT5_DriverIRQHandler
|
||||
PIN_INT6_DriverIRQHandler
|
||||
PIN_INT7_DriverIRQHandler
|
||||
CTIMER2_DriverIRQHandler
|
||||
CTIMER4_DriverIRQHandler
|
||||
Reserved54_DriverIRQHandler
|
||||
SPIFI0_DriverIRQHandler
|
||||
DefaultISR
|
||||
B .
|
||||
|
||||
END
|
|
@ -0,0 +1,46 @@
|
|||
/* 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
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
extern uint32_t Image$$VECTOR_RAM$$Base[];
|
||||
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
|
||||
#else
|
||||
extern uint32_t __VECTOR_RAM[];
|
||||
#endif
|
||||
|
||||
/* Symbols defined by the linker script */
|
||||
#define NVIC_NUM_VECTORS (16 + 40) // CORE + MCU Peripherals
|
||||
#define NVIC_RAM_VECTOR_ADDRESS (__VECTOR_RAM) // Vectors positioned at start of RAM
|
||||
|
||||
#endif
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
** ###################################################################
|
||||
** Processors: LPC54114J256BD64_cm4
|
||||
** LPC54114J256UK49_cm4
|
||||
**
|
||||
** Compilers: Keil ARM C/C++ Compiler
|
||||
** GNU C Compiler
|
||||
** IAR ANSI C/C++ Compiler for ARM
|
||||
**
|
||||
** Reference manual: LPC5411x User manual Rev. 1.0 16 February 2016
|
||||
** Version: rev. 1.0, 2016-04-29
|
||||
** Build: b160525
|
||||
**
|
||||
** 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) 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
|
||||
**
|
||||
** Revisions:
|
||||
** - rev. 1.0 (2016-04-29)
|
||||
** Initial version.
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file LPC54114_cm4
|
||||
* @version 1.0
|
||||
* @date 2016-04-29
|
||||
* @brief Device specific configuration file for LPC54114_cm4 (implementation
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "fsl_device_registers.h"
|
||||
|
||||
#define NVALMAX (0x100)
|
||||
#define PVALMAX (0x20)
|
||||
#define MVALMAX (0x8000)
|
||||
#define PLL_SSCG0_MDEC_VAL_P (0) /* MDEC is in bits 16 downto 0 */
|
||||
#define PLL_SSCG0_MDEC_VAL_M (0x1FFFFUL << PLL_SSCG0_MDEC_VAL_P) /* NDEC is in bits 9 downto 0 */
|
||||
#define PLL_NDEC_VAL_P (0) /* NDEC is in bits 9:0 */
|
||||
#define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)
|
||||
#define PLL_PDEC_VAL_P (0) /* PDEC is in bits 6:0 */
|
||||
#define PLL_PDEC_VAL_M (0x3FFUL << PLL_PDEC_VAL_P)
|
||||
|
||||
extern void *__Vectors;
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
-- Core clock
|
||||
---------------------------------------------------------------------------- */
|
||||
|
||||
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
|
||||
|
||||
static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 42, 44, 45, 46,
|
||||
48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};
|
||||
|
||||
static uint32_t GetWdtOscFreq(void)
|
||||
{
|
||||
uint8_t freq_sel, div_sel;
|
||||
div_sel = ((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_DIVSEL_MASK) + 1) << 1;
|
||||
freq_sel = wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];
|
||||
return ((uint32_t) freq_sel * 50000U)/((uint32_t)div_sel);
|
||||
}
|
||||
|
||||
/* Find decoded N value for raw NDEC value */
|
||||
static uint32_t pllDecodeN(uint32_t NDEC)
|
||||
{
|
||||
uint32_t n, x, i;
|
||||
|
||||
/* Find NDec */
|
||||
switch (NDEC)
|
||||
{
|
||||
case 0xFFF:
|
||||
n = 0;
|
||||
break;
|
||||
case 0x302:
|
||||
n = 1;
|
||||
break;
|
||||
case 0x202:
|
||||
n = 2;
|
||||
break;
|
||||
default:
|
||||
x = 0x080;
|
||||
n = 0xFFFFFFFF;
|
||||
for (i = NVALMAX; ((i >= 3) && (n == 0xFFFFFFFF)); i--)
|
||||
{
|
||||
x = (((x ^ (x >> 2) ^ (x >> 3) ^ (x >> 4)) & 1) << 7) | ((x >> 1) & 0x7F);
|
||||
if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
|
||||
{
|
||||
/* Decoded value of NDEC */
|
||||
n = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Find decoded P value for raw PDEC value */
|
||||
static uint32_t pllDecodeP(uint32_t PDEC)
|
||||
{
|
||||
uint32_t p, x, i;
|
||||
/* Find PDec */
|
||||
switch (PDEC)
|
||||
{
|
||||
case 0xFF:
|
||||
p = 0;
|
||||
break;
|
||||
case 0x62:
|
||||
p = 1;
|
||||
break;
|
||||
case 0x42:
|
||||
p = 2;
|
||||
break;
|
||||
default:
|
||||
x = 0x10;
|
||||
p = 0xFFFFFFFF;
|
||||
for (i = PVALMAX; ((i >= 3) && (p == 0xFFFFFFFF)); i--)
|
||||
{
|
||||
x = (((x ^ (x >> 2)) & 1) << 4) | ((x >> 1) & 0xF);
|
||||
if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)
|
||||
{
|
||||
/* Decoded value of PDEC */
|
||||
p = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Find decoded M value for raw MDEC value */
|
||||
static uint32_t pllDecodeM(uint32_t MDEC)
|
||||
{
|
||||
uint32_t m, i, x;
|
||||
|
||||
/* Find MDec */
|
||||
switch (MDEC)
|
||||
{
|
||||
case 0xFFFFF:
|
||||
m = 0;
|
||||
break;
|
||||
case 0x18003:
|
||||
m = 1;
|
||||
break;
|
||||
case 0x10003:
|
||||
m = 2;
|
||||
break;
|
||||
default:
|
||||
x = 0x04000;
|
||||
m = 0xFFFFFFFF;
|
||||
for (i = MVALMAX; ((i >= 3) && (m == 0xFFFFFFFF)); i--)
|
||||
{
|
||||
x = (((x ^ (x >> 1)) & 1) << 14) | ((x >> 1) & 0x3FFF);
|
||||
if ((x & (PLL_SSCG0_MDEC_VAL_M >> PLL_SSCG0_MDEC_VAL_P)) == MDEC)
|
||||
{
|
||||
/* Decoded value of MDEC */
|
||||
m = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* Get predivider (N) from PLL NDEC setting */
|
||||
static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
|
||||
{
|
||||
uint32_t preDiv = 1;
|
||||
|
||||
/* Direct input is not used? */
|
||||
if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTI_MASK) == 0)
|
||||
{
|
||||
/* Decode NDEC value to get (N) pre divider */
|
||||
preDiv = pllDecodeN(nDecReg & 0x3FF);
|
||||
if (preDiv == 0)
|
||||
{
|
||||
preDiv = 1;
|
||||
}
|
||||
}
|
||||
/* Adjusted by 1, directi is used to bypass */
|
||||
return preDiv;
|
||||
}
|
||||
|
||||
/* Get postdivider (P) from PLL PDEC setting */
|
||||
static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
|
||||
{
|
||||
uint32_t postDiv = 1;
|
||||
|
||||
/* Direct input is not used? */
|
||||
if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0)
|
||||
{
|
||||
/* Decode PDEC value to get (P) post divider */
|
||||
postDiv = 2 * pllDecodeP(pDecReg & 0x7F);
|
||||
if (postDiv == 0)
|
||||
{
|
||||
postDiv = 2;
|
||||
}
|
||||
}
|
||||
/* Adjusted by 1, directo is used to bypass */
|
||||
return postDiv;
|
||||
}
|
||||
|
||||
/* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
|
||||
static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
|
||||
{
|
||||
uint32_t mMult = 1;
|
||||
|
||||
/* Decode MDEC value to get (M) multiplier */
|
||||
mMult = pllDecodeM(mDecReg & 0x1FFFF);
|
||||
/* Extra multiply by 2 needed? */
|
||||
if ((ctrlReg & SYSCON_SYSPLLCTRL_BYPASSCCODIV2_MASK) == 0)
|
||||
{
|
||||
mMult = mMult << 1;
|
||||
}
|
||||
if (mMult == 0)
|
||||
{
|
||||
mMult = 1;
|
||||
}
|
||||
return mMult;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
-- SystemInit()
|
||||
---------------------------------------------------------------------------- */
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) || (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access */
|
||||
#endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
|
||||
SCB->VTOR = (uint32_t)&__Vectors;
|
||||
/* Optionally enable RAM banks that may be off by default at reset */
|
||||
#if !defined(DONT_ENABLE_DISABLED_RAMBANKS)
|
||||
SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL_SRAM2_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
-- SystemCoreClockUpdate()
|
||||
---------------------------------------------------------------------------- */
|
||||
|
||||
void SystemCoreClockUpdate(void)
|
||||
{
|
||||
uint32_t clkRate = 0;
|
||||
uint32_t prediv, postdiv;
|
||||
uint64_t workRate;
|
||||
|
||||
switch (SYSCON->MAINCLKSELB & SYSCON_MAINCLKSELB_SEL_MASK)
|
||||
{
|
||||
case 0x00: /* MAINCLKSELA clock (main_clk_a)*/
|
||||
switch (SYSCON->MAINCLKSELA & SYSCON_MAINCLKSELA_SEL_MASK)
|
||||
{
|
||||
case 0x00: /* FRO 12 MHz (fro_12m) */
|
||||
clkRate = CLK_FRO_12MHZ;
|
||||
break;
|
||||
case 0x01: /* CLKIN (clk_in) */
|
||||
clkRate = CLK_CLK_IN;
|
||||
break;
|
||||
case 0x02: /* Watchdog oscillator (wdt_clk) */
|
||||
clkRate = GetWdtOscFreq();
|
||||
break;
|
||||
default: /* = 0x03 = FRO 96 or 48 MHz (fro_hf) */
|
||||
if (SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK)
|
||||
{
|
||||
clkRate = CLK_FRO_96MHZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
clkRate = CLK_FRO_48MHZ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x02: /* System PLL clock (pll_clk)*/
|
||||
switch (SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK)
|
||||
{
|
||||
case 0x00: /* FRO 12 MHz (fro_12m) */
|
||||
clkRate = CLK_FRO_12MHZ;
|
||||
break;
|
||||
case 0x01: /* CLKIN (clk_in) */
|
||||
clkRate = CLK_CLK_IN;
|
||||
break;
|
||||
case 0x02: /* Watchdog oscillator (wdt_clk) */
|
||||
clkRate = GetWdtOscFreq();
|
||||
break;
|
||||
case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
|
||||
clkRate = CLK_RTC_32K_CLK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((SYSCON->SYSPLLCTRL & SYSCON_SYSPLLCTRL_BYPASS_MASK) == 0)
|
||||
{
|
||||
/* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */
|
||||
prediv = findPllPreDiv(SYSCON->SYSPLLCTRL, SYSCON->SYSPLLNDEC);
|
||||
postdiv = findPllPostDiv(SYSCON->SYSPLLCTRL, SYSCON->SYSPLLPDEC);
|
||||
/* Adjust input clock */
|
||||
clkRate = clkRate / prediv;
|
||||
/* If using the SS, use the multiplier */
|
||||
if (SYSCON->SYSPLLSSCTRL1 & SYSCON_SYSPLLSSCTRL1_PD_MASK)
|
||||
{
|
||||
/* MDEC used for rate */
|
||||
workRate = (uint64_t)clkRate * (uint64_t)findPllMMult(SYSCON->SYSPLLCTRL, SYSCON->SYSPLLSSCTRL0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SS multipler used for rate */
|
||||
workRate = 0;
|
||||
/* Adjust by fractional */
|
||||
workRate = workRate + ((clkRate * (uint64_t)((SYSCON->SYSPLLSSCTRL1 & 0x7FF) >> 0)) / 0x800);
|
||||
}
|
||||
clkRate = workRate / ((uint64_t)postdiv);
|
||||
}
|
||||
break;
|
||||
case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
|
||||
clkRate = CLK_RTC_32K_CLK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SystemCoreClock = clkRate / ((SYSCON->AHBCLKDIV & 0xFF) + 1);
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
** ###################################################################
|
||||
** Processors: LPC54114J256BD64_cm4
|
||||
** LPC54114J256UK49_cm4
|
||||
**
|
||||
** Compilers: Keil ARM C/C++ Compiler
|
||||
** GNU C Compiler
|
||||
** IAR ANSI C/C++ Compiler for ARM
|
||||
**
|
||||
** Reference manual: LPC5411x User manual Rev. 1.0 16 February 2016
|
||||
** Version: rev. 1.0, 2016-04-29
|
||||
** Build: b160525
|
||||
**
|
||||
** 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) 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
|
||||
**
|
||||
** Revisions:
|
||||
** - rev. 1.0 (2016-04-29)
|
||||
** Initial version.
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file LPC54114_cm4
|
||||
* @version 1.0
|
||||
* @date 2016-04-29
|
||||
* @brief Device specific configuration file for LPC54114_cm4 (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_LPC54114_cm4_H_
|
||||
#define _SYSTEM_LPC54114_cm4_H_ /**< Symbol preventing repeated inclusion */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define DEFAULT_SYSTEM_CLOCK 12000000u /* Default System clock value */
|
||||
#define CLK_RTC_32K_CLK 32768u /* RTC oscillator 32 kHz output (32k_clk */
|
||||
#define CLK_FRO_12MHZ 12000000u /* FRO 12 MHz (fro_12m) */
|
||||
#define CLK_FRO_48MHZ 48000000u /* FRO 48 MHz (fro_48m) */
|
||||
#define CLK_FRO_96MHZ 96000000u /* FRO 96 MHz (fro_96m) */
|
||||
#define CLK_CLK_IN 0u /* Default CLK_IN pin clock */
|
||||
|
||||
|
||||
/**
|
||||
* @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_LPC54114_cm4_H_ */
|
|
@ -0,0 +1,13 @@
|
|||
/* mbed Microcontroller Library - CMSIS
|
||||
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
|
||||
*
|
||||
* A generic CMSIS include header, pulling in LPC54114 specifics
|
||||
*/
|
||||
|
||||
#ifndef MBED_CMSIS_H
|
||||
#define MBED_CMSIS_H
|
||||
|
||||
#include "fsl_device_registers.h"
|
||||
#include "cmsis_nvic.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2014 - 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.
|
||||
*/
|
||||
|
||||
#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_LPC54114J256BD64_cm4) || defined(CPU_LPC54114J256UK49_cm4))
|
||||
|
||||
#define LPC54114_cm4_SERIES
|
||||
|
||||
/* CMSIS-style register definitions */
|
||||
#include "LPC54114_cm4.h"
|
||||
/* CPU specific feature definitions */
|
||||
#include "LPC54114_cm4_features.h"
|
||||
|
||||
#elif (defined(CPU_LPC54114J256BD64_cm0plus) || defined(CPU_LPC54114J256UK49_cm0plus))
|
||||
|
||||
#define LPC54114_cm0plus_SERIES
|
||||
|
||||
/* CMSIS-style register definitions */
|
||||
#include "LPC54114_cm0plus.h"
|
||||
/* CPU specific feature definitions */
|
||||
#include "LPC54114_cm0plus_features.h"
|
||||
|
||||
#else
|
||||
#error "No valid CPU defined!"
|
||||
#endif
|
||||
|
||||
#endif /* __FSL_DEVICE_REGISTERS_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_adc.h"
|
||||
#include "fsl_clock.h"
|
||||
|
||||
static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
|
||||
static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
|
||||
|
||||
static uint32_t ADC_GetInstance(ADC_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_ADC_COUNT; instance++)
|
||||
{
|
||||
if (s_adcBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_ADC_COUNT);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ADC_Init(ADC_Type *base, const adc_config_t *config)
|
||||
{
|
||||
assert(config != NULL);
|
||||
|
||||
uint32_t tmp32 = 0U;
|
||||
|
||||
/* Enable clock. */
|
||||
CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
|
||||
|
||||
/* Disable the interrupts. */
|
||||
base->INTEN = 0U; /* Quickly disable all the interrupts. */
|
||||
|
||||
/* Configure the ADC block. */
|
||||
tmp32 = ADC_CTRL_CLKDIV(config->clockDividerNumber);
|
||||
|
||||
/* Async or Sync clock mode. */
|
||||
switch (config->clockMode)
|
||||
{
|
||||
case kADC_ClockAsynchronousMode:
|
||||
tmp32 |= ADC_CTRL_ASYNMODE_MASK;
|
||||
break;
|
||||
default: /* kADC_ClockSynchronousMode */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Resolution. */
|
||||
tmp32 |= ADC_CTRL_RESOL(config->resolution);
|
||||
|
||||
/* Bypass calibration. */
|
||||
if (config->enableBypassCalibration)
|
||||
{
|
||||
tmp32 |= ADC_CTRL_BYPASSCAL_MASK;
|
||||
}
|
||||
|
||||
/* Sample time clock count. */
|
||||
tmp32 |= ADC_CTRL_TSAMP(config->sampleTimeNumber);
|
||||
|
||||
base->CTRL = tmp32;
|
||||
}
|
||||
|
||||
void ADC_GetDefaultConfig(adc_config_t *config)
|
||||
{
|
||||
config->clockMode = kADC_ClockSynchronousMode;
|
||||
config->clockDividerNumber = 0U;
|
||||
config->resolution = kADC_Resolution12bit;
|
||||
config->enableBypassCalibration = false;
|
||||
config->sampleTimeNumber = 0U;
|
||||
}
|
||||
|
||||
void ADC_Deinit(ADC_Type *base)
|
||||
{
|
||||
/* Disable the clock. */
|
||||
CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
|
||||
}
|
||||
|
||||
bool ADC_DoSelfCalibration(ADC_Type *base)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* Enable the converter. */
|
||||
/* This bit acn only be set 1 by software. It is cleared automatically whenever the ADC is powered down.
|
||||
This bit should be set after at least 10 ms after the ADC is powered on. */
|
||||
base->STARTUP = ADC_STARTUP_ADC_ENA_MASK;
|
||||
for (i = 0U; i < 0x10; i++) /* Wait a few clocks to startup up. */
|
||||
{
|
||||
__ASM("NOP");
|
||||
}
|
||||
if (!(base->STARTUP & ADC_STARTUP_ADC_ENA_MASK))
|
||||
{
|
||||
return false; /* ADC is not powered up. */
|
||||
}
|
||||
|
||||
/* If not in by-pass mode, do the calibration. */
|
||||
if ((ADC_CALIB_CALREQD_MASK == (base->CALIB & ADC_CALIB_CALREQD_MASK)) &&
|
||||
(0U == (base->CTRL & ADC_CTRL_BYPASSCAL_MASK)))
|
||||
{
|
||||
/* Calibration is needed, do it now. */
|
||||
base->CALIB = ADC_CALIB_CALIB_MASK;
|
||||
i = 0xF0000;
|
||||
while ((ADC_CALIB_CALIB_MASK == (base->CALIB & ADC_CALIB_CALIB_MASK)) && (--i))
|
||||
{
|
||||
}
|
||||
if (i == 0U)
|
||||
{
|
||||
return false; /* Calibration timeout. */
|
||||
}
|
||||
}
|
||||
|
||||
/* A dummy conversion cycle will be performed. */
|
||||
base->STARTUP |= ADC_STARTUP_ADC_INIT_MASK;
|
||||
i = 0x7FFFF;
|
||||
while ((ADC_STARTUP_ADC_INIT_MASK == (base->STARTUP & ADC_STARTUP_ADC_INIT_MASK)) && (--i))
|
||||
{
|
||||
}
|
||||
if (i == 0U)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ADC_SetConvSeqAConfig(ADC_Type *base, const adc_conv_seq_config_t *config)
|
||||
{
|
||||
assert(config != NULL);
|
||||
|
||||
uint32_t tmp32;
|
||||
|
||||
tmp32 = ADC_SEQ_CTRL_CHANNELS(config->channelMask) /* Channel mask. */
|
||||
| ADC_SEQ_CTRL_TRIGGER(config->triggerMask); /* Trigger mask. */
|
||||
|
||||
/* Polarity for tirgger signal. */
|
||||
switch (config->triggerPolarity)
|
||||
{
|
||||
case kADC_TriggerPolarityPositiveEdge:
|
||||
tmp32 |= ADC_SEQ_CTRL_TRIGPOL_MASK;
|
||||
break;
|
||||
default: /* kADC_TriggerPolarityNegativeEdge */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Bypass the clock Sync. */
|
||||
if (config->enableSyncBypass)
|
||||
{
|
||||
tmp32 |= ADC_SEQ_CTRL_SYNCBYPASS_MASK;
|
||||
}
|
||||
|
||||
/* Interrupt point. */
|
||||
switch (config->interruptMode)
|
||||
{
|
||||
case kADC_InterruptForEachSequence:
|
||||
tmp32 |= ADC_SEQ_CTRL_MODE_MASK;
|
||||
break;
|
||||
default: /* kADC_InterruptForEachConversion */
|
||||
break;
|
||||
}
|
||||
|
||||
/* One trigger for a conversion, or for a sequence. */
|
||||
if (config->enableSingleStep)
|
||||
{
|
||||
tmp32 |= ADC_SEQ_CTRL_SINGLESTEP_MASK;
|
||||
}
|
||||
|
||||
base->SEQ_CTRL[0] = tmp32;
|
||||
}
|
||||
|
||||
void ADC_SetConvSeqBConfig(ADC_Type *base, const adc_conv_seq_config_t *config)
|
||||
{
|
||||
assert(config != NULL);
|
||||
|
||||
uint32_t tmp32;
|
||||
|
||||
tmp32 = ADC_SEQ_CTRL_CHANNELS(config->channelMask) /* Channel mask. */
|
||||
| ADC_SEQ_CTRL_TRIGGER(config->triggerMask); /* Trigger mask. */
|
||||
|
||||
/* Polarity for tirgger signal. */
|
||||
switch (config->triggerPolarity)
|
||||
{
|
||||
case kADC_TriggerPolarityPositiveEdge:
|
||||
tmp32 |= ADC_SEQ_CTRL_TRIGPOL_MASK;
|
||||
break;
|
||||
default: /* kADC_TriggerPolarityPositiveEdge */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Bypass the clock Sync. */
|
||||
if (config->enableSyncBypass)
|
||||
{
|
||||
tmp32 |= ADC_SEQ_CTRL_SYNCBYPASS_MASK;
|
||||
}
|
||||
|
||||
/* Interrupt point. */
|
||||
switch (config->interruptMode)
|
||||
{
|
||||
case kADC_InterruptForEachSequence:
|
||||
tmp32 |= ADC_SEQ_CTRL_MODE_MASK;
|
||||
break;
|
||||
default: /* kADC_InterruptForEachConversion */
|
||||
break;
|
||||
}
|
||||
|
||||
/* One trigger for a conversion, or for a sequence. */
|
||||
if (config->enableSingleStep)
|
||||
{
|
||||
tmp32 |= ADC_SEQ_CTRL_SINGLESTEP_MASK;
|
||||
}
|
||||
|
||||
base->SEQ_CTRL[1] = tmp32;
|
||||
}
|
||||
|
||||
bool ADC_GetConvSeqAGlobalConversionResult(ADC_Type *base, adc_result_info_t *info)
|
||||
{
|
||||
assert(info != NULL);
|
||||
|
||||
uint32_t tmp32 = base->SEQ_GDAT[0]; /* Read to clear the status. */
|
||||
|
||||
if (0U == (ADC_SEQ_GDAT_DATAVALID_MASK & tmp32))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->result = (tmp32 & ADC_SEQ_GDAT_RESULT_MASK) >> ADC_SEQ_GDAT_RESULT_SHIFT;
|
||||
info->thresholdCompareStatus =
|
||||
(adc_threshold_compare_status_t)((tmp32 & ADC_SEQ_GDAT_THCMPRANGE_MASK) >> ADC_SEQ_GDAT_THCMPRANGE_SHIFT);
|
||||
info->thresholdCorssingStatus =
|
||||
(adc_threshold_crossing_status_t)((tmp32 & ADC_SEQ_GDAT_THCMPCROSS_MASK) >> ADC_SEQ_GDAT_THCMPCROSS_SHIFT);
|
||||
info->channelNumber = (tmp32 & ADC_SEQ_GDAT_CHN_MASK) >> ADC_SEQ_GDAT_CHN_SHIFT;
|
||||
info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ADC_GetConvSeqBGlobalConversionResult(ADC_Type *base, adc_result_info_t *info)
|
||||
{
|
||||
assert(info != NULL);
|
||||
|
||||
uint32_t tmp32 = base->SEQ_GDAT[1]; /* Read to clear the status. */
|
||||
|
||||
if (0U == (ADC_SEQ_GDAT_DATAVALID_MASK & tmp32))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->result = (tmp32 & ADC_SEQ_GDAT_RESULT_MASK) >> ADC_SEQ_GDAT_RESULT_SHIFT;
|
||||
info->thresholdCompareStatus =
|
||||
(adc_threshold_compare_status_t)((tmp32 & ADC_SEQ_GDAT_THCMPRANGE_MASK) >> ADC_SEQ_GDAT_THCMPRANGE_SHIFT);
|
||||
info->thresholdCorssingStatus =
|
||||
(adc_threshold_crossing_status_t)((tmp32 & ADC_SEQ_GDAT_THCMPCROSS_MASK) >> ADC_SEQ_GDAT_THCMPCROSS_SHIFT);
|
||||
info->channelNumber = (tmp32 & ADC_SEQ_GDAT_CHN_MASK) >> ADC_SEQ_GDAT_CHN_SHIFT;
|
||||
info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ADC_GetChannelConversionResult(ADC_Type *base, uint32_t channel, adc_result_info_t *info)
|
||||
{
|
||||
assert(info != NULL);
|
||||
assert(channel < ADC_DAT_COUNT);
|
||||
|
||||
uint32_t tmp32 = base->DAT[channel]; /* Read to clear the status. */
|
||||
|
||||
if (0U == (ADC_DAT_DATAVALID_MASK & tmp32))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->result = (tmp32 & ADC_DAT_RESULT_MASK) >> ADC_DAT_RESULT_SHIFT;
|
||||
info->thresholdCompareStatus =
|
||||
(adc_threshold_compare_status_t)((tmp32 & ADC_DAT_THCMPRANGE_MASK) >> ADC_DAT_THCMPRANGE_SHIFT);
|
||||
info->thresholdCorssingStatus =
|
||||
(adc_threshold_crossing_status_t)((tmp32 & ADC_DAT_THCMPCROSS_MASK) >> ADC_DAT_THCMPCROSS_SHIFT);
|
||||
info->channelNumber = (tmp32 & ADC_DAT_CHANNEL_MASK) >> ADC_DAT_CHANNEL_SHIFT;
|
||||
info->overrunFlag = ((tmp32 & ADC_DAT_OVERRUN_MASK) == ADC_DAT_OVERRUN_MASK);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,664 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __FSL_ADC_H__
|
||||
#define __FSL_ADC_H__
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup lpc_adc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief ADC driver version 1.0.0. */
|
||||
#define LPC_ADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Flags
|
||||
*/
|
||||
enum _adc_status_flags
|
||||
{
|
||||
kADC_ThresholdCompareFlagOnChn0 = 1U << 0U, /*!< Threshold comparison event on Channel 0. */
|
||||
kADC_ThresholdCompareFlagOnChn1 = 1U << 1U, /*!< Threshold comparison event on Channel 1. */
|
||||
kADC_ThresholdCompareFlagOnChn2 = 1U << 2U, /*!< Threshold comparison event on Channel 2. */
|
||||
kADC_ThresholdCompareFlagOnChn3 = 1U << 3U, /*!< Threshold comparison event on Channel 3. */
|
||||
kADC_ThresholdCompareFlagOnChn4 = 1U << 4U, /*!< Threshold comparison event on Channel 4. */
|
||||
kADC_ThresholdCompareFlagOnChn5 = 1U << 5U, /*!< Threshold comparison event on Channel 5. */
|
||||
kADC_ThresholdCompareFlagOnChn6 = 1U << 6U, /*!< Threshold comparison event on Channel 6. */
|
||||
kADC_ThresholdCompareFlagOnChn7 = 1U << 7U, /*!< Threshold comparison event on Channel 7. */
|
||||
kADC_ThresholdCompareFlagOnChn8 = 1U << 8U, /*!< Threshold comparison event on Channel 8. */
|
||||
kADC_ThresholdCompareFlagOnChn9 = 1U << 9U, /*!< Threshold comparison event on Channel 9. */
|
||||
kADC_ThresholdCompareFlagOnChn10 = 1U << 10U, /*!< Threshold comparison event on Channel 10. */
|
||||
kADC_ThresholdCompareFlagOnChn11 = 1U << 11U, /*!< Threshold comparison event on Channel 11. */
|
||||
kADC_OverrunFlagForChn0 =
|
||||
1U << 12U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 0. */
|
||||
kADC_OverrunFlagForChn1 =
|
||||
1U << 13U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 1. */
|
||||
kADC_OverrunFlagForChn2 =
|
||||
1U << 14U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 2. */
|
||||
kADC_OverrunFlagForChn3 =
|
||||
1U << 15U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 3. */
|
||||
kADC_OverrunFlagForChn4 =
|
||||
1U << 16U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 4. */
|
||||
kADC_OverrunFlagForChn5 =
|
||||
1U << 17U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 5. */
|
||||
kADC_OverrunFlagForChn6 =
|
||||
1U << 18U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 6. */
|
||||
kADC_OverrunFlagForChn7 =
|
||||
1U << 19U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 7. */
|
||||
kADC_OverrunFlagForChn8 =
|
||||
1U << 20U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 8. */
|
||||
kADC_OverrunFlagForChn9 =
|
||||
1U << 21U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 9. */
|
||||
kADC_OverrunFlagForChn10 =
|
||||
1U << 22U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 10. */
|
||||
kADC_OverrunFlagForChn11 =
|
||||
1U << 23U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 11. */
|
||||
kADC_GlobalOverrunFlagForSeqA = 1U << 24U, /*!< Mirror the glabal OVERRUN status flag for conversion sequence A. */
|
||||
kADC_GlobalOverrunFlagForSeqB = 1U << 25U, /*!< Mirror the global OVERRUN status flag for conversion sequence B. */
|
||||
kADC_ConvSeqAInterruptFlag = 1U << 28U, /*!< Sequence A interrupt/DMA trigger. */
|
||||
kADC_ConvSeqBInterruptFlag = 1U << 29U, /*!< Sequence B interrupt/DMA trigger. */
|
||||
kADC_ThresholdCompareInterruptFlag = 1U << 30U, /*!< Threshold comparision interrupt flag. */
|
||||
kADC_OverrunInterruptFlag = 1U << 31U, /*!< Overrun interrupt flag. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Interrupts
|
||||
* @note Not all the interrupt options are listed here
|
||||
*/
|
||||
enum _adc_interrupt_enable
|
||||
{
|
||||
kADC_ConvSeqAInterruptEnable = ADC_INTEN_SEQA_INTEN_MASK, /*!< Enable interrupt upon completion of each individual
|
||||
conversion in sequence A, or entire sequence. */
|
||||
kADC_ConvSeqBInterruptEnable = ADC_INTEN_SEQB_INTEN_MASK, /*!< Enable interrupt upon completion of each individual
|
||||
conversion in sequence B, or entire sequence. */
|
||||
kADC_OverrunInterruptEnable = ADC_INTEN_OVR_INTEN_MASK, /*!< Enable the detection of an overrun condition on any of
|
||||
the channel data registers will cause an overrun
|
||||
interrupt/DMA trigger. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Define selection of clock mode.
|
||||
*/
|
||||
typedef enum _adc_clock_mode
|
||||
{
|
||||
kADC_ClockSynchronousMode =
|
||||
0U, /*!< The ADC clock would be derived from the system clock based on "clockDividerNumber". */
|
||||
kADC_ClockAsynchronousMode = 1U, /*!< The ADC clock would be based on the SYSCON block's divider. */
|
||||
} adc_clock_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Define selection of resolution.
|
||||
*/
|
||||
typedef enum _adc_resolution
|
||||
{
|
||||
kADC_Resolution6bit = 0U, /*!< 6-bit resolution. */
|
||||
kADC_Resolution8bit = 1U, /*!< 8-bit resolution. */
|
||||
kADC_Resolution10bit = 2U, /*!< 10-bit resolution. */
|
||||
kADC_Resolution12bit = 3U, /*!< 12-bit resolution. */
|
||||
} adc_resolution_t;
|
||||
|
||||
/*!
|
||||
* @brief Define selection of polarity of selected input trigger for conversion sequence.
|
||||
*/
|
||||
typedef enum _adc_trigger_polarity
|
||||
{
|
||||
kADC_TriggerPolarityNegativeEdge = 0U, /*!< A negative edge launches the conversion sequence on the trigger(s). */
|
||||
kADC_TriggerPolarityPositiveEdge = 1U, /*!< A positive edge launches the conversion sequence on the trigger(s). */
|
||||
} adc_trigger_polarity_t;
|
||||
|
||||
/*!
|
||||
* @brief Define selection of conversion sequence's priority.
|
||||
*/
|
||||
typedef enum _adc_priority
|
||||
{
|
||||
kADC_PriorityLow = 0U, /*!< This sequence would be preempted when another sequence is started. */
|
||||
kADC_PriorityHigh = 1U, /*!< This sequence would preempt other sequence even when is is started. */
|
||||
} adc_priority_t;
|
||||
|
||||
/*!
|
||||
* @brief Define selection of conversion sequence's interrupt.
|
||||
*/
|
||||
typedef enum _adc_seq_interrupt_mode
|
||||
{
|
||||
kADC_InterruptForEachConversion = 0U, /*!< The sequence interrupt/DMA trigger will be set at the end of each
|
||||
individual ADC conversion inside this conversion sequence. */
|
||||
kADC_InterruptForEachSequence = 1U, /*!< The sequence interrupt/DMA trigger will be set when the entire set of
|
||||
this sequence conversions completes. */
|
||||
} adc_seq_interrupt_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Define status of threshold compare result.
|
||||
*/
|
||||
typedef enum _adc_threshold_compare_status
|
||||
{
|
||||
kADC_ThresholdCompareInRange = 0U, /*!< LOW threshold <= conversion value <= HIGH threshold. */
|
||||
kADC_ThresholdCompareBelowRange = 1U, /*!< conversion value < LOW threshold. */
|
||||
kADC_ThresholdCompareAboveRange = 2U, /*!< conversion value > HIGH threshold. */
|
||||
} adc_threshold_compare_status_t;
|
||||
|
||||
/*!
|
||||
* @brief Define status of threshold crossing detection result.
|
||||
*/
|
||||
typedef enum _adc_threshold_crossing_status
|
||||
{
|
||||
/* The conversion on this channel had the same relationship (above or below) to the threshold value established by
|
||||
* the designated LOW threshold value as did the previous conversion on this channel. */
|
||||
kADC_ThresholdCrossingNoDetected = 0U, /*!< No threshold Crossing detected. */
|
||||
|
||||
/* Indicates that a threshold crossing in the downward direction has occurred - i.e. the previous sample on this
|
||||
* channel was above the threshold value established by the designated LOW threshold value and the current sample is
|
||||
* below that threshold. */
|
||||
kADC_ThresholdCrossingDownward = 2U, /*!< Downward Threshold Crossing detected. */
|
||||
|
||||
/* Indicates that a thre shold crossing in the upward direction has occurred - i.e. the previous sample on this
|
||||
* channel was below the threshold value established by the designated LOW threshold value and the current sample is
|
||||
* above that threshold. */
|
||||
kADC_ThresholdCrossingUpward = 3U, /*!< Upward Threshold Crossing Detected. */
|
||||
} adc_threshold_crossing_status_t;
|
||||
|
||||
/*!
|
||||
* @brief Define interrupt mode for threshold compare event.
|
||||
*/
|
||||
typedef enum _adc_threshold_interrupt_mode
|
||||
{
|
||||
kADC_ThresholdInterruptDisabled = 0U, /*!< Threshold comparison interrupt is disabled. */
|
||||
kADC_ThresholdInterruptOnOutside = 1U, /*!< Threshold comparison interrupt is enabled on outside threshold. */
|
||||
kADC_ThresholdInterruptOnCrossing = 2U, /*!< Threshold comparison interrupt is enabled on crossing threshold. */
|
||||
} adc_threshold_interrupt_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief Define structure for configuring the block.
|
||||
*/
|
||||
typedef struct _adc_config
|
||||
{
|
||||
adc_clock_mode_t clockMode; /*!< Select the clock mode for ADC converter. */
|
||||
uint32_t clockDividerNumber; /*!< This field is only available when using kADC_ClockSynchronousMode for "clockMode"
|
||||
field. The divider would be plused by 1 based on the value in this field. The
|
||||
available range is in 8 bits. */
|
||||
adc_resolution_t resolution; /*!< Select the conversion bits. */
|
||||
bool enableBypassCalibration; /*!< By default, a calibration cycle must be performed each time the chip is
|
||||
powered-up. Re-calibration may be warranted periodically - especially if
|
||||
operating conditions have changed. To enable this option would avoid the need to
|
||||
calibrate if offset error is not a concern in the application. */
|
||||
uint32_t sampleTimeNumber; /*!< By default, with value as "0U", the sample period would be 2.5 ADC clocks. Then,
|
||||
to plus the "sampleTimeNumber" value here. The available value range is in 3 bits.*/
|
||||
} adc_config_t;
|
||||
|
||||
/*!
|
||||
* @brief Define structure for configuring conversion sequence.
|
||||
*/
|
||||
typedef struct _adc_conv_seq_config
|
||||
{
|
||||
uint32_t channelMask; /*!< Selects which one or more of the ADC channels will be sampled and converted when this
|
||||
sequence is launched. The masked channels would be involved in current conversion
|
||||
sequence, beginning with the lowest-order. The available range is in 12-bit. */
|
||||
uint32_t triggerMask; /*!< Selects which one or more of the available hardware trigger sources will cause this
|
||||
conversion sequence to be initiated. The available range is 6-bit.*/
|
||||
adc_trigger_polarity_t triggerPolarity; /*!< Select the trigger to lauch conversion sequence. */
|
||||
bool enableSyncBypass; /*!< To enable this feature allows the hardware trigger input to bypass synchronization
|
||||
flip-flop stages and therefore shorten the time between the trigger input signal and the
|
||||
start of a conversion. */
|
||||
bool enableSingleStep; /*!< When enabling this feature, a trigger will launch a single conversion on the next
|
||||
channel in the sequence instead of the default response of launching an entire sequence
|
||||
of conversions. */
|
||||
adc_seq_interrupt_mode_t interruptMode; /*!< Select the interrpt/DMA trigger mode. */
|
||||
} adc_conv_seq_config_t;
|
||||
|
||||
/*!
|
||||
* @brief Define structure of keeping conversion result information.
|
||||
*/
|
||||
typedef struct _adc_result_info
|
||||
{
|
||||
uint32_t result; /*!< Keey the conversion data value. */
|
||||
adc_threshold_compare_status_t thresholdCompareStatus; /*!< Keep the threshold compare status. */
|
||||
adc_threshold_crossing_status_t thresholdCorssingStatus; /*!< Keep the threshold crossing status. */
|
||||
uint32_t channelNumber; /*!< Keep the channel number for this conversion. */
|
||||
bool overrunFlag; /*!< Keep the status whether the conversion is overrun or not. */
|
||||
/* The data available flag would be returned by the reading result API. */
|
||||
} adc_result_info_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @name Initialization and Deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initialize the ADC module.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param config Pointer to configuration structure, see to #adc_config_t.
|
||||
*/
|
||||
void ADC_Init(ADC_Type *base, const adc_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Deinitialize the ADC module.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
*/
|
||||
void ADC_Deinit(ADC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Gets an available pre-defined settings for initial configuration.
|
||||
*
|
||||
* This function initializes the initial configuration structure with an available settings. The default values are:
|
||||
* @code
|
||||
* config->clockMode = kADC_ClockSynchronousMode;
|
||||
* config->clockDividerNumber = 0U;
|
||||
* config->resolution = kADC_Resolution12bit;
|
||||
* config->enableBypassCalibration = false;
|
||||
* config->sampleTimeNumber = 0U;
|
||||
* @endcode
|
||||
* @param config Pointer to configuration structure.
|
||||
*/
|
||||
void ADC_GetDefaultConfig(adc_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Do the self hardware calibration.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @retval true Calibration succeed.
|
||||
* @retval false Calibration failed.
|
||||
*/
|
||||
bool ADC_DoSelfCalibration(ADC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Enable the internal temperature sensor measurement.
|
||||
*
|
||||
* When enabling the internal temperature sensor measurement, the channel 0 would be connected to internal sensor
|
||||
* instead of external pin.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param enable Switcher to enable the feature or not.
|
||||
*/
|
||||
static inline void ADC_EnableTemperatureSensor(ADC_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->INSEL = (base->INSEL & ~ADC_INSEL_SEL_MASK) | ADC_INSEL_SEL(0x3);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->INSEL = (base->INSEL & ~ADC_INSEL_SEL_MASK) | ADC_INSEL_SEL(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Control conversion sequence A.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enable the conversion sequence A.
|
||||
*
|
||||
* In order to avoid spuriously triggering the sequence, the trigger to conversion sequence should be ready before the
|
||||
* sequence is ready. when the sequence is disabled, the trigger would be ignored. Also, it is suggested to disable the
|
||||
* sequence during changing the sequence's setting.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param enable Switcher to enable the feature or not.
|
||||
*/
|
||||
static inline void ADC_EnableConvSeqA(ADC_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->SEQ_CTRL[0] |= ADC_SEQ_CTRL_SEQ_ENA_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->SEQ_CTRL[0] &= ~ADC_SEQ_CTRL_SEQ_ENA_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Configure the conversion sequence A.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param config Pointer to configuration structure, see to #adc_conv_seq_config_t.
|
||||
*/
|
||||
void ADC_SetConvSeqAConfig(ADC_Type *base, const adc_conv_seq_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Do trigger the sequence's conversion by software.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
*/
|
||||
static inline void ADC_DoSoftwareTriggerConvSeqA(ADC_Type *base)
|
||||
{
|
||||
base->SEQ_CTRL[0] |= ADC_SEQ_CTRL_START_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable the burst conversion of sequence A.
|
||||
*
|
||||
* Enable the burst mode would cause the conversion sequence to be cntinuously cycled through. Other triggers would be
|
||||
* ignored while this mode is enabled. Repeated conversions could be halted by disabling this mode. And the sequence
|
||||
* currently in process will be completed before cnversions are terminated.
|
||||
* Note that a new sequence could begin just before the burst mode is disabled.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param enable Switcher to enable this feature.
|
||||
*/
|
||||
static inline void ADC_EnableConvSeqABurstMode(ADC_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->SEQ_CTRL[0] |= ADC_SEQ_CTRL_BURST_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->SEQ_CTRL[0] &= ~ADC_SEQ_CTRL_BURST_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the high priority for conversion sequence A.
|
||||
*
|
||||
* @param base ADC peripheral bass address.
|
||||
*/
|
||||
static inline void ADC_SetConvSeqAHighPriority(ADC_Type *base)
|
||||
{
|
||||
base->SEQ_CTRL[0] |= ADC_SEQ_CTRL_LOWPRIO_MASK;
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Control conversion sequence B.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enable the conversion sequence B.
|
||||
*
|
||||
* In order to avoid spuriously triggering the sequence, the trigger to conversion sequence should be ready before the
|
||||
* sequence is ready. when the sequence is disabled, the trigger would be ignored. Also, it is suggested to disable the
|
||||
* sequence during changing the sequence's setting.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param enable Switcher to enable the feature or not.
|
||||
*/
|
||||
static inline void ADC_EnableConvSeqB(ADC_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->SEQ_CTRL[1] |= ADC_SEQ_CTRL_SEQ_ENA_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->SEQ_CTRL[1] &= ~ADC_SEQ_CTRL_SEQ_ENA_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Configure the conversion sequence B.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param config Pointer to configuration structure, see to #adc_conv_seq_config_t.
|
||||
*/
|
||||
void ADC_SetConvSeqBConfig(ADC_Type *base, const adc_conv_seq_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Do trigger the sequence's conversion by software.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
*/
|
||||
static inline void ADC_DoSoftwareTriggerConvSeqB(ADC_Type *base)
|
||||
{
|
||||
base->SEQ_CTRL[1] |= ADC_SEQ_CTRL_START_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable the burst conversion of sequence B.
|
||||
*
|
||||
* Enable the burst mode would cause the conversion sequence to be continuously cycled through. Other triggers would be
|
||||
* ignored while this mode is enabled. Repeated conversions could be halted by disabling this mode. And the sequence
|
||||
* currently in process will be completed before cnversions are terminated.
|
||||
* Note that a new sequence could begin just before the burst mode is disabled.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param enable Switcher to enable this feature.
|
||||
*/
|
||||
static inline void ADC_EnableConvSeqBBurstMode(ADC_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->SEQ_CTRL[1] |= ADC_SEQ_CTRL_BURST_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->SEQ_CTRL[1] &= ~ADC_SEQ_CTRL_BURST_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the high priority for conversion sequence B.
|
||||
*
|
||||
* @param base ADC peripheral bass address.
|
||||
*/
|
||||
static inline void ADC_SetConvSeqBHighPriority(ADC_Type *base)
|
||||
{
|
||||
base->SEQ_CTRL[0] &= ~ADC_SEQ_CTRL_LOWPRIO_MASK;
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Data result.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get the global ADC conversion infomation of sequence A.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param info Pointer to information structure, see to #adc_result_info_t;
|
||||
* @retval true The conversion result is ready.
|
||||
* @retval false The conversion result is not ready yet.
|
||||
*/
|
||||
bool ADC_GetConvSeqAGlobalConversionResult(ADC_Type *base, adc_result_info_t *info);
|
||||
|
||||
/*!
|
||||
* @brief Get the global ADC conversion infomation of sequence B.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param info Pointer to information structure, see to #adc_result_info_t;
|
||||
* @retval true The conversion result is ready.
|
||||
* @retval false The conversion result is not ready yet.
|
||||
*/
|
||||
bool ADC_GetConvSeqBGlobalConversionResult(ADC_Type *base, adc_result_info_t *info);
|
||||
|
||||
/*!
|
||||
* @brief Get the channel's ADC conversion completed under each conversion sequence.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param channel The indicated channel number.
|
||||
* @param info Pointer to information structure, see to #adc_result_info_t;
|
||||
* @retval true The conversion result is ready.
|
||||
* @retval false The conversion result is not ready yet.
|
||||
*/
|
||||
bool ADC_GetChannelConversionResult(ADC_Type *base, uint32_t channel, adc_result_info_t *info);
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Threshold function.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Set the threshhold pair 0 with low and high value.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param lowValue LOW threshold value.
|
||||
* @param highValue HIGH threshold value.
|
||||
*/
|
||||
static inline void ADC_SetThresholdPair0(ADC_Type *base, uint32_t lowValue, uint32_t highValue)
|
||||
{
|
||||
base->THR0_LOW = ADC_THR0_LOW_THRLOW(lowValue);
|
||||
base->THR0_HIGH = ADC_THR0_HIGH_THRHIGH(highValue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the threshhold pair 1 with low and high value.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param lowValue LOW threshold value. The available value is with 12-bit.
|
||||
* @param highValue HIGH threshold value. The available value is with 12-bit.
|
||||
*/
|
||||
static inline void ADC_SetThresholdPair1(ADC_Type *base, uint32_t lowValue, uint32_t highValue)
|
||||
{
|
||||
base->THR1_LOW = ADC_THR1_LOW_THRLOW(lowValue);
|
||||
base->THR1_HIGH = ADC_THR1_HIGH_THRHIGH(highValue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set given channels to apply the threshold pare 0.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param channelMask Indicated channels' mask.
|
||||
*/
|
||||
static inline void ADC_SetChannelWithThresholdPair0(ADC_Type *base, uint32_t channelMask)
|
||||
{
|
||||
base->CHAN_THRSEL &= ~(channelMask);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set given channels to apply the threshold pare 1.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param channelMask Indicated channels' mask.
|
||||
*/
|
||||
static inline void ADC_SetChannelWithThresholdPair1(ADC_Type *base, uint32_t channelMask)
|
||||
{
|
||||
base->CHAN_THRSEL |= channelMask;
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Interrupts.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enable interrupts for conversion sequences.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param mask Mask of interrupt mask value for global block except each channal, see to #_adc_interrupt_enable.
|
||||
*/
|
||||
static inline void ADC_EnableInterrupts(ADC_Type *base, uint32_t mask)
|
||||
{
|
||||
base->INTEN |= (0x7 & mask);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable interrupts for conversion sequence.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param mask Mask of interrupt mask value for global block except each channel, see to #_adc_interrupt_enable.
|
||||
*/
|
||||
static inline void ADC_DisableInterrupts(ADC_Type *base, uint32_t mask)
|
||||
{
|
||||
base->INTEN &= ~(0x7 & mask);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable the interrupt of shreshold compare event for each channel.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param channel Channel number.
|
||||
* @param mode Interrupt mode for threshold compare event, see to #adc_threshold_interrupt_mode_t.
|
||||
*/
|
||||
static inline void ADC_EnableShresholdCompareInterrupt(ADC_Type *base,
|
||||
uint32_t channel,
|
||||
adc_threshold_interrupt_mode_t mode)
|
||||
{
|
||||
base->INTEN = (base->INTEN & ~(0x3U << ((channel << 1U) + 3U))) | ((uint32_t)(mode) << ((channel << 1U) + 3U));
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Status.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get status flags of ADC module.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @return Mask of status flags of module, see to #_adc_status_flags.
|
||||
*/
|
||||
static inline uint32_t ADC_GetStatusFlags(ADC_Type *base)
|
||||
{
|
||||
return base->FLAGS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear status flags of ADC module.
|
||||
*
|
||||
* @param base ADC peripheral base address.
|
||||
* @param mask Mask of status flags of module, see to #_adc_status_flags.
|
||||
*/
|
||||
static inline void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
|
||||
{
|
||||
base->FLAGS = mask; /* Write 1 to clear. */
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* @} */
|
||||
|
||||
#endif /* __FSL_ADC_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,857 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_CLOCK_H_
|
||||
#define _FSL_CLOCK_H_
|
||||
|
||||
#include "fsl_device_registers.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*! @addtogroup clock */
|
||||
/*! @{ */
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
*****************************************************************************/
|
||||
/*! @brief Clock ip name array for FLEXCOMM. */
|
||||
#define FLEXCOMM_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_FlexComm0, kCLOCK_FlexComm1, kCLOCK_FlexComm2, kCLOCK_FlexComm3, \
|
||||
kCLOCK_FlexComm4, kCLOCK_FlexComm5, kCLOCK_FlexComm6, kCLOCK_FlexComm7 \
|
||||
}
|
||||
/*! @brief Clock ip name array for LPUART. */
|
||||
#define LPUART_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_MinUart0, kCLOCK_MinUart1, kCLOCK_MinUart2, kCLOCK_MinUart3, kCLOCK_MinUart4, kCLOCK_MinUart5, \
|
||||
kCLOCK_MinUart6, kCLOCK_MinUart7 \
|
||||
}
|
||||
|
||||
/*! @brief Clock ip name array for BI2C. */
|
||||
#define BI2C_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_BI2c0, kCLOCK_BI2c1, kCLOCK_BI2c2, kCLOCK_BI2c3, kCLOCK_BI2c4, kCLOCK_BI2c5, kCLOCK_BI2c6, kCLOCK_BI2c7 \
|
||||
}
|
||||
/*! @brief Clock ip name array for LSPI. */
|
||||
#define LPSI_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_LSpi0, kCLOCK_LSpi1, kCLOCK_LSpi2, kCLOCK_LSpi3, kCLOCK_LSpi4, kCLOCK_LSpi5, kCLOCK_LSpi6, kCLOCK_LSpi7 \
|
||||
}
|
||||
/*! @brief Clock ip name array for FLEXI2S. */
|
||||
#define FLEXI2S_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_FlexI2s0, kCLOCK_FlexI2s1, kCLOCK_FlexI2s2, kCLOCK_FlexI2s3, kCLOCK_FlexI2s4, kCLOCK_FlexI2s5, \
|
||||
kCLOCK_FlexI2s6, kCLOCK_FlexI2s7 \
|
||||
}
|
||||
/*! @brief Clock ip name array for UTICK. */
|
||||
#define UTICK_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Utick \
|
||||
}
|
||||
/*! @brief Clock ip name array for DMIC. */
|
||||
#define DMIC_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_DMic \
|
||||
}
|
||||
/*! @brief Clock ip name array for DMA. */
|
||||
#define DMA_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Dma \
|
||||
}
|
||||
/*! @brief Clock ip name array for CT32B. */
|
||||
#define CTIMER_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Ct32b0, kCLOCK_Ct32b1, kCLOCK_Ct32b2, kCLOCK_Ct32b3, kCLOCK_Ct32b4 \
|
||||
}
|
||||
|
||||
/*! @brief Clock ip name array for GPIO. */
|
||||
#define GPIO_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Gpio0, kCLOCK_Gpio1 \
|
||||
}
|
||||
/*! @brief Clock ip name array for ADC. */
|
||||
#define ADC_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Adc0 \
|
||||
}
|
||||
/*! @brief Clock ip name array for MRT. */
|
||||
#define MRT_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Mrt \
|
||||
}
|
||||
/*! @brief Clock ip name array for MRT. */
|
||||
#define SCT_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Sct0 \
|
||||
}
|
||||
/*! @brief Clock ip name array for RTC. */
|
||||
#define RTC_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Rtc \
|
||||
}
|
||||
/*! @brief Clock ip name array for WWDT. */
|
||||
#define WWDT_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Wwdt \
|
||||
}
|
||||
/*! @brief Clock ip name array for CRC. */
|
||||
#define CRC_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Crc \
|
||||
}
|
||||
/*! @brief Clock ip name array for USBD. */
|
||||
#define USBD_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Usbd0 \
|
||||
}
|
||||
|
||||
/*! @brief Clock ip name array for GINT. GINT0 & GINT1 share same slot */
|
||||
#define GINT_CLOCKS \
|
||||
{ \
|
||||
kCLOCK_Gint, kCLOCK_Gint \
|
||||
}
|
||||
|
||||
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
|
||||
/*------------------------------------------------------------------------------
|
||||
clock_ip_name_t definition:
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
#define CLK_GATE_REG_OFFSET_SHIFT 8U
|
||||
#define CLK_GATE_REG_OFFSET_MASK 0xFFFFFF00U
|
||||
#define CLK_GATE_BIT_SHIFT_SHIFT 0U
|
||||
#define CLK_GATE_BIT_SHIFT_MASK 0x000000FFU
|
||||
|
||||
#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) (((uint32_t)(x)&CLK_GATE_REG_OFFSET_MASK) >> CLK_GATE_REG_OFFSET_SHIFT)
|
||||
#define CLK_GATE_ABSTRACT_BITS_SHIFT(x) (((uint32_t)(x)&CLK_GATE_BIT_SHIFT_MASK) >> CLK_GATE_BIT_SHIFT_SHIFT)
|
||||
|
||||
#define AHB_CLK_CTRL0 0
|
||||
#define AHB_CLK_CTRL1 1
|
||||
#define ASYNC_CLK_CTRL0 2
|
||||
|
||||
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
|
||||
typedef enum _clock_ip_name
|
||||
{
|
||||
kCLOCK_IpInvalid = 0U,
|
||||
kCLOCK_Rom = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 1),
|
||||
kCLOCK_Sram1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 3),
|
||||
kCLOCK_Sram2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 4),
|
||||
kCLOCK_Regfile = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 6),
|
||||
kCLOCK_Flash = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 7),
|
||||
kCLOCK_Fmc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 8),
|
||||
kCLOCK_InputMux = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 11),
|
||||
kCLOCK_Iocon = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 13),
|
||||
kCLOCK_Gpio0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 14),
|
||||
kCLOCK_Gpio1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 15),
|
||||
kCLOCK_Gpio2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 16),
|
||||
kCLOCK_Gpio3 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 17),
|
||||
kCLOCK_Pint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 18),
|
||||
kCLOCK_Gint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 19), /* GPIO_GLOBALINT0 and GPIO_GLOBALINT1 share the same slot */
|
||||
kCLOCK_Dma = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 20),
|
||||
kCLOCK_Crc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 21),
|
||||
kCLOCK_Wwdt = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 22),
|
||||
kCLOCK_Rtc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 23),
|
||||
kCLOCK_Mailbox = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 26),
|
||||
kCLOCK_Adc0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 27),
|
||||
kCLOCK_Mrt = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 0),
|
||||
kCLOCK_Sct0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 2),
|
||||
kCLOCK_SctIpu0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 6),
|
||||
kCLOCK_Utick = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 10),
|
||||
kCLOCK_FlexComm0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11),
|
||||
kCLOCK_FlexComm1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12),
|
||||
kCLOCK_FlexComm2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13),
|
||||
kCLOCK_FlexComm3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14),
|
||||
kCLOCK_FlexComm4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15),
|
||||
kCLOCK_FlexComm5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16),
|
||||
kCLOCK_FlexComm6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17),
|
||||
kCLOCK_FlexComm7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18),
|
||||
kCLOCK_MinUart0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11),
|
||||
kCLOCK_MinUart1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12),
|
||||
kCLOCK_MinUart2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13),
|
||||
kCLOCK_MinUart3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14),
|
||||
kCLOCK_MinUart4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15),
|
||||
kCLOCK_MinUart5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16),
|
||||
kCLOCK_MinUart6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17),
|
||||
kCLOCK_MinUart7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18),
|
||||
kCLOCK_LSpi0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11),
|
||||
kCLOCK_LSpi1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12),
|
||||
kCLOCK_LSpi2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13),
|
||||
kCLOCK_LSpi3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14),
|
||||
kCLOCK_LSpi4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15),
|
||||
kCLOCK_LSpi5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16),
|
||||
kCLOCK_LSpi6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17),
|
||||
kCLOCK_LSpi7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18),
|
||||
kCLOCK_BI2c0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11),
|
||||
kCLOCK_BI2c1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12),
|
||||
kCLOCK_BI2c2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13),
|
||||
kCLOCK_BI2c3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14),
|
||||
kCLOCK_BI2c4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15),
|
||||
kCLOCK_BI2c5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16),
|
||||
kCLOCK_BI2c6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17),
|
||||
kCLOCK_BI2c7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18),
|
||||
kCLOCK_FlexI2s0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11),
|
||||
kCLOCK_FlexI2s1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12),
|
||||
kCLOCK_FlexI2s2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13),
|
||||
kCLOCK_FlexI2s3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14),
|
||||
kCLOCK_FlexI2s4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15),
|
||||
kCLOCK_FlexI2s5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16),
|
||||
kCLOCK_FlexI2s6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17),
|
||||
kCLOCK_FlexI2s7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18),
|
||||
kCLOCK_DMic = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 19),
|
||||
kCLOCK_Ct32b2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 22),
|
||||
kCLOCK_Usbd0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 25),
|
||||
kCLOCK_Ct32b0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 26),
|
||||
kCLOCK_Ct32b1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 27),
|
||||
kCLOCK_Pvtvf0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 28),
|
||||
kCLOCK_Pvtvf1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 28),
|
||||
kCLOCK_BodyBias0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 29),
|
||||
kCLOCK_EzhArchB0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 31),
|
||||
|
||||
kCLOCK_Ct32b3 = CLK_GATE_DEFINE(ASYNC_CLK_CTRL0, 13),
|
||||
kCLOCK_Ct32b4 = CLK_GATE_DEFINE(ASYNC_CLK_CTRL0, 14)
|
||||
} clock_ip_name_t;
|
||||
|
||||
/*! @brief Clock name used to get clock frequency. */
|
||||
typedef enum _clock_name
|
||||
{
|
||||
kCLOCK_CoreSysClk, /*!< Core/system clock (aka MAIN_CLK) */
|
||||
kCLOCK_BusClk, /*!< Bus clock (AHB clock) */
|
||||
kCLOCK_FroHf, /*!< FRO48/96 */
|
||||
kCLOCK_Fro12M, /*!< FRO12M */
|
||||
kCLOCK_ExtClk, /*!< External Clock */
|
||||
kCLOCK_PllOut, /*!< PLL Output */
|
||||
kCLOCK_UsbClk, /*!< USB input */
|
||||
kClock_WdtOsc, /*!< Watchdog Oscillator */
|
||||
kCLOCK_Frg, /*!< Frg Clock */
|
||||
kCLOCK_Dmic, /*!< Digital Mic clock */
|
||||
kCLOCK_AsyncApbClk, /*!< Async APB clock */
|
||||
kCLOCK_FlexI2S, /*!< FlexI2S clock */
|
||||
kCLOCK_Flexcomm0, /*!< Flexcomm0Clock */
|
||||
kCLOCK_Flexcomm1, /*!< Flexcomm1Clock */
|
||||
kCLOCK_Flexcomm2, /*!< Flexcomm2Clock */
|
||||
kCLOCK_Flexcomm3, /*!< Flexcomm3Clock */
|
||||
kCLOCK_Flexcomm4, /*!< Flexcomm4Clock */
|
||||
kCLOCK_Flexcomm5, /*!< Flexcomm5Clock */
|
||||
kCLOCK_Flexcomm6, /*!< Flexcomm6Clock */
|
||||
kCLOCK_Flexcomm7, /*!< Flexcomm7Clock */
|
||||
} clock_name_t;
|
||||
|
||||
/**
|
||||
* Clock source selections for the asynchronous APB clock
|
||||
*/
|
||||
typedef enum _async_clock_src
|
||||
{
|
||||
kCLOCK_AsyncMainClk = 0, /*!< Main System clock */
|
||||
kCLOCK_AsyncFro12Mhz, /*!< 12MHz FRO */
|
||||
} async_clock_src_t;
|
||||
|
||||
/*! @brief Clock Mux Switches
|
||||
* The encoding is as follows each connection identified is 64bits wide
|
||||
* starting from LSB upwards
|
||||
*
|
||||
* [4 bits for choice, where 1 is A, 2 is B, 3 is C and 4 is D, 0 means end of descriptor] [8 bits mux ID]*
|
||||
*
|
||||
*/
|
||||
|
||||
#define MUX_A(m, choice) (((m) << 0) | ((choice + 1) << 8))
|
||||
#define MUX_B(m, choice) (((m) << 12) | ((choice + 1) << 20))
|
||||
#define MUX_C(m, choice) (((m) << 24) | ((choice + 1) << 32))
|
||||
#define MUX_D(m, choice) (((m) << 36) | ((choice + 1) << 44))
|
||||
#define MUX_E(m, choice) (((m) << 48) | ((choice + 1) << 56))
|
||||
|
||||
#define CM_MAINCLKSELA 0
|
||||
#define CM_MAINCLKSELB 1
|
||||
#define CM_CLKOUTCLKSELA 2
|
||||
#define CM_CLKOUTCLKSELB 3
|
||||
#define CM_SYSPLLCLKSEL 4
|
||||
#define CM_USBPLLCLKSEL 5
|
||||
#define CM_AUDPLLCLKSEL 6
|
||||
#define CM_SCTPLLCLKSEL 7
|
||||
#define CM_SPIFICLKSEL 8
|
||||
#define CM_ADCASYNCCLKSEL 9
|
||||
#define CM_USBCLKSEL 10
|
||||
#define CM_USB1CLKSEL 11
|
||||
#define CM_FXCOMCLKSEL0 12
|
||||
#define CM_FXCOMCLKSEL1 13
|
||||
#define CM_FXCOMCLKSEL2 14
|
||||
#define CM_FXCOMCLKSEL3 15
|
||||
#define CM_FXCOMCLKSEL4 16
|
||||
#define CM_FXCOMCLKSEL5 17
|
||||
#define CM_FXCOMCLKSEL6 18
|
||||
#define CM_FXCOMCLKSEL7 19
|
||||
#define CM_FXCOMCLKSEL8 20
|
||||
#define CM_FXCOMCLKSEL9 21
|
||||
#define CM_FXCOMCLKSEL10 22
|
||||
#define CM_FXCOMCLKSEL11 23
|
||||
#define CM_FXI2S0MCLKCLKSEL 24
|
||||
#define CM_FXI2S1MCLKCLKSEL 25
|
||||
#define CM_FRGCLKSEL 26
|
||||
#define CM_DMICCLKSEL 27
|
||||
|
||||
#define CM_ASYNCAPB 28
|
||||
|
||||
typedef enum _clock_attach_id
|
||||
{
|
||||
|
||||
kFRO12M_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 0),
|
||||
kEXT_CLK_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 1) | MUX_B(CM_MAINCLKSELB, 0),
|
||||
kWDT_OSC_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 2) | MUX_B(CM_MAINCLKSELB, 0),
|
||||
kFRO_HF_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 3) | MUX_B(CM_MAINCLKSELB, 0),
|
||||
kSYS_PLL_to_MAIN_CLK = MUX_A(CM_MAINCLKSELB, 2),
|
||||
kOSC32K_to_MAIN_CLK = MUX_A(CM_MAINCLKSELB, 3),
|
||||
|
||||
kFRO12M_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 0),
|
||||
kEXT_CLK_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 1),
|
||||
kWDT_OSC_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 2),
|
||||
kOSC32K_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 3),
|
||||
kNONE_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 7),
|
||||
|
||||
kMAIN_CLK_to_ASYNC_APB = MUX_A(CM_ASYNCAPB, 0),
|
||||
kFRO12M_to_ASYNC_APB = MUX_A(CM_ASYNCAPB, 1),
|
||||
|
||||
kMAIN_CLK_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 0),
|
||||
kSYS_PLL_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 1),
|
||||
kFRO_HF_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 2),
|
||||
kNONE_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 7),
|
||||
|
||||
kMAIN_CLK_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 0),
|
||||
kSYS_PLL_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 1),
|
||||
kFRO_HF_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 3),
|
||||
kNONE_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 0),
|
||||
kFRO_HF_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 1),
|
||||
kSYS_PLL_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 2),
|
||||
kMCLK_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 3),
|
||||
kFRG_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 4),
|
||||
kNONE_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 0),
|
||||
kFRO_HF_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 1),
|
||||
kSYS_PLL_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 2),
|
||||
kMCLK_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 3),
|
||||
kFRG_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 4),
|
||||
kNONE_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 0),
|
||||
kFRO_HF_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 1),
|
||||
kSYS_PLL_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 2),
|
||||
kMCLK_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 3),
|
||||
kFRG_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 4),
|
||||
kNONE_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 0),
|
||||
kFRO_HF_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 1),
|
||||
kSYS_PLL_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 2),
|
||||
kMCLK_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 3),
|
||||
kFRG_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 4),
|
||||
kNONE_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 0),
|
||||
kFRO_HF_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 1),
|
||||
kSYS_PLL_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 2),
|
||||
kMCLK_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 3),
|
||||
kFRG_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 4),
|
||||
kNONE_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 0),
|
||||
kFRO_HF_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 1),
|
||||
kSYS_PLL_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 2),
|
||||
kMCLK_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 3),
|
||||
kFRG_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 4),
|
||||
kNONE_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 0),
|
||||
kFRO_HF_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 1),
|
||||
kSYS_PLL_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 2),
|
||||
kMCLK_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 3),
|
||||
kFRG_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 4),
|
||||
kNONE_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 7),
|
||||
|
||||
kFRO12M_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 0),
|
||||
kFRO_HF_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 1),
|
||||
kSYS_PLL_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 2),
|
||||
kMCLK_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 3),
|
||||
kFRG_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 4),
|
||||
kNONE_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 7),
|
||||
|
||||
kMAIN_CLK_to_FRG = MUX_A(CM_FRGCLKSEL, 0),
|
||||
kSYS_PLL_to_FRG = MUX_A(CM_FRGCLKSEL, 1),
|
||||
kFRO12M_to_FRG = MUX_A(CM_FRGCLKSEL, 2),
|
||||
kFRO_HF_to_FRG = MUX_A(CM_FRGCLKSEL, 3),
|
||||
kNONE_to_FRG = MUX_A(CM_FRGCLKSEL, 7),
|
||||
|
||||
kFRO_HF_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 0),
|
||||
kSYS_PLL_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 1),
|
||||
kNONE_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 7),
|
||||
|
||||
kFRO12M_to_DMIC = MUX_A(CM_DMICCLKSEL, 0),
|
||||
kFRO_HF_to_DMIC = MUX_A(CM_DMICCLKSEL, 1),
|
||||
kSYS_PLL_to_DMIC = MUX_A(CM_DMICCLKSEL, 2),
|
||||
kMCLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 3),
|
||||
kMAIN_CLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 4),
|
||||
kWDT_CLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 5),
|
||||
kNONE_to_DMIC = MUX_A(CM_DMICCLKSEL, 7),
|
||||
|
||||
kFRO_HF_to_USB_CLK = MUX_A(CM_USBCLKSEL, 0),
|
||||
kSYS_PLL_to_USB_CLK = MUX_A(CM_USBCLKSEL, 1),
|
||||
kNONE_to_USB_CLK = MUX_A(CM_USBCLKSEL, 7),
|
||||
|
||||
kMAIN_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 0),
|
||||
kEXT_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 1),
|
||||
kWDT_OSC_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 2),
|
||||
kFRO_HF_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 3),
|
||||
kSYS_PLL_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 4),
|
||||
kFRO12M_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 5),
|
||||
kOSC32K_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 6),
|
||||
kNONE_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 7),
|
||||
kNONE_to_NONE = 0x80000000U,
|
||||
} clock_attach_id_t;
|
||||
|
||||
/* Clock dividers */
|
||||
typedef enum _clock_div_name
|
||||
{
|
||||
kCLOCK_DivSystickClk = 0,
|
||||
kCLOCK_DivTraceClk = 1,
|
||||
kCLOCK_DivAhbClk = 32,
|
||||
kCLOCK_DivClkOut = 33,
|
||||
kCLOCK_DivSpifiClk = 36,
|
||||
kCLOCK_DivAdcAsyncClk = 37,
|
||||
kCLOCK_DivUsbClk = 38,
|
||||
kCLOCK_DivFrg = 40,
|
||||
kCLOCK_DivDmicClk = 42,
|
||||
kCLOCK_DivFxI2s0MClk = 43
|
||||
} clock_div_name_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
static inline void CLOCK_EnableClock(clock_ip_name_t clk)
|
||||
{
|
||||
uint32_t index = CLK_GATE_ABSTRACT_REG_OFFSET(clk);
|
||||
if (index < 2)
|
||||
{
|
||||
SYSCON->AHBCLKCTRLSET[index] = (1U << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
|
||||
}
|
||||
else
|
||||
{
|
||||
ASYNC_SYSCON->ASYNCAPBCLKCTRLSET = (1U << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void CLOCK_DisableClock(clock_ip_name_t clk)
|
||||
{
|
||||
uint32_t index = CLK_GATE_ABSTRACT_REG_OFFSET(clk);
|
||||
if (index < 2)
|
||||
{
|
||||
SYSCON->AHBCLKCTRLCLR[index] = (1U << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
|
||||
}
|
||||
else
|
||||
{
|
||||
ASYNC_SYSCON->ASYNCAPBCLKCTRLCLR = (1U << CLK_GATE_ABSTRACT_BITS_SHIFT(clk));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief FLASH Access time definitions
|
||||
*/
|
||||
typedef enum _clock_flashtim
|
||||
{
|
||||
kCLOCK_Flash1Cycle = 0, /*!< Flash accesses use 1 CPU clock */
|
||||
kCLOCK_Flash2Cycle, /*!< Flash accesses use 2 CPU clocks */
|
||||
kCLOCK_Flash3Cycle, /*!< Flash accesses use 3 CPU clocks */
|
||||
kCLOCK_Flash4Cycle, /*!< Flash accesses use 4 CPU clocks */
|
||||
kCLOCK_Flash5Cycle, /*!< Flash accesses use 5 CPU clocks */
|
||||
kCLOCK_Flash6Cycle, /*!< Flash accesses use 6 CPU clocks */
|
||||
kCLOCK_Flash7Cycle, /*!< Flash accesses use 7 CPU clocks */
|
||||
kCLOCK_Flash8Cycle /*!< Flash accesses use 8 CPU clocks */
|
||||
} clock_flashtim_t;
|
||||
|
||||
/**
|
||||
* @brief Set FLASH memory access time in clocks
|
||||
* @param clks : Clock cycles for FLASH access
|
||||
* @return Nothing
|
||||
*/
|
||||
static inline void CLOCK_SetFLASHAccessCycles(clock_flashtim_t clks)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = SYSCON->FLASHCFG & ~(SYSCON_FLASHCFG_FLASHTIM_MASK);
|
||||
|
||||
/* Don't alter lower bits */
|
||||
SYSCON->FLASHCFG = tmp | ((uint32_t)clks << SYSCON_FLASHCFG_FLASHTIM_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
|
||||
* Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
|
||||
* enabled.
|
||||
* @param iFreq : Desired frequency (must be one of CLK_FRO_12MHZ or CLK_FRO_48MHZ or CLK_FRO_96MHZ)
|
||||
* @return returns success or fail status.
|
||||
*/
|
||||
status_t CLOCK_SetupFROClocking(uint32_t iFreq);
|
||||
/**
|
||||
* @brief Configure the clock selection muxes.
|
||||
* @param connection : Clock to be configured.
|
||||
* @return Nothing
|
||||
*/
|
||||
void CLOCK_AttachClk(clock_attach_id_t connection);
|
||||
/**
|
||||
* @brief Setup peripheral clock dividers.
|
||||
* @param div_name : Clock divider name
|
||||
* @param divided_by_value: Value to be divided
|
||||
* @param reset : Whether to reset the divider counter.
|
||||
* @return Nothing
|
||||
*/
|
||||
void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset);
|
||||
/**
|
||||
* @brief Set the flash wait states for the input freuqency.
|
||||
* @param iFreq : Input frequency
|
||||
* @return Nothing
|
||||
*/
|
||||
void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq);
|
||||
/*! @brief Return Frequency of selected clock
|
||||
* @return Frequency of selected clock
|
||||
*/
|
||||
uint32_t CLOCK_GetFreq(clock_name_t clockName);
|
||||
|
||||
/*! @brief Return Input frequency for the Fractional baud rate generator
|
||||
* @return Input Frequency for FRG
|
||||
*/
|
||||
uint32_t CLOCK_GetFRGInputClock(void);
|
||||
|
||||
/*! @brief Set output of the Fractional baud rate generator
|
||||
* @param freq : Desired output frequency
|
||||
* @return Error Code 0 - fail 1 - success
|
||||
*/
|
||||
uint32_t CLOCK_SetFRGClock(uint32_t freq);
|
||||
|
||||
/*! @brief Return Frequency of FRO 12MHz
|
||||
* @return Frequency of FRO 12MHz
|
||||
*/
|
||||
uint32_t CLOCK_GetFro12MFreq(void);
|
||||
/*! @brief Return Frequency of External Clock
|
||||
* @return Frequency of External Clock. If no external clock is used returns 0.
|
||||
*/
|
||||
uint32_t CLOCK_GetExtClkFreq(void);
|
||||
/*! @brief Return Frequency of Watchdog Oscillator
|
||||
* @return Frequency of Watchdog Oscillator
|
||||
*/
|
||||
uint32_t CLOCK_GetWdtOscFreq(void);
|
||||
/*! @brief Return Frequency of High-Freq output of FRO
|
||||
* @return Frequency of High-Freq output of FRO
|
||||
*/
|
||||
uint32_t CLOCK_GetFroHfFreq(void);
|
||||
/*! @brief Return Frequency of PLL
|
||||
* @return Frequency of PLL
|
||||
*/
|
||||
uint32_t CLOCK_GetPllOutFreq(void);
|
||||
/*! @brief Return Frequency of 32kHz osc
|
||||
* @return Frequency of 32kHz osc
|
||||
*/
|
||||
uint32_t CLOCK_GetOsc32KFreq(void);
|
||||
/*! @brief Return Frequency of Core System
|
||||
* @return Frequency of Core System
|
||||
*/
|
||||
uint32_t CLOCK_GetCoreSysClkFreq(void);
|
||||
/*! @brief Return Frequency of I2S MCLK Clock
|
||||
* @return Frequency of I2S MCLK Clock
|
||||
*/
|
||||
uint32_t CLOCK_GetI2SMClkFreq(void);
|
||||
/*! @brief Return Frequency of Flexcomm functional Clock
|
||||
* @return Frequency of Flexcomm functional Clock
|
||||
*/
|
||||
uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id);
|
||||
/*! @brief Return Asynchronous APB Clock source
|
||||
* @return Asynchronous APB CLock source
|
||||
*/
|
||||
__STATIC_INLINE async_clock_src_t CLOCK_GetAsyncApbClkSrc(void)
|
||||
{
|
||||
return (async_clock_src_t)(ASYNC_SYSCON->ASYNCAPBCLKSELA & 0x3);
|
||||
}
|
||||
/*! @brief Return Frequency of Asynchronous APB Clock
|
||||
* @return Frequency of Asynchronous APB Clock Clock
|
||||
*/
|
||||
uint32_t CLOCK_GetAsyncApbClkFreq(void);
|
||||
/*! @brief Return System PLL input clock rate
|
||||
* @return System PLL input clock rate
|
||||
*/
|
||||
uint32_t CLOCK_GetSystemPLLInClockRate(void);
|
||||
|
||||
/*! @brief Return System PLL output clock rate
|
||||
* @param recompute : Forces a PLL rate recomputation if true
|
||||
* @return System PLL output clock rate
|
||||
* @note The PLL rate is cached in the driver in a variable as
|
||||
* the rate computation function can take some time to perform. It
|
||||
* is recommended to use 'false' with the 'recompute' parameter.
|
||||
*/
|
||||
uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute);
|
||||
|
||||
/*! @brief Enables and disables PLL bypass mode
|
||||
* @brief bypass : true to bypass PLL (PLL output = PLL input, false to disable bypass
|
||||
* @return System PLL output clock rate
|
||||
*/
|
||||
__STATIC_INLINE void CLOCK_SetBypassPLL(bool bypass)
|
||||
{
|
||||
if (bypass)
|
||||
{
|
||||
SYSCON->SYSPLLCTRL |= (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
SYSCON->SYSPLLCTRL &= ~(1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
/*! @brief Check if PLL is locked or not
|
||||
* @return true if the PLL is locked, false if not locked
|
||||
*/
|
||||
__STATIC_INLINE bool CLOCK_IsSystemPLLLocked(void)
|
||||
{
|
||||
return (bool)((SYSCON->SYSPLLSTAT & SYSCON_SYSPLLSTAT_LOCK_MASK) != 0);
|
||||
}
|
||||
|
||||
/*! @brief Store the current PLL rate
|
||||
* @param rate: Current rate of the PLL
|
||||
* @return Nothing
|
||||
**/
|
||||
void CLOCK_SetStoredPLLClockRate(uint32_t rate);
|
||||
|
||||
/*! @brief PLL configuration structure flags for 'flags' field
|
||||
* These flags control how the PLL configuration function sets up the PLL setup structure.<br>
|
||||
*
|
||||
* When the PLL_CONFIGFLAG_USEINRATE flag is selected, the 'InputRate' field in the
|
||||
* configuration structure must be assigned with the expected PLL frequency. If the
|
||||
* PLL_CONFIGFLAG_USEINRATE is not used, 'InputRate' is ignored in the configuration
|
||||
* function and the driver will determine the PLL rate from the currently selected
|
||||
* PLL source. This flag might be used to configure the PLL input clock more accurately
|
||||
* when using the WDT oscillator or a more dyanmic CLKIN source.<br>
|
||||
*
|
||||
* When the PLL_CONFIGFLAG_FORCENOFRACT flag is selected, the PLL hardware for the
|
||||
* automatic bandwidth selection, Spread Spectrum (SS) support, and fractional M-divider
|
||||
* are not used.<br>
|
||||
*/
|
||||
#define PLL_CONFIGFLAG_USEINRATE (1 << 0) /*!< Flag to use InputRate in PLL configuration structure for setup */
|
||||
#define PLL_CONFIGFLAG_FORCENOFRACT \
|
||||
(1 \
|
||||
<< 2) /*!< Force non-fractional output mode, PLL output will not use the fractional, automatic bandwidth, or SS \ \
|
||||
\ \ \ \
|
||||
\ \ \ \ \ \
|
||||
\ \ \ \ \ \ \ \
|
||||
hardware */
|
||||
|
||||
/*! @brief PLL Spread Spectrum (SS) Programmable modulation frequency
|
||||
* See (MF) field in the SYSPLLSSCTRL1 register in the UM.
|
||||
*/
|
||||
typedef enum _ss_progmodfm
|
||||
{
|
||||
kSS_MF_512 = (0 << 20), /*!< Nss = 512 (fm ? 3.9 - 7.8 kHz) */
|
||||
kSS_MF_384 = (1 << 20), /*!< Nss ?= 384 (fm ? 5.2 - 10.4 kHz) */
|
||||
kSS_MF_256 = (2 << 20), /*!< Nss = 256 (fm ? 7.8 - 15.6 kHz) */
|
||||
kSS_MF_128 = (3 << 20), /*!< Nss = 128 (fm ? 15.6 - 31.3 kHz) */
|
||||
kSS_MF_64 = (4 << 20), /*!< Nss = 64 (fm ? 32.3 - 64.5 kHz) */
|
||||
kSS_MF_32 = (5 << 20), /*!< Nss = 32 (fm ? 62.5- 125 kHz) */
|
||||
kSS_MF_24 = (6 << 20), /*!< Nss ?= 24 (fm ? 83.3- 166.6 kHz) */
|
||||
kSS_MF_16 = (7 << 20) /*!< Nss = 16 (fm ? 125- 250 kHz) */
|
||||
} ss_progmodfm_t;
|
||||
|
||||
/*! @brief PLL Spread Spectrum (SS) Programmable frequency modulation depth
|
||||
* See (MR) field in the SYSPLLSSCTRL1 register in the UM.
|
||||
*/
|
||||
typedef enum _ss_progmoddp
|
||||
{
|
||||
kSS_MR_K0 = (0 << 23), /*!< k = 0 (no spread spectrum) */
|
||||
kSS_MR_K1 = (1 << 23), /*!< k = 1 */
|
||||
kSS_MR_K1_5 = (2 << 23), /*!< k = 1.5 */
|
||||
kSS_MR_K2 = (3 << 23), /*!< k = 2 */
|
||||
kSS_MR_K3 = (4 << 23), /*!< k = 3 */
|
||||
kSS_MR_K4 = (5 << 23), /*!< k = 4 */
|
||||
kSS_MR_K6 = (6 << 23), /*!< k = 6 */
|
||||
kSS_MR_K8 = (7 << 23) /*!< k = 8 */
|
||||
} ss_progmoddp_t;
|
||||
|
||||
/*! @brief PLL Spread Spectrum (SS) Modulation waveform control
|
||||
* See (MC) field in the SYSPLLSSCTRL1 register in the UM.<br>
|
||||
* Compensation for low pass filtering of the PLL to get a triangular
|
||||
* modulation at the output of the PLL, giving a flat frequency spectrum.
|
||||
*/
|
||||
typedef enum _ss_modwvctrl
|
||||
{
|
||||
kSS_MC_NOC = (0 << 26), /*!< no compensation */
|
||||
kSS_MC_RECC = (2 << 26), /*!< recommended setting */
|
||||
kSS_MC_MAXC = (3 << 26), /*!< max. compensation */
|
||||
} ss_modwvctrl_t;
|
||||
|
||||
/*! @brief PLL configuration structure
|
||||
*
|
||||
* This structure can be used to configure the settings for a PLL
|
||||
* setup structure. Fill in the desired configuration for the PLL
|
||||
* and call the PLL setup function to fill in a PLL setup structure.
|
||||
*/
|
||||
typedef struct _pll_config
|
||||
{
|
||||
uint32_t desiredRate; /*!< Desired PLL rate in Hz */
|
||||
uint32_t inputRate; /*!< PLL input clock in Hz, only used if PLL_CONFIGFLAG_USEINRATE flag is set */
|
||||
uint32_t flags; /*!< PLL configuration flags, Or'ed value of PLL_CONFIGFLAG_* definitions */
|
||||
ss_progmodfm_t ss_mf; /*!< SS Programmable modulation frequency, only applicable when not using
|
||||
PLL_CONFIGFLAG_FORCENOFRACT flag */
|
||||
ss_progmoddp_t ss_mr; /*!< SS Programmable frequency modulation depth, only applicable when not using
|
||||
PLL_CONFIGFLAG_FORCENOFRACT flag */
|
||||
ss_modwvctrl_t
|
||||
ss_mc; /*!< SS Modulation waveform control, only applicable when not using PLL_CONFIGFLAG_FORCENOFRACT flag */
|
||||
bool mfDither; /*!< false for fixed modulation frequency or true for dithering, only applicable when not using
|
||||
PLL_CONFIGFLAG_FORCENOFRACT flag */
|
||||
|
||||
} pll_config_t;
|
||||
|
||||
/*! @brief PLL setup structure flags for 'flags' field
|
||||
* These flags control how the PLL setup function sets up the PLL
|
||||
*/
|
||||
#define PLL_SETUPFLAG_POWERUP (1 << 0) /*!< Setup will power on the PLL after setup */
|
||||
#define PLL_SETUPFLAG_WAITLOCK (1 << 1) /*!< Setup will wait for PLL lock, implies the PLL will be pwoered on */
|
||||
#define PLL_SETUPFLAG_ADGVOLT (1 << 2) /*!< Optimize system voltage for the new PLL rate */
|
||||
|
||||
/*! @brief PLL setup structure
|
||||
* This structure can be used to pre-build a PLL setup configuration
|
||||
* at run-time and quickly set the PLL to the configuration. It can be
|
||||
* populated with the PLL setup function. If powering up or waiting
|
||||
* for PLL lock, the PLL input clock source should be configured prior
|
||||
* to PLL setup.
|
||||
*/
|
||||
typedef struct _pll_setup
|
||||
{
|
||||
uint32_t syspllctrl; /*!< PLL control register SYSPLLCTRL */
|
||||
uint32_t syspllndec; /*!< PLL NDEC register SYSPLLNDEC */
|
||||
uint32_t syspllpdec; /*!< PLL PDEC register SYSPLLPDEC */
|
||||
uint32_t syspllssctrl[2]; /*!< PLL SSCTL registers SYSPLLSSCTRL */
|
||||
uint32_t pllRate; /*!< Acutal PLL rate */
|
||||
uint32_t flags; /*!< PLL setup flags, Or'ed value of PLL_SETUPFLAG_* definitions */
|
||||
} pll_setup_t;
|
||||
|
||||
/*! @brief PLL status definitions
|
||||
*/
|
||||
typedef enum _pll_error
|
||||
{
|
||||
kStatus_PLL_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< PLL operation was successful */
|
||||
kStatus_PLL_OutputTooLow = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< PLL output rate request was too low */
|
||||
kStatus_PLL_OutputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< PLL output rate request was too high */
|
||||
kStatus_PLL_InputTooLow = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< PLL input rate is too low */
|
||||
kStatus_PLL_InputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< PLL input rate is too high */
|
||||
kStatus_PLL_OutsideIntLimit = MAKE_STATUS(kStatusGroup_Generic, 5) /*!< Requested output rate isn't possible */
|
||||
} pll_error_t;
|
||||
|
||||
/*! @brief USB clock source definition. */
|
||||
typedef enum _clock_usb_src
|
||||
{
|
||||
kCLOCK_UsbSrcFro = (uint32_t)kCLOCK_FroHf, /*!< Use FRO 96 or 48 MHz. */
|
||||
kCLOCK_UsbSrcSystemPll = (uint32_t)kCLOCK_PllOut, /*!< Use System PLL output. */
|
||||
kCLOCK_UsbSrcMainClock = (uint32_t)kCLOCK_CoreSysClk, /*!< Use Main clock. */
|
||||
kCLOCK_UsbSrcNone = SYSCON_USBCLKSEL_SEL(
|
||||
7) /*!< Use None, this may be selected in order to reduce power when no output is needed. */
|
||||
} clock_usb_src_t;
|
||||
|
||||
/*! @brief Return System PLL output clock rate from setup structure
|
||||
* @param pSetup : Pointer to a PLL setup structure
|
||||
* @return System PLL output clock rate calculated from the setup structure
|
||||
*/
|
||||
uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup);
|
||||
|
||||
/*! @brief Set PLL output based on the passed PLL setup data
|
||||
* @param pControl : Pointer to populated PLL control structure to generate setup with
|
||||
* @param pSetup : Pointer to PLL setup structure to be filled
|
||||
* @return PLL_ERROR_SUCCESS on success, or PLL setup error code
|
||||
* @note Actual frequency for setup may vary from the desired frequency based on the
|
||||
* accuracy of input clocks, rounding, non-fractional PLL mode, etc.
|
||||
*/
|
||||
pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup);
|
||||
|
||||
/*! @brief Set PLL output from PLL setup structure (precise frequency)
|
||||
* @param pSetup : Pointer to populated PLL setup structure
|
||||
* @param flagcfg : Flag configuration for PLL config structure
|
||||
* @return PLL_ERROR_SUCCESS on success, or PLL setup error code
|
||||
* @note This function will power off the PLL, setup the PLL with the
|
||||
* new setup data, and then optionally powerup the PLL, wait for PLL lock,
|
||||
* and adjust system voltages to the new PLL rate. The function will not
|
||||
* alter any source clocks (ie, main systen clock) that may use the PLL,
|
||||
* so these should be setup prior to and after exiting the function.
|
||||
*/
|
||||
pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg);
|
||||
|
||||
/**
|
||||
* @brief Set PLL output from PLL setup structure (precise frequency)
|
||||
* @param pSetup : Pointer to populated PLL setup structure
|
||||
* @return kStatus_PLL_Success on success, or PLL setup error code
|
||||
* @note This function will power off the PLL, setup the PLL with the
|
||||
* new setup data, and then optionally powerup the PLL, wait for PLL lock,
|
||||
* and adjust system voltages to the new PLL rate. The function will not
|
||||
* alter any source clocks (ie, main systen clock) that may use the PLL,
|
||||
* so these should be setup prior to and after exiting the function.
|
||||
*/
|
||||
pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup);
|
||||
|
||||
/*! @brief Set PLL output based on the multiplier and input frequency
|
||||
* @param multiply_by : multiplier
|
||||
* @param input_freq : Clock input frequency of the PLL
|
||||
* @return Nothing
|
||||
* @note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
|
||||
* function does not disable or enable PLL power, wait for PLL lock,
|
||||
* or adjust system voltages. These must be done in the application.
|
||||
* The function will not alter any source clocks (ie, main systen clock)
|
||||
* that may use the PLL, so these should be setup prior to and after
|
||||
* exiting the function.
|
||||
*/
|
||||
void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq);
|
||||
|
||||
/*! @brief Disable USB FS clock.
|
||||
*
|
||||
* Disable USB FS clock.
|
||||
*/
|
||||
static inline void CLOCK_DisableUsbfs0Clock(void)
|
||||
{
|
||||
CLOCK_DisableClock(kCLOCK_Usbd0);
|
||||
}
|
||||
bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq);
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _FSL_CLOCK_H_ */
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
#ifndef CPU_QN908X
|
||||
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
|
||||
|
||||
void EnableDeepSleepIRQ(IRQn_Type interrupt)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
uint32_t intNumber = (uint32_t)interrupt;
|
||||
while (intNumber >= 32u)
|
||||
{
|
||||
index++;
|
||||
intNumber -= 32u;
|
||||
}
|
||||
|
||||
SYSCON->STARTERSET[index] = 1u << intNumber;
|
||||
EnableIRQ(interrupt); /* also enable interrupt at NVIC */
|
||||
}
|
||||
|
||||
void DisableDeepSleepIRQ(IRQn_Type interrupt)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
uint32_t intNumber = (uint32_t)interrupt;
|
||||
while (intNumber >= 32u)
|
||||
{
|
||||
index++;
|
||||
intNumber -= 32u;
|
||||
}
|
||||
|
||||
DisableIRQ(interrupt); /* also disable interrupt at NVIC */
|
||||
SYSCON->STARTERCLR[index] = 1u << intNumber;
|
||||
}
|
||||
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
|
||||
#else
|
||||
void EnableDeepSleepIRQ(IRQn_Type interrupt)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
uint32_t intNumber = (uint32_t)interrupt;
|
||||
while (intNumber >= 32u)
|
||||
{
|
||||
index++;
|
||||
intNumber -= 32u;
|
||||
}
|
||||
|
||||
/* SYSCON->STARTERSET[index] = 1u << intNumber; */
|
||||
EnableIRQ(interrupt); /* also enable interrupt at NVIC */
|
||||
}
|
||||
|
||||
void DisableDeepSleepIRQ(IRQn_Type interrupt)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
uint32_t intNumber = (uint32_t)interrupt;
|
||||
while (intNumber >= 32u)
|
||||
{
|
||||
index++;
|
||||
intNumber -= 32u;
|
||||
}
|
||||
|
||||
DisableIRQ(interrupt); /* also disable interrupt at NVIC */
|
||||
/* SYSCON->STARTERCLR[index] = 1u << intNumber; */
|
||||
}
|
||||
#endif /*CPU_QN908X */
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
|
||||
#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
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* 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. */
|
||||
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< 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_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
|
||||
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
|
||||
kStatusGroup_I2S = 27, /*!< Group number for 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_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
|
||||
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
|
||||
kStatusGroup_DMIC = 58, /*!< Group number for DMIC 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"
|
||||
|
||||
/*
|
||||
* Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
|
||||
*/
|
||||
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
|
||||
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
|
||||
#include "fsl_reset.h"
|
||||
#endif
|
||||
|
||||
/*! @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 (NotAvail_IRQn == interrupt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#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 (NotAvail_IRQn == interrupt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#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(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
|
||||
/*!
|
||||
* @brief Enable specific interrupt for wake-up from deep-sleep mode.
|
||||
*
|
||||
* Enable the interrupt for wake-up from deep sleep mode.
|
||||
* Some interrupts are typically used in sleep mode only and will not occur during
|
||||
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
|
||||
* those clocks (significantly increasing power consumption in the reduced power mode),
|
||||
* making these wake-ups possible.
|
||||
*
|
||||
* @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally).
|
||||
*
|
||||
* @param interrupt The IRQ number.
|
||||
*/
|
||||
void EnableDeepSleepIRQ(IRQn_Type interrupt);
|
||||
|
||||
/*!
|
||||
* @brief Disable specific interrupt for wake-up from deep-sleep mode.
|
||||
*
|
||||
* Disable the interrupt for wake-up from deep sleep mode.
|
||||
* Some interrupts are typically used in sleep mode only and will not occur during
|
||||
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
|
||||
* those clocks (significantly increasing power consumption in the reduced power mode),
|
||||
* making these wake-ups possible.
|
||||
*
|
||||
* @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally).
|
||||
*
|
||||
* @param interrupt The IRQ number.
|
||||
*/
|
||||
void DisableDeepSleepIRQ(IRQn_Type interrupt);
|
||||
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _FSL_COMMON_H_ */
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
#include "fsl_crc.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(CRC_DRIVER_USE_CRC16_CCITT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCITT_FALSE_AS_DEFAULT
|
||||
/* @brief Default user configuration structure for CRC-CCITT */
|
||||
#define CRC_DRIVER_DEFAULT_POLYNOMIAL kCRC_Polynomial_CRC_CCITT
|
||||
/*< CRC-CCIT polynomial x^16 + x^12 + x^5 + x^0 */
|
||||
#define CRC_DRIVER_DEFAULT_REVERSE_IN false
|
||||
/*< Default is no bit reverse */
|
||||
#define CRC_DRIVER_DEFAULT_COMPLEMENT_IN false
|
||||
/*< Default is without complement of written data */
|
||||
#define CRC_DRIVER_DEFAULT_REVERSE_OUT false
|
||||
/*< Default is no bit reverse */
|
||||
#define CRC_DRIVER_DEFAULT_COMPLEMENT_OUT false
|
||||
/*< Default is without complement of CRC data register read data */
|
||||
#define CRC_DRIVER_DEFAULT_SEED 0xFFFFU
|
||||
/*< Default initial checksum */
|
||||
#endif /* CRC_DRIVER_USE_CRC16_CCITT_FALSE_AS_DEFAULT */
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void CRC_Init(CRC_Type *base, const crc_config_t *config)
|
||||
{
|
||||
/* enable clock to CRC */
|
||||
CLOCK_EnableClock(kCLOCK_Crc);
|
||||
|
||||
/* configure CRC module and write the seed */
|
||||
base->MODE = 0 | CRC_MODE_CRC_POLY(config->polynomial) | CRC_MODE_BIT_RVS_WR(config->reverseIn) |
|
||||
CRC_MODE_CMPL_WR(config->complementIn) | CRC_MODE_BIT_RVS_SUM(config->reverseOut) |
|
||||
CRC_MODE_CMPL_SUM(config->complementOut);
|
||||
base->SEED = config->seed;
|
||||
}
|
||||
|
||||
void CRC_GetDefaultConfig(crc_config_t *config)
|
||||
{
|
||||
static const crc_config_t default_config = {CRC_DRIVER_DEFAULT_POLYNOMIAL, CRC_DRIVER_DEFAULT_REVERSE_IN,
|
||||
CRC_DRIVER_DEFAULT_COMPLEMENT_IN, CRC_DRIVER_DEFAULT_REVERSE_OUT,
|
||||
CRC_DRIVER_DEFAULT_COMPLEMENT_OUT, CRC_DRIVER_DEFAULT_SEED};
|
||||
|
||||
*config = default_config;
|
||||
}
|
||||
|
||||
void CRC_Reset(CRC_Type *base)
|
||||
{
|
||||
/* TODO - HW reset currently not exposed in API and they don't want
|
||||
* dependencies to other modules anyway, so use SW reset temporarily. */
|
||||
|
||||
/* SYSCON_PeriphReset(RESET_CRC); */
|
||||
|
||||
crc_config_t config;
|
||||
CRC_GetDefaultConfig(&config);
|
||||
CRC_Init(base, &config);
|
||||
}
|
||||
|
||||
void CRC_GetConfig(CRC_Type *base, crc_config_t *config)
|
||||
{
|
||||
/* extract CRC mode settings */
|
||||
uint32_t mode = base->MODE;
|
||||
config->polynomial = (crc_polynomial_t)((mode & CRC_MODE_CRC_POLY_MASK) >> CRC_MODE_CRC_POLY_SHIFT);
|
||||
config->reverseIn = (bool)(mode & CRC_MODE_BIT_RVS_WR_MASK);
|
||||
config->complementIn = (bool)(mode & CRC_MODE_CMPL_WR_MASK);
|
||||
config->reverseOut = (bool)(mode & CRC_MODE_BIT_RVS_SUM_MASK);
|
||||
config->complementOut = (bool)(mode & CRC_MODE_CMPL_SUM_MASK);
|
||||
|
||||
/* reset CRC sum bit reverse and 1's complement setting, so its value can be used as a seed */
|
||||
base->MODE = mode & ~((1U << CRC_MODE_BIT_RVS_SUM_SHIFT) | (1U << CRC_MODE_CMPL_SUM_SHIFT));
|
||||
|
||||
/* now we can obtain intermediate raw CRC sum value */
|
||||
config->seed = base->SUM;
|
||||
|
||||
/* restore original CRC sum bit reverse and 1's complement setting */
|
||||
base->MODE = mode;
|
||||
}
|
||||
|
||||
void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize)
|
||||
{
|
||||
const uint32_t *data32;
|
||||
|
||||
/* 8-bit reads and writes till source address is aligned 4 bytes */
|
||||
while ((dataSize) && ((uint32_t)data & 3U))
|
||||
{
|
||||
*((__O uint8_t *)&(base->WR_DATA)) = *data;
|
||||
data++;
|
||||
dataSize--;
|
||||
}
|
||||
|
||||
/* use 32-bit reads and writes as long as possible */
|
||||
data32 = (const uint32_t *)data;
|
||||
while (dataSize >= sizeof(uint32_t))
|
||||
{
|
||||
base->WR_DATA = *data32;
|
||||
data32++;
|
||||
dataSize -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
data = (const uint8_t *)data32;
|
||||
|
||||
/* 8-bit reads and writes till end of data buffer */
|
||||
while (dataSize)
|
||||
{
|
||||
*((__O uint8_t *)&(base->WR_DATA)) = *data;
|
||||
data++;
|
||||
dataSize--;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_CRC_H_
|
||||
#define _FSL_CRC_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup crc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief CRC driver version. Version 2.0.0.
|
||||
*
|
||||
* Current version: 2.0.0
|
||||
*
|
||||
* Change log:
|
||||
* - Version 2.0.0
|
||||
* - initial version
|
||||
*/
|
||||
#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
#ifndef CRC_DRIVER_CUSTOM_DEFAULTS
|
||||
/*! @brief Default configuration structure filled by CRC_GetDefaultConfig(). Uses CRC-16/CCITT-FALSE as default. */
|
||||
#define CRC_DRIVER_USE_CRC16_CCITT_FALSE_AS_DEFAULT 1
|
||||
#endif
|
||||
|
||||
/*! @brief CRC polynomials to use. */
|
||||
typedef enum _crc_polynomial
|
||||
{
|
||||
kCRC_Polynomial_CRC_CCITT = 0U, /*!< x^16+x^12+x^5+1 */
|
||||
kCRC_Polynomial_CRC_16 = 1U, /*!< x^16+x^15+x^2+1 */
|
||||
kCRC_Polynomial_CRC_32 = 2U /*!< x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */
|
||||
} crc_polynomial_t;
|
||||
|
||||
/*!
|
||||
* @brief CRC protocol configuration.
|
||||
*
|
||||
* This structure holds the configuration for the CRC protocol.
|
||||
*
|
||||
*/
|
||||
typedef struct _crc_config
|
||||
{
|
||||
crc_polynomial_t polynomial; /*!< CRC polynomial. */
|
||||
bool reverseIn; /*!< Reverse bits on input. */
|
||||
bool complementIn; /*!< Perform 1's complement on input. */
|
||||
bool reverseOut; /*!< Reverse bits on output. */
|
||||
bool complementOut; /*!< Perform 1's complement on output. */
|
||||
uint32_t seed; /*!< Starting checksum value. */
|
||||
} crc_config_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Enables and configures the CRC peripheral module.
|
||||
*
|
||||
* This functions enables the CRC peripheral clock in the LPC SYSCON block.
|
||||
* It also configures the CRC engine and starts checksum computation by writing the seed.
|
||||
*
|
||||
* @param base CRC peripheral address.
|
||||
* @param config CRC module configuration structure.
|
||||
*/
|
||||
void CRC_Init(CRC_Type *base, const crc_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Disables the CRC peripheral module.
|
||||
*
|
||||
* This functions disables the CRC peripheral clock in the LPC SYSCON block.
|
||||
*
|
||||
* @param base CRC peripheral address.
|
||||
*/
|
||||
static inline void CRC_Deinit(CRC_Type *base)
|
||||
{
|
||||
/* disable clock to CRC */
|
||||
CLOCK_DisableClock(kCLOCK_Crc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief resets CRC peripheral module.
|
||||
*
|
||||
* @param base CRC peripheral address, currently not used.
|
||||
*/
|
||||
void CRC_Reset(CRC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Loads default values to CRC protocol configuration structure.
|
||||
*
|
||||
* Loads default values to CRC protocol configuration structure. The default values are:
|
||||
* @code
|
||||
* config->polynomial = kCRC_Polynomial_CRC_CCITT;
|
||||
* config->reverseIn = false;
|
||||
* config->complementIn = false;
|
||||
* config->reverseOut = false;
|
||||
* config->complementOut = false;
|
||||
* config->seed = 0xFFFFU;
|
||||
* @endcode
|
||||
*
|
||||
* @param config CRC protocol configuration structure
|
||||
*/
|
||||
void CRC_GetDefaultConfig(crc_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Loads actual values configured in CRC peripheral to CRC protocol configuration structure.
|
||||
*
|
||||
* The values, including seed, can be used to resume CRC calculation later.
|
||||
|
||||
* @param base CRC peripheral address.
|
||||
* @param config CRC protocol configuration structure
|
||||
*/
|
||||
void CRC_GetConfig(CRC_Type *base, crc_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Writes data to the CRC module.
|
||||
*
|
||||
* Writes input data buffer bytes to CRC data register.
|
||||
*
|
||||
* @param base CRC peripheral address.
|
||||
* @param data Input data stream, MSByte in data[0].
|
||||
* @param dataSize Size of the input data buffer in bytes.
|
||||
*/
|
||||
void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize);
|
||||
|
||||
/*!
|
||||
* @brief Reads 32-bit checksum from the CRC module.
|
||||
*
|
||||
* Reads CRC data register.
|
||||
*
|
||||
* @param base CRC peripheral address.
|
||||
* @return final 32-bit checksum, after configured bit reverse and complement operations.
|
||||
*/
|
||||
static inline uint32_t CRC_Get32bitResult(CRC_Type *base)
|
||||
{
|
||||
return base->SUM;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads 16-bit checksum from the CRC module.
|
||||
*
|
||||
* Reads CRC data register.
|
||||
*
|
||||
* @param base CRC peripheral address.
|
||||
* @return final 16-bit checksum, after configured bit reverse and complement operations.
|
||||
*/
|
||||
static inline uint16_t CRC_Get16bitResult(CRC_Type *base)
|
||||
{
|
||||
return (uint16_t)base->SUM;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
*@}
|
||||
*/
|
||||
|
||||
#endif /* _FSL_CRC_H_ */
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_ctimer.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Gets the instance from the base address
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*
|
||||
* @return The Timer instance
|
||||
*/
|
||||
static uint32_t CTIMER_GetInstance(CTIMER_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief Pointers to Timer bases for each instance. */
|
||||
static CTIMER_Type *const s_ctimerBases[] = CTIMER_BASE_PTRS;
|
||||
|
||||
/*! @brief Pointers to Timer clocks for each instance. */
|
||||
static const clock_ip_name_t s_ctimerClocks[] = CTIMER_CLOCKS;
|
||||
|
||||
/*! @brief Pointers to Timer resets for each instance. */
|
||||
static const reset_ip_name_t s_ctimerResets[] = CTIMER_RSTS;
|
||||
|
||||
/*! @brief Pointers real ISRs installed by drivers for each instance. */
|
||||
static ctimer_callback_t *s_ctimerCallback[FSL_FEATURE_SOC_CTIMER_COUNT] = {0};
|
||||
|
||||
/*! @brief Callback type installed by drivers for each instance. */
|
||||
static ctimer_callback_type_t ctimerCallbackType[FSL_FEATURE_SOC_CTIMER_COUNT] = {kCTIMER_SingleCallback};
|
||||
|
||||
/*! @brief Array to map timer instance to IRQ number. */
|
||||
static const IRQn_Type s_ctimerIRQ[] = CTIMER_IRQS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static uint32_t CTIMER_GetInstance(CTIMER_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
uint32_t ctimerArrayCount = (sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0]));
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < ctimerArrayCount; instance++)
|
||||
{
|
||||
if (s_ctimerBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < ctimerArrayCount);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void CTIMER_Init(CTIMER_Type *base, const ctimer_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
/* Enable the timer clock*/
|
||||
CLOCK_EnableClock(s_ctimerClocks[CTIMER_GetInstance(base)]);
|
||||
|
||||
/* Reset the module */
|
||||
RESET_PeripheralReset(s_ctimerResets[CTIMER_GetInstance(base)]);
|
||||
|
||||
/* Setup the cimer mode and count select */
|
||||
base->CTCR = CTIMER_CTCR_CTMODE(config->mode) | CTIMER_CTCR_CINSEL(config->input);
|
||||
|
||||
/* Setup the timer prescale value */
|
||||
base->PR = CTIMER_PR_PRVAL(config->prescale);
|
||||
}
|
||||
|
||||
void CTIMER_Deinit(CTIMER_Type *base)
|
||||
{
|
||||
uint32_t index = CTIMER_GetInstance(base);
|
||||
/* Stop the timer */
|
||||
base->TCR &= ~CTIMER_TCR_CEN_MASK;
|
||||
|
||||
/* Disable the timer clock*/
|
||||
CLOCK_DisableClock(s_ctimerClocks[index]);
|
||||
|
||||
/* Disable IRQ at NVIC Level */
|
||||
DisableIRQ(s_ctimerIRQ[index]);
|
||||
}
|
||||
|
||||
void CTIMER_GetDefaultConfig(ctimer_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
/* Run as a timer */
|
||||
config->mode = kCTIMER_TimerMode;
|
||||
/* This field is ignored when mode is timer */
|
||||
config->input = kCTIMER_Capture_0;
|
||||
/* Timer counter is incremented on every APB bus clock */
|
||||
config->prescale = 0;
|
||||
}
|
||||
|
||||
status_t CTIMER_SetupPwm(CTIMER_Type *base,
|
||||
ctimer_match_t matchChannel,
|
||||
uint8_t dutyCyclePercent,
|
||||
uint32_t pwmFreq_Hz,
|
||||
uint32_t srcClock_Hz,
|
||||
bool enableInt)
|
||||
{
|
||||
assert(pwmFreq_Hz > 0);
|
||||
|
||||
uint32_t reg;
|
||||
uint32_t period, pulsePeriod = 0;
|
||||
uint32_t timerClock = srcClock_Hz / (base->PR + 1);
|
||||
uint32_t index = CTIMER_GetInstance(base);
|
||||
|
||||
if (matchChannel == kCTIMER_Match_3)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* Enable PWM mode on the channel */
|
||||
base->PWMC |= (1U << matchChannel);
|
||||
|
||||
/* Clear the stop, reset and interrupt bits for this channel */
|
||||
reg = base->MCR;
|
||||
reg &= ~((CTIMER_MCR_MR0R_MASK | CTIMER_MCR_MR0S_MASK | CTIMER_MCR_MR0I_MASK) << (matchChannel * 3));
|
||||
|
||||
/* If call back function is valid then enable match interrupt for the channel */
|
||||
if (enableInt)
|
||||
{
|
||||
reg |= (CTIMER_MCR_MR0I_MASK << (CTIMER_MCR_MR0I_SHIFT + (matchChannel * 3)));
|
||||
}
|
||||
|
||||
/* Reset the counter when match on channel 3 */
|
||||
reg |= CTIMER_MCR_MR3R_MASK;
|
||||
|
||||
base->MCR = reg;
|
||||
|
||||
/* Calculate PWM period match value */
|
||||
period = (timerClock / pwmFreq_Hz) - 1;
|
||||
|
||||
/* Calculate pulse width match value */
|
||||
if (dutyCyclePercent == 0)
|
||||
{
|
||||
pulsePeriod = period + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulsePeriod = (period * (100 - dutyCyclePercent)) / 100;
|
||||
}
|
||||
|
||||
/* Match on channel 3 will define the PWM period */
|
||||
base->MR[kCTIMER_Match_3] = period;
|
||||
|
||||
/* This will define the PWM pulse period */
|
||||
base->MR[matchChannel] = pulsePeriod;
|
||||
/* Clear status flags */
|
||||
CTIMER_ClearStatusFlags(base, CTIMER_IR_MR0INT_MASK << matchChannel);
|
||||
/* If call back function is valid then enable interrupt and update the call back function */
|
||||
if (enableInt)
|
||||
{
|
||||
EnableIRQ(s_ctimerIRQ[index]);
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void CTIMER_UpdatePwmDutycycle(CTIMER_Type *base, ctimer_match_t matchChannel, uint8_t dutyCyclePercent)
|
||||
{
|
||||
uint32_t pulsePeriod = 0, period;
|
||||
|
||||
/* Match channel 3 defines the PWM period */
|
||||
period = base->MR[kCTIMER_Match_3];
|
||||
|
||||
/* Calculate pulse width match value */
|
||||
pulsePeriod = (period * dutyCyclePercent) / 100;
|
||||
|
||||
/* For 0% dutycyle, make pulse period greater than period so the event will never occur */
|
||||
if (dutyCyclePercent == 0)
|
||||
{
|
||||
pulsePeriod = period + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulsePeriod = (period * (100 - dutyCyclePercent)) / 100;
|
||||
}
|
||||
|
||||
/* Update dutycycle */
|
||||
base->MR[matchChannel] = pulsePeriod;
|
||||
}
|
||||
|
||||
void CTIMER_SetupMatch(CTIMER_Type *base, ctimer_match_t matchChannel, const ctimer_match_config_t *config)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t index = CTIMER_GetInstance(base);
|
||||
|
||||
/* Set the counter operation when a match on this channel occurs */
|
||||
reg = base->MCR;
|
||||
reg &= ~((CTIMER_MCR_MR0R_MASK | CTIMER_MCR_MR0S_MASK | CTIMER_MCR_MR0I_MASK) << (matchChannel * 3));
|
||||
reg |= (uint32_t)((uint32_t)(config->enableCounterReset) << (CTIMER_MCR_MR0R_SHIFT + (matchChannel * 3)));
|
||||
reg |= (uint32_t)((uint32_t)(config->enableCounterStop) << (CTIMER_MCR_MR0S_SHIFT + (matchChannel * 3)));
|
||||
reg |= (uint32_t)((uint32_t)(config->enableInterrupt) << (CTIMER_MCR_MR0I_SHIFT + (matchChannel * 3)));
|
||||
base->MCR = reg;
|
||||
|
||||
reg = base->EMR;
|
||||
/* Set the match output operation when a match on this channel occurs */
|
||||
reg &= ~(CTIMER_EMR_EMC0_MASK << (matchChannel * 2));
|
||||
reg |= (uint32_t)config->outControl << (CTIMER_EMR_EMC0_SHIFT + (matchChannel * 2));
|
||||
|
||||
/* Set the initial state of the EM bit/output */
|
||||
reg &= ~(CTIMER_EMR_EM0_MASK << matchChannel);
|
||||
reg |= (uint32_t)config->outPinInitState << matchChannel;
|
||||
base->EMR = reg;
|
||||
|
||||
/* Set the match value */
|
||||
base->MR[matchChannel] = config->matchValue;
|
||||
/* Clear status flags */
|
||||
CTIMER_ClearStatusFlags(base, CTIMER_IR_MR0INT_MASK << matchChannel);
|
||||
/* If interrupt is enabled then enable interrupt and update the call back function */
|
||||
if (config->enableInterrupt)
|
||||
{
|
||||
EnableIRQ(s_ctimerIRQ[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void CTIMER_SetupCapture(CTIMER_Type *base,
|
||||
ctimer_capture_channel_t capture,
|
||||
ctimer_capture_edge_t edge,
|
||||
bool enableInt)
|
||||
{
|
||||
uint32_t reg = base->CCR;
|
||||
uint32_t index = CTIMER_GetInstance(base);
|
||||
|
||||
/* Set the capture edge */
|
||||
reg &= ~((CTIMER_CCR_CAP0RE_MASK | CTIMER_CCR_CAP0FE_MASK | CTIMER_CCR_CAP0I_MASK) << (capture * 3));
|
||||
reg |= (uint32_t)edge << (CTIMER_CCR_CAP0RE_SHIFT + (capture * 3));
|
||||
/* Clear status flags */
|
||||
CTIMER_ClearStatusFlags(base, (kCTIMER_Capture0Flag << capture));
|
||||
/* If call back function is valid then enable capture interrupt for the channel and update the call back function */
|
||||
if (enableInt)
|
||||
{
|
||||
reg |= CTIMER_CCR_CAP0I_MASK << (capture * 3);
|
||||
EnableIRQ(s_ctimerIRQ[index]);
|
||||
}
|
||||
base->CCR = reg;
|
||||
}
|
||||
|
||||
void CTIMER_RegisterCallBack(CTIMER_Type *base, ctimer_callback_t *cb_func, ctimer_callback_type_t cb_type)
|
||||
{
|
||||
uint32_t index = CTIMER_GetInstance(base);
|
||||
s_ctimerCallback[index] = cb_func;
|
||||
ctimerCallbackType[index] = cb_type;
|
||||
}
|
||||
|
||||
void CTIMER_GenericIRQHandler(uint32_t index)
|
||||
{
|
||||
uint32_t int_stat, i, mask;
|
||||
/* Get Interrupt status flags */
|
||||
int_stat = CTIMER_GetStatusFlags(s_ctimerBases[index]);
|
||||
/* Clear the status flags that were set */
|
||||
CTIMER_ClearStatusFlags(s_ctimerBases[index], int_stat);
|
||||
if (ctimerCallbackType[index] == kCTIMER_SingleCallback)
|
||||
{
|
||||
if (s_ctimerCallback[index][0])
|
||||
{
|
||||
s_ctimerCallback[index][0](int_stat);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i <= CTIMER_IR_CR3INT_SHIFT; i++)
|
||||
{
|
||||
mask = 0x01 << i;
|
||||
/* For each status flag bit that was set call the callback function if it is valid */
|
||||
if ((int_stat & mask) && (s_ctimerCallback[index][i]))
|
||||
{
|
||||
s_ctimerCallback[index][i](int_stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (FSL_FEATURE_SOC_CTIMER_COUNT > 0U)
|
||||
/* IRQ handler functions overloading weak symbols in the startup */
|
||||
void CTIMER0_DriverIRQHandler(void)
|
||||
{
|
||||
CTIMER_GenericIRQHandler(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_CTIMER_COUNT > 1U)
|
||||
void CTIMER1_DriverIRQHandler(void)
|
||||
{
|
||||
CTIMER_GenericIRQHandler(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_CTIMER_COUNT > 2U)
|
||||
void CTIMER2_DriverIRQHandler(void)
|
||||
{
|
||||
CTIMER_GenericIRQHandler(2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_CTIMER_COUNT > 3U)
|
||||
void CTIMER3_DriverIRQHandler(void)
|
||||
{
|
||||
CTIMER_GenericIRQHandler(3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_CTIMER_COUNT > 4U)
|
||||
void CTIMER4_DriverIRQHandler(void)
|
||||
{
|
||||
CTIMER_GenericIRQHandler(4);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,434 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_CTIMER_H_
|
||||
#define _FSL_CTIMER_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup ctimer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
#define FSL_CTIMER_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
|
||||
/*@}*/
|
||||
|
||||
/*! @brief List of Timer capture channels */
|
||||
typedef enum _ctimer_capture_channel
|
||||
{
|
||||
kCTIMER_Capture_0 = 0U, /*!< Timer capture channel 0 */
|
||||
kCTIMER_Capture_1, /*!< Timer capture channel 1 */
|
||||
kCTIMER_Capture_2, /*!< Timer capture channel 2 */
|
||||
kCTIMER_Capture_3 /*!< Timer capture channel 3 */
|
||||
} ctimer_capture_channel_t;
|
||||
|
||||
/*! @brief List of capture edge options */
|
||||
typedef enum _ctimer_capture_edge
|
||||
{
|
||||
kCTIMER_Capture_RiseEdge = 1U, /*!< Capture on rising edge */
|
||||
kCTIMER_Capture_FallEdge = 2U, /*!< Capture on falling edge */
|
||||
kCTIMER_Capture_BothEdge = 3U, /*!< Capture on rising and falling edge */
|
||||
} ctimer_capture_edge_t;
|
||||
|
||||
/*! @brief List of Timer match registers */
|
||||
typedef enum _ctimer_match
|
||||
{
|
||||
kCTIMER_Match_0 = 0U, /*!< Timer match register 0 */
|
||||
kCTIMER_Match_1, /*!< Timer match register 1 */
|
||||
kCTIMER_Match_2, /*!< Timer match register 2 */
|
||||
kCTIMER_Match_3 /*!< Timer match register 3 */
|
||||
} ctimer_match_t;
|
||||
|
||||
/*! @brief List of output control options */
|
||||
typedef enum _ctimer_match_output_control
|
||||
{
|
||||
kCTIMER_Output_NoAction = 0U, /*!< No action is taken */
|
||||
kCTIMER_Output_Clear, /*!< Clear the EM bit/output to 0 */
|
||||
kCTIMER_Output_Set, /*!< Set the EM bit/output to 1 */
|
||||
kCTIMER_Output_Toggle /*!< Toggle the EM bit/output */
|
||||
} ctimer_match_output_control_t;
|
||||
|
||||
/*! @brief List of Timer modes */
|
||||
typedef enum _ctimer_timer_mode
|
||||
{
|
||||
kCTIMER_TimerMode = 0U, /* TC is incremented every rising APB bus clock edge */
|
||||
kCTIMER_IncreaseOnRiseEdge, /* TC is incremented on rising edge of input signal */
|
||||
kCTIMER_IncreaseOnFallEdge, /* TC is incremented on falling edge of input signal */
|
||||
kCTIMER_IncreaseOnBothEdge /* TC is incremented on both edges of input signal */
|
||||
} ctimer_timer_mode_t;
|
||||
|
||||
/*! @brief List of Timer interrupts */
|
||||
typedef enum _ctimer_interrupt_enable
|
||||
{
|
||||
kCTIMER_Match0InterruptEnable = CTIMER_MCR_MR0I_MASK, /*!< Match 0 interrupt */
|
||||
kCTIMER_Match1InterruptEnable = CTIMER_MCR_MR1I_MASK, /*!< Match 1 interrupt */
|
||||
kCTIMER_Match2InterruptEnable = CTIMER_MCR_MR2I_MASK, /*!< Match 2 interrupt */
|
||||
kCTIMER_Match3InterruptEnable = CTIMER_MCR_MR3I_MASK, /*!< Match 3 interrupt */
|
||||
kCTIMER_Capture0InterruptEnable = CTIMER_CCR_CAP0I_MASK, /*!< Capture 0 interrupt */
|
||||
kCTIMER_Capture1InterruptEnable = CTIMER_CCR_CAP1I_MASK, /*!< Capture 1 interrupt */
|
||||
kCTIMER_Capture2InterruptEnable = CTIMER_CCR_CAP2I_MASK, /*!< Capture 2 interrupt */
|
||||
kCTIMER_Capture3InterruptEnable = CTIMER_CCR_CAP3I_MASK, /*!< Capture 3 interrupt */
|
||||
} ctimer_interrupt_enable_t;
|
||||
|
||||
/*! @brief List of Timer flags */
|
||||
typedef enum _ctimer_status_flags
|
||||
{
|
||||
kCTIMER_Match0Flag = CTIMER_IR_MR0INT_MASK, /*!< Match 0 interrupt flag */
|
||||
kCTIMER_Match1Flag = CTIMER_IR_MR1INT_MASK, /*!< Match 1 interrupt flag */
|
||||
kCTIMER_Match2Flag = CTIMER_IR_MR2INT_MASK, /*!< Match 2 interrupt flag */
|
||||
kCTIMER_Match3Flag = CTIMER_IR_MR3INT_MASK, /*!< Match 3 interrupt flag */
|
||||
kCTIMER_Capture0Flag = CTIMER_IR_CR0INT_MASK, /*!< Capture 0 interrupt flag */
|
||||
kCTIMER_Capture1Flag = CTIMER_IR_CR1INT_MASK, /*!< Capture 1 interrupt flag */
|
||||
kCTIMER_Capture2Flag = CTIMER_IR_CR2INT_MASK, /*!< Capture 2 interrupt flag */
|
||||
kCTIMER_Capture3Flag = CTIMER_IR_CR3INT_MASK, /*!< Capture 3 interrupt flag */
|
||||
} ctimer_status_flags_t;
|
||||
|
||||
typedef void (*ctimer_callback_t)(uint32_t flags);
|
||||
|
||||
/*! @brief Callback type when registering for a callback. When registering a callback
|
||||
* an array of function pointers is passed the size could be 1 or 8, the callback
|
||||
* type will tell that.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
kCTIMER_SingleCallback, /*!< Single Callback type where there is only one callback for the timer.
|
||||
based on the status flags different channels needs to be handled differently */
|
||||
kCTIMER_MultipleCallback /*!< Multiple Callback type where there can be 8 valid callbacks, one per channel.
|
||||
for both match/capture */
|
||||
} ctimer_callback_type_t;
|
||||
|
||||
/*!
|
||||
* @brief Match configuration
|
||||
*
|
||||
* This structure holds the configuration settings for each match register.
|
||||
*/
|
||||
typedef struct _ctimer_match_config
|
||||
{
|
||||
uint32_t matchValue; /*!< This is stored in the match register */
|
||||
bool enableCounterReset; /*!< true: Match will reset the counter
|
||||
false: Match will not reser the counter */
|
||||
bool enableCounterStop; /*!< true: Match will stop the counter
|
||||
false: Match will not stop the counter */
|
||||
ctimer_match_output_control_t outControl; /*!< Action to be taken on a match on the EM bit/output */
|
||||
bool outPinInitState; /*!< Initial value of the EM bit/output */
|
||||
bool enableInterrupt; /*!< true: Generate interrupt upon match
|
||||
false: Do not generate interrupt on match */
|
||||
|
||||
} ctimer_match_config_t;
|
||||
|
||||
/*!
|
||||
* @brief Timer configuration structure
|
||||
*
|
||||
* This structure holds the configuration settings for the Timer peripheral. To initialize this
|
||||
* structure to reasonable defaults, call the CTIMER_GetDefaultConfig() function and pass a
|
||||
* pointer to the configuration structure instance.
|
||||
*
|
||||
* The configuration structure can be made constant so as to reside in flash.
|
||||
*/
|
||||
typedef struct _ctimer_config
|
||||
{
|
||||
ctimer_timer_mode_t mode; /*!< Timer mode */
|
||||
ctimer_capture_channel_t input; /*!< Input channel to increment the timer, used only in timer
|
||||
modes that rely on this input signal to increment TC */
|
||||
uint32_t prescale; /*!< Prescale value */
|
||||
} ctimer_config_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Ungates the clock and configures the peripheral for basic operation.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application before using the driver.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param config Pointer to the user configuration structure.
|
||||
*/
|
||||
void CTIMER_Init(CTIMER_Type *base, const ctimer_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Gates the timer clock.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*/
|
||||
void CTIMER_Deinit(CTIMER_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Fills in the timers configuration structure with the default settings.
|
||||
*
|
||||
* The default values are:
|
||||
* @code
|
||||
* config->mode = kCTIMER_TimerMode;
|
||||
* config->input = kCTIMER_Capture_0;
|
||||
* config->prescale = 0;
|
||||
* @endcode
|
||||
* @param config Pointer to the user configuration structure.
|
||||
*/
|
||||
void CTIMER_GetDefaultConfig(ctimer_config_t *config);
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name PWM setup operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Configures the PWM signal parameters.
|
||||
*
|
||||
* Enables PWM mode on the match channel passed in and will then setup the match value
|
||||
* and other match parameters to generate a PWM signal.
|
||||
* This function will assign match channel 3 to set the PWM cycle.
|
||||
*
|
||||
* @note When setting PWM output from multiple output pins, all should use the same PWM
|
||||
* frequency
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param matchChannel Match pin to be used to output the PWM signal
|
||||
* @param dutyCyclePercent PWM pulse width; the value should be between 0 to 100
|
||||
* @param pwmFreq_Hz PWM signal frequency in Hz
|
||||
* @param srcClock_Hz Timer counter clock in Hz
|
||||
* @param enableInt Enable interrupt when the timer value reaches the match value of the PWM pulse,
|
||||
* if it is 0 then no interrupt is generated
|
||||
*
|
||||
* @return kStatus_Success on success
|
||||
* kStatus_Fail If matchChannel passed in is 3; this channel is reserved to set the PWM cycle
|
||||
*/
|
||||
status_t CTIMER_SetupPwm(CTIMER_Type *base,
|
||||
ctimer_match_t matchChannel,
|
||||
uint8_t dutyCyclePercent,
|
||||
uint32_t pwmFreq_Hz,
|
||||
uint32_t srcClock_Hz,
|
||||
bool enableInt);
|
||||
|
||||
/*!
|
||||
* @brief Updates the duty cycle of an active PWM signal.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param matchChannel Match pin to be used to output the PWM signal
|
||||
* @param dutyCyclePercent New PWM pulse width; the value should be between 0 to 100
|
||||
*/
|
||||
void CTIMER_UpdatePwmDutycycle(CTIMER_Type *base, ctimer_match_t matchChannel, uint8_t dutyCyclePercent);
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @brief Setup the match register.
|
||||
*
|
||||
* User configuration is used to setup the match value and action to be taken when a match occurs.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param matchChannel Match register to configure
|
||||
* @param config Pointer to the match configuration structure
|
||||
*/
|
||||
void CTIMER_SetupMatch(CTIMER_Type *base, ctimer_match_t matchChannel, const ctimer_match_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Setup the capture.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param capture Capture channel to configure
|
||||
* @param edge Edge on the channel that will trigger a capture
|
||||
* @param enableInt Flag to enable channel interrupts, if enabled then the registered call back
|
||||
* is called upon capture
|
||||
*/
|
||||
void CTIMER_SetupCapture(CTIMER_Type *base,
|
||||
ctimer_capture_channel_t capture,
|
||||
ctimer_capture_edge_t edge,
|
||||
bool enableInt);
|
||||
|
||||
/*!
|
||||
* @brief Register callback.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param cb_func callback function
|
||||
* @param cb_type callback function type, singular or multiple
|
||||
*/
|
||||
void CTIMER_RegisterCallBack(CTIMER_Type *base, ctimer_callback_t *cb_func, ctimer_callback_type_t cb_type);
|
||||
|
||||
/*!
|
||||
* @name Interrupt Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables the selected Timer interrupts.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param mask The interrupts to enable. This is a logical OR of members of the
|
||||
* enumeration ::ctimer_interrupt_enable_t
|
||||
*/
|
||||
static inline void CTIMER_EnableInterrupts(CTIMER_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Enable match interrupts */
|
||||
base->MCR |= mask;
|
||||
|
||||
/* Enable capture interrupts */
|
||||
base->CCR |= mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables the selected Timer interrupts.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param mask The interrupts to enable. This is a logical OR of members of the
|
||||
* enumeration ::ctimer_interrupt_enable_t
|
||||
*/
|
||||
static inline void CTIMER_DisableInterrupts(CTIMER_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Disable match interrupts */
|
||||
base->MCR &= ~mask;
|
||||
|
||||
/* Disable capture interrupts */
|
||||
base->CCR &= ~mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the enabled Timer interrupts.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*
|
||||
* @return The enabled interrupts. This is the logical OR of members of the
|
||||
* enumeration ::ctimer_interrupt_enable_t
|
||||
*/
|
||||
static inline uint32_t CTIMER_GetEnabledInterrupts(CTIMER_Type *base)
|
||||
{
|
||||
uint32_t enabledIntrs = 0;
|
||||
|
||||
/* Get all the match interrupts enabled */
|
||||
enabledIntrs =
|
||||
base->MCR & (CTIMER_MCR_MR0I_SHIFT | CTIMER_MCR_MR1I_SHIFT | CTIMER_MCR_MR2I_SHIFT | CTIMER_MCR_MR3I_SHIFT);
|
||||
|
||||
/* Get all the capture interrupts enabled */
|
||||
enabledIntrs |=
|
||||
base->CCR & (CTIMER_CCR_CAP0I_SHIFT | CTIMER_CCR_CAP1I_SHIFT | CTIMER_CCR_CAP2I_SHIFT | CTIMER_CCR_CAP3I_SHIFT);
|
||||
|
||||
return enabledIntrs;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Status Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Gets the Timer status flags.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*
|
||||
* @return The status flags. This is the logical OR of members of the
|
||||
* enumeration ::ctimer_status_flags_t
|
||||
*/
|
||||
static inline uint32_t CTIMER_GetStatusFlags(CTIMER_Type *base)
|
||||
{
|
||||
return base->IR;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clears the Timer status flags.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
* @param mask The status flags to clear. This is a logical OR of members of the
|
||||
* enumeration ::ctimer_status_flags_t
|
||||
*/
|
||||
static inline void CTIMER_ClearStatusFlags(CTIMER_Type *base, uint32_t mask)
|
||||
{
|
||||
base->IR = mask;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Counter Start and Stop
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Starts the Timer counter.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*/
|
||||
static inline void CTIMER_StartTimer(CTIMER_Type *base)
|
||||
{
|
||||
base->TCR |= CTIMER_TCR_CEN_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Stops the Timer counter.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*/
|
||||
static inline void CTIMER_StopTimer(CTIMER_Type *base)
|
||||
{
|
||||
base->TCR &= ~CTIMER_TCR_CEN_MASK;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @brief Reset the counter.
|
||||
*
|
||||
* The timer counter and prescale counter are reset on the next positive edge of the APB clock.
|
||||
*
|
||||
* @param base Ctimer peripheral base address
|
||||
*/
|
||||
static inline void CTIMER_Reset(CTIMER_Type *base)
|
||||
{
|
||||
base->TCR |= CTIMER_TCR_CRST_MASK;
|
||||
base->TCR &= ~CTIMER_TCR_CRST_MASK;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_CTIMER_H_ */
|
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_dma.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Get instance number for DMA.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
*/
|
||||
static int32_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 IRQ number. */
|
||||
static const IRQn_Type s_dmaIRQNumber[] = DMA_IRQS;
|
||||
|
||||
/*! @brief Pointers to transfer handle for each DMA channel. */
|
||||
static dma_handle_t *s_DMAHandle[FSL_FEATURE_DMA_NUMBER_OF_CHANNELS];
|
||||
|
||||
/*! @brief Static table of descriptors */
|
||||
#if defined(__ICCARM__)
|
||||
#pragma data_alignment = 512
|
||||
dma_descriptor_t s_dma_descriptor_table[FSL_FEATURE_DMA_NUMBER_OF_CHANNELS] = {0};
|
||||
#elif defined(__CC_ARM)
|
||||
__attribute__((aligned(512))) dma_descriptor_t s_dma_descriptor_table[FSL_FEATURE_DMA_NUMBER_OF_CHANNELS] = {0};
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((aligned(512))) dma_descriptor_t s_dma_descriptor_table[FSL_FEATURE_DMA_NUMBER_OF_CHANNELS] = {0};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
static int32_t DMA_GetInstance(DMA_Type *base)
|
||||
{
|
||||
int32_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 < FSL_FEATURE_SOC_DMA_COUNT ? instance : -1;
|
||||
}
|
||||
|
||||
void DMA_Init(DMA_Type *base)
|
||||
{
|
||||
/* enable dma clock gate */
|
||||
CLOCK_EnableClock(kCLOCK_Dma);
|
||||
/* set descriptor table */
|
||||
base->SRAMBASE = (uint32_t)s_dma_descriptor_table;
|
||||
/* enable dma peripheral */
|
||||
base->CTRL |= DMA_CTRL_ENABLE_MASK;
|
||||
}
|
||||
|
||||
void DMA_Deinit(DMA_Type *base)
|
||||
{
|
||||
/* Disable DMA peripheral */
|
||||
base->CTRL &= ~(DMA_CTRL_ENABLE_MASK);
|
||||
}
|
||||
|
||||
void DMA_ConfigureChannelTrigger(DMA_Type *base, uint32_t channel, dma_channel_trigger_t *trigger)
|
||||
{
|
||||
assert((channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS) && (NULL != trigger));
|
||||
|
||||
uint32_t tmp = (
|
||||
DMA_CHANNEL_CFG_HWTRIGEN_MASK | DMA_CHANNEL_CFG_TRIGPOL_MASK | DMA_CHANNEL_CFG_TRIGTYPE_MASK |
|
||||
DMA_CHANNEL_CFG_TRIGBURST_MASK | DMA_CHANNEL_CFG_BURSTPOWER_MASK | DMA_CHANNEL_CFG_SRCBURSTWRAP_MASK |
|
||||
DMA_CHANNEL_CFG_DSTBURSTWRAP_MASK
|
||||
);
|
||||
tmp = base->CHANNEL[channel].CFG & (~tmp);
|
||||
tmp |= (uint32_t)(trigger->type) | (uint32_t)(trigger->burst) | (uint32_t)(trigger->wrap);
|
||||
base->CHANNEL[channel].CFG = tmp;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the remaining bytes of the current DMA descriptor transfer.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @return The number of bytes which have not been transferred yet.
|
||||
*/
|
||||
uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
|
||||
/* NOTE: when descriptors are chained, ACTIVE bit is set for whole chain. It makes
|
||||
* impossible to distinguish between:
|
||||
* - transfer finishes (represented by value '0x3FF')
|
||||
* - and remaining 1024 bytes to transfer (value 0x3FF)
|
||||
* for all descriptor in chain, except the last one.
|
||||
* If you decide to use this function, please use 1023 transfers as maximal value */
|
||||
|
||||
/* Channel not active (transfer finished) and value is 0x3FF - nothing to transfer */
|
||||
if (
|
||||
(!(base->COMMON[DMA_CHANNEL_GROUP(channel)].ACTIVE & (1U << (DMA_CHANNEL_INDEX(channel))))) &&
|
||||
(0x3FF == ((base->CHANNEL[channel].XFERCFG & DMA_CHANNEL_XFERCFG_XFERCOUNT_MASK) >> DMA_CHANNEL_XFERCFG_XFERCOUNT_SHIFT))
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return base->CHANNEL[channel].XFERCFG + 1;
|
||||
}
|
||||
|
||||
static void DMA_SetupDescriptor(
|
||||
dma_descriptor_t *desc,
|
||||
uint32_t xfercfg,
|
||||
void *srcEndAddr,
|
||||
void *dstEndAddr,
|
||||
void *nextDesc
|
||||
)
|
||||
{
|
||||
desc->xfercfg = xfercfg;
|
||||
desc->srcEndAddr = srcEndAddr;
|
||||
desc->dstEndAddr = dstEndAddr;
|
||||
desc->linkToNextDesc = nextDesc;
|
||||
}
|
||||
|
||||
/* Verify and convert dma_xfercfg_t to XFERCFG register */
|
||||
static void DMA_SetupXferCFG(
|
||||
dma_xfercfg_t *xfercfg,
|
||||
uint32_t *xfercfg_addr
|
||||
)
|
||||
{
|
||||
assert(xfercfg != NULL);
|
||||
/* check source increment */
|
||||
assert((xfercfg->srcInc == 0) || (xfercfg->srcInc == 1) || (xfercfg->srcInc == 2) || (xfercfg->srcInc == 4));
|
||||
/* check destination increment */
|
||||
assert((xfercfg->dstInc == 0) || (xfercfg->dstInc == 1) || (xfercfg->dstInc == 2) || (xfercfg->dstInc == 4));
|
||||
/* check data width */
|
||||
assert((xfercfg->byteWidth == 1) || (xfercfg->byteWidth == 2) || (xfercfg->byteWidth == 4));
|
||||
/* check transfer count */
|
||||
assert(xfercfg->transferCount <= DMA_MAX_TRANSFER_COUNT);
|
||||
|
||||
uint32_t xfer = 0, tmp;
|
||||
/* set valid flag - descriptor is ready now */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_CFGVALID(xfercfg->valid ? 1 : 0);
|
||||
/* set reload - allow link to next descriptor */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_RELOAD(xfercfg->reload ? 1 : 0);
|
||||
/* set swtrig flag - start transfer */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_SWTRIG(xfercfg->swtrig? 1 : 0);
|
||||
/* set transfer count */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_CLRTRIG(xfercfg->clrtrig? 1 : 0);
|
||||
/* set INTA */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_SETINTA(xfercfg->intA ? 1 : 0);
|
||||
/* set INTB */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_SETINTB(xfercfg->intB ? 1 : 0);
|
||||
/* set data width */
|
||||
tmp = xfercfg->byteWidth == 4 ? 2 : xfercfg->byteWidth - 1;
|
||||
xfer |= DMA_CHANNEL_XFERCFG_WIDTH(tmp);
|
||||
/* set source increment value */
|
||||
tmp = xfercfg->srcInc == 4 ? 3 : xfercfg->srcInc;
|
||||
xfer |= DMA_CHANNEL_XFERCFG_SRCINC(tmp);
|
||||
/* set destination increment value */
|
||||
tmp = xfercfg->dstInc == 4 ? 3 : xfercfg->dstInc;
|
||||
xfer |= DMA_CHANNEL_XFERCFG_DSTINC(tmp);
|
||||
/* set transfer count */
|
||||
xfer |= DMA_CHANNEL_XFERCFG_XFERCOUNT(xfercfg->transferCount - 1);
|
||||
|
||||
/* store xferCFG */
|
||||
*xfercfg_addr = xfer;
|
||||
}
|
||||
|
||||
void DMA_CreateDescriptor(
|
||||
dma_descriptor_t *desc,
|
||||
dma_xfercfg_t *xfercfg,
|
||||
void *srcAddr,
|
||||
void *dstAddr,
|
||||
void *nextDesc
|
||||
)
|
||||
{
|
||||
uint32_t xfercfg_reg = 0;
|
||||
|
||||
assert((NULL != desc) && (0 == (uint32_t)desc % 16) && (NULL != xfercfg));
|
||||
assert((NULL != srcAddr) && (0 == (uint32_t)srcAddr % xfercfg->byteWidth));
|
||||
assert((NULL != dstAddr) && (0 == (uint32_t)dstAddr % xfercfg->byteWidth));
|
||||
assert((NULL == nextDesc) || (0 == (uint32_t)nextDesc % 16));
|
||||
|
||||
/* Setup channel configuration */
|
||||
DMA_SetupXferCFG(xfercfg, &xfercfg_reg);
|
||||
|
||||
/* Set descriptor structure */
|
||||
DMA_SetupDescriptor(desc, xfercfg_reg,
|
||||
(uint8_t*)srcAddr + (xfercfg->srcInc * xfercfg->byteWidth * (xfercfg->transferCount - 1)),
|
||||
(uint8_t*)dstAddr + (xfercfg->dstInc * xfercfg->byteWidth * (xfercfg->transferCount - 1)),
|
||||
nextDesc
|
||||
);
|
||||
}
|
||||
|
||||
void DMA_AbortTransfer(dma_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
DMA_DisableChannel(handle->base, handle->channel);
|
||||
while (handle->base->COMMON[DMA_CHANNEL_GROUP(handle->channel)].BUSY & (1U << DMA_CHANNEL_INDEX(handle->channel)))
|
||||
{ }
|
||||
handle->base->COMMON[DMA_CHANNEL_GROUP(handle->channel)].ABORT |= 1U << DMA_CHANNEL_INDEX(handle->channel);
|
||||
DMA_EnableChannel(handle->base, handle->channel);
|
||||
}
|
||||
|
||||
void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
int32_t dmaInstance;
|
||||
assert((NULL != handle) && (channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS));
|
||||
|
||||
/* base address is invalid DMA instance */
|
||||
dmaInstance = DMA_GetInstance(base);
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
handle->base = base;
|
||||
handle->channel = channel;
|
||||
s_DMAHandle[channel] = handle;
|
||||
/* Enable NVIC interrupt */
|
||||
EnableIRQ(s_dmaIRQNumber[dmaInstance]);
|
||||
}
|
||||
|
||||
void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
}
|
||||
|
||||
void DMA_PrepareTransfer(dma_transfer_config_t *config,
|
||||
void *srcAddr,
|
||||
void *dstAddr,
|
||||
uint32_t byteWidth,
|
||||
uint32_t transferBytes,
|
||||
dma_transfer_type_t type,
|
||||
void *nextDesc)
|
||||
{
|
||||
uint32_t xfer_count;
|
||||
assert((NULL != config) && (NULL != srcAddr) && (NULL != dstAddr));
|
||||
assert((byteWidth == 1) || (byteWidth == 2) || (byteWidth == 4));
|
||||
|
||||
/* check max */
|
||||
xfer_count = transferBytes / byteWidth;
|
||||
assert((xfer_count <= DMA_MAX_TRANSFER_COUNT) && (0 == transferBytes % byteWidth));
|
||||
|
||||
memset(config, 0, sizeof(*config));
|
||||
switch (type)
|
||||
{
|
||||
case kDMA_MemoryToMemory:
|
||||
config->xfercfg.srcInc = 1;
|
||||
config->xfercfg.dstInc = 1;
|
||||
config->isPeriph = false;
|
||||
break;
|
||||
case kDMA_PeripheralToMemory:
|
||||
/* Peripheral register - source doesn't increment */
|
||||
config->xfercfg.srcInc = 0;
|
||||
config->xfercfg.dstInc = 1;
|
||||
config->isPeriph = true;
|
||||
break;
|
||||
case kDMA_MemoryToPeripheral:
|
||||
/* Peripheral register - destination doesn't increment */
|
||||
config->xfercfg.srcInc = 1;
|
||||
config->xfercfg.dstInc = 0;
|
||||
config->isPeriph = true;
|
||||
break;
|
||||
case kDMA_StaticToStatic:
|
||||
config->xfercfg.srcInc = 0;
|
||||
config->xfercfg.dstInc = 0;
|
||||
config->isPeriph = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
config->dstAddr = (uint8_t*)dstAddr;
|
||||
config->srcAddr = (uint8_t*)srcAddr;
|
||||
config->nextDesc = (uint8_t*)nextDesc;
|
||||
config->xfercfg.transferCount = xfer_count;
|
||||
config->xfercfg.byteWidth = byteWidth;
|
||||
config->xfercfg.intA = true;
|
||||
config->xfercfg.reload = nextDesc != NULL;
|
||||
config->xfercfg.valid = true;
|
||||
}
|
||||
|
||||
status_t DMA_SubmitTransfer(dma_handle_t *handle, dma_transfer_config_t *config)
|
||||
{
|
||||
assert((NULL != handle) && (NULL != config));
|
||||
|
||||
/* Previous transfer has not finished */
|
||||
if (DMA_ChannelIsActive(handle->base, handle->channel))
|
||||
{
|
||||
return kStatus_DMA_Busy;
|
||||
}
|
||||
|
||||
/* enable/disable peripheral request */
|
||||
if (config->isPeriph)
|
||||
{
|
||||
DMA_EnableChannelPeriphRq(handle->base, handle->channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
DMA_DisableChannelPeriphRq(handle->base, handle->channel);
|
||||
}
|
||||
|
||||
DMA_CreateDescriptor(
|
||||
&s_dma_descriptor_table[ handle->channel ], &config->xfercfg,
|
||||
config->srcAddr, config->dstAddr, config->nextDesc
|
||||
);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void DMA_StartTransfer(dma_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
/* Enable channel interrupt */
|
||||
handle->base->COMMON[DMA_CHANNEL_GROUP(handle->channel)].INTENSET |= 1U << DMA_CHANNEL_INDEX(handle->channel);
|
||||
|
||||
/* If HW trigger is enabled - disable SW trigger */
|
||||
if (handle->base->CHANNEL[handle->channel].CFG & DMA_CHANNEL_CFG_HWTRIGEN_MASK)
|
||||
{
|
||||
s_dma_descriptor_table[ handle->channel ].xfercfg &= ~(DMA_CHANNEL_XFERCFG_SWTRIG_MASK);
|
||||
}
|
||||
/* Otherwise enable SW trigger */
|
||||
else
|
||||
{
|
||||
s_dma_descriptor_table[ handle->channel ].xfercfg |= DMA_CHANNEL_XFERCFG_SWTRIG_MASK;
|
||||
}
|
||||
|
||||
/* Set channel XFERCFG register according first channel descriptor. */
|
||||
handle->base->CHANNEL[handle->channel].XFERCFG = s_dma_descriptor_table[ handle->channel ].xfercfg;
|
||||
/* At this moment, the channel ACTIVE bit is set and application cannot modify
|
||||
* or start another transfer using this channel. Channel ACTIVE bit is cleared by
|
||||
* 'AbortTransfer' function or when the transfer finishes */
|
||||
}
|
||||
|
||||
void DMA0_DriverIRQHandler(void)
|
||||
{
|
||||
dma_handle_t *handle;
|
||||
int32_t channel_group;
|
||||
int32_t channel_index;
|
||||
|
||||
/* Find channels that have completed transfer */
|
||||
for (int i = 0; i < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS; i++)
|
||||
{
|
||||
handle = s_DMAHandle[i];
|
||||
/* Handle is not present */
|
||||
if (NULL == handle)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
channel_group = DMA_CHANNEL_GROUP(handle->channel);
|
||||
channel_index = DMA_CHANNEL_INDEX(handle->channel);
|
||||
/* Channel uses INTA flag */
|
||||
if (handle->base->COMMON[channel_group].INTA & (1U << channel_index))
|
||||
{
|
||||
/* Clear INTA flag */
|
||||
handle->base->COMMON[channel_group].INTA = 1U << channel_index;
|
||||
if (handle->callback)
|
||||
{
|
||||
(handle->callback)(handle, handle->userData, true, kDMA_IntA);
|
||||
}
|
||||
}
|
||||
/* Channel uses INTB flag */
|
||||
if (handle->base->COMMON[channel_group].INTB & (1U << channel_index))
|
||||
{
|
||||
/* Clear INTB flag */
|
||||
handle->base->COMMON[channel_group].INTB = 1U << channel_index;
|
||||
if (handle->callback)
|
||||
{
|
||||
(handle->callback)(handle, handle->userData, true, kDMA_IntB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_DMA_H_
|
||||
#define _FSL_DMA_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup dma
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief DMA driver version */
|
||||
#define FSL_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
|
||||
/*@}*/
|
||||
|
||||
#define DMA_MAX_TRANSFER_COUNT 0x400
|
||||
|
||||
/* Channel group consists of 32 channels. channel_group = (channel / 32) */
|
||||
#define DMA_CHANNEL_GROUP(channel) (((uint8_t)channel) >> 5U)
|
||||
/* Channel index in channel group. channel_index = (channel % 32) */
|
||||
#define DMA_CHANNEL_INDEX(channel) (((uint8_t)channel) & 0x1F)
|
||||
|
||||
|
||||
/*! @brief DMA descriptor structure */
|
||||
typedef struct _dma_descriptor {
|
||||
uint32_t xfercfg; /*!< Transfer configuration */
|
||||
void *srcEndAddr; /*!< Last source address of DMA transfer */
|
||||
void *dstEndAddr; /*!< Last destination address of DMA transfer */
|
||||
void *linkToNextDesc; /*!< Address of next DMA descriptor in chain */
|
||||
} dma_descriptor_t;
|
||||
|
||||
/*! @brief DMA transfer configuration */
|
||||
typedef struct _dma_xfercfg {
|
||||
bool valid; /*!< Descriptor is ready to transfer */
|
||||
bool reload; /*!< Reload channel configuration register after
|
||||
current descriptor is exhausted */
|
||||
bool swtrig; /*!< Perform software trigger. Transfer if fired
|
||||
when 'valid' is set */
|
||||
bool clrtrig; /*!< Clear trigger */
|
||||
bool intA; /*!< Raises IRQ when transfer is done and set IRQA status register flag */
|
||||
bool intB; /*!< Raises IRQ when transfer is done and set IRQB status register flag */
|
||||
uint8_t byteWidth; /*!< Byte width of data to transfer */
|
||||
uint8_t srcInc; /*!< Increment source address by 'srcInc' x 'byteWidth' */
|
||||
uint8_t dstInc; /*!< Increment destination address by 'dstInc' x 'byteWidth' */
|
||||
uint16_t transferCount; /*!< Number of transfers */
|
||||
} dma_xfercfg_t;
|
||||
|
||||
/*! @brief DMA channel priority */
|
||||
typedef enum _dma_priority {
|
||||
kDMA_ChannelPriority0 = 0, /*!< Highest channel priority - priority 0 */
|
||||
kDMA_ChannelPriority1, /*!< Channel priority 1 */
|
||||
kDMA_ChannelPriority2, /*!< Channel priority 2 */
|
||||
kDMA_ChannelPriority3, /*!< Channel priority 3 */
|
||||
kDMA_ChannelPriority4, /*!< Channel priority 4 */
|
||||
kDMA_ChannelPriority5, /*!< Channel priority 5 */
|
||||
kDMA_ChannelPriority6, /*!< Channel priority 6 */
|
||||
kDMA_ChannelPriority7, /*!< Lowest channel priority - priority 7 */
|
||||
} dma_priority_t;
|
||||
|
||||
/*! @brief DMA interrupt flags */
|
||||
typedef enum _dma_int {
|
||||
kDMA_IntA, /*!< DMA interrupt flag A */
|
||||
kDMA_IntB, /*!< DMA interrupt flag B */
|
||||
} dma_irq_t;
|
||||
|
||||
/*! @brief DMA trigger type*/
|
||||
typedef enum _dma_trigger_type {
|
||||
kDMA_NoTrigger = 0, /*!< Trigger is disabled */
|
||||
kDMA_LowLevelTrigger = DMA_CHANNEL_CFG_HWTRIGEN(1) | DMA_CHANNEL_CFG_TRIGTYPE(1), /*!< Low level active trigger */
|
||||
kDMA_HighLevelTrigger = DMA_CHANNEL_CFG_HWTRIGEN(1) | DMA_CHANNEL_CFG_TRIGTYPE(1) | DMA_CHANNEL_CFG_TRIGPOL(1), /*!< High level active trigger */
|
||||
kDMA_FallingEdgeTrigger = DMA_CHANNEL_CFG_HWTRIGEN(1), /*!< Falling edge active trigger */
|
||||
kDMA_RisingEdgeTrigger = DMA_CHANNEL_CFG_HWTRIGEN(1) | DMA_CHANNEL_CFG_TRIGPOL(1), /*!< Rising edge active trigger */
|
||||
} dma_trigger_type_t;
|
||||
|
||||
/*! @brief DMA trigger burst */
|
||||
typedef enum _dma_trigger_burst {
|
||||
kDMA_SingleTransfer = 0, /*!< Single transfer */
|
||||
kDMA_LevelBurstTransfer = DMA_CHANNEL_CFG_TRIGBURST(1), /*!< Burst transfer driven by level trigger */
|
||||
kDMA_EdgeBurstTransfer1 = DMA_CHANNEL_CFG_TRIGBURST(1), /*!< Perform 1 transfer by edge trigger */
|
||||
kDMA_EdgeBurstTransfer2 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(1), /*!< Perform 2 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer4 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(2), /*!< Perform 4 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer8 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(3), /*!< Perform 8 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer16 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(4), /*!< Perform 16 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer32 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(5), /*!< Perform 32 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer64 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(6), /*!< Perform 64 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer128 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(7), /*!< Perform 128 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer256 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(8), /*!< Perform 256 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer512 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(9), /*!< Perform 512 transfers by edge trigger */
|
||||
kDMA_EdgeBurstTransfer1024 = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(10), /*!< Perform 1024 transfers by edge trigger */
|
||||
} dma_trigger_burst_t;
|
||||
|
||||
/*! @brief DMA burst wrapping */
|
||||
typedef enum _dma_burst_wrap {
|
||||
kDMA_NoWrap = 0, /*!< Wrapping is disabled */
|
||||
kDMA_SrcWrap = DMA_CHANNEL_CFG_SRCBURSTWRAP(1), /*!< Wrapping is enabled for source */
|
||||
kDMA_DstWrap = DMA_CHANNEL_CFG_DSTBURSTWRAP(1), /*!< Wrapping is enabled for destination */
|
||||
kDMA_SrcAndDstWrap = DMA_CHANNEL_CFG_SRCBURSTWRAP(1) | DMA_CHANNEL_CFG_DSTBURSTWRAP(1), /*!< Wrapping is enabled for source and destination */
|
||||
} dma_burst_wrap_t;
|
||||
|
||||
/*! @brief DMA transfer type */
|
||||
typedef enum _dma_transfer_type
|
||||
{
|
||||
kDMA_MemoryToMemory = 0x0U, /*!< Transfer from memory to memory (increment source and destination) */
|
||||
kDMA_PeripheralToMemory, /*!< Transfer from peripheral to memory (increment only destination) */
|
||||
kDMA_MemoryToPeripheral, /*!< Transfer from memory to peripheral (increment only source)*/
|
||||
kDMA_StaticToStatic, /*!< Peripheral to static memory (do not increment source or destination) */
|
||||
} dma_transfer_type_t;
|
||||
|
||||
/*! @brief DMA channel trigger */
|
||||
typedef struct _dma_channel_trigger {
|
||||
dma_trigger_type_t type;
|
||||
dma_trigger_burst_t burst;
|
||||
dma_burst_wrap_t wrap;
|
||||
} dma_channel_trigger_t;
|
||||
|
||||
/*! @brief DMA transfer status */
|
||||
enum _dma_transfer_status
|
||||
{
|
||||
kStatus_DMA_Busy = MAKE_STATUS(kStatusGroup_DMA, 0), /*!< Channel is busy and can't handle the
|
||||
transfer request. */
|
||||
};
|
||||
|
||||
/*! @brief DMA transfer configuration */
|
||||
typedef struct _dma_transfer_config
|
||||
{
|
||||
uint8_t *srcAddr; /*!< Source data address */
|
||||
uint8_t *dstAddr; /*!< Destination data address */
|
||||
uint8_t *nextDesc; /*!< Chain custom descriptor */
|
||||
dma_xfercfg_t xfercfg; /*!< Transfer options */
|
||||
bool isPeriph; /*!< DMA transfer is driven by peripheral */
|
||||
} dma_transfer_config_t;
|
||||
|
||||
/*! @brief Callback for DMA */
|
||||
struct _dma_handle;
|
||||
|
||||
/*! @brief Define Callback function for DMA. */
|
||||
typedef void (*dma_callback)(struct _dma_handle *handle, void *userData, bool transferDone, uint32_t intmode);
|
||||
|
||||
/*! @brief DMA transfer handle structure */
|
||||
typedef struct _dma_handle
|
||||
{
|
||||
dma_callback callback; /*!< Callback function. Invoked when transfer
|
||||
of descriptor with interrupt flag finishes */
|
||||
void *userData; /*!< Callback function parameter */
|
||||
DMA_Type *base; /*!< DMA peripheral base address */
|
||||
uint8_t channel; /*!< DMA channel number */
|
||||
} dma_handle_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* APIs
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*!
|
||||
* @name DMA initialization and De-initialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes DMA peripheral.
|
||||
*
|
||||
* This function enable the DMA clock, set descriptor table and
|
||||
* enable DMA peripheral.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
*/
|
||||
void DMA_Init(DMA_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Deinitializes 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 Return whether DMA channel is processing transfer
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @return True for active state, false otherwise.
|
||||
*/
|
||||
static inline bool DMA_ChannelIsActive(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
return (base->COMMON[DMA_CHANNEL_GROUP(channel)].ACTIVE & (1U << DMA_CHANNEL_INDEX(channel))) ? true : false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enables the interrupt source for the DMA transfer.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
*/
|
||||
static inline void DMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->COMMON[DMA_CHANNEL_GROUP(channel)].INTENSET |= 1U << DMA_CHANNEL_INDEX(channel);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables the interrupt source for the DMA transfer.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
*/
|
||||
static inline void DMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->COMMON[DMA_CHANNEL_GROUP(channel)].INTENCLR |= 1U << DMA_CHANNEL_INDEX(channel);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable DMA channel.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
*/
|
||||
static inline void DMA_EnableChannel(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->COMMON[DMA_CHANNEL_GROUP(channel)].ENABLESET |= 1U << DMA_CHANNEL_INDEX(channel);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable DMA channel.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
*/
|
||||
static inline void DMA_DisableChannel(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->COMMON[DMA_CHANNEL_GROUP(channel)].ENABLECLR |= 1U << DMA_CHANNEL_INDEX(channel);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set PERIPHREQEN of channel configuration register.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
*/
|
||||
static inline void DMA_EnableChannelPeriphRq(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->CHANNEL[channel].CFG |= DMA_CHANNEL_CFG_PERIPHREQEN_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get PERIPHREQEN value of channel configuration register.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @return True for enabled PeriphRq, false for disabled.
|
||||
*/
|
||||
static inline void DMA_DisableChannelPeriphRq(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->CHANNEL[channel].CFG &= ~DMA_CHANNEL_CFG_PERIPHREQEN_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set trigger settings of DMA channel.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @param trigger trigger configuration.
|
||||
*/
|
||||
void DMA_ConfigureChannelTrigger(DMA_Type *base, uint32_t channel, dma_channel_trigger_t *trigger);
|
||||
|
||||
/*!
|
||||
* @brief Gets the remaining bytes of the current DMA descriptor transfer.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @return The number of bytes which have not been transferred yet.
|
||||
*/
|
||||
uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel);
|
||||
|
||||
/*!
|
||||
* @brief Set priority of channel configuration register.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @param priority Channel priority value.
|
||||
*/
|
||||
static inline void DMA_SetChannelPriority(DMA_Type *base, uint32_t channel, dma_priority_t priority)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
base->CHANNEL[channel].CFG = (base->CHANNEL[channel].CFG & (~(DMA_CHANNEL_CFG_CHPRIORITY_MASK))) | DMA_CHANNEL_CFG_CHPRIORITY(priority);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get priority of channel configuration register.
|
||||
*
|
||||
* @param base DMA peripheral base address.
|
||||
* @param channel DMA channel number.
|
||||
* @return Channel priority value.
|
||||
*/
|
||||
static inline dma_priority_t DMA_GetChannelPriority(DMA_Type *base, uint32_t channel)
|
||||
{
|
||||
assert(channel < FSL_FEATURE_DMA_NUMBER_OF_CHANNELS);
|
||||
return (dma_priority_t)((base->CHANNEL[channel].CFG & DMA_CHANNEL_CFG_CHPRIORITY_MASK) >> DMA_CHANNEL_CFG_CHPRIORITY_SHIFT);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create application specific DMA descriptor
|
||||
* to be used in a chain in transfer
|
||||
*
|
||||
* @param desc DMA descriptor address.
|
||||
* @param xfercfg Transfer configuration for DMA descriptor.
|
||||
* @param srcAddr Address of last item to transmit
|
||||
* @param dstAddr Address of last item to receive.
|
||||
* @param nextDesc Address of next descriptor in chain.
|
||||
*/
|
||||
void DMA_CreateDescriptor(
|
||||
dma_descriptor_t *desc,
|
||||
dma_xfercfg_t *xfercfg,
|
||||
void *srcAddr,
|
||||
void *dstAddr,
|
||||
void *nextDesc
|
||||
);
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name DMA Transactional Operation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Abort running transfer by handle.
|
||||
*
|
||||
* This function aborts DMA transfer specified by handle.
|
||||
*
|
||||
* @param handle DMA handle pointer.
|
||||
*/
|
||||
void DMA_AbortTransfer(dma_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Creates the DMA handle.
|
||||
*
|
||||
* This function is called if using transaction API for DMA. This function
|
||||
* initializes the internal state of 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 Installs a callback function for the DMA transfer.
|
||||
*
|
||||
* This callback is called in DMA IRQ handler. Use the callback to do something after
|
||||
* the current major loop transfer completes.
|
||||
*
|
||||
* @param handle DMA handle pointer.
|
||||
* @param callback DMA callback function pointer.
|
||||
* @param userData Parameter for callback function.
|
||||
*/
|
||||
void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData);
|
||||
|
||||
/*!
|
||||
* @brief Prepares the DMA transfer structure.
|
||||
*
|
||||
* This function prepares the transfer configuration structure according to the user input.
|
||||
*
|
||||
* @param config The user configuration structure of type dma_transfer_t.
|
||||
* @param srcAddr DMA transfer source address.
|
||||
* @param dstAddr DMA transfer destination address.
|
||||
* @param byteWidth DMA transfer destination address width(bytes).
|
||||
* @param transferBytes DMA transfer bytes to be transferred.
|
||||
* @param type DMA transfer type.
|
||||
* @param nextDesc Chain custom descriptor to transfer.
|
||||
* @note The data address and the data width must be consistent. For example, if the SRC
|
||||
* is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in
|
||||
* source address error(SAE).
|
||||
*/
|
||||
void DMA_PrepareTransfer(dma_transfer_config_t *config,
|
||||
void *srcAddr,
|
||||
void *dstAddr,
|
||||
uint32_t byteWidth,
|
||||
uint32_t transferBytes,
|
||||
dma_transfer_type_t type,
|
||||
void *nextDesc);
|
||||
|
||||
/*!
|
||||
* @brief Submits the DMA transfer request.
|
||||
*
|
||||
* This function submits the DMA transfer request according to the transfer configuration structure.
|
||||
* If the user submits the transfer request repeatedly, this function packs an unprocessed request as
|
||||
* a TCD and enables scatter/gather feature to process it in the next time.
|
||||
*
|
||||
* @param handle DMA handle pointer.
|
||||
* @param config Pointer to DMA transfer configuration structure.
|
||||
* @retval kStatus_DMA_Success It means submit transfer request succeed.
|
||||
* @retval kStatus_DMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
|
||||
* @retval kStatus_DMA_Busy It means the given channel is busy, need to submit request later.
|
||||
*/
|
||||
status_t DMA_SubmitTransfer(dma_handle_t *handle, dma_transfer_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief DMA start transfer.
|
||||
*
|
||||
* This function enables the channel request. User can call this function after submitting the transfer request
|
||||
* or before submitting the transfer request.
|
||||
*
|
||||
* @param handle DMA handle pointer.
|
||||
*/
|
||||
void DMA_StartTransfer(dma_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief DMA IRQ handler for descriptor transfer complete.
|
||||
*
|
||||
* This function clears the channel major interrupt flag and call
|
||||
* the callback function if it is not NULL.
|
||||
*/
|
||||
void DMA_HandleIRQ(void);
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* @} */
|
||||
|
||||
#endif /*_FSL_DMA_H_*/
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_dmic.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
/* Array of DMIC peripheral base address. */
|
||||
static DMIC_Type *const s_dmicBases[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_BASE_PTRS;
|
||||
|
||||
/* Array of DMIC clock name. */
|
||||
static const clock_ip_name_t s_dmicClock[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_CLOCKS;
|
||||
|
||||
/* Array of DMIC IRQ number. */
|
||||
static const IRQn_Type s_dmicIRQ[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_IRQS;
|
||||
|
||||
/*! @brief Callback function array for DMIC(s). */
|
||||
static dmic_callback_t s_dmicCallback[FSL_FEATURE_SOC_DMIC_COUNT];
|
||||
|
||||
/* Array of HWVAD IRQ number. */
|
||||
static const IRQn_Type s_dmicHwvadIRQ[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_HWVAD_IRQS;
|
||||
|
||||
/*! @brief Callback function array for HWVAD(s). */
|
||||
static dmic_hwvad_callback_t s_dmicHwvadCallback[FSL_FEATURE_SOC_DMIC_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the DMIC instance from peripheral base address.
|
||||
*
|
||||
* @param base DMIC peripheral base address.
|
||||
* @return DMIC instance.
|
||||
*/
|
||||
uint32_t DMIC_GetInstance(DMIC_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_DMIC_COUNT; instance++)
|
||||
{
|
||||
if (s_dmicBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_DMIC_COUNT);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void DMIC_Init(DMIC_Type *base)
|
||||
{
|
||||
assert(base);
|
||||
|
||||
/* Enable the clock to the register interface */
|
||||
CLOCK_EnableClock(s_dmicClock[DMIC_GetInstance(base)]);
|
||||
|
||||
/* Reset the peripheral */
|
||||
RESET_PeripheralReset(kDMIC_RST_SHIFT_RSTn);
|
||||
|
||||
/* Disable DMA request*/
|
||||
base->CHANNEL[0].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
|
||||
base->CHANNEL[1].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
|
||||
|
||||
/* Disable DMIC interrupt. */
|
||||
base->CHANNEL[0].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
|
||||
base->CHANNEL[1].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
|
||||
}
|
||||
|
||||
void DMIC_DeInit(DMIC_Type *base)
|
||||
{
|
||||
assert(base);
|
||||
/* Disable the clock to the register interface */
|
||||
CLOCK_DisableClock(s_dmicClock[DMIC_GetInstance(base)]);
|
||||
}
|
||||
|
||||
void DMIC_ConfigIO(DMIC_Type *base, dmic_io_t config)
|
||||
{
|
||||
base->IOCFG = config;
|
||||
}
|
||||
|
||||
void DMIC_SetOperationMode(DMIC_Type *base, operation_mode_t mode)
|
||||
{
|
||||
if (mode == kDMIC_OperationModeInterrupt)
|
||||
{
|
||||
/* Enable DMIC interrupt. */
|
||||
base->CHANNEL[0].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
|
||||
base->CHANNEL[1].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
|
||||
}
|
||||
if (mode == kDMIC_OperationModeDma)
|
||||
{
|
||||
/* enable DMA request*/
|
||||
base->CHANNEL[0].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
|
||||
base->CHANNEL[1].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DMIC_ConfigChannel(DMIC_Type *base,
|
||||
dmic_channel_t channel,
|
||||
stereo_side_t side,
|
||||
dmic_channel_config_t *channel_config)
|
||||
{
|
||||
base->CHANNEL[channel].DIVHFCLK = channel_config->divhfclk;
|
||||
base->CHANNEL[channel].OSR = channel_config->osr;
|
||||
base->CHANNEL[channel].GAINSHIFT = channel_config->gainshft;
|
||||
base->CHANNEL[channel].PREAC2FSCOEF = channel_config->preac2coef;
|
||||
base->CHANNEL[channel].PREAC4FSCOEF = channel_config->preac4coef;
|
||||
base->CHANNEL[channel].PHY_CTRL =
|
||||
DMIC_CHANNEL_PHY_CTRL_PHY_FALL(side) | DMIC_CHANNEL_PHY_CTRL_PHY_HALF(channel_config->sample_rate);
|
||||
base->CHANNEL[channel].DC_CTRL = DMIC_CHANNEL_DC_CTRL_DCPOLE(channel_config->dc_cut_level) |
|
||||
DMIC_CHANNEL_DC_CTRL_DCGAIN(channel_config->post_dc_gain_reduce) |
|
||||
DMIC_CHANNEL_DC_CTRL_SATURATEAT16BIT(channel_config->saturate16bit);
|
||||
}
|
||||
|
||||
void DMIC_CfgChannelDc(DMIC_Type *base,
|
||||
dmic_channel_t channel,
|
||||
dc_removal_t dc_cut_level,
|
||||
uint32_t post_dc_gain_reduce,
|
||||
bool saturate16bit)
|
||||
{
|
||||
base->CHANNEL[channel].DC_CTRL = DMIC_CHANNEL_DC_CTRL_DCPOLE(dc_cut_level) |
|
||||
DMIC_CHANNEL_DC_CTRL_DCGAIN(post_dc_gain_reduce) |
|
||||
DMIC_CHANNEL_DC_CTRL_SATURATEAT16BIT(saturate16bit);
|
||||
}
|
||||
|
||||
void DMIC_Use2fs(DMIC_Type *base, bool use2fs)
|
||||
{
|
||||
base->USE2FS = (use2fs) ? 0x1 : 0x0;
|
||||
}
|
||||
|
||||
void DMIC_EnableChannnel(DMIC_Type *base, uint32_t channelmask)
|
||||
{
|
||||
base->CHANEN = channelmask;
|
||||
}
|
||||
|
||||
void DMIC_FifoChannel(DMIC_Type *base, uint32_t channel, uint32_t trig_level, uint32_t enable, uint32_t resetn)
|
||||
{
|
||||
base->CHANNEL[channel].FIFO_CTRL |=
|
||||
(base->CHANNEL[channel].FIFO_CTRL & (DMIC_CHANNEL_FIFO_CTRL_INTEN_MASK | DMIC_CHANNEL_FIFO_CTRL_DMAEN_MASK)) |
|
||||
DMIC_CHANNEL_FIFO_CTRL_TRIGLVL(trig_level) | DMIC_CHANNEL_FIFO_CTRL_ENABLE(enable) |
|
||||
DMIC_CHANNEL_FIFO_CTRL_RESETN(resetn);
|
||||
}
|
||||
|
||||
void DMIC_EnableIntCallback(DMIC_Type *base, dmic_callback_t cb)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = DMIC_GetInstance(base);
|
||||
NVIC_ClearPendingIRQ(s_dmicIRQ[instance]);
|
||||
/* Save callback pointer */
|
||||
s_dmicCallback[instance] = cb;
|
||||
EnableIRQ(s_dmicIRQ[instance]);
|
||||
}
|
||||
|
||||
void DMIC_DisableIntCallback(DMIC_Type *base, dmic_callback_t cb)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = DMIC_GetInstance(base);
|
||||
DisableIRQ(s_dmicIRQ[instance]);
|
||||
s_dmicCallback[instance] = NULL;
|
||||
NVIC_ClearPendingIRQ(s_dmicIRQ[instance]);
|
||||
}
|
||||
|
||||
void DMIC_HwvadEnableIntCallback(DMIC_Type *base, dmic_hwvad_callback_t vadcb)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = DMIC_GetInstance(base);
|
||||
NVIC_ClearPendingIRQ(s_dmicHwvadIRQ[instance]);
|
||||
/* Save callback pointer */
|
||||
s_dmicHwvadCallback[instance] = vadcb;
|
||||
EnableIRQ(s_dmicHwvadIRQ[instance]);
|
||||
}
|
||||
|
||||
void DMIC_HwvadDisableIntCallback(DMIC_Type *base, dmic_hwvad_callback_t vadcb)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = DMIC_GetInstance(base);
|
||||
DisableIRQ(s_dmicHwvadIRQ[instance]);
|
||||
s_dmicHwvadCallback[instance] = NULL;
|
||||
NVIC_ClearPendingIRQ(s_dmicHwvadIRQ[instance]);
|
||||
}
|
||||
|
||||
/* IRQ handler functions overloading weak symbols in the startup */
|
||||
#if defined(DMIC0)
|
||||
/*DMIC0 IRQ handler */
|
||||
void DMIC0_DriverIRQHandler(void)
|
||||
{
|
||||
if (s_dmicCallback[0] != NULL)
|
||||
{
|
||||
s_dmicCallback[0]();
|
||||
}
|
||||
}
|
||||
/*DMIC0 HWVAD IRQ handler */
|
||||
void HWVAD0_IRQHandler(void)
|
||||
{
|
||||
if (s_dmicHwvadCallback[0] != NULL)
|
||||
{
|
||||
s_dmicHwvadCallback[0]();
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_DMIC_H_
|
||||
#define _FSL_DMIC_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup dmic_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @name DMIC version
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @brief DMIC driver version 2.0.0. */
|
||||
#define FSL_DMIC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*! @brief DMIC different operation modes. */
|
||||
typedef enum _operation_mode
|
||||
{
|
||||
kDMIC_OperationModePoll = 0U, /*!< Polling mode */
|
||||
kDMIC_OperationModeInterrupt = 1U, /*!< Interrupt mode */
|
||||
kDMIC_OperationModeDma = 2U, /*!< DMA mode */
|
||||
} operation_mode_t;
|
||||
|
||||
/*! @brief DMIC left/right values. */
|
||||
typedef enum _stereo_side
|
||||
{
|
||||
kDMIC_Left = 0U, /*!< Left Stereo channel */
|
||||
kDMIC_Right = 1U, /*!< Right Stereo channel */
|
||||
} stereo_side_t;
|
||||
|
||||
/*! @brief DMIC Clock pre-divider values. */
|
||||
typedef enum
|
||||
{
|
||||
kDMIC_PdmDiv1 = 0U, /*!< DMIC pre-divider set in divide by 1 */
|
||||
kDMIC_PdmDiv2 = 1U, /*!< DMIC pre-divider set in divide by 2 */
|
||||
kDMIC_PdmDiv3 = 2U, /*!< DMIC pre-divider set in divide by 3 */
|
||||
kDMIC_PdmDiv4 = 3U, /*!< DMIC pre-divider set in divide by 4 */
|
||||
kDMIC_PdmDiv6 = 4U, /*!< DMIC pre-divider set in divide by 6 */
|
||||
kDMIC_PdmDiv8 = 5U, /*!< DMIC pre-divider set in divide by 8 */
|
||||
kDMIC_PdmDiv12 = 6U, /*!< DMIC pre-divider set in divide by 12 */
|
||||
kDMIC_PdmDiv16 = 7U, /*!< DMIC pre-divider set in divide by 16*/
|
||||
kDMIC_PdmDiv24 = 8U, /*!< DMIC pre-divider set in divide by 24*/
|
||||
kDMIC_PdmDiv32 = 9U, /*!< DMIC pre-divider set in divide by 32 */
|
||||
kDMIC_PdmDiv48 = 10U, /*!< DMIC pre-divider set in divide by 48 */
|
||||
kDMIC_PdmDiv64 = 11U, /*!< DMIC pre-divider set in divide by 64*/
|
||||
kDMIC_PdmDiv96 = 12U, /*!< DMIC pre-divider set in divide by 96*/
|
||||
kDMIC_PdmDiv128 = 13U, /*!< DMIC pre-divider set in divide by 128 */
|
||||
} pdm_div_t;
|
||||
|
||||
/*! @brief Pre-emphasis Filter coefficient value for 2FS and 4FS modes. */
|
||||
typedef enum _compensation
|
||||
{
|
||||
kDMIC_CompValueZero = 0U, /*!< Compensation 0 */
|
||||
kDMIC_CompValueNegativePoint16 = 1U, /*!< Compensation -0.16 */
|
||||
kDMIC_CompValueNegativePoint15 = 2U, /*!< Compensation -0.15 */
|
||||
kDMIC_CompValueNegativePoint13 = 3U, /*!< Compensation -0.13 */
|
||||
} compensation_t;
|
||||
|
||||
/*! @brief DMIC DC filter control values. */
|
||||
typedef enum _dc_removal
|
||||
{
|
||||
kDMIC_DcNoRemove = 0U, /*!< Flat response no filter */
|
||||
kDMIC_DcCut155 = 1U, /*!< Cut off Frequency is 155 Hz */
|
||||
kDMIC_DcCut78 = 2U, /*!< Cut off Frequency is 78 Hz */
|
||||
kDMIC_DcCut39 = 3U, /*!< Cut off Frequency is 39 Hz */
|
||||
} dc_removal_t;
|
||||
|
||||
/*! @brief DMIC IO configiration. */
|
||||
typedef enum _dmic_io
|
||||
{
|
||||
kDMIC_PdmDual = 0U, /*!< Two separate pairs of PDM wires */
|
||||
kDMIC_PdmStereo = 4U, /*!< Stereo Mic */
|
||||
kDMIC_PdmBypass = 3U, /*!< Clk Bypass clocks both channels */
|
||||
kDMIC_PdmBypassClk0 = 1U, /*!< Clk Bypass clocks only channel0 */
|
||||
kDMIC_PdmBypassClk1 = 2U, /*!< Clk Bypas clocks only channel1 */
|
||||
} dmic_io_t;
|
||||
|
||||
/*! @brief DMIC Channel number. */
|
||||
typedef enum _dmic_channel
|
||||
{
|
||||
kDMIC_Channel0 = 0U, /*!< DMIC channel 0 */
|
||||
kDMIC_Channel1 = 1U, /*!< DMIC channel 1 */
|
||||
} dmic_channel_t;
|
||||
|
||||
/*! @brief DMIC and decimator sample rates. */
|
||||
typedef enum _dmic_phy_sample_rate
|
||||
{
|
||||
kDMIC_PhyFullSpeed = 0U, /*!< Decimator gets one sample per each chosen clock edge of PDM interface */
|
||||
kDMIC_PhyHalfSpeed = 1U, /*!< PDM clock to Microphone is halved, decimator receives each sample twice */
|
||||
} dmic_phy_sample_rate_t;
|
||||
|
||||
/*! @brief DMIC transfer status.*/
|
||||
enum _dmic_status
|
||||
{
|
||||
kStatus_DMIC_Busy = MAKE_STATUS(kStatusGroup_DMIC, 0), /*!< DMIC is busy */
|
||||
kStatus_DMIC_Idle = MAKE_STATUS(kStatusGroup_DMIC, 1), /*!< DMIC is idle */
|
||||
kStatus_DMIC_OverRunError = MAKE_STATUS(kStatusGroup_DMIC, 2), /*!< DMIC over run Error */
|
||||
kStatus_DMIC_UnderRunError = MAKE_STATUS(kStatusGroup_DMIC, 3), /*!< DMIC under run Error */
|
||||
};
|
||||
|
||||
/*! @brief DMIC Channel configuration structure. */
|
||||
typedef struct _dmic_channel_config
|
||||
{
|
||||
pdm_div_t divhfclk; /*!< DMIC Clock pre-divider values */
|
||||
uint32_t osr; /*!< oversampling rate(CIC decimation rate) for PCM */
|
||||
int32_t gainshft; /*!< 4FS PCM data gain control */
|
||||
compensation_t preac2coef; /*!< Pre-emphasis Filter coefficient value for 2FS */
|
||||
compensation_t preac4coef; /*!< Pre-emphasis Filter coefficient value for 4FS */
|
||||
dc_removal_t dc_cut_level; /*!< DMIC DC filter control values. */
|
||||
uint32_t post_dc_gain_reduce; /*!< Fine gain adjustment in the form of a number of bits to downshift */
|
||||
dmic_phy_sample_rate_t sample_rate; /*!< DMIC and decimator sample rates */
|
||||
bool saturate16bit; /*!< Selects 16-bit saturation. 0 means results roll over if out range and do not saturate.
|
||||
1 means if the result overflows, it saturates at 0xFFFF for positive overflow and
|
||||
0x8000 for negative overflow.*/
|
||||
} dmic_channel_config_t;
|
||||
|
||||
/*! @brief DMIC Callback function. */
|
||||
typedef void (*dmic_callback_t)(void);
|
||||
|
||||
/*! @brief HWVAD Callback function. */
|
||||
typedef void (*dmic_hwvad_callback_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Get the DMIC instance from peripheral base address.
|
||||
*
|
||||
* @param base DMIC peripheral base address.
|
||||
* @return DMIC instance.
|
||||
*/
|
||||
uint32_t DMIC_GetInstance(DMIC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Turns DMIC Clock on
|
||||
* @param base : DMIC base
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_Init(DMIC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Turns DMIC Clock off
|
||||
* @param base : DMIC base
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_DeInit(DMIC_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configure DMIC io
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param config : DMIC io configuration
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_ConfigIO(DMIC_Type *base, dmic_io_t config);
|
||||
|
||||
/*!
|
||||
* @brief Set DMIC operating mode
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param mode : DMIC mode
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_SetOperationMode(DMIC_Type *base, operation_mode_t mode);
|
||||
|
||||
/*!
|
||||
* @brief Configure DMIC channel
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param channel : DMIC channel
|
||||
* @param side : stereo_side_t, choice of left or right
|
||||
* @param channel_config : Channel configuration
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_ConfigChannel(DMIC_Type *base,
|
||||
dmic_channel_t channel,
|
||||
stereo_side_t side,
|
||||
dmic_channel_config_t *channel_config);
|
||||
|
||||
/*!
|
||||
* @brief Configure Clock scaling
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param use2fs : clock scaling
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_Use2fs(DMIC_Type *base, bool use2fs);
|
||||
|
||||
/*!
|
||||
* @brief Enable a particualr channel
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param channelmask : Channel selection
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_EnableChannnel(DMIC_Type *base, uint32_t channelmask);
|
||||
|
||||
/*!
|
||||
* @brief Configure fifo settings for DMIC channel
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param channel : DMIC channel
|
||||
* @param trig_level : FIFO trigger level
|
||||
* @param enable : FIFO level
|
||||
* @param resetn : FIFO reset
|
||||
* @return Nothing
|
||||
*/
|
||||
void DMIC_FifoChannel(DMIC_Type *base, uint32_t channel, uint32_t trig_level, uint32_t enable, uint32_t resetn);
|
||||
|
||||
/*!
|
||||
* @brief Get FIFO status
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param channel : DMIC channel
|
||||
* @return FIFO status
|
||||
*/
|
||||
static inline uint32_t DMIC_FifoGetStatus(DMIC_Type *base, uint32_t channel)
|
||||
{
|
||||
return base->CHANNEL[channel].FIFO_STATUS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear FIFO status
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param channel : DMIC channel
|
||||
* @param mask : Bits to be cleared
|
||||
* @return FIFO status
|
||||
*/
|
||||
static inline void DMIC_FifoClearStatus(DMIC_Type *base, uint32_t channel, uint32_t mask)
|
||||
{
|
||||
base->CHANNEL[channel].FIFO_STATUS = mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get FIFO data
|
||||
* @param base : The base address of DMIC interface
|
||||
* @param channel : DMIC channel
|
||||
* @return FIFO data
|
||||
*/
|
||||
static inline uint32_t DMIC_FifoGetData(DMIC_Type *base, uint32_t channel)
|
||||
{
|
||||
return base->CHANNEL[channel].FIFO_DATA;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable callback.
|
||||
|
||||
* This function enables the interrupt for the selected DMIC peripheral.
|
||||
* The callback function is not enabled until this function is called.
|
||||
*
|
||||
* @param base Base address of the DMIC peripheral.
|
||||
* @param cb callback Pointer to store callback function.
|
||||
* @retval None.
|
||||
*/
|
||||
void DMIC_EnableIntCallback(DMIC_Type *base, dmic_callback_t cb);
|
||||
|
||||
/*!
|
||||
* @brief Disable callback.
|
||||
|
||||
* This function disables the interrupt for the selected DMIC peripheral.
|
||||
*
|
||||
* @param base Base address of the DMIC peripheral.
|
||||
* @param cb callback Pointer to store callback function..
|
||||
* @retval None.
|
||||
*/
|
||||
void DMIC_DisableIntCallback(DMIC_Type *base, dmic_callback_t cb);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @name hwvad
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Sets the gain value for the noise estimator.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @param value gain value for the noise estimator.
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void DMIC_SetGainNoiseEstHwvad(DMIC_Type *base, uint32_t value)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->HWVADTHGN = value & 0xFu;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the gain value for the signal estimator.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @param value gain value for the signal estimator.
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void DMIC_SetGainSignalEstHwvad(DMIC_Type *base, uint32_t value)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->HWVADTHGS = value & 0xFu;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the hwvad filter cutoff frequency parameter.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @param value cut off frequency value.
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void DMIC_SetFilterCtrlHwvad(DMIC_Type *base, uint32_t value)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->HWVADHPFS = value & 0x3u;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the input gain of hwvad.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @param value input gain value for hwvad.
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void DMIC_SetInputGainHwvad(DMIC_Type *base, uint32_t value)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->HWVADGAIN = value & 0xFu;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clears hwvad internal interrupt flag.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @param st10 bit value.
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void DMIC_CtrlClrIntrHwvad(DMIC_Type *base, bool st10)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->HWVADST10 = (st10) ? 0x1 : 0x0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Resets hwvad filters.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @param rstt Reset bit value.
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void DMIC_FilterResetHwvad(DMIC_Type *base, bool rstt)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->HWVADRSTT = (rstt) ? 0x1 : 0x0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the value from output of the filter z7.
|
||||
*
|
||||
* @param base DMIC base pointer
|
||||
* @retval output of filter z7.
|
||||
*/
|
||||
static inline uint16_t DMIC_GetNoiseEnvlpEst(DMIC_Type *base)
|
||||
{
|
||||
assert(NULL != base);
|
||||
return (base->HWVADLOWZ & 0xFFFFu);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable hwvad callback.
|
||||
|
||||
* This function enables the hwvad interrupt for the selected DMIC peripheral.
|
||||
* The callback function is not enabled until this function is called.
|
||||
*
|
||||
* @param base Base address of the DMIC peripheral.
|
||||
* @param vadcb callback Pointer to store callback function.
|
||||
* @retval None.
|
||||
*/
|
||||
void DMIC_HwvadEnableIntCallback(DMIC_Type *base, dmic_hwvad_callback_t vadcb);
|
||||
|
||||
/*!
|
||||
* @brief Disable callback.
|
||||
|
||||
* This function disables the hwvad interrupt for the selected DMIC peripheral.
|
||||
*
|
||||
* @param base Base address of the DMIC peripheral.
|
||||
* @param vadcb callback Pointer to store callback function..
|
||||
* @retval None.
|
||||
*/
|
||||
void DMIC_HwvadDisableIntCallback(DMIC_Type *base, dmic_hwvad_callback_t vadcb);
|
||||
|
||||
/*! @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* __FSL_DMIC_H */
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_dmic_dma.h"
|
||||
#include "fsl_dmic.h"
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
#define DMIC_HANDLE_ARRAY_SIZE 1
|
||||
|
||||
/*<! Structure definition for dmic_dma_handle_t. The structure is private. */
|
||||
typedef struct _dmic_dma_private_handle
|
||||
{
|
||||
DMIC_Type *base;
|
||||
dmic_dma_handle_t *handle;
|
||||
} dmic_dma_private_handle_t;
|
||||
|
||||
/*! @brief DMIC transfer state, which is used for DMIC transactiaonl APIs' internal state. */
|
||||
enum _dmic_dma_states_t
|
||||
{
|
||||
kDMIC_Idle = 0x0, /*!< DMIC is idle state */
|
||||
kDMIC_Busy /*!< DMIC is busy tranferring data. */
|
||||
};
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the DMIC instance from peripheral base address.
|
||||
*
|
||||
* @param base DMIC peripheral base address.
|
||||
* @return DMIC instance.
|
||||
*/
|
||||
extern uint32_t DMIC_GetInstance(DMIC_Type *base);
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*<! Private handle only used for internally. */
|
||||
static dmic_dma_private_handle_t s_dmaPrivateHandle[DMIC_HANDLE_ARRAY_SIZE];
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
********************************************************************************/
|
||||
|
||||
static void DMIC_TransferReceiveDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t intmode)
|
||||
{
|
||||
assert(handle);
|
||||
assert(param);
|
||||
|
||||
dmic_dma_private_handle_t *dmicPrivateHandle = (dmic_dma_private_handle_t *)param;
|
||||
dmicPrivateHandle->handle->state = kDMIC_Idle;
|
||||
|
||||
if (dmicPrivateHandle->handle->callback)
|
||||
{
|
||||
dmicPrivateHandle->handle->callback(dmicPrivateHandle->base, dmicPrivateHandle->handle, kStatus_DMIC_Idle,
|
||||
dmicPrivateHandle->handle->userData);
|
||||
}
|
||||
}
|
||||
|
||||
status_t DMIC_TransferCreateHandleDMA(DMIC_Type *base,
|
||||
dmic_dma_handle_t *handle,
|
||||
dmic_dma_transfer_callback_t callback,
|
||||
void *userData,
|
||||
dma_handle_t *rxDmaHandle)
|
||||
{
|
||||
int32_t instance = 0;
|
||||
|
||||
/* check 'base' */
|
||||
assert(!(NULL == base));
|
||||
if (NULL == base)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* check 'handle' */
|
||||
assert(!(NULL == handle));
|
||||
if (NULL == handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* check DMIC instance by 'base'*/
|
||||
instance = DMIC_GetInstance(base);
|
||||
assert(!(instance < 0));
|
||||
if (instance < 0)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
/* assign 'base' and 'handle' */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
handle->rxDmaHandle = rxDmaHandle;
|
||||
|
||||
/* Set DMIC state to idle */
|
||||
handle->state = kDMIC_Idle;
|
||||
/* Configure RX. */
|
||||
if (rxDmaHandle)
|
||||
{
|
||||
DMA_SetCallback(rxDmaHandle, DMIC_TransferReceiveDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t DMIC_TransferReceiveDMA(DMIC_Type *base,
|
||||
dmic_dma_handle_t *handle,
|
||||
dmic_transfer_t *xfer,
|
||||
uint32_t dmic_channel)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->rxDmaHandle);
|
||||
assert(xfer);
|
||||
assert(xfer->data);
|
||||
assert(xfer->dataSize);
|
||||
|
||||
dma_transfer_config_t xferConfig;
|
||||
status_t status;
|
||||
|
||||
/* Check if the device is busy. If previous RX not finished.*/
|
||||
if (handle->state == kDMIC_Busy)
|
||||
{
|
||||
status = kStatus_DMIC_Busy;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->state = kDMIC_Busy;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
|
||||
/* Prepare transfer. */
|
||||
DMA_PrepareTransfer(&xferConfig, (void *)&base->CHANNEL[dmic_channel].FIFO_DATA, xfer->data, sizeof(uint16_t),
|
||||
xfer->dataSize, kDMA_PeripheralToMemory, NULL);
|
||||
|
||||
/* Submit transfer. */
|
||||
DMA_SubmitTransfer(handle->rxDmaHandle, &xferConfig);
|
||||
|
||||
DMA_StartTransfer(handle->rxDmaHandle);
|
||||
|
||||
status = kStatus_Success;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void DMIC_TransferAbortReceiveDMA(DMIC_Type *base, dmic_dma_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
assert(NULL != handle->rxDmaHandle);
|
||||
|
||||
/* Stop transfer. */
|
||||
DMA_AbortTransfer(handle->rxDmaHandle);
|
||||
handle->state = kDMIC_Idle;
|
||||
}
|
||||
|
||||
status_t DMIC_TransferGetReceiveCountDMA(DMIC_Type *base, dmic_dma_handle_t *handle, uint32_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->rxDmaHandle);
|
||||
assert(count);
|
||||
|
||||
if (kDMIC_Idle == handle->state)
|
||||
{
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->transferSize - DMA_GetRemainingBytes(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_DMIC_DMA_H_
|
||||
#define _FSL_DMIC_DMA_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_dma.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup dmic_dma_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief DMIC transfer structure. */
|
||||
typedef struct _dmic_transfer
|
||||
{
|
||||
uint16_t *data; /*!< The buffer of data to be transfer.*/
|
||||
size_t dataSize; /*!< The byte count to be transfer. */
|
||||
} dmic_transfer_t;
|
||||
|
||||
/* Forward declaration of the handle typedef. */
|
||||
typedef struct _dmic_dma_handle dmic_dma_handle_t;
|
||||
|
||||
/*! @brief DMIC transfer callback function. */
|
||||
typedef void (*dmic_dma_transfer_callback_t)(DMIC_Type *base,
|
||||
dmic_dma_handle_t *handle,
|
||||
status_t status,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
* @brief DMIC DMA handle
|
||||
*/
|
||||
struct _dmic_dma_handle
|
||||
{
|
||||
DMIC_Type *base; /*!< DMIC peripheral base address. */
|
||||
dma_handle_t *rxDmaHandle; /*!< The DMA RX channel used. */
|
||||
dmic_dma_transfer_callback_t callback; /*!< Callback function. */
|
||||
void *userData; /*!< DMIC callback function parameter.*/
|
||||
size_t transferSize; /*!< Size of the data to receive. */
|
||||
volatile uint8_t state; /*!< Internal state of DMIC DMA transfer */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* _cplusplus */
|
||||
|
||||
/*!
|
||||
* @name DMA transactional
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes the DMIC handle which is used in transactional functions.
|
||||
* @param base DMIC peripheral base address.
|
||||
* @param handle Pointer to dmic_dma_handle_t structure.
|
||||
* @param callback Callback function.
|
||||
* @param userData User data.
|
||||
* @param rxDmaHandle User-requested DMA handle for RX DMA transfer.
|
||||
*/
|
||||
status_t DMIC_TransferCreateHandleDMA(DMIC_Type *base,
|
||||
dmic_dma_handle_t *handle,
|
||||
dmic_dma_transfer_callback_t callback,
|
||||
void *userData,
|
||||
dma_handle_t *rxDmaHandle);
|
||||
|
||||
/*!
|
||||
* @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 USART peripheral base address.
|
||||
* @param handle Pointer to usart_dma_handle_t structure.
|
||||
* @param xfer DMIC DMA transfer structure. See #dmic_transfer_t.
|
||||
* @param dmic_channel DMIC channel
|
||||
* @retval kStatus_Success
|
||||
*/
|
||||
status_t DMIC_TransferReceiveDMA(DMIC_Type *base,
|
||||
dmic_dma_handle_t *handle,
|
||||
dmic_transfer_t *xfer,
|
||||
uint32_t dmic_channel);
|
||||
|
||||
/*!
|
||||
* @brief Aborts the received data using DMA.
|
||||
*
|
||||
* This function aborts the received data using DMA.
|
||||
*
|
||||
* @param base DMIC peripheral base address
|
||||
* @param handle Pointer to dmic_dma_handle_t structure
|
||||
*/
|
||||
void DMIC_TransferAbortReceiveDMA(DMIC_Type *base, dmic_dma_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 DMIC peripheral base address.
|
||||
* @param handle DMIC 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 count;
|
||||
*/
|
||||
status_t DMIC_TransferGetReceiveCountDMA(DMIC_Type *base, dmic_dma_handle_t *handle, uint32_t *count);
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_DMIC_DMA_H_ */
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_flashiap.h"
|
||||
|
||||
#define HZ_TO_KHZ_DIV 1000
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
static status_t translate_iap_status(uint32_t status)
|
||||
{
|
||||
/* Translate IAP return code to sdk status code */
|
||||
if (status == kStatus_Success)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MAKE_STATUS(kStatusGroup_FLASHIAP, status);
|
||||
}
|
||||
}
|
||||
|
||||
status_t FLASHIAP_PrepareSectorForWrite(uint32_t startSector, uint32_t endSector)
|
||||
{
|
||||
uint32_t command[5], result[4];
|
||||
|
||||
command[0] = kIapCmd_FLASHIAP_PrepareSectorforWrite;
|
||||
command[1] = startSector;
|
||||
command[2] = endSector;
|
||||
iap_entry(command, result);
|
||||
|
||||
return translate_iap_status(result[0]);
|
||||
}
|
||||
|
||||
status_t FLASHIAP_CopyRamToFlash(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes, uint32_t systemCoreClock)
|
||||
{
|
||||
uint32_t command[5], result[4];
|
||||
|
||||
command[0] = kIapCmd_FLASHIAP_CopyRamToFlash;
|
||||
command[1] = dstAddr;
|
||||
command[2] = (uint32_t)srcAddr;
|
||||
command[3] = numOfBytes;
|
||||
command[4] = systemCoreClock / HZ_TO_KHZ_DIV;
|
||||
iap_entry(command, result);
|
||||
|
||||
return translate_iap_status(result[0]);
|
||||
}
|
||||
|
||||
status_t FLASHIAP_EraseSector(uint32_t startSector, uint32_t endSector, uint32_t systemCoreClock)
|
||||
{
|
||||
uint32_t command[5], result[4];
|
||||
|
||||
command[0] = kIapCmd_FLASHIAP_EraseSector;
|
||||
command[1] = startSector;
|
||||
command[2] = endSector;
|
||||
command[3] = systemCoreClock / HZ_TO_KHZ_DIV;
|
||||
iap_entry(command, result);
|
||||
|
||||
return translate_iap_status(result[0]);
|
||||
}
|
||||
|
||||
status_t FLASHIAP_ErasePage(uint32_t startPage, uint32_t endPage, uint32_t systemCoreClock)
|
||||
{
|
||||
uint32_t command[5], result[4];
|
||||
|
||||
command[0] = kIapCmd_FLASHIAP_ErasePage;
|
||||
command[1] = startPage;
|
||||
command[2] = endPage;
|
||||
command[3] = systemCoreClock / HZ_TO_KHZ_DIV;
|
||||
iap_entry(command, result);
|
||||
|
||||
return translate_iap_status(result[0]);
|
||||
}
|
||||
|
||||
status_t FLASHIAP_BlankCheckSector(uint32_t startSector, uint32_t endSector)
|
||||
{
|
||||
uint32_t command[5], result[4];
|
||||
|
||||
command[0] = kIapCmd_FLASHIAP_BlankCheckSector;
|
||||
command[1] = startSector;
|
||||
command[2] = endSector;
|
||||
iap_entry(command, result);
|
||||
|
||||
return translate_iap_status(result[0]);
|
||||
}
|
||||
|
||||
status_t FLASHIAP_Compare(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes)
|
||||
{
|
||||
uint32_t command[5], result[4];
|
||||
|
||||
command[0] = kIapCmd_FLASHIAP_Compare;
|
||||
command[1] = dstAddr;
|
||||
command[2] = (uint32_t)srcAddr;
|
||||
command[3] = numOfBytes;
|
||||
iap_entry(command, result);
|
||||
|
||||
return translate_iap_status(result[0]);
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_FLASHIAP_H_
|
||||
#define _FSL_FLASHIAP_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup flashiap_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
#define FSL_FLASHIAP_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Flashiap status codes.
|
||||
*/
|
||||
enum _flashiap_status
|
||||
{
|
||||
kStatus_FLASHIAP_Success = kStatus_Success, /*!< Api is executed successfully */
|
||||
kStatus_FLASHIAP_InvalidCommand = MAKE_STATUS(kStatusGroup_FLASHIAP, 1U), /*!< Invalid command */
|
||||
kStatus_FLASHIAP_SrcAddrError =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 2U), /*!< Source address is not on word boundary */
|
||||
kStatus_FLASHIAP_DstAddrError =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 3U), /*!< Destination address is not on a correct boundary */
|
||||
kStatus_FLASHIAP_SrcAddrNotMapped =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 4U), /*!< Source address is not mapped in the memory map */
|
||||
kStatus_FLASHIAP_DstAddrNotMapped =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 5U), /*!< Destination address is not mapped in the memory map */
|
||||
kStatus_FLASHIAP_CountError =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 6U), /*!< Byte count is not multiple of 4 or is not a permitted value */
|
||||
kStatus_FLASHIAP_InvalidSector =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP,
|
||||
7), /*!< Sector number is invalid or end sector number is greater than start sector number */
|
||||
kStatus_FLASHIAP_SectorNotblank = MAKE_STATUS(kStatusGroup_FLASHIAP, 8U), /*!< One or more sectors are not blank */
|
||||
kStatus_FLASHIAP_NotPrepared =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 9U), /*!< Command to prepare sector for write operation was not executed */
|
||||
kStatus_FLASHIAP_CompareError =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 10U), /*!< Destination and source memory contents do not match */
|
||||
kStatus_FLASHIAP_Busy =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 11U), /*!< Flash programming hardware interface is busy */
|
||||
kStatus_FLASHIAP_ParamError =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 12U), /*!< Insufficient number of parameters or invalid parameter */
|
||||
kStatus_FLASHIAP_AddrError = MAKE_STATUS(kStatusGroup_FLASHIAP, 13U), /*!< Address is not on word boundary */
|
||||
kStatus_FLASHIAP_AddrNotMapped =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 14U), /*!< Address is not mapped in the memory map */
|
||||
kStatus_FLASHIAP_NoPower = MAKE_STATUS(kStatusGroup_FLASHIAP, 24U), /*!< Flash memory block is powered down */
|
||||
kStatus_FLASHIAP_NoClock =
|
||||
MAKE_STATUS(kStatusGroup_FLASHIAP, 27U), /*!< Flash memory block or controller is not clocked */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Flashiap command codes.
|
||||
*/
|
||||
enum _flashiap_commands
|
||||
{
|
||||
kIapCmd_FLASHIAP_PrepareSectorforWrite = 50U, /*!< Prepare Sector for write */
|
||||
kIapCmd_FLASHIAP_CopyRamToFlash = 51U, /*!< Copy RAM to flash */
|
||||
kIapCmd_FLASHIAP_EraseSector = 52U, /*!< Erase Sector */
|
||||
kIapCmd_FLASHIAP_BlankCheckSector = 53U, /*!< Blank check sector */
|
||||
kIapCmd_FLASHIAP_ReadPartId = 54U, /*!< Read part id */
|
||||
kIapCmd_FLASHIAP_Read_BootromVersion = 55U, /*!< Read bootrom version */
|
||||
kIapCmd_FLASHIAP_Compare = 56U, /*!< Compare */
|
||||
kIapCmd_FLASHIAP_ReinvokeISP = 57U, /*!< Reinvoke ISP */
|
||||
kIapCmd_FLASHIAP_ReadUid = 58U, /*!< Read Uid isp */
|
||||
kIapCmd_FLASHIAP_ErasePage = 59U, /*!< Erase Page */
|
||||
kIapCmd_FLASHIAP_ReadMisr = 70U, /*!< Read Misr */
|
||||
kIapCmd_FLASHIAP_ReinvokeI2cSpiISP = 71U /*!< Reinvoke I2C/SPI isp */
|
||||
};
|
||||
|
||||
/*! @brief IAP_ENTRY API function type */
|
||||
typedef void (*IAP_ENTRY_T)(uint32_t cmd[5], uint32_t stat[4]);
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief IAP_ENTRY API function type
|
||||
*
|
||||
* Wrapper for rom iap call
|
||||
*
|
||||
* @param cmd_param IAP command and relevant parameter array.
|
||||
* @param status_result IAP status result array.
|
||||
*
|
||||
* @retval None. Status/Result is returned via status_result array.
|
||||
*/
|
||||
static inline void iap_entry(uint32_t *cmd_param, uint32_t *status_result)
|
||||
{
|
||||
((IAP_ENTRY_T)FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION)(cmd_param, status_result);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Prepare sector for write operation
|
||||
|
||||
* This function prepares sector(s) for write/erase operation. This function must be
|
||||
* called before calling the FLASHIAP_CopyRamToFlash() or FLASHIAP_EraseSector() or
|
||||
* FLASHIAP_ErasePage() function. The end sector must be greater than or equal to
|
||||
* start sector number.
|
||||
*
|
||||
* @param startSector Start sector number.
|
||||
* @param endSector End sector number.
|
||||
*
|
||||
* @retval #kStatus_FLASHIAP_Success Api was executed successfully.
|
||||
* @retval #kStatus_FLASHIAP_NoPower Flash memory block is powered down.
|
||||
* @retval #kStatus_FLASHIAP_NoClock Flash memory block or controller is not clocked.
|
||||
* @retval #kStatus_FLASHIAP_InvalidSector Sector number is invalid or end sector number
|
||||
* is greater than start sector number.
|
||||
* @retval #kStatus_FLASHIAP_Busy Flash programming hardware interface is busy.
|
||||
*/
|
||||
status_t FLASHIAP_PrepareSectorForWrite(uint32_t startSector, uint32_t endSector);
|
||||
|
||||
/*!
|
||||
* @brief Copy RAM to flash.
|
||||
|
||||
* This function programs the flash memory. Corresponding sectors must be prepared
|
||||
* via FLASHIAP_PrepareSectorForWrite before calling calling this function. The addresses
|
||||
* should be a 256 byte boundary and the number of bytes should be 256 | 512 | 1024 | 4096.
|
||||
*
|
||||
* @param dstAddr Destination flash address where data bytes are to be written.
|
||||
* @param srcAddr Source ram address from where data bytes are to be read.
|
||||
* @param numOfBytes Number of bytes to be written.
|
||||
* @param systemCoreClock SystemCoreClock in Hz. It is converted to KHz before calling the
|
||||
* rom IAP function.
|
||||
*
|
||||
* @retval #kStatus_FLASHIAP_Success Api was executed successfully.
|
||||
* @retval #kStatus_FLASHIAP_NoPower Flash memory block is powered down.
|
||||
* @retval #kStatus_FLASHIAP_NoClock Flash memory block or controller is not clocked.
|
||||
* @retval #kStatus_FLASHIAP_SrcAddrError Source address is not on word boundary.
|
||||
* @retval #kStatus_FLASHIAP_DstAddrError Destination address is not on a correct boundary.
|
||||
* @retval #kStatus_FLASHIAP_SrcAddrNotMapped Source address is not mapped in the memory map.
|
||||
* @retval #kStatus_FLASHIAP_DstAddrNotMapped Destination address is not mapped in the memory map.
|
||||
* @retval #kStatus_FLASHIAP_CountError Byte count is not multiple of 4 or is not a permitted value.
|
||||
* @retval #kStatus_FLASHIAP_NotPrepared Command to prepare sector for write operation was not executed.
|
||||
* @retval #kStatus_FLASHIAP_Busy Flash programming hardware interface is busy.
|
||||
*/
|
||||
status_t FLASHIAP_CopyRamToFlash(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes, uint32_t systemCoreClock);
|
||||
|
||||
/*!
|
||||
* @brief Erase sector
|
||||
|
||||
* This function erases sector(s). The end sector must be greater than or equal to
|
||||
* start sector number. FLASHIAP_PrepareSectorForWrite must be called before
|
||||
* calling this function.
|
||||
*
|
||||
* @param startSector Start sector number.
|
||||
* @param endSector End sector number.
|
||||
* @param systemCoreClock SystemCoreClock in Hz. It is converted to KHz before calling the
|
||||
* rom IAP function.
|
||||
*
|
||||
* @retval #kStatus_FLASHIAP_Success Api was executed successfully.
|
||||
* @retval #kStatus_FLASHIAP_NoPower Flash memory block is powered down.
|
||||
* @retval #kStatus_FLASHIAP_NoClock Flash memory block or controller is not clocked.
|
||||
* @retval #kStatus_FLASHIAP_InvalidSector Sector number is invalid or end sector number
|
||||
* is greater than start sector number.
|
||||
* @retval #kStatus_FLASHIAP_NotPrepared Command to prepare sector for write operation was not executed.
|
||||
* @retval #kStatus_FLASHIAP_Busy Flash programming hardware interface is busy.
|
||||
*/
|
||||
status_t FLASHIAP_EraseSector(uint32_t startSector, uint32_t endSector, uint32_t systemCoreClock);
|
||||
|
||||
/*!
|
||||
|
||||
* This function erases page(s). The end page must be greater than or equal to
|
||||
* start page number. Corresponding sectors must be prepared via FLASHIAP_PrepareSectorForWrite
|
||||
* before calling calling this function.
|
||||
*
|
||||
* @param startPage Start page number
|
||||
* @param endPage End page number
|
||||
* @param systemCoreClock SystemCoreClock in Hz. It is converted to KHz before calling the
|
||||
* rom IAP function.
|
||||
*
|
||||
* @retval #kStatus_FLASHIAP_Success Api was executed successfully.
|
||||
* @retval #kStatus_FLASHIAP_NoPower Flash memory block is powered down.
|
||||
* @retval #kStatus_FLASHIAP_NoClock Flash memory block or controller is not clocked.
|
||||
* @retval #kStatus_FLASHIAP_InvalidSector Page number is invalid or end page number
|
||||
* is greater than start page number
|
||||
* @retval #kStatus_FLASHIAP_NotPrepared Command to prepare sector for write operation was not executed.
|
||||
* @retval #kStatus_FLASHIAP_Busy Flash programming hardware interface is busy.
|
||||
*/
|
||||
status_t FLASHIAP_ErasePage(uint32_t startPage, uint32_t endPage, uint32_t systemCoreClock);
|
||||
|
||||
/*!
|
||||
* @brief Blank check sector(s)
|
||||
*
|
||||
* Blank check single or multiples sectors of flash memory. The end sector must be greater than or equal to
|
||||
* start sector number. It can be used to verify the sector eraseure after FLASHIAP_EraseSector call.
|
||||
*
|
||||
* @param startSector : Start sector number. Must be greater than or equal to start sector number
|
||||
* @param endSector : End sector number
|
||||
* @retval #kStatus_FLASHIAP_Success One or more sectors are in erased state.
|
||||
* @retval #kStatus_FLASHIAP_NoPower Flash memory block is powered down.
|
||||
* @retval #kStatus_FLASHIAP_NoClock Flash memory block or controller is not clocked.
|
||||
* @retval #kStatus_FLASHIAP_SectorNotblank One or more sectors are not blank.
|
||||
*/
|
||||
status_t FLASHIAP_BlankCheckSector(uint32_t startSector, uint32_t endSector);
|
||||
|
||||
/*!
|
||||
* @brief Compare memory contents of flash with ram.
|
||||
|
||||
* This function compares the contents of flash and ram. It can be used to verify the flash
|
||||
* memory contents after FLASHIAP_CopyRamToFlash call.
|
||||
*
|
||||
* @param dstAddr Destination flash address.
|
||||
* @param srcAddr Source ram address.
|
||||
* @param numOfBytes Number of bytes to be compared.
|
||||
*
|
||||
* @retval #kStatus_FLASHIAP_Success Contents of flash and ram match.
|
||||
* @retval #kStatus_FLASHIAP_NoPower Flash memory block is powered down.
|
||||
* @retval #kStatus_FLASHIAP_NoClock Flash memory block or controller is not clocked.
|
||||
* @retval #kStatus_FLASHIAP_AddrError Address is not on word boundary.
|
||||
* @retval #kStatus_FLASHIAP_AddrNotMapped Address is not mapped in the memory map.
|
||||
* @retval #kStatus_FLASHIAP_CountError Byte count is not multiple of 4 or is not a permitted value.
|
||||
* @retval #kStatus_FLASHIAP_CompareError Destination and source memory contents do not match.
|
||||
*/
|
||||
status_t FLASHIAP_Compare(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_FLASHIAP_H_ */
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Pointers to real IRQ handlers installed by drivers for each instance. */
|
||||
static flexcomm_irq_handler_t s_flexcommIrqHandler[FSL_FEATURE_SOC_FLEXCOMM_COUNT];
|
||||
|
||||
/*! @brief Pointers to handles for each instance to provide context to interrupt routines */
|
||||
static void *s_flexcommHandle[FSL_FEATURE_SOC_FLEXCOMM_COUNT];
|
||||
|
||||
/*! @brief Array to map FLEXCOMM instance number to IRQ number. */
|
||||
IRQn_Type const kFlexcommIrqs[] = USART_IRQS;
|
||||
|
||||
/*! @brief Array to map FLEXCOMM instance number to base address. */
|
||||
static const uint32_t s_flexcommBaseAddrs[FSL_FEATURE_SOC_FLEXCOMM_COUNT] = FLEXCOMM_BASE_ADDRS;
|
||||
|
||||
/*! @brief IDs of clock for each FLEXCOMM module */
|
||||
static const clock_ip_name_t s_flexcommClocks[] = FLEXCOMM_CLOCKS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
/* check whether flexcomm supports peripheral type */
|
||||
static bool FLEXCOMM_PeripheralIsPresent(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph)
|
||||
{
|
||||
if (periph == FLEXCOMM_PERIPH_NONE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ((periph >= FLEXCOMM_PERIPH_USART) && (periph <= FLEXCOMM_PERIPH_I2S_TX))
|
||||
{
|
||||
return (base->PSELID & (uint32_t)(1 << ((uint32_t)periph + 3))) > 0 ? true : false;
|
||||
}
|
||||
else if (periph == FLEXCOMM_PERIPH_I2S_RX)
|
||||
{
|
||||
return (base->PSELID & (1 << 7)) > 0 ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the index corresponding to the FLEXCOMM */
|
||||
uint32_t FLEXCOMM_GetInstance(void *base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FSL_FEATURE_SOC_FLEXCOMM_COUNT; i++)
|
||||
{
|
||||
if ((uint32_t)base == s_flexcommBaseAddrs[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Changes FLEXCOMM mode */
|
||||
status_t FLEXCOMM_SetPeriph(FLEXCOMM_Type *base, FLEXCOMM_PERIPH_T periph, int lock)
|
||||
{
|
||||
/* Check whether peripheral type is present */
|
||||
if (!FLEXCOMM_PeripheralIsPresent(base, periph))
|
||||
{
|
||||
return kStatus_OutOfRange;
|
||||
}
|
||||
|
||||
/* Flexcomm is locked to different peripheral type than expected */
|
||||
if ((base->PSELID & FLEXCOMM_PSELID_LOCK_MASK) && ((base->PSELID & FLEXCOMM_PSELID_PERSEL_MASK) != periph))
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* Check if we are asked to lock */
|
||||
if (lock)
|
||||
{
|
||||
base->PSELID = (uint32_t)periph | FLEXCOMM_PSELID_LOCK_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->PSELID = (uint32_t)periph;
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph)
|
||||
{
|
||||
int idx = FLEXCOMM_GetInstance(base);
|
||||
|
||||
if (idx < 0)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Enable the peripheral clock */
|
||||
CLOCK_EnableClock(s_flexcommClocks[idx]);
|
||||
|
||||
/* Set the FLEXCOMM to given peripheral */
|
||||
return FLEXCOMM_SetPeriph((FLEXCOMM_Type *)base, periph, 0);
|
||||
}
|
||||
|
||||
void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *handle)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Look up instance number */
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
|
||||
/* Clear handler first to avoid execution of the handler with wrong handle */
|
||||
s_flexcommIrqHandler[instance] = NULL;
|
||||
s_flexcommHandle[instance] = handle;
|
||||
s_flexcommIrqHandler[instance] = handler;
|
||||
}
|
||||
|
||||
/* IRQ handler functions overloading weak symbols in the startup */
|
||||
void FLEXCOMM0_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[0]);
|
||||
s_flexcommIrqHandler[0]((void *)s_flexcommBaseAddrs[0], s_flexcommHandle[0]);
|
||||
}
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 1U)
|
||||
void FLEXCOMM1_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[1]);
|
||||
s_flexcommIrqHandler[1]((void *)s_flexcommBaseAddrs[1], s_flexcommHandle[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 2U)
|
||||
void FLEXCOMM2_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[2]);
|
||||
s_flexcommIrqHandler[2]((void *)s_flexcommBaseAddrs[2], s_flexcommHandle[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 3U)
|
||||
void FLEXCOMM3_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[3]);
|
||||
s_flexcommIrqHandler[3]((void *)s_flexcommBaseAddrs[3], s_flexcommHandle[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 4U)
|
||||
void FLEXCOMM4_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[4]);
|
||||
s_flexcommIrqHandler[4]((void *)s_flexcommBaseAddrs[4], s_flexcommHandle[4]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 5U)
|
||||
void FLEXCOMM5_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[5]);
|
||||
s_flexcommIrqHandler[5]((void *)s_flexcommBaseAddrs[5], s_flexcommHandle[5]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 6U)
|
||||
void FLEXCOMM6_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[6]);
|
||||
s_flexcommIrqHandler[6]((void *)s_flexcommBaseAddrs[6], s_flexcommHandle[6]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_FLEXCOMM_COUNT > 7U)
|
||||
void FLEXCOMM7_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_flexcommIrqHandler[7]);
|
||||
s_flexcommIrqHandler[7]((void *)s_flexcommBaseAddrs[7], s_flexcommHandle[7]);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_FLEXCOMM_H_
|
||||
#define _FSL_FLEXCOMM_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup flexcomm_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @brief FLEXCOMM peripheral modes. */
|
||||
typedef enum
|
||||
{
|
||||
FLEXCOMM_PERIPH_NONE, /*!< No peripheral */
|
||||
FLEXCOMM_PERIPH_USART, /*!< USART peripheral */
|
||||
FLEXCOMM_PERIPH_SPI, /*!< SPI Peripheral */
|
||||
FLEXCOMM_PERIPH_I2C, /*!< I2C Peripheral */
|
||||
FLEXCOMM_PERIPH_I2S_TX, /*!< I2S TX Peripheral */
|
||||
FLEXCOMM_PERIPH_I2S_RX, /*!< I2S RX Peripheral */
|
||||
} FLEXCOMM_PERIPH_T;
|
||||
|
||||
/*! @brief Typedef for interrupt handler. */
|
||||
typedef void (*flexcomm_irq_handler_t)(void *base, void *handle);
|
||||
|
||||
/*! @brief Array with IRQ number for each FLEXCOMM module. */
|
||||
extern IRQn_Type const kFlexcommIrqs[];
|
||||
|
||||
/*! @brief Returns instance number for FLEXCOMM module with given base address. */
|
||||
uint32_t FLEXCOMM_GetInstance(void *base);
|
||||
|
||||
/*! @brief Initializes FLEXCOMM and selects peripheral mode according to the second parameter. */
|
||||
status_t FLEXCOMM_Init(void *base, FLEXCOMM_PERIPH_T periph);
|
||||
|
||||
/*! @brief Sets IRQ handler for given FLEXCOMM module. It is used by drivers register IRQ handler according to FLEXCOMM
|
||||
* mode */
|
||||
void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *handle);
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_FLEXCOMM_H_*/
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_fmeas.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
*******************************************************************************/
|
||||
|
||||
/*! @brief Target clock counter value.
|
||||
* According to user manual, 2 has to be subtracted from captured value (CAPVAL). */
|
||||
#define TARGET_CLOCK_COUNT(base) \
|
||||
((uint32_t)( \
|
||||
((((SYSCON_Type *)base)->FREQMECTRL & SYSCON_FREQMECTRL_CAPVAL_MASK) >> SYSCON_FREQMECTRL_CAPVAL_SHIFT) - 2))
|
||||
|
||||
/*! @brief Reference clock counter value. */
|
||||
#define REFERENCE_CLOCK_COUNT ((uint32_t)((SYSCON_FREQMECTRL_CAPVAL_MASK >> SYSCON_FREQMECTRL_CAPVAL_SHIFT) + 1))
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
uint32_t FMEAS_GetFrequency(SYSCON_Type *base, uint32_t refClockRate)
|
||||
{
|
||||
uint32_t targetClockCount = TARGET_CLOCK_COUNT(base);
|
||||
uint64_t clkrate = 0;
|
||||
|
||||
if (targetClockCount > 0)
|
||||
{
|
||||
clkrate = (((uint64_t)targetClockCount) * (uint64_t)refClockRate) / REFERENCE_CLOCK_COUNT;
|
||||
}
|
||||
|
||||
return (uint32_t)clkrate;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_FMEAS_H_
|
||||
#define _FSL_FMEAS_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup fmeas
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
*******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief Defines LPC Frequency Measure driver version 2.0.0.
|
||||
*
|
||||
* Change log:
|
||||
* - Version 2.0.0
|
||||
* - initial version
|
||||
*/
|
||||
#define FSL_FMEAS_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
*******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*!
|
||||
* @name FMEAS Functional Operation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Starts a frequency measurement cycle.
|
||||
*
|
||||
* @param base : SYSCON peripheral base address.
|
||||
*/
|
||||
static inline void FMEAS_StartMeasure(SYSCON_Type *base)
|
||||
{
|
||||
base->FREQMECTRL = 0;
|
||||
base->FREQMECTRL = (1UL << 31);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Indicates when a frequency measurement cycle is complete.
|
||||
*
|
||||
* @param base : SYSCON peripheral base address.
|
||||
* @return true if a measurement cycle is active, otherwise false.
|
||||
*/
|
||||
static inline bool FMEAS_IsMeasureComplete(SYSCON_Type *base)
|
||||
{
|
||||
return (bool)((base->FREQMECTRL & (1UL << 31)) == 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Returns the computed value for a frequency measurement cycle
|
||||
*
|
||||
* @param base : SYSCON peripheral base address.
|
||||
* @param refClockRate : Reference clock rate used during the frequency measurement cycle.
|
||||
*
|
||||
* @return Frequency in Hz.
|
||||
*/
|
||||
uint32_t FMEAS_GetFrequency(SYSCON_Type *base, uint32_t refClockRate);
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_FMEAS_H_ */
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_gint.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief Pointers to GINT bases for each instance. */
|
||||
static GINT_Type *const s_gintBases[FSL_FEATURE_SOC_GINT_COUNT] = GINT_BASE_PTRS;
|
||||
|
||||
/*! @brief Clocks for each instance. */
|
||||
static const clock_ip_name_t s_gintClocks[FSL_FEATURE_SOC_GINT_COUNT] = GINT_CLOCKS;
|
||||
|
||||
/*! @brief Resets for each instance. */
|
||||
static const reset_ip_name_t s_gintResets[FSL_FEATURE_SOC_GINT_COUNT] = GINT_RSTS;
|
||||
|
||||
/* @brief Irq number for each instance */
|
||||
static const IRQn_Type s_gintIRQ[FSL_FEATURE_SOC_GINT_COUNT] = GINT_IRQS;
|
||||
|
||||
/*! @brief Callback function array for GINT(s). */
|
||||
static gint_cb_t s_gintCallback[FSL_FEATURE_SOC_GINT_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
static uint32_t GINT_GetInstance(GINT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_GINT_COUNT; instance++)
|
||||
{
|
||||
if (s_gintBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_GINT_COUNT);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void GINT_Init(GINT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = GINT_GetInstance(base);
|
||||
|
||||
s_gintCallback[instance] = NULL;
|
||||
|
||||
/* Enable the peripheral clock */
|
||||
CLOCK_EnableClock(s_gintClocks[instance]);
|
||||
|
||||
/* Reset the peripheral */
|
||||
RESET_PeripheralReset(s_gintResets[instance]);
|
||||
}
|
||||
|
||||
void GINT_SetCtrl(GINT_Type *base, gint_comb_t comb, gint_trig_t trig, gint_cb_t callback)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = GINT_GetInstance(base);
|
||||
|
||||
base->CTRL = (GINT_CTRL_COMB(comb) | GINT_CTRL_TRIG(trig));
|
||||
|
||||
/* Save callback pointer */
|
||||
s_gintCallback[instance] = callback;
|
||||
}
|
||||
|
||||
void GINT_GetCtrl(GINT_Type *base, gint_comb_t *comb, gint_trig_t *trig, gint_cb_t *callback)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = GINT_GetInstance(base);
|
||||
|
||||
*comb = (gint_comb_t)((base->CTRL & GINT_CTRL_COMB_MASK) >> GINT_CTRL_COMB_SHIFT);
|
||||
*trig = (gint_trig_t)((base->CTRL & GINT_CTRL_TRIG_MASK) >> GINT_CTRL_TRIG_SHIFT);
|
||||
*callback = s_gintCallback[instance];
|
||||
}
|
||||
|
||||
void GINT_ConfigPins(GINT_Type *base, gint_port_t port, uint32_t polarityMask, uint32_t enableMask)
|
||||
{
|
||||
base->PORT_POL[port] = polarityMask;
|
||||
base->PORT_ENA[port] = enableMask;
|
||||
}
|
||||
|
||||
void GINT_GetConfigPins(GINT_Type *base, gint_port_t port, uint32_t *polarityMask, uint32_t *enableMask)
|
||||
{
|
||||
*polarityMask = base->PORT_POL[port];
|
||||
*enableMask = base->PORT_ENA[port];
|
||||
}
|
||||
|
||||
void GINT_EnableCallback(GINT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = GINT_GetInstance(base);
|
||||
/* If GINT is configured in "AND" mode a spurious interrupt is generated.
|
||||
Clear status and pending interrupt before enabling the irq in NVIC. */
|
||||
GINT_ClrStatus(base);
|
||||
NVIC_ClearPendingIRQ(s_gintIRQ[instance]);
|
||||
EnableIRQ(s_gintIRQ[instance]);
|
||||
}
|
||||
|
||||
void GINT_DisableCallback(GINT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = GINT_GetInstance(base);
|
||||
DisableIRQ(s_gintIRQ[instance]);
|
||||
GINT_ClrStatus(base);
|
||||
NVIC_ClearPendingIRQ(s_gintIRQ[instance]);
|
||||
}
|
||||
|
||||
void GINT_Deinit(GINT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
instance = GINT_GetInstance(base);
|
||||
|
||||
/* Cleanup */
|
||||
GINT_DisableCallback(base);
|
||||
s_gintCallback[instance] = NULL;
|
||||
|
||||
/* Reset the peripheral */
|
||||
RESET_PeripheralReset(s_gintResets[instance]);
|
||||
|
||||
/* Disable the peripheral clock */
|
||||
CLOCK_DisableClock(s_gintClocks[instance]);
|
||||
}
|
||||
|
||||
/* IRQ handler functions overloading weak symbols in the startup */
|
||||
void GINT0_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[0]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[0] != NULL)
|
||||
{
|
||||
s_gintCallback[0]();
|
||||
}
|
||||
}
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 1U)
|
||||
void GINT1_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[1]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[1] != NULL)
|
||||
{
|
||||
s_gintCallback[1]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 2U)
|
||||
void GINT2_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[2]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[2] != NULL)
|
||||
{
|
||||
s_gintCallback[2]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 3U)
|
||||
void GINT3_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[3]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[3] != NULL)
|
||||
{
|
||||
s_gintCallback[3]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 4U)
|
||||
void GINT4_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[4]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[4] != NULL)
|
||||
{
|
||||
s_gintCallback[4]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 5U)
|
||||
void GINT5_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[5]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[5] != NULL)
|
||||
{
|
||||
s_gintCallback[5]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 6U)
|
||||
void GINT6_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[6]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[6] != NULL)
|
||||
{
|
||||
s_gintCallback[6]();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_GINT_COUNT > 7U)
|
||||
void GINT7_DriverIRQHandler(void)
|
||||
{
|
||||
/* Clear interrupt before callback */
|
||||
s_gintBases[7]->CTRL |= GINT_CTRL_INT_MASK;
|
||||
/* Call user function */
|
||||
if (s_gintCallback[7] != NULL)
|
||||
{
|
||||
s_gintCallback[7]();
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_GINT_H_
|
||||
#define _FSL_GINT_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup gint_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
#define FSL_GINT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
|
||||
/*@}*/
|
||||
|
||||
/*! @brief GINT combine inputs type */
|
||||
typedef enum _gint_comb
|
||||
{
|
||||
kGINT_CombineOr = 0U, /*!< A grouped interrupt is generated when any one of the enabled inputs is active */
|
||||
kGINT_CombineAnd = 1U /*!< A grouped interrupt is generated when all enabled inputs are active */
|
||||
} gint_comb_t;
|
||||
|
||||
/*! @brief GINT trigger type */
|
||||
typedef enum _gint_trig
|
||||
{
|
||||
kGINT_TrigEdge = 0U, /*!< Edge triggered based on polarity */
|
||||
kGINT_TrigLevel = 1U /*!< Level triggered based on polarity */
|
||||
} gint_trig_t;
|
||||
|
||||
/* @brief GINT port type */
|
||||
typedef enum _gint_port
|
||||
{
|
||||
kGINT_Port0 = 0U,
|
||||
kGINT_Port1 = 1U,
|
||||
#if defined(FSL_FEATURE_GINT_PORT_COUNT) && (FSL_FEATURE_GINT_PORT_COUNT > 2U)
|
||||
kGINT_Port2 = 2U,
|
||||
#endif
|
||||
#if defined(FSL_FEATURE_GINT_PORT_COUNT) && (FSL_FEATURE_GINT_PORT_COUNT > 3U)
|
||||
kGINT_Port3 = 3U,
|
||||
#endif
|
||||
#if defined(FSL_FEATURE_GINT_PORT_COUNT) && (FSL_FEATURE_GINT_PORT_COUNT > 4U)
|
||||
kGINT_Port4 = 4U,
|
||||
#endif
|
||||
#if defined(FSL_FEATURE_GINT_PORT_COUNT) && (FSL_FEATURE_GINT_PORT_COUNT > 5U)
|
||||
kGINT_Port5 = 5U,
|
||||
#endif
|
||||
#if defined(FSL_FEATURE_GINT_PORT_COUNT) && (FSL_FEATURE_GINT_PORT_COUNT > 6U)
|
||||
kGINT_Port6 = 6U,
|
||||
#endif
|
||||
#if defined(FSL_FEATURE_GINT_PORT_COUNT) && (FSL_FEATURE_GINT_PORT_COUNT > 7U)
|
||||
kGINT_Port7 = 7U,
|
||||
#endif
|
||||
} gint_port_t;
|
||||
|
||||
/*! @brief GINT Callback function. */
|
||||
typedef void (*gint_cb_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Initialize GINT peripheral.
|
||||
|
||||
* This function initializes the GINT peripheral and enables the clock.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_Init(GINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Setup GINT peripheral control parameters.
|
||||
|
||||
* This function sets the control parameters of GINT peripheral.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
* @param comb Controls if the enabled inputs are logically ORed or ANDed for interrupt generation.
|
||||
* @param trig Controls if the enabled inputs are level or edge sensitive based on polarity.
|
||||
* @param callback This function is called when configured group interrupt is generated.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_SetCtrl(GINT_Type *base, gint_comb_t comb, gint_trig_t trig, gint_cb_t callback);
|
||||
|
||||
/*!
|
||||
* @brief Get GINT peripheral control parameters.
|
||||
|
||||
* This function returns the control parameters of GINT peripheral.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
* @param comb Pointer to store combine input value.
|
||||
* @param trig Pointer to store trigger value.
|
||||
* @param callback Pointer to store callback function.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_GetCtrl(GINT_Type *base, gint_comb_t *comb, gint_trig_t *trig, gint_cb_t *callback);
|
||||
|
||||
/*!
|
||||
* @brief Configure GINT peripheral pins.
|
||||
|
||||
* This function enables and controls the polarity of enabled pin(s) of a given port.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
* @param port Port number.
|
||||
* @param polarityMask Each bit position selects the polarity of the corresponding enabled pin.
|
||||
* 0 = The pin is active LOW. 1 = The pin is active HIGH.
|
||||
* @param enableMask Each bit position selects if the corresponding pin is enabled or not.
|
||||
* 0 = The pin is disabled. 1 = The pin is enabled.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_ConfigPins(GINT_Type *base, gint_port_t port, uint32_t polarityMask, uint32_t enableMask);
|
||||
|
||||
/*!
|
||||
* @brief Get GINT peripheral pin configuration.
|
||||
|
||||
* This function returns the pin configuration of a given port.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
* @param port Port number.
|
||||
* @param polarityMask Pointer to store the polarity mask Each bit position indicates the polarity of the corresponding
|
||||
enabled pin.
|
||||
* 0 = The pin is active LOW. 1 = The pin is active HIGH.
|
||||
* @param enableMask Pointer to store the enable mask. Each bit position indicates if the corresponding pin is enabled
|
||||
or not.
|
||||
* 0 = The pin is disabled. 1 = The pin is enabled.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_GetConfigPins(GINT_Type *base, gint_port_t port, uint32_t *polarityMask, uint32_t *enableMask);
|
||||
|
||||
/*!
|
||||
* @brief Enable callback.
|
||||
|
||||
* This function enables the interrupt for the selected GINT peripheral. Although the pin(s) are monitored
|
||||
* as soon as they are enabled, the callback function is not enabled until this function is called.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_EnableCallback(GINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Disable callback.
|
||||
|
||||
* This function disables the interrupt for the selected GINT peripheral. Although the pins are still
|
||||
* being monitored but the callback function is not called.
|
||||
*
|
||||
* @param base Base address of the peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_DisableCallback(GINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Clear GINT status.
|
||||
|
||||
* This function clears the GINT status bit.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void GINT_ClrStatus(GINT_Type *base)
|
||||
{
|
||||
base->CTRL |= GINT_CTRL_INT_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get GINT status.
|
||||
|
||||
* This function returns the GINT status.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
*
|
||||
* @retval status = 0 No group interrupt request. = 1 Group interrupt request active.
|
||||
*/
|
||||
static inline uint32_t GINT_GetStatus(GINT_Type *base)
|
||||
{
|
||||
return (base->CTRL & GINT_CTRL_INT_MASK);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Deinitialize GINT peripheral.
|
||||
|
||||
* This function disables the GINT clock.
|
||||
*
|
||||
* @param base Base address of the GINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void GINT_Deinit(GINT_Type *base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_GINT_H_ */
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_gpio.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
************ ******************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void GPIO_PinInit(GPIO_Type *base, uint32_t port, uint32_t pin, const gpio_pin_config_t *config)
|
||||
{
|
||||
if (config->pinDirection == kGPIO_DigitalInput)
|
||||
{
|
||||
base->DIR[port] &= ~(1U << pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->DIR[port] |= 1U << pin;
|
||||
/* Set default output value */
|
||||
if (config->outputLogic == 0U)
|
||||
{
|
||||
base->CLR[port] = (1U << pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->PIN[port] = (1U << pin);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* 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 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 _LPC_GPIO_H_
|
||||
#define _LPC_GPIO_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup lpc_gpio
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief LPC GPIO driver version 1.0.0. */
|
||||
#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(1, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*! @brief LPC 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.
|
||||
*/
|
||||
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
|
||||
|
||||
/*! @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(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param pin GPIO pin number
|
||||
* @param config GPIO pin configuration pointer
|
||||
*/
|
||||
void GPIO_PinInit(GPIO_Type *base, uint32_t port, uint32_t pin, const gpio_pin_config_t *config);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/*! @name GPIO Output Operations */
|
||||
/*@{*/
|
||||
|
||||
/*!
|
||||
* @brief Sets the output level of the one GPIO pin to the logic 1 or 0.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param pin GPIO pin 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 port, uint32_t pin, uint8_t output)
|
||||
{
|
||||
base->B[port][pin] = output;
|
||||
}
|
||||
/*@}*/
|
||||
/*! @name GPIO Input Operations */
|
||||
/*@{*/
|
||||
|
||||
/*!
|
||||
* @brief Reads the current input value of the GPIO PIN.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param pin GPIO pin 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 port, uint32_t pin)
|
||||
{
|
||||
return (uint32_t)base->B[port][pin];
|
||||
}
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Sets the output level of the multiple GPIO pins to the logic 1.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param mask GPIO pin number macro
|
||||
*/
|
||||
static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t port, uint32_t mask)
|
||||
{
|
||||
base->SET[port] = mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the output level of the multiple GPIO pins to the logic 0.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param mask GPIO pin number macro
|
||||
*/
|
||||
static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t port, uint32_t mask)
|
||||
{
|
||||
base->CLR[port] = mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reverses current output logic of the multiple GPIO pins.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param mask GPIO pin number macro
|
||||
*/
|
||||
static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t port, uint32_t mask)
|
||||
{
|
||||
base->NOT[port] = mask;
|
||||
}
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief Reads the current input value of the whole GPIO port.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
*/
|
||||
static inline uint32_t GPIO_ReadPinsInput(GPIO_Type *base, uint32_t port)
|
||||
{
|
||||
return (uint32_t)base->PIN[port];
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
/*! @name GPIO Mask Operations */
|
||||
/*@{*/
|
||||
|
||||
/*!
|
||||
* @brief Sets port mask, 0 - enable pin, 1 - disable pin.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param mask GPIO pin number macro
|
||||
*/
|
||||
static inline void GPIO_SetPortMask(GPIO_Type *base, uint32_t port, uint32_t mask)
|
||||
{
|
||||
base->MASK[port] = mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the output level of the masked GPIO port. Only pins enabled by GPIO_SetPortMask() will be affected.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @param output GPIO port output value.
|
||||
*/
|
||||
static inline void GPIO_WriteMPort(GPIO_Type *base, uint32_t port, uint32_t output)
|
||||
{
|
||||
base->MPIN[port] = output;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads the current input value of the masked GPIO port. Only pins enabled by GPIO_SetPortMask() will be
|
||||
* affected.
|
||||
*
|
||||
* @param base GPIO peripheral base pointer(Typically GPIO)
|
||||
* @param port GPIO port number
|
||||
* @retval masked GPIO port value
|
||||
*/
|
||||
static inline uint32_t GPIO_ReadMPort(GPIO_Type *base, uint32_t port)
|
||||
{
|
||||
return (uint32_t)base->MPIN[port];
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _LPC_GPIO_H_*/
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_i2c_dma.h"
|
||||
#include "fsl_flexcomm.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;
|
||||
|
||||
/*******************************************************************************
|
||||
* 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 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_FLEXCOMM_COUNT];
|
||||
|
||||
/*******************************************************************************
|
||||
* Codes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Prepares the transfer state machine and fills in the command buffer.
|
||||
* @param handle Master nonblocking driver handle.
|
||||
*/
|
||||
static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
|
||||
i2c_master_dma_handle_t *handle,
|
||||
i2c_master_transfer_t *xfer)
|
||||
{
|
||||
struct _i2c_master_transfer *transfer;
|
||||
|
||||
handle->transfer = *xfer;
|
||||
transfer = &(handle->transfer);
|
||||
|
||||
handle->transferCount = 0;
|
||||
handle->remainingBytesDMA = 0;
|
||||
handle->buf = (uint8_t *)transfer->data;
|
||||
handle->remainingSubaddr = 0;
|
||||
|
||||
if (transfer->flags & kI2C_TransferNoStartFlag)
|
||||
{
|
||||
/* Start condition shall be ommited, switch directly to next phase */
|
||||
if (transfer->dataSize == 0)
|
||||
{
|
||||
handle->state = kStopState;
|
||||
}
|
||||
else if (handle->transfer.direction == kI2C_Write)
|
||||
{
|
||||
handle->state = xfer->dataSize = kTransmitDataState;
|
||||
}
|
||||
else if (handle->transfer.direction == kI2C_Read)
|
||||
{
|
||||
handle->state = (xfer->dataSize == 1) ? kReceiveLastDataState : kReceiveDataState;
|
||||
}
|
||||
else
|
||||
{
|
||||
return kStatus_I2C_InvalidParameter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transfer->subaddressSize != 0)
|
||||
{
|
||||
int i;
|
||||
uint32_t subaddress;
|
||||
|
||||
if (transfer->subaddressSize > sizeof(handle->subaddrBuf))
|
||||
{
|
||||
return kStatus_I2C_InvalidParameter;
|
||||
}
|
||||
|
||||
/* Prepare subaddress transmit buffer, most significant byte is stored at the lowest address */
|
||||
subaddress = xfer->subaddress;
|
||||
for (i = xfer->subaddressSize - 1; i >= 0; i--)
|
||||
{
|
||||
handle->subaddrBuf[i] = subaddress & 0xff;
|
||||
subaddress >>= 8;
|
||||
}
|
||||
handle->remainingSubaddr = transfer->subaddressSize;
|
||||
}
|
||||
|
||||
handle->state = kStartState;
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
static void I2C_RunDMATransfer(I2C_Type *base, i2c_master_dma_handle_t *handle)
|
||||
{
|
||||
int transfer_size;
|
||||
dma_transfer_config_t xferConfig;
|
||||
|
||||
/* Update transfer count */
|
||||
handle->transferCount = handle->buf - (uint8_t *)handle->transfer.data;
|
||||
|
||||
/* Check if there is anything to be transferred at all */
|
||||
if (handle->remainingBytesDMA == 0)
|
||||
{
|
||||
/* No data to be transferrred, disable DMA */
|
||||
base->MSTCTL = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate transfer size */
|
||||
transfer_size = handle->remainingBytesDMA;
|
||||
if (transfer_size > I2C_MAX_DMA_TRANSFER_COUNT)
|
||||
{
|
||||
transfer_size = I2C_MAX_DMA_TRANSFER_COUNT;
|
||||
}
|
||||
|
||||
switch (handle->transfer.direction)
|
||||
{
|
||||
case kI2C_Write:
|
||||
DMA_PrepareTransfer(&xferConfig, handle->buf, (void *)&base->MSTDAT, sizeof(uint8_t), transfer_size,
|
||||
kDMA_MemoryToPeripheral, NULL);
|
||||
break;
|
||||
|
||||
case kI2C_Read:
|
||||
DMA_PrepareTransfer(&xferConfig, (void *)&base->MSTDAT, handle->buf, sizeof(uint8_t), transfer_size,
|
||||
kDMA_PeripheralToMemory, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* This should never happen */
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
|
||||
DMA_StartTransfer(handle->dmaHandle);
|
||||
|
||||
handle->remainingBytesDMA -= transfer_size;
|
||||
handle->buf += transfer_size;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Execute states until the transfer is done.
|
||||
* @param handle Master nonblocking driver handle.
|
||||
* @param[out] isDone Set to true if the transfer has completed.
|
||||
* @retval #kStatus_Success
|
||||
* @retval #kStatus_I2C_ArbitrationLost
|
||||
* @retval #kStatus_I2C_Nak
|
||||
*/
|
||||
static status_t I2C_RunTransferStateMachineDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, bool *isDone)
|
||||
{
|
||||
uint32_t status;
|
||||
uint32_t master_state;
|
||||
struct _i2c_master_transfer *transfer;
|
||||
dma_transfer_config_t xferConfig;
|
||||
status_t err;
|
||||
uint32_t start_flag = 0;
|
||||
|
||||
transfer = &(handle->transfer);
|
||||
|
||||
*isDone = false;
|
||||
|
||||
status = I2C_GetStatusFlags(base);
|
||||
|
||||
if (status & I2C_STAT_MSTARBLOSS_MASK)
|
||||
{
|
||||
I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK);
|
||||
DMA_AbortTransfer(handle->dmaHandle);
|
||||
base->MSTCTL = 0;
|
||||
return kStatus_I2C_ArbitrationLost;
|
||||
}
|
||||
|
||||
if (status & I2C_STAT_MSTSTSTPERR_MASK)
|
||||
{
|
||||
I2C_MasterClearStatusFlags(base, I2C_STAT_MSTSTSTPERR_MASK);
|
||||
DMA_AbortTransfer(handle->dmaHandle);
|
||||
base->MSTCTL = 0;
|
||||
return kStatus_I2C_StartStopError;
|
||||
}
|
||||
|
||||
if ((status & I2C_STAT_MSTPENDING_MASK) == 0)
|
||||
{
|
||||
return kStatus_I2C_Busy;
|
||||
}
|
||||
|
||||
/* Get the state of the I2C module */
|
||||
master_state = (status & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
|
||||
|
||||
if ((master_state == I2C_STAT_MSTCODE_NACKADR) || (master_state == I2C_STAT_MSTCODE_NACKDAT))
|
||||
{
|
||||
/* Slave NACKed last byte, issue stop and return error */
|
||||
DMA_AbortTransfer(handle->dmaHandle);
|
||||
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
|
||||
handle->state = kWaitForCompletionState;
|
||||
return kStatus_I2C_Nak;
|
||||
}
|
||||
|
||||
err = kStatus_Success;
|
||||
|
||||
if (handle->state == kStartState)
|
||||
{
|
||||
/* set start flag for later use */
|
||||
start_flag = I2C_MSTCTL_MSTSTART_MASK;
|
||||
|
||||
if (handle->remainingSubaddr)
|
||||
{
|
||||
base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
|
||||
handle->state = kTransmitSubaddrState;
|
||||
}
|
||||
else if (transfer->direction == kI2C_Write)
|
||||
{
|
||||
base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
|
||||
if (transfer->dataSize == 0)
|
||||
{
|
||||
/* No data to be transferred, initiate start and schedule stop */
|
||||
base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
|
||||
handle->state = kStopState;
|
||||
return err;
|
||||
}
|
||||
handle->state = kTransmitDataState;
|
||||
}
|
||||
else if ((transfer->direction == kI2C_Read) && (transfer->dataSize > 0))
|
||||
{
|
||||
base->MSTDAT = ((uint32_t)transfer->slaveAddress << 1) | 1u;
|
||||
if (transfer->dataSize == 1)
|
||||
{
|
||||
/* The very last byte is always received by means of SW */
|
||||
base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
|
||||
handle->state = kReceiveLastDataState;
|
||||
return err;
|
||||
}
|
||||
handle->state = kReceiveDataState;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->state = kIdleState;
|
||||
err = kStatus_I2C_UnexpectedState;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
switch (handle->state)
|
||||
{
|
||||
case kTransmitSubaddrState:
|
||||
if ((master_state != I2C_STAT_MSTCODE_TXREADY) && (!start_flag))
|
||||
{
|
||||
return kStatus_I2C_UnexpectedState;
|
||||
}
|
||||
|
||||
base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
|
||||
|
||||
/* Prepare and submit DMA transfer. */
|
||||
DMA_PrepareTransfer(&xferConfig, handle->subaddrBuf, (void *)&base->MSTDAT, sizeof(uint8_t),
|
||||
handle->remainingSubaddr, kDMA_MemoryToPeripheral, NULL);
|
||||
DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
|
||||
|
||||
handle->remainingSubaddr = 0;
|
||||
if (transfer->dataSize)
|
||||
{
|
||||
/* There is data to be transferred, if there is write to read turnaround it is necessary to perform
|
||||
* repeated start */
|
||||
handle->state = (transfer->direction == kI2C_Read) ? kStartState : kTransmitDataState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No more data, schedule stop condition */
|
||||
handle->state = kStopState;
|
||||
}
|
||||
break;
|
||||
|
||||
case kTransmitDataState:
|
||||
if ((master_state != I2C_STAT_MSTCODE_TXREADY) && (!start_flag))
|
||||
{
|
||||
return kStatus_I2C_UnexpectedState;
|
||||
}
|
||||
|
||||
base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
|
||||
handle->remainingBytesDMA = handle->transfer.dataSize;
|
||||
|
||||
I2C_RunDMATransfer(base, handle);
|
||||
|
||||
/* Schedule stop condition */
|
||||
handle->state = kStopState;
|
||||
break;
|
||||
|
||||
case kReceiveDataState:
|
||||
if ((master_state != I2C_STAT_MSTCODE_RXREADY) && (!start_flag))
|
||||
{
|
||||
return kStatus_I2C_UnexpectedState;
|
||||
}
|
||||
|
||||
base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
|
||||
handle->remainingBytesDMA = handle->transfer.dataSize - 1;
|
||||
|
||||
I2C_RunDMATransfer(base, handle);
|
||||
|
||||
/* Schedule reception of last data byte */
|
||||
handle->state = kReceiveLastDataState;
|
||||
break;
|
||||
|
||||
case kReceiveLastDataState:
|
||||
if (master_state != I2C_STAT_MSTCODE_RXREADY)
|
||||
{
|
||||
return kStatus_I2C_UnexpectedState;
|
||||
}
|
||||
|
||||
((uint8_t *)transfer->data)[transfer->dataSize - 1] = base->MSTDAT;
|
||||
handle->transferCount++;
|
||||
|
||||
/* No more data expected, issue NACK and STOP right away */
|
||||
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
|
||||
handle->state = kWaitForCompletionState;
|
||||
break;
|
||||
|
||||
case kStopState:
|
||||
if (transfer->flags & kI2C_TransferNoStopFlag)
|
||||
{
|
||||
/* Stop condition is omitted, we are done */
|
||||
*isDone = true;
|
||||
handle->state = kIdleState;
|
||||
break;
|
||||
}
|
||||
/* Send stop condition */
|
||||
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
|
||||
handle->state = kWaitForCompletionState;
|
||||
break;
|
||||
|
||||
case kWaitForCompletionState:
|
||||
*isDone = true;
|
||||
handle->state = kIdleState;
|
||||
break;
|
||||
|
||||
case kStartState:
|
||||
case kIdleState:
|
||||
default:
|
||||
/* State machine shall not be invoked again once it enters the idle state */
|
||||
err = kStatus_I2C_UnexpectedState;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void I2C_MasterTransferDMAHandleIRQ(I2C_Type *base, i2c_master_dma_handle_t *handle)
|
||||
{
|
||||
bool isDone;
|
||||
status_t result;
|
||||
|
||||
/* Don't do anything if we don't have a valid handle. */
|
||||
if (!handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result = I2C_RunTransferStateMachineDMA(base, handle, &isDone);
|
||||
|
||||
if (isDone || (result != kStatus_Success))
|
||||
{
|
||||
/* Disable internal IRQ enables. */
|
||||
I2C_DisableInterrupts(base,
|
||||
I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK);
|
||||
|
||||
/* Invoke callback. */
|
||||
if (handle->completionCallback)
|
||||
{
|
||||
handle->completionCallback(base, handle, result, handle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
i2c_master_dma_private_handle_t *dmaPrivateHandle;
|
||||
|
||||
/* Don't do anything if we don't have a valid handle. */
|
||||
if (!handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dmaPrivateHandle = (i2c_master_dma_private_handle_t *)userData;
|
||||
I2C_RunDMATransfer(dmaPrivateHandle->base, dmaPrivateHandle->handle);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
assert(handle);
|
||||
assert(dmaHandle);
|
||||
|
||||
/* Zero handle. */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Look up instance number */
|
||||
instance = I2C_GetInstance(base);
|
||||
|
||||
/* Set the user callback and userData. */
|
||||
handle->completionCallback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)(uintptr_t)I2C_MasterTransferDMAHandleIRQ, handle);
|
||||
|
||||
/* Clear internal IRQ enables and enable NVIC IRQ. */
|
||||
I2C_DisableInterrupts(base,
|
||||
I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK);
|
||||
EnableIRQ(kFlexcommIrqs[instance]);
|
||||
|
||||
/* Set the handle for DMA. */
|
||||
handle->dmaHandle = dmaHandle;
|
||||
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
DMA_SetCallback(dmaHandle, (dma_callback)(uintptr_t)I2C_MasterTransferCallbackDMA, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
status_t I2C_MasterTransferDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer)
|
||||
{
|
||||
status_t result;
|
||||
|
||||
assert(handle);
|
||||
assert(xfer);
|
||||
assert(xfer->subaddressSize <= sizeof(xfer->subaddress));
|
||||
|
||||
/* Return busy if another transaction is in progress. */
|
||||
if (handle->state != kIdleState)
|
||||
{
|
||||
return kStatus_I2C_Busy;
|
||||
}
|
||||
|
||||
/* Prepare transfer state machine. */
|
||||
result = I2C_InitTransferStateMachineDMA(base, handle, xfer);
|
||||
|
||||
/* Clear error flags. */
|
||||
I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
|
||||
|
||||
/* Enable I2C internal IRQ sources */
|
||||
I2C_EnableInterrupts(base,
|
||||
I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK | I2C_INTSTAT_MSTPENDING_MASK);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Catch when there is not an active transfer. */
|
||||
if (handle->state == kIdleState)
|
||||
{
|
||||
*count = 0;
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
/* There is no necessity to disable interrupts as we read a single integer value */
|
||||
*count = handle->transferCount;
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2C_MasterTransferAbortDMA(I2C_Type *base, i2c_master_dma_handle_t *handle)
|
||||
{
|
||||
DMA_AbortTransfer(handle->dmaHandle);
|
||||
|
||||
/* Disable DMA */
|
||||
base->MSTCTL = 0;
|
||||
|
||||
/* Reset the state to idle. */
|
||||
handle->state = kIdleState;
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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_dma.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup i2c_dma_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Maximum lenght of single DMA transfer (determined by capability of the DMA engine) */
|
||||
#define I2C_MAX_DMA_TRANSFER_COUNT 1024
|
||||
|
||||
/*! @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
|
||||
{
|
||||
uint8_t state; /*!< Transfer state machine current state. */
|
||||
uint32_t transferCount; /*!< Indicates progress of the transfer */
|
||||
uint32_t remainingBytesDMA; /*!< Remaining byte count to be transferred using DMA. */
|
||||
uint8_t *buf; /*!< Buffer pointer for current state. */
|
||||
uint32_t remainingSubaddr;
|
||||
uint8_t subaddrBuf[4];
|
||||
dma_handle_t *dmaHandle; /*!< The DMA handler used. */
|
||||
i2c_master_transfer_t transfer; /*!< Copy of the current transfer info. */
|
||||
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_*/
|
|
@ -0,0 +1,824 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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_i2s.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
#include <string.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* TODO - absent in device header files, should be there */
|
||||
#define I2S_FIFOCFG_TXI2SE0_MASK (0x4U)
|
||||
#define I2S_FIFOCFG_TXI2SE0_SHIFT (2U)
|
||||
#define I2S_FIFOCFG_TXI2SE0(x) (((uint32_t)(((uint32_t)(x)) << I2S_FIFOCFG_TXI2SE0_SHIFT)) & I2S_FIFOCFG_TXI2SE0_MASK)
|
||||
#define I2S_FIFOCFG_PACK48_MASK (0x8U)
|
||||
#define I2S_FIFOCFG_PACK48_SHIFT (3U)
|
||||
#define I2S_FIFOCFG_PACK48(x) (((uint32_t)(((uint32_t)(x)) << I2S_FIFOCFG_PACK48_SHIFT)) & I2S_FIFOCFG_PACK48_MASK)
|
||||
|
||||
/*! @brief I2S states. */
|
||||
enum _i2s_state
|
||||
{
|
||||
kI2S_StateIdle = 0x0, /*!< Not performing transfer */
|
||||
kI2S_StateTx, /*!< Performing transmit */
|
||||
kI2S_StateTxWaitToWriteDummyData, /*!< Wait on FIFO in order to write final dummy data there */
|
||||
kI2S_StateTxWaitForEmptyFifo, /*!< Wait for FIFO to be flushed */
|
||||
kI2S_StateRx, /*!< Performing receive */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
static void I2S_Config(I2S_Type *base, const i2s_config_t *config);
|
||||
static status_t I2S_ValidateBuffer(i2s_handle_t *handle, i2s_transfer_t *transfer);
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void I2S_TxInit(I2S_Type *base, const i2s_config_t *config)
|
||||
{
|
||||
uint32_t cfg = 0U;
|
||||
uint32_t trig = 0U;
|
||||
|
||||
FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2S_TX);
|
||||
I2S_Config(base, config);
|
||||
|
||||
/* Configure FIFO */
|
||||
|
||||
cfg |= I2S_FIFOCFG_ENABLETX(1U); /* enable TX FIFO */
|
||||
cfg |= I2S_FIFOCFG_EMPTYTX(1U); /* empty TX FIFO */
|
||||
cfg |= I2S_FIFOCFG_TXI2SE0(config->txEmptyZero); /* transmit zero when buffer becomes empty or last item */
|
||||
cfg |= I2S_FIFOCFG_PACK48(config->pack48); /* set pack 48-bit format or not */
|
||||
trig |= I2S_FIFOTRIG_TXLVLENA(1U); /* enable TX FIFO trigger */
|
||||
trig |= I2S_FIFOTRIG_TXLVL(config->watermark); /* set TX FIFO trigger level */
|
||||
|
||||
base->FIFOCFG = cfg;
|
||||
base->FIFOTRIG = trig;
|
||||
}
|
||||
|
||||
void I2S_RxInit(I2S_Type *base, const i2s_config_t *config)
|
||||
{
|
||||
uint32_t cfg = 0U;
|
||||
uint32_t trig = 0U;
|
||||
|
||||
FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2S_RX);
|
||||
I2S_Config(base, config);
|
||||
|
||||
/* Configure FIFO */
|
||||
|
||||
cfg |= I2S_FIFOCFG_ENABLERX(1U); /* enable RX FIFO */
|
||||
cfg |= I2S_FIFOCFG_EMPTYRX(1U); /* empty RX FIFO */
|
||||
cfg |= I2S_FIFOCFG_PACK48(config->pack48); /* set pack 48-bit format or not */
|
||||
trig |= I2S_FIFOTRIG_RXLVLENA(1U); /* enable RX FIFO trigger */
|
||||
trig |= I2S_FIFOTRIG_RXLVL(config->watermark); /* set RX FIFO trigger level */
|
||||
|
||||
base->FIFOCFG = cfg;
|
||||
base->FIFOTRIG = trig;
|
||||
}
|
||||
|
||||
void I2S_TxGetDefaultConfig(i2s_config_t *config)
|
||||
{
|
||||
config->masterSlave = kI2S_MasterSlaveNormalMaster;
|
||||
config->mode = kI2S_ModeI2sClassic;
|
||||
config->rightLow = false;
|
||||
config->leftJust = false;
|
||||
config->pdmData = false;
|
||||
config->sckPol = false;
|
||||
config->wsPol = false;
|
||||
config->divider = 1U;
|
||||
config->oneChannel = false;
|
||||
config->dataLength = 16U;
|
||||
config->frameLength = 32U;
|
||||
config->position = 0U;
|
||||
config->watermark = 4U;
|
||||
config->txEmptyZero = true;
|
||||
config->pack48 = false;
|
||||
}
|
||||
|
||||
void I2S_RxGetDefaultConfig(i2s_config_t *config)
|
||||
{
|
||||
config->masterSlave = kI2S_MasterSlaveNormalSlave;
|
||||
config->mode = kI2S_ModeI2sClassic;
|
||||
config->rightLow = false;
|
||||
config->leftJust = false;
|
||||
config->pdmData = false;
|
||||
config->sckPol = false;
|
||||
config->wsPol = false;
|
||||
config->divider = 1U;
|
||||
config->oneChannel = false;
|
||||
config->dataLength = 16U;
|
||||
config->frameLength = 32U;
|
||||
config->position = 0U;
|
||||
config->watermark = 4U;
|
||||
config->txEmptyZero = false;
|
||||
config->pack48 = false;
|
||||
}
|
||||
|
||||
static void I2S_Config(I2S_Type *base, const i2s_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
uint32_t cfg1 = 0U;
|
||||
uint32_t cfg2 = 0U;
|
||||
|
||||
/* set master/slave configuration */
|
||||
cfg1 |= I2S_CFG1_MSTSLVCFG(config->masterSlave);
|
||||
|
||||
/* set I2S mode */
|
||||
cfg1 |= I2S_CFG1_MODE(config->mode);
|
||||
|
||||
/* set right low (channel swap) */
|
||||
cfg1 |= I2S_CFG1_RIGHTLOW(config->rightLow);
|
||||
|
||||
/* set data justification */
|
||||
cfg1 |= I2S_CFG1_LEFTJUST(config->leftJust);
|
||||
|
||||
/* set source to PDM dmic */
|
||||
cfg1 |= I2S_CFG1_PDMDATA(config->pdmData);
|
||||
|
||||
/* set SCLK polarity */
|
||||
cfg1 |= I2S_CFG1_SCK_POL(config->sckPol);
|
||||
|
||||
/* set WS polarity */
|
||||
cfg1 |= I2S_CFG1_WS_POL(config->wsPol);
|
||||
|
||||
/* set mono mode */
|
||||
cfg1 |= I2S_CFG1_ONECHANNEL(config->oneChannel);
|
||||
|
||||
/* set data length */
|
||||
cfg1 |= I2S_CFG1_DATALEN(config->dataLength - 1U);
|
||||
|
||||
/* set frame length */
|
||||
cfg2 |= I2S_CFG2_FRAMELEN(config->frameLength - 1U);
|
||||
|
||||
/* set data position of this channel pair within the frame */
|
||||
cfg2 |= I2S_CFG2_POSITION(config->position);
|
||||
|
||||
/* write to registers */
|
||||
base->CFG1 = cfg1;
|
||||
base->CFG2 = cfg2;
|
||||
|
||||
/* set the clock divider */
|
||||
base->DIV = I2S_DIV_DIV(config->divider - 1U);
|
||||
}
|
||||
|
||||
void I2S_Deinit(I2S_Type *base)
|
||||
{
|
||||
/* TODO gate FLEXCOMM clock via FLEXCOMM driver */
|
||||
}
|
||||
|
||||
void I2S_TxEnable(I2S_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
I2S_EnableInterrupts(base, kI2S_TxErrorFlag | kI2S_TxLevelFlag);
|
||||
I2S_Enable(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
I2S_DisableInterrupts(base, kI2S_TxErrorFlag | kI2S_TxLevelFlag);
|
||||
I2S_Disable(base);
|
||||
base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
void I2S_RxEnable(I2S_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
I2S_EnableInterrupts(base, kI2S_RxErrorFlag | kI2S_RxLevelFlag);
|
||||
I2S_Enable(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
I2S_DisableInterrupts(base, kI2S_RxErrorFlag | kI2S_RxLevelFlag);
|
||||
I2S_Disable(base);
|
||||
base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static status_t I2S_ValidateBuffer(i2s_handle_t *handle, i2s_transfer_t *transfer)
|
||||
{
|
||||
assert(transfer->data);
|
||||
if (!transfer->data)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert(transfer->dataSize > 0U);
|
||||
if (transfer->dataSize <= 0U)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
if (handle->dataLength == 4U)
|
||||
{
|
||||
/* No alignment and data length requirements */
|
||||
}
|
||||
else if ((handle->dataLength >= 5U) && (handle->dataLength <= 8U))
|
||||
{
|
||||
assert((((uint32_t)transfer->data) % 2U) == 0U);
|
||||
if ((((uint32_t)transfer->data) % 2U) != 0U)
|
||||
{
|
||||
/* Data not 2-bytes aligned */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert((transfer->dataSize % 2U) == 0U);
|
||||
if ((transfer->dataSize % 2U) != 0U)
|
||||
{
|
||||
/* Data not in pairs of left/right channel bytes */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
}
|
||||
else if ((handle->dataLength >= 9U) && (handle->dataLength <= 16U))
|
||||
{
|
||||
assert((((uint32_t)transfer->data) % 4U) == 0U);
|
||||
if ((((uint32_t)transfer->data) % 4U) != 0U)
|
||||
{
|
||||
/* Data not 4-bytes aligned */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert((transfer->dataSize % 4U) == 0U);
|
||||
if ((transfer->dataSize % 4U) != 0U)
|
||||
{
|
||||
/* Data lenght not multiply of 4 */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
}
|
||||
else if ((handle->dataLength >= 17U) && (handle->dataLength <= 24U))
|
||||
{
|
||||
assert((transfer->dataSize % 6U) == 0U);
|
||||
if ((transfer->dataSize % 6U) != 0U)
|
||||
{
|
||||
/* Data lenght not multiply of 6 */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert(!((handle->pack48) && ((((uint32_t)transfer->data) % 4U) != 0U)));
|
||||
if ((handle->pack48) && ((((uint32_t)transfer->data) % 4U) != 0U))
|
||||
{
|
||||
/* Data not 4-bytes aligned */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
}
|
||||
else /* if (handle->dataLength >= 25U) */
|
||||
{
|
||||
assert((((uint32_t)transfer->data) % 4U) == 0U);
|
||||
if ((((uint32_t)transfer->data) % 4U) != 0U)
|
||||
{
|
||||
/* Data not 4-bytes aligned */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
if (handle->oneChannel)
|
||||
{
|
||||
assert((transfer->dataSize % 4U) == 0U);
|
||||
if ((transfer->dataSize % 4U) != 0U)
|
||||
{
|
||||
/* Data lenght not multiply of 4 */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert((transfer->dataSize % 8U) == 0U);
|
||||
if ((transfer->dataSize % 8U) != 0U)
|
||||
{
|
||||
/* Data lenght not multiply of 8 */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2S_TxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
/* Clear out the handle */
|
||||
memset(handle, 0U, sizeof(*handle));
|
||||
|
||||
/* Save callback and user data */
|
||||
handle->completionCallback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
/* Remember some items set previously by configuration */
|
||||
handle->watermark = ((base->FIFOTRIG & I2S_FIFOTRIG_TXLVL_MASK) >> I2S_FIFOTRIG_TXLVL_SHIFT);
|
||||
handle->oneChannel = ((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) >> I2S_CFG1_ONECHANNEL_SHIFT);
|
||||
handle->dataLength = ((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U;
|
||||
handle->pack48 = ((base->FIFOCFG & I2S_FIFOCFG_PACK48_MASK) >> I2S_FIFOCFG_PACK48_SHIFT);
|
||||
|
||||
handle->useFifo48H = false;
|
||||
|
||||
/* Register IRQ handling */
|
||||
FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)(uintptr_t)I2S_TxHandleIRQ, handle);
|
||||
}
|
||||
|
||||
status_t I2S_TxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer)
|
||||
{
|
||||
assert(handle);
|
||||
if (!handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
status_t result;
|
||||
|
||||
result = I2S_ValidateBuffer(handle, &transfer);
|
||||
if (result != kStatus_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (handle->i2sQueue[handle->queueUser].dataSize)
|
||||
{
|
||||
/* Previously prepared buffers not processed yet */
|
||||
return kStatus_I2S_Busy;
|
||||
}
|
||||
|
||||
handle->state = kI2S_StateTx;
|
||||
handle->i2sQueue[handle->queueUser].data = transfer.data;
|
||||
handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
|
||||
handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
|
||||
|
||||
base->FIFOTRIG = (base->FIFOTRIG & (~I2S_FIFOTRIG_TXLVL_MASK)) | I2S_FIFOTRIG_TXLVL(handle->watermark);
|
||||
I2S_TxEnable(base, true);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2S_TxTransferAbort(I2S_Type *base, i2s_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
/* Disable I2S operation and interrupts */
|
||||
I2S_TxEnable(base, false);
|
||||
|
||||
/* Reset state */
|
||||
handle->state = kI2S_StateIdle;
|
||||
|
||||
/* Clear transfer queue */
|
||||
memset((void *)&handle->i2sQueue, 0U, sizeof(i2s_transfer_t) * I2S_NUM_BUFFERS);
|
||||
handle->queueDriver = 0U;
|
||||
handle->queueUser = 0U;
|
||||
}
|
||||
|
||||
void I2S_RxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
/* Clear out the handle */
|
||||
memset(handle, 0U, sizeof(*handle));
|
||||
|
||||
/* Save callback and user data */
|
||||
handle->completionCallback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
/* Remember some items set previously by configuration */
|
||||
handle->watermark = ((base->FIFOTRIG & I2S_FIFOTRIG_RXLVL_MASK) >> I2S_FIFOTRIG_RXLVL_SHIFT);
|
||||
handle->oneChannel = ((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) >> I2S_CFG1_ONECHANNEL_SHIFT);
|
||||
handle->dataLength = ((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U;
|
||||
handle->pack48 = ((base->FIFOCFG & I2S_FIFOCFG_PACK48_MASK) >> I2S_FIFOCFG_PACK48_SHIFT);
|
||||
|
||||
handle->useFifo48H = false;
|
||||
|
||||
/* Register IRQ handling */
|
||||
FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)(uintptr_t)I2S_RxHandleIRQ, handle);
|
||||
}
|
||||
|
||||
status_t I2S_RxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer)
|
||||
{
|
||||
assert(handle);
|
||||
if (!handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
status_t result;
|
||||
|
||||
result = I2S_ValidateBuffer(handle, &transfer);
|
||||
if (result != kStatus_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (handle->i2sQueue[handle->queueUser].dataSize)
|
||||
{
|
||||
/* Previously prepared buffers not processed yet */
|
||||
return kStatus_I2S_Busy;
|
||||
}
|
||||
|
||||
handle->state = kI2S_StateRx;
|
||||
handle->i2sQueue[handle->queueUser].data = transfer.data;
|
||||
handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
|
||||
handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
|
||||
|
||||
base->FIFOTRIG = (base->FIFOTRIG & (~I2S_FIFOTRIG_RXLVL_MASK)) | I2S_FIFOTRIG_RXLVL(handle->watermark);
|
||||
I2S_RxEnable(base, true);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2S_RxTransferAbort(I2S_Type *base, i2s_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
/* Disable I2S operation and interrupts */
|
||||
I2S_RxEnable(base, false);
|
||||
|
||||
/* Reset state */
|
||||
handle->state = kI2S_StateIdle;
|
||||
|
||||
/* Clear transfer queue */
|
||||
memset((void *)&handle->i2sQueue, 0U, sizeof(i2s_transfer_t) * I2S_NUM_BUFFERS);
|
||||
handle->queueDriver = 0U;
|
||||
handle->queueUser = 0U;
|
||||
}
|
||||
|
||||
status_t I2S_TransferGetCount(I2S_Type *base, i2s_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
if (!handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert(count);
|
||||
if (!count)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
if (handle->state == kI2S_StateIdle)
|
||||
{
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->transferCount;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t I2S_TransferGetErrorCount(I2S_Type *base, i2s_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
if (!handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert(count);
|
||||
if (!count)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
if (handle->state == kI2S_StateIdle)
|
||||
{
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->errorCount;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2S_TxHandleIRQ(I2S_Type *base, i2s_handle_t *handle)
|
||||
{
|
||||
uint32_t intstat = base->FIFOINTSTAT;
|
||||
uint32_t data;
|
||||
|
||||
if (intstat & I2S_FIFOINTSTAT_TXERR_MASK)
|
||||
{
|
||||
handle->errorCount++;
|
||||
|
||||
/* Clear TX error interrupt flag */
|
||||
base->FIFOSTAT = I2S_FIFOSTAT_TXERR(1U);
|
||||
}
|
||||
|
||||
if (intstat & I2S_FIFOINTSTAT_TXLVL_MASK)
|
||||
{
|
||||
if (handle->state == kI2S_StateTx)
|
||||
{
|
||||
/* Send data */
|
||||
|
||||
while ((base->FIFOSTAT & I2S_FIFOSTAT_TXNOTFULL_MASK) &&
|
||||
(handle->i2sQueue[handle->queueDriver].dataSize > 0U))
|
||||
{
|
||||
/* Write output data */
|
||||
if (handle->dataLength == 4U)
|
||||
{
|
||||
data = *(handle->i2sQueue[handle->queueDriver].data);
|
||||
base->FIFOWR = ((data & 0xF0U) << 12U) | (data & 0xFU);
|
||||
handle->i2sQueue[handle->queueDriver].data++;
|
||||
handle->transferCount++;
|
||||
handle->i2sQueue[handle->queueDriver].dataSize--;
|
||||
}
|
||||
else if (handle->dataLength <= 8U)
|
||||
{
|
||||
data = *((uint16_t *)handle->i2sQueue[handle->queueDriver].data);
|
||||
base->FIFOWR = ((data & 0xFF00U) << 8U) | (data & 0xFFU);
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
|
||||
handle->transferCount += sizeof(uint16_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
|
||||
}
|
||||
else if (handle->dataLength <= 16U)
|
||||
{
|
||||
base->FIFOWR = *((uint32_t *)(handle->i2sQueue[handle->queueDriver].data));
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
|
||||
handle->transferCount += sizeof(uint32_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
|
||||
}
|
||||
else if (handle->dataLength <= 24U)
|
||||
{
|
||||
if (handle->pack48)
|
||||
{
|
||||
if (handle->useFifo48H)
|
||||
{
|
||||
base->FIFOWR48H = *((uint16_t *)(handle->i2sQueue[handle->queueDriver].data));
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
|
||||
handle->transferCount += sizeof(uint16_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
|
||||
handle->useFifo48H = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOWR = *((uint32_t *)(handle->i2sQueue[handle->queueDriver].data));
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
|
||||
handle->transferCount += sizeof(uint32_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
|
||||
handle->useFifo48H = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (uint32_t)(*(handle->i2sQueue[handle->queueDriver].data++));
|
||||
data |= ((uint32_t)(*(handle->i2sQueue[handle->queueDriver].data++))) << 8U;
|
||||
data |= ((uint32_t)(*(handle->i2sQueue[handle->queueDriver].data++))) << 16U;
|
||||
if (handle->useFifo48H)
|
||||
{
|
||||
base->FIFOWR48H = data;
|
||||
handle->useFifo48H = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOWR = data;
|
||||
handle->useFifo48H = true;
|
||||
}
|
||||
handle->transferCount += 3U;
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= 3U;
|
||||
}
|
||||
}
|
||||
else /* if (handle->dataLength <= 32U) */
|
||||
{
|
||||
base->FIFOWR = *((uint32_t *)(handle->i2sQueue[handle->queueDriver].data));
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
|
||||
handle->transferCount += sizeof(uint32_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
|
||||
{
|
||||
/* Actual data buffer sent out, switch to a next one */
|
||||
handle->queueDriver = (handle->queueDriver + 1U) % I2S_NUM_BUFFERS;
|
||||
|
||||
/* Notify user */
|
||||
if (handle->completionCallback)
|
||||
{
|
||||
handle->completionCallback(base, handle, kStatus_I2S_BufferComplete, handle->userData);
|
||||
}
|
||||
|
||||
/* Check if the next buffer contains anything to send */
|
||||
if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
|
||||
{
|
||||
/* Everything has been written to FIFO */
|
||||
handle->state = kI2S_StateTxWaitToWriteDummyData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (handle->state == kI2S_StateTxWaitToWriteDummyData)
|
||||
{
|
||||
/* Write dummy data */
|
||||
if ((handle->dataLength > 16U) && (handle->dataLength < 25U))
|
||||
{
|
||||
if (handle->useFifo48H)
|
||||
{
|
||||
base->FIFOWR48H = 0U;
|
||||
handle->useFifo48H = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOWR = 0U;
|
||||
base->FIFOWR48H = 0U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOWR = 0U;
|
||||
}
|
||||
|
||||
/* Next time invoke this handler when FIFO becomes empty (TX level 0) */
|
||||
base->FIFOTRIG &= ~I2S_FIFOTRIG_TXLVL_MASK;
|
||||
handle->state = kI2S_StateTxWaitForEmptyFifo;
|
||||
}
|
||||
else if (handle->state == kI2S_StateTxWaitForEmptyFifo)
|
||||
{
|
||||
/* FIFO, including additional dummy data, has been emptied now,
|
||||
* all relevant data should have been output from peripheral */
|
||||
|
||||
/* Stop transfer */
|
||||
I2S_Disable(base);
|
||||
I2S_DisableInterrupts(base, kI2S_TxErrorFlag | kI2S_TxLevelFlag);
|
||||
base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
|
||||
|
||||
/* Reset state */
|
||||
handle->state = kI2S_StateIdle;
|
||||
|
||||
/* Notify user */
|
||||
if (handle->completionCallback)
|
||||
{
|
||||
handle->completionCallback(base, handle, kStatus_I2S_Done, handle->userData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
/* Clear TX level interrupt flag */
|
||||
base->FIFOSTAT = I2S_FIFOSTAT_TXLVL(1U);
|
||||
}
|
||||
}
|
||||
|
||||
void I2S_RxHandleIRQ(I2S_Type *base, i2s_handle_t *handle)
|
||||
{
|
||||
uint32_t intstat = base->FIFOINTSTAT;
|
||||
uint32_t data;
|
||||
|
||||
if (intstat & I2S_FIFOINTSTAT_RXERR_MASK)
|
||||
{
|
||||
handle->errorCount++;
|
||||
|
||||
/* Clear RX error interrupt flag */
|
||||
base->FIFOSTAT = I2S_FIFOSTAT_RXERR(1U);
|
||||
}
|
||||
|
||||
if (intstat & I2S_FIFOINTSTAT_RXLVL_MASK)
|
||||
{
|
||||
while ((base->FIFOSTAT & I2S_FIFOSTAT_RXNOTEMPTY_MASK) && (handle->i2sQueue[handle->queueDriver].dataSize > 0U))
|
||||
{
|
||||
/* Read input data */
|
||||
if (handle->dataLength == 4U)
|
||||
{
|
||||
data = base->FIFORD;
|
||||
*(handle->i2sQueue[handle->queueDriver].data) = ((data & 0x000F0000U) >> 12U) | (data & 0x0000000FU);
|
||||
handle->i2sQueue[handle->queueDriver].data++;
|
||||
handle->transferCount++;
|
||||
handle->i2sQueue[handle->queueDriver].dataSize--;
|
||||
}
|
||||
else if (handle->dataLength <= 8U)
|
||||
{
|
||||
data = base->FIFORD;
|
||||
*((uint16_t *)handle->i2sQueue[handle->queueDriver].data) = ((data >> 8U) & 0xFF00U) | (data & 0xFFU);
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
|
||||
handle->transferCount += sizeof(uint16_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
|
||||
}
|
||||
else if (handle->dataLength <= 16U)
|
||||
{
|
||||
data = base->FIFORD;
|
||||
*((uint32_t *)handle->i2sQueue[handle->queueDriver].data) = data;
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
|
||||
handle->transferCount += sizeof(uint32_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
|
||||
}
|
||||
else if (handle->dataLength <= 24U)
|
||||
{
|
||||
if (handle->pack48)
|
||||
{
|
||||
if (handle->useFifo48H)
|
||||
{
|
||||
data = base->FIFORD48H;
|
||||
handle->useFifo48H = false;
|
||||
|
||||
*((uint16_t *)handle->i2sQueue[handle->queueDriver].data) = data;
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
|
||||
handle->transferCount += sizeof(uint16_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = base->FIFORD;
|
||||
handle->useFifo48H = true;
|
||||
|
||||
*((uint32_t *)handle->i2sQueue[handle->queueDriver].data) = data;
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
|
||||
handle->transferCount += sizeof(uint32_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle->useFifo48H)
|
||||
{
|
||||
data = base->FIFORD48H;
|
||||
handle->useFifo48H = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = base->FIFORD;
|
||||
handle->useFifo48H = true;
|
||||
}
|
||||
|
||||
*(handle->i2sQueue[handle->queueDriver].data++) = data & 0xFFU;
|
||||
*(handle->i2sQueue[handle->queueDriver].data++) = (data >> 8U) & 0xFFU;
|
||||
*(handle->i2sQueue[handle->queueDriver].data++) = (data >> 16U) & 0xFFU;
|
||||
handle->transferCount += 3U;
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= 3U;
|
||||
}
|
||||
}
|
||||
else /* if (handle->dataLength <= 32U) */
|
||||
{
|
||||
data = base->FIFORD;
|
||||
*((uint32_t *)handle->i2sQueue[handle->queueDriver].data) = data;
|
||||
handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
|
||||
handle->transferCount += sizeof(uint32_t);
|
||||
handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
|
||||
{
|
||||
/* Actual data buffer filled with input data, switch to a next one */
|
||||
handle->queueDriver = (handle->queueDriver + 1U) % I2S_NUM_BUFFERS;
|
||||
|
||||
/* Notify user */
|
||||
if (handle->completionCallback)
|
||||
{
|
||||
handle->completionCallback(base, handle, kStatus_I2S_BufferComplete, handle->userData);
|
||||
}
|
||||
|
||||
if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
|
||||
{
|
||||
/* No other buffer prepared to receive data into */
|
||||
|
||||
/* Disable I2S operation and interrupts */
|
||||
I2S_Disable(base);
|
||||
I2S_DisableInterrupts(base, kI2S_RxErrorFlag | kI2S_RxLevelFlag);
|
||||
base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
|
||||
|
||||
/* Reset state */
|
||||
handle->state = kI2S_StateIdle;
|
||||
|
||||
/* Notify user */
|
||||
if (handle->completionCallback)
|
||||
{
|
||||
handle->completionCallback(base, handle, kStatus_I2S_Done, handle->userData);
|
||||
}
|
||||
|
||||
/* Clear RX level interrupt flag */
|
||||
base->FIFOSTAT = I2S_FIFOSTAT_RXLVL(1U);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear RX level interrupt flag */
|
||||
base->FIFOSTAT = I2S_FIFOSTAT_RXLVL(1U);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,483 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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_I2S_H_
|
||||
#define _FSL_I2S_H_
|
||||
|
||||
#include "fsl_device_registers.h"
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @addtogroup i2s_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief I2S driver version 2.0.0.
|
||||
*
|
||||
* Current version: 2.0.0
|
||||
*
|
||||
* Change log:
|
||||
* - Version 2.0.0
|
||||
* - initial version
|
||||
*/
|
||||
#define FSL_I2S_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
#ifndef I2S_NUM_BUFFERS
|
||||
|
||||
/*! @brief Number of buffers . */
|
||||
#define I2S_NUM_BUFFERS (4)
|
||||
|
||||
#endif
|
||||
|
||||
/*! @brief I2S status codes. */
|
||||
enum _i2s_status
|
||||
{
|
||||
kStatus_I2S_BufferComplete =
|
||||
MAKE_STATUS(kStatusGroup_I2S, 0), /*!< Transfer from/into a single buffer has completed */
|
||||
kStatus_I2S_Done = MAKE_STATUS(kStatusGroup_I2S, 1), /*!< All buffers transfers have completed */
|
||||
kStatus_I2S_Busy =
|
||||
MAKE_STATUS(kStatusGroup_I2S, 2), /*!< Already performing a transfer and cannot queue another buffer */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief I2S flags.
|
||||
*
|
||||
* @note These enums are meant to be OR'd together to form a bit mask.
|
||||
*/
|
||||
typedef enum _i2s_flags
|
||||
{
|
||||
kI2S_TxErrorFlag = I2S_FIFOINTENSET_TXERR_MASK, /*!< TX error interrupt */
|
||||
kI2S_TxLevelFlag = I2S_FIFOINTENSET_TXLVL_MASK, /*!< TX level interrupt */
|
||||
kI2S_RxErrorFlag = I2S_FIFOINTENSET_RXERR_MASK, /*!< RX error interrupt */
|
||||
kI2S_RxLevelFlag = I2S_FIFOINTENSET_RXLVL_MASK /*!< RX level interrupt */
|
||||
} i2s_flags_t;
|
||||
|
||||
/*! @brief Master / slave mode. */
|
||||
typedef enum _i2s_master_slave
|
||||
{
|
||||
kI2S_MasterSlaveNormalSlave = 0x0, /*!< Normal slave */
|
||||
kI2S_MasterSlaveWsSyncMaster = 0x1, /*!< WS synchronized master */
|
||||
kI2S_MasterSlaveExtSckMaster = 0x2, /*!< Master using existing SCK */
|
||||
kI2S_MasterSlaveNormalMaster = 0x3 /*!< Normal master */
|
||||
} i2s_master_slave_t;
|
||||
|
||||
/*! @brief I2S mode. */
|
||||
typedef enum _i2s_mode
|
||||
{
|
||||
kI2S_ModeI2sClassic = 0x0, /*!< I2S classic mode */
|
||||
kI2S_ModeDspWs50 = 0x1, /*!< DSP mode, WS having 50% duty cycle */
|
||||
kI2S_ModeDspWsShort = 0x2, /*!< DSP mode, WS having one clock long pulse */
|
||||
kI2S_ModeDspWsLong = 0x3 /*!< DSP mode, WS having one data slot long pulse */
|
||||
} i2s_mode_t;
|
||||
|
||||
/*! @brief I2S configuration structure. */
|
||||
typedef struct _i2s_config
|
||||
{
|
||||
i2s_master_slave_t masterSlave; /*!< Master / slave configuration */
|
||||
i2s_mode_t mode; /*!< I2S mode */
|
||||
bool rightLow; /*!< Right channel data in low portion of FIFO */
|
||||
bool leftJust; /*!< Left justify data in FIFO */
|
||||
bool pdmData; /*!< Data source is the D-Mic subsystem */
|
||||
bool sckPol; /*!< SCK polarity */
|
||||
bool wsPol; /*!< WS polarity */
|
||||
uint16_t divider; /*!< Flexcomm function clock divider (1 - 4096) */
|
||||
bool oneChannel; /*!< true mono, false stereo */
|
||||
uint8_t dataLength; /*!< Data length (4 - 32) */
|
||||
uint16_t frameLength; /*!< Frame width (4 - 512) */
|
||||
uint16_t position; /*!< Data position in the frame */
|
||||
uint8_t watermark; /*!< FIFO trigger level */
|
||||
bool txEmptyZero; /*!< Transmit zero when buffer becomes empty or last item */
|
||||
bool pack48; /*!< Packing format for 48-bit data (false - 24 bit values, true - alternating 32-bit and 16-bit
|
||||
values) */
|
||||
} i2s_config_t;
|
||||
|
||||
/*! @brief Buffer to transfer from or receive audio data into. */
|
||||
typedef struct _i2s_transfer
|
||||
{
|
||||
volatile uint8_t *data; /*!< Pointer to data buffer. */
|
||||
volatile size_t dataSize; /*!< Buffer size in bytes. */
|
||||
} i2s_transfer_t;
|
||||
|
||||
/*! @brief Transactional state of the intialized transfer or receive I2S operation. */
|
||||
typedef struct _i2s_handle i2s_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Callback function invoked from transactional API
|
||||
* on completion of a single buffer transfer.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to I2S transaction.
|
||||
* @param completionStatus status of the transaction.
|
||||
* @param userData optional pointer to user arguments data.
|
||||
*/
|
||||
typedef void (*i2s_transfer_callback_t)(I2S_Type *base,
|
||||
i2s_handle_t *handle,
|
||||
status_t completionStatus,
|
||||
void *userData);
|
||||
|
||||
/*! @brief Members not to be accessed / modified outside of the driver. */
|
||||
struct _i2s_handle
|
||||
{
|
||||
uint32_t state; /*!< State of transfer */
|
||||
i2s_transfer_callback_t completionCallback; /*!< Callback function pointer */
|
||||
void *userData; /*!< Application data passed to callback */
|
||||
bool oneChannel; /*!< true mono, false stereo */
|
||||
uint8_t dataLength; /*!< Data length (4 - 32) */
|
||||
bool pack48; /*!< Packing format for 48-bit data (false - 24 bit values, true - alternating 32-bit and 16-bit
|
||||
values) */
|
||||
bool useFifo48H; /*!< When dataLength 17-24: true use FIFOWR48H, false use FIFOWR */
|
||||
volatile i2s_transfer_t i2sQueue[I2S_NUM_BUFFERS]; /*!< Transfer queue storing transfer buffers */
|
||||
volatile uint8_t queueUser; /*!< Queue index where user's next transfer will be stored */
|
||||
volatile uint8_t queueDriver; /*!< Queue index of buffer actually used by the driver */
|
||||
volatile uint32_t errorCount; /*!< Number of buffer underruns/overruns */
|
||||
volatile uint32_t transferCount; /*!< Number of bytes transferred */
|
||||
volatile uint8_t watermark; /*!< FIFO trigger level */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes the FLEXCOMM peripheral for I2S transmit functionality.
|
||||
*
|
||||
* Ungates the FLEXCOMM clock and configures the module
|
||||
* for I2S transmission using a configuration structure.
|
||||
* The configuration structure can be custom filled or set with default values by
|
||||
* I2S_TxGetDefaultConfig().
|
||||
*
|
||||
* @note This API should be called at the beginning of the application to use
|
||||
* the I2S driver.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param config pointer to I2S configuration structure.
|
||||
*/
|
||||
void I2S_TxInit(I2S_Type *base, const i2s_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Initializes the FLEXCOMM peripheral for I2S receive functionality.
|
||||
*
|
||||
* Ungates the FLEXCOMM clock and configures the module
|
||||
* for I2S receive using a configuration structure.
|
||||
* The configuration structure can be custom filled or set with default values by
|
||||
* I2S_RxGetDefaultConfig().
|
||||
*
|
||||
* @note This API should be called at the beginning of the application to use
|
||||
* the I2S driver.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param config pointer to I2S configuration structure.
|
||||
*/
|
||||
void I2S_RxInit(I2S_Type *base, const i2s_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Sets the I2S Tx configuration structure to default values.
|
||||
*
|
||||
* This API initializes the configuration structure for use in I2S_TxInit().
|
||||
* The initialized structure can remain unchanged in I2S_TxInit(), or it can be modified
|
||||
* before calling I2S_TxInit().
|
||||
* Example:
|
||||
@code
|
||||
i2s_config_t config;
|
||||
I2S_TxGetDefaultConfig(&config);
|
||||
@endcode
|
||||
*
|
||||
* Default values:
|
||||
* @code
|
||||
* config->masterSlave = kI2S_MasterSlaveNormalMaster;
|
||||
* config->mode = kI2S_ModeI2sClassic;
|
||||
* config->rightLow = false;
|
||||
* config->leftJust = false;
|
||||
* config->pdmData = false;
|
||||
* config->sckPol = false;
|
||||
* config->wsPol = false;
|
||||
* config->divider = 1;
|
||||
* config->oneChannel = false;
|
||||
* config->dataLength = 16;
|
||||
* config->frameLength = 32;
|
||||
* config->position = 0;
|
||||
* config->watermark = 4;
|
||||
* config->txEmptyZero = true;
|
||||
* config->pack48 = false;
|
||||
* @endcode
|
||||
*
|
||||
* @param config pointer to I2S configuration structure.
|
||||
*/
|
||||
void I2S_TxGetDefaultConfig(i2s_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Sets the I2S Rx configuration structure to default values.
|
||||
*
|
||||
* This API initializes the configuration structure for use in I2S_RxInit().
|
||||
* The initialized structure can remain unchanged in I2S_RxInit(), or it can be modified
|
||||
* before calling I2S_RxInit().
|
||||
* Example:
|
||||
@code
|
||||
i2s_config_t config;
|
||||
I2S_RxGetDefaultConfig(&config);
|
||||
@endcode
|
||||
*
|
||||
* Default values:
|
||||
* @code
|
||||
* config->masterSlave = kI2S_MasterSlaveNormalSlave;
|
||||
* config->mode = kI2S_ModeI2sClassic;
|
||||
* config->rightLow = false;
|
||||
* config->leftJust = false;
|
||||
* config->pdmData = false;
|
||||
* config->sckPol = false;
|
||||
* config->wsPol = false;
|
||||
* config->divider = 1;
|
||||
* config->oneChannel = false;
|
||||
* config->dataLength = 16;
|
||||
* config->frameLength = 32;
|
||||
* config->position = 0;
|
||||
* config->watermark = 4;
|
||||
* config->txEmptyZero = false;
|
||||
* config->pack48 = false;
|
||||
* @endcode
|
||||
*
|
||||
* @param config pointer to I2S configuration structure.
|
||||
*/
|
||||
void I2S_RxGetDefaultConfig(i2s_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief De-initializes the I2S peripheral.
|
||||
*
|
||||
* This API gates the FLEXCOMM clock. The I2S module can't operate unless I2S_TxInit
|
||||
* or I2S_RxInit is called to enable the clock.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
*/
|
||||
void I2S_Deinit(I2S_Type *base);
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Non-blocking API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes handle for transfer of audio data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param callback function to be called back when transfer is done or fails.
|
||||
* @param userData pointer to data passed to callback.
|
||||
*/
|
||||
void I2S_TxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData);
|
||||
|
||||
/*!
|
||||
* @brief Begins or queue sending of the given data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param transfer data buffer.
|
||||
*
|
||||
* @retval kStatus_Success
|
||||
* @retval kStatus_I2S_Busy if all queue slots are occupied with unsent buffers.
|
||||
*/
|
||||
status_t I2S_TxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer);
|
||||
|
||||
/*!
|
||||
* @brief Aborts sending of data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
*/
|
||||
void I2S_TxTransferAbort(I2S_Type *base, i2s_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Initializes handle for reception of audio data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param callback function to be called back when transfer is done or fails.
|
||||
* @param userData pointer to data passed to callback.
|
||||
*/
|
||||
void I2S_RxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData);
|
||||
|
||||
/*!
|
||||
* @brief Begins or queue reception of data into given buffer.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param transfer data buffer.
|
||||
*
|
||||
* @retval kStatus_Success
|
||||
* @retval kStatus_I2S_Busy if all queue slots are occupied with buffers which are not full.
|
||||
*/
|
||||
status_t I2S_RxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer);
|
||||
|
||||
/*!
|
||||
* @brief Aborts receiving of data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
*/
|
||||
void I2S_RxTransferAbort(I2S_Type *base, i2s_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Returns number of bytes transferred so far.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param[out] count number of bytes transferred so far by the non-blocking transaction.
|
||||
*
|
||||
* @retval kStatus_Success
|
||||
* @retval kStatus_NoTransferInProgress there is no non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t I2S_TransferGetCount(I2S_Type *base, i2s_handle_t *handle, size_t *count);
|
||||
|
||||
/*!
|
||||
* @brief Returns number of buffer underruns or overruns.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param[out] count number of transmit errors encountered so far by the non-blocking transaction.
|
||||
*
|
||||
* @retval kStatus_Success
|
||||
* @retval kStatus_NoTransferInProgress there is no non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t I2S_TransferGetErrorCount(I2S_Type *base, i2s_handle_t *handle, size_t *count);
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Enable / disable
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables I2S operation.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
*/
|
||||
static inline void I2S_Enable(I2S_Type *base)
|
||||
{
|
||||
base->CFG1 |= I2S_CFG1_MAINENABLE(1U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables I2S operation.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
*/
|
||||
static inline void I2S_Disable(I2S_Type *base)
|
||||
{
|
||||
base->CFG1 &= (~I2S_CFG1_MAINENABLE(1U));
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Interrupts
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables I2S FIFO interrupts.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param interruptMask bit mask of interrupts to enable. See #i2s_flags_t for the set
|
||||
* of constants that should be OR'd together to form the bit mask.
|
||||
*/
|
||||
static inline void I2S_EnableInterrupts(I2S_Type *base, uint32_t interruptMask)
|
||||
{
|
||||
base->FIFOINTENSET = interruptMask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables I2S FIFO interrupts.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param interruptMask bit mask of interrupts to enable. See #i2s_flags_t for the set
|
||||
* of constants that should be OR'd together to form the bit mask.
|
||||
*/
|
||||
static inline void I2S_DisableInterrupts(I2S_Type *base, uint32_t interruptMask)
|
||||
{
|
||||
base->FIFOINTENCLR = interruptMask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Returns the set of currently enabled I2S FIFO interrupts.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
*
|
||||
* @return A bitmask composed of #i2s_flags_t enumerators OR'd together
|
||||
* to indicate the set of enabled interrupts.
|
||||
*/
|
||||
static inline uint32_t I2S_GetEnabledInterrupts(I2S_Type *base)
|
||||
{
|
||||
return base->FIFOINTENSET;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Invoked from interrupt handler when transmit FIFO level decreases.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
*/
|
||||
void I2S_TxHandleIRQ(I2S_Type *base, i2s_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Invoked from interrupt handler when receive FIFO level decreases.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
*/
|
||||
void I2S_RxHandleIRQ(I2S_Type *base, i2s_handle_t *handle);
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*! @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FSL_I2S_H_ */
|
|
@ -0,0 +1,603 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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"
|
||||
#include "fsl_i2s_dma.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
#include <string.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
#define DMA_MAX_TRANSFER_BYTES (DMA_MAX_TRANSFER_COUNT * sizeof(uint32_t))
|
||||
#define DMA_DESCRIPTORS (2U)
|
||||
#define ENQUEUED_BYTES_BUFFER_SIZE (DMA_DESCRIPTORS + 1U)
|
||||
#define I2S_FIFO_DEPTH (8U)
|
||||
|
||||
/*<! @brief Structure for statically allocated private data. */
|
||||
typedef struct _i2s_dma_private_handle
|
||||
{
|
||||
I2S_Type *base; /*!< I2S base address */
|
||||
i2s_dma_handle_t *handle; /*!< I2S handle */
|
||||
volatile uint16_t
|
||||
enqueuedBytes[ENQUEUED_BYTES_BUFFER_SIZE]; /*!< Number of bytes being transferred by DMA descriptors */
|
||||
volatile uint8_t enqueuedBytesStart; /*!< First item in enqueuedBytes (for reading) */
|
||||
volatile uint8_t enqueuedBytesEnd; /*!< Last item in enqueuedBytes (for adding) */
|
||||
volatile bool initialDescriptor; /*!< Initial DMA descriptor transfer not finished yet */
|
||||
volatile uint8_t
|
||||
dmaDescriptorsUsed; /*!< Number of DMA descriptors with valid data (in queue, excluding initial descriptor) */
|
||||
volatile uint8_t descriptor; /*!< Index of next descriptor to be configured with data */
|
||||
volatile uint8_t queueDescriptor; /*!< Queue index of buffer to be actually consumed by DMA */
|
||||
volatile i2s_transfer_t descriptorQueue[I2S_NUM_BUFFERS]; /*!< Transfer data as queued to descriptors for DMA */
|
||||
} i2s_dma_private_handle_t;
|
||||
|
||||
/*! @brief I2S DMA transfer private state. */
|
||||
enum _i2s_dma_state
|
||||
{
|
||||
kI2S_DmaStateIdle = 0x0U, /*!< I2S is in idle state */
|
||||
kI2S_DmaStateTx, /*!< I2S is busy transmitting data */
|
||||
kI2S_DmaStateRx, /*!< I2S is busy receiving data */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
|
||||
static uint32_t I2S_GetInstance(I2S_Type *base);
|
||||
static void I2S_TxEnableDMA(I2S_Type *base, bool enable);
|
||||
static void I2S_RxEnableDMA(I2S_Type *base, bool enable);
|
||||
static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
|
||||
static status_t I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle, const uint16_t maxSize);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
/*<! @brief DMA transfer descriptors. */
|
||||
#if defined(__ICCARM__)
|
||||
#pragma data_alignment = 16
|
||||
static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
|
||||
#elif defined(__CC_ARM)
|
||||
__attribute__((aligned(16))) static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((aligned(16))) static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
|
||||
#endif
|
||||
|
||||
/*<! @brief Buffer with dummy TX data. */
|
||||
#if defined(__ICCARM__)
|
||||
#pragma data_alignment = 4
|
||||
static uint32_t s_DummyBufferTx = 0U;
|
||||
#elif defined(__CC_ARM)
|
||||
__attribute__((aligned(4))) static uint32_t s_DummyBufferTx = 0U;
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((aligned(4))) static uint32_t s_DummyBufferTx = 0U;
|
||||
#endif
|
||||
|
||||
/*<! @brief Buffer to fill with RX data. */
|
||||
#if defined(__ICCARM__)
|
||||
#pragma data_alignment = 4
|
||||
static uint32_t s_DummyBufferRx = 0U;
|
||||
#elif defined(__CC_ARM)
|
||||
__attribute__((aligned(4))) static uint32_t s_DummyBufferRx = 0U;
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((aligned(4))) static uint32_t s_DummyBufferRx = 0U;
|
||||
#endif
|
||||
|
||||
/*<! @brief Private array of data associated with available I2S peripherals. */
|
||||
static i2s_dma_private_handle_t s_DmaPrivateHandle[FSL_FEATURE_SOC_I2S_COUNT];
|
||||
|
||||
/*<! @brief Base addresses of available I2S peripherals. */
|
||||
static const uint32_t s_I2sBaseAddrs[FSL_FEATURE_SOC_I2S_COUNT] = I2S_BASE_ADDRS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
|
||||
{
|
||||
uint32_t instance = I2S_GetInstance(base);
|
||||
i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
|
||||
|
||||
/* Validate input data and tranfer buffer */
|
||||
|
||||
assert(handle);
|
||||
if (!handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert((((uint32_t)transfer.data) % 4U) == 0U);
|
||||
if ((((uint32_t)transfer.data) % 4U) != 0U)
|
||||
{
|
||||
/* Data not 4-bytes aligned */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert(transfer.dataSize != 0U);
|
||||
if (transfer.dataSize == 0U)
|
||||
{
|
||||
/* No data to send or receive */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
assert((transfer.dataSize % 4U) == 0U);
|
||||
if ((transfer.dataSize % 4U) != 0U)
|
||||
{
|
||||
/* Data length not multiply of 4 bytes */
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
if (handle->i2sQueue[handle->queueUser].dataSize)
|
||||
{
|
||||
/* Previously prepared buffers not processed yet, reject request */
|
||||
return kStatus_I2S_Busy;
|
||||
}
|
||||
|
||||
/* Enqueue data */
|
||||
privateHandle->descriptorQueue[handle->queueUser].data = transfer.data;
|
||||
privateHandle->descriptorQueue[handle->queueUser].dataSize = transfer.dataSize;
|
||||
handle->i2sQueue[handle->queueUser].data = transfer.data;
|
||||
handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
|
||||
handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
static uint32_t I2S_GetInstance(I2S_Type *base)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0U; i < FSL_FEATURE_SOC_I2S_COUNT; i++)
|
||||
{
|
||||
if ((uint32_t)base == s_I2sBaseAddrs[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void I2S_TxTransferCreateHandleDMA(I2S_Type *base,
|
||||
i2s_dma_handle_t *handle,
|
||||
dma_handle_t *dmaHandle,
|
||||
i2s_dma_transfer_callback_t callback,
|
||||
void *userData)
|
||||
{
|
||||
assert(handle);
|
||||
assert(dmaHandle);
|
||||
|
||||
uint32_t instance = I2S_GetInstance(base);
|
||||
i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
|
||||
|
||||
memset(handle, 0U, sizeof(*handle));
|
||||
handle->state = kI2S_DmaStateIdle;
|
||||
handle->dmaHandle = dmaHandle;
|
||||
handle->completionCallback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
memset(privateHandle, 0U, sizeof(*privateHandle));
|
||||
privateHandle->base = base;
|
||||
privateHandle->handle = handle;
|
||||
privateHandle->initialDescriptor = false;
|
||||
|
||||
DMA_SetCallback(dmaHandle, I2S_DMACallback, privateHandle);
|
||||
}
|
||||
|
||||
status_t I2S_TxTransferSendDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
|
||||
{
|
||||
/* Enqueue transfer buffer */
|
||||
status_t status = I2S_EnqueueUserBuffer(base, handle, transfer);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Initialize DMA transfer */
|
||||
if (handle->state == kI2S_DmaStateIdle)
|
||||
{
|
||||
handle->state = kI2S_DmaStateTx;
|
||||
return I2S_StartTransferDMA(base, handle);
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2S_TransferAbortDMA(I2S_Type *base, i2s_dma_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->dmaHandle);
|
||||
|
||||
uint32_t instance = I2S_GetInstance(base);
|
||||
i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
|
||||
|
||||
/* Abort operation */
|
||||
DMA_AbortTransfer(handle->dmaHandle);
|
||||
if (handle->state == kI2S_DmaStateTx)
|
||||
{
|
||||
I2S_TxEnableDMA(base, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
I2S_RxEnableDMA(base, false);
|
||||
}
|
||||
I2S_Disable(base);
|
||||
|
||||
/* Reset state */
|
||||
handle->state = kI2S_DmaStateIdle;
|
||||
|
||||
/* Clear transfer queue */
|
||||
memset((void *)&(handle->i2sQueue), 0U, sizeof(handle->i2sQueue));
|
||||
handle->queueDriver = 0U;
|
||||
handle->queueUser = 0U;
|
||||
|
||||
/* Clear internal state */
|
||||
memset((void *)&(privateHandle->descriptorQueue), 0U, sizeof(privateHandle->descriptorQueue));
|
||||
memset((void *)&(privateHandle->enqueuedBytes), 0U, sizeof(privateHandle->enqueuedBytes));
|
||||
privateHandle->enqueuedBytesStart = 0U;
|
||||
privateHandle->enqueuedBytesEnd = 0U;
|
||||
privateHandle->initialDescriptor = false;
|
||||
privateHandle->dmaDescriptorsUsed = 0U;
|
||||
privateHandle->descriptor = 0U;
|
||||
privateHandle->queueDescriptor = 0U;
|
||||
}
|
||||
|
||||
void I2S_RxTransferCreateHandleDMA(I2S_Type *base,
|
||||
i2s_dma_handle_t *handle,
|
||||
dma_handle_t *dmaHandle,
|
||||
i2s_dma_transfer_callback_t callback,
|
||||
void *userData)
|
||||
{
|
||||
I2S_TxTransferCreateHandleDMA(base, handle, dmaHandle, callback, userData);
|
||||
}
|
||||
|
||||
status_t I2S_RxTransferReceiveDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
|
||||
{
|
||||
/* Enqueue transfer buffer */
|
||||
status_t status = I2S_EnqueueUserBuffer(base, handle, transfer);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Initialize DMA transfer */
|
||||
if (handle->state == kI2S_DmaStateIdle)
|
||||
{
|
||||
handle->state = kI2S_DmaStateRx;
|
||||
return I2S_StartTransferDMA(base, handle);
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
static void I2S_TxEnableDMA(I2S_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->FIFOCFG |= I2S_FIFOCFG_DMATX_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOCFG &= (~I2S_FIFOCFG_DMATX_MASK);
|
||||
base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static void I2S_RxEnableDMA(I2S_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->FIFOCFG |= I2S_FIFOCFG_DMARX_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOCFG &= (~I2S_FIFOCFG_DMARX_MASK);
|
||||
base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
|
||||
{
|
||||
status_t status;
|
||||
dma_transfer_config_t xferConfig = {0};
|
||||
i2s_dma_private_handle_t *privateHandle;
|
||||
i2s_transfer_t volatile *transfer;
|
||||
uint16_t transferBytes;
|
||||
uint32_t instance;
|
||||
uint32_t i;
|
||||
|
||||
instance = I2S_GetInstance(base);
|
||||
privateHandle = &(s_DmaPrivateHandle[instance]);
|
||||
transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
|
||||
|
||||
/*
|
||||
* Divide first buffer between initial DMA descriptor and chained DMA descriptors.
|
||||
* This allows to enqueue more data before entire buffer is processed
|
||||
* and thus could prevent audio drop-outs due to requeing.
|
||||
* But user is expected to enqueue more data in order for this to work.
|
||||
*/
|
||||
transferBytes = (transfer->dataSize / (DMA_DESCRIPTORS + 1U));
|
||||
|
||||
if (transferBytes > DMA_MAX_TRANSFER_BYTES)
|
||||
{
|
||||
transferBytes = DMA_MAX_TRANSFER_BYTES;
|
||||
}
|
||||
|
||||
if ((transferBytes % 4U) != 0U)
|
||||
{
|
||||
transferBytes -= (transferBytes % 4U);
|
||||
}
|
||||
|
||||
assert(transferBytes > 0U);
|
||||
if (transferBytes == 0U)
|
||||
{
|
||||
/*
|
||||
* TODO buffer too small to be divided for multiple descriptors
|
||||
* return invalid argument status for now
|
||||
*/
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Prepare transfer of data via initial DMA transfer descriptor */
|
||||
DMA_PrepareTransfer(
|
||||
&xferConfig, (handle->state == kI2S_DmaStateTx) ? (void *)transfer->data : (void *)&(base->FIFORD),
|
||||
(handle->state == kI2S_DmaStateTx) ? (void *)&(base->FIFOWR) : (void *)transfer->data, sizeof(uint32_t),
|
||||
transferBytes, (handle->state == kI2S_DmaStateTx) ? kDMA_MemoryToPeripheral : kDMA_PeripheralToMemory,
|
||||
(void *)&(s_DmaDescriptors[(instance * FSL_FEATURE_SOC_I2S_COUNT) + 0U]));
|
||||
|
||||
privateHandle->initialDescriptor = true; /* For IRQ handler to know that it will be fired for first descriptor */
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
|
||||
privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % ENQUEUED_BYTES_BUFFER_SIZE;
|
||||
|
||||
transfer->dataSize -= transferBytes;
|
||||
transfer->data += transferBytes;
|
||||
if (transfer->dataSize == 0U)
|
||||
{
|
||||
transfer->data = NULL;
|
||||
privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
|
||||
}
|
||||
|
||||
/* Prepare chained descriptors to transfer 2nd and 3rd part of initial data */
|
||||
for (i = 0; i < DMA_DESCRIPTORS; i++)
|
||||
{
|
||||
if (i == (DMA_DESCRIPTORS - 1))
|
||||
{
|
||||
/* Last buffer will take the rest of data (because of possible truncating by division) */
|
||||
transferBytes = transfer->dataSize;
|
||||
if (transferBytes > DMA_MAX_TRANSFER_BYTES)
|
||||
{
|
||||
transferBytes = DMA_MAX_TRANSFER_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
I2S_AddTransferDMA(base, handle, transferBytes);
|
||||
}
|
||||
|
||||
/* Submit and start initial DMA transfer */
|
||||
|
||||
if (handle->state == kI2S_DmaStateTx)
|
||||
{
|
||||
I2S_TxEnableDMA(base, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
I2S_RxEnableDMA(base, true);
|
||||
}
|
||||
|
||||
status = DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
DMA_StartTransfer(handle->dmaHandle);
|
||||
|
||||
I2S_Enable(base);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
static status_t I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle, const uint16_t maxSize)
|
||||
{
|
||||
dma_xfercfg_t xfercfg;
|
||||
i2s_transfer_t volatile *transfer;
|
||||
uint16_t transferBytes;
|
||||
uint32_t instance;
|
||||
i2s_dma_private_handle_t *privateHandle;
|
||||
dma_descriptor_t *descriptor;
|
||||
dma_descriptor_t *nextDescriptor;
|
||||
|
||||
instance = I2S_GetInstance(base);
|
||||
privateHandle = &(s_DmaPrivateHandle[instance]);
|
||||
|
||||
if (privateHandle->dmaDescriptorsUsed >= DMA_DESCRIPTORS)
|
||||
{
|
||||
/* No unprocessed DMA transfer descriptor */
|
||||
return kStatus_I2S_Busy;
|
||||
}
|
||||
|
||||
transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
|
||||
|
||||
/* Determine currently configured descriptor and the other which it will link to */
|
||||
descriptor = &(s_DmaDescriptors[(instance * FSL_FEATURE_SOC_I2S_COUNT) + privateHandle->descriptor]);
|
||||
privateHandle->descriptor = (privateHandle->descriptor + 1U) % DMA_DESCRIPTORS;
|
||||
nextDescriptor = &(s_DmaDescriptors[(instance * FSL_FEATURE_SOC_I2S_COUNT) + privateHandle->descriptor]);
|
||||
|
||||
if (transfer->dataSize == 0U)
|
||||
{
|
||||
/* Currently nothing to enqueue, use dummy buffer instead */
|
||||
|
||||
xfercfg.valid = false;
|
||||
xfercfg.reload = true;
|
||||
xfercfg.swtrig = false;
|
||||
xfercfg.clrtrig = false;
|
||||
xfercfg.intA = true;
|
||||
xfercfg.intB = false;
|
||||
xfercfg.byteWidth = sizeof(uint32_t);
|
||||
xfercfg.srcInc = 0U;
|
||||
xfercfg.dstInc = 0U;
|
||||
xfercfg.transferCount = I2S_FIFO_DEPTH + 1U;
|
||||
|
||||
DMA_CreateDescriptor(descriptor, &xfercfg,
|
||||
(handle->state == kI2S_DmaStateTx) ? (void *)&s_DummyBufferTx : (void *)&(base->FIFORD),
|
||||
(handle->state == kI2S_DmaStateTx) ? (void *)&(base->FIFOWR) : (void *)&s_DummyBufferRx,
|
||||
(void *)nextDescriptor);
|
||||
|
||||
/* TODO use API for this once it is available in DMA driver */
|
||||
descriptor->xfercfg |= DMA_CHANNEL_XFERCFG_CFGVALID(1U);
|
||||
handle->dmaHandle->base->COMMON->SETVALID = (1U << (handle->dmaHandle->channel));
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
else if (transfer->dataSize > maxSize)
|
||||
{
|
||||
/* Take part of data - DMA transfer limitation */
|
||||
transferBytes = maxSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Entire buffer can fit into a single descriptor */
|
||||
transferBytes = transfer->dataSize;
|
||||
privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
|
||||
}
|
||||
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
|
||||
privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % ENQUEUED_BYTES_BUFFER_SIZE;
|
||||
|
||||
/* Configure descriptor */
|
||||
|
||||
xfercfg.valid = false;
|
||||
xfercfg.reload = true;
|
||||
xfercfg.swtrig = false;
|
||||
xfercfg.clrtrig = false;
|
||||
xfercfg.intA = true;
|
||||
xfercfg.intB = false;
|
||||
xfercfg.byteWidth = sizeof(uint32_t);
|
||||
xfercfg.srcInc = (handle->state == kI2S_DmaStateTx) ? 1U : 0U;
|
||||
xfercfg.dstInc = (handle->state == kI2S_DmaStateTx) ? 0U : 1U;
|
||||
xfercfg.transferCount = transferBytes / sizeof(uint32_t);
|
||||
|
||||
DMA_CreateDescriptor(
|
||||
descriptor, &xfercfg, (handle->state == kI2S_DmaStateTx) ? (void *)transfer->data : (void *)&(base->FIFORD),
|
||||
(handle->state == kI2S_DmaStateTx) ? (void *)&(base->FIFOWR) : (void *)transfer->data, (void *)nextDescriptor);
|
||||
|
||||
/* TODO use API for this once it is available in DMA driver */
|
||||
descriptor->xfercfg |= DMA_CHANNEL_XFERCFG_CFGVALID(1U);
|
||||
handle->dmaHandle->base->COMMON->SETVALID = (1U << (handle->dmaHandle->channel));
|
||||
|
||||
/* Advance internal state */
|
||||
privateHandle->dmaDescriptorsUsed++;
|
||||
transfer->dataSize -= transferBytes;
|
||||
transfer->data += transferBytes;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void I2S_DMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
|
||||
{
|
||||
i2s_dma_private_handle_t *privateHandle = (i2s_dma_private_handle_t *)userData;
|
||||
i2s_dma_handle_t *i2sHandle = privateHandle->handle;
|
||||
I2S_Type *base = privateHandle->base;
|
||||
|
||||
if (!transferDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
|
||||
{
|
||||
/*
|
||||
* All user buffers processed before, dataSize already zero,
|
||||
* this means at least one dummy buffer sent/received
|
||||
* and no new buffer enqueued by user meanwhile.
|
||||
*/
|
||||
|
||||
I2S_TransferAbortDMA(base, i2sHandle);
|
||||
|
||||
/* Notify user about completion of the final buffer */
|
||||
if (i2sHandle->completionCallback)
|
||||
{
|
||||
(i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_Done, i2sHandle->userData);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (privateHandle->initialDescriptor)
|
||||
{
|
||||
/* Initial descriptor finished, decrease amount of data to be processed */
|
||||
|
||||
assert(privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] > 0U);
|
||||
|
||||
i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize -=
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
|
||||
i2sHandle->i2sQueue[i2sHandle->queueDriver].data +=
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] = 0U;
|
||||
privateHandle->enqueuedBytesStart = (privateHandle->enqueuedBytesStart + 1U) % ENQUEUED_BYTES_BUFFER_SIZE;
|
||||
|
||||
privateHandle->initialDescriptor = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (privateHandle->dmaDescriptorsUsed > 0U)
|
||||
{
|
||||
/* Finished one of chained descriptors, decrease amount of data to be processed */
|
||||
|
||||
assert(privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] > 0U);
|
||||
|
||||
i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize -=
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
|
||||
i2sHandle->i2sQueue[i2sHandle->queueDriver].data +=
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
|
||||
privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] = 0U;
|
||||
privateHandle->enqueuedBytesStart = (privateHandle->enqueuedBytesStart + 1U) % ENQUEUED_BYTES_BUFFER_SIZE;
|
||||
|
||||
privateHandle->dmaDescriptorsUsed--;
|
||||
}
|
||||
}
|
||||
|
||||
if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
|
||||
{
|
||||
/* Entire user buffer sent or received - advance to next one */
|
||||
i2sHandle->i2sQueue[i2sHandle->queueDriver].data = NULL;
|
||||
i2sHandle->queueDriver = (i2sHandle->queueDriver + 1U) % I2S_NUM_BUFFERS;
|
||||
|
||||
/* Notify user about buffer completion */
|
||||
if (i2sHandle->completionCallback)
|
||||
{
|
||||
(i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_BufferComplete, i2sHandle->userData);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enqueue new chunk of data to DMA (if any) */
|
||||
I2S_AddTransferDMA(base, i2sHandle, DMA_MAX_TRANSFER_BYTES);
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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_I2S_DMA_H_
|
||||
#define _FSL_I2S_DMA_H_
|
||||
|
||||
#include "fsl_device_registers.h"
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
|
||||
#include "fsl_dma.h"
|
||||
#include "fsl_i2s.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @addtogroup i2s_dma_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief I2S DMA driver version 2.0.0.
|
||||
*
|
||||
* Current version: 2.0.0
|
||||
*
|
||||
* Change log:
|
||||
* - Version 2.0.0
|
||||
* - initial version
|
||||
*/
|
||||
#define FSL_I2S_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*! @brief Members not to be accessed / modified outside of the driver. */
|
||||
typedef struct _i2s_dma_handle i2s_dma_handle_t;
|
||||
|
||||
/*!
|
||||
* @brief Callback function invoked from DMA API on completion.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to I2S transaction.
|
||||
* @param completionStatus status of the transaction.
|
||||
* @param userData optional pointer to user arguments data.
|
||||
*/
|
||||
typedef void (*i2s_dma_transfer_callback_t)(I2S_Type *base,
|
||||
i2s_dma_handle_t *handle,
|
||||
status_t completionStatus,
|
||||
void *userData);
|
||||
|
||||
struct _i2s_dma_handle
|
||||
{
|
||||
uint32_t state; /*!< Internal state of I2S DMA transfer */
|
||||
i2s_dma_transfer_callback_t completionCallback; /*!< Callback function pointer */
|
||||
void *userData; /*!< Application data passed to callback */
|
||||
dma_handle_t *dmaHandle; /*!< DMA handle */
|
||||
volatile i2s_transfer_t i2sQueue[I2S_NUM_BUFFERS]; /*!< Transfer queue storing transfer buffers */
|
||||
volatile uint8_t queueUser; /*!< Queue index where user's next transfer will be stored */
|
||||
volatile uint8_t queueDriver; /*!< Queue index of buffer actually used by the driver */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name DMA API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes handle for transfer of audio data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param dmaHandle pointer to dma handle structure.
|
||||
* @param callback function to be called back when transfer is done or fails.
|
||||
* @param userData pointer to data passed to callback.
|
||||
*/
|
||||
void I2S_TxTransferCreateHandleDMA(I2S_Type *base,
|
||||
i2s_dma_handle_t *handle,
|
||||
dma_handle_t *dmaHandle,
|
||||
i2s_dma_transfer_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
* @brief Begins or queue sending of the given data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param transfer data buffer.
|
||||
*
|
||||
* @retval kStatus_Success
|
||||
* @retval kStatus_I2S_Busy if all queue slots are occupied with unsent buffers.
|
||||
*/
|
||||
status_t I2S_TxTransferSendDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
|
||||
|
||||
/*!
|
||||
* @brief Aborts transfer of data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
*/
|
||||
void I2S_TransferAbortDMA(I2S_Type *base, i2s_dma_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Initializes handle for reception of audio data.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param dmaHandle pointer to dma handle structure.
|
||||
* @param callback function to be called back when transfer is done or fails.
|
||||
* @param userData pointer to data passed to callback.
|
||||
*/
|
||||
void I2S_RxTransferCreateHandleDMA(I2S_Type *base,
|
||||
i2s_dma_handle_t *handle,
|
||||
dma_handle_t *dmaHandle,
|
||||
i2s_dma_transfer_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
* @brief Begins or queue reception of data into given buffer.
|
||||
*
|
||||
* @param base I2S base pointer.
|
||||
* @param handle pointer to handle structure.
|
||||
* @param transfer data buffer.
|
||||
*
|
||||
* @retval kStatus_Success
|
||||
* @retval kStatus_I2S_Busy if all queue slots are occupied with buffers
|
||||
* which are not full.
|
||||
*/
|
||||
status_t I2S_RxTransferReceiveDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
|
||||
|
||||
/*!
|
||||
* @brief Invoked from DMA interrupt handler.
|
||||
*
|
||||
* @param handle pointer to DMA handle structure.
|
||||
* @param userData argument for user callback.
|
||||
* @param transferDone if transfer was done.
|
||||
* @param tcds
|
||||
*/
|
||||
void I2S_DMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds);
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*! @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FSL_I2S_DMA_H_ */
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_inputmux.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void INPUTMUX_Init(INPUTMUX_Type *base)
|
||||
{
|
||||
CLOCK_EnableClock(kCLOCK_InputMux);
|
||||
}
|
||||
|
||||
void INPUTMUX_AttachSignal(INPUTMUX_Type *base, uint32_t index, inputmux_connection_t connection)
|
||||
{
|
||||
uint32_t pmux_id;
|
||||
uint32_t output_id;
|
||||
|
||||
/* extract pmux to be used */
|
||||
pmux_id = ((uint32_t)(connection)) >> PMUX_SHIFT;
|
||||
/* extract function number */
|
||||
output_id = ((uint32_t)(connection)) & 0xffffU;
|
||||
/* programm signal */
|
||||
*(volatile uint32_t *)(((uint32_t)base) + pmux_id + (index * 4)) = output_id;
|
||||
}
|
||||
|
||||
void INPUTMUX_Deinit(INPUTMUX_Type *base)
|
||||
{
|
||||
CLOCK_DisableClock(kCLOCK_InputMux);
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_INPUTMUX_H_
|
||||
#define _FSL_INPUTMUX_H_
|
||||
|
||||
#include "fsl_inputmux_connections.h"
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup inputmux_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
/*! @file fsl_inputmux_connections.h */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief Group interrupt driver version for SDK */
|
||||
#define FSL_INPUTMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
|
||||
/*@}*/
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Initialize INPUTMUX peripheral.
|
||||
|
||||
* This function enables the INPUTMUX clock.
|
||||
*
|
||||
* @param base Base address of the INPUTMUX peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void INPUTMUX_Init(INPUTMUX_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Attaches a signal
|
||||
*
|
||||
* This function gates the INPUTPMUX clock.
|
||||
*
|
||||
* @param base Base address of the INPUTMUX peripheral.
|
||||
* @param index Destination peripheral to attach the signal to.
|
||||
* @param connection Selects connection.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void INPUTMUX_AttachSignal(INPUTMUX_Type *base, uint32_t index, inputmux_connection_t connection);
|
||||
|
||||
/*!
|
||||
* @brief Deinitialize INPUTMUX peripheral.
|
||||
|
||||
* This function disables the INPUTMUX clock.
|
||||
*
|
||||
* @param base Base address of the INPUTMUX peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void INPUTMUX_Deinit(INPUTMUX_Type *base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_INPUTMUX_H_ */
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_INPUTMUX_CONNECTIONS_
|
||||
#define _FSL_INPUTMUX_CONNECTIONS_
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @addtogroup inputmux_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @brief Periphinmux IDs */
|
||||
#define PINTSEL_PMUX_ID 0xC0U
|
||||
#define DMA_TRIG0_PMUX_ID 0xE0U
|
||||
#define DMA_OTRIG_PMUX_ID 0x160U
|
||||
#define FREQMEAS_PMUX_ID 0x180U
|
||||
#define PMUX_SHIFT 20U
|
||||
|
||||
/*! @brief INPUTMUX connections type */
|
||||
typedef enum _inputmux_connection_t
|
||||
{
|
||||
/*!< Frequency measure. */
|
||||
kINPUTMUX_MainOscToFreqmeas = 0U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Fro12MhzToFreqmeas = 1U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_WdtOscToFreqmeas = 2U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_32KhzOscToFreqmeas = 3U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_MainClkToFreqmeas = 4U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin4ToFreqmeas = 5U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin20ToFreqmeas = 6U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin24ToFreqmeas = 7U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin4ToFreqmeas = 8U + (FREQMEAS_PMUX_ID << PMUX_SHIFT),
|
||||
/*!< Pin Interrupt. */
|
||||
kINPUTMUX_GpioPort0Pin0ToPintsel = 0U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin1ToPintsel = 1U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin2ToPintsel = 2U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin3ToPintsel = 3U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin4ToPintsel = 4U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin5ToPintsel = 5U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin6ToPintsel = 6U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin7ToPintsel = 7U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin8ToPintsel = 8U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin9ToPintsel = 9U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin10ToPintsel = 10U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin11ToPintsel = 11U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin12ToPintsel = 12U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin13ToPintsel = 13U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin14ToPintsel = 14U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin15ToPintsel = 15U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin16ToPintsel = 16U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin17ToPintsel = 17U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin18ToPintsel = 18U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin19ToPintsel = 19U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin20ToPintsel = 20U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin21ToPintsel = 21U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin22ToPintsel = 22U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin23ToPintsel = 23U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin24ToPintsel = 24U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin25ToPintsel = 25U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin26ToPintsel = 26U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin27ToPintsel = 27U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin28ToPintsel = 28U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin29ToPintsel = 29U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin30ToPintsel = 30U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort0Pin31ToPintsel = 31U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin0ToPintsel = 32U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin1ToPintsel = 33U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin2ToPintsel = 34U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin3ToPintsel = 35U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin4ToPintsel = 36U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin5ToPintsel = 37U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin6ToPintsel = 38U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin7ToPintsel = 39U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin8ToPintsel = 40U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin9ToPintsel = 41U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin10ToPintsel = 42U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin11ToPintsel = 43U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin12ToPintsel = 44U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin13ToPintsel = 45U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin14ToPintsel = 46U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin15ToPintsel = 47U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin16ToPintsel = 48U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin17ToPintsel = 49U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin18ToPintsel = 50U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin19ToPintsel = 51U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin20ToPintsel = 52U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin21ToPintsel = 53U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin22ToPintsel = 54U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin23ToPintsel = 55U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin24ToPintsel = 56U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin25ToPintsel = 57U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin26ToPintsel = 58U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin27ToPintsel = 59U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin28ToPintsel = 60U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin29ToPintsel = 61U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin30ToPintsel = 62U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_GpioPort1Pin31ToPintsel = 63U + (PINTSEL_PMUX_ID << PMUX_SHIFT),
|
||||
/*!< DMA ITRIG. */
|
||||
kINPUTMUX_Adc0SeqaIrqToDma = 0U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_ADC0SeqbIrqToDma = 1U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Sct0DmaReq0ToDma = 2U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Sct0DmaReq1ToDma = 3U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer0M0ToDma = 4U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer0M1ToDma = 5U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer1M0ToDma = 6U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer2M0ToDma = 7U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer2M1ToDma = 8U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer3M0ToDma = 9U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer4M0ToDma = 10U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Ctimer4M1ToDma = 11U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_PinInt0ToDma = 12U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_PinInt1ToDma = 13U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_PinInt2ToDma = 14U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_PinInt3ToDma = 15U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Otrig0ToDma = 16U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Otrig1ToDma = 17U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Otrig2ToDma = 18U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Otrig3ToDma = 19U + (DMA_TRIG0_PMUX_ID << PMUX_SHIFT),
|
||||
/*!< DMA OTRIG. */
|
||||
kINPUTMUX_DmaFlexcomm0RxTrigoutToTriginChannels = 0U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm0TxTrigoutToTriginChannels = 1U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm1RxTrigoutToTriginChannels = 2U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm1TxTrigoutToTriginChannels = 3U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm2RxTrigoutToTriginChannels = 4U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm2TxTrigoutToTriginChannels = 5U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm3RxTrigoutToTriginChannels = 6U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm3TxTrigoutToTriginChannels = 7U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm4RxTrigoutToTriginChannels = 8U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm4TxTrigoutToTriginChannels = 9U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm5RxTrigoutToTriginChannels = 10U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm5TxTrigoutToTriginChannels = 11U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm6RxTrigoutToTriginChannels = 12U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm6TxTrigoutToTriginChannels = 13U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm7RxTrigoutToTriginChannels = 14U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaFlexcomm7TxTrigoutToTriginChannels = 15U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaDmic0Ch0TrigoutToTriginChannels = 16U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_Dmamic0Ch1TrigoutToTriginChannels = 17U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaSpifi0TrigoutToTriginChannels = 18U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
kINPUTMUX_DmaChannel19_TrigoutToTriginChannels = 19U + (DMA_OTRIG_PMUX_ID << PMUX_SHIFT),
|
||||
} inputmux_connection_t;
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_INPUTMUX_CONNECTIONS_ */
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_IOCON_H_
|
||||
#define _FSL_IOCON_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup lpc_iocon
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief IOCON driver version 2.0.0. */
|
||||
#define LPC_IOCON_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* @brief Array of IOCON pin definitions passed to IOCON_SetPinMuxing() must be in this format
|
||||
*/
|
||||
typedef struct _iocon_group
|
||||
{
|
||||
uint32_t port : 8; /* Pin port */
|
||||
uint32_t pin : 8; /* Pin number */
|
||||
uint32_t modefunc : 16; /* Function and mode */
|
||||
} iocon_group_t;
|
||||
|
||||
/**
|
||||
* @brief IOCON function and mode selection definitions
|
||||
* @note See the User Manual for specific modes and functions supported by the various pins.
|
||||
*/
|
||||
#define IOCON_FUNC0 0x0 /*!< Selects pin function 0 */
|
||||
#define IOCON_FUNC1 0x1 /*!< Selects pin function 1 */
|
||||
#define IOCON_FUNC2 0x2 /*!< Selects pin function 2 */
|
||||
#define IOCON_FUNC3 0x3 /*!< Selects pin function 3 */
|
||||
#define IOCON_FUNC4 0x4 /*!< Selects pin function 4 */
|
||||
#define IOCON_FUNC5 0x5 /*!< Selects pin function 5 */
|
||||
#define IOCON_FUNC6 0x6 /*!< Selects pin function 6 */
|
||||
#define IOCON_FUNC7 0x7 /*!< Selects pin function 7 */
|
||||
#define IOCON_MODE_INACT (0x0 << 3) /*!< No addition pin function */
|
||||
#define IOCON_MODE_PULLDOWN (0x1 << 3) /*!< Selects pull-down function */
|
||||
#define IOCON_MODE_PULLUP (0x2 << 3) /*!< Selects pull-up function */
|
||||
#define IOCON_MODE_REPEATER (0x3 << 3) /*!< Selects pin repeater function */
|
||||
#define IOCON_HYS_EN (0x1 << 5) /*!< Enables hysteresis */
|
||||
#define IOCON_GPIO_MODE (0x1 << 5) /*!< GPIO Mode */
|
||||
#define IOCON_I2C_SLEW (0x1 << 5) /*!< I2C Slew Rate Control */
|
||||
#define IOCON_INV_EN (0x1 << 6) /*!< Enables invert function on input */
|
||||
#define IOCON_ANALOG_EN (0x0 << 7) /*!< Enables analog function by setting 0 to bit 7 */
|
||||
#define IOCON_DIGITAL_EN (0x1 << 7) /*!< Enables digital function by setting 1 to bit 7(default) */
|
||||
#define IOCON_STDI2C_EN (0x1 << 8) /*!< I2C standard mode/fast-mode */
|
||||
#define IOCON_FASTI2C_EN (0x3 << 8) /*!< I2C Fast-mode Plus and high-speed slave */
|
||||
#define IOCON_INPFILT_OFF (0x1 << 8) /*!< Input filter Off for GPIO pins */
|
||||
#define IOCON_INPFILT_ON (0x0 << 8) /*!< Input filter On for GPIO pins */
|
||||
#define IOCON_OPENDRAIN_EN (0x1 << 10) /*!< Enables open-drain function */
|
||||
#define IOCON_S_MODE_0CLK (0x0 << 11) /*!< Bypass input filter */
|
||||
#define IOCON_S_MODE_1CLK (0x1 << 11) /*!< Input pulses shorter than 1 filter clock are rejected */
|
||||
#define IOCON_S_MODE_2CLK (0x2 << 11) /*!< Input pulses shorter than 2 filter clock2 are rejected */
|
||||
#define IOCON_S_MODE_3CLK (0x3 << 11) /*!< Input pulses shorter than 3 filter clock2 are rejected */
|
||||
#define IOCON_S_MODE(clks) ((clks) << 11) /*!< Select clocks for digital input filter mode */
|
||||
#define IOCON_CLKDIV(div) \
|
||||
((div) << 13) /*!< Select peripheral clock divider for input filter sampling clock, 2^n, n=0-6 */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sets I/O Control pin mux
|
||||
* @param base : The base of IOCON peripheral on the chip
|
||||
* @param port : GPIO port to mux
|
||||
* @param pin : GPIO pin to mux
|
||||
* @param modefunc : OR'ed values of type IOCON_*
|
||||
* @return Nothing
|
||||
*/
|
||||
__STATIC_INLINE void IOCON_PinMuxSet(IOCON_Type *base, uint8_t port, uint8_t pin, uint32_t modefunc)
|
||||
{
|
||||
base->PIO[port][pin] = modefunc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set all I/O Control pin muxing
|
||||
* @param base : The base of IOCON peripheral on the chip
|
||||
* @param pinArray : Pointer to array of pin mux selections
|
||||
* @param arrayLength : Number of entries in pinArray
|
||||
* @return Nothing
|
||||
*/
|
||||
__STATIC_INLINE void IOCON_SetPinMuxing(IOCON_Type *base, const iocon_group_t *pinArray, uint32_t arrayLength)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < arrayLength; i++)
|
||||
{
|
||||
IOCON_PinMuxSet(base, pinArray[i].port, pinArray[i].pin, pinArray[i].modefunc);
|
||||
}
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FSL_IOCON_H_ */
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_MAILBOX_H_
|
||||
#define _FSL_MAILBOX_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup mailbox
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/******************************************************************************
|
||||
* Definitions
|
||||
*****************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief MAILBOX driver version 2.0.0. */
|
||||
#define FSL_MAILBOX_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*!
|
||||
* @brief CPU ID.
|
||||
*/
|
||||
typedef enum _mailbox_cpu_id
|
||||
{
|
||||
kMAILBOX_CM0Plus = 0,
|
||||
kMAILBOX_CM4
|
||||
} mailbox_cpu_id_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name MAILBOX initialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes the MAILBOX module.
|
||||
*
|
||||
* This function enables the MAILBOX clock only.
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
*/
|
||||
static inline void MAILBOX_Init(MAILBOX_Type *base)
|
||||
{
|
||||
CLOCK_EnableClock(kCLOCK_Mailbox);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief De-initializes the MAILBOX module.
|
||||
*
|
||||
* This function disables the MAILBOX clock only.
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
*/
|
||||
static inline void MAILBOX_Deinit(MAILBOX_Type *base)
|
||||
{
|
||||
CLOCK_DisableClock(kCLOCK_Mailbox);
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @brief Set data value in the mailbox based on the CPU ID.
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
* @param cpu_id CPU id, kMAILBOX_CM0Plus is M0+ or kMAILBOX_CM4 is M4.
|
||||
* @param mboxData Data to send in the mailbox.
|
||||
*
|
||||
* @note Sets a data value to send via the MAILBOX to the other core.
|
||||
*/
|
||||
static inline void MAILBOX_SetValue(MAILBOX_Type *base, mailbox_cpu_id_t cpu_id, uint32_t mboxData)
|
||||
{
|
||||
assert((cpu_id == kMAILBOX_CM0Plus) || (cpu_id == kMAILBOX_CM4));
|
||||
base->MBOXIRQ[cpu_id].IRQ = mboxData;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get data in the mailbox based on the CPU ID.
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
* @param cpu_id CPU id, kMAILBOX_CM0Plus is M0+ or kMAILBOX_CM4 is M4.
|
||||
*
|
||||
* @return Current mailbox data.
|
||||
*/
|
||||
static inline uint32_t MAILBOX_GetValue(MAILBOX_Type *base, mailbox_cpu_id_t cpu_id)
|
||||
{
|
||||
assert((cpu_id == kMAILBOX_CM0Plus) || (cpu_id == kMAILBOX_CM4));
|
||||
return base->MBOXIRQ[cpu_id].IRQ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set data bits in the mailbox based on the CPU ID.
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
* @param cpu_id CPU id, kMAILBOX_CM0Plus is M0+ or kMAILBOX_CM4 is M4.
|
||||
* @param mboxSetBits Data bits to set in the mailbox.
|
||||
*
|
||||
* @note Sets data bits to send via the MAILBOX to the other core. A value of 0 will
|
||||
* do nothing. Only sets bits selected with a 1 in it's bit position.
|
||||
*/
|
||||
static inline void MAILBOX_SetValueBits(MAILBOX_Type *base, mailbox_cpu_id_t cpu_id, uint32_t mboxSetBits)
|
||||
{
|
||||
assert((cpu_id == kMAILBOX_CM0Plus) || (cpu_id == kMAILBOX_CM4));
|
||||
base->MBOXIRQ[cpu_id].IRQSET = mboxSetBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear data bits in the mailbox based on the CPU ID.
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
* @param cpu_id CPU id, kMAILBOX_CM0Plus is M0+ or kMAILBOX_CM4 is M4.
|
||||
* @param mboxClrBits Data bits to clear in the mailbox.
|
||||
*
|
||||
* @note Clear data bits to send via the MAILBOX to the other core. A value of 0 will
|
||||
* do nothing. Only clears bits selected with a 1 in it's bit position.
|
||||
*/
|
||||
static inline void MAILBOX_ClearValueBits(MAILBOX_Type *base, mailbox_cpu_id_t cpu_id, uint32_t mboxClrBits)
|
||||
{
|
||||
assert((cpu_id == kMAILBOX_CM0Plus) || (cpu_id == kMAILBOX_CM4));
|
||||
base->MBOXIRQ[cpu_id].IRQCLR = mboxClrBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get MUTEX state and lock mutex
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
*
|
||||
* @return See note
|
||||
*
|
||||
* @note Returns '1' if the mutex was taken or '0' if another resources has the
|
||||
* mutex locked. Once a mutex is taken, it can be returned with the MAILBOX_SetMutex()
|
||||
* function.
|
||||
*/
|
||||
static inline uint32_t MAILBOX_GetMutex(MAILBOX_Type *base)
|
||||
{
|
||||
return (base->MUTEX & MAILBOX_MUTEX_EX_MASK);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set MUTEX state
|
||||
*
|
||||
* @param base MAILBOX peripheral base address.
|
||||
*
|
||||
* @note Sets mutex state to '1' and allows other resources to get the mutex.
|
||||
*/
|
||||
static inline void MAILBOX_SetMutex(MAILBOX_Type *base)
|
||||
{
|
||||
base->MUTEX = MAILBOX_MUTEX_EX_MASK;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /*_cplusplus*/
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_MAILBOX_H_ */
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_mrt.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Gets the instance from the base address
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
*
|
||||
* @return The MRT instance
|
||||
*/
|
||||
static uint32_t MRT_GetInstance(MRT_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief Pointers to MRT bases for each instance. */
|
||||
static MRT_Type *const s_mrtBases[] = MRT_BASE_PTRS;
|
||||
|
||||
/*! @brief Pointers to MRT clocks for each instance. */
|
||||
static const clock_ip_name_t s_mrtClocks[] = MRT_CLOCKS;
|
||||
|
||||
/*! @brief Pointers to MRT resets for each instance. */
|
||||
static const reset_ip_name_t s_mrtResets[] = MRT_RSTS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static uint32_t MRT_GetInstance(MRT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
uint32_t mrtArrayCount = (sizeof(s_mrtBases) / sizeof(s_mrtBases[0]));
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < mrtArrayCount; instance++)
|
||||
{
|
||||
if (s_mrtBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < mrtArrayCount);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void MRT_Init(MRT_Type *base, const mrt_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
/* Ungate the MRT clock */
|
||||
CLOCK_EnableClock(s_mrtClocks[MRT_GetInstance(base)]);
|
||||
|
||||
/* Reset the module */
|
||||
RESET_PeripheralReset(s_mrtResets[MRT_GetInstance(base)]);
|
||||
|
||||
/* Set timer operating mode */
|
||||
base->MODCFG = MRT_MODCFG_MULTITASK(config->enableMultiTask);
|
||||
}
|
||||
|
||||
void MRT_Deinit(MRT_Type *base)
|
||||
{
|
||||
/* Stop all the timers */
|
||||
MRT_StopTimer(base, kMRT_Channel_0);
|
||||
MRT_StopTimer(base, kMRT_Channel_1);
|
||||
MRT_StopTimer(base, kMRT_Channel_2);
|
||||
MRT_StopTimer(base, kMRT_Channel_3);
|
||||
|
||||
/* Gate the MRT clock*/
|
||||
CLOCK_DisableClock(s_mrtClocks[MRT_GetInstance(base)]);
|
||||
}
|
||||
|
||||
void MRT_UpdateTimerPeriod(MRT_Type *base, mrt_chnl_t channel, uint32_t count, bool immediateLoad)
|
||||
{
|
||||
uint32_t newValue = count;
|
||||
if (((base->CHANNEL[channel].CTRL & MRT_CHANNEL_CTRL_MODE_MASK) == kMRT_OneShotMode) || (immediateLoad))
|
||||
{
|
||||
/* For one-shot interrupt mode, load the new value immediately even if user forgot to enable */
|
||||
newValue |= MRT_CHANNEL_INTVAL_LOAD_MASK;
|
||||
}
|
||||
|
||||
/* Update the timer interval value */
|
||||
base->CHANNEL[channel].INTVAL = newValue;
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_MRT_H_
|
||||
#define _FSL_MRT_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup mrt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
#define FSL_MRT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
|
||||
/*@}*/
|
||||
|
||||
/*! @brief List of MRT channels */
|
||||
typedef enum _mrt_chnl
|
||||
{
|
||||
kMRT_Channel_0 = 0U, /*!< MRT channel number 0*/
|
||||
kMRT_Channel_1, /*!< MRT channel number 1 */
|
||||
kMRT_Channel_2, /*!< MRT channel number 2 */
|
||||
kMRT_Channel_3 /*!< MRT channel number 3 */
|
||||
} mrt_chnl_t;
|
||||
|
||||
/*! @brief List of MRT timer modes */
|
||||
typedef enum _mrt_timer_mode
|
||||
{
|
||||
kMRT_RepeatMode = (0 << MRT_CHANNEL_CTRL_MODE_SHIFT), /*!< Repeat Interrupt mode */
|
||||
kMRT_OneShotMode = (1 << MRT_CHANNEL_CTRL_MODE_SHIFT), /*!< One-shot Interrupt mode */
|
||||
kMRT_OneShotStallMode = (2 << MRT_CHANNEL_CTRL_MODE_SHIFT) /*!< One-shot stall mode */
|
||||
} mrt_timer_mode_t;
|
||||
|
||||
/*! @brief List of MRT interrupts */
|
||||
typedef enum _mrt_interrupt_enable
|
||||
{
|
||||
kMRT_TimerInterruptEnable = MRT_CHANNEL_CTRL_INTEN_MASK /*!< Timer interrupt enable*/
|
||||
} mrt_interrupt_enable_t;
|
||||
|
||||
/*! @brief List of MRT status flags */
|
||||
typedef enum _mrt_status_flags
|
||||
{
|
||||
kMRT_TimerInterruptFlag = MRT_CHANNEL_STAT_INTFLAG_MASK, /*!< Timer interrupt flag */
|
||||
kMRT_TimerRunFlag = MRT_CHANNEL_STAT_RUN_MASK, /*!< Indicates state of the timer */
|
||||
} mrt_status_flags_t;
|
||||
|
||||
/*!
|
||||
* @brief MRT configuration structure
|
||||
*
|
||||
* This structure holds the configuration settings for the MRT peripheral. To initialize this
|
||||
* structure to reasonable defaults, call the MRT_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 _mrt_config
|
||||
{
|
||||
bool enableMultiTask; /*!< true: Timers run in multi-task mode; false: Timers run in hardware status mode */
|
||||
} mrt_config_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Ungates the MRT clock and configures the peripheral for basic operation.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application using the MRT driver.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param config Pointer to user's MRT config structure
|
||||
*/
|
||||
void MRT_Init(MRT_Type *base, const mrt_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Gate the MRT clock
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
*/
|
||||
void MRT_Deinit(MRT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Fill in the MRT config struct with the default settings
|
||||
*
|
||||
* The default values are:
|
||||
* @code
|
||||
* config->enableMultiTask = false;
|
||||
* @endcode
|
||||
* @param config Pointer to user's MRT config structure.
|
||||
*/
|
||||
static inline void MRT_GetDefaultConfig(mrt_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
/* Use hardware status operating mode */
|
||||
config->enableMultiTask = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets up an MRT channel mode.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Channel that is being configured.
|
||||
* @param mode Timer mode to use for the channel.
|
||||
*/
|
||||
static inline void MRT_SetupChannelMode(MRT_Type *base, mrt_chnl_t channel, const mrt_timer_mode_t mode)
|
||||
{
|
||||
uint32_t reg = base->CHANNEL[channel].CTRL;
|
||||
|
||||
/* Clear old value */
|
||||
reg &= ~MRT_CHANNEL_CTRL_MODE_MASK;
|
||||
/* Add the new mode */
|
||||
reg |= mode;
|
||||
|
||||
base->CHANNEL[channel].CTRL = reg;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Interrupt Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables the MRT interrupt.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number
|
||||
* @param mask The interrupts to enable. This is a logical OR of members of the
|
||||
* enumeration ::mrt_interrupt_enable_t
|
||||
*/
|
||||
static inline void MRT_EnableInterrupts(MRT_Type *base, mrt_chnl_t channel, uint32_t mask)
|
||||
{
|
||||
base->CHANNEL[channel].CTRL |= mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables the selected MRT interrupt.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number
|
||||
* @param mask The interrupts to disable. This is a logical OR of members of the
|
||||
* enumeration ::mrt_interrupt_enable_t
|
||||
*/
|
||||
static inline void MRT_DisableInterrupts(MRT_Type *base, mrt_chnl_t channel, uint32_t mask)
|
||||
{
|
||||
base->CHANNEL[channel].CTRL &= ~mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the enabled MRT interrupts.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number
|
||||
*
|
||||
* @return The enabled interrupts. This is the logical OR of members of the
|
||||
* enumeration ::mrt_interrupt_enable_t
|
||||
*/
|
||||
static inline uint32_t MRT_GetEnabledInterrupts(MRT_Type *base, mrt_chnl_t channel)
|
||||
{
|
||||
return (base->CHANNEL[channel].CTRL & MRT_CHANNEL_CTRL_INTEN_MASK);
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Status Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Gets the MRT status flags
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number
|
||||
*
|
||||
* @return The status flags. This is the logical OR of members of the
|
||||
* enumeration ::mrt_status_flags_t
|
||||
*/
|
||||
static inline uint32_t MRT_GetStatusFlags(MRT_Type *base, mrt_chnl_t channel)
|
||||
{
|
||||
return (base->CHANNEL[channel].STAT & (MRT_CHANNEL_STAT_INTFLAG_MASK | MRT_CHANNEL_STAT_RUN_MASK));
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clears the MRT status flags.
|
||||
*
|
||||
* @param base Multi-Rate timer 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 ::mrt_status_flags_t
|
||||
*/
|
||||
static inline void MRT_ClearStatusFlags(MRT_Type *base, mrt_chnl_t channel, uint32_t mask)
|
||||
{
|
||||
base->CHANNEL[channel].STAT = (mask & MRT_CHANNEL_STAT_INTFLAG_MASK);
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Read and Write the timer period
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Used to update the timer period in units of count.
|
||||
*
|
||||
* The new value will be immediately loaded or will be loaded at the end of the current time
|
||||
* interval. For one-shot interrupt mode the new value will be immediately loaded.
|
||||
*
|
||||
* @note User can call the utility macros provided in fsl_common.h to convert to ticks
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number
|
||||
* @param count Timer period in units of ticks
|
||||
* @param immediateLoad true: Load the new value immediately into the TIMER register;
|
||||
* false: Load the new value at the end of current timer interval
|
||||
*/
|
||||
void MRT_UpdateTimerPeriod(MRT_Type *base, mrt_chnl_t channel, uint32_t count, bool immediateLoad);
|
||||
|
||||
/*!
|
||||
* @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 Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number
|
||||
*
|
||||
* @return Current timer counting value in ticks
|
||||
*/
|
||||
static inline uint32_t MRT_GetCurrentTimerCount(MRT_Type *base, mrt_chnl_t channel)
|
||||
{
|
||||
return base->CHANNEL[channel].TIMER;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Timer Start and Stop
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Starts the timer counting.
|
||||
*
|
||||
* After calling this function, timers load period value, counts down to 0 and
|
||||
* depending on the timer mode it will either load the respective start value again or stop.
|
||||
*
|
||||
* @note User can call the utility macros provided in fsl_common.h to convert to ticks
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number.
|
||||
* @param count Timer period in units of ticks
|
||||
*/
|
||||
static inline void MRT_StartTimer(MRT_Type *base, mrt_chnl_t channel, uint32_t count)
|
||||
{
|
||||
/* Write the timer interval value */
|
||||
base->CHANNEL[channel].INTVAL = count;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Stops the timer counting.
|
||||
*
|
||||
* This function stops the timer from counting.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number.
|
||||
*/
|
||||
static inline void MRT_StopTimer(MRT_Type *base, mrt_chnl_t channel)
|
||||
{
|
||||
/* Stop the timer immediately */
|
||||
base->CHANNEL[channel].INTVAL = MRT_CHANNEL_INTVAL_LOAD_MASK;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Get & release channel
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Find the available channel.
|
||||
*
|
||||
* This function returns the lowest available channel number.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
*/
|
||||
static inline uint32_t MRT_GetIdleChannel(MRT_Type *base)
|
||||
{
|
||||
return base->IDLE_CH;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Release the channel when the timer is using the multi-task mode.
|
||||
*
|
||||
* In multi-task mode, the INUSE flags allow more control over when MRT channels are released for
|
||||
* further use. The user can hold on to a channel acquired by calling MRT_GetIdleChannel() for as
|
||||
* long as it is needed and release it by calling this function. This removes the need to ask for
|
||||
* an available channel for every use.
|
||||
*
|
||||
* @param base Multi-Rate timer peripheral base address
|
||||
* @param channel Timer channel number.
|
||||
*/
|
||||
static inline void MRT_ReleaseChannel(MRT_Type *base, mrt_chnl_t channel)
|
||||
{
|
||||
uint32_t reg = base->CHANNEL[channel].STAT;
|
||||
|
||||
/* Clear flag bits to prevent accidentally clearing anything when writing back */
|
||||
reg = ~MRT_CHANNEL_STAT_INTFLAG_MASK;
|
||||
reg |= MRT_CHANNEL_STAT_INUSE_MASK;
|
||||
|
||||
base->CHANNEL[channel].STAT = reg;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_MRT_H_ */
|
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_pint.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Irq number array */
|
||||
static const IRQn_Type s_pintIRQ[FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS] = PINT_IRQS;
|
||||
|
||||
/*! @brief Callback function array for PINT(s). */
|
||||
static pint_cb_t s_pintCallback[FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS];
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void PINT_Init(PINT_Type *base)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t pmcfg;
|
||||
|
||||
assert(base);
|
||||
|
||||
pmcfg = 0;
|
||||
for (i = 0; i < FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS; i++)
|
||||
{
|
||||
s_pintCallback[i] = NULL;
|
||||
}
|
||||
|
||||
/* Disable all bit slices */
|
||||
for (i = 0; i < PINT_PIN_INT_COUNT; i++)
|
||||
{
|
||||
pmcfg = pmcfg | (kPINT_PatternMatchNever << (PININT_BITSLICE_CFG_START + (i * 3U)));
|
||||
}
|
||||
|
||||
/* Enable the peripheral clock */
|
||||
CLOCK_EnableClock(kCLOCK_Pint);
|
||||
|
||||
/* Reset the peripheral */
|
||||
RESET_PeripheralReset(kPINT_RST_SHIFT_RSTn);
|
||||
|
||||
/* Disable all pattern match bit slices */
|
||||
base->PMCFG = pmcfg;
|
||||
}
|
||||
|
||||
void PINT_PinInterruptConfig(PINT_Type *base, pint_pin_int_t intr, pint_pin_enable_t enable, pint_cb_t callback)
|
||||
{
|
||||
assert(base);
|
||||
|
||||
/* Clear Rise and Fall flags first */
|
||||
PINT_PinInterruptClrRiseFlag(base, intr);
|
||||
PINT_PinInterruptClrFallFlag(base, intr);
|
||||
|
||||
/* select level or edge sensitive */
|
||||
base->ISEL = (base->ISEL & ~(1U << intr)) | ((enable & PINT_PIN_INT_LEVEL) ? (1U << intr) : 0U);
|
||||
|
||||
/* enable rising or level interrupt */
|
||||
if (enable & (PINT_PIN_INT_LEVEL | PINT_PIN_INT_RISE))
|
||||
{
|
||||
base->SIENR = 1U << intr;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->CIENR = 1U << intr;
|
||||
}
|
||||
|
||||
/* Enable falling or select high level */
|
||||
if (enable & PINT_PIN_INT_FALL_OR_HIGH_LEVEL)
|
||||
{
|
||||
base->SIENF = 1U << intr;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->CIENF = 1U << intr;
|
||||
}
|
||||
|
||||
s_pintCallback[intr] = callback;
|
||||
}
|
||||
|
||||
void PINT_PinInterruptGetConfig(PINT_Type *base, pint_pin_int_t pintr, pint_pin_enable_t *enable, pint_cb_t *callback)
|
||||
{
|
||||
uint32_t mask;
|
||||
bool level;
|
||||
|
||||
assert(base);
|
||||
|
||||
*enable = kPINT_PinIntEnableNone;
|
||||
level = false;
|
||||
|
||||
mask = 1U << pintr;
|
||||
if (base->ISEL & mask)
|
||||
{
|
||||
/* Pin interrupt is level sensitive */
|
||||
level = true;
|
||||
}
|
||||
|
||||
if (base->IENR & mask)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
/* Level interrupt is enabled */
|
||||
*enable = kPINT_PinIntEnableLowLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rising edge interrupt */
|
||||
*enable = kPINT_PinIntEnableRiseEdge;
|
||||
}
|
||||
}
|
||||
|
||||
if (base->IENF & mask)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
/* Level interrupt is active high */
|
||||
*enable = kPINT_PinIntEnableHighLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Either falling or both edge */
|
||||
if (*enable == kPINT_PinIntEnableRiseEdge)
|
||||
{
|
||||
/* Rising and faling edge */
|
||||
*enable = kPINT_PinIntEnableBothEdges;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Falling edge */
|
||||
*enable = kPINT_PinIntEnableFallEdge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*callback = s_pintCallback[pintr];
|
||||
}
|
||||
|
||||
void PINT_PatternMatchConfig(PINT_Type *base, pint_pmatch_bslice_t bslice, pint_pmatch_cfg_t *cfg)
|
||||
{
|
||||
uint32_t src_shift;
|
||||
uint32_t cfg_shift;
|
||||
uint32_t pmcfg;
|
||||
|
||||
assert(base);
|
||||
|
||||
src_shift = PININT_BITSLICE_SRC_START + (bslice * 3U);
|
||||
cfg_shift = PININT_BITSLICE_CFG_START + (bslice * 3U);
|
||||
|
||||
/* Input source selection for selected bit slice */
|
||||
base->PMSRC = (base->PMSRC & ~(PININT_BITSLICE_SRC_MASK << src_shift)) | (cfg->bs_src << src_shift);
|
||||
|
||||
/* Bit slice configuration */
|
||||
pmcfg = base->PMCFG;
|
||||
pmcfg = (pmcfg & ~(PININT_BITSLICE_CFG_MASK << cfg_shift)) | (cfg->bs_cfg << cfg_shift);
|
||||
|
||||
/* If end point is true, enable the bits */
|
||||
if (bslice != 7U)
|
||||
{
|
||||
if (cfg->end_point)
|
||||
{
|
||||
pmcfg |= (0x1U << bslice);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmcfg &= ~(0x1U << bslice);
|
||||
}
|
||||
}
|
||||
|
||||
base->PMCFG = pmcfg;
|
||||
|
||||
/* Save callback pointer */
|
||||
s_pintCallback[bslice] = cfg->callback;
|
||||
}
|
||||
|
||||
void PINT_PatternMatchGetConfig(PINT_Type *base, pint_pmatch_bslice_t bslice, pint_pmatch_cfg_t *cfg)
|
||||
{
|
||||
uint32_t src_shift;
|
||||
uint32_t cfg_shift;
|
||||
|
||||
assert(base);
|
||||
|
||||
src_shift = PININT_BITSLICE_SRC_START + (bslice * 3U);
|
||||
cfg_shift = PININT_BITSLICE_CFG_START + (bslice * 3U);
|
||||
|
||||
cfg->bs_src = (pint_pmatch_input_src_t)((base->PMSRC & (PININT_BITSLICE_SRC_MASK << src_shift)) >> src_shift);
|
||||
cfg->bs_cfg = (pint_pmatch_bslice_cfg_t)((base->PMCFG & (PININT_BITSLICE_CFG_MASK << cfg_shift)) >> cfg_shift);
|
||||
|
||||
if (bslice == 7U)
|
||||
{
|
||||
cfg->end_point = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg->end_point = (base->PMCFG & (0x1U << bslice)) >> bslice;
|
||||
}
|
||||
cfg->callback = s_pintCallback[bslice];
|
||||
}
|
||||
|
||||
uint32_t PINT_PatternMatchResetDetectLogic(PINT_Type *base)
|
||||
{
|
||||
uint32_t pmctrl;
|
||||
uint32_t pmstatus;
|
||||
uint32_t pmsrc;
|
||||
|
||||
pmctrl = PINT->PMCTRL;
|
||||
pmstatus = pmctrl >> PINT_PMCTRL_PMAT_SHIFT;
|
||||
if (pmstatus)
|
||||
{
|
||||
/* Reset Pattern match engine detection logic */
|
||||
pmsrc = base->PMSRC;
|
||||
base->PMSRC = pmsrc;
|
||||
}
|
||||
return (pmstatus);
|
||||
}
|
||||
|
||||
void PINT_EnableCallback(PINT_Type *base)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
assert(base);
|
||||
|
||||
PINT_PinInterruptClrStatusAll(base);
|
||||
for (i = 0; i < FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS; i++)
|
||||
{
|
||||
NVIC_ClearPendingIRQ(s_pintIRQ[i]);
|
||||
PINT_PinInterruptClrStatus(base, (pint_pin_int_t)i);
|
||||
EnableIRQ(s_pintIRQ[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PINT_DisableCallback(PINT_Type *base)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
assert(base);
|
||||
|
||||
for (i = 0; i < FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS; i++)
|
||||
{
|
||||
DisableIRQ(s_pintIRQ[i]);
|
||||
PINT_PinInterruptClrStatus(base, (pint_pin_int_t)i);
|
||||
NVIC_ClearPendingIRQ(s_pintIRQ[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PINT_Deinit(PINT_Type *base)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
assert(base);
|
||||
|
||||
/* Cleanup */
|
||||
PINT_DisableCallback(base);
|
||||
for (i = 0; i < FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS; i++)
|
||||
{
|
||||
s_pintCallback[i] = NULL;
|
||||
}
|
||||
|
||||
/* Reset the peripheral */
|
||||
RESET_PeripheralReset(kPINT_RST_SHIFT_RSTn);
|
||||
|
||||
/* Disable the peripheral clock */
|
||||
CLOCK_DisableClock(kCLOCK_Pint);
|
||||
}
|
||||
|
||||
/* IRQ handler functions overloading weak symbols in the startup */
|
||||
void PIN_INT0_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt0] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt0](kPINT_PinInt0, pmstatus);
|
||||
}
|
||||
}
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 1U)
|
||||
void PIN_INT1_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt1] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt1](kPINT_PinInt1, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 2U)
|
||||
void PIN_INT2_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt2] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt2](kPINT_PinInt2, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 3U)
|
||||
void PIN_INT3_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt3] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt3](kPINT_PinInt3, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 4U)
|
||||
void PIN_INT4_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt4] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt4](kPINT_PinInt4, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 5U)
|
||||
void PIN_INT5_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt5] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt5](kPINT_PinInt5, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 6U)
|
||||
void PIN_INT6_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt6] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt6](kPINT_PinInt6, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 7U)
|
||||
void PIN_INT7_DriverIRQHandler(void)
|
||||
{
|
||||
uint32_t pmstatus;
|
||||
|
||||
/* Reset pattern match detection */
|
||||
pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
|
||||
/* Call user function */
|
||||
if (s_pintCallback[kPINT_PinInt7] != NULL)
|
||||
{
|
||||
s_pintCallback[kPINT_PinInt7](kPINT_PinInt7, pmstatus);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_PINT_H_
|
||||
#define _FSL_PINT_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup pint_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
#define FSL_PINT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
|
||||
/*@}*/
|
||||
|
||||
/* Number of interrupt line supported by PINT */
|
||||
#define PINT_PIN_INT_COUNT 8U
|
||||
|
||||
/* Number of input sources supported by PINT */
|
||||
#define PINT_INPUT_COUNT 8U
|
||||
|
||||
/* PININT Bit slice source register bits */
|
||||
#define PININT_BITSLICE_SRC_START 8U
|
||||
#define PININT_BITSLICE_SRC_MASK 7U
|
||||
|
||||
/* PININT Bit slice configuration register bits */
|
||||
#define PININT_BITSLICE_CFG_START 8U
|
||||
#define PININT_BITSLICE_CFG_MASK 7U
|
||||
#define PININT_BITSLICE_ENDP_MASK 7U
|
||||
|
||||
#define PINT_PIN_INT_LEVEL 0x10U
|
||||
#define PINT_PIN_INT_EDGE 0x00U
|
||||
#define PINT_PIN_INT_FALL_OR_HIGH_LEVEL 0x02U
|
||||
#define PINT_PIN_INT_RISE 0x01U
|
||||
#define PINT_PIN_RISE_EDGE (PINT_PIN_INT_EDGE | PINT_PIN_INT_RISE)
|
||||
#define PINT_PIN_FALL_EDGE (PINT_PIN_INT_EDGE | PINT_PIN_INT_FALL_OR_HIGH_LEVEL)
|
||||
#define PINT_PIN_BOTH_EDGE (PINT_PIN_INT_EDGE | PINT_PIN_INT_RISE | PINT_PIN_INT_FALL_OR_HIGH_LEVEL)
|
||||
#define PINT_PIN_LOW_LEVEL (PINT_PIN_INT_LEVEL)
|
||||
#define PINT_PIN_HIGH_LEVEL (PINT_PIN_INT_LEVEL | PINT_PIN_INT_FALL_OR_HIGH_LEVEL)
|
||||
|
||||
/*! @brief PINT Pin Interrupt enable type */
|
||||
typedef enum _pint_pin_enable
|
||||
{
|
||||
kPINT_PinIntEnableNone = 0U, /*!< Do not generate Pin Interrupt */
|
||||
kPINT_PinIntEnableRiseEdge = PINT_PIN_RISE_EDGE, /*!< Generate Pin Interrupt on rising edge */
|
||||
kPINT_PinIntEnableFallEdge = PINT_PIN_FALL_EDGE, /*!< Generate Pin Interrupt on falling edge */
|
||||
kPINT_PinIntEnableBothEdges = PINT_PIN_BOTH_EDGE, /*!< Generate Pin Interrupt on both edges */
|
||||
kPINT_PinIntEnableLowLevel = PINT_PIN_LOW_LEVEL, /*!< Generate Pin Interrupt on low level */
|
||||
kPINT_PinIntEnableHighLevel = PINT_PIN_HIGH_LEVEL /*!< Generate Pin Interrupt on high level */
|
||||
} pint_pin_enable_t;
|
||||
|
||||
/*! @brief PINT Pin Interrupt type */
|
||||
typedef enum _pint_int
|
||||
{
|
||||
kPINT_PinInt0 = 0U, /*!< Pin Interrupt 0 */
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 1U)
|
||||
kPINT_PinInt1 = 1U, /*!< Pin Interrupt 1 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 2U)
|
||||
kPINT_PinInt2 = 2U, /*!< Pin Interrupt 2 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 3U)
|
||||
kPINT_PinInt3 = 3U, /*!< Pin Interrupt 3 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 4U)
|
||||
kPINT_PinInt4 = 4U, /*!< Pin Interrupt 4 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 5U)
|
||||
kPINT_PinInt5 = 5U, /*!< Pin Interrupt 5 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 6U)
|
||||
kPINT_PinInt6 = 6U, /*!< Pin Interrupt 6 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 7U)
|
||||
kPINT_PinInt7 = 7U, /*!< Pin Interrupt 7 */
|
||||
#endif
|
||||
} pint_pin_int_t;
|
||||
|
||||
/*! @brief PINT Pattern Match bit slice input source type */
|
||||
typedef enum _pint_pmatch_input_src
|
||||
{
|
||||
kPINT_PatternMatchInp0Src = 0U, /*!< Input source 0 */
|
||||
kPINT_PatternMatchInp1Src = 1U, /*!< Input source 1 */
|
||||
kPINT_PatternMatchInp2Src = 2U, /*!< Input source 2 */
|
||||
kPINT_PatternMatchInp3Src = 3U, /*!< Input source 3 */
|
||||
kPINT_PatternMatchInp4Src = 4U, /*!< Input source 4 */
|
||||
kPINT_PatternMatchInp5Src = 5U, /*!< Input source 5 */
|
||||
kPINT_PatternMatchInp6Src = 6U, /*!< Input source 6 */
|
||||
kPINT_PatternMatchInp7Src = 7U, /*!< Input source 7 */
|
||||
} pint_pmatch_input_src_t;
|
||||
|
||||
/*! @brief PINT Pattern Match bit slice type */
|
||||
typedef enum _pint_pmatch_bslice
|
||||
{
|
||||
kPINT_PatternMatchBSlice0 = 0U, /*!< Bit slice 0 */
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 1U)
|
||||
kPINT_PatternMatchBSlice1 = 1U, /*!< Bit slice 1 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 2U)
|
||||
kPINT_PatternMatchBSlice2 = 2U, /*!< Bit slice 2 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 3U)
|
||||
kPINT_PatternMatchBSlice3 = 3U, /*!< Bit slice 3 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 4U)
|
||||
kPINT_PatternMatchBSlice4 = 4U, /*!< Bit slice 4 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 5U)
|
||||
kPINT_PatternMatchBSlice5 = 5U, /*!< Bit slice 5 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 6U)
|
||||
kPINT_PatternMatchBSlice6 = 6U, /*!< Bit slice 6 */
|
||||
#endif
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 7U)
|
||||
kPINT_PatternMatchBSlice7 = 7U, /*!< Bit slice 7 */
|
||||
#endif
|
||||
} pint_pmatch_bslice_t;
|
||||
|
||||
/*! @brief PINT Pattern Match configuration type */
|
||||
typedef enum _pint_pmatch_bslice_cfg
|
||||
{
|
||||
kPINT_PatternMatchAlways = 0U, /*!< Always Contributes to product term match */
|
||||
kPINT_PatternMatchStickyRise = 1U, /*!< Sticky Rising edge */
|
||||
kPINT_PatternMatchStickyFall = 2U, /*!< Sticky Falling edge */
|
||||
kPINT_PatternMatchStickyBothEdges = 3U, /*!< Sticky Rising or Falling edge */
|
||||
kPINT_PatternMatchHigh = 4U, /*!< High level */
|
||||
kPINT_PatternMatchLow = 5U, /*!< Low level */
|
||||
kPINT_PatternMatchNever = 6U, /*!< Never contributes to product term match */
|
||||
kPINT_PatternMatchBothEdges = 7U, /*!< Either rising or falling edge */
|
||||
} pint_pmatch_bslice_cfg_t;
|
||||
|
||||
/*! @brief PINT Callback function. */
|
||||
typedef void (*pint_cb_t)(pint_pin_int_t pintr, uint32_t pmatch_status);
|
||||
|
||||
typedef struct _pint_pmatch_cfg
|
||||
{
|
||||
pint_pmatch_input_src_t bs_src;
|
||||
pint_pmatch_bslice_cfg_t bs_cfg;
|
||||
bool end_point;
|
||||
pint_cb_t callback;
|
||||
} pint_pmatch_cfg_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Initialize PINT peripheral.
|
||||
|
||||
* This function initializes the PINT peripheral and enables the clock.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_Init(PINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Configure PINT peripheral pin interrupt.
|
||||
|
||||
* This function configures a given pin interrupt.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param intr Pin interrupt.
|
||||
* @param enable Selects detection logic.
|
||||
* @param callback Callback.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_PinInterruptConfig(PINT_Type *base, pint_pin_int_t intr, pint_pin_enable_t enable, pint_cb_t callback);
|
||||
|
||||
/*!
|
||||
* @brief Get PINT peripheral pin interrupt configuration.
|
||||
|
||||
* This function returns the configuration of a given pin interrupt.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
* @param enable Pointer to store the detection logic.
|
||||
* @param callback Callback.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_PinInterruptGetConfig(PINT_Type *base, pint_pin_int_t pintr, pint_pin_enable_t *enable, pint_cb_t *callback);
|
||||
|
||||
/*!
|
||||
* @brief Clear Selected pin interrupt status.
|
||||
|
||||
* This function clears the selected pin interrupt status.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PinInterruptClrStatus(PINT_Type *base, pint_pin_int_t pintr)
|
||||
{
|
||||
base->IST = (1U << pintr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get Selected pin interrupt status.
|
||||
|
||||
* This function returns the selected pin interrupt status.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
*
|
||||
* @retval status = 0 No pin interrupt request. = 1 Selected Pin interrupt request active.
|
||||
*/
|
||||
static inline uint32_t PINT_PinInterruptGetStatus(PINT_Type *base, pint_pin_int_t pintr)
|
||||
{
|
||||
return ((base->IST & (1U << pintr)) ? 1U : 0U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear all pin interrupts status.
|
||||
|
||||
* This function clears the status of all pin interrupts.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PinInterruptClrStatusAll(PINT_Type *base)
|
||||
{
|
||||
base->IST = PINT_IST_PSTAT_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get all pin interrupts status.
|
||||
|
||||
* This function returns the status of all pin interrupts.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval status Each bit position indicates the status of corresponding pin interrupt.
|
||||
* = 0 No pin interrupt request. = 1 Pin interrupt request active.
|
||||
*/
|
||||
static inline uint32_t PINT_PinInterruptGetStatusAll(PINT_Type *base)
|
||||
{
|
||||
return (base->IST);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear Selected pin interrupt fall flag.
|
||||
|
||||
* This function clears the selected pin interrupt fall flag.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PinInterruptClrFallFlag(PINT_Type *base, pint_pin_int_t pintr)
|
||||
{
|
||||
base->FALL = (1U << pintr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get selected pin interrupt fall flag.
|
||||
|
||||
* This function returns the selected pin interrupt fall flag.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
*
|
||||
* @retval flag = 0 Falling edge has not been detected. = 1 Falling edge has been detected.
|
||||
*/
|
||||
static inline uint32_t PINT_PinInterruptGetFallFlag(PINT_Type *base, pint_pin_int_t pintr)
|
||||
{
|
||||
return ((base->FALL & (1U << pintr)) ? 1U : 0U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear all pin interrupt fall flags.
|
||||
|
||||
* This function clears the fall flag for all pin interrupts.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PinInterruptClrFallFlagAll(PINT_Type *base)
|
||||
{
|
||||
base->FALL = PINT_FALL_FDET_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get all pin interrupt fall flags.
|
||||
|
||||
* This function returns the fall flag of all pin interrupts.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval flags Each bit position indicates the falling edge detection of the corresponding pin interrupt.
|
||||
* 0 Falling edge has not been detected. = 1 Falling edge has been detected.
|
||||
*/
|
||||
static inline uint32_t PINT_PinInterruptGetFallFlagAll(PINT_Type *base)
|
||||
{
|
||||
return (base->FALL);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear Selected pin interrupt rise flag.
|
||||
|
||||
* This function clears the selected pin interrupt rise flag.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PinInterruptClrRiseFlag(PINT_Type *base, pint_pin_int_t pintr)
|
||||
{
|
||||
base->RISE = (1U << pintr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get selected pin interrupt rise flag.
|
||||
|
||||
* This function returns the selected pin interrupt rise flag.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param pintr Pin interrupt.
|
||||
*
|
||||
* @retval flag = 0 Rising edge has not been detected. = 1 Rising edge has been detected.
|
||||
*/
|
||||
static inline uint32_t PINT_PinInterruptGetRiseFlag(PINT_Type *base, pint_pin_int_t pintr)
|
||||
{
|
||||
return ((base->RISE & (1U << pintr)) ? 1U : 0U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear all pin interrupt rise flags.
|
||||
|
||||
* This function clears the rise flag for all pin interrupts.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PinInterruptClrRiseFlagAll(PINT_Type *base)
|
||||
{
|
||||
base->RISE = PINT_RISE_RDET_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get all pin interrupt rise flags.
|
||||
|
||||
* This function returns the rise flag of all pin interrupts.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval flags Each bit position indicates the rising edge detection of the corresponding pin interrupt.
|
||||
* 0 Rising edge has not been detected. = 1 Rising edge has been detected.
|
||||
*/
|
||||
static inline uint32_t PINT_PinInterruptGetRiseFlagAll(PINT_Type *base)
|
||||
{
|
||||
return (base->RISE);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Configure PINT pattern match.
|
||||
|
||||
* This function configures a given pattern match bit slice.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param bslice Pattern match bit slice number.
|
||||
* @param cfg Pointer to bit slice configuration.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_PatternMatchConfig(PINT_Type *base, pint_pmatch_bslice_t bslice, pint_pmatch_cfg_t *cfg);
|
||||
|
||||
/*!
|
||||
* @brief Get PINT pattern match configuration.
|
||||
|
||||
* This function returns the configuration of a given pattern match bit slice.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param bslice Pattern match bit slice number.
|
||||
* @param cfg Pointer to bit slice configuration.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_PatternMatchGetConfig(PINT_Type *base, pint_pmatch_bslice_t bslice, pint_pmatch_cfg_t *cfg);
|
||||
|
||||
/*!
|
||||
* @brief Get pattern match bit slice status.
|
||||
|
||||
* This function returns the status of selected bit slice.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
* @param bslice Pattern match bit slice number.
|
||||
*
|
||||
* @retval status = 0 Match has not been detected. = 1 Match has been detected.
|
||||
*/
|
||||
static inline uint32_t PINT_PatternMatchGetStatus(PINT_Type *base, pint_pmatch_bslice_t bslice)
|
||||
{
|
||||
return ((base->PMCTRL >> PINT_PMCTRL_PMAT_SHIFT) & (0x1U << bslice)) >> bslice;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get status of all pattern match bit slices.
|
||||
|
||||
* This function returns the status of all bit slices.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval status Each bit position indicates the match status of corresponding bit slice.
|
||||
* = 0 Match has not been detected. = 1 Match has been detected.
|
||||
*/
|
||||
static inline uint32_t PINT_PatternMatchGetStatusAll(PINT_Type *base)
|
||||
{
|
||||
return base->PMCTRL >> PINT_PMCTRL_PMAT_SHIFT;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reset pattern match detection logic.
|
||||
|
||||
* This function resets the pattern match detection logic if any of the product term is matching.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval pmstatus Each bit position indicates the match status of corresponding bit slice.
|
||||
* = 0 Match was detected. = 1 Match was not detected.
|
||||
*/
|
||||
uint32_t PINT_PatternMatchResetDetectLogic(PINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Enable pattern match function.
|
||||
|
||||
* This function enables the pattern match function.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PatternMatchEnable(PINT_Type *base)
|
||||
{
|
||||
base->PMCTRL = (base->PMCTRL & PINT_PMCTRL_ENA_RXEV_MASK) | PINT_PMCTRL_SEL_PMATCH_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable pattern match function.
|
||||
|
||||
* This function disables the pattern match function.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PatternMatchDisable(PINT_Type *base)
|
||||
{
|
||||
base->PMCTRL = (base->PMCTRL & PINT_PMCTRL_ENA_RXEV_MASK) & ~PINT_PMCTRL_SEL_PMATCH_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable RXEV output.
|
||||
|
||||
* This function enables the pattern match RXEV output.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PatternMatchEnableRXEV(PINT_Type *base)
|
||||
{
|
||||
base->PMCTRL = (base->PMCTRL & PINT_PMCTRL_SEL_PMATCH_MASK) | PINT_PMCTRL_ENA_RXEV_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disable RXEV output.
|
||||
|
||||
* This function disables the pattern match RXEV output.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
static inline void PINT_PatternMatchDisableRXEV(PINT_Type *base)
|
||||
{
|
||||
base->PMCTRL = (base->PMCTRL & PINT_PMCTRL_SEL_PMATCH_MASK) & ~PINT_PMCTRL_ENA_RXEV_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable callback.
|
||||
|
||||
* This function enables the interrupt for the selected PINT peripheral. Although the pin(s) are monitored
|
||||
* as soon as they are enabled, the callback function is not enabled until this function is called.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_EnableCallback(PINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Disable callback.
|
||||
|
||||
* This function disables the interrupt for the selected PINT peripheral. Although the pins are still
|
||||
* being monitored but the callback function is not called.
|
||||
*
|
||||
* @param base Base address of the peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_DisableCallback(PINT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Deinitialize PINT peripheral.
|
||||
|
||||
* This function disables the PINT clock.
|
||||
*
|
||||
* @param base Base address of the PINT peripheral.
|
||||
*
|
||||
* @retval None.
|
||||
*/
|
||||
void PINT_Deinit(PINT_Type *base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* _FSL_PINT_H_ */
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_power.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
/* Empty file since implementation is in header file and power library */
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_POWER_H_
|
||||
#define _FSL_POWER_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*! @addtogroup power */
|
||||
/*! @{ */
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
#define MAKE_PD_BITS(reg, slot) ((reg << 8) | slot)
|
||||
#define PDRCFG0 0x0U
|
||||
#define PDRCFG1 0x1U
|
||||
|
||||
typedef enum pd_bits
|
||||
{
|
||||
kPDRUNCFG_PD_FRO_EN = MAKE_PD_BITS(PDRCFG0, 4U),
|
||||
kPDRUNCFG_PD_FLASH = MAKE_PD_BITS(PDRCFG0, 5U),
|
||||
kPDRUNCFG_PD_TEMPS = MAKE_PD_BITS(PDRCFG0, 6U),
|
||||
kPDRUNCFG_PD_BOD_RESET = MAKE_PD_BITS(PDRCFG0, 7U),
|
||||
kPDRUNCFG_PD_BOD_INTR = MAKE_PD_BITS(PDRCFG0, 8U),
|
||||
kPDRUNCFG_PD_ADC0 = MAKE_PD_BITS(PDRCFG0, 10U),
|
||||
kPDRUNCFG_PD_VDDFLASH = MAKE_PD_BITS(PDRCFG0, 11U),
|
||||
kPDRUNCFG_LP_VDDFLASH = MAKE_PD_BITS(PDRCFG0, 12U),
|
||||
kPDRUNCFG_PD_RAM0 = MAKE_PD_BITS(PDRCFG0, 13U),
|
||||
kPDRUNCFG_PD_RAM1 = MAKE_PD_BITS(PDRCFG0, 14U),
|
||||
kPDRUNCFG_PD_RAM2 = MAKE_PD_BITS(PDRCFG0, 15U),
|
||||
kPDRUNCFG_PD_RAMX = MAKE_PD_BITS(PDRCFG0, 16U),
|
||||
kPDRUNCFG_PD_ROM = MAKE_PD_BITS(PDRCFG0, 17U),
|
||||
kPDRUNCFG_PD_VDDHV_ENA = MAKE_PD_BITS(PDRCFG0, 18U),
|
||||
kPDRUNCFG_PD_VD7_ENA = MAKE_PD_BITS(PDRCFG0, 19U),
|
||||
kPDRUNCFG_PD_WDT_OSC = MAKE_PD_BITS(PDRCFG0, 20U),
|
||||
kPDRUNCFG_PD_USB0_PHY = MAKE_PD_BITS(PDRCFG0, 21U),
|
||||
kPDRUNCFG_PD_SYS_PLL0 = MAKE_PD_BITS(PDRCFG0, 22U),
|
||||
kPDRUNCFG_PD_VREFP_SW = MAKE_PD_BITS(PDRCFG0, 23U),
|
||||
kPDRUNCFG_PD_FLASH_BG = MAKE_PD_BITS(PDRCFG0, 25U),
|
||||
|
||||
kPDRUNCFG_PD_ALT_FLASH_IBG = MAKE_PD_BITS(PDRCFG1, 28U),
|
||||
kPDRUNCFG_SEL_ALT_FLASH_IBG = MAKE_PD_BITS(PDRCFG1, 29U),
|
||||
|
||||
kPDRUNCFG_ForceUnsigned = 0x80000000U
|
||||
} pd_bit_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Power Configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief API to enable PDRUNCFG bit in the Syscon. Note that enabling the bit powers down the peripheral
|
||||
*
|
||||
* @param en peripheral for which to enable the PDRUNCFG bit
|
||||
* @return none
|
||||
*/
|
||||
static inline void POWER_EnablePD(pd_bit_t en)
|
||||
{
|
||||
/* PDRUNCFGSET */
|
||||
SYSCON->PDRUNCFGSET[(en >> 8UL)] = (1UL << (en & 0xffU));
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief API to disable PDRUNCFG bit in the Syscon. Note that disabling the bit powers up the peripheral
|
||||
*
|
||||
* @param en peripheral for which to disable the PDRUNCFG bit
|
||||
* @return none
|
||||
*/
|
||||
static inline void POWER_DisablePD(pd_bit_t en)
|
||||
{
|
||||
/* PDRUNCFGCLR */
|
||||
SYSCON->PDRUNCFGCLR[(en >> 8UL)] = (1UL << (en & 0xffU));
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief API to enable deep sleep bit in the ARM Core.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static inline void POWER_EnableDeepSleep(void)
|
||||
{
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief API to disable deep sleep bit in the ARM Core.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static inline void POWER_DisableDeepSleep(void)
|
||||
{
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief API to power down flash controller.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static inline void POWER_PowerDownFlash(void)
|
||||
{
|
||||
/* note, we retain flash trim to make waking back up faster */
|
||||
SYSCON->PDRUNCFGSET[0] = SYSCON_PDRUNCFG_LP_VDDFLASH_MASK | SYSCON_PDRUNCFG_PD_VDDHV_ENA_MASK | SYSCON_PDRUNCFG_PD_FLASH_BG_MASK;
|
||||
|
||||
/* TURN OFF clock for Flash Controller (only needed for FLASH programming, will be turned on by ROM API) */
|
||||
CLOCK_DisableClock(kCLOCK_Flash);
|
||||
|
||||
/* TURN OFF clock for Flash Accelerator */
|
||||
CLOCK_DisableClock(kCLOCK_Fmc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief API to power up flash controller.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static inline void POWER_PowerUpFlash(void)
|
||||
{
|
||||
SYSCON->PDRUNCFGCLR[0] = SYSCON_PDRUNCFG_LP_VDDFLASH_MASK | SYSCON_PDRUNCFG_PD_VDDHV_ENA_MASK;
|
||||
|
||||
/* TURN ON clock for flash controller */
|
||||
CLOCK_EnableClock(kCLOCK_Fmc);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Power Library API to enter deep sleep mode.
|
||||
*
|
||||
* @param exclude_from_pd Bit mask of the PDRUNCFG bits that needs to be powered on during deep sleep
|
||||
* @return none
|
||||
*/
|
||||
void POWER_EnterDeepSleep(uint32_t exclude_from_pd);
|
||||
|
||||
/*!
|
||||
* @brief Power Library API to enter deep power down mode.
|
||||
*
|
||||
* @param exclude_from_pd Bit mask of the PDRUNCFG bits that needs to be powered on during deep power down mode,
|
||||
* but this is has no effect as the voltages are cut off.
|
||||
* @return none
|
||||
*/
|
||||
void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd);
|
||||
|
||||
/*!
|
||||
* @brief Power Library API to choose normal regulation and set the voltage for the desired operating frequency.
|
||||
*
|
||||
* @param freq - The desired frequency at which the part would like to operate,
|
||||
* note that the voltage and flash wait states should be set before changing frequency
|
||||
* @return none
|
||||
*/
|
||||
void POWER_SetVoltageForFreq(uint32_t freq);
|
||||
|
||||
/*!
|
||||
* @brief Power Library API to choose low power regulation and set the voltage for the desired operating frequency.
|
||||
*
|
||||
* @param freq - The desired frequency at which the part would like to operate,
|
||||
* note only 12MHz and 48Mhz are supported
|
||||
* @return none
|
||||
*/
|
||||
void POWER_SetLowPowerVoltageForFreq(uint32_t freq);
|
||||
|
||||
/*!
|
||||
* @brief Power Library API to return the library version.
|
||||
*
|
||||
* @return version number of the power library
|
||||
*/
|
||||
uint32_t POWER_GetLibVersion(void);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _FSL_POWER_H_ */
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_reset.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
|
||||
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
|
||||
|
||||
void RESET_SetPeripheralReset(reset_ip_name_t peripheral)
|
||||
{
|
||||
const uint32_t regIndex = ((uint32_t)peripheral & 0xFFFF0000u) >> 16;
|
||||
const uint32_t bitPos = ((uint32_t)peripheral & 0x0000FFFFu);
|
||||
const uint32_t bitMask = 1u << bitPos;
|
||||
|
||||
assert(bitPos < 32u);
|
||||
|
||||
/* ASYNC_SYSCON registers have offset 1024 */
|
||||
if (regIndex >= SYSCON_PRESETCTRL_COUNT)
|
||||
{
|
||||
/* reset register is in ASYNC_SYSCON */
|
||||
|
||||
/* set bit */
|
||||
ASYNC_SYSCON->ASYNCPRESETCTRLSET = bitMask;
|
||||
/* wait until it reads 0b1 */
|
||||
while (0u == (ASYNC_SYSCON->ASYNCPRESETCTRL & bitMask))
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reset register is in SYSCON */
|
||||
|
||||
/* set bit */
|
||||
SYSCON->PRESETCTRLSET[regIndex] = bitMask;
|
||||
/* wait until it reads 0b1 */
|
||||
while (0u == (SYSCON->PRESETCTRL[regIndex] & bitMask))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RESET_ClearPeripheralReset(reset_ip_name_t peripheral)
|
||||
{
|
||||
const uint32_t regIndex = ((uint32_t)peripheral & 0xFFFF0000u) >> 16;
|
||||
const uint32_t bitPos = ((uint32_t)peripheral & 0x0000FFFFu);
|
||||
const uint32_t bitMask = 1u << bitPos;
|
||||
|
||||
assert(bitPos < 32u);
|
||||
|
||||
/* ASYNC_SYSCON registers have offset 1024 */
|
||||
if (regIndex >= SYSCON_PRESETCTRL_COUNT)
|
||||
{
|
||||
/* reset register is in ASYNC_SYSCON */
|
||||
|
||||
/* clear bit */
|
||||
ASYNC_SYSCON->ASYNCPRESETCTRLCLR = bitMask;
|
||||
/* wait until it reads 0b0 */
|
||||
while (bitMask == (ASYNC_SYSCON->ASYNCPRESETCTRL & bitMask))
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reset register is in SYSCON */
|
||||
|
||||
/* clear bit */
|
||||
SYSCON->PRESETCTRLCLR[regIndex] = bitMask;
|
||||
/* wait until it reads 0b0 */
|
||||
while (bitMask == (SYSCON->PRESETCTRL[regIndex] & bitMask))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RESET_PeripheralReset(reset_ip_name_t peripheral)
|
||||
{
|
||||
RESET_SetPeripheralReset(peripheral);
|
||||
RESET_ClearPeripheralReset(peripheral);
|
||||
}
|
||||
|
||||
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT || FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT */
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_RESET_H_
|
||||
#define _FSL_RESET_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "fsl_device_registers.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup ksdk_common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Enumeration for peripheral reset control bits
|
||||
*
|
||||
* Defines the enumeration for peripheral reset control bits in PRESETCTRL/ASYNCPRESETCTRL registers
|
||||
*/
|
||||
typedef enum _SYSCON_RSTn
|
||||
{
|
||||
kFLASH_RST_SHIFT_RSTn = 0 | 7U, /**< Flash controller reset control */
|
||||
kFMC_RST_SHIFT_RSTn = 0 | 8U, /**< Flash accelerator reset control */
|
||||
kMUX_RST_SHIFT_RSTn = 0 | 11U, /**< Input mux reset control */
|
||||
kIOCON_RST_SHIFT_RSTn = 0 | 13U, /**< IOCON reset control */
|
||||
kGPIO0_RST_SHIFT_RSTn = 0 | 14U, /**< GPIO0 reset control */
|
||||
kGPIO1_RST_SHIFT_RSTn = 0 | 15U, /**< GPIO1 reset control */
|
||||
kPINT_RST_SHIFT_RSTn = 0 | 18U, /**< Pin interrupt (PINT) reset control */
|
||||
kGINT_RST_SHIFT_RSTn = 0 | 19U, /**< Grouped interrupt (PINT) reset control. */
|
||||
kDMA_RST_SHIFT_RSTn = 0 | 20U, /**< DMA reset control */
|
||||
kCRC_RST_SHIFT_RSTn = 0 | 21U, /**< CRC reset control */
|
||||
kWWDT_RST_SHIFT_RSTn = 0 | 22U, /**< Watchdog timer reset control */
|
||||
kADC0_RST_SHIFT_RSTn = 0 | 27U, /**< ADC0 reset control */
|
||||
kMRT_RST_SHIFT_RSTn = 65536 | 0U, /**< Multi-rate timer (MRT) reset control */
|
||||
kSCT0_RST_SHIFT_RSTn = 65536 | 2U, /**< SCTimer/PWM 0 (SCT0) reset control */
|
||||
kUTICK_RST_SHIFT_RSTn = 65536 | 10U, /**< Micro-tick timer reset control */
|
||||
kFC0_RST_SHIFT_RSTn = 65536 | 11U, /**< Flexcomm Interface 0 reset control */
|
||||
kFC1_RST_SHIFT_RSTn = 65536 | 12U, /**< Flexcomm Interface 1 reset control */
|
||||
kFC2_RST_SHIFT_RSTn = 65536 | 13U, /**< Flexcomm Interface 2 reset control */
|
||||
kFC3_RST_SHIFT_RSTn = 65536 | 14U, /**< Flexcomm Interface 3 reset control */
|
||||
kFC4_RST_SHIFT_RSTn = 65536 | 15U, /**< Flexcomm Interface 4 reset control */
|
||||
kFC5_RST_SHIFT_RSTn = 65536 | 16U, /**< Flexcomm Interface 5 reset control */
|
||||
kFC6_RST_SHIFT_RSTn = 65536 | 17U, /**< Flexcomm Interface 6 reset control */
|
||||
kFC7_RST_SHIFT_RSTn = 65536 | 18U, /**< Flexcomm Interface 7 reset control */
|
||||
kDMIC_RST_SHIFT_RSTn = 65536 | 19U, /**< Digital microphone interface reset control */
|
||||
kCT32B2_RST_SHIFT_RSTn = 65536 | 22U, /**< CT32B2 reset control */
|
||||
kUSB_RST_SHIFT_RSTn = 65536 | 25U, /**< USB reset control */
|
||||
kCT32B0_RST_SHIFT_RSTn = 65536 | 26U, /**< CT32B0 reset control */
|
||||
kCT32B1_RST_SHIFT_RSTn = 65536 | 27U, /**< CT32B1 reset control */
|
||||
kCT32B3_RST_SHIFT_RSTn = 67108864 | 13U, /**< CT32B3 reset control */
|
||||
kCT32B4_RST_SHIFT_RSTn = 67108864 | 14U, /**< CT32B4 reset control */
|
||||
} SYSCON_RSTn_t;
|
||||
|
||||
/** Array initializers with peripheral reset bits **/
|
||||
#define ADC_RSTS \
|
||||
{ \
|
||||
kADC0_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for ADC peripheral */
|
||||
#define CRC_RSTS \
|
||||
{ \
|
||||
kCRC_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for CRC peripheral */
|
||||
#define DMA_RSTS \
|
||||
{ \
|
||||
kDMA_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for DMA peripheral */
|
||||
#define DMIC_RSTS \
|
||||
{ \
|
||||
kDMIC_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for ADC peripheral */
|
||||
#define FLEXCOMM_RSTS \
|
||||
{ \
|
||||
kFC0_RST_SHIFT_RSTn, kFC1_RST_SHIFT_RSTn, kFC2_RST_SHIFT_RSTn, kFC3_RST_SHIFT_RSTn, kFC4_RST_SHIFT_RSTn, \
|
||||
kFC5_RST_SHIFT_RSTn, kFC6_RST_SHIFT_RSTn, kFC7_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for FLEXCOMM peripheral */
|
||||
#define GINT_RSTS \
|
||||
{ \
|
||||
kGINT_RST_SHIFT_RSTn, kGINT_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for GINT peripheral. GINT0 & GINT1 share same slot */
|
||||
#define GPIO_RSTS \
|
||||
{ \
|
||||
kGPIO0_RST_SHIFT_RSTn, kGPIO1_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for GPIO peripheral */
|
||||
#define INPUTMUX_RSTS \
|
||||
{ \
|
||||
kMUX_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for INPUTMUX peripheral */
|
||||
#define IOCON_RSTS \
|
||||
{ \
|
||||
kIOCON_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for IOCON peripheral */
|
||||
#define FLASH_RSTS \
|
||||
{ \
|
||||
kFLASH_RST_SHIFT_RSTn, kFMC_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for Flash peripheral */
|
||||
#define MRT_RSTS \
|
||||
{ \
|
||||
kMRT_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for MRT peripheral */
|
||||
#define PINT_RSTS \
|
||||
{ \
|
||||
kPINT_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for PINT peripheral */
|
||||
#define SCT_RSTS \
|
||||
{ \
|
||||
kSCT0_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for SCT peripheral */
|
||||
#define CTIMER_RSTS \
|
||||
{ \
|
||||
kCT32B0_RST_SHIFT_RSTn, kCT32B1_RST_SHIFT_RSTn, kCT32B2_RST_SHIFT_RSTn, kCT32B3_RST_SHIFT_RSTn, \
|
||||
kCT32B4_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for TIMER peripheral */
|
||||
#define USB_RSTS \
|
||||
{ \
|
||||
kUSB_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for USB peripheral */
|
||||
#define UTICK_RSTS \
|
||||
{ \
|
||||
kUTICK_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for UTICK peripheral */
|
||||
#define WWDT_RSTS \
|
||||
{ \
|
||||
kWWDT_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for WWDT peripheral */
|
||||
|
||||
typedef SYSCON_RSTn_t reset_ip_name_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Assert reset to peripheral.
|
||||
*
|
||||
* Asserts reset signal to specified peripheral module.
|
||||
*
|
||||
* @param peripheral Assert reset to this peripheral. The enum argument contains encoding of reset register
|
||||
* and reset bit position in the reset register.
|
||||
*/
|
||||
void RESET_SetPeripheralReset(reset_ip_name_t peripheral);
|
||||
|
||||
/*!
|
||||
* @brief Clear reset to peripheral.
|
||||
*
|
||||
* Clears reset signal to specified peripheral module, allows it to operate.
|
||||
*
|
||||
* @param peripheral Clear reset to this peripheral. The enum argument contains encoding of reset register
|
||||
* and reset bit position in the reset register.
|
||||
*/
|
||||
void RESET_ClearPeripheralReset(reset_ip_name_t peripheral);
|
||||
|
||||
/*!
|
||||
* @brief Reset peripheral module.
|
||||
*
|
||||
* Reset peripheral module.
|
||||
*
|
||||
* @param peripheral Peripheral to reset. The enum argument contains encoding of reset register
|
||||
* and reset bit position in the reset register.
|
||||
*/
|
||||
void RESET_PeripheralReset(reset_ip_name_t peripheral);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _FSL_RESET_H_ */
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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)
|
||||
{
|
||||
assert(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) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0))
|
||||
{
|
||||
daysPerMonth[2] = 29U;
|
||||
}
|
||||
|
||||
/* Check the validity of the day */
|
||||
if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime)
|
||||
{
|
||||
assert(datetime);
|
||||
|
||||
/* Number of days from begin of the non Leap-year*/
|
||||
/* 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)
|
||||
{
|
||||
assert(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)
|
||||
{
|
||||
/* Enable the RTC peripheral clock */
|
||||
CLOCK_EnableClock(kCLOCK_Rtc);
|
||||
|
||||
/* Make sure the reset bit is cleared */
|
||||
base->CTRL &= ~RTC_CTRL_SWRESET_MASK;
|
||||
|
||||
/* Make sure the RTC OSC is powered up */
|
||||
base->CTRL &= ~RTC_CTRL_RTC_OSC_PD_MASK;
|
||||
}
|
||||
|
||||
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->COUNT = RTC_ConvertDatetimeToSeconds(datetime);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime)
|
||||
{
|
||||
assert(datetime);
|
||||
|
||||
uint32_t seconds = 0;
|
||||
|
||||
seconds = base->COUNT;
|
||||
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->COUNT;
|
||||
|
||||
/* Return error if the alarm time has passed */
|
||||
if (alarmSeconds < currSeconds)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* Set alarm in seconds*/
|
||||
base->MATCH = 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->MATCH;
|
||||
|
||||
RTC_ConvertSecondsToDatetime(alarmSeconds, datetime);
|
||||
}
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_RTC_H_
|
||||
#define _FSL_RTC_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup rtc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @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_AlarmInterruptEnable = RTC_CTRL_ALARMDPD_EN_MASK, /*!< Alarm interrupt.*/
|
||||
kRTC_WakeupInterruptEnable = RTC_CTRL_WAKEDPD_EN_MASK /*!< Wake-up interrupt.*/
|
||||
} rtc_interrupt_enable_t;
|
||||
|
||||
/*! @brief List of RTC flags */
|
||||
typedef enum _rtc_status_flags
|
||||
{
|
||||
kRTC_AlarmFlag = RTC_CTRL_ALARM1HZ_MASK, /*!< Alarm flag*/
|
||||
kRTC_WakeupFlag = RTC_CTRL_WAKE1KHZ_MASK /*!< 1kHz wake-up timer flag*/
|
||||
} rtc_status_flags_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;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Ungates the RTC clock and enables the RTC oscillator.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application using the RTC driver.
|
||||
*
|
||||
* @param base RTC peripheral base address
|
||||
*/
|
||||
void RTC_Init(RTC_Type *base);
|
||||
|
||||
/*!
|
||||
* @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->CTRL &= ~RTC_CTRL_RTC_EN_MASK;
|
||||
|
||||
/* Gate the module clock */
|
||||
CLOCK_DisableClock(kCLOCK_Rtc);
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @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);
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @brief Enable the RTC high resolution timer and set the wake-up time.
|
||||
*
|
||||
* @param base RTC peripheral base address
|
||||
* @param wakeupValue The value to be loaded into the RTC WAKE register
|
||||
*/
|
||||
static inline void RTC_SetWakeupCount(RTC_Type *base, uint16_t wakeupValue)
|
||||
{
|
||||
/* Enable the 1kHz RTC timer */
|
||||
base->CTRL |= RTC_CTRL_RTC1KHZ_EN_MASK;
|
||||
|
||||
/* Set the start count value into the wake-up timer */
|
||||
base->WAKE = wakeupValue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read actual RTC counter value.
|
||||
*
|
||||
* @param base RTC peripheral base address
|
||||
*/
|
||||
static inline uint16_t RTC_GetWakeupCount(RTC_Type *base)
|
||||
{
|
||||
/* Read wake-up counter */
|
||||
return RTC_WAKE_VAL(base->WAKE);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @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)
|
||||
{
|
||||
uint32_t reg = base->CTRL;
|
||||
|
||||
/* Clear flag bits to prevent accidentally clearing anything when writing back */
|
||||
reg &= ~(RTC_CTRL_ALARM1HZ_MASK | RTC_CTRL_WAKE1KHZ_MASK);
|
||||
reg |= mask;
|
||||
|
||||
base->CTRL = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @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)
|
||||
{
|
||||
uint32_t reg = base->CTRL;
|
||||
|
||||
/* Clear flag bits to prevent accidentally clearing anything when writing back */
|
||||
reg &= ~(RTC_CTRL_ALARM1HZ_MASK | RTC_CTRL_WAKE1KHZ_MASK | mask);
|
||||
|
||||
base->CTRL = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @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->CTRL & (RTC_CTRL_ALARMDPD_EN_MASK | RTC_CTRL_WAKEDPD_EN_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->CTRL & (RTC_CTRL_ALARM1HZ_MASK | RTC_CTRL_WAKE1KHZ_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
|
||||
*/
|
||||
static inline void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask)
|
||||
{
|
||||
uint32_t reg = base->CTRL;
|
||||
|
||||
/* Clear flag bits to prevent accidentally clearing anything when writing back */
|
||||
reg &= ~(RTC_CTRL_ALARM1HZ_MASK | RTC_CTRL_WAKE1KHZ_MASK);
|
||||
|
||||
/* Write 1 to the flags we wish to clear */
|
||||
reg |= mask;
|
||||
|
||||
base->CTRL = reg;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @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->CTRL |= RTC_CTRL_RTC_EN_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->CTRL &= ~RTC_CTRL_RTC_EN_MASK;
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @brief Performs a software reset on the RTC module.
|
||||
*
|
||||
* This resets all RTC registers to their reset value. The bit is cleared by software explicitly clearing it.
|
||||
*
|
||||
* @param base RTC peripheral base address
|
||||
*/
|
||||
static inline void RTC_Reset(RTC_Type *base)
|
||||
{
|
||||
base->CTRL |= RTC_CTRL_SWRESET_MASK;
|
||||
base->CTRL &= ~RTC_CTRL_SWRESET_MASK;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_RTC_H_ */
|
|
@ -0,0 +1,529 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_sctimer.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
/*! @brief Typedef for interrupt handler. */
|
||||
typedef void (*sctimer_isr_t)(SCT_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Gets the instance from the base address
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
*
|
||||
* @return The SCTimer instance
|
||||
*/
|
||||
static uint32_t SCTIMER_GetInstance(SCT_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief Pointers to SCT bases for each instance. */
|
||||
static SCT_Type *const s_sctBases[] = SCT_BASE_PTRS;
|
||||
|
||||
/*! @brief Pointers to SCT clocks for each instance. */
|
||||
static const clock_ip_name_t s_sctClocks[] = SCT_CLOCKS;
|
||||
|
||||
/*! @brief Pointers to SCT resets for each instance. */
|
||||
static const reset_ip_name_t s_sctResets[] = SCT_RSTS;
|
||||
|
||||
/*!< @brief SCTimer event Callback function. */
|
||||
static sctimer_event_callback_t s_eventCallback[FSL_FEATURE_SCT_NUMBER_OF_EVENTS];
|
||||
|
||||
/*!< @brief Keep track of SCTimer event number */
|
||||
static uint32_t s_currentEvent;
|
||||
|
||||
/*!< @brief Keep track of SCTimer state number */
|
||||
static uint32_t s_currentState;
|
||||
|
||||
/*!< @brief Keep track of SCTimer match/capture register number */
|
||||
static uint32_t s_currentMatch;
|
||||
|
||||
/*! @brief Pointer to SCTimer IRQ handler */
|
||||
static sctimer_isr_t s_sctimerIsr;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static uint32_t SCTIMER_GetInstance(SCT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
uint32_t sctArrayCount = (sizeof(s_sctBases) / sizeof(s_sctBases[0]));
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < sctArrayCount; instance++)
|
||||
{
|
||||
if (s_sctBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < sctArrayCount);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
status_t SCTIMER_Init(SCT_Type *base, const sctimer_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
uint32_t i;
|
||||
|
||||
/* Enable the SCTimer clock*/
|
||||
CLOCK_EnableClock(s_sctClocks[SCTIMER_GetInstance(base)]);
|
||||
|
||||
/* Reset the module */
|
||||
RESET_PeripheralReset(s_sctResets[SCTIMER_GetInstance(base)]);
|
||||
|
||||
/* Setup the counter operation */
|
||||
base->CONFIG = SCT_CONFIG_CKSEL(config->clockSelect) | SCT_CONFIG_CLKMODE(config->clockMode) |
|
||||
SCT_CONFIG_UNIFY(config->enableCounterUnify);
|
||||
|
||||
/* Write to the control register, clear the counter and keep the counters halted */
|
||||
base->CTRL = SCT_CTRL_BIDIR_L(config->enableBidirection_l) | SCT_CTRL_PRE_L(config->prescale_l) |
|
||||
SCT_CTRL_CLRCTR_L_MASK | SCT_CTRL_HALT_L_MASK;
|
||||
|
||||
if (!(config->enableCounterUnify))
|
||||
{
|
||||
base->CTRL |= SCT_CTRL_BIDIR_H(config->enableBidirection_h) | SCT_CTRL_PRE_H(config->prescale_h) |
|
||||
SCT_CTRL_CLRCTR_H_MASK | SCT_CTRL_HALT_H_MASK;
|
||||
}
|
||||
|
||||
/* Initial state of channel output */
|
||||
base->OUTPUT = config->outInitState;
|
||||
|
||||
/* Clear the global variables */
|
||||
s_currentEvent = 0;
|
||||
s_currentState = 0;
|
||||
s_currentMatch = 0;
|
||||
|
||||
/* Clear the callback array */
|
||||
for (i = 0; i < FSL_FEATURE_SCT_NUMBER_OF_EVENTS; i++)
|
||||
{
|
||||
s_eventCallback[i] = NULL;
|
||||
}
|
||||
|
||||
/* Save interrupt handler */
|
||||
s_sctimerIsr = SCTIMER_EventHandleIRQ;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SCTIMER_Deinit(SCT_Type *base)
|
||||
{
|
||||
/* Halt the counters */
|
||||
base->CTRL |= (SCT_CTRL_HALT_L_MASK | SCT_CTRL_HALT_H_MASK);
|
||||
|
||||
/* Disable the SCTimer clock*/
|
||||
CLOCK_DisableClock(s_sctClocks[SCTIMER_GetInstance(base)]);
|
||||
}
|
||||
|
||||
void SCTIMER_GetDefaultConfig(sctimer_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
/* SCT operates as a unified 32-bit counter */
|
||||
config->enableCounterUnify = true;
|
||||
/* System clock clocks the entire SCT module */
|
||||
config->clockMode = kSCTIMER_System_ClockMode;
|
||||
/* This is used only by certain clock modes */
|
||||
config->clockSelect = kSCTIMER_Clock_On_Rise_Input_0;
|
||||
/* Up count mode only for the unified counter */
|
||||
config->enableBidirection_l = false;
|
||||
/* Up count mode only for Counte_H */
|
||||
config->enableBidirection_h = false;
|
||||
/* Prescale factor of 1 */
|
||||
config->prescale_l = 0;
|
||||
/* Prescale factor of 1 for Counter_H*/
|
||||
config->prescale_h = 0;
|
||||
/* Clear outputs */
|
||||
config->outInitState = 0;
|
||||
}
|
||||
|
||||
status_t SCTIMER_SetupPwm(SCT_Type *base,
|
||||
const sctimer_pwm_signal_param_t *pwmParams,
|
||||
sctimer_pwm_mode_t mode,
|
||||
uint32_t pwmFreq_Hz,
|
||||
uint32_t srcClock_Hz,
|
||||
uint32_t *event)
|
||||
{
|
||||
assert(pwmParams);
|
||||
assert(srcClock_Hz);
|
||||
assert(pwmFreq_Hz);
|
||||
|
||||
uint32_t period, pulsePeriod = 0;
|
||||
uint32_t sctClock = srcClock_Hz / (((base->CTRL & SCT_CTRL_PRE_L_MASK) >> SCT_CTRL_PRE_L_SHIFT) + 1);
|
||||
uint32_t periodEvent, pulseEvent;
|
||||
uint32_t reg;
|
||||
|
||||
/* This function will create 2 events, return an error if we do not have enough events available */
|
||||
if ((s_currentEvent + 2) > FSL_FEATURE_SCT_NUMBER_OF_EVENTS)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
if (pwmParams->dutyCyclePercent == 0)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* Set unify bit to operate in 32-bit counter mode */
|
||||
base->CONFIG |= SCT_CONFIG_UNIFY_MASK;
|
||||
|
||||
/* Use bi-directional mode for center-aligned PWM */
|
||||
if (mode == kSCTIMER_CenterAlignedPwm)
|
||||
{
|
||||
base->CTRL |= SCT_CTRL_BIDIR_L_MASK;
|
||||
}
|
||||
|
||||
/* Calculate PWM period match value */
|
||||
if (mode == kSCTIMER_EdgeAlignedPwm)
|
||||
{
|
||||
period = (sctClock / pwmFreq_Hz) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
period = sctClock / (pwmFreq_Hz * 2);
|
||||
}
|
||||
|
||||
/* Calculate pulse width match value */
|
||||
pulsePeriod = (period * pwmParams->dutyCyclePercent) / 100;
|
||||
|
||||
/* For 100% dutycyle, make pulse period greater than period so the event will never occur */
|
||||
if (pwmParams->dutyCyclePercent >= 100)
|
||||
{
|
||||
pulsePeriod = period + 2;
|
||||
}
|
||||
|
||||
/* Schedule an event when we reach the PWM period */
|
||||
SCTIMER_CreateAndScheduleEvent(base, kSCTIMER_MatchEventOnly, period, 0, kSCTIMER_Counter_L, &periodEvent);
|
||||
|
||||
/* Schedule an event when we reach the pulse width */
|
||||
SCTIMER_CreateAndScheduleEvent(base, kSCTIMER_MatchEventOnly, pulsePeriod, 0, kSCTIMER_Counter_L, &pulseEvent);
|
||||
|
||||
/* Reset the counter when we reach the PWM period */
|
||||
SCTIMER_SetupCounterLimitAction(base, kSCTIMER_Counter_L, periodEvent);
|
||||
|
||||
/* Return the period event to the user */
|
||||
*event = periodEvent;
|
||||
|
||||
/* For high-true level */
|
||||
if (pwmParams->level == kSCTIMER_HighTrue)
|
||||
{
|
||||
/* Set the initial output level to low which is the inactive state */
|
||||
base->OUTPUT &= ~(1U << pwmParams->output);
|
||||
|
||||
if (mode == kSCTIMER_EdgeAlignedPwm)
|
||||
{
|
||||
/* Set the output when we reach the PWM period */
|
||||
SCTIMER_SetupOutputSetAction(base, pwmParams->output, periodEvent);
|
||||
/* Clear the output when we reach the PWM pulse value */
|
||||
SCTIMER_SetupOutputClearAction(base, pwmParams->output, pulseEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the output when we reach the PWM pulse event */
|
||||
SCTIMER_SetupOutputClearAction(base, pwmParams->output, pulseEvent);
|
||||
/* Reverse output when down counting */
|
||||
reg = base->OUTPUTDIRCTRL;
|
||||
reg &= ~(SCT_OUTPUTDIRCTRL_SETCLR0_MASK << (2 * pwmParams->output));
|
||||
reg |= (1U << (2 * pwmParams->output));
|
||||
base->OUTPUTDIRCTRL = reg;
|
||||
}
|
||||
}
|
||||
/* For low-true level */
|
||||
else
|
||||
{
|
||||
/* Set the initial output level to high which is the inactive state */
|
||||
base->OUTPUT |= (1U << pwmParams->output);
|
||||
|
||||
if (mode == kSCTIMER_EdgeAlignedPwm)
|
||||
{
|
||||
/* Clear the output when we reach the PWM period */
|
||||
SCTIMER_SetupOutputClearAction(base, pwmParams->output, periodEvent);
|
||||
/* Set the output when we reach the PWM pulse value */
|
||||
SCTIMER_SetupOutputSetAction(base, pwmParams->output, pulseEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the output when we reach the PWM pulse event */
|
||||
SCTIMER_SetupOutputSetAction(base, pwmParams->output, pulseEvent);
|
||||
/* Reverse output when down counting */
|
||||
reg = base->OUTPUTDIRCTRL;
|
||||
reg &= ~(SCT_OUTPUTDIRCTRL_SETCLR0_MASK << (2 * pwmParams->output));
|
||||
reg |= (1U << (2 * pwmParams->output));
|
||||
base->OUTPUTDIRCTRL = reg;
|
||||
}
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SCTIMER_UpdatePwmDutycycle(SCT_Type *base, sctimer_out_t output, uint8_t dutyCyclePercent, uint32_t event)
|
||||
|
||||
{
|
||||
assert(dutyCyclePercent > 0);
|
||||
|
||||
uint32_t periodMatchReg, pulseMatchReg;
|
||||
uint32_t pulsePeriod = 0, period;
|
||||
|
||||
/* Retrieve the match register number for the PWM period */
|
||||
periodMatchReg = base->EVENT[event].CTRL & SCT_EVENT_CTRL_MATCHSEL_MASK;
|
||||
|
||||
/* Retrieve the match register number for the PWM pulse period */
|
||||
pulseMatchReg = base->EVENT[event + 1].CTRL & SCT_EVENT_CTRL_MATCHSEL_MASK;
|
||||
|
||||
period = base->SCTMATCH[periodMatchReg];
|
||||
|
||||
/* Calculate pulse width match value */
|
||||
pulsePeriod = (period * dutyCyclePercent) / 100;
|
||||
|
||||
/* For 100% dutycyle, make pulse period greater than period so the event will never occur */
|
||||
if (dutyCyclePercent >= 100)
|
||||
{
|
||||
pulsePeriod = period + 2;
|
||||
}
|
||||
|
||||
/* Stop the counter before updating match register */
|
||||
SCTIMER_StopTimer(base, kSCTIMER_Counter_L);
|
||||
|
||||
/* Update dutycycle */
|
||||
base->SCTMATCH[pulseMatchReg] = SCT_SCTMATCH_MATCHn_L(pulsePeriod);
|
||||
base->SCTMATCHREL[pulseMatchReg] = SCT_SCTMATCHREL_RELOADn_L(pulsePeriod);
|
||||
|
||||
/* Restart the counter */
|
||||
SCTIMER_StartTimer(base, kSCTIMER_Counter_L);
|
||||
}
|
||||
|
||||
status_t SCTIMER_CreateAndScheduleEvent(SCT_Type *base,
|
||||
sctimer_event_t howToMonitor,
|
||||
uint32_t matchValue,
|
||||
uint32_t whichIO,
|
||||
sctimer_counter_t whichCounter,
|
||||
uint32_t *event)
|
||||
{
|
||||
uint32_t combMode = (((uint32_t)howToMonitor & SCT_EVENT_CTRL_COMBMODE_MASK) >> SCT_EVENT_CTRL_COMBMODE_SHIFT);
|
||||
uint32_t currentCtrlVal = howToMonitor;
|
||||
|
||||
/* Return an error if we have hit the limit in terms of number of events created */
|
||||
if (s_currentEvent >= FSL_FEATURE_SCT_NUMBER_OF_EVENTS)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* IO only mode */
|
||||
if (combMode == 0x2U)
|
||||
{
|
||||
base->EVENT[s_currentEvent].CTRL = currentCtrlVal | SCT_EVENT_CTRL_IOSEL(whichIO);
|
||||
}
|
||||
/* Match mode only */
|
||||
else if (combMode == 0x1U)
|
||||
{
|
||||
/* Return an error if we have hit the limit in terms of number of number of match registers */
|
||||
if (s_currentMatch >= FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
currentCtrlVal |= SCT_EVENT_CTRL_MATCHSEL(s_currentMatch);
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_L(matchValue);
|
||||
base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_L(matchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Select the counter, no need for this if operating in 32-bit mode */
|
||||
currentCtrlVal |= SCT_EVENT_CTRL_HEVENT(whichCounter);
|
||||
base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_H(matchValue);
|
||||
base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_H(matchValue);
|
||||
}
|
||||
base->EVENT[s_currentEvent].CTRL = currentCtrlVal;
|
||||
/* Increment the match register number */
|
||||
s_currentMatch++;
|
||||
}
|
||||
/* Use both Match & IO */
|
||||
else
|
||||
{
|
||||
/* Return an error if we have hit the limit in terms of number of number of match registers */
|
||||
if (s_currentMatch >= FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
currentCtrlVal |= SCT_EVENT_CTRL_MATCHSEL(s_currentMatch) | SCT_EVENT_CTRL_IOSEL(whichIO);
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_L(matchValue);
|
||||
base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_L(matchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Select the counter, no need for this if operating in 32-bit mode */
|
||||
currentCtrlVal |= SCT_EVENT_CTRL_HEVENT(whichCounter);
|
||||
base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_H(matchValue);
|
||||
base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_H(matchValue);
|
||||
}
|
||||
base->EVENT[s_currentEvent].CTRL = currentCtrlVal;
|
||||
/* Increment the match register number */
|
||||
s_currentMatch++;
|
||||
}
|
||||
|
||||
/* Enable the event in the current state */
|
||||
base->EVENT[s_currentEvent].STATE = (1U << s_currentState);
|
||||
|
||||
/* Return the event number */
|
||||
*event = s_currentEvent;
|
||||
|
||||
/* Increment the event number */
|
||||
s_currentEvent++;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SCTIMER_ScheduleEvent(SCT_Type *base, uint32_t event)
|
||||
{
|
||||
/* Enable event in the current state */
|
||||
base->EVENT[event].STATE |= (1U << s_currentState);
|
||||
}
|
||||
|
||||
status_t SCTIMER_IncreaseState(SCT_Type *base)
|
||||
{
|
||||
/* Return an error if we have hit the limit in terms of states used */
|
||||
if (s_currentState >= FSL_FEATURE_SCT_NUMBER_OF_STATES)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
s_currentState++;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
uint32_t SCTIMER_GetCurrentState(SCT_Type *base)
|
||||
{
|
||||
return s_currentState;
|
||||
}
|
||||
|
||||
void SCTIMER_SetupOutputToggleAction(SCT_Type *base, uint32_t whichIO, uint32_t event)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Set the same event to set and clear the output */
|
||||
base->OUT[whichIO].CLR |= (1U << event);
|
||||
base->OUT[whichIO].SET |= (1U << event);
|
||||
|
||||
/* Set the conflict resolution to toggle output */
|
||||
reg = base->RES;
|
||||
reg &= ~(SCT_RES_O0RES_MASK << (2 * whichIO));
|
||||
reg |= (uint32_t)(kSCTIMER_ResolveToggle << (2 * whichIO));
|
||||
base->RES = reg;
|
||||
}
|
||||
|
||||
status_t SCTIMER_SetupCaptureAction(SCT_Type *base,
|
||||
sctimer_counter_t whichCounter,
|
||||
uint32_t *captureRegister,
|
||||
uint32_t event)
|
||||
{
|
||||
/* Return an error if we have hit the limit in terms of number of capture/match registers used */
|
||||
if (s_currentMatch >= FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
/* Set the bit to enable event */
|
||||
base->SCTCAPCTRL[s_currentMatch] |= SCT_SCTCAPCTRL_CAPCONn_L(1 << event);
|
||||
|
||||
/* Set this resource to be a capture rather than match */
|
||||
base->REGMODE |= SCT_REGMODE_REGMOD_L(1 << s_currentMatch);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set bit to enable event */
|
||||
base->SCTCAPCTRL[s_currentMatch] |= SCT_SCTCAPCTRL_CAPCONn_H(1 << event);
|
||||
|
||||
/* Set this resource to be a capture rather than match */
|
||||
base->REGMODE |= SCT_REGMODE_REGMOD_H(1 << s_currentMatch);
|
||||
}
|
||||
|
||||
/* Return the match register number */
|
||||
*captureRegister = s_currentMatch;
|
||||
|
||||
/* Increase the match register number */
|
||||
s_currentMatch++;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SCTIMER_SetCallback(SCT_Type *base, sctimer_event_callback_t callback, uint32_t event)
|
||||
{
|
||||
s_eventCallback[event] = callback;
|
||||
}
|
||||
|
||||
void SCTIMER_EventHandleIRQ(SCT_Type *base)
|
||||
{
|
||||
uint32_t eventFlag = SCT0->EVFLAG;
|
||||
/* Only clear the flags whose interrupt field is enabled */
|
||||
uint32_t clearFlag = (eventFlag & SCT0->EVEN);
|
||||
uint32_t mask = eventFlag;
|
||||
int i = 0;
|
||||
|
||||
/* Invoke the callback for certain events */
|
||||
for (i = 0; (i < FSL_FEATURE_SCT_NUMBER_OF_EVENTS) && (mask != 0); i++)
|
||||
{
|
||||
if (mask & 0x1)
|
||||
{
|
||||
if (s_eventCallback[i] != NULL)
|
||||
{
|
||||
s_eventCallback[i]();
|
||||
}
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
/* Clear event interrupt flag */
|
||||
SCT0->EVFLAG = clearFlag;
|
||||
}
|
||||
|
||||
void SCT0_IRQHandler(void)
|
||||
{
|
||||
s_sctimerIsr(SCT0);
|
||||
}
|
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_SCTIMER_H_
|
||||
#define _FSL_SCTIMER_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup sctimer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
#define FSL_SCTIMER_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
|
||||
/*@}*/
|
||||
|
||||
/*! @brief SCTimer PWM operation modes */
|
||||
typedef enum _sctimer_pwm_mode
|
||||
{
|
||||
kSCTIMER_EdgeAlignedPwm = 0U, /*!< Edge-aligned PWM */
|
||||
kSCTIMER_CenterAlignedPwm /*!< Center-aligned PWM */
|
||||
} sctimer_pwm_mode_t;
|
||||
|
||||
/*! @brief SCTimer counters when working as two independent 16-bit counters */
|
||||
typedef enum _sctimer_counter
|
||||
{
|
||||
kSCTIMER_Counter_L = 0U, /*!< Counter L */
|
||||
kSCTIMER_Counter_H /*!< Counter H */
|
||||
} sctimer_counter_t;
|
||||
|
||||
/*! @brief List of SCTimer input pins */
|
||||
typedef enum _sctimer_input
|
||||
{
|
||||
kSCTIMER_Input_0 = 0U, /*!< SCTIMER input 0 */
|
||||
kSCTIMER_Input_1, /*!< SCTIMER input 1 */
|
||||
kSCTIMER_Input_2, /*!< SCTIMER input 2 */
|
||||
kSCTIMER_Input_3, /*!< SCTIMER input 3 */
|
||||
kSCTIMER_Input_4, /*!< SCTIMER input 4 */
|
||||
kSCTIMER_Input_5, /*!< SCTIMER input 5 */
|
||||
kSCTIMER_Input_6, /*!< SCTIMER input 6 */
|
||||
kSCTIMER_Input_7 /*!< SCTIMER input 7 */
|
||||
} sctimer_input_t;
|
||||
|
||||
/*! @brief List of SCTimer output pins */
|
||||
typedef enum _sctimer_out
|
||||
{
|
||||
kSCTIMER_Out_0 = 0U, /*!< SCTIMER output 0*/
|
||||
kSCTIMER_Out_1, /*!< SCTIMER output 1 */
|
||||
kSCTIMER_Out_2, /*!< SCTIMER output 2 */
|
||||
kSCTIMER_Out_3, /*!< SCTIMER output 3 */
|
||||
kSCTIMER_Out_4, /*!< SCTIMER output 4 */
|
||||
kSCTIMER_Out_5, /*!< SCTIMER output 5 */
|
||||
kSCTIMER_Out_6, /*!< SCTIMER output 6 */
|
||||
kSCTIMER_Out_7 /*!< SCTIMER output 7 */
|
||||
} sctimer_out_t;
|
||||
|
||||
/*! @brief SCTimer PWM output pulse mode: high-true, low-true or no output */
|
||||
typedef enum _sctimer_pwm_level_select
|
||||
{
|
||||
kSCTIMER_LowTrue = 0U, /*!< Low true pulses */
|
||||
kSCTIMER_HighTrue /*!< High true pulses */
|
||||
} sctimer_pwm_level_select_t;
|
||||
|
||||
/*! @brief Options to configure a SCTimer PWM signal */
|
||||
typedef struct _sctimer_pwm_signal_param
|
||||
{
|
||||
sctimer_out_t output; /*!< The output pin to use to generate the PWM signal */
|
||||
sctimer_pwm_level_select_t level; /*!< PWM output active level select. */
|
||||
uint8_t dutyCyclePercent; /*!< PWM pulse width, value should be between 1 to 100
|
||||
100 = always active signal (100% duty cycle).*/
|
||||
} sctimer_pwm_signal_param_t;
|
||||
|
||||
/*! @brief SCTimer clock mode options */
|
||||
typedef enum _sctimer_clock_mode
|
||||
{
|
||||
kSCTIMER_System_ClockMode = 0U, /*!< System Clock Mode */
|
||||
kSCTIMER_Sampled_ClockMode, /*!< Sampled System Clock Mode */
|
||||
kSCTIMER_Input_ClockMode, /*!< SCT Input Clock Mode */
|
||||
kSCTIMER_Asynchronous_ClockMode /*!< Asynchronous Mode */
|
||||
} sctimer_clock_mode_t;
|
||||
|
||||
/*! @brief SCTimer clock select options */
|
||||
typedef enum _sctimer_clock_select
|
||||
{
|
||||
kSCTIMER_Clock_On_Rise_Input_0 = 0U, /*!< Rising edges on input 0 */
|
||||
kSCTIMER_Clock_On_Fall_Input_0, /*!< Falling edges on input 0 */
|
||||
kSCTIMER_Clock_On_Rise_Input_1, /*!< Rising edges on input 1 */
|
||||
kSCTIMER_Clock_On_Fall_Input_1, /*!< Falling edges on input 1 */
|
||||
kSCTIMER_Clock_On_Rise_Input_2, /*!< Rising edges on input 2 */
|
||||
kSCTIMER_Clock_On_Fall_Input_2, /*!< Falling edges on input 2 */
|
||||
kSCTIMER_Clock_On_Rise_Input_3, /*!< Rising edges on input 3 */
|
||||
kSCTIMER_Clock_On_Fall_Input_3, /*!< Falling edges on input 3 */
|
||||
kSCTIMER_Clock_On_Rise_Input_4, /*!< Rising edges on input 4 */
|
||||
kSCTIMER_Clock_On_Fall_Input_4, /*!< Falling edges on input 4 */
|
||||
kSCTIMER_Clock_On_Rise_Input_5, /*!< Rising edges on input 5 */
|
||||
kSCTIMER_Clock_On_Fall_Input_5, /*!< Falling edges on input 5 */
|
||||
kSCTIMER_Clock_On_Rise_Input_6, /*!< Rising edges on input 6 */
|
||||
kSCTIMER_Clock_On_Fall_Input_6, /*!< Falling edges on input 6 */
|
||||
kSCTIMER_Clock_On_Rise_Input_7, /*!< Rising edges on input 7 */
|
||||
kSCTIMER_Clock_On_Fall_Input_7 /*!< Falling edges on input 7 */
|
||||
} sctimer_clock_select_t;
|
||||
|
||||
/*!
|
||||
* @brief SCTimer output conflict resolution options.
|
||||
*
|
||||
* Specifies what action should be taken if multiple events dictate that a given output should be
|
||||
* both set and cleared at the same time
|
||||
*/
|
||||
typedef enum _sctimer_conflict_resolution
|
||||
{
|
||||
kSCTIMER_ResolveNone = 0U, /*!< No change */
|
||||
kSCTIMER_ResolveSet, /*!< Set output */
|
||||
kSCTIMER_ResolveClear, /*!< Clear output */
|
||||
kSCTIMER_ResolveToggle /*!< Toggle output */
|
||||
} sctimer_conflict_resolution_t;
|
||||
|
||||
/*! @brief List of SCTimer event types */
|
||||
typedef enum _sctimer_event
|
||||
{
|
||||
kSCTIMER_InputLowOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputRiseOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (1 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputFallOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (2 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputHighOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (3 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
|
||||
kSCTIMER_MatchEventOnly =
|
||||
(1 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
|
||||
kSCTIMER_InputLowEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputRiseEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (1 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputFallEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (2 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputHighEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (3 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
|
||||
kSCTIMER_InputLowAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputRiseAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (1 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputFallAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (2 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_InputHighAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (3 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (0 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
|
||||
kSCTIMER_OutputLowOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputRiseOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (1 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputFallOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (2 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputHighOrMatchEvent =
|
||||
(0 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (3 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
|
||||
kSCTIMER_OutputLowEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputRiseEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (1 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputFallEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (2 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputHighEvent =
|
||||
(2 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (3 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
|
||||
kSCTIMER_OutputLowAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (0 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputRiseAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (1 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputFallAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (2 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT),
|
||||
kSCTIMER_OutputHighAndMatchEvent =
|
||||
(3 << SCT_EVENT_CTRL_COMBMODE_SHIFT) + (3 << SCT_EVENT_CTRL_IOCOND_SHIFT) + (1 << SCT_EVENT_CTRL_OUTSEL_SHIFT)
|
||||
} sctimer_event_t;
|
||||
|
||||
/*! @brief SCTimer callback typedef. */
|
||||
typedef void (*sctimer_event_callback_t)(void);
|
||||
|
||||
/*! @brief List of SCTimer interrupts */
|
||||
typedef enum _sctimer_interrupt_enable
|
||||
{
|
||||
kSCTIMER_Event0InterruptEnable = (1U << 0), /*!< Event 0 interrupt */
|
||||
kSCTIMER_Event1InterruptEnable = (1U << 1), /*!< Event 1 interrupt */
|
||||
kSCTIMER_Event2InterruptEnable = (1U << 2), /*!< Event 2 interrupt */
|
||||
kSCTIMER_Event3InterruptEnable = (1U << 3), /*!< Event 3 interrupt */
|
||||
kSCTIMER_Event4InterruptEnable = (1U << 4), /*!< Event 4 interrupt */
|
||||
kSCTIMER_Event5InterruptEnable = (1U << 5), /*!< Event 5 interrupt */
|
||||
kSCTIMER_Event6InterruptEnable = (1U << 6), /*!< Event 6 interrupt */
|
||||
kSCTIMER_Event7InterruptEnable = (1U << 7), /*!< Event 7 interrupt */
|
||||
kSCTIMER_Event8InterruptEnable = (1U << 8), /*!< Event 8 interrupt */
|
||||
kSCTIMER_Event9InterruptEnable = (1U << 9), /*!< Event 9 interrupt */
|
||||
kSCTIMER_Event10InterruptEnable = (1U << 10), /*!< Event 10 interrupt */
|
||||
kSCTIMER_Event11InterruptEnable = (1U << 11), /*!< Event 11 interrupt */
|
||||
kSCTIMER_Event12InterruptEnable = (1U << 12), /*!< Event 12 interrupt */
|
||||
} sctimer_interrupt_enable_t;
|
||||
|
||||
/*! @brief List of SCTimer flags */
|
||||
typedef enum _sctimer_status_flags
|
||||
{
|
||||
kSCTIMER_Event0Flag = (1U << 0), /*!< Event 0 Flag */
|
||||
kSCTIMER_Event1Flag = (1U << 1), /*!< Event 1 Flag */
|
||||
kSCTIMER_Event2Flag = (1U << 2), /*!< Event 2 Flag */
|
||||
kSCTIMER_Event3Flag = (1U << 3), /*!< Event 3 Flag */
|
||||
kSCTIMER_Event4Flag = (1U << 4), /*!< Event 4 Flag */
|
||||
kSCTIMER_Event5Flag = (1U << 5), /*!< Event 5 Flag */
|
||||
kSCTIMER_Event6Flag = (1U << 6), /*!< Event 6 Flag */
|
||||
kSCTIMER_Event7Flag = (1U << 7), /*!< Event 7 Flag */
|
||||
kSCTIMER_Event8Flag = (1U << 8), /*!< Event 8 Flag */
|
||||
kSCTIMER_Event9Flag = (1U << 9), /*!< Event 9 Flag */
|
||||
kSCTIMER_Event10Flag = (1U << 10), /*!< Event 10 Flag */
|
||||
kSCTIMER_Event11Flag = (1U << 11), /*!< Event 11 Flag */
|
||||
kSCTIMER_Event12Flag = (1U << 12), /*!< Event 12 Flag */
|
||||
kSCTIMER_BusErrorLFlag =
|
||||
(1U << SCT_CONFLAG_BUSERRL_SHIFT), /*!< Bus error due to write when L counter was not halted */
|
||||
kSCTIMER_BusErrorHFlag =
|
||||
(1U << SCT_CONFLAG_BUSERRH_SHIFT) /*!< Bus error due to write when H counter was not halted */
|
||||
} sctimer_status_flags_t;
|
||||
|
||||
/*!
|
||||
* @brief SCTimer configuration structure
|
||||
*
|
||||
* This structure holds the configuration settings for the SCTimer peripheral. To initialize this
|
||||
* structure to reasonable defaults, call the SCTMR_GetDefaultConfig() function and pass a
|
||||
* pointer to the configuration structure instance.
|
||||
*
|
||||
* The configuration structure can be made constant so as to reside in flash.
|
||||
*/
|
||||
typedef struct _sctimer_config
|
||||
{
|
||||
bool enableCounterUnify; /*!< true: SCT operates as a unified 32-bit counter;
|
||||
false: SCT operates as two 16-bit counters */
|
||||
sctimer_clock_mode_t clockMode; /*!< SCT clock mode value */
|
||||
sctimer_clock_select_t clockSelect; /*!< SCT clock select value */
|
||||
bool enableBidirection_l; /*!< true: Up-down count mode for the L or unified counter
|
||||
false: Up count mode only for the L or unified counter */
|
||||
bool enableBidirection_h; /*!< true: Up-down count mode for the H or unified counter
|
||||
false: Up count mode only for the H or unified counter.
|
||||
This field is used only if the enableCounterUnify is set
|
||||
to false */
|
||||
uint8_t prescale_l; /*!< Prescale value to produce the L or unified counter clock */
|
||||
uint8_t prescale_h; /*!< Prescale value to produce the H counter clock.
|
||||
This field is used only if the enableCounterUnify is set
|
||||
to false */
|
||||
uint8_t outInitState; /*!< Defines the initial output value */
|
||||
} sctimer_config_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Ungates the SCTimer clock and configures the peripheral for basic operation.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application using the SCTimer driver.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param config Pointer to the user configuration structure.
|
||||
*
|
||||
* @return kStatus_Success indicates success; Else indicates failure.
|
||||
*/
|
||||
status_t SCTIMER_Init(SCT_Type *base, const sctimer_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Gates the SCTimer clock.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
*/
|
||||
void SCTIMER_Deinit(SCT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Fills in the SCTimer configuration structure with the default settings.
|
||||
*
|
||||
* The default values are:
|
||||
* @code
|
||||
* config->enableCounterUnify = true;
|
||||
* config->clockMode = kSCTIMER_System_ClockMode;
|
||||
* config->clockSelect = kSCTIMER_Clock_On_Rise_Input_0;
|
||||
* config->enableBidirection_l = false;
|
||||
* config->enableBidirection_h = false;
|
||||
* config->prescale_l = 0;
|
||||
* config->prescale_h = 0;
|
||||
* config->outInitState = 0;
|
||||
* @endcode
|
||||
* @param config Pointer to the user configuration structure.
|
||||
*/
|
||||
void SCTIMER_GetDefaultConfig(sctimer_config_t *config);
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name PWM setup operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Configures the PWM signal parameters.
|
||||
*
|
||||
* Call this function to configure the PWM signal period, mode, duty cycle, and edge. This
|
||||
* function will create 2 events; one of the events will trigger on match with the pulse value
|
||||
* and the other will trigger when the counter matches the PWM period. The PWM period event is
|
||||
* also used as a limit event to reset the counter or change direction. Both events are enabled
|
||||
* for the same state. The state number can be retrieved by calling the function
|
||||
* SCTIMER_GetCurrentStateNumber().
|
||||
* The counter is set to operate as one 32-bit counter (unify bit is set to 1).
|
||||
* The counter operates in bi-directional mode when generating a center-aligned PWM.
|
||||
*
|
||||
* @note When setting PWM output from multiple output pins, they all should use the same PWM mode
|
||||
* i.e all PWM's should be either edge-aligned or center-aligned.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param pwmParams PWM parameters to configure the output
|
||||
* @param mode PWM operation mode, options available in enumeration ::sctimer_pwm_mode_t
|
||||
* @param pwmFreq_Hz PWM signal frequency in Hz
|
||||
* @param srcClock_Hz SCTimer counter clock in Hz
|
||||
* @param event Pointer to a variable where the PWM period event number is stored
|
||||
*
|
||||
* @return kStatus_Success on success
|
||||
* kStatus_Fail If we have hit the limit in terms of number of events created or if
|
||||
* an incorrect PWM dutycylce is passed in.
|
||||
*/
|
||||
status_t SCTIMER_SetupPwm(SCT_Type *base,
|
||||
const sctimer_pwm_signal_param_t *pwmParams,
|
||||
sctimer_pwm_mode_t mode,
|
||||
uint32_t pwmFreq_Hz,
|
||||
uint32_t srcClock_Hz,
|
||||
uint32_t *event);
|
||||
|
||||
/*!
|
||||
* @brief Updates the duty cycle of an active PWM signal.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param output The output to configure
|
||||
* @param dutyCyclePercent New PWM pulse width; the value should be between 1 to 100
|
||||
* @param event Event number associated with this PWM signal. This was returned to the user by the
|
||||
* function SCTIMER_SetupPwm().
|
||||
*/
|
||||
void SCTIMER_UpdatePwmDutycycle(SCT_Type *base, sctimer_out_t output, uint8_t dutyCyclePercent, uint32_t event);
|
||||
|
||||
/*!
|
||||
* @name Interrupt Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables the selected SCTimer interrupts.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param mask The interrupts to enable. This is a logical OR of members of the
|
||||
* enumeration ::sctimer_interrupt_enable_t
|
||||
*/
|
||||
static inline void SCTIMER_EnableInterrupts(SCT_Type *base, uint32_t mask)
|
||||
{
|
||||
base->EVEN |= mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables the selected SCTimer interrupts.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param mask The interrupts to enable. This is a logical OR of members of the
|
||||
* enumeration ::sctimer_interrupt_enable_t
|
||||
*/
|
||||
static inline void SCTIMER_DisableInterrupts(SCT_Type *base, uint32_t mask)
|
||||
{
|
||||
base->EVEN &= ~mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the enabled SCTimer interrupts.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
*
|
||||
* @return The enabled interrupts. This is the logical OR of members of the
|
||||
* enumeration ::sctimer_interrupt_enable_t
|
||||
*/
|
||||
static inline uint32_t SCTIMER_GetEnabledInterrupts(SCT_Type *base)
|
||||
{
|
||||
return (base->EVEN & 0xFFFFU);
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Status Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Gets the SCTimer status flags.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
*
|
||||
* @return The status flags. This is the logical OR of members of the
|
||||
* enumeration ::sctimer_status_flags_t
|
||||
*/
|
||||
static inline uint32_t SCTIMER_GetStatusFlags(SCT_Type *base)
|
||||
{
|
||||
uint32_t statusFlags = 0;
|
||||
|
||||
/* Add the recorded events */
|
||||
statusFlags = (base->EVFLAG & 0xFFFFU);
|
||||
|
||||
/* Add bus error flags */
|
||||
statusFlags |= (base->CONFLAG & (SCT_CONFLAG_BUSERRL_MASK | SCT_CONFLAG_BUSERRH_MASK));
|
||||
|
||||
return statusFlags;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clears the SCTimer status flags.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param mask The status flags to clear. This is a logical OR of members of the
|
||||
* enumeration ::sctimer_status_flags_t
|
||||
*/
|
||||
static inline void SCTIMER_ClearStatusFlags(SCT_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Write to the flag registers */
|
||||
base->EVFLAG = (mask & 0xFFFFU);
|
||||
base->CONFLAG = (mask & (SCT_CONFLAG_BUSERRL_MASK | SCT_CONFLAG_BUSERRH_MASK));
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Counter Start and Stop
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Starts the SCTimer counter.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param countertoStart SCTimer counter to start; if unify mode is set then function always
|
||||
* writes to HALT_L bit
|
||||
*/
|
||||
static inline void SCTIMER_StartTimer(SCT_Type *base, sctimer_counter_t countertoStart)
|
||||
{
|
||||
/* Clear HALT_L bit if counter is operating in 32-bit mode or user wants to start L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (countertoStart == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->CTRL &= ~(SCT_CTRL_HALT_L_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start H counter */
|
||||
base->CTRL &= ~(SCT_CTRL_HALT_H_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Halts the SCTimer counter.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param countertoStop SCTimer counter to stop; if unify mode is set then function always
|
||||
* writes to HALT_L bit
|
||||
*/
|
||||
static inline void SCTIMER_StopTimer(SCT_Type *base, sctimer_counter_t countertoStop)
|
||||
{
|
||||
/* Set HALT_L bit if counter is operating in 32-bit mode or user wants to stop L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (countertoStop == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->CTRL |= (SCT_CTRL_HALT_L_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Stop H counter */
|
||||
base->CTRL |= (SCT_CTRL_HALT_H_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Functions to create a new event and manage the state logic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Create an event that is triggered on a match or IO and schedule in current state.
|
||||
*
|
||||
* This function will configure an event using the options provided by the user. If the event type uses
|
||||
* the counter match, then the function will set the user provided match value into a match register
|
||||
* and put this match register number into the event control register.
|
||||
* The event is enabled for the current state and the event number is increased by one at the end.
|
||||
* The function returns the event number; this event number can be used to configure actions to be
|
||||
* done when this event is triggered.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param howToMonitor Event type; options are available in the enumeration ::sctimer_interrupt_enable_t
|
||||
* @param matchValue The match value that will be programmed to a match register
|
||||
* @param whichIO The input or output that will be involved in event triggering. This field
|
||||
* is ignored if the event type is "match only"
|
||||
* @param whichCounter SCTimer counter to use when operating in 16-bit mode. In 32-bit mode, this
|
||||
* field has no meaning as we have only 1 unified counter; hence ignored.
|
||||
* @param event Pointer to a variable where the new event number is stored
|
||||
*
|
||||
* @return kStatus_Success on success
|
||||
* kStatus_Error if we have hit the limit in terms of number of events created or
|
||||
if we have reached the limit in terms of number of match registers
|
||||
*/
|
||||
status_t SCTIMER_CreateAndScheduleEvent(SCT_Type *base,
|
||||
sctimer_event_t howToMonitor,
|
||||
uint32_t matchValue,
|
||||
uint32_t whichIO,
|
||||
sctimer_counter_t whichCounter,
|
||||
uint32_t *event);
|
||||
|
||||
/*!
|
||||
* @brief Enable an event in the current state.
|
||||
*
|
||||
* This function will allow the event passed in to trigger in the current state. The event must
|
||||
* be created earlier by either calling the function SCTIMER_SetupPwm() or function
|
||||
* SCTIMER_CreateAndScheduleEvent() .
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param event Event number to enable in the current state
|
||||
*
|
||||
*/
|
||||
void SCTIMER_ScheduleEvent(SCT_Type *base, uint32_t event);
|
||||
|
||||
/*!
|
||||
* @brief Increase the state by 1
|
||||
*
|
||||
* All future events created by calling the function SCTIMER_ScheduleEvent() will be enabled in this new
|
||||
* state.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
*
|
||||
* @return kStatus_Success on success
|
||||
* kStatus_Error if we have hit the limit in terms of states used
|
||||
|
||||
*/
|
||||
status_t SCTIMER_IncreaseState(SCT_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Provides the current state
|
||||
*
|
||||
* User can use this to set the next state by calling the function SCTIMER_SetupNextStateAction().
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
*
|
||||
* @return The current state
|
||||
*/
|
||||
uint32_t SCTIMER_GetCurrentState(SCT_Type *base);
|
||||
|
||||
/*! @}*/
|
||||
|
||||
/*!
|
||||
* @name Actions to take in response to an event
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Setup capture of the counter value on trigger of a selected event
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichCounter SCTimer counter to use when operating in 16-bit mode. In 32-bit mode, this
|
||||
* field has no meaning as only the Counter_L bits are used.
|
||||
* @param captureRegister Pointer to a variable where the capture register number will be returned. User
|
||||
* can read the captured value from this register when the specified event is triggered.
|
||||
* @param event Event number that will trigger the capture
|
||||
*
|
||||
* @return kStatus_Success on success
|
||||
* kStatus_Error if we have hit the limit in terms of number of match/capture registers available
|
||||
*/
|
||||
status_t SCTIMER_SetupCaptureAction(SCT_Type *base,
|
||||
sctimer_counter_t whichCounter,
|
||||
uint32_t *captureRegister,
|
||||
uint32_t event);
|
||||
|
||||
/*!
|
||||
* @brief Receive noticification when the event trigger an interrupt.
|
||||
*
|
||||
* If the interrupt for the event is enabled by the user, then a callback can be registered
|
||||
* which will be invoked when the event is triggered
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param event Event number that will trigger the interrupt
|
||||
* @param callback Function to invoke when the event is triggered
|
||||
*/
|
||||
|
||||
void SCTIMER_SetCallback(SCT_Type *base, sctimer_event_callback_t callback, uint32_t event);
|
||||
|
||||
/*!
|
||||
* @brief Transition to the specified state.
|
||||
*
|
||||
* This transition will be triggered by the event number that is passed in by the user.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param nextState The next state SCTimer will transition to
|
||||
* @param event Event number that will trigger the state transition
|
||||
*/
|
||||
static inline void SCTIMER_SetupNextStateAction(SCT_Type *base, uint32_t nextState, uint32_t event)
|
||||
{
|
||||
uint32_t reg = base->EVENT[event].CTRL;
|
||||
|
||||
reg &= ~(SCT_EVENT_CTRL_STATEV_MASK);
|
||||
/* Load the STATEV value when the event occurs to be the next state */
|
||||
reg |= SCT_EVENT_CTRL_STATEV(nextState) | SCT_EVENT_CTRL_STATELD_MASK;
|
||||
|
||||
base->EVENT[event].CTRL = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the Output.
|
||||
*
|
||||
* This output will be set when the event number that is passed in by the user is triggered.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichIO The output to set
|
||||
* @param event Event number that will trigger the output change
|
||||
*/
|
||||
static inline void SCTIMER_SetupOutputSetAction(SCT_Type *base, uint32_t whichIO, uint32_t event)
|
||||
{
|
||||
base->OUT[whichIO].SET |= (1U << event);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear the Output.
|
||||
*
|
||||
* This output will be cleared when the event number that is passed in by the user is triggered.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichIO The output to clear
|
||||
* @param event Event number that will trigger the output change
|
||||
*/
|
||||
static inline void SCTIMER_SetupOutputClearAction(SCT_Type *base, uint32_t whichIO, uint32_t event)
|
||||
{
|
||||
base->OUT[whichIO].CLR |= (1U << event);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Toggle the output level.
|
||||
*
|
||||
* This change in the output level is triggered by the event number that is passed in by the user.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichIO The output to toggle
|
||||
* @param event Event number that will trigger the output change
|
||||
*/
|
||||
void SCTIMER_SetupOutputToggleAction(SCT_Type *base, uint32_t whichIO, uint32_t event);
|
||||
|
||||
/*!
|
||||
* @brief Limit the running counter.
|
||||
*
|
||||
* The counter is limited when the event number that is passed in by the user is triggered.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichCounter SCTimer counter to use when operating in 16-bit mode. In 32-bit mode, this
|
||||
* field has no meaning as only the Counter_L bits are used.
|
||||
* @param event Event number that will trigger the counter to be limited
|
||||
*/
|
||||
static inline void SCTIMER_SetupCounterLimitAction(SCT_Type *base, sctimer_counter_t whichCounter, uint32_t event)
|
||||
{
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->LIMIT |= SCT_LIMIT_LIMMSK_L(1U << event);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->LIMIT |= SCT_LIMIT_LIMMSK_H(1U << event);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Stop the running counter.
|
||||
*
|
||||
* The counter is stopped when the event number that is passed in by the user is triggered.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichCounter SCTimer counter to use when operating in 16-bit mode. In 32-bit mode, this
|
||||
* field has no meaning as only the Counter_L bits are used.
|
||||
* @param event Event number that will trigger the counter to be stopped
|
||||
*/
|
||||
static inline void SCTIMER_SetupCounterStopAction(SCT_Type *base, sctimer_counter_t whichCounter, uint32_t event)
|
||||
{
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->STOP |= SCT_STOP_STOPMSK_L(1U << event);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->STOP |= SCT_STOP_STOPMSK_H(1U << event);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Re-start the stopped counter.
|
||||
*
|
||||
* The counter will re-start when the event number that is passed in by the user is triggered.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichCounter SCTimer counter to use when operating in 16-bit mode. In 32-bit mode, this
|
||||
* field has no meaning as only the Counter_L bits are used.
|
||||
* @param event Event number that will trigger the counter to re-start
|
||||
*/
|
||||
static inline void SCTIMER_SetupCounterStartAction(SCT_Type *base, sctimer_counter_t whichCounter, uint32_t event)
|
||||
{
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->START |= SCT_START_STARTMSK_L(1U << event);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->START |= SCT_START_STARTMSK_H(1U << event);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Halt the running counter.
|
||||
*
|
||||
* The counter is disabled (halted) when the event number that is passed in by the user is
|
||||
* triggered. When the counter is halted, all further events are disabled. The HALT condition
|
||||
* can only be removed by calling the SCTIMER_StartTimer() function.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param whichCounter SCTimer counter to use when operating in 16-bit mode. In 32-bit mode, this
|
||||
* field has no meaning as only the Counter_L bits are used.
|
||||
* @param event Event number that will trigger the counter to be halted
|
||||
*/
|
||||
static inline void SCTIMER_SetupCounterHaltAction(SCT_Type *base, sctimer_counter_t whichCounter, uint32_t event)
|
||||
{
|
||||
/* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
|
||||
if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
|
||||
{
|
||||
base->HALT |= SCT_HALT_HALTMSK_L(1U << event);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->HALT |= SCT_HALT_HALTMSK_H(1U << event);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Generate a DMA request.
|
||||
*
|
||||
* DMA request will be triggered by the event number that is passed in by the user.
|
||||
*
|
||||
* @param base SCTimer peripheral base address
|
||||
* @param dmaNumber The DMA request to generate
|
||||
* @param event Event number that will trigger the DMA request
|
||||
*/
|
||||
static inline void SCTIMER_SetupDmaTriggerAction(SCT_Type *base, uint32_t dmaNumber, uint32_t event)
|
||||
{
|
||||
if (dmaNumber == 0)
|
||||
{
|
||||
base->DMA0REQUEST |= (1U << event);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->DMA1REQUEST |= (1U << event);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief SCTimer interrupt handler.
|
||||
*
|
||||
* @param base SCTimer peripheral base address.
|
||||
*/
|
||||
void SCTIMER_EventHandleIRQ(SCT_Type *base);
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_SCTIMER_H_ */
|
|
@ -0,0 +1,688 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_spi.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
******************************************************************************/
|
||||
/* Note: FIFOCFG[SIZE] has always value 1 = 8 items depth */
|
||||
#define SPI_FIFO_DEPTH(base) ((((base)->FIFOCFG & SPI_FIFOCFG_SIZE_MASK) >> SPI_FIFOCFG_SIZE_SHIFT) << 3)
|
||||
|
||||
/* Convert transfer count to transfer bytes. dataWidth is a
|
||||
* range <0,15>. Range <8,15> represents 2B transfer */
|
||||
#define SPI_COUNT_TO_BYTES(dataWidth, count) ((count) << ((dataWidth) >> 3U))
|
||||
#define SPI_BYTES_TO_COUNT(dataWidth, bytes) ((bytes) >> ((dataWidth) >> 3U))
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief internal SPI config array */
|
||||
static spi_config_t g_configs[FSL_FEATURE_SOC_SPI_COUNT] = {(spi_data_width_t)0};
|
||||
|
||||
/*! @brief IRQ name array */
|
||||
static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void *SPI_GetConfig(SPI_Type *base)
|
||||
{
|
||||
int32_t instance;
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
if (instance < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &g_configs[instance];
|
||||
}
|
||||
|
||||
void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
||||
{
|
||||
assert(NULL != config);
|
||||
|
||||
config->enableLoopback = false;
|
||||
config->enableMaster = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->baudRate_Bps = 500000U;
|
||||
config->dataWidth = kSPI_Data8Bits;
|
||||
config->sselNum = kSPI_Ssel0;
|
||||
config->txWatermark = kSPI_TxFifo0;
|
||||
config->rxWatermark = kSPI_RxFifo1;
|
||||
}
|
||||
|
||||
status_t SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
|
||||
{
|
||||
int32_t result = 0, instance = 0;
|
||||
uint32_t tmp;
|
||||
|
||||
/* assert params */
|
||||
assert(!((NULL == base) || (NULL == config) || (0 == srcClock_Hz)));
|
||||
if ((NULL == base) || (NULL == config) || (0 == srcClock_Hz))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* initialize flexcomm to SPI mode */
|
||||
result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_SPI);
|
||||
assert(kStatus_Success == result);
|
||||
if (kStatus_Success != result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* set divider */
|
||||
result = SPI_MasterSetBaud(base, config->baudRate_Bps, srcClock_Hz);
|
||||
if (kStatus_Success != result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
/* get instance number */
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
assert(instance >= 0);
|
||||
|
||||
/* store configuration */
|
||||
g_configs[instance].dataWidth = config->dataWidth;
|
||||
g_configs[instance].sselNum = config->sselNum;
|
||||
/* enable FIFOs */
|
||||
base->FIFOCFG |= SPI_FIFOCFG_EMPTYTX_MASK | SPI_FIFOCFG_EMPTYRX_MASK;
|
||||
base->FIFOCFG |= SPI_FIFOCFG_ENABLETX_MASK | SPI_FIFOCFG_ENABLERX_MASK;
|
||||
/* trigger level - empty txFIFO, one item in rxFIFO */
|
||||
tmp = base->FIFOTRIG & (~(SPI_FIFOTRIG_RXLVL_MASK | SPI_FIFOTRIG_TXLVL_MASK));
|
||||
tmp |= SPI_FIFOTRIG_TXLVL(config->txWatermark) | SPI_FIFOTRIG_RXLVL(config->rxWatermark);
|
||||
/* enable generating interrupts for FIFOTRIG levels */
|
||||
tmp |= SPI_FIFOTRIG_TXLVLENA_MASK | SPI_FIFOTRIG_RXLVLENA_MASK;
|
||||
/* set FIFOTRIG */
|
||||
base->FIFOTRIG = tmp;
|
||||
/* configure SPI mode */
|
||||
tmp = base->CFG;
|
||||
tmp &= ~(SPI_CFG_MASTER_MASK | SPI_CFG_LSBF_MASK | SPI_CFG_CPHA_MASK | SPI_CFG_CPOL_MASK | SPI_CFG_LOOP_MASK);
|
||||
/* phase */
|
||||
tmp |= SPI_CFG_CPHA(config->phase);
|
||||
/* polarity */
|
||||
tmp |= SPI_CFG_CPOL(config->polarity);
|
||||
/* direction */
|
||||
tmp |= SPI_CFG_LSBF(config->direction);
|
||||
/* master mode */
|
||||
tmp |= SPI_CFG_MASTER(1);
|
||||
/* loopback */
|
||||
tmp |= SPI_CFG_LOOP(config->enableLoopback);
|
||||
base->CFG = tmp;
|
||||
SPI_Enable(base, config->enableMaster);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
||||
{
|
||||
assert(NULL != config);
|
||||
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->dataWidth = kSPI_Data8Bits;
|
||||
config->txWatermark = kSPI_TxFifo0;
|
||||
config->rxWatermark = kSPI_RxFifo1;
|
||||
}
|
||||
|
||||
status_t SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
||||
{
|
||||
int32_t result = 0, instance;
|
||||
uint32_t tmp;
|
||||
|
||||
/* assert params */
|
||||
assert(!((NULL == base) || (NULL == config)));
|
||||
if ((NULL == base) || (NULL == config))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* configure flexcomm to SPI, enable clock gate */
|
||||
result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_SPI);
|
||||
assert(kStatus_Success == result);
|
||||
if (kStatus_Success != result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
|
||||
/* store configuration */
|
||||
g_configs[instance].dataWidth = config->dataWidth;
|
||||
/* empty and enable FIFOs */
|
||||
base->FIFOCFG |= SPI_FIFOCFG_EMPTYTX_MASK | SPI_FIFOCFG_EMPTYRX_MASK;
|
||||
base->FIFOCFG |= SPI_FIFOCFG_ENABLETX_MASK | SPI_FIFOCFG_ENABLERX_MASK;
|
||||
/* trigger level - empty txFIFO, one item in rxFIFO */
|
||||
tmp = base->FIFOTRIG & (~(SPI_FIFOTRIG_RXLVL_MASK | SPI_FIFOTRIG_TXLVL_MASK));
|
||||
tmp |= SPI_FIFOTRIG_TXLVL(config->txWatermark) | SPI_FIFOTRIG_RXLVL(config->rxWatermark);
|
||||
/* enable generating interrupts for FIFOTRIG levels */
|
||||
tmp |= SPI_FIFOTRIG_TXLVLENA_MASK | SPI_FIFOTRIG_RXLVLENA_MASK;
|
||||
/* set FIFOTRIG */
|
||||
base->FIFOTRIG = tmp;
|
||||
/* configure SPI mode */
|
||||
tmp = base->CFG;
|
||||
tmp &= ~(SPI_CFG_MASTER_MASK | SPI_CFG_LSBF_MASK | SPI_CFG_CPHA_MASK | SPI_CFG_CPOL_MASK);
|
||||
/* phase */
|
||||
tmp |= SPI_CFG_CPHA(config->phase);
|
||||
/* polarity */
|
||||
tmp |= SPI_CFG_CPOL(config->polarity);
|
||||
/* direction */
|
||||
tmp |= SPI_CFG_LSBF(config->direction);
|
||||
base->CFG = tmp;
|
||||
SPI_Enable(base, config->enableSlave);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SPI_Deinit(SPI_Type *base)
|
||||
{
|
||||
/* Assert arguments */
|
||||
assert(NULL != base);
|
||||
/* Disable interrupts, disable dma requests, disable peripheral */
|
||||
base->FIFOINTENCLR = SPI_FIFOINTENCLR_TXERR_MASK | SPI_FIFOINTENCLR_RXERR_MASK | SPI_FIFOINTENCLR_TXLVL_MASK |
|
||||
SPI_FIFOINTENCLR_RXLVL_MASK;
|
||||
base->FIFOCFG &= ~(SPI_FIFOCFG_DMATX_MASK | SPI_FIFOCFG_DMARX_MASK);
|
||||
base->CFG &= ~(SPI_CFG_ENABLE_MASK);
|
||||
}
|
||||
|
||||
void SPI_EnableTxDMA(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->FIFOCFG |= SPI_FIFOCFG_DMATX_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOCFG &= ~SPI_FIFOCFG_DMATX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
void SPI_EnableRxDMA(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->FIFOCFG |= SPI_FIFOCFG_DMARX_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOCFG &= ~SPI_FIFOCFG_DMARX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
status_t SPI_MasterSetBaud(SPI_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* assert params */
|
||||
assert(!((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz)));
|
||||
if ((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* calculate baudrate */
|
||||
tmp = (srcClock_Hz / baudrate_Bps) - 1;
|
||||
if (tmp > 0xFFFF)
|
||||
{
|
||||
return kStatus_SPI_BaudrateNotSupport;
|
||||
}
|
||||
base->DIV &= ~SPI_DIV_DIVVAL_MASK;
|
||||
base->DIV |= SPI_DIV_DIVVAL(tmp);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SPI_WriteData(SPI_Type *base, uint16_t data, uint32_t configFlags)
|
||||
{
|
||||
uint32_t control = 0;
|
||||
int32_t instance;
|
||||
|
||||
/* check params */
|
||||
assert(NULL != base);
|
||||
/* get and check instance */
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
assert(!(instance < 0));
|
||||
if (instance < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* set data width */
|
||||
control |= SPI_FIFOWR_LEN(g_configs[instance].dataWidth);
|
||||
/* set sssel */
|
||||
control |= (SPI_DEASSERT_ALL & (~SPI_DEASSERTNUM_SSEL(g_configs[instance].sselNum)));
|
||||
/* mask configFlags */
|
||||
control |= (configFlags & SPI_FIFOWR_FLAGS_MASK);
|
||||
/* control should not affect lower 16 bits */
|
||||
assert(!(control & 0xFFFF));
|
||||
base->FIFOWR = data | control;
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferCreateHandle(SPI_Type *base,
|
||||
spi_master_handle_t *handle,
|
||||
spi_master_callback_t callback,
|
||||
void *userData)
|
||||
{
|
||||
int32_t instance = 0;
|
||||
|
||||
/* check 'base' */
|
||||
assert(!(NULL == base));
|
||||
if (NULL == base)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* check 'handle' */
|
||||
assert(!(NULL == handle));
|
||||
if (NULL == handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* get flexcomm instance by 'base' param */
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
assert(!(instance < 0));
|
||||
if (instance < 0)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
/* Initialize the handle */
|
||||
if (base->CFG & SPI_CFG_MASTER_MASK)
|
||||
{
|
||||
FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)(uintptr_t)SPI_MasterTransferHandleIRQ, handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)(uintptr_t)SPI_SlaveTransferHandleIRQ, handle);
|
||||
}
|
||||
|
||||
handle->dataWidth = g_configs[instance].dataWidth;
|
||||
/* in slave mode, the sselNum is not important */
|
||||
handle->sselNum = g_configs[instance].sselNum;
|
||||
handle->txWatermark = (spi_txfifo_watermark_t)SPI_FIFOTRIG_TXLVL_GET(base);
|
||||
handle->rxWatermark = (spi_rxfifo_watermark_t)SPI_FIFOTRIG_RXLVL_GET(base);
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
/* Enable SPI NVIC */
|
||||
EnableIRQ(s_spiIRQ[instance]);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
||||
{
|
||||
int32_t instance;
|
||||
uint32_t tx_ctrl = 0, last_ctrl = 0;
|
||||
uint32_t tmp32, rxRemainingBytes, txRemainingBytes, dataWidth;
|
||||
uint32_t toReceiveCount = 0;
|
||||
uint8_t *txData, *rxData;
|
||||
uint32_t fifoDepth;
|
||||
|
||||
/* check params */
|
||||
assert(!((NULL == base) || (NULL == xfer) || ((NULL == xfer->txData) && (NULL == xfer->rxData))));
|
||||
if ((NULL == base) || (NULL == xfer) || ((NULL == xfer->txData) && (NULL == xfer->rxData)))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
fifoDepth = SPI_FIFO_DEPTH(base);
|
||||
txData = xfer->txData;
|
||||
rxData = xfer->rxData;
|
||||
txRemainingBytes = txData ? xfer->dataSize : 0;
|
||||
rxRemainingBytes = rxData ? xfer->dataSize : 0;
|
||||
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
assert(instance >= 0);
|
||||
dataWidth = g_configs[instance].dataWidth;
|
||||
|
||||
/* dataSize (in bytes) is not aligned to 16bit (2B) transfer */
|
||||
assert(!((dataWidth > kSPI_Data8Bits) && (xfer->dataSize & 0x1)));
|
||||
if ((dataWidth > kSPI_Data8Bits) && (xfer->dataSize & 0x1))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* clear tx/rx errors and empty FIFOs */
|
||||
base->FIFOCFG |= SPI_FIFOCFG_EMPTYTX_MASK | SPI_FIFOCFG_EMPTYRX_MASK;
|
||||
base->FIFOSTAT |= SPI_FIFOSTAT_TXERR_MASK | SPI_FIFOSTAT_RXERR_MASK;
|
||||
/* select slave to talk with */
|
||||
tx_ctrl |= (SPI_DEASSERT_ALL & (~SPI_DEASSERTNUM_SSEL(g_configs[instance].sselNum)));
|
||||
/* set width of data - range asserted at entry */
|
||||
tx_ctrl |= SPI_FIFOWR_LEN(dataWidth);
|
||||
/* end of transfer */
|
||||
last_ctrl |= (xfer->configFlags & (uint32_t)kSPI_FrameAssert) ? (uint32_t)kSPI_FrameAssert : 0;
|
||||
/* delay end of transfer */
|
||||
last_ctrl |= (xfer->configFlags & (uint32_t)kSPI_FrameDelay) ? (uint32_t)kSPI_FrameDelay : 0;
|
||||
/* last index of loop */
|
||||
while (txRemainingBytes || rxRemainingBytes || toReceiveCount)
|
||||
{
|
||||
/* if rxFIFO is not empty */
|
||||
if (base->FIFOSTAT & SPI_FIFOSTAT_RXNOTEMPTY_MASK)
|
||||
{
|
||||
tmp32 = base->FIFORD;
|
||||
/* rxBuffer is not empty */
|
||||
if (rxRemainingBytes)
|
||||
{
|
||||
*(rxData++) = tmp32;
|
||||
rxRemainingBytes--;
|
||||
/* read 16 bits at once */
|
||||
if (dataWidth > 8)
|
||||
{
|
||||
*(rxData++) = tmp32 >> 8;
|
||||
rxRemainingBytes--;
|
||||
}
|
||||
}
|
||||
/* decrease number of data expected to receive */
|
||||
toReceiveCount -= 1;
|
||||
}
|
||||
/* transmit if txFIFO is not full and data to receive does not exceed FIFO depth */
|
||||
if ((base->FIFOSTAT & SPI_FIFOSTAT_TXNOTFULL_MASK) && (toReceiveCount < fifoDepth) &&
|
||||
((txRemainingBytes) || (rxRemainingBytes >= SPI_COUNT_TO_BYTES(dataWidth, toReceiveCount + 1))))
|
||||
{
|
||||
/* txBuffer is not empty */
|
||||
if (txRemainingBytes)
|
||||
{
|
||||
tmp32 = *(txData++);
|
||||
txRemainingBytes--;
|
||||
/* write 16 bit at once */
|
||||
if (dataWidth > 8)
|
||||
{
|
||||
tmp32 |= ((uint32_t)(*(txData++))) << 8U;
|
||||
txRemainingBytes--;
|
||||
}
|
||||
if (!txRemainingBytes)
|
||||
{
|
||||
tx_ctrl |= last_ctrl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp32 = SPI_DUMMYDATA;
|
||||
/* last transfer */
|
||||
if (rxRemainingBytes == SPI_COUNT_TO_BYTES(dataWidth, toReceiveCount + 1))
|
||||
{
|
||||
tx_ctrl |= last_ctrl;
|
||||
}
|
||||
}
|
||||
/* send data */
|
||||
tmp32 = tx_ctrl | tmp32;
|
||||
base->FIFOWR = tmp32;
|
||||
toReceiveCount += 1;
|
||||
}
|
||||
}
|
||||
/* wait if TX FIFO of previous transfer is not empty */
|
||||
while (!(base->FIFOSTAT & SPI_FIFOSTAT_TXEMPTY_MASK))
|
||||
{
|
||||
}
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
/* check params */
|
||||
assert(
|
||||
!((NULL == base) || (NULL == handle) || (NULL == xfer) || ((NULL == xfer->txData) && (NULL == xfer->rxData))));
|
||||
if ((NULL == base) || (NULL == handle) || (NULL == xfer) || ((NULL == xfer->txData) && (NULL == xfer->rxData)))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* dataSize (in bytes) is not aligned to 16bit (2B) transfer */
|
||||
assert(!((handle->dataWidth > kSPI_Data8Bits) && (xfer->dataSize & 0x1)));
|
||||
if ((handle->dataWidth > kSPI_Data8Bits) && (xfer->dataSize & 0x1))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Check if SPI is busy */
|
||||
if (handle->state == kStatus_SPI_Busy)
|
||||
{
|
||||
return kStatus_SPI_Busy;
|
||||
}
|
||||
|
||||
/* Set the handle information */
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
/* set count */
|
||||
handle->txRemainingBytes = xfer->txData ? xfer->dataSize : 0;
|
||||
handle->rxRemainingBytes = xfer->rxData ? xfer->dataSize : 0;
|
||||
handle->totalByteCount = xfer->dataSize;
|
||||
/* other options */
|
||||
handle->toReceiveCount = 0;
|
||||
handle->configFlags = xfer->configFlags;
|
||||
/* Set the SPI state to busy */
|
||||
handle->state = kStatus_SPI_Busy;
|
||||
/* clear FIFOs when transfer starts */
|
||||
base->FIFOCFG |= SPI_FIFOCFG_EMPTYTX_MASK | SPI_FIFOCFG_EMPTYRX_MASK;
|
||||
base->FIFOSTAT |= SPI_FIFOSTAT_TXERR_MASK | SPI_FIFOSTAT_RXERR_MASK;
|
||||
/* enable generating txIRQ and rxIRQ, first transfer is fired by empty txFIFO */
|
||||
base->FIFOINTENSET |= SPI_FIFOINTENSET_TXLVL_MASK | SPI_FIFOINTENSET_RXLVL_MASK;
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Catch when there is not an active transfer. */
|
||||
if (handle->state != kStatus_SPI_Busy)
|
||||
{
|
||||
*count = 0;
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->totalByteCount - handle->rxRemainingBytes;
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
/* Disable interrupt requests*/
|
||||
base->FIFOINTENSET &= ~(SPI_FIFOINTENSET_TXLVL_MASK | SPI_FIFOINTENSET_RXLVL_MASK);
|
||||
/* Empty FIFOs */
|
||||
base->FIFOCFG |= SPI_FIFOCFG_EMPTYTX_MASK | SPI_FIFOCFG_EMPTYRX_MASK;
|
||||
|
||||
handle->state = kStatus_SPI_Idle;
|
||||
handle->txRemainingBytes = 0;
|
||||
handle->rxRemainingBytes = 0;
|
||||
}
|
||||
|
||||
static void SPI_TransferHandleIRQInternal(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint32_t tx_ctrl = 0, last_ctrl = 0, tmp32;
|
||||
bool loopContinue;
|
||||
uint32_t fifoDepth;
|
||||
|
||||
/* check params */
|
||||
assert((NULL != base) && (NULL != handle) && ((NULL != handle->txData) || (NULL != handle->rxData)));
|
||||
|
||||
fifoDepth = SPI_FIFO_DEPTH(base);
|
||||
/* select slave to talk with */
|
||||
tx_ctrl |= (SPI_DEASSERT_ALL & SPI_ASSERTNUM_SSEL(handle->sselNum));
|
||||
/* set width of data */
|
||||
tx_ctrl |= SPI_FIFOWR_LEN(handle->dataWidth);
|
||||
/* end of transfer */
|
||||
last_ctrl |= (handle->configFlags & (uint32_t)kSPI_FrameAssert) ? (uint32_t)kSPI_FrameAssert : 0;
|
||||
/* delay end of transfer */
|
||||
last_ctrl |= (handle->configFlags & (uint32_t)kSPI_FrameDelay) ? (uint32_t)kSPI_FrameDelay : 0;
|
||||
do
|
||||
{
|
||||
loopContinue = false;
|
||||
|
||||
/* rxFIFO is not empty */
|
||||
if (base->FIFOSTAT & SPI_FIFOSTAT_RXNOTEMPTY_MASK)
|
||||
{
|
||||
tmp32 = base->FIFORD;
|
||||
/* rxBuffer is not empty */
|
||||
if (handle->rxRemainingBytes)
|
||||
{
|
||||
/* low byte must go first */
|
||||
*(handle->rxData++) = tmp32;
|
||||
handle->rxRemainingBytes--;
|
||||
/* read 16 bits at once */
|
||||
if (handle->dataWidth > kSPI_Data8Bits)
|
||||
{
|
||||
*(handle->rxData++) = tmp32 >> 8;
|
||||
handle->rxRemainingBytes--;
|
||||
}
|
||||
}
|
||||
/* decrease number of data expected to receive */
|
||||
handle->toReceiveCount -= 1;
|
||||
loopContinue = true;
|
||||
}
|
||||
|
||||
/* - txFIFO is not full
|
||||
* - we cannot cause rxFIFO overflow by sending more data than is the depth of FIFO
|
||||
* - txBuffer is not empty or the next 'toReceiveCount' data can fit into rxBuffer
|
||||
*/
|
||||
if ((base->FIFOSTAT & SPI_FIFOSTAT_TXNOTFULL_MASK) && (handle->toReceiveCount < fifoDepth) &&
|
||||
((handle->txRemainingBytes) ||
|
||||
(handle->rxRemainingBytes >= SPI_COUNT_TO_BYTES(handle->dataWidth, handle->toReceiveCount + 1))))
|
||||
{
|
||||
/* txBuffer is not empty */
|
||||
if (handle->txRemainingBytes)
|
||||
{
|
||||
/* low byte must go first */
|
||||
tmp32 = *(handle->txData++);
|
||||
handle->txRemainingBytes--;
|
||||
/* write 16 bit at once */
|
||||
if (handle->dataWidth > kSPI_Data8Bits)
|
||||
{
|
||||
tmp32 |= ((uint32_t)(*(handle->txData++))) << 8U;
|
||||
handle->txRemainingBytes--;
|
||||
}
|
||||
/* last transfer */
|
||||
if (!handle->txRemainingBytes)
|
||||
{
|
||||
tx_ctrl |= last_ctrl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp32 = SPI_DUMMYDATA;
|
||||
/* last transfer */
|
||||
if (handle->rxRemainingBytes == SPI_COUNT_TO_BYTES(handle->dataWidth, handle->toReceiveCount + 1))
|
||||
{
|
||||
tx_ctrl |= last_ctrl;
|
||||
}
|
||||
}
|
||||
/* send data */
|
||||
tmp32 = tx_ctrl | tmp32;
|
||||
base->FIFOWR = tmp32;
|
||||
/* increase number of expected data to receive */
|
||||
handle->toReceiveCount += 1;
|
||||
loopContinue = true;
|
||||
}
|
||||
} while (loopContinue);
|
||||
}
|
||||
|
||||
void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert((NULL != base) && (NULL != handle));
|
||||
|
||||
/* IRQ behaviour:
|
||||
* - first interrupt is triggered by empty txFIFO. The transfer function
|
||||
* then tries empty rxFIFO and fill txFIFO interleaved that results to
|
||||
* strategy to process as many items as possible.
|
||||
* - the next IRQs can be:
|
||||
* rxIRQ from nonempty rxFIFO which requires to empty rxFIFO.
|
||||
* txIRQ from empty txFIFO which requires to refill txFIFO.
|
||||
* - last interrupt is triggered by empty txFIFO. The last state is
|
||||
* known by empty rxBuffer and txBuffer. If there is nothing to receive
|
||||
* or send - both operations have been finished and interrupts can be
|
||||
* disabled.
|
||||
*/
|
||||
|
||||
/* Data to send or read or expected to receive */
|
||||
if ((handle->txRemainingBytes) || (handle->rxRemainingBytes) || (handle->toReceiveCount))
|
||||
{
|
||||
/* Transmit or receive data */
|
||||
SPI_TransferHandleIRQInternal(base, handle);
|
||||
/* No data to send or read or receive. Transfer ends. Set txTrigger to 0 level and
|
||||
* enable txIRQ to confirm when txFIFO becomes empty */
|
||||
if ((!handle->txRemainingBytes) && (!handle->rxRemainingBytes) && (!handle->toReceiveCount))
|
||||
{
|
||||
base->FIFOTRIG = base->FIFOTRIG & (~SPI_FIFOTRIG_TXLVL_MASK);
|
||||
base->FIFOINTENSET |= SPI_FIFOINTENSET_TXLVL_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t rxRemainingCount = SPI_BYTES_TO_COUNT(handle->dataWidth, handle->rxRemainingBytes);
|
||||
/* If, there are no data to send or rxFIFO is already filled with necessary number of dummy data,
|
||||
* disable txIRQ. From this point only rxIRQ is used to receive data without any transmission */
|
||||
if ((!handle->txRemainingBytes) && (rxRemainingCount <= handle->toReceiveCount))
|
||||
{
|
||||
base->FIFOINTENCLR = SPI_FIFOINTENCLR_TXLVL_MASK;
|
||||
}
|
||||
/* Nothing to receive or transmit, but we still have pending data which are bellow rxLevel.
|
||||
* Cannot clear rxFIFO, txFIFO might be still active */
|
||||
if (rxRemainingCount == 0)
|
||||
{
|
||||
if ((handle->txRemainingBytes == 0) && (handle->toReceiveCount != 0) &&
|
||||
(handle->toReceiveCount < SPI_FIFOTRIG_RXLVL_GET(base) + 1))
|
||||
{
|
||||
base->FIFOTRIG =
|
||||
(base->FIFOTRIG & (~SPI_FIFOTRIG_RXLVL_MASK)) | SPI_FIFOTRIG_RXLVL(handle->toReceiveCount - 1);
|
||||
}
|
||||
}
|
||||
/* Expected to receive less data than rxLevel value, we have to update rxLevel */
|
||||
else
|
||||
{
|
||||
if (rxRemainingCount < (SPI_FIFOTRIG_RXLVL_GET(base) + 1))
|
||||
{
|
||||
base->FIFOTRIG =
|
||||
(base->FIFOTRIG & (~SPI_FIFOTRIG_RXLVL_MASK)) | SPI_FIFOTRIG_RXLVL(rxRemainingCount - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Empty txFIFO is confirmed. Disable IRQs and restore triggers values */
|
||||
base->FIFOINTENCLR = SPI_FIFOINTENCLR_RXLVL_MASK | SPI_FIFOINTENCLR_TXLVL_MASK;
|
||||
base->FIFOTRIG = (base->FIFOTRIG & (~(SPI_FIFOTRIG_RXLVL_MASK | SPI_FIFOTRIG_RXLVL_MASK))) |
|
||||
SPI_FIFOTRIG_RXLVL(handle->rxWatermark) | SPI_FIFOTRIG_TXLVL(handle->txWatermark);
|
||||
/* set idle state and call user callback */
|
||||
handle->state = kStatus_SPI_Idle;
|
||||
if (handle->callback)
|
||||
{
|
||||
(handle->callback)(base, handle, handle->state, handle->userData);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
* 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 tom 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_SPI_H_
|
||||
#define _FSL_SPI_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup spi_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief USART driver version 2.0.0. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
#define SPI_DUMMYDATA (0xFFFF)
|
||||
#define SPI_DATA(n) (((uint32_t)(n)) & 0xFFFF)
|
||||
#define SPI_CTRLMASK (0xFFFF0000)
|
||||
|
||||
#define SPI_ASSERTNUM_SSEL(n) ((~(1U << ((n) + 16))) & 0xF0000)
|
||||
#define SPI_DEASSERTNUM_SSEL(n) (1U << ((n) + 16))
|
||||
#define SPI_DEASSERT_ALL (0xF0000)
|
||||
|
||||
#define SPI_FIFOWR_FLAGS_MASK (~(SPI_DEASSERT_ALL | SPI_FIFOWR_TXDATA_MASK | SPI_FIFOWR_LEN_MASK))
|
||||
|
||||
#define SPI_FIFOTRIG_TXLVL_GET(base) (((base)->FIFOTRIG & SPI_FIFOTRIG_TXLVL_MASK) >> SPI_FIFOTRIG_TXLVL_SHIFT)
|
||||
#define SPI_FIFOTRIG_RXLVL_GET(base) (((base)->FIFOTRIG & SPI_FIFOTRIG_RXLVL_MASK) >> SPI_FIFOTRIG_RXLVL_SHIFT)
|
||||
|
||||
/*! @brief SPI transfer option.*/
|
||||
typedef enum _spi_xfer_option {
|
||||
kSPI_FrameDelay = (SPI_FIFOWR_EOF_MASK), /*!< Delay chip select */
|
||||
kSPI_FrameAssert = (SPI_FIFOWR_EOT_MASK), /*!< When transfer ends, assert chip select */
|
||||
} spi_xfer_option_t;
|
||||
|
||||
/*! @brief SPI data shifter direction options.*/
|
||||
typedef enum _spi_shift_direction {
|
||||
kSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit. */
|
||||
kSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. */
|
||||
} spi_shift_direction_t;
|
||||
|
||||
/*! @brief SPI clock polarity configuration.*/
|
||||
typedef enum _spi_clock_polarity {
|
||||
kSPI_ClockPolarityActiveHigh = 0x0U, /*!< Active-high SPI clock (idles low). */
|
||||
kSPI_ClockPolarityActiveLow /*!< Active-low SPI clock (idles high). */
|
||||
} spi_clock_polarity_t;
|
||||
|
||||
/*! @brief SPI clock phase configuration.*/
|
||||
typedef enum _spi_clock_phase {
|
||||
kSPI_ClockPhaseFirstEdge = 0x0U, /*!< First edge on SCK occurs at the middle of the first
|
||||
* cycle of a data transfer. */
|
||||
kSPI_ClockPhaseSecondEdge /*!< First edge on SCK occurs at the start of the
|
||||
* first cycle of a data transfer. */
|
||||
} spi_clock_phase_t;
|
||||
|
||||
/*! @brief txFIFO watermark values */
|
||||
typedef enum _spi_txfifo_watermark {
|
||||
kSPI_TxFifo0 = 0, /*!< SPI tx watermark is empty */
|
||||
kSPI_TxFifo1 = 1, /*!< SPI tx watermark at 1 item */
|
||||
kSPI_TxFifo2 = 2, /*!< SPI tx watermark at 2 items */
|
||||
kSPI_TxFifo3 = 3, /*!< SPI tx watermark at 3 items */
|
||||
kSPI_TxFifo4 = 4, /*!< SPI tx watermark at 4 items */
|
||||
kSPI_TxFifo5 = 5, /*!< SPI tx watermark at 5 items */
|
||||
kSPI_TxFifo6 = 6, /*!< SPI tx watermark at 6 items */
|
||||
kSPI_TxFifo7 = 7, /*!< SPI tx watermark at 7 items */
|
||||
} spi_txfifo_watermark_t;
|
||||
|
||||
/*! @brief rxFIFO watermark values */
|
||||
typedef enum _spi_rxfifo_watermark {
|
||||
kSPI_RxFifo1 = 0, /*!< SPI rx watermark at 1 item */
|
||||
kSPI_RxFifo2 = 1, /*!< SPI rx watermark at 2 items */
|
||||
kSPI_RxFifo3 = 2, /*!< SPI rx watermark at 3 items */
|
||||
kSPI_RxFifo4 = 3, /*!< SPI rx watermark at 4 items */
|
||||
kSPI_RxFifo5 = 4, /*!< SPI rx watermark at 5 items */
|
||||
kSPI_RxFifo6 = 5, /*!< SPI rx watermark at 6 items */
|
||||
kSPI_RxFifo7 = 6, /*!< SPI rx watermark at 7 items */
|
||||
kSPI_RxFifo8 = 7, /*!< SPI rx watermark at 8 items */
|
||||
} spi_rxfifo_watermark_t;
|
||||
|
||||
/*! @brief Transfer data width */
|
||||
typedef enum _spi_data_width {
|
||||
kSPI_Data4Bits = 3, /*!< 4 bits data width */
|
||||
kSPI_Data5Bits = 4, /*!< 5 bits data width */
|
||||
kSPI_Data6Bits = 5, /*!< 6 bits data width */
|
||||
kSPI_Data7Bits = 6, /*!< 7 bits data width */
|
||||
kSPI_Data8Bits = 7, /*!< 8 bits data width */
|
||||
kSPI_Data9Bits = 8, /*!< 9 bits data width */
|
||||
kSPI_Data10Bits = 9, /*!< 10 bits data width */
|
||||
kSPI_Data11Bits = 10, /*!< 11 bits data width */
|
||||
kSPI_Data12Bits = 11, /*!< 12 bits data width */
|
||||
kSPI_Data13Bits = 12, /*!< 13 bits data width */
|
||||
kSPI_Data14Bits = 13, /*!< 14 bits data width */
|
||||
kSPI_Data15Bits = 14, /*!< 15 bits data width */
|
||||
kSPI_Data16Bits = 15, /*!< 16 bits data width */
|
||||
} spi_data_width_t;
|
||||
|
||||
/*! @brief Slave select */
|
||||
typedef enum _spi_ssel {
|
||||
kSPI_Ssel0 = 0, /*!< Slave select 0 */
|
||||
kSPI_Ssel1 = 1, /*!< Slave select 1 */
|
||||
kSPI_Ssel2 = 2, /*!< Slave select 2 */
|
||||
kSPI_Ssel3 = 3, /*!< Slave select 3 */
|
||||
} spi_ssel_t;
|
||||
|
||||
/*! @brief SPI master user configure structure.*/
|
||||
typedef struct _spi_master_config
|
||||
{
|
||||
bool enableLoopback; /*!< Enable loopback for test purpose */
|
||||
bool enableMaster; /*!< Enable SPI at initialization time */
|
||||
spi_clock_polarity_t polarity; /*!< Clock polarity */
|
||||
spi_clock_phase_t phase; /*!< Clock phase */
|
||||
spi_shift_direction_t direction; /*!< MSB or LSB */
|
||||
uint32_t baudRate_Bps; /*!< Baud Rate for SPI in Hz */
|
||||
spi_data_width_t dataWidth; /*!< Width of the data */
|
||||
spi_ssel_t sselNum; /*!< Slave select number */
|
||||
spi_txfifo_watermark_t txWatermark; /*!< txFIFO watermark */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< rxFIFO watermark */
|
||||
} spi_master_config_t;
|
||||
|
||||
/*! @brief SPI slave user configure structure.*/
|
||||
typedef struct _spi_slave_config
|
||||
{
|
||||
bool enableSlave; /*!< Enable SPI at initialization time */
|
||||
spi_clock_polarity_t polarity; /*!< Clock polarity */
|
||||
spi_clock_phase_t phase; /*!< Clock phase */
|
||||
spi_shift_direction_t direction; /*!< MSB or LSB */
|
||||
spi_data_width_t dataWidth; /*!< Width of the data */
|
||||
spi_txfifo_watermark_t txWatermark; /*!< txFIFO watermark */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< rxFIFO watermark */
|
||||
} spi_slave_config_t;
|
||||
|
||||
/*! @brief SPI transfer status.*/
|
||||
enum _spi_status
|
||||
{
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_LPC_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_LPC_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_LPC_SPI, 2), /*!< SPI error */
|
||||
kStatus_SPI_BaudrateNotSupport =
|
||||
MAKE_STATUS(kStatusGroup_LPC_SPI, 3) /*!< Baudrate is not support in current clock source */
|
||||
};
|
||||
|
||||
/*! @brief SPI interrupt sources.*/
|
||||
enum _spi_interrupt_enable
|
||||
{
|
||||
kSPI_RxLvlIrq = SPI_FIFOINTENSET_RXLVL_MASK, /*!< Rx level interrupt */
|
||||
kSPI_TxLvlIrq = SPI_FIFOINTENSET_TXLVL_MASK, /*!< Tx level interrupt */
|
||||
};
|
||||
|
||||
/*! @brief SPI status flags.*/
|
||||
enum _spi_statusflags
|
||||
{
|
||||
kSPI_TxEmptyFlag = SPI_FIFOSTAT_TXEMPTY_MASK, /*!< txFifo is empty */
|
||||
kSPI_TxNotFullFlag = SPI_FIFOSTAT_TXNOTFULL_MASK, /*!< txFifo is not full */
|
||||
kSPI_RxNotEmptyFlag = SPI_FIFOSTAT_RXNOTEMPTY_MASK, /*!< rxFIFO is not empty */
|
||||
kSPI_RxFullFlag = SPI_FIFOSTAT_RXFULL_MASK, /*!< rxFIFO is full */
|
||||
};
|
||||
|
||||
/*! @brief SPI transfer structure */
|
||||
typedef struct _spi_transfer
|
||||
{
|
||||
uint8_t *txData; /*!< Send buffer */
|
||||
uint8_t *rxData; /*!< Receive buffer */
|
||||
uint32_t configFlags; /*!< Additional option to control transfer */
|
||||
size_t dataSize; /*!< Transfer bytes */
|
||||
} spi_transfer_t;
|
||||
|
||||
/*! @brief Internal configuration structure used in 'spi' and 'spi_dma' driver */
|
||||
typedef struct _spi_config
|
||||
{
|
||||
spi_data_width_t dataWidth;
|
||||
spi_ssel_t sselNum;
|
||||
} spi_config_t;
|
||||
|
||||
/*! @brief Master handle type */
|
||||
typedef struct _spi_master_handle spi_master_handle_t;
|
||||
|
||||
/*! @brief Slave handle type */
|
||||
typedef spi_master_handle_t spi_slave_handle_t;
|
||||
|
||||
/*! @brief SPI master callback for finished transmit */
|
||||
typedef void (*spi_master_callback_t)(SPI_Type *base, spi_master_handle_t *handle, status_t status, void *userData);
|
||||
|
||||
/*! @brief SPI slave callback for finished transmit */
|
||||
typedef void (*spi_slave_callback_t)(SPI_Type *base, spi_slave_handle_t *handle, status_t status, void *userData);
|
||||
|
||||
/*! @brief SPI transfer handle structure */
|
||||
struct _spi_master_handle
|
||||
{
|
||||
uint8_t *volatile txData; /*!< Transfer buffer */
|
||||
uint8_t *volatile rxData; /*!< Receive buffer */
|
||||
volatile size_t txRemainingBytes; /*!< Number of data to be transmitted [in bytes] */
|
||||
volatile size_t rxRemainingBytes; /*!< Number of data to be received [in bytes] */
|
||||
volatile size_t toReceiveCount; /*!< Receive data remaining in bytes */
|
||||
size_t totalByteCount; /*!< A number of transfer bytes */
|
||||
volatile uint32_t state; /*!< SPI internal state */
|
||||
spi_master_callback_t callback; /*!< SPI callback */
|
||||
void *userData; /*!< Callback parameter */
|
||||
uint8_t dataWidth; /*!< Width of the data [Valid values: 1 to 16] */
|
||||
uint8_t sselNum; /*!< Slave select number to be asserted when transferring data [Valid values: 0 to 3] */
|
||||
uint32_t configFlags; /*!< Additional option to control transfer */
|
||||
spi_txfifo_watermark_t txWatermark; /*!< txFIFO watermark */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< rxFIFO watermark */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Sets the SPI master configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
|
||||
* User may use the initialized structure unchanged in SPI_MasterInit(), or modify
|
||||
* some fields of the structure before calling SPI_MasterInit(). After calling this API,
|
||||
* the master is ready to transfer.
|
||||
* Example:
|
||||
@code
|
||||
spi_master_config_t config;
|
||||
SPI_MasterGetDefaultConfig(&config);
|
||||
@endcode
|
||||
*
|
||||
* @param config pointer to master config structure
|
||||
*/
|
||||
void SPI_MasterGetDefaultConfig(spi_master_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Initializes the SPI with master configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch, or be set with default
|
||||
* values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
@code
|
||||
spi_master_config_t config = {
|
||||
.baudRate_Bps = 400000,
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
@endcode
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param config pointer to master configuration structure
|
||||
* @param srcClock_Hz Source clock frequency.
|
||||
*/
|
||||
status_t SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz);
|
||||
|
||||
/*!
|
||||
* @brief Sets the SPI slave configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
|
||||
* Modify some fields of the structure before calling SPI_SlaveInit().
|
||||
* Example:
|
||||
@code
|
||||
spi_slave_config_t config;
|
||||
SPI_SlaveGetDefaultConfig(&config);
|
||||
@endcode
|
||||
*
|
||||
* @param config pointer to slave configuration structure
|
||||
*/
|
||||
void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Initializes the SPI with slave configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch or be set with
|
||||
* default values by SPI_SlaveGetDefaultConfig().
|
||||
* After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
@code
|
||||
spi_slave_config_t config = {
|
||||
.polarity = flexSPIClockPolarity_ActiveHigh;
|
||||
.phase = flexSPIClockPhase_FirstEdge;
|
||||
.direction = flexSPIMsbFirst;
|
||||
...
|
||||
};
|
||||
SPI_SlaveInit(SPI0, &config);
|
||||
@endcode
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param config pointer to slave configuration structure
|
||||
*/
|
||||
status_t SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief De-initializes the SPI.
|
||||
*
|
||||
* Calling this API resets the SPI module, gates the SPI clock.
|
||||
* The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
*/
|
||||
void SPI_Deinit(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Enable or disable the SPI Master or Slave
|
||||
* @param base SPI base pointer
|
||||
* @param enable or disable ( true = enable, false = disable)
|
||||
*/
|
||||
static inline void SPI_Enable(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->CFG |= SPI_CFG_ENABLE_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->CFG &= ~SPI_CFG_ENABLE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Status
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Gets the status flag.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @return SPI Status, use status flag to AND @ref _spi_statusflags could get the related status.
|
||||
*/
|
||||
static inline uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
||||
{
|
||||
assert(NULL != base);
|
||||
return base->FIFOSTAT;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Interrupts
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables the interrupt for the SPI.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param irqs SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* @arg kSPI_RxLvlIrq
|
||||
* @arg kSPI_TxLvlIrq
|
||||
*/
|
||||
static inline void SPI_EnableInterrupts(SPI_Type *base, uint32_t irqs)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->FIFOINTENSET = irqs;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables the interrupt for the SPI.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param irqs SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* @arg kSPI_RxLvlIrq
|
||||
* @arg kSPI_TxLvlIrq
|
||||
*/
|
||||
static inline void SPI_DisableInterrupts(SPI_Type *base, uint32_t irqs)
|
||||
{
|
||||
assert(NULL != base);
|
||||
base->FIFOINTENCLR = irqs;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name DMA Control
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables the DMA request from SPI txFIFO.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param enable True means enable DMA, false means disable DMA
|
||||
*/
|
||||
void SPI_EnableTxDMA(SPI_Type *base, bool enable);
|
||||
|
||||
/*!
|
||||
* @brief Enables the DMA request from SPI rxFIFO.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param enable True means enable DMA, false means disable DMA
|
||||
*/
|
||||
void SPI_EnableRxDMA(SPI_Type *base, bool enable);
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Bus Operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param baudrate_Bps baud rate needed in Hz.
|
||||
* @param srcClock_Hz SPI source clock frequency in Hz.
|
||||
*/
|
||||
status_t SPI_MasterSetBaud(SPI_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz);
|
||||
|
||||
/*!
|
||||
* @brief Writes a data into the SPI data register.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param data needs to be write.
|
||||
* @param configFlags transfer configuration options @ref spi_xfer_option_t
|
||||
*/
|
||||
void SPI_WriteData(SPI_Type *base, uint16_t data, uint32_t configFlags);
|
||||
|
||||
/*!
|
||||
* @brief Gets a data from the SPI data register.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @return Data in the register.
|
||||
*/
|
||||
static inline uint32_t SPI_ReadData(SPI_Type *base)
|
||||
{
|
||||
assert(NULL != base);
|
||||
return base->FIFORD;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* @name Transactional
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes the SPI master handle.
|
||||
*
|
||||
* This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI handle pointer.
|
||||
* @param callback Callback function.
|
||||
* @param userData User data.
|
||||
*/
|
||||
status_t SPI_MasterTransferCreateHandle(SPI_Type *base,
|
||||
spi_master_handle_t *handle,
|
||||
spi_master_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
* @brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param xfer pointer to spi_xfer_config_t structure
|
||||
* @retval kStatus_Success Successfully start a transfer.
|
||||
* @retval kStatus_InvalidArgument Input argument is invalid.
|
||||
*/
|
||||
status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Performs a non-blocking SPI interrupt transfer.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
* @param xfer pointer to spi_xfer_config_t structure
|
||||
* @retval kStatus_Success Successfully start a transfer.
|
||||
* @retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* @retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Gets the master transfer count.
|
||||
*
|
||||
* This function gets the master transfer count.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle Pointer to the spi_master_handle_t structure which stores the transfer state.
|
||||
* @param count The number of bytes transferred by using the non-blocking transaction.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count);
|
||||
|
||||
/*!
|
||||
* @brief SPI master aborts a transfer using an interrupt.
|
||||
*
|
||||
* This function aborts a transfer using an interrupt.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle Pointer to the spi_master_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Interrupts the handler for the SPI.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Initializes the SPI slave handle.
|
||||
*
|
||||
* This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI handle pointer.
|
||||
* @param callback Callback function.
|
||||
* @param userData User data.
|
||||
*/
|
||||
static inline status_t SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
void *userData)
|
||||
{
|
||||
return SPI_MasterTransferCreateHandle(base, handle, callback, userData);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Performs a non-blocking SPI slave interrupt transfer.
|
||||
*
|
||||
* @note The API returns immediately after the transfer initialization is finished.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
* @param xfer pointer to spi_xfer_config_t structure
|
||||
* @retval kStatus_Success Successfully start a transfer.
|
||||
* @retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* @retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
static inline status_t SPI_SlaveTransferNonBlocking(SPI_Type *base, spi_slave_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
return SPI_MasterTransferNonBlocking(base, handle, xfer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the slave transfer count.
|
||||
*
|
||||
* This function gets the slave transfer count.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle Pointer to the spi_master_handle_t structure which stores the transfer state.
|
||||
* @param count The number of bytes transferred by using the non-blocking transaction.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
static inline status_t SPI_SlaveTransferGetCount(SPI_Type *base, spi_slave_handle_t *handle, size_t *count)
|
||||
{
|
||||
return SPI_MasterTransferGetCount(base, (spi_master_handle_t*)handle, count);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief SPI slave aborts a transfer using an interrupt.
|
||||
*
|
||||
* This function aborts a transfer using an interrupt.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle Pointer to the spi_slave_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
static inline void SPI_SlaveTransferAbort(SPI_Type *base, spi_slave_handle_t *handle)
|
||||
{
|
||||
SPI_MasterTransferAbort(base, (spi_master_handle_t*)handle);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Interrupts a handler for the SPI slave.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_slave_handle_t structure which stores the transfer state
|
||||
*/
|
||||
static inline void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
||||
{
|
||||
SPI_MasterTransferHandleIRQ(base, handle);
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _FSL_SPI_H_*/
|
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_spi_dma.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
******************************************************************************/
|
||||
/*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
|
||||
typedef struct _spi_dma_private_handle
|
||||
{
|
||||
SPI_Type *base;
|
||||
spi_dma_handle_t *handle;
|
||||
} spi_dma_private_handle_t;
|
||||
|
||||
/*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
|
||||
enum _spi_dma_states_t
|
||||
{
|
||||
kSPI_Idle = 0x0, /*!< SPI is idle state */
|
||||
kSPI_Busy /*!< SPI is busy tranferring data. */
|
||||
};
|
||||
|
||||
typedef struct _spi_dma_txdummy
|
||||
{
|
||||
uint32_t lastWord;
|
||||
uint32_t word;
|
||||
} spi_dma_txdummy_t;
|
||||
|
||||
/*<! Private handle only used for internally. */
|
||||
static spi_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief SPI private function to return SPI configuration
|
||||
*
|
||||
* @param base SPI base address.
|
||||
*/
|
||||
void *SPI_GetConfig(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief DMA callback function for SPI send transfer.
|
||||
*
|
||||
* @param handle DMA handle pointer.
|
||||
* @param userData User data for DMA callback function.
|
||||
*/
|
||||
static void SPI_TxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode);
|
||||
|
||||
/*!
|
||||
* @brief DMA callback function for SPI receive transfer.
|
||||
*
|
||||
* @param handle DMA handle pointer.
|
||||
* @param userData User data for DMA callback function.
|
||||
*/
|
||||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
static spi_dma_txdummy_t s_txDummy[FSL_FEATURE_SOC_SPI_COUNT] = {0};
|
||||
static uint16_t s_rxDummy;
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#pragma data_alignment = 16
|
||||
static dma_descriptor_t s_spi_descriptor_table[FSL_FEATURE_SOC_SPI_COUNT] = {0};
|
||||
#elif defined(__CC_ARM)
|
||||
__attribute__((aligned(16))) static dma_descriptor_t s_spi_descriptor_table[FSL_FEATURE_SOC_SPI_COUNT] = {0};
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((aligned(16))) static dma_descriptor_t s_spi_descriptor_table[FSL_FEATURE_SOC_SPI_COUNT] = {0};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
static void XferToFifoWR(spi_transfer_t *xfer, uint32_t *fifowr)
|
||||
{
|
||||
*fifowr |= xfer->configFlags & (uint32_t)kSPI_FrameDelay ? (uint32_t)kSPI_FrameDelay : 0;
|
||||
*fifowr |= xfer->configFlags & (uint32_t)kSPI_FrameAssert ? (uint32_t)kSPI_FrameAssert : 0;
|
||||
}
|
||||
|
||||
static void SpiConfigToFifoWR(spi_config_t *config, uint32_t *fifowr)
|
||||
{
|
||||
*fifowr |= (SPI_DEASSERT_ALL & (~SPI_DEASSERTNUM_SSEL(config->sselNum)));
|
||||
/* set width of data - range asserted at entry */
|
||||
*fifowr |= SPI_FIFOWR_LEN(config->dataWidth);
|
||||
}
|
||||
|
||||
static void PrepareTxFIFO(uint32_t *fifo, uint32_t count, uint32_t ctrl)
|
||||
{
|
||||
assert(!(fifo == NULL));
|
||||
if (fifo == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* CS deassert and CS delay are relevant only for last word */
|
||||
uint32_t tx_ctrl = ctrl & (~(SPI_FIFOWR_EOT_MASK | SPI_FIFOWR_EOF_MASK));
|
||||
uint32_t i = 0;
|
||||
for (; i + 1 < count; i++)
|
||||
{
|
||||
fifo[i] = (fifo[i] & 0xFFFFU) | (tx_ctrl & 0xFFFF0000U);
|
||||
}
|
||||
if (i < count)
|
||||
{
|
||||
fifo[i] = (fifo[i] & 0xFFFFU) | (ctrl & 0xFFFF0000U);
|
||||
}
|
||||
}
|
||||
|
||||
static void SPI_SetupDummy(uint32_t *dummy, spi_transfer_t *xfer, spi_config_t *spi_config_p)
|
||||
{
|
||||
*dummy = SPI_DUMMYDATA;
|
||||
XferToFifoWR(xfer, dummy);
|
||||
SpiConfigToFifoWR(spi_config_p, dummy);
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
void *userData,
|
||||
dma_handle_t *txHandle,
|
||||
dma_handle_t *rxHandle)
|
||||
{
|
||||
int32_t instance = 0;
|
||||
|
||||
/* check 'base' */
|
||||
assert(!(NULL == base));
|
||||
if (NULL == base)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* check 'handle' */
|
||||
assert(!(NULL == handle));
|
||||
if (NULL == handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
/* Set spi base to handle */
|
||||
handle->txHandle = txHandle;
|
||||
handle->rxHandle = rxHandle;
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
/* Set SPI state to idle */
|
||||
handle->state = kSPI_Idle;
|
||||
|
||||
/* Set handle to global state */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
/* Install callback for Tx dma channel */
|
||||
DMA_SetCallback(handle->txHandle, SPI_TxDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
DMA_SetCallback(handle->rxHandle, SPI_RxDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
int32_t instance;
|
||||
status_t result = kStatus_Success;
|
||||
spi_config_t *spi_config_p;
|
||||
|
||||
assert(!((NULL == handle) || (NULL == xfer)));
|
||||
if ((NULL == handle) || (NULL == xfer))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* txData set and not aligned to sizeof(uint32_t) */
|
||||
assert(!((NULL != xfer->txData) && ((uint32_t)xfer->txData % sizeof(uint32_t))));
|
||||
if ((NULL != xfer->txData) && ((uint32_t)xfer->txData % sizeof(uint32_t)))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* rxData set and not aligned to sizeof(uint32_t) */
|
||||
assert(!((NULL != xfer->rxData) && ((uint32_t)xfer->rxData % sizeof(uint32_t))));
|
||||
if ((NULL != xfer->rxData) && ((uint32_t)xfer->rxData % sizeof(uint32_t)))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* byte size is zero or not aligned to sizeof(uint32_t) */
|
||||
assert(!((xfer->dataSize == 0) || (xfer->dataSize % sizeof(uint32_t))));
|
||||
if ((xfer->dataSize == 0) || (xfer->dataSize % sizeof(uint32_t)))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* cannot get instance from base address */
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
assert(!(instance < 0));
|
||||
if (instance < 0)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Check if the device is busy */
|
||||
if (handle->state == kSPI_Busy)
|
||||
{
|
||||
return kStatus_SPI_Busy;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t tmp;
|
||||
dma_transfer_config_t xferConfig = {0};
|
||||
spi_config_p = (spi_config_t *)SPI_GetConfig(base);
|
||||
|
||||
handle->state = kStatus_SPI_Busy;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
|
||||
/* receive */
|
||||
SPI_EnableRxDMA(base, true);
|
||||
if (xfer->rxData)
|
||||
{
|
||||
DMA_PrepareTransfer(&xferConfig, (void *)&base->FIFORD, xfer->rxData, sizeof(uint32_t), xfer->dataSize,
|
||||
kDMA_PeripheralToMemory, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
DMA_PrepareTransfer(&xferConfig, (void *)&base->FIFORD, &s_rxDummy, sizeof(uint32_t), xfer->dataSize,
|
||||
kDMA_StaticToStatic, NULL);
|
||||
}
|
||||
DMA_SubmitTransfer(handle->rxHandle, &xferConfig);
|
||||
handle->rxInProgress = true;
|
||||
DMA_StartTransfer(handle->rxHandle);
|
||||
|
||||
/* transmit */
|
||||
SPI_EnableTxDMA(base, true);
|
||||
if (xfer->txData)
|
||||
{
|
||||
tmp = 0;
|
||||
XferToFifoWR(xfer, &tmp);
|
||||
SpiConfigToFifoWR(spi_config_p, &tmp);
|
||||
PrepareTxFIFO((uint32_t *)xfer->txData, xfer->dataSize / sizeof(uint32_t), tmp);
|
||||
DMA_PrepareTransfer(&xferConfig, xfer->txData, (void *)&base->FIFOWR, sizeof(uint32_t), xfer->dataSize,
|
||||
kDMA_MemoryToPeripheral, NULL);
|
||||
DMA_SubmitTransfer(handle->txHandle, &xferConfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((xfer->configFlags & kSPI_FrameAssert) && (xfer->dataSize > sizeof(uint32_t)))
|
||||
{
|
||||
dma_xfercfg_t tmp_xfercfg = { 0 };
|
||||
tmp_xfercfg.valid = true;
|
||||
tmp_xfercfg.swtrig = true;
|
||||
tmp_xfercfg.intA = true;
|
||||
tmp_xfercfg.byteWidth = sizeof(uint32_t);
|
||||
tmp_xfercfg.srcInc = 0;
|
||||
tmp_xfercfg.dstInc = 0;
|
||||
tmp_xfercfg.transferCount = 1;
|
||||
/* create chained descriptor to transmit last word */
|
||||
SPI_SetupDummy(&s_txDummy[instance].lastWord, xfer, spi_config_p);
|
||||
DMA_CreateDescriptor(&s_spi_descriptor_table[instance], &tmp_xfercfg, &s_txDummy[instance].lastWord,
|
||||
(uint32_t *)&base->FIFOWR, NULL);
|
||||
/* use common API to setup first descriptor */
|
||||
SPI_SetupDummy(&s_txDummy[instance].word, NULL, spi_config_p);
|
||||
DMA_PrepareTransfer(&xferConfig, &s_txDummy[instance].word, (void *)&base->FIFOWR, sizeof(uint32_t),
|
||||
xfer->dataSize - sizeof(uint32_t), kDMA_StaticToStatic,
|
||||
&s_spi_descriptor_table[instance]);
|
||||
/* disable interrupts for first descriptor
|
||||
* to avoid calling callback twice */
|
||||
xferConfig.xfercfg.intA = false;
|
||||
xferConfig.xfercfg.intB = false;
|
||||
result = DMA_SubmitTransfer(handle->txHandle, &xferConfig);
|
||||
if (result != kStatus_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_SetupDummy(&s_txDummy[instance].word, xfer, spi_config_p);
|
||||
DMA_PrepareTransfer(&xferConfig, &s_txDummy[instance].word, (void *)&base->FIFOWR, sizeof(uint32_t),
|
||||
xfer->dataSize, kDMA_StaticToStatic, NULL);
|
||||
result = DMA_SubmitTransfer(handle->txHandle, &xferConfig);
|
||||
if (result != kStatus_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
handle->txInProgress = true;
|
||||
DMA_StartTransfer(handle->txHandle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* change the state */
|
||||
spiHandle->rxInProgress = false;
|
||||
|
||||
/* All finished, call the callback */
|
||||
if ((spiHandle->txInProgress == false) && (spiHandle->rxInProgress == false))
|
||||
{
|
||||
spiHandle->state = kSPI_Idle;
|
||||
if (spiHandle->callback)
|
||||
{
|
||||
(spiHandle->callback)(base, spiHandle, kStatus_Success, spiHandle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SPI_TxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* change the state */
|
||||
spiHandle->txInProgress = false;
|
||||
|
||||
/* All finished, call the callback */
|
||||
if ((spiHandle->txInProgress == false) && (spiHandle->rxInProgress == false))
|
||||
{
|
||||
spiHandle->state = kSPI_Idle;
|
||||
if (spiHandle->callback)
|
||||
{
|
||||
(spiHandle->callback)(base, spiHandle, kStatus_Success, spiHandle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
/* Stop tx transfer first */
|
||||
DMA_AbortTransfer(handle->txHandle);
|
||||
/* Then rx transfer */
|
||||
DMA_AbortTransfer(handle->rxHandle);
|
||||
|
||||
/* Set the handle state */
|
||||
handle->txInProgress = false;
|
||||
handle->rxInProgress = false;
|
||||
handle->state = kSPI_Idle;
|
||||
}
|
||||
|
||||
status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Catch when there is not an active transfer. */
|
||||
if (handle->state != kSPI_Busy)
|
||||
{
|
||||
*count = 0;
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
size_t bytes;
|
||||
|
||||
bytes = DMA_GetRemainingBytes(handle->rxHandle->base, handle->rxHandle->channel);
|
||||
|
||||
*count = handle->transferSize - bytes;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* 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 tom 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_SPI_DMA_H_
|
||||
#define _FSL_SPI_DMA_H_
|
||||
|
||||
#include "fsl_dma.h"
|
||||
#include "fsl_spi.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup spi_dma_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
typedef struct _spi_dma_handle spi_dma_handle_t;
|
||||
|
||||
/*! @brief SPI DMA callback called at the end of transfer. */
|
||||
typedef void (*spi_dma_callback_t)(SPI_Type *base, spi_dma_handle_t *handle, status_t status, void *userData);
|
||||
|
||||
/*! @brief SPI DMA transfer handle, users should not touch the content of the handle.*/
|
||||
struct _spi_dma_handle
|
||||
{
|
||||
volatile bool txInProgress; /*!< Send transfer finished */
|
||||
volatile bool rxInProgress; /*!< Receive transfer finished */
|
||||
dma_handle_t *txHandle; /*!< DMA handler for SPI send */
|
||||
dma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI tranfer */
|
||||
spi_dma_callback_t callback; /*!< Callback for SPI DMA transfer */
|
||||
void *userData; /*!< User Data for SPI DMA callback */
|
||||
uint32_t state; /*!< Internal state of SPI DMA transfer */
|
||||
size_t transferSize; /*!< Bytes need to be transfer */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* APIs
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @name DMA Transactional
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initialize the SPI master DMA handle.
|
||||
*
|
||||
* This function initializes the SPI master DMA handle which can be used for other SPI master transactional APIs.
|
||||
* Usually, for a specified SPI instance, user need only call this API once to get the initialized handle.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI handle pointer.
|
||||
* @param callback User callback function called at the end of a transfer.
|
||||
* @param userData User data for callback.
|
||||
* @param txHandle DMA handle pointer for SPI Tx, the handle shall be static allocated by users.
|
||||
* @param rxHandle DMA handle pointer for SPI Rx, the handle shall be static allocated by users.
|
||||
*/
|
||||
status_t SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
void *userData,
|
||||
dma_handle_t *txHandle,
|
||||
dma_handle_t *rxHandle);
|
||||
|
||||
/*!
|
||||
* @brief Perform a non-blocking SPI transfer using DMA.
|
||||
*
|
||||
* @note This interface returned immediately after transfer initiates, users should call
|
||||
* SPI_GetTransferStatus to poll the transfer status to check whether SPI transfer finished.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI DMA handle pointer.
|
||||
* @param xfer Pointer to dma transfer structure.
|
||||
* @retval kStatus_Success Successfully start a transfer.
|
||||
* @retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* @retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Initialize the SPI slave DMA handle.
|
||||
*
|
||||
* This function initializes the SPI slave DMA handle which can be used for other SPI master transactional APIs.
|
||||
* Usually, for a specified SPI instance, user need only call this API once to get the initialized handle.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI handle pointer.
|
||||
* @param callback User callback function called at the end of a transfer.
|
||||
* @param userData User data for callback.
|
||||
* @param txHandle DMA handle pointer for SPI Tx, the handle shall be static allocated by users.
|
||||
* @param rxHandle DMA handle pointer for SPI Rx, the handle shall be static allocated by users.
|
||||
*/
|
||||
static inline status_t SPI_SlaveTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
void *userData,
|
||||
dma_handle_t *txHandle,
|
||||
dma_handle_t *rxHandle)
|
||||
{
|
||||
return SPI_MasterTransferCreateHandleDMA(base, handle, callback, userData, txHandle, rxHandle);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Perform a non-blocking SPI transfer using DMA.
|
||||
*
|
||||
* @note This interface returned immediately after transfer initiates, users should call
|
||||
* SPI_GetTransferStatus to poll the transfer status to check whether SPI transfer finished.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI DMA handle pointer.
|
||||
* @param xfer Pointer to dma transfer structure.
|
||||
* @retval kStatus_Success Successfully start a transfer.
|
||||
* @retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* @retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
static inline status_t SPI_SlaveTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
return SPI_MasterTransferDMA(base, handle, xfer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Abort a SPI transfer using DMA.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI DMA handle pointer.
|
||||
*/
|
||||
void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Gets the master DMA transfer remaining bytes.
|
||||
*
|
||||
* This function gets the master DMA transfer remaining bytes.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle A pointer to the spi_dma_handle_t structure which stores the transfer state.
|
||||
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count);
|
||||
|
||||
/*!
|
||||
* @brief Abort a SPI transfer using DMA.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle SPI DMA handle pointer.
|
||||
*/
|
||||
static inline void SPI_SlaveTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
||||
{
|
||||
SPI_MasterTransferAbortDMA(base, handle);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets the slave DMA transfer remaining bytes.
|
||||
*
|
||||
* This function gets the slave DMA transfer remaining bytes.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle A pointer to the spi_dma_handle_t structure which stores the transfer state.
|
||||
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||
* @return status of status_t.
|
||||
*/
|
||||
static inline status_t SPI_SlaveTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
|
||||
{
|
||||
return SPI_MasterTransferGetCountDMA(base, handle, count);
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif /* _FSL_SPI_DMA_H_*/
|
|
@ -0,0 +1,667 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_usart.h"
|
||||
#include "fsl_device_registers.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
|
||||
enum _usart_transfer_states
|
||||
{
|
||||
kUSART_TxIdle, /* TX idle. */
|
||||
kUSART_TxBusy, /* TX busy. */
|
||||
kUSART_RxIdle, /* RX idle. */
|
||||
kUSART_RxBusy /* RX busy. */
|
||||
};
|
||||
|
||||
/* Array of UART IRQ number. */
|
||||
static const IRQn_Type s_usartIRQ[] = USART_IRQS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
/* Check arguments */
|
||||
assert(NULL != handle);
|
||||
|
||||
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 USART_TransferIsRxRingBufferFull(usart_handle_t *handle)
|
||||
{
|
||||
bool full;
|
||||
|
||||
/* Check arguments */
|
||||
assert(NULL != handle);
|
||||
|
||||
if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
|
||||
{
|
||||
full = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
full = false;
|
||||
}
|
||||
return full;
|
||||
}
|
||||
|
||||
void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert(NULL != base);
|
||||
assert(NULL != handle);
|
||||
assert(NULL != ringBuffer);
|
||||
|
||||
/* Setup the ringbuffer address */
|
||||
handle->rxRingBuffer = ringBuffer;
|
||||
handle->rxRingBufferSize = ringBufferSize;
|
||||
handle->rxRingBufferHead = 0U;
|
||||
handle->rxRingBufferTail = 0U;
|
||||
/* ring buffer is ready we can start receiving data */
|
||||
base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
|
||||
}
|
||||
|
||||
void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert(NULL != base);
|
||||
assert(NULL != handle);
|
||||
|
||||
if (handle->rxState == kUSART_RxIdle)
|
||||
{
|
||||
base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENCLR_RXERR_MASK;
|
||||
}
|
||||
handle->rxRingBuffer = NULL;
|
||||
handle->rxRingBufferSize = 0U;
|
||||
handle->rxRingBufferHead = 0U;
|
||||
handle->rxRingBufferTail = 0U;
|
||||
}
|
||||
|
||||
status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* check arguments */
|
||||
assert(!((NULL == base) || (NULL == config) || (0 == srcClock_Hz)));
|
||||
if ((NULL == base) || (NULL == config) || (0 == srcClock_Hz))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* initialize flexcomm to USART mode */
|
||||
result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_USART);
|
||||
if (kStatus_Success != result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* setup baudrate */
|
||||
result = USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
|
||||
if (kStatus_Success != result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (config->enableTx)
|
||||
{
|
||||
/* empty and enable txFIFO */
|
||||
base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK | USART_FIFOCFG_ENABLETX_MASK;
|
||||
/* setup trigger level */
|
||||
base->FIFOTRIG &= ~(USART_FIFOTRIG_TXLVL_MASK);
|
||||
base->FIFOTRIG |= USART_FIFOTRIG_TXLVL(config->txWatermark);
|
||||
/* enable trigger interrupt */
|
||||
base->FIFOTRIG |= USART_FIFOTRIG_TXLVLENA_MASK;
|
||||
}
|
||||
|
||||
/* empty and enable rxFIFO */
|
||||
if (config->enableRx)
|
||||
{
|
||||
base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK | USART_FIFOCFG_ENABLERX_MASK;
|
||||
/* setup trigger level */
|
||||
base->FIFOTRIG &= ~(USART_FIFOTRIG_RXLVL_MASK);
|
||||
base->FIFOTRIG |= USART_FIFOTRIG_RXLVL(config->rxWatermark);
|
||||
/* enable trigger interrupt */
|
||||
base->FIFOTRIG |= USART_FIFOTRIG_RXLVLENA_MASK;
|
||||
}
|
||||
/* setup configuration and enable USART */
|
||||
base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |
|
||||
USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) | USART_CFG_ENABLE_MASK;
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void USART_Deinit(USART_Type *base)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert(NULL != base);
|
||||
/* Disable interrupts, disable dma requests, disable peripheral */
|
||||
base->FIFOINTENCLR = USART_FIFOINTENCLR_TXERR_MASK | USART_FIFOINTENCLR_RXERR_MASK | USART_FIFOINTENCLR_TXLVL_MASK | USART_FIFOINTENCLR_RXLVL_MASK;
|
||||
base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK | USART_FIFOCFG_DMARX_MASK);
|
||||
base->CFG &= ~(USART_CFG_ENABLE_MASK);
|
||||
}
|
||||
|
||||
void USART_GetDefaultConfig(usart_config_t *config)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert(NULL != config);
|
||||
|
||||
/* Set always all members ! */
|
||||
config->baudRate_Bps = 115200U;
|
||||
config->parityMode = kUSART_ParityDisabled;
|
||||
config->stopBitCount = kUSART_OneStopBit;
|
||||
config->bitCountPerChar = kUSART_8BitsPerChar;
|
||||
config->loopback = false;
|
||||
config->enableRx = false;
|
||||
config->enableTx = false;
|
||||
config->txWatermark = kUSART_TxFifo0;
|
||||
config->rxWatermark = kUSART_RxFifo1;
|
||||
}
|
||||
|
||||
status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
|
||||
{
|
||||
uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;
|
||||
uint32_t osrval, brgval, diff, baudrate;
|
||||
|
||||
/* check arguments */
|
||||
assert(!((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz)));
|
||||
if ((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
for (osrval = best_osrval; osrval >= 4; osrval--)
|
||||
{
|
||||
brgval = (srcClock_Hz / ((osrval + 1) * baudrate_Bps)) - 1;
|
||||
if (brgval > 0xFFFF)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
baudrate = srcClock_Hz / ((osrval + 1) * (brgval + 1));
|
||||
diff = baudrate_Bps < baudrate ? baudrate - baudrate_Bps : baudrate_Bps - baudrate;
|
||||
if (diff < best_diff)
|
||||
{
|
||||
best_diff = diff;
|
||||
best_osrval = osrval;
|
||||
best_brgval = brgval;
|
||||
}
|
||||
}
|
||||
|
||||
/* value over range */
|
||||
if (best_brgval > 0xFFFF)
|
||||
{
|
||||
return kStatus_USART_BaudrateNotSupport;
|
||||
}
|
||||
|
||||
base->OSR = best_osrval;
|
||||
base->BRG = best_brgval;
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert(!((NULL == base) || (NULL == data)));
|
||||
if ((NULL == base) || (NULL == data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* Check whether txFIFO is enabled */
|
||||
if (!(base->FIFOCFG & USART_FIFOCFG_ENABLETX_MASK))
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (; length > 0; length--)
|
||||
{
|
||||
/* Loop until txFIFO get some space for new data */
|
||||
while (!(base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
|
||||
{
|
||||
}
|
||||
base->FIFOWR = *data;
|
||||
data++;
|
||||
}
|
||||
/* Wait to finish transfer */
|
||||
while (!(base->FIFOSTAT & USART_FIFOSTAT_TXEMPTY_MASK))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
/* check arguments */
|
||||
assert(!((NULL == base) || (NULL == data)));
|
||||
if ((NULL == base) || (NULL == data))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Check whether rxFIFO is enabled */
|
||||
if (!(base->FIFOCFG & USART_FIFOCFG_ENABLERX_MASK))
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
for (; length > 0; length--)
|
||||
{
|
||||
/* loop until rxFIFO have some data to read */
|
||||
while (!(base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))
|
||||
{
|
||||
}
|
||||
/* check receive status */
|
||||
status = base->STAT;
|
||||
if (status & USART_STAT_FRAMERRINT_MASK)
|
||||
{
|
||||
return kStatus_USART_FramingError;
|
||||
}
|
||||
if (status & USART_STAT_PARITYERRINT_MASK)
|
||||
{
|
||||
return kStatus_USART_ParityError;
|
||||
}
|
||||
if (status & USART_STAT_RXNOISEINT_MASK)
|
||||
{
|
||||
return kStatus_USART_NoiseError;
|
||||
}
|
||||
/* check rxFIFO status */
|
||||
if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)
|
||||
{
|
||||
return kStatus_USART_RxError;
|
||||
}
|
||||
*data = base->FIFORD;
|
||||
data++;
|
||||
}
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t USART_TransferCreateHandle(USART_Type *base,
|
||||
usart_handle_t *handle,
|
||||
usart_transfer_callback_t callback,
|
||||
void *userData)
|
||||
{
|
||||
int32_t instance = 0;
|
||||
|
||||
/* Check 'base' */
|
||||
assert(!((NULL == base) || (NULL == handle)));
|
||||
if ((NULL == base) || (NULL == handle))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
/* Set the TX/RX state. */
|
||||
handle->rxState = kUSART_RxIdle;
|
||||
handle->txState = kUSART_TxIdle;
|
||||
/* Set the callback and user data. */
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
handle->rxWatermark = (usart_rxfifo_watermark_t)USART_FIFOTRIG_RXLVL_GET(base);
|
||||
handle->txWatermark = (usart_txfifo_watermark_t)USART_FIFOTRIG_TXLVL_GET(base);
|
||||
|
||||
FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)(uintptr_t)USART_TransferHandleIRQ, handle);
|
||||
|
||||
/* Enable interrupt in NVIC. */
|
||||
EnableIRQ(s_usartIRQ[instance]);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
|
||||
if ((NULL == base) || (NULL == handle) || (NULL == xfer))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* Check xfer members */
|
||||
assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));
|
||||
if ((0 == xfer->dataSize) || (NULL == xfer->data))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
/* Return error if current TX busy. */
|
||||
if (kUSART_TxBusy == handle->txState)
|
||||
{
|
||||
return kStatus_USART_TxBusy;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->txData = xfer->data;
|
||||
handle->txDataSize = xfer->dataSize;
|
||||
handle->txDataSizeAll = xfer->dataSize;
|
||||
handle->txState = kUSART_TxBusy;
|
||||
/* Enable transmiter interrupt. */
|
||||
base->FIFOINTENSET |= USART_FIFOINTENSET_TXLVL_MASK;
|
||||
}
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
/* Disable interrupts */
|
||||
base->FIFOINTENSET &= ~USART_FIFOINTENSET_TXLVL_MASK;
|
||||
/* Empty txFIFO */
|
||||
base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK;
|
||||
|
||||
handle->txDataSize = 0;
|
||||
handle->txState = kUSART_TxIdle;
|
||||
}
|
||||
|
||||
status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
assert(NULL != count);
|
||||
|
||||
if (kUSART_TxIdle == handle->txState)
|
||||
{
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->txDataSizeAll - handle->txDataSize;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t USART_TransferReceiveNonBlocking(USART_Type *base,
|
||||
usart_handle_t *handle,
|
||||
usart_transfer_t *xfer,
|
||||
size_t *receivedBytes)
|
||||
{
|
||||
uint32_t i;
|
||||
/* 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;
|
||||
|
||||
/* Check arguments */
|
||||
assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
|
||||
if ((NULL == base) || (NULL == handle) || (NULL == xfer))
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* Check xfer members */
|
||||
assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));
|
||||
if ((0 == 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 (kUSART_RxBusy == handle->rxState)
|
||||
{
|
||||
return kStatus_USART_RxBusy;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesToReceive = xfer->dataSize;
|
||||
bytesCurrentReceived = 0U;
|
||||
/* If RX ring buffer is used. */
|
||||
if (handle->rxRingBuffer)
|
||||
{
|
||||
/* Disable IRQ, protect ring buffer. */
|
||||
regPrimask = DisableGlobalIRQ();
|
||||
/* How many bytes in RX ring buffer currently. */
|
||||
bytesToCopy = USART_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->rxDataSizeAll = bytesToReceive;
|
||||
handle->rxState = kUSART_RxBusy;
|
||||
}
|
||||
/* Enable IRQ if previously enabled. */
|
||||
EnableGlobalIRQ(regPrimask);
|
||||
/* Call user callback since all data are received. */
|
||||
if (0 == bytesToReceive)
|
||||
{
|
||||
if (handle->callback)
|
||||
{
|
||||
handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Ring buffer not used. */
|
||||
else
|
||||
{
|
||||
handle->rxData = xfer->data + bytesCurrentReceived;
|
||||
handle->rxDataSize = bytesToReceive;
|
||||
handle->rxDataSizeAll = bytesToReceive;
|
||||
handle->rxState = kUSART_RxBusy;
|
||||
|
||||
/* Enable RX interrupt. */
|
||||
base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK;
|
||||
}
|
||||
/* Return the how many bytes have read. */
|
||||
if (receivedBytes)
|
||||
{
|
||||
*receivedBytes = bytesCurrentReceived;
|
||||
}
|
||||
}
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
|
||||
/* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
|
||||
if (!handle->rxRingBuffer)
|
||||
{
|
||||
/* Disable interrupts */
|
||||
base->FIFOINTENSET &= ~USART_FIFOINTENSET_RXLVL_MASK;
|
||||
/* Empty rxFIFO */
|
||||
base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
|
||||
}
|
||||
|
||||
handle->rxDataSize = 0U;
|
||||
handle->rxState = kUSART_RxIdle;
|
||||
}
|
||||
|
||||
status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
assert(NULL != count);
|
||||
|
||||
if (kUSART_RxIdle == handle->rxState)
|
||||
{
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->rxDataSizeAll - handle->rxDataSize;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
|
||||
{
|
||||
/* Check arguments */
|
||||
assert((NULL != base) && (NULL != handle));
|
||||
|
||||
bool receiveEnabled = (handle->rxDataSize) || (handle->rxRingBuffer);
|
||||
bool sendEnabled = handle->txDataSize;
|
||||
|
||||
/* If RX overrun. */
|
||||
if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)
|
||||
{
|
||||
/* Clear rx error state. */
|
||||
base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
|
||||
/* clear rxFIFO */
|
||||
base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
|
||||
/* Trigger callback. */
|
||||
if (handle->callback)
|
||||
{
|
||||
handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
|
||||
}
|
||||
}
|
||||
while ((receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK)) ||
|
||||
(sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK)))
|
||||
{
|
||||
/* Receive data */
|
||||
if (receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))
|
||||
{
|
||||
/* Receive to app bufffer if app buffer is present */
|
||||
if (handle->rxDataSize)
|
||||
{
|
||||
*handle->rxData = base->FIFORD;
|
||||
handle->rxDataSize--;
|
||||
handle->rxData++;
|
||||
receiveEnabled = ((handle->rxDataSize != 0) || (handle->rxRingBuffer));
|
||||
if (!handle->rxDataSize)
|
||||
{
|
||||
if (!handle->rxRingBuffer)
|
||||
{
|
||||
base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
|
||||
}
|
||||
handle->rxState = kUSART_RxIdle;
|
||||
if (handle->callback)
|
||||
{
|
||||
handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Otherwise receive to ring buffer if ring buffer is present */
|
||||
else
|
||||
{
|
||||
if (handle->rxRingBuffer)
|
||||
{
|
||||
/* If RX ring buffer is full, trigger callback to notify over run. */
|
||||
if (USART_TransferIsRxRingBufferFull(handle))
|
||||
{
|
||||
if (handle->callback)
|
||||
{
|
||||
handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
|
||||
}
|
||||
}
|
||||
/* If ring buffer is still full after callback function, the oldest data is overrided. */
|
||||
if (USART_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->FIFORD;
|
||||
/* Increase handle->rxRingBufferHead. */
|
||||
if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
|
||||
{
|
||||
handle->rxRingBufferHead = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->rxRingBufferHead++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Send data */
|
||||
if (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
|
||||
{
|
||||
base->FIFOWR = *handle->txData;
|
||||
handle->txDataSize--;
|
||||
handle->txData++;
|
||||
sendEnabled = handle->txDataSize != 0;
|
||||
if (!sendEnabled)
|
||||
{
|
||||
base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
|
||||
handle->txState = kUSART_TxIdle;
|
||||
if (handle->callback)
|
||||
{
|
||||
handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ring buffer is not used */
|
||||
if (NULL == handle->rxRingBuffer)
|
||||
{
|
||||
/* restore if rx transfer ends and rxLevel is different from default value */
|
||||
if ((handle->rxDataSize == 0) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))
|
||||
{
|
||||
base->FIFOTRIG = (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);
|
||||
}
|
||||
/* decrease level if rx transfer is bellow */
|
||||
if ((handle->rxDataSize != 0) && (handle->rxDataSize < (USART_FIFOTRIG_RXLVL_GET(base) + 1)))
|
||||
{
|
||||
base->FIFOTRIG = (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(handle->rxDataSize - 1));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,614 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_USART_H_
|
||||
#define _FSL_USART_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup usart_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief USART driver version 2.0.0. */
|
||||
#define FSL_USART_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
#define USART_FIFOTRIG_TXLVL_GET(base) (((base)->FIFOTRIG & USART_FIFOTRIG_TXLVL_MASK) >> USART_FIFOTRIG_TXLVL_SHIFT)
|
||||
#define USART_FIFOTRIG_RXLVL_GET(base) (((base)->FIFOTRIG & USART_FIFOTRIG_RXLVL_MASK) >> USART_FIFOTRIG_RXLVL_SHIFT)
|
||||
|
||||
/*! @brief Error codes for the USART driver. */
|
||||
enum _usart_status
|
||||
{
|
||||
kStatus_USART_TxBusy = MAKE_STATUS(kStatusGroup_LPC_USART, 0), /*!< Transmitter is busy. */
|
||||
kStatus_USART_RxBusy = MAKE_STATUS(kStatusGroup_LPC_USART, 1), /*!< Receiver is busy. */
|
||||
kStatus_USART_TxIdle = MAKE_STATUS(kStatusGroup_LPC_USART, 2), /*!< USART transmitter is idle. */
|
||||
kStatus_USART_RxIdle = MAKE_STATUS(kStatusGroup_LPC_USART, 3), /*!< USART receiver is idle. */
|
||||
kStatus_USART_TxError = MAKE_STATUS(kStatusGroup_LPC_USART, 7), /*!< Error happens on txFIFO. */
|
||||
kStatus_USART_RxError = MAKE_STATUS(kStatusGroup_LPC_USART, 9), /*!< Error happens on txFIFO. */
|
||||
kStatus_USART_RxRingBufferOverrun = MAKE_STATUS(kStatusGroup_LPC_USART, 8), /*!< Error happens on rx ring buffer */
|
||||
kStatus_USART_NoiseError = MAKE_STATUS(kStatusGroup_LPC_USART, 10), /*!< USART noise error. */
|
||||
kStatus_USART_FramingError = MAKE_STATUS(kStatusGroup_LPC_USART, 11), /*!< USART framing error. */
|
||||
kStatus_USART_ParityError = MAKE_STATUS(kStatusGroup_LPC_USART, 12), /*!< USART parity error. */
|
||||
kStatus_USART_BaudrateNotSupport =
|
||||
MAKE_STATUS(kStatusGroup_LPC_USART, 13), /*!< Baudrate is not support in current clock source */
|
||||
};
|
||||
|
||||
/*! @brief USART parity mode. */
|
||||
typedef enum _usart_parity_mode {
|
||||
kUSART_ParityDisabled = 0x0U, /*!< Parity disabled */
|
||||
kUSART_ParityEven = 0x2U, /*!< Parity enabled, type even, bit setting: PE|PT = 10 */
|
||||
kUSART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */
|
||||
} usart_parity_mode_t;
|
||||
|
||||
/*! @brief USART stop bit count. */
|
||||
typedef enum _usart_stop_bit_count {
|
||||
kUSART_OneStopBit = 0U, /*!< One stop bit */
|
||||
kUSART_TwoStopBit = 1U, /*!< Two stop bits */
|
||||
} usart_stop_bit_count_t;
|
||||
|
||||
/*! @brief USART data size. */
|
||||
typedef enum _usart_data_len {
|
||||
kUSART_7BitsPerChar = 0U, /*!< Seven bit mode */
|
||||
kUSART_8BitsPerChar = 1U, /*!< Eight bit mode */
|
||||
} usart_data_len_t;
|
||||
|
||||
/*! @brief txFIFO watermark values */
|
||||
typedef enum _usart_txfifo_watermark {
|
||||
kUSART_TxFifo0 = 0, /*!< USART tx watermark is empty */
|
||||
kUSART_TxFifo1 = 1, /*!< USART tx watermark at 1 item */
|
||||
kUSART_TxFifo2 = 2, /*!< USART tx watermark at 2 items */
|
||||
kUSART_TxFifo3 = 3, /*!< USART tx watermark at 3 items */
|
||||
kUSART_TxFifo4 = 4, /*!< USART tx watermark at 4 items */
|
||||
kUSART_TxFifo5 = 5, /*!< USART tx watermark at 5 items */
|
||||
kUSART_TxFifo6 = 6, /*!< USART tx watermark at 6 items */
|
||||
kUSART_TxFifo7 = 7, /*!< USART tx watermark at 7 items */
|
||||
} usart_txfifo_watermark_t;
|
||||
|
||||
/*! @brief rxFIFO watermark values */
|
||||
typedef enum _usart_rxfifo_watermark {
|
||||
kUSART_RxFifo1 = 0, /*!< USART rx watermark at 1 item */
|
||||
kUSART_RxFifo2 = 1, /*!< USART rx watermark at 2 items */
|
||||
kUSART_RxFifo3 = 2, /*!< USART rx watermark at 3 items */
|
||||
kUSART_RxFifo4 = 3, /*!< USART rx watermark at 4 items */
|
||||
kUSART_RxFifo5 = 4, /*!< USART rx watermark at 5 items */
|
||||
kUSART_RxFifo6 = 5, /*!< USART rx watermark at 6 items */
|
||||
kUSART_RxFifo7 = 6, /*!< USART rx watermark at 7 items */
|
||||
kUSART_RxFifo8 = 7, /*!< USART rx watermark at 8 items */
|
||||
} usart_rxfifo_watermark_t;
|
||||
|
||||
/*!
|
||||
* @brief USART interrupt configuration structure, default settings all disabled.
|
||||
*/
|
||||
enum _usart_interrupt_enable
|
||||
{
|
||||
kUSART_TxErrorInterruptEnable = (USART_FIFOINTENSET_TXERR_MASK),
|
||||
kUSART_RxErrorInterruptEnable = (USART_FIFOINTENSET_RXERR_MASK),
|
||||
kUSART_TxLevelInterruptEnable = (USART_FIFOINTENSET_TXLVL_MASK),
|
||||
kUSART_RxLevelInterruptEnable = (USART_FIFOINTENSET_RXLVL_MASK),
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief USART status flags.
|
||||
*
|
||||
* This provides constants for the USART status flags for use in the USART functions.
|
||||
*/
|
||||
enum _usart_flags
|
||||
{
|
||||
kUSART_TxError = (USART_FIFOSTAT_TXERR_MASK), /*!< TXEMPT bit, sets if TX buffer is empty */
|
||||
kUSART_RxError = (USART_FIFOSTAT_RXERR_MASK), /*!< TXEMPT bit, sets if TX buffer is empty */
|
||||
kUSART_TxFifoEmptyFlag = (USART_FIFOSTAT_TXEMPTY_MASK), /*!< TXEMPT bit, sets if TX buffer is empty */
|
||||
kUSART_TxFifoNotFullFlag = (USART_FIFOSTAT_TXNOTFULL_MASK), /*!< TXEMPT bit, sets if TX buffer is not full */
|
||||
kUSART_RxFifoNotEmptyFlag = (USART_FIFOSTAT_RXNOTEMPTY_MASK), /*!< RXEMPT bit, sets if RX buffer is not empty */
|
||||
kUSART_RxFifoFullFlag = (USART_FIFOSTAT_RXFULL_MASK), /*!< RXEMPT bit, sets if RX buffer is full */
|
||||
};
|
||||
|
||||
/*! @brief USART configuration structure. */
|
||||
typedef struct _usart_config
|
||||
{
|
||||
uint32_t baudRate_Bps; /*!< USART baud rate */
|
||||
usart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */
|
||||
usart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */
|
||||
usart_data_len_t bitCountPerChar; /*!< Data length - 7 bit, 8 bit */
|
||||
bool loopback; /*!< Enable peripheral loopback */
|
||||
bool enableRx; /*!< Enable RX */
|
||||
bool enableTx; /*!< Enable TX */
|
||||
usart_txfifo_watermark_t txWatermark;/*!< txFIFO watermark */
|
||||
usart_rxfifo_watermark_t rxWatermark;/*!< rxFIFO watermark */
|
||||
} usart_config_t;
|
||||
|
||||
/*! @brief USART transfer structure. */
|
||||
typedef struct _usart_transfer
|
||||
{
|
||||
uint8_t *data; /*!< The buffer of data to be transfer.*/
|
||||
size_t dataSize; /*!< The byte count to be transfer. */
|
||||
} usart_transfer_t;
|
||||
|
||||
/* Forward declaration of the handle typedef. */
|
||||
typedef struct _usart_handle usart_handle_t;
|
||||
|
||||
/*! @brief USART transfer callback function. */
|
||||
typedef void (*usart_transfer_callback_t)(USART_Type *base, usart_handle_t *handle, status_t status, void *userData);
|
||||
|
||||
/*! @brief USART handle structure. */
|
||||
struct _usart_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. */
|
||||
|
||||
usart_transfer_callback_t callback; /*!< Callback function. */
|
||||
void *userData; /*!< USART callback function parameter.*/
|
||||
|
||||
volatile uint8_t txState; /*!< TX transfer state. */
|
||||
volatile uint8_t rxState; /*!< RX transfer state */
|
||||
|
||||
usart_txfifo_watermark_t txWatermark; /*!< txFIFO watermark */
|
||||
usart_rxfifo_watermark_t rxWatermark; /*!< rxFIFO watermark */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* _cplusplus */
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes a USART instance with user configuration structure and peripheral clock.
|
||||
*
|
||||
* This function configures the USART module with the user-defined settings. The user can configure the configuration
|
||||
* structure and also get the default configuration by using the USART_GetDefaultConfig() function.
|
||||
* Example below shows how to use this API to configure USART.
|
||||
* @code
|
||||
* usart_config_t usartConfig;
|
||||
* usartConfig.baudRate_Bps = 115200U;
|
||||
* usartConfig.parityMode = kUSART_ParityDisabled;
|
||||
* usartConfig.stopBitCount = kUSART_OneStopBit;
|
||||
* USART_Init(USART1, &usartConfig, 20000000U);
|
||||
* @endcode
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param config Pointer to user-defined configuration structure.
|
||||
* @param srcClock_Hz USART clock source frequency in HZ.
|
||||
* @retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
|
||||
* @retval kStatus_InvalidArgument USART base address is not valid
|
||||
* @retval kStatus_Success Status USART initialize succeed
|
||||
*/
|
||||
status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz);
|
||||
|
||||
/*!
|
||||
* @brief Deinitializes a USART instance.
|
||||
*
|
||||
* This function waits for TX complete, disables TX and RX, and disables the USART clock.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
*/
|
||||
void USART_Deinit(USART_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Gets the default configuration structure.
|
||||
*
|
||||
* This function initializes the USART configuration structure to a default value. The default
|
||||
* values are:
|
||||
* usartConfig->baudRate_Bps = 115200U;
|
||||
* usartConfig->parityMode = kUSART_ParityDisabled;
|
||||
* usartConfig->stopBitCount = kUSART_OneStopBit;
|
||||
* usartConfig->bitCountPerChar = kUSART_8BitsPerChar;
|
||||
* usartConfig->loopback = false;
|
||||
* usartConfig->enableTx = false;
|
||||
* usartConfig->enableRx = false;
|
||||
*
|
||||
* @param config Pointer to configuration structure.
|
||||
*/
|
||||
void USART_GetDefaultConfig(usart_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Sets the USART instance baud rate.
|
||||
*
|
||||
* This function configures the USART module baud rate. This function is used to update
|
||||
* the USART module baud rate after the USART module is initialized by the USART_Init.
|
||||
* @code
|
||||
* USART_SetBaudRate(USART1, 115200U, 20000000U);
|
||||
* @endcode
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param baudrate_Bps USART baudrate to be set.
|
||||
* @param srcClock_Hz USART clock source freqency in HZ.
|
||||
* @retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
|
||||
* @retval kStatus_Success Set baudrate succeed.
|
||||
* @retval kStatus_InvalidArgument One or more arguments are invalid.
|
||||
*/
|
||||
status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz);
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Status
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get USART status flags.
|
||||
*
|
||||
* This function get all USART status flags, the flags are returned as the logical
|
||||
* OR value of the enumerators @ref _usart_flags. To check a specific status,
|
||||
* compare the return value with enumerators in @ref _usart_flags.
|
||||
* For example, to check whether the TX is empty:
|
||||
* @code
|
||||
* if (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(USART1))
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @return USART status flags which are ORed by the enumerators in the _usart_flags.
|
||||
*/
|
||||
static inline uint32_t USART_GetStatusFlags(USART_Type *base)
|
||||
{
|
||||
return base->FIFOSTAT;
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Interrupts
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables USART interrupts according to the provided mask.
|
||||
*
|
||||
* This function enables the USART interrupts according to the provided mask. The mask
|
||||
* is a logical OR of enumeration members. See @ref _usart_interrupt_enable.
|
||||
* For example, to enable TX empty interrupt and RX full interrupt:
|
||||
* @code
|
||||
* USART_EnableInterrupts(USART1, kUSART_TxLevelInterruptEnable | kUSART_RxLevelInterruptEnable);
|
||||
* @endcode
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param mask The interrupts to enable. Logical OR of @ref _usart_interrupt_enable.
|
||||
*/
|
||||
static inline void USART_EnableInterrupts(USART_Type *base, uint32_t mask)
|
||||
{
|
||||
base->FIFOINTENSET = mask & 0xF;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables USART interrupts according to a provided mask.
|
||||
*
|
||||
* This function disables the USART interrupts according to a provided mask. The mask
|
||||
* is a logical OR of enumeration members. See @ref _usart_interrupt_enable.
|
||||
* This example shows how to disable the TX empty interrupt and RX full interrupt:
|
||||
* @code
|
||||
* USART_DisableInterrupts(USART1, kUSART_TxLevelInterruptEnable | kUSART_RxLevelInterruptEnable);
|
||||
* @endcode
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param mask The interrupts to disable. Logical OR of @ref _usart_interrupt_enable.
|
||||
*/
|
||||
static inline void USART_DisableInterrupts(USART_Type *base, uint32_t mask)
|
||||
{
|
||||
base->FIFOINTENSET = ~(mask & 0xF);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable DMA for Tx
|
||||
*/
|
||||
static inline void USART_EnableTxDMA(USART_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->FIFOCFG |= USART_FIFOCFG_DMATX_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Enable DMA for Rx
|
||||
*/
|
||||
static inline void USART_EnableRxDMA(USART_Type *base, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
base->FIFOCFG |= USART_FIFOCFG_DMARX_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
base->FIFOCFG &= ~(USART_FIFOCFG_DMARX_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Bus Operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Writes to the FIFOWR register.
|
||||
*
|
||||
* This function writes data to the txFIFO directly. The upper layer must ensure
|
||||
* that txFIFO has space for data to write before calling this function.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param data The byte to write.
|
||||
*/
|
||||
static inline void USART_WriteByte(USART_Type *base, uint8_t data)
|
||||
{
|
||||
base->FIFOWR = data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads the FIFORD register directly.
|
||||
*
|
||||
* This function reads data from the rxFIFO directly. The upper layer must
|
||||
* ensure that the rxFIFO is not empty before calling this function.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @return The byte read from USART data register.
|
||||
*/
|
||||
static inline uint8_t USART_ReadByte(USART_Type *base)
|
||||
{
|
||||
return base->FIFORD;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Writes to the TX register using a blocking method.
|
||||
*
|
||||
* This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
|
||||
* to have room and writes data to the TX buffer.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param data Start address of the data to write.
|
||||
* @param length Size of the data to write.
|
||||
*/
|
||||
void USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length);
|
||||
|
||||
/*!
|
||||
* @brief Read RX data register using a blocking method.
|
||||
*
|
||||
* This function polls the RX register, waits for the RX register to be full or for RX FIFO to
|
||||
* have data and read data from the TX register.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param data Start address of the buffer to store the received data.
|
||||
* @param length Size of the buffer.
|
||||
* @retval kStatus_USART_FramingError Receiver overrun happened while receiving data.
|
||||
* @retval kStatus_USART_ParityError Noise error happened while receiving data.
|
||||
* @retval kStatus_USART_NoiseError Framing error happened while receiving data.
|
||||
* @retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.
|
||||
* @retval kStatus_Success Successfully received all data.
|
||||
*/
|
||||
status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length);
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name Transactional
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes the USART handle.
|
||||
*
|
||||
* This function initializes the USART handle which can be used for other USART
|
||||
* transactional APIs. Usually, for a specified USART instance,
|
||||
* call this API once to get the initialized handle.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
* @param callback The callback function.
|
||||
* @param userData The parameter of the callback function.
|
||||
*/
|
||||
status_t USART_TransferCreateHandle(USART_Type *base,
|
||||
usart_handle_t *handle,
|
||||
usart_transfer_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
* @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 is written to the TX register in the IRQ handler, the USART driver calls the callback
|
||||
* function and passes the @ref kStatus_USART_TxIdle as status parameter.
|
||||
*
|
||||
* @note The kStatus_USART_TxIdle is passed to the upper layer when all data is written
|
||||
* to the TX register. However it does not ensure that all data are sent out. Before disabling the TX,
|
||||
* check the kUSART_TransmissionCompleteFlag to ensure that the TX is finished.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
* @param xfer USART transfer structure. See #usart_transfer_t.
|
||||
* @retval kStatus_Success Successfully start the data transmission.
|
||||
* @retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.
|
||||
* @retval kStatus_InvalidArgument Invalid argument.
|
||||
*/
|
||||
status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Sets up the RX ring buffer.
|
||||
*
|
||||
* This function sets up the RX ring buffer to a specific USART handle.
|
||||
*
|
||||
* When the RX ring buffer is used, data received are stored into the ring buffer even when the
|
||||
* user doesn't call the USART_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 the 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 USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
* @param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
|
||||
* @param ringBufferSize size of the ring buffer.
|
||||
*/
|
||||
void USART_TransferStartRingBuffer(USART_Type *base,
|
||||
usart_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 USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
*/
|
||||
void USART_TransferStopRingBuffer(USART_Type *base, usart_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 USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
*/
|
||||
void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Get the number of bytes that have been written to USART TX register.
|
||||
*
|
||||
* This function gets the number of bytes that have been written to USART TX
|
||||
* register by interrupt method.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param handle USART 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 USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count);
|
||||
|
||||
/*!
|
||||
* @brief Receives a buffer of data using an interrupt method.
|
||||
*
|
||||
* This function receives data using an 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 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 to read, the receive
|
||||
* request is saved by the USART driver. When the new data arrives, the receive request
|
||||
* is serviced first. When all data is received, the USART driver notifies the upper layer
|
||||
* through a callback function and passes the status parameter @ref kStatus_USART_RxIdle.
|
||||
* For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
|
||||
* The 5 bytes are copied to the xfer->data and this function returns with the
|
||||
* parameter @p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
|
||||
* saved from the xfer->data[5]. When 5 bytes are received, the USART 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 the xfer->data. When all data is received, the upper layer is notified.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
* @param xfer USART transfer structure, see #usart_transfer_t.
|
||||
* @param receivedBytes Bytes received from the ring buffer directly.
|
||||
* @retval kStatus_Success Successfully queue the transfer into transmit queue.
|
||||
* @retval kStatus_USART_RxBusy Previous receive request is not finished.
|
||||
* @retval kStatus_InvalidArgument Invalid argument.
|
||||
*/
|
||||
status_t USART_TransferReceiveNonBlocking(USART_Type *base,
|
||||
usart_handle_t *handle,
|
||||
usart_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 USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
*/
|
||||
void USART_TransferAbortReceive(USART_Type *base, usart_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 USART peripheral base address.
|
||||
* @param handle USART 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 USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count);
|
||||
|
||||
/*!
|
||||
* @brief USART IRQ handle function.
|
||||
*
|
||||
* This function handles the USART transmit and receive IRQ request.
|
||||
*
|
||||
* @param base USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
*/
|
||||
void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle);
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_USART_H_ */
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_usart.h"
|
||||
#include "fsl_device_registers.h"
|
||||
#include "fsl_dma.h"
|
||||
#include "fsl_flexcomm.h"
|
||||
#include "fsl_usart_dma.h"
|
||||
|
||||
#define USART_HANDLE_ARRAY_SIZE 7
|
||||
|
||||
/*<! Structure definition for uart_dma_handle_t. The structure is private. */
|
||||
typedef struct _usart_dma_private_handle
|
||||
{
|
||||
USART_Type *base;
|
||||
usart_dma_handle_t *handle;
|
||||
} usart_dma_private_handle_t;
|
||||
|
||||
enum _usart_transfer_states
|
||||
{
|
||||
kUSART_TxIdle, /* TX idle. */
|
||||
kUSART_TxBusy, /* TX busy. */
|
||||
kUSART_RxIdle, /* RX idle. */
|
||||
kUSART_RxBusy /* RX busy. */
|
||||
};
|
||||
|
||||
/*<! Private handle only used for internally. */
|
||||
static usart_dma_private_handle_t s_dmaPrivateHandle[USART_HANDLE_ARRAY_SIZE];
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
static void USART_TransferSendDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t intmode)
|
||||
{
|
||||
assert(handle);
|
||||
assert(param);
|
||||
|
||||
usart_dma_private_handle_t *usartPrivateHandle = (usart_dma_private_handle_t *)param;
|
||||
|
||||
/* Disable UART TX DMA. */
|
||||
USART_EnableTxDMA(usartPrivateHandle->base, false);
|
||||
|
||||
usartPrivateHandle->handle->txState = kUSART_TxIdle;
|
||||
|
||||
if (usartPrivateHandle->handle->callback)
|
||||
{
|
||||
usartPrivateHandle->handle->callback(usartPrivateHandle->base, usartPrivateHandle->handle, kStatus_USART_TxIdle,
|
||||
usartPrivateHandle->handle->userData);
|
||||
}
|
||||
}
|
||||
|
||||
static void USART_TransferReceiveDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t intmode)
|
||||
{
|
||||
assert(handle);
|
||||
assert(param);
|
||||
|
||||
usart_dma_private_handle_t *usartPrivateHandle = (usart_dma_private_handle_t *)param;
|
||||
|
||||
/* Disable UART RX DMA. */
|
||||
USART_EnableRxDMA(usartPrivateHandle->base, false);
|
||||
|
||||
usartPrivateHandle->handle->rxState = kUSART_RxIdle;
|
||||
|
||||
if (usartPrivateHandle->handle->callback)
|
||||
{
|
||||
usartPrivateHandle->handle->callback(usartPrivateHandle->base, usartPrivateHandle->handle, kStatus_USART_RxIdle,
|
||||
usartPrivateHandle->handle->userData);
|
||||
}
|
||||
}
|
||||
|
||||
status_t USART_TransferCreateHandleDMA(USART_Type *base,
|
||||
usart_dma_handle_t *handle,
|
||||
usart_dma_transfer_callback_t callback,
|
||||
void *userData,
|
||||
dma_handle_t *txDmaHandle,
|
||||
dma_handle_t *rxDmaHandle)
|
||||
{
|
||||
int32_t instance = 0;
|
||||
|
||||
/* check 'base' */
|
||||
assert(!(NULL == base));
|
||||
if (NULL == base)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
/* check 'handle' */
|
||||
assert(!(NULL == handle));
|
||||
if (NULL == handle)
|
||||
{
|
||||
return kStatus_InvalidArgument;
|
||||
}
|
||||
|
||||
instance = FLEXCOMM_GetInstance(base);
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
/* assign 'base' and 'handle' */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
/* set tx/rx 'idle' state */
|
||||
handle->rxState = kUSART_RxIdle;
|
||||
handle->txState = kUSART_TxIdle;
|
||||
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
|
||||
handle->rxDmaHandle = rxDmaHandle;
|
||||
handle->txDmaHandle = txDmaHandle;
|
||||
|
||||
/* Configure TX. */
|
||||
if (txDmaHandle)
|
||||
{
|
||||
DMA_SetCallback(txDmaHandle, USART_TransferSendDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
/* Configure RX. */
|
||||
if (rxDmaHandle)
|
||||
{
|
||||
DMA_SetCallback(rxDmaHandle, USART_TransferReceiveDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status_t USART_TransferSendDMA(USART_Type *base, usart_dma_handle_t *handle, usart_transfer_t *xfer)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->txDmaHandle);
|
||||
assert(xfer);
|
||||
assert(xfer->data);
|
||||
assert(xfer->dataSize);
|
||||
|
||||
dma_transfer_config_t xferConfig;
|
||||
status_t status;
|
||||
|
||||
/* If previous TX not finished. */
|
||||
if (kUSART_TxBusy == handle->txState)
|
||||
{
|
||||
status = kStatus_USART_TxBusy;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->txState = kUSART_TxBusy;
|
||||
handle->txDataSizeAll = xfer->dataSize;
|
||||
|
||||
/* Enable DMA request from txFIFO */
|
||||
USART_EnableTxDMA(base, true);
|
||||
|
||||
/* Prepare transfer. */
|
||||
DMA_PrepareTransfer(&xferConfig, xfer->data, (void *)&base->FIFOWR, sizeof(uint8_t), xfer->dataSize,
|
||||
kDMA_MemoryToPeripheral, NULL);
|
||||
|
||||
/* Submit transfer. */
|
||||
DMA_SubmitTransfer(handle->txDmaHandle, &xferConfig);
|
||||
DMA_StartTransfer(handle->txDmaHandle);
|
||||
|
||||
status = kStatus_Success;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t USART_TransferReceiveDMA(USART_Type *base, usart_dma_handle_t *handle, usart_transfer_t *xfer)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->rxDmaHandle);
|
||||
assert(xfer);
|
||||
assert(xfer->data);
|
||||
assert(xfer->dataSize);
|
||||
|
||||
dma_transfer_config_t xferConfig;
|
||||
status_t status;
|
||||
|
||||
/* If previous RX not finished. */
|
||||
if (kUSART_RxBusy == handle->rxState)
|
||||
{
|
||||
status = kStatus_USART_RxBusy;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->rxState = kUSART_RxBusy;
|
||||
handle->rxDataSizeAll = xfer->dataSize;
|
||||
|
||||
/* Enable DMA request from rxFIFO */
|
||||
USART_EnableRxDMA(base, true);
|
||||
|
||||
/* Prepare transfer. */
|
||||
DMA_PrepareTransfer(&xferConfig, (void *)&base->FIFORD, xfer->data, sizeof(uint8_t), xfer->dataSize,
|
||||
kDMA_PeripheralToMemory, NULL);
|
||||
|
||||
/* Submit transfer. */
|
||||
DMA_SubmitTransfer(handle->rxDmaHandle, &xferConfig);
|
||||
DMA_StartTransfer(handle->rxDmaHandle);
|
||||
|
||||
status = kStatus_Success;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void USART_TransferAbortSendDMA(USART_Type *base, usart_dma_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
assert(NULL != handle->txDmaHandle);
|
||||
|
||||
/* Stop transfer. */
|
||||
DMA_AbortTransfer(handle->txDmaHandle);
|
||||
handle->txState = kUSART_TxIdle;
|
||||
}
|
||||
|
||||
void USART_TransferAbortReceiveDMA(USART_Type *base, usart_dma_handle_t *handle)
|
||||
{
|
||||
assert(NULL != handle);
|
||||
assert(NULL != handle->rxDmaHandle);
|
||||
|
||||
/* Stop transfer. */
|
||||
DMA_AbortTransfer(handle->rxDmaHandle);
|
||||
handle->rxState = kUSART_RxIdle;
|
||||
}
|
||||
|
||||
status_t USART_TransferGetReceiveCountDMA(USART_Type *base, usart_dma_handle_t *handle, uint32_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->rxDmaHandle);
|
||||
assert(count);
|
||||
|
||||
if (kUSART_RxIdle == handle->rxState)
|
||||
{
|
||||
return kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
||||
*count = handle->rxDataSizeAll - DMA_GetRemainingBytes(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_USART_DMA_H_
|
||||
#define _FSL_USART_DMA_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_dma.h"
|
||||
#include "fsl_usart.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup usart_dma_driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Forward declaration of the handle typedef. */
|
||||
typedef struct _usart_dma_handle usart_dma_handle_t;
|
||||
|
||||
/*! @brief UART transfer callback function. */
|
||||
typedef void (*usart_dma_transfer_callback_t)(USART_Type *base,
|
||||
usart_dma_handle_t *handle,
|
||||
status_t status,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
* @brief UART DMA handle
|
||||
*/
|
||||
struct _usart_dma_handle
|
||||
{
|
||||
USART_Type *base; /*!< UART peripheral base address. */
|
||||
|
||||
usart_dma_transfer_callback_t callback; /*!< Callback function. */
|
||||
void *userData; /*!< UART 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 /* _cplusplus */
|
||||
|
||||
/*!
|
||||
* @name DMA transactional
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes the USART handle which is used in transactional functions.
|
||||
* @param base USART peripheral base address.
|
||||
* @param handle Pointer to usart_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.
|
||||
*/
|
||||
status_t USART_TransferCreateHandleDMA(USART_Type *base,
|
||||
usart_dma_handle_t *handle,
|
||||
usart_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 USART peripheral base address.
|
||||
* @param handle USART handle pointer.
|
||||
* @param xfer USART DMA transfer structure. See #usart_transfer_t.
|
||||
* @retval kStatus_Success if succeed, others failed.
|
||||
* @retval kStatus_USART_TxBusy Previous transfer on going.
|
||||
* @retval kStatus_InvalidArgument Invalid argument.
|
||||
*/
|
||||
status_t USART_TransferSendDMA(USART_Type *base, usart_dma_handle_t *handle, usart_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 USART peripheral base address.
|
||||
* @param handle Pointer to usart_dma_handle_t structure.
|
||||
* @param xfer USART DMA transfer structure. See #usart_transfer_t.
|
||||
* @retval kStatus_Success if succeed, others failed.
|
||||
* @retval kStatus_USART_RxBusy Previous transfer on going.
|
||||
* @retval kStatus_InvalidArgument Invalid argument.
|
||||
*/
|
||||
status_t USART_TransferReceiveDMA(USART_Type *base, usart_dma_handle_t *handle, usart_transfer_t *xfer);
|
||||
|
||||
/*!
|
||||
* @brief Aborts the sent data using DMA.
|
||||
*
|
||||
* This function aborts send data using DMA.
|
||||
*
|
||||
* @param base USART peripheral base address
|
||||
* @param handle Pointer to usart_dma_handle_t structure
|
||||
*/
|
||||
void USART_TransferAbortSendDMA(USART_Type *base, usart_dma_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Aborts the received data using DMA.
|
||||
*
|
||||
* This function aborts the received data using DMA.
|
||||
*
|
||||
* @param base USART peripheral base address
|
||||
* @param handle Pointer to usart_dma_handle_t structure
|
||||
*/
|
||||
void USART_TransferAbortReceiveDMA(USART_Type *base, usart_dma_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 USART peripheral base address.
|
||||
* @param handle USART 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 USART_TransferGetReceiveCountDMA(USART_Type *base, usart_dma_handle_t *handle, uint32_t *count);
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_USART_DMA_H_ */
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_utick.h"
|
||||
#include "fsl_power.h"
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Typedef for interrupt handler. */
|
||||
typedef void (*utick_isr_t)(UTICK_Type *base, utick_callback_t cb);
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Gets the instance from the base address
|
||||
*
|
||||
* @param base UTICK peripheral base address
|
||||
*
|
||||
* @return The UTICK instance
|
||||
*/
|
||||
static uint32_t UTICK_GetInstance(UTICK_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/* Array of UTICK handle. */
|
||||
static utick_callback_t s_utickHandle[FSL_FEATURE_SOC_UTICK_COUNT];
|
||||
/* Array of UTICK peripheral base address. */
|
||||
static UTICK_Type *const s_utickBases[] = UTICK_BASE_PTRS;
|
||||
/* Array of UTICK IRQ number. */
|
||||
static const IRQn_Type s_utickIRQ[] = UTICK_IRQS;
|
||||
/* Array of UTICK clock name. */
|
||||
static const clock_ip_name_t s_utickClock[] = UTICK_CLOCKS;
|
||||
/* UTICK ISR for transactional APIs. */
|
||||
static utick_isr_t s_utickIsr;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static uint32_t UTICK_GetInstance(UTICK_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_UTICK_COUNT; instance++)
|
||||
{
|
||||
if (s_utickBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_UTICK_COUNT);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void UTICK_SetTick(UTICK_Type *base, utick_mode_t mode, uint32_t count, utick_callback_t cb)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Get instance from peripheral base address. */
|
||||
instance = UTICK_GetInstance(base);
|
||||
|
||||
/* Save the handle in global variables to support the double weak mechanism. */
|
||||
s_utickHandle[instance] = cb;
|
||||
EnableDeepSleepIRQ(s_utickIRQ[instance]);
|
||||
base->CTRL = count | UTICK_CTRL_REPEAT(mode);
|
||||
}
|
||||
|
||||
void UTICK_Init(UTICK_Type *base)
|
||||
{
|
||||
/* Enable utick clock */
|
||||
CLOCK_EnableClock(s_utickClock[UTICK_GetInstance(base)]);
|
||||
/* Power up Watchdog oscillator*/
|
||||
POWER_DisablePD(kPDRUNCFG_PD_WDT_OSC);
|
||||
s_utickIsr = UTICK_HandleIRQ;
|
||||
}
|
||||
|
||||
void UTICK_Deinit(UTICK_Type *base)
|
||||
{
|
||||
/* Turn off utick */
|
||||
base->CTRL = 0;
|
||||
/* Disable utick clock */
|
||||
CLOCK_DisableClock(s_utickClock[UTICK_GetInstance(base)]);
|
||||
}
|
||||
|
||||
uint32_t UTICK_GetStatusFlags(UTICK_Type *base)
|
||||
{
|
||||
return (base->STAT);
|
||||
}
|
||||
|
||||
void UTICK_ClearStatusFlags(UTICK_Type *base)
|
||||
{
|
||||
base->STAT = UTICK_STAT_INTR_MASK;
|
||||
}
|
||||
|
||||
void UTICK_HandleIRQ(UTICK_Type *base, utick_callback_t cb)
|
||||
{
|
||||
UTICK_ClearStatusFlags(base);
|
||||
if (cb)
|
||||
{
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(UTICK0)
|
||||
void UTICK0_DriverIRQHandler(void)
|
||||
{
|
||||
s_utickIsr(UTICK0, s_utickHandle[0]);
|
||||
}
|
||||
#endif
|
||||
#if defined(UTICK1)
|
||||
void UTICK1_DriverIRQHandler(void)
|
||||
{
|
||||
s_utickIsr(UTICK1, s_utickHandle[1]);
|
||||
}
|
||||
#endif
|
||||
#if defined(UTICK2)
|
||||
void UTICK2_DriverIRQHandler(void)
|
||||
{
|
||||
s_utickIsr(UTICK2, s_utickHandle[2]);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_UTICK_H_
|
||||
#define _FSL_UTICK_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
/*!
|
||||
* @addtogroup utick
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief UTICK driver version 2.0.0. */
|
||||
#define FSL_UTICK_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*! @brief UTICK timer operational mode. */
|
||||
typedef enum _utick_mode
|
||||
{
|
||||
kUTICK_Onetime = 0x0U, /*!< Trigger once*/
|
||||
kUTICK_Repeat = 0x1U, /*!< Trigger repeatedly */
|
||||
} utick_mode_t;
|
||||
|
||||
/*! @brief UTICK callback function. */
|
||||
typedef void (*utick_callback_t)(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* _cplusplus */
|
||||
|
||||
/*!
|
||||
* @name Initialization and deinitialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes an UTICK by turning its bus clock on
|
||||
*
|
||||
*/
|
||||
void UTICK_Init(UTICK_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Deinitializes a UTICK instance.
|
||||
*
|
||||
* This function shuts down Utick bus clock
|
||||
*
|
||||
* @param base UTICK peripheral base address.
|
||||
*/
|
||||
void UTICK_Deinit(UTICK_Type *base);
|
||||
/*!
|
||||
* @brief Get Status Flags.
|
||||
*
|
||||
* This returns the status flag
|
||||
*
|
||||
* @param base UTICK peripheral base address.
|
||||
* @return status register value
|
||||
*/
|
||||
uint32_t UTICK_GetStatusFlags(UTICK_Type *base);
|
||||
/*!
|
||||
* @brief Clear Status Interrupt Flags.
|
||||
*
|
||||
* This clears intr status flag
|
||||
*
|
||||
* @param base UTICK peripheral base address.
|
||||
* @return none
|
||||
*/
|
||||
void UTICK_ClearStatusFlags(UTICK_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Starts UTICK.
|
||||
*
|
||||
* This function starts a repeat/onetime countdown with an optional callback
|
||||
*
|
||||
* @param base UTICK peripheral base address.
|
||||
* @param mode UTICK timer mode (ie kUTICK_onetime or kUTICK_repeat)
|
||||
* @param count UTICK timer mode (ie kUTICK_onetime or kUTICK_repeat)
|
||||
* @param cb UTICK callback (can be left as NULL if none, otherwise should be a void func(void))
|
||||
* @return none
|
||||
*/
|
||||
void UTICK_SetTick(UTICK_Type *base, utick_mode_t mode, uint32_t count, utick_callback_t cb);
|
||||
/*!
|
||||
* @brief UTICK Interrupt Service Handler.
|
||||
*
|
||||
* This function handles the interrupt and refers to the callback array in the driver to callback user (as per request
|
||||
* in UTICK_SetTick()).
|
||||
* if no user callback is scheduled, the interrupt will simply be cleared.
|
||||
*
|
||||
* @param base UTICK peripheral base address.
|
||||
* @param cb callback scheduled for this instance of UTICK
|
||||
* @return none
|
||||
*/
|
||||
void UTICK_HandleIRQ(UTICK_Type *base, utick_callback_t cb);
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_UTICK_H_ */
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fsl_wwdt.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Gets the instance from the base address
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
*
|
||||
* @return The WWDT instance
|
||||
*/
|
||||
static uint32_t WWDT_GetInstance(WWDT_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief Pointers to WWDT bases for each instance. */
|
||||
static WWDT_Type *const s_wwdtBases[] = WWDT_BASE_PTRS;
|
||||
|
||||
/*! @brief Pointers to WWDT clocks for each instance. */
|
||||
static const clock_ip_name_t s_wwdtClocks[] = WWDT_CLOCKS;
|
||||
|
||||
/*! @brief Pointers to WWDT resets for each instance. */
|
||||
static const reset_ip_name_t s_wwdtResets[] = WWDT_RSTS;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static uint32_t WWDT_GetInstance(WWDT_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
uint32_t wwdtArrayCount = (sizeof(s_wwdtBases) / sizeof(s_wwdtBases[0]));
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < wwdtArrayCount; instance++)
|
||||
{
|
||||
if (s_wwdtBases[instance] == base)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(instance < wwdtArrayCount);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void WWDT_GetDefaultConfig(wwdt_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
/* Enable the watch dog */
|
||||
config->enableWwdt = true;
|
||||
/* Disable the watchdog timeout reset */
|
||||
config->enableWatchdogReset = false;
|
||||
/* Disable the watchdog protection for updating the timeout value */
|
||||
config->enableWatchdogProtect = false;
|
||||
/* Do not lock the watchdog oscillator */
|
||||
config->enableLockOscillator = false;
|
||||
/* Windowing is not in effect */
|
||||
config->windowValue = 0xFFFFFFU;
|
||||
/* Set the timeout value to the max */
|
||||
config->timeoutValue = 0xFFFFFFU;
|
||||
/* No warning is provided */
|
||||
config->warningValue = 0;
|
||||
}
|
||||
|
||||
void WWDT_Init(WWDT_Type *base, const wwdt_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
uint32_t value = 0U;
|
||||
|
||||
/* Enable the WWDT clock */
|
||||
CLOCK_EnableClock(s_wwdtClocks[WWDT_GetInstance(base)]);
|
||||
|
||||
/* Reset the WWDT module */
|
||||
RESET_PeripheralReset(s_wwdtResets[WWDT_GetInstance(base)]);
|
||||
|
||||
value = WWDT_MOD_WDEN(config->enableWwdt) | WWDT_MOD_WDRESET(config->enableWatchdogReset) |
|
||||
WWDT_MOD_WDPROTECT(config->enableWatchdogProtect) | WWDT_MOD_LOCK(config->enableLockOscillator);
|
||||
/* Set configruation */
|
||||
base->WINDOW = WWDT_WINDOW_WINDOW(config->windowValue);
|
||||
base->TC = WWDT_TC_COUNT(config->timeoutValue);
|
||||
base->WARNINT = WWDT_WARNINT_WARNINT(config->warningValue);
|
||||
base->MOD = value;
|
||||
}
|
||||
|
||||
void WWDT_Deinit(WWDT_Type *base)
|
||||
{
|
||||
WWDT_Disable(base);
|
||||
|
||||
/* Disable the WWDT clock */
|
||||
CLOCK_DisableClock(s_wwdtClocks[WWDT_GetInstance(base)]);
|
||||
}
|
||||
|
||||
void WWDT_Refresh(WWDT_Type *base)
|
||||
{
|
||||
uint32_t primaskValue = 0U;
|
||||
|
||||
/* Disable the global interrupt to protect refresh sequence */
|
||||
primaskValue = DisableGlobalIRQ();
|
||||
base->FEED = WWDT_FIRST_WORD_OF_REFRESH;
|
||||
base->FEED = WWDT_SECOND_WORD_OF_REFRESH;
|
||||
EnableGlobalIRQ(primaskValue);
|
||||
}
|
||||
|
||||
void WWDT_ClearStatusFlags(WWDT_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Clear the WDINT bit so that we don't accidentally clear it */
|
||||
uint32_t reg = (base->MOD & (~WWDT_MOD_WDINT_MASK));
|
||||
|
||||
/* Clear timeout by writing a zero */
|
||||
if (mask & kWWDT_TimeoutFlag)
|
||||
{
|
||||
reg &= ~WWDT_MOD_WDTOF_MASK;
|
||||
}
|
||||
|
||||
/* Clear warning interrupt flag by writing a one */
|
||||
if (mask & kWWDT_WarningFlag)
|
||||
{
|
||||
reg |= WWDT_MOD_WDINT_MASK;
|
||||
}
|
||||
|
||||
base->MOD = reg;
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _FSL_WWDT_H_
|
||||
#define _FSL_WWDT_H_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*!
|
||||
* @addtogroup wwdt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
*******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief Defines WWDT driver version 2.0.0. */
|
||||
#define FSL_WWDT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*@}*/
|
||||
|
||||
/*! @name Refresh sequence */
|
||||
/*@{*/
|
||||
#define WWDT_FIRST_WORD_OF_REFRESH (0xAAU) /*!< First word of refresh sequence */
|
||||
#define WWDT_SECOND_WORD_OF_REFRESH (0x55U) /*!< Second word of refresh sequence */
|
||||
/*@}*/
|
||||
|
||||
/*! @brief Describes WWDT configuration structure. */
|
||||
typedef struct _wwdt_config
|
||||
{
|
||||
bool enableWwdt; /*!< Enables or disables WWDT */
|
||||
bool enableWatchdogReset; /*!< true: Watchdog timeout will cause a chip reset
|
||||
false: Watchdog timeout will not cause a chip reset */
|
||||
bool enableWatchdogProtect; /*!< true: Enable watchdog protect i.e timeout value can only be
|
||||
changed after counter is below warning & window values
|
||||
false: Disable watchdog protect; timeout value can be changed
|
||||
at any time */
|
||||
bool enableLockOscillator; /*!< true: Disabling or powering down the watchdog oscillator is prevented
|
||||
Once set, this bit can only be cleared by a reset
|
||||
false: Do not lock oscillator */
|
||||
uint32_t windowValue; /*!< Window value, set this to 0xFFFFFF if windowing is not in effect */
|
||||
uint32_t timeoutValue; /*!< Timeout value */
|
||||
uint32_t warningValue; /*!< Watchdog time counter value that will generate a
|
||||
warning interrupt. Set this to 0 for no warning */
|
||||
|
||||
} wwdt_config_t;
|
||||
|
||||
/*!
|
||||
* @brief WWDT status flags.
|
||||
*
|
||||
* This structure contains the WWDT status flags for use in the WWDT functions.
|
||||
*/
|
||||
enum _wwdt_status_flags_t
|
||||
{
|
||||
kWWDT_TimeoutFlag = WWDT_MOD_WDTOF_MASK, /*!< Time-out flag, set when the timer times out */
|
||||
kWWDT_WarningFlag = WWDT_MOD_WDINT_MASK /*!< Warning interrupt flag, set when timer is below the value WDWARNINT */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
*******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*!
|
||||
* @name WWDT Initialization and De-initialization
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Initializes WWDT configure sturcture.
|
||||
*
|
||||
* This function initializes the WWDT configure structure to default value. The default
|
||||
* value are:
|
||||
* @code
|
||||
* config->enableWwdt = true;
|
||||
* config->enableWatchdogReset = false;
|
||||
* config->enableWatchdogProtect = false;
|
||||
* config->enableLockOscillator = false;
|
||||
* config->windowValue = 0xFFFFFFU;
|
||||
* config->timeoutValue = 0xFFFFFFU;
|
||||
* config->warningValue = 0;
|
||||
* @endcode
|
||||
*
|
||||
* @param config Pointer to WWDT config structure.
|
||||
* @see wwdt_config_t
|
||||
*/
|
||||
void WWDT_GetDefaultConfig(wwdt_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Initializes the WWDT.
|
||||
*
|
||||
* This function initializes the WWDT. When called, the WWDT runs according to the configuration.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* wwdt_config_t config;
|
||||
* WWDT_GetDefaultConfig(&config);
|
||||
* config.timeoutValue = 0x7ffU;
|
||||
* WWDT_Init(wwdt_base,&config);
|
||||
* @endcode
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
* @param config The configuration of WWDT
|
||||
*/
|
||||
void WWDT_Init(WWDT_Type *base, const wwdt_config_t *config);
|
||||
|
||||
/*!
|
||||
* @brief Shuts down the WWDT.
|
||||
*
|
||||
* This function shuts down the WWDT.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
*/
|
||||
void WWDT_Deinit(WWDT_Type *base);
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
* @name WWDT Functional Operation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Enables the WWDT module.
|
||||
*
|
||||
* This function write value into WWDT_MOD register to enable the WWDT, it is a write-once bit;
|
||||
* once this bit is set to one and a watchdog feed is performed, the watchdog timer will run
|
||||
* permanently.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
*/
|
||||
static inline void WWDT_Enable(WWDT_Type *base)
|
||||
{
|
||||
base->MOD |= WWDT_MOD_WDEN_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Disables the WWDT module.
|
||||
*
|
||||
* This function write value into WWDT_MOD register to disable the WWDT.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
*/
|
||||
static inline void WWDT_Disable(WWDT_Type *base)
|
||||
{
|
||||
base->MOD &= ~WWDT_MOD_WDEN_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Gets all WWDT status flags.
|
||||
*
|
||||
* This function gets all status flags.
|
||||
*
|
||||
* Example for getting Timeout Flag:
|
||||
* @code
|
||||
* uint32_t status;
|
||||
* status = WWDT_GetStatusFlags(wwdt_base) & kWWDT_TimeoutFlag;
|
||||
* @endcode
|
||||
* @param base WWDT peripheral base address
|
||||
* @return The status flags. This is the logical OR of members of the
|
||||
* enumeration ::_wwdt_status_flags_t
|
||||
*/
|
||||
static inline uint32_t WWDT_GetStatusFlags(WWDT_Type *base)
|
||||
{
|
||||
return (base->MOD & (WWDT_MOD_WDTOF_MASK | WWDT_MOD_WDINT_MASK));
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Clear WWDT flag.
|
||||
*
|
||||
* This function clears WWDT status flag.
|
||||
*
|
||||
* Example for clearing warning flag:
|
||||
* @code
|
||||
* WWDT_ClearStatusFlags(wwdt_base, kWWDT_WarningFlag);
|
||||
* @endcode
|
||||
* @param base WWDT peripheral base address
|
||||
* @param mask The status flags to clear. This is a logical OR of members of the
|
||||
* enumeration ::_wwdt_status_flags_t
|
||||
*/
|
||||
void WWDT_ClearStatusFlags(WWDT_Type *base, uint32_t mask);
|
||||
|
||||
/*!
|
||||
* @brief Set the WWDT warning value.
|
||||
*
|
||||
* The WDWARNINT register determines the watchdog timer counter value that will generate a watchdog
|
||||
* interrupt. When the watchdog timer counter is no longer greater than the value defined by
|
||||
* WARNINT, an interrupt will be generated after the subsequent WDCLK.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
* @param warningValue WWDT warning value.
|
||||
*/
|
||||
static inline void WWDT_SetWarningValue(WWDT_Type *base, uint32_t warningValue)
|
||||
{
|
||||
base->WARNINT = WWDT_WARNINT_WARNINT(warningValue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the WWDT timeout value.
|
||||
*
|
||||
* This function sets the timeout value. Every time a feed sequence occurs the value in the TC
|
||||
* register is loaded into the Watchdog timer. Writing a value below 0xFF will cause 0xFF to be
|
||||
* loaded into the TC register. Thus the minimum time-out interval is TWDCLK*256*4.
|
||||
* If enableWatchdogProtect flag is true in wwdt_config_t config structure, any attempt to change
|
||||
* the timeout value before the watchdog counter is below the warning and window values
|
||||
* will cause a watchdog reset and set the WDTOF flag.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
* @param timeoutCount WWDT timeout value, count of WWDT clock tick.
|
||||
*/
|
||||
static inline void WWDT_SetTimeoutValue(WWDT_Type *base, uint32_t timeoutCount)
|
||||
{
|
||||
base->TC = WWDT_TC_COUNT(timeoutCount);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the WWDT window value.
|
||||
*
|
||||
* The WINDOW register determines the highest TV value allowed when a watchdog feed is performed.
|
||||
* If a feed sequence occurs when timer value is greater than the value in WINDOW, a watchdog
|
||||
* event will occur. To disable windowing, set windowValue to 0xFFFFFF (maximum possible timer
|
||||
* value) so windowing is not in effect.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
* @param windowValue WWDT window value.
|
||||
*/
|
||||
static inline void WWDT_SetWindowValue(WWDT_Type *base, uint32_t windowValue)
|
||||
{
|
||||
base->WINDOW = WWDT_WINDOW_WINDOW(windowValue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Refreshes the WWDT timer.
|
||||
*
|
||||
* This function feeds the WWDT.
|
||||
* This function should be called before WWDT timer is in timeout. Otherwise, a reset is asserted.
|
||||
*
|
||||
* @param base WWDT peripheral base address
|
||||
*/
|
||||
void WWDT_Refresh(WWDT_Type *base);
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* _FSL_WWDT_H_ */
|
|
@ -0,0 +1,112 @@
|
|||
/* 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"
|
||||
#include "PortNames.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
OSC32KCLK = 0,
|
||||
} RTCName;
|
||||
|
||||
typedef enum {
|
||||
UART_0 = Flexcomm0,
|
||||
UART_1 = Flexcomm4
|
||||
} UARTName;
|
||||
|
||||
#define STDIO_UART_TX USBTX
|
||||
#define STDIO_UART_RX USBRX
|
||||
#define STDIO_UART UART_0
|
||||
|
||||
typedef enum {
|
||||
I2C_0 = Flexcomm1,
|
||||
I2C_1 = Flexcomm2
|
||||
} I2CName;
|
||||
|
||||
#define TPM_SHIFT 8
|
||||
typedef enum {
|
||||
PWM_1 = (0 << TPM_SHIFT) | (0), // FTM0 CH0
|
||||
PWM_2 = (0 << TPM_SHIFT) | (1), // FTM0 CH1
|
||||
PWM_3 = (0 << TPM_SHIFT) | (2), // FTM0 CH2
|
||||
PWM_4 = (0 << TPM_SHIFT) | (3), // FTM0 CH3
|
||||
PWM_5 = (0 << TPM_SHIFT) | (4), // FTM0 CH4
|
||||
PWM_6 = (0 << TPM_SHIFT) | (5), // FTM0 CH5
|
||||
PWM_7 = (0 << TPM_SHIFT) | (6), // FTM0 CH6
|
||||
PWM_8 = (0 << TPM_SHIFT) | (7), // FTM0 CH7
|
||||
PWM_9 = (1 << TPM_SHIFT) | (0), // FTM1 CH0
|
||||
PWM_10 = (1 << TPM_SHIFT) | (1), // FTM1 CH1
|
||||
PWM_11 = (1 << TPM_SHIFT) | (2), // FTM1 CH2
|
||||
PWM_12 = (1 << TPM_SHIFT) | (3), // FTM1 CH3
|
||||
PWM_13 = (1 << TPM_SHIFT) | (4), // FTM1 CH4
|
||||
PWM_14 = (1 << TPM_SHIFT) | (5), // FTM1 CH5
|
||||
PWM_15 = (1 << TPM_SHIFT) | (6), // FTM1 CH6
|
||||
PWM_16 = (1 << TPM_SHIFT) | (7), // FTM1 CH7
|
||||
PWM_17 = (2 << TPM_SHIFT) | (0), // FTM2 CH0
|
||||
PWM_18 = (2 << TPM_SHIFT) | (1), // FTM2 CH1
|
||||
PWM_19 = (2 << TPM_SHIFT) | (2), // FTM2 CH2
|
||||
PWM_20 = (2 << TPM_SHIFT) | (3), // FTM2 CH3
|
||||
PWM_21 = (2 << TPM_SHIFT) | (4), // FTM2 CH4
|
||||
PWM_22 = (2 << TPM_SHIFT) | (5), // FTM2 CH5
|
||||
PWM_23 = (2 << TPM_SHIFT) | (6), // FTM2 CH6
|
||||
PWM_24 = (2 << TPM_SHIFT) | (7), // FTM2 CH7
|
||||
PWM_25 = (3 << TPM_SHIFT) | (0), // FTM3 CH0
|
||||
PWM_26 = (3 << TPM_SHIFT) | (1), // FTM3 CH1
|
||||
PWM_27 = (3 << TPM_SHIFT) | (2), // FTM3 CH2
|
||||
PWM_28 = (3 << TPM_SHIFT) | (3), // FTM3 CH3
|
||||
PWM_29 = (3 << TPM_SHIFT) | (4), // FTM3 CH4
|
||||
PWM_30 = (3 << TPM_SHIFT) | (5), // FTM3 CH5
|
||||
PWM_31 = (3 << TPM_SHIFT) | (6), // FTM3 CH6
|
||||
PWM_32 = (3 << TPM_SHIFT) | (7), // FTM3 CH7
|
||||
} PWMName;
|
||||
|
||||
#define ADC_INSTANCE_SHIFT 8
|
||||
#define ADC_B_CHANNEL_SHIFT 5
|
||||
|
||||
typedef enum {
|
||||
ADC0_SE0 = 0,
|
||||
ADC0_SE1 = 1,
|
||||
ADC0_SE2 = 2,
|
||||
ADC0_SE3 = 3,
|
||||
ADC0_SE4 = 4,
|
||||
ADC0_SE5 = 5,
|
||||
ADC0_SE6 = 6,
|
||||
ADC0_SE7 = 7,
|
||||
ADC0_SE8 = 8,
|
||||
ADC0_SE9 = 9,
|
||||
ADC0_SE10 = 10,
|
||||
ADC0_SE11 = 11,
|
||||
} ADCName;
|
||||
|
||||
typedef enum {
|
||||
CAN_0 = 0,
|
||||
CAN_1 = 1
|
||||
} CANName;
|
||||
|
||||
typedef enum {
|
||||
SPI_0 = Flexcomm3,
|
||||
SPI_1 = Flexcomm9
|
||||
} SPIName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,117 @@
|
|||
/* 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 "PeripheralPins.h"
|
||||
|
||||
/************RTC***************/
|
||||
const PinMap PinMap_RTC[] = {
|
||||
{NC, OSC32KCLK, 0},
|
||||
};
|
||||
|
||||
/************ADC***************/
|
||||
const PinMap PinMap_ADC[] = {
|
||||
{P0_16, ADC0_SE4, 0},
|
||||
{P0_31, ADC0_SE5, 0},
|
||||
{P1_0, ADC0_SE6, 0},
|
||||
{P2_0, ADC0_SE7, 0},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************CAN***************/
|
||||
const PinMap PinMap_CAN_TD[] = {
|
||||
{P3_18, CAN_0, 4},
|
||||
{P1_17, CAN_1, 5},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_CAN_RD[] = {
|
||||
{P3_19, CAN_0, 4},
|
||||
{P1_18, CAN_1, 5},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
|
||||
/************DAC***************/
|
||||
const PinMap PinMap_DAC[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************I2C***************/
|
||||
const PinMap PinMap_I2C_SDA[] = {
|
||||
{P0_13, I2C_0, 1},
|
||||
{P3_23, I2C_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_I2C_SCL[] = {
|
||||
{P0_14, I2C_0, 1},
|
||||
{P3_24, I2C_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************UART***************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
{P0_30, UART_0, 1},
|
||||
{P3_27, UART_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
{P0_29, UART_0, 1},
|
||||
{P3_26, UART_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_CTS[] = {
|
||||
{P3_28, UART_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RTS[] = {
|
||||
{P3_29, UART_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************SPI***************/
|
||||
const PinMap PinMap_SPI_SCLK[] = {
|
||||
{P0_0, SPI_0, 2},
|
||||
{P3_20, SPI_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
{P0_3, SPI_0, 1},
|
||||
{P3_21, SPI_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
{P0_2, SPI_0, 1},
|
||||
{P3_22, SPI_1, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_SSEL[] = {
|
||||
{P0_1, SPI_0, 2},
|
||||
{P3_30, SPI_1, 1},
|
||||
{P4_6, SPI_1, 2},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************PWM***************/
|
||||
const PinMap PinMap_PWM[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
|
@ -0,0 +1,245 @@
|
|||
/* 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 5
|
||||
|
||||
typedef enum {
|
||||
P0_0 = (0 << PORT_SHIFT | 0),
|
||||
P0_1 = (0 << PORT_SHIFT | 1),
|
||||
P0_2 = (0 << PORT_SHIFT | 2),
|
||||
P0_3 = (0 << PORT_SHIFT | 3),
|
||||
P0_4 = (0 << PORT_SHIFT | 4),
|
||||
P0_5 = (0 << PORT_SHIFT | 5),
|
||||
P0_6 = (0 << PORT_SHIFT | 6),
|
||||
P0_7 = (0 << PORT_SHIFT | 7),
|
||||
P0_8 = (0 << PORT_SHIFT | 8),
|
||||
P0_9 = (0 << PORT_SHIFT | 9),
|
||||
P0_10 = (0 << PORT_SHIFT | 10),
|
||||
P0_11 = (0 << PORT_SHIFT | 11),
|
||||
P0_12 = (0 << PORT_SHIFT | 12),
|
||||
P0_13 = (0 << PORT_SHIFT | 13),
|
||||
P0_14 = (0 << PORT_SHIFT | 14),
|
||||
P0_15 = (0 << PORT_SHIFT | 15),
|
||||
P0_16 = (0 << PORT_SHIFT | 16),
|
||||
P0_17 = (0 << PORT_SHIFT | 17),
|
||||
P0_18 = (0 << PORT_SHIFT | 18),
|
||||
P0_19 = (0 << PORT_SHIFT | 19),
|
||||
P0_20 = (0 << PORT_SHIFT | 20),
|
||||
P0_21 = (0 << PORT_SHIFT | 21),
|
||||
P0_22 = (0 << PORT_SHIFT | 22),
|
||||
P0_23 = (0 << PORT_SHIFT | 23),
|
||||
P0_24 = (0 << PORT_SHIFT | 24),
|
||||
P0_25 = (0 << PORT_SHIFT | 25),
|
||||
P0_26 = (0 << PORT_SHIFT | 26),
|
||||
P0_27 = (0 << PORT_SHIFT | 27),
|
||||
P0_28 = (0 << PORT_SHIFT | 28),
|
||||
P0_29 = (0 << PORT_SHIFT | 29),
|
||||
P0_30 = (0 << PORT_SHIFT | 30),
|
||||
P0_31 = (0 << PORT_SHIFT | 31),
|
||||
|
||||
P1_0 = (1 << PORT_SHIFT | 0),
|
||||
P1_1 = (1 << PORT_SHIFT | 1),
|
||||
P1_2 = (1 << PORT_SHIFT | 2),
|
||||
P1_3 = (1 << PORT_SHIFT | 3),
|
||||
P1_4 = (1 << PORT_SHIFT | 4),
|
||||
P1_5 = (1 << PORT_SHIFT | 5),
|
||||
P1_6 = (1 << PORT_SHIFT | 6),
|
||||
P1_7 = (1 << PORT_SHIFT | 7),
|
||||
P1_8 = (1 << PORT_SHIFT | 8),
|
||||
P1_9 = (1 << PORT_SHIFT | 9),
|
||||
P1_10 = (1 << PORT_SHIFT | 10),
|
||||
P1_11 = (1 << PORT_SHIFT | 11),
|
||||
P1_12 = (1 << PORT_SHIFT | 12),
|
||||
P1_13 = (1 << PORT_SHIFT | 13),
|
||||
P1_14 = (1 << PORT_SHIFT | 14),
|
||||
P1_15 = (1 << PORT_SHIFT | 15),
|
||||
P1_16 = (1 << PORT_SHIFT | 16),
|
||||
P1_17 = (1 << PORT_SHIFT | 17),
|
||||
P1_18 = (1 << PORT_SHIFT | 18),
|
||||
P1_19 = (1 << PORT_SHIFT | 19),
|
||||
P1_20 = (1 << PORT_SHIFT | 20),
|
||||
P1_21 = (1 << PORT_SHIFT | 21),
|
||||
P1_22 = (1 << PORT_SHIFT | 22),
|
||||
P1_23 = (1 << PORT_SHIFT | 23),
|
||||
P1_24 = (1 << PORT_SHIFT | 24),
|
||||
P1_25 = (1 << PORT_SHIFT | 25),
|
||||
P1_26 = (1 << PORT_SHIFT | 26),
|
||||
P1_27 = (1 << PORT_SHIFT | 27),
|
||||
P1_28 = (1 << PORT_SHIFT | 28),
|
||||
P1_29 = (1 << PORT_SHIFT | 29),
|
||||
P1_30 = (1 << PORT_SHIFT | 30),
|
||||
P1_31 = (1 << PORT_SHIFT | 31),
|
||||
|
||||
P2_0 = (2 << PORT_SHIFT | 0),
|
||||
P2_1 = (2 << PORT_SHIFT | 1),
|
||||
P2_2 = (2 << PORT_SHIFT | 2),
|
||||
P2_3 = (2 << PORT_SHIFT | 3),
|
||||
P2_4 = (2 << PORT_SHIFT | 4),
|
||||
P2_5 = (2 << PORT_SHIFT | 5),
|
||||
P2_6 = (2 << PORT_SHIFT | 6),
|
||||
P2_7 = (2 << PORT_SHIFT | 7),
|
||||
P2_8 = (2 << PORT_SHIFT | 8),
|
||||
P2_9 = (2 << PORT_SHIFT | 9),
|
||||
P2_10 = (2 << PORT_SHIFT | 10),
|
||||
P2_11 = (2 << PORT_SHIFT | 11),
|
||||
P2_12 = (2 << PORT_SHIFT | 12),
|
||||
P2_13 = (2 << PORT_SHIFT | 13),
|
||||
P2_14 = (2 << PORT_SHIFT | 14),
|
||||
P2_15 = (2 << PORT_SHIFT | 15),
|
||||
P2_16 = (2 << PORT_SHIFT | 16),
|
||||
P2_17 = (2 << PORT_SHIFT | 17),
|
||||
P2_18 = (2 << PORT_SHIFT | 18),
|
||||
P2_19 = (2 << PORT_SHIFT | 19),
|
||||
P2_20 = (2 << PORT_SHIFT | 20),
|
||||
P2_21 = (2 << PORT_SHIFT | 21),
|
||||
P2_22 = (2 << PORT_SHIFT | 22),
|
||||
P2_23 = (2 << PORT_SHIFT | 23),
|
||||
P2_24 = (2 << PORT_SHIFT | 24),
|
||||
P2_25 = (2 << PORT_SHIFT | 25),
|
||||
P2_26 = (2 << PORT_SHIFT | 26),
|
||||
P2_27 = (2 << PORT_SHIFT | 27),
|
||||
P2_28 = (2 << PORT_SHIFT | 28),
|
||||
P2_29 = (2 << PORT_SHIFT | 29),
|
||||
P2_30 = (2 << PORT_SHIFT | 30),
|
||||
P2_31 = (2 << PORT_SHIFT | 31),
|
||||
|
||||
P3_0 = (3 << PORT_SHIFT | 0),
|
||||
P3_1 = (3 << PORT_SHIFT | 1),
|
||||
P3_2 = (3 << PORT_SHIFT | 2),
|
||||
P3_3 = (3 << PORT_SHIFT | 3),
|
||||
P3_4 = (3 << PORT_SHIFT | 4),
|
||||
P3_5 = (3 << PORT_SHIFT | 5),
|
||||
P3_6 = (3 << PORT_SHIFT | 6),
|
||||
P3_7 = (3 << PORT_SHIFT | 7),
|
||||
P3_8 = (3 << PORT_SHIFT | 8),
|
||||
P3_9 = (3 << PORT_SHIFT | 9),
|
||||
P3_10 = (3 << PORT_SHIFT | 10),
|
||||
P3_11 = (3 << PORT_SHIFT | 11),
|
||||
P3_12 = (3 << PORT_SHIFT | 12),
|
||||
P3_13 = (3 << PORT_SHIFT | 13),
|
||||
P3_14 = (3 << PORT_SHIFT | 14),
|
||||
P3_15 = (3 << PORT_SHIFT | 15),
|
||||
P3_16 = (3 << PORT_SHIFT | 16),
|
||||
P3_17 = (3 << PORT_SHIFT | 17),
|
||||
P3_18 = (3 << PORT_SHIFT | 18),
|
||||
P3_19 = (3 << PORT_SHIFT | 19),
|
||||
P3_20 = (3 << PORT_SHIFT | 20),
|
||||
P3_21 = (3 << PORT_SHIFT | 21),
|
||||
P3_22 = (3 << PORT_SHIFT | 22),
|
||||
P3_23 = (3 << PORT_SHIFT | 23),
|
||||
P3_24 = (3 << PORT_SHIFT | 24),
|
||||
P3_25 = (3 << PORT_SHIFT | 25),
|
||||
P3_26 = (3 << PORT_SHIFT | 26),
|
||||
P3_27 = (3 << PORT_SHIFT | 27),
|
||||
P3_28 = (3 << PORT_SHIFT | 28),
|
||||
P3_29 = (3 << PORT_SHIFT | 29),
|
||||
P3_30 = (3 << PORT_SHIFT | 30),
|
||||
P3_31 = (3 << PORT_SHIFT | 31),
|
||||
|
||||
P4_0 = (4 << PORT_SHIFT | 0),
|
||||
P4_1 = (4 << PORT_SHIFT | 1),
|
||||
P4_2 = (4 << PORT_SHIFT | 2),
|
||||
P4_3 = (4 << PORT_SHIFT | 3),
|
||||
P4_4 = (4 << PORT_SHIFT | 4),
|
||||
P4_5 = (4 << PORT_SHIFT | 5),
|
||||
P4_6 = (4 << PORT_SHIFT | 6),
|
||||
P4_7 = (4 << PORT_SHIFT | 7),
|
||||
P4_8 = (4 << PORT_SHIFT | 8),
|
||||
P4_9 = (4 << PORT_SHIFT | 9),
|
||||
P4_10 = (4 << PORT_SHIFT | 10),
|
||||
P4_11 = (4 << PORT_SHIFT | 11),
|
||||
P4_12 = (4 << PORT_SHIFT | 12),
|
||||
P4_13 = (4 << PORT_SHIFT | 13),
|
||||
P4_14 = (4 << PORT_SHIFT | 14),
|
||||
P4_15 = (4 << PORT_SHIFT | 15),
|
||||
P4_16 = (4 << PORT_SHIFT | 16),
|
||||
|
||||
LED_RED = P2_2,
|
||||
|
||||
// mbed original LED naming
|
||||
LED1 = LED_RED,
|
||||
LED2 = P3_3,
|
||||
LED3 = P3_14,
|
||||
LED4 = LED_RED,
|
||||
|
||||
//Push buttons
|
||||
SW2 = P0_6,
|
||||
SW3 = P0_5,
|
||||
SW4 = P0_4,
|
||||
SW5 = P1_1,
|
||||
|
||||
// USB Pins
|
||||
USBTX = P0_30,
|
||||
USBRX = P0_29,
|
||||
|
||||
// Arduino Headers
|
||||
D0 = P3_26,
|
||||
D1 = P3_27,
|
||||
D2 = P3_2,
|
||||
D3 = P4_5,
|
||||
D4 = P3_10,
|
||||
D5 = P3_14,
|
||||
D6 = P3_1,
|
||||
D7 = P1_22,
|
||||
D8 = P4_7,
|
||||
D9 = P2_1,
|
||||
D10 = P3_30,
|
||||
D11 = P3_21,
|
||||
D12 = P3_22,
|
||||
D13 = P3_20,
|
||||
D14 = P3_23,
|
||||
D15 = P3_24,
|
||||
|
||||
I2C_SCL = D15,
|
||||
I2C_SDA = D14,
|
||||
|
||||
A0 = P0_16,
|
||||
A1 = P0_31,
|
||||
A2 = P1_0,
|
||||
A3 = P2_0,
|
||||
A4 = P3_4,
|
||||
A5 = P1_1,
|
||||
|
||||
// Not connected
|
||||
NC = (int)0xFFFFFFFF
|
||||
} PinName;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PullNone = 0,
|
||||
PullDown = 1,
|
||||
PullUp = 2,
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* 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 the copyright holder 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* How to set up clock using clock driver functions:
|
||||
*
|
||||
* 1. Setup clock sources.
|
||||
*
|
||||
* 2. Setup voltage for the fastest of the clock outputs
|
||||
*
|
||||
* 3. Set up wait states of the flash.
|
||||
*
|
||||
* 4. Set up all dividers.
|
||||
*
|
||||
* 5. Set up all selectors to provide selected clocks.
|
||||
*/
|
||||
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!ClocksProfile
|
||||
product: Clocks v1.0
|
||||
processor: LPC54608J512
|
||||
package_id: LPC54608J512ET180
|
||||
mcu_data: ksdk2_0
|
||||
processor_version: 0.0.0
|
||||
board: LPCXpresso54608
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
#include "fsl_power.h"
|
||||
#include "fsl_clock.h"
|
||||
#include "clock_config.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/* System clock frequency. */
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFRO12M ***********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockFRO12M
|
||||
outputs:
|
||||
- {id: System_clock.outFreq, value: 12 MHz}
|
||||
settings:
|
||||
- {id: SYSCON.EMCCLKDIV.scale, value: '1', locked: true}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockFRO12M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(
|
||||
kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
CLOCK_SetupFROClocking(12000000U); /*!< Set up FRO to the 12 MHz, just for sure */
|
||||
POWER_SetVoltageForFreq(
|
||||
12000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(12000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
/*!< Set up dividers */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /*!< Reset divider counter and set divider to value 1 */
|
||||
|
||||
/*!< Set up clock selectors - Attach clocks to the peripheries */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO12M */
|
||||
/*!< Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BOOTCLOCKFRO12M_CORE_CLOCK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************** Configuration BOARD_BootClockFROHF48M ***********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockFROHF48M
|
||||
outputs:
|
||||
- {id: System_clock.outFreq, value: 48 MHz}
|
||||
settings:
|
||||
- {id: SYSCON.MAINCLKSELA.sel, value: SYSCON.fro_hf}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockFROHF48M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(
|
||||
kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
POWER_SetVoltageForFreq(
|
||||
48000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(48000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
CLOCK_SetupFROClocking(48000000U); /*!< Set up high frequency FRO output to selected frequency */
|
||||
|
||||
/*!< Set up dividers */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /*!< Reset divider counter and set divider to value 1 */
|
||||
|
||||
/*!< Set up clock selectors - Attach clocks to the peripheries */
|
||||
CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */
|
||||
/*!< Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFROHF96M **********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockFROHF96M
|
||||
outputs:
|
||||
- {id: System_clock.outFreq, value: 96 MHz}
|
||||
settings:
|
||||
- {id: SYSCON.MAINCLKSELA.sel, value: SYSCON.fro_hf}
|
||||
sources:
|
||||
- {id: SYSCON.fro_hf.outFreq, value: 96 MHz}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockFROHF96M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(
|
||||
kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
POWER_SetVoltageForFreq(
|
||||
96000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(96000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
CLOCK_SetupFROClocking(96000000U); /*!< Set up high frequency FRO output to selected frequency */
|
||||
|
||||
/*!< Set up dividers */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /*!< Reset divider counter and set divider to value 1 */
|
||||
|
||||
/*!< Set up clock selectors - Attach clocks to the peripheries */
|
||||
CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */
|
||||
/*!< Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BOOTCLOCKFROHF96M_CORE_CLOCK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockPLL180M **********************
|
||||
******************************************************************************/
|
||||
/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL *****************************
|
||||
!!Configuration
|
||||
name: BOARD_BootClockPLL180M
|
||||
outputs:
|
||||
- {id: FRO12M_clock.outFreq, value: 12 MHz}
|
||||
- {id: FROHF_clock.outFreq, value: 48 MHz}
|
||||
- {id: SYSPLL_clock.outFreq, value: 180 MHz}
|
||||
- {id: System_clock.outFreq, value: 180 MHz}
|
||||
settings:
|
||||
- {id: SYSCON.M_MULT.scale, value: '30', locked: true}
|
||||
- {id: SYSCON.N_DIV.scale, value: '1', locked: true}
|
||||
- {id: SYSCON.PDEC.scale, value: '2', locked: true}
|
||||
- {id: SYSCON_PDRUNCFG0_PDEN_SYS_PLL_CFG, value: Power_up}
|
||||
sources:
|
||||
- {id: SYSCON._clk_in.outFreq, value: 12 MHz, enabled: true}
|
||||
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables for BOARD_BootClockPLL180M configuration
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Code for BOARD_BootClockPLL180M configuration
|
||||
******************************************************************************/
|
||||
void BOARD_BootClockPLL180M(void)
|
||||
{
|
||||
/*!< Set up the clock sources */
|
||||
/*!< Set up FRO */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_FRO_EN); /*!< Ensure FRO is on */
|
||||
CLOCK_AttachClk(
|
||||
kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12MHz first to ensure we can change voltage without accidentally
|
||||
being below the voltage for current speed */
|
||||
POWER_SetVoltageForFreq(
|
||||
12000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(12000000U); /*!< Set FLASH wait states for core */
|
||||
|
||||
/*!< Set up SYS PLL */
|
||||
const pll_setup_t pllSetup = {
|
||||
.pllctrl = SYSCON_SYSPLLCTRL_SELI(32U) | SYSCON_SYSPLLCTRL_SELP(16U) | SYSCON_SYSPLLCTRL_SELR(0U),
|
||||
.pllmdec = (SYSCON_SYSPLLMDEC_MDEC(8191U)),
|
||||
.pllndec = (SYSCON_SYSPLLNDEC_NDEC(770U)),
|
||||
.pllpdec = (SYSCON_SYSPLLPDEC_PDEC(98U)),
|
||||
.pllRate = 180000000U,
|
||||
.flags = PLL_SETUPFLAG_WAITLOCK | PLL_SETUPFLAG_POWERUP};
|
||||
CLOCK_AttachClk(kEXT_CLK_to_SYS_PLL); /*!< Set sys pll clock source from external crystal */
|
||||
CLOCK_SetPLLFreq(&pllSetup); /*!< Configure PLL to the desired value */
|
||||
POWER_SetVoltageForFreq(
|
||||
180000000U); /*!< Set voltage for the one of the fastest clock outputs: System clock output */
|
||||
CLOCK_SetFLASHAccessCyclesForFreq(180000000U); /*!< Set FLASH wait states for core */
|
||||
CLOCK_AttachClk(kSYS_PLL_to_MAIN_CLK); /*!< Switch System clock to SYS PLL 180MHz */
|
||||
|
||||
/* Set SystemCoreClock variable. */
|
||||
SystemCoreClock = BOARD_BootClockPLL180M_CORE_CLOCK;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* 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 the copyright holder 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_
|
||||
|
||||
#include "fsl_common.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
#define BOARD_XTAL0_CLK_HZ 12000000U /*!< Board xtal0 frequency in Hz */
|
||||
#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32K frequency in Hz */
|
||||
#define BOARD_BootClockRUN BOARD_BootClockFROHF48M
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFRO12M ***********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency:12000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockFRO12M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockFRO12M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*******************************************************************************
|
||||
********************** Configuration BOARD_BootClockFROHF48M ***********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK 48000000U /*!< Core clock frequency:48000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockFROHF48M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockFROHF48M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockFROHF96M **********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BOOTCLOCKFROHF96M_CORE_CLOCK 96000000U /*!< Core clock frequency:96000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockFROHF96M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockFROHF96M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*******************************************************************************
|
||||
********************* Configuration BOARD_BootClockPLL180M **********************
|
||||
******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* Definitions for BOARD_BootClockPLL180M configuration
|
||||
******************************************************************************/
|
||||
#define BOARD_BootClockPLL180M_CORE_CLOCK 180000000U /*!< Core clock frequency:180000000Hz */
|
||||
|
||||
/*******************************************************************************
|
||||
* API for BOARD_BootClockPLL180M configuration
|
||||
******************************************************************************/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief This function executes configuration of clocks.
|
||||
*
|
||||
*/
|
||||
void BOARD_BootClockPLL180M(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
#endif /* _CLOCK_CONFIG_H_ */
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// The 'features' section in 'target.json' is now used to create the device's hardware preprocessor switches.
|
||||
// Check the 'features' section of the target description in 'targets.json' for more details.
|
||||
/* 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_DEVICE_H
|
||||
#define MBED_DEVICE_H
|
||||
|
||||
#define NUMBER_OF_GPIO_INTS 8
|
||||
|
||||
#define APP_EXCLUDE_FROM_DEEPSLEEP \
|
||||
(SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK | SYSCON_PDRUNCFG_PDEN_SRAMX_MASK | \
|
||||
SYSCON_PDRUNCFG_PDEN_SRAM0_MASK | SYSCON_PDRUNCFG_PDEN_SRAM1_2_3_MASK)
|
||||
|
||||
/* Defines used by the sleep code */
|
||||
#define LPC_CLOCK_INTERNAL_IRC BOARD_BootClockFRO12M
|
||||
#define LPC_CLOCK_RUN BOARD_BootClockFROHF48M
|
||||
|
||||
#define DEVICE_ID_LENGTH 24
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "objects.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,121 @@
|
|||
/* 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 "gpio_api.h"
|
||||
#include "clock_config.h"
|
||||
#include "fsl_emc.h"
|
||||
#include "fsl_power.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
/* The SDRAM timing. */
|
||||
#define SDRAM_REFRESHPERIOD_NS (64 * 1000000 / 4096) /* 4096 rows/ 64ms */
|
||||
#define SDRAM_TRP_NS (18u)
|
||||
#define SDRAM_TRAS_NS (42u)
|
||||
#define SDRAM_TSREX_NS (67u)
|
||||
#define SDRAM_TAPR_NS (18u)
|
||||
#define SDRAM_TWRDELT_NS (6u)
|
||||
#define SDRAM_TRC_NS (60u)
|
||||
#define SDRAM_RFC_NS (60u)
|
||||
#define SDRAM_XSR_NS (67u)
|
||||
#define SDRAM_RRD_NS (12u)
|
||||
#define SDRAM_MRD_NCLK (2u)
|
||||
#define SDRAM_RAS_NCLK (2u)
|
||||
#define SDRAM_MODEREG_VALUE (0x23u)
|
||||
#define SDRAM_DEV_MEMORYMAP (0x09u) /* 128Mbits (8M*16, 4banks, 12 rows, 9 columns)*/
|
||||
|
||||
// called before main
|
||||
void mbed_sdk_init()
|
||||
{
|
||||
BOARD_BootClockFROHF48M();
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
//gpio_t gpio;
|
||||
//gpio_init_in(&gpio, PTA4);
|
||||
}
|
||||
|
||||
// Enable the RTC oscillator if available on the board
|
||||
void rtc_setup_oscillator(void)
|
||||
{
|
||||
/* Enable the RTC 32K Oscillator */
|
||||
SYSCON->RTCOSCCTRL |= SYSCON_RTCOSCCTRL_EN_MASK;
|
||||
}
|
||||
|
||||
void ADC_ClockPower_Configuration(void)
|
||||
{
|
||||
/* SYSCON power. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_VDDA); /* Power on VDDA. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_ADC0); /* Power on the ADC converter. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_VD2_ANA); /* Power on the analog power supply. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_VREFP); /* Power on the reference voltage source. */
|
||||
POWER_DisablePD(kPDRUNCFG_PD_TS); /* Power on the temperature sensor. */
|
||||
|
||||
/* Enable the clock. */
|
||||
CLOCK_AttachClk(kFRO12M_to_MAIN_CLK);
|
||||
|
||||
/* CLOCK_AttachClk(kMAIN_CLK_to_ADC_CLK); */
|
||||
/* Sync clock source is not used. Using sync clock source and would be divided by 2.
|
||||
* The divider would be set when configuring the converter.
|
||||
*/
|
||||
CLOCK_EnableClock(kCLOCK_Adc0); /* SYSCON->AHBCLKCTRL[0] |= SYSCON_AHBCLKCTRL_ADC0_MASK; */
|
||||
}
|
||||
|
||||
/* Initialize the external memory. */
|
||||
void BOARD_InitSDRAM(void)
|
||||
{
|
||||
emc_basic_config_t basicConfig;
|
||||
emc_dynamic_timing_config_t dynTiming;
|
||||
emc_dynamic_chip_config_t dynChipConfig;
|
||||
|
||||
/* Basic configuration. */
|
||||
basicConfig.endian = kEMC_LittleEndian;
|
||||
basicConfig.fbClkSrc = kEMC_IntloopbackEmcclk;
|
||||
/* EMC Clock = CPU FREQ/2 here can fit CPU freq from 12M ~ 180M.
|
||||
* If you change the divide to 0 and EMC clock is larger than 100M
|
||||
* please take refer to emc.dox to adjust EMC clock delay.
|
||||
*/
|
||||
basicConfig.emcClkDiv = 1;
|
||||
/* Dynamic memory timing configuration. */
|
||||
dynTiming.readConfig = kEMC_Cmddelay;
|
||||
dynTiming.refreshPeriod_Nanosec = SDRAM_REFRESHPERIOD_NS;
|
||||
dynTiming.tRp_Ns = SDRAM_TRP_NS;
|
||||
dynTiming.tRas_Ns = SDRAM_TRAS_NS;
|
||||
dynTiming.tSrex_Ns = SDRAM_TSREX_NS;
|
||||
dynTiming.tApr_Ns = SDRAM_TAPR_NS;
|
||||
dynTiming.tWr_Ns = (1000000000 / CLOCK_GetFreq(kCLOCK_EMC) + SDRAM_TWRDELT_NS); /* one clk + 6ns */
|
||||
dynTiming.tDal_Ns = dynTiming.tWr_Ns + dynTiming.tRp_Ns;
|
||||
dynTiming.tRc_Ns = SDRAM_TRC_NS;
|
||||
dynTiming.tRfc_Ns = SDRAM_RFC_NS;
|
||||
dynTiming.tXsr_Ns = SDRAM_XSR_NS;
|
||||
dynTiming.tRrd_Ns = SDRAM_RRD_NS;
|
||||
dynTiming.tMrd_Nclk = SDRAM_MRD_NCLK;
|
||||
/* Dynamic memory chip specific configuration: Chip 0 - MTL48LC8M16A2B4-6A */
|
||||
dynChipConfig.chipIndex = 0;
|
||||
dynChipConfig.dynamicDevice = kEMC_Sdram;
|
||||
dynChipConfig.rAS_Nclk = SDRAM_RAS_NCLK;
|
||||
dynChipConfig.sdramModeReg = SDRAM_MODEREG_VALUE;
|
||||
dynChipConfig.sdramExtModeReg = 0; /* it has no use for normal sdram */
|
||||
dynChipConfig.devAddrMap = SDRAM_DEV_MEMORYMAP;
|
||||
/* EMC Basic configuration. */
|
||||
EMC_Init(EMC, &basicConfig);
|
||||
/* EMC Dynamc memory configuration. */
|
||||
EMC_DynamicMemInit(EMC, &dynTiming, &dynChipConfig, 1);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
** ###################################################################
|
||||
** Version: rev. 1.1, 2016-11-25
|
||||
** Build: b170112
|
||||
**
|
||||
** Abstract:
|
||||
** Chip specific module features.
|
||||
**
|
||||
** Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
** Copyright 2016 - 2017 NXP
|
||||
** 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 the copyright holder 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.nxp.com
|
||||
** mail: support@nxp.com
|
||||
**
|
||||
** Revisions:
|
||||
** - rev. 1.0 (2016-08-12)
|
||||
** Initial version.
|
||||
** - rev. 1.1 (2016-11-25)
|
||||
** Update CANFD and Classic CAN register.
|
||||
** Add MAC TIMERSTAMP registers.
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
|
||||
#ifndef _LPC54608_FEATURES_H_
|
||||
#define _LPC54608_FEATURES_H_
|
||||
|
||||
/* SOC module features */
|
||||
|
||||
/* @brief ADC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_ADC_COUNT (1)
|
||||
/* @brief ASYNC_SYSCON availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT (1)
|
||||
/* @brief CRC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_CRC_COUNT (1)
|
||||
/* @brief DMA availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_DMA_COUNT (1)
|
||||
/* @brief DMIC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_DMIC_COUNT (1)
|
||||
/* @brief FLEXCOMM availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_FLEXCOMM_COUNT (10)
|
||||
/* @brief GINT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_GINT_COUNT (2)
|
||||
/* @brief GPIO availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_GPIO_COUNT (1)
|
||||
/* @brief I2C availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_I2C_COUNT (10)
|
||||
/* @brief I2S availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_I2S_COUNT (2)
|
||||
/* @brief INPUTMUX availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_INPUTMUX_COUNT (1)
|
||||
/* @brief IOCON availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_IOCON_COUNT (1)
|
||||
/* @brief MRT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_MRT_COUNT (1)
|
||||
/* @brief PINT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_PINT_COUNT (1)
|
||||
/* @brief RTC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_RTC_COUNT (1)
|
||||
/* @brief SCT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SCT_COUNT (1)
|
||||
/* @brief SPI availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SPI_COUNT (10)
|
||||
/* @brief SPIFI availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SPIFI_COUNT (1)
|
||||
/* @brief SYSCON availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SYSCON_COUNT (1)
|
||||
/* @brief CTIMER availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_CTIMER_COUNT (5)
|
||||
/* @brief USART availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USART_COUNT (10)
|
||||
/* @brief USB availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USB_COUNT (1)
|
||||
/* @brief UTICK availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_UTICK_COUNT (1)
|
||||
/* @brief WWDT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_WWDT_COUNT (1)
|
||||
/* @brief USBFSH availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USBFSH_COUNT (1)
|
||||
/* @brief USBHSD availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USBHSD_COUNT (1)
|
||||
/* @brief USBHSH availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_USBHSH_COUNT (1)
|
||||
/* @brief EEPROM availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_EEPROM_COUNT (1)
|
||||
/* @brief EMC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_EMC_COUNT (1)
|
||||
/* @brief ENET availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_LPC_ENET_COUNT (1)
|
||||
/* @brief SDIF availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SDIF_COUNT (1)
|
||||
/* @brief SMARTCARD availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SMARTCARD_COUNT (2)
|
||||
/* @brief LCD availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_LCD_COUNT (1)
|
||||
/* @brief CAN availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_LPC_CAN_COUNT (2)
|
||||
/* @brief SHA availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_SHA_COUNT (0)
|
||||
/* @brief AES availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_AES_COUNT (0)
|
||||
/* @brief RIT availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_RIT_COUNT (1)
|
||||
/* @brief FMC availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_FMC_COUNT (1)
|
||||
/* @brief RNG availability on the SoC. */
|
||||
#define FSL_FEATURE_SOC_LPC_RNG_COUNT (1)
|
||||
|
||||
/* CAN module features */
|
||||
|
||||
/* @brief Support CANFD or not */
|
||||
#define FSL_FEATURE_CAN_SUPPORT_CANFD (0)
|
||||
|
||||
/* DMA module features */
|
||||
|
||||
/* @brief Number of channels */
|
||||
#define FSL_FEATURE_DMA_NUMBER_OF_CHANNELS (30)
|
||||
|
||||
/* EEPROM module features */
|
||||
|
||||
/* @brief Size of the EEPROM */
|
||||
#define FSL_FEATURE_EEPROM_SIZE (0x00004000)
|
||||
/* @brief Base address of the EEPROM */
|
||||
#define FSL_FEATURE_EEPROM_BASE_ADDRESS (0x40108000)
|
||||
/* @brief Page count of the EEPROM */
|
||||
#define FSL_FEATURE_EEPROM_PAGE_COUNT (128)
|
||||
/* @brief Command number for eeprom program */
|
||||
#define FSL_FEATURE_EEPROM_PROGRAM_CMD (6)
|
||||
/* @brief EEPROM internal clock freqency */
|
||||
#define FSL_FEATURE_EEPROM_INTERNAL_FREQ (1500000)
|
||||
|
||||
/* IOCON module features */
|
||||
|
||||
/* @brief Func bit field width */
|
||||
#define FSL_FEATURE_IOCON_FUNC_FIELD_WIDTH (4)
|
||||
|
||||
/* PINT module features */
|
||||
|
||||
/* @brief Number of connected outputs */
|
||||
#define FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS (8)
|
||||
|
||||
/* SCT module features */
|
||||
|
||||
/* @brief Number of events */
|
||||
#define FSL_FEATURE_SCT_NUMBER_OF_EVENTS (10)
|
||||
/* @brief Number of states */
|
||||
#define FSL_FEATURE_SCT_NUMBER_OF_STATES (10)
|
||||
/* @brief Number of match capture */
|
||||
#define FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE (10)
|
||||
|
||||
/* SDIF module features */
|
||||
|
||||
/* @brief FIFO depth, every location is a WORD */
|
||||
#define FSL_FEATURE_SDIF_FIFO_DEPTH_64_32BITS (64)
|
||||
/* @brief Max DMA buffer size */
|
||||
#define FSL_FEATURE_SDIF_INTERNAL_DMA_MAX_BUFFER_SIZE (4096)
|
||||
/* @brief Max source clock in HZ */
|
||||
#define FSL_FEATURE_SDIF_MAX_SOURCE_CLOCK (52000000)
|
||||
|
||||
/* SPIFI module features */
|
||||
|
||||
/* @brief SPIFI start address */
|
||||
#define FSL_FEATURE_SPIFI_START_ADDR (0x10000000)
|
||||
/* @brief SPIFI end address */
|
||||
#define FSL_FEATURE_SPIFI_END_ADDR (0x17FFFFFF)
|
||||
|
||||
/* SYSCON module features */
|
||||
|
||||
/* @brief Pointer to ROM IAP entry functions */
|
||||
#define FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION (0x03000205)
|
||||
/* @brief Flash page size in bytes */
|
||||
#define FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES (256)
|
||||
/* @brief Flash sector size in bytes */
|
||||
#define FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES (32768)
|
||||
/* @brief Flash size in bytes */
|
||||
#define FSL_FEATURE_SYSCON_FLASH_SIZE_BYTES (524288)
|
||||
|
||||
/* USB module features */
|
||||
|
||||
/* @brief Size of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USB_USB_RAM (0x00002000)
|
||||
/* @brief Base address of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USB_USB_RAM_BASE_ADDRESS (0x40100000)
|
||||
|
||||
/* USBFSH module features */
|
||||
|
||||
/* @brief Size of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USBFSH_USB_RAM (0x00002000)
|
||||
/* @brief Base address of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USBFSH_USB_RAM_BASE_ADDRESS (0x40100000)
|
||||
|
||||
/* USBHSD module features */
|
||||
|
||||
/* @brief Size of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USBHSD_USB_RAM (0x00002000)
|
||||
/* @brief Base address of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS (0x40100000)
|
||||
|
||||
/* USBHSH module features */
|
||||
|
||||
/* @brief Size of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USBHSH_USB_RAM (0x00002000)
|
||||
/* @brief Base address of the USB dedicated RAM */
|
||||
#define FSL_FEATURE_USBHSH_USB_RAM_BASE_ADDRESS (0x40100000)
|
||||
|
||||
#endif /* _LPC54608_FEATURES_H_ */
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
#! armcc -E
|
||||
/*
|
||||
** ###################################################################
|
||||
** Processors: LPC54608J512BD208
|
||||
** LPC54608J512ET180
|
||||
**
|
||||
** Compiler: Keil ARM C/C++ Compiler
|
||||
** Reference manual: LPC54S60x/LPC5460x User manual Rev.0.9 7 Nov 2016
|
||||
** Version: rev. 1.1, 2016-11-25
|
||||
** Build: b161227
|
||||
**
|
||||
** Abstract:
|
||||
** Linker file for the Keil ARM C/C++ Compiler
|
||||
**
|
||||
** Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
** Copyright 2016 - 2017 NXP
|
||||
** 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 the copyright holder 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.nxp.com
|
||||
** mail: support@nxp.com
|
||||
**
|
||||
** ###################################################################
|
||||
*/
|
||||
#define __ram_vector_table__ 1
|
||||
|
||||
#if (defined(__ram_vector_table__))
|
||||
#define __ram_vector_table_size__ 0x00000400
|
||||
#else
|
||||
#define __ram_vector_table_size__ 0x00000000
|
||||
#endif
|
||||
|
||||
#define m_interrupts_start 0x00000000
|
||||
#define m_interrupts_size 0x00000400
|
||||
|
||||
#define m_text_start 0x00000400
|
||||
#define m_text_size 0x0007FC00
|
||||
|
||||
#define m_interrupts_ram_start 0x20000000
|
||||
#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 (0x00028000 - m_interrupts_ram_size)
|
||||
|
||||
#define m_usb_sram_start 0x40100000
|
||||
#define m_usb_sram_size 0x00002000
|
||||
|
||||
/* USB BDT size */
|
||||
#define usb_bdt_size 0x0
|
||||
/* 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_text m_text_start FIXED 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
|
||||
}
|
||||
ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down
|
||||
}
|
||||
}
|
||||
|
||||
LR_m_usb_bdt m_usb_sram_start usb_bdt_size {
|
||||
ER_m_usb_bdt m_usb_sram_start UNINIT usb_bdt_size {
|
||||
* (m_usb_bdt)
|
||||
}
|
||||
}
|
||||
|
||||
LR_m_usb_ram (m_usb_sram_start + usb_bdt_size) (m_usb_sram_size - usb_bdt_size) {
|
||||
ER_m_usb_ram (m_usb_sram_start + usb_bdt_size) UNINIT (m_usb_sram_size - usb_bdt_size) {
|
||||
* (m_usb_global)
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
|
@ -0,0 +1,713 @@
|
|||
;/*****************************************************************************
|
||||
; * @file: startup_LPC54608.s
|
||||
; * @purpose: CMSIS Cortex-M4 Core Device Startup File for the
|
||||
; * LPC54608
|
||||
; * @version: 1.1
|
||||
; * @date: 2016-11-25
|
||||
; *
|
||||
; * Copyright 1997 - 2016 Freescale Semiconductor, Inc.
|
||||
; * Copyright 2016 - 2017 NXP
|
||||
; *
|
||||
; * 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 the copyright holder 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.
|
||||
; *
|
||||
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
|
||||
; *
|
||||
; *****************************************************************************/
|
||||
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; Vector Table Mapped to Address 0 at Reset
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
IMPORT |Image$$ARM_LIB_STACK$$ZI$$Limit|
|
||||
|
||||
__Vectors DCD |Image$$ARM_LIB_STACK$$ZI$$Limit| ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
|
||||
DCD NMI_Handler
|
||||
DCD HardFault_Handler
|
||||
DCD MemManage_Handler
|
||||
DCD BusFault_Handler
|
||||
DCD UsageFault_Handler
|
||||
__vector_table_0x1c
|
||||
DCD 0 ; Checksum of the first 7 words
|
||||
DCD 0xFFFFFFFF ; ECRP
|
||||
DCD 0 ; Enhanced image marker, set to 0x0 for legacy boot
|
||||
DCD 0 ; Pointer to enhanced boot block, set to 0x0 for legacy boot
|
||||
DCD SVC_Handler
|
||||
DCD DebugMon_Handler
|
||||
DCD 0
|
||||
DCD PendSV_Handler
|
||||
DCD SysTick_Handler
|
||||
|
||||
; External Interrupts
|
||||
DCD WDT_BOD_IRQHandler ; Windowed watchdog timer, Brownout detect
|
||||
DCD DMA0_IRQHandler ; DMA controller
|
||||
DCD GINT0_IRQHandler ; GPIO group 0
|
||||
DCD GINT1_IRQHandler ; GPIO group 1
|
||||
DCD PIN_INT0_IRQHandler ; Pin interrupt 0 or pattern match engine slice 0
|
||||
DCD PIN_INT1_IRQHandler ; Pin interrupt 1or pattern match engine slice 1
|
||||
DCD PIN_INT2_IRQHandler ; Pin interrupt 2 or pattern match engine slice 2
|
||||
DCD PIN_INT3_IRQHandler ; Pin interrupt 3 or pattern match engine slice 3
|
||||
DCD UTICK0_IRQHandler ; Micro-tick Timer
|
||||
DCD MRT0_IRQHandler ; Multi-rate timer
|
||||
DCD CTIMER0_IRQHandler ; Standard counter/timer CTIMER0
|
||||
DCD CTIMER1_IRQHandler ; Standard counter/timer CTIMER1
|
||||
DCD SCT0_IRQHandler ; SCTimer/PWM
|
||||
DCD CTIMER3_IRQHandler ; Standard counter/timer CTIMER3
|
||||
DCD FLEXCOMM0_IRQHandler ; Flexcomm Interface 0 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD FLEXCOMM1_IRQHandler ; Flexcomm Interface 1 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD FLEXCOMM2_IRQHandler ; Flexcomm Interface 2 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD FLEXCOMM3_IRQHandler ; Flexcomm Interface 3 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD FLEXCOMM4_IRQHandler ; Flexcomm Interface 4 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD FLEXCOMM5_IRQHandler ; Flexcomm Interface 5 (USART, SPI, I2C,, FLEXCOMM)
|
||||
DCD FLEXCOMM6_IRQHandler ; Flexcomm Interface 6 (USART, SPI, I2C, I2S,, FLEXCOMM)
|
||||
DCD FLEXCOMM7_IRQHandler ; Flexcomm Interface 7 (USART, SPI, I2C, I2S,, FLEXCOMM)
|
||||
DCD ADC0_SEQA_IRQHandler ; ADC0 sequence A completion.
|
||||
DCD ADC0_SEQB_IRQHandler ; ADC0 sequence B completion.
|
||||
DCD ADC0_THCMP_IRQHandler ; ADC0 threshold compare and error.
|
||||
DCD DMIC0_IRQHandler ; Digital microphone and DMIC subsystem
|
||||
DCD HWVAD0_IRQHandler ; Hardware Voice Activity Detector
|
||||
DCD USB0_NEEDCLK_IRQHandler ; USB Activity Wake-up Interrupt
|
||||
DCD USB0_IRQHandler ; USB device
|
||||
DCD RTC_IRQHandler ; RTC alarm and wake-up interrupts
|
||||
DCD Reserved46_IRQHandler ; Reserved interrupt
|
||||
DCD Reserved47_IRQHandler ; Reserved interrupt
|
||||
DCD PIN_INT4_IRQHandler ; Pin interrupt 4 or pattern match engine slice 4 int
|
||||
DCD PIN_INT5_IRQHandler ; Pin interrupt 5 or pattern match engine slice 5 int
|
||||
DCD PIN_INT6_IRQHandler ; Pin interrupt 6 or pattern match engine slice 6 int
|
||||
DCD PIN_INT7_IRQHandler ; Pin interrupt 7 or pattern match engine slice 7 int
|
||||
DCD CTIMER2_IRQHandler ; Standard counter/timer CTIMER2
|
||||
DCD CTIMER4_IRQHandler ; Standard counter/timer CTIMER4
|
||||
DCD RIT_IRQHandler ; Repetitive Interrupt Timer
|
||||
DCD SPIFI0_IRQHandler ; SPI flash interface
|
||||
DCD FLEXCOMM8_IRQHandler ; Flexcomm Interface 8 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD FLEXCOMM9_IRQHandler ; Flexcomm Interface 9 (USART, SPI, I2C, FLEXCOMM)
|
||||
DCD SDIO_IRQHandler ; SD/MMC
|
||||
DCD CAN0_IRQ0_IRQHandler ; CAN0 interrupt0
|
||||
DCD CAN0_IRQ1_IRQHandler ; CAN0 interrupt1
|
||||
DCD CAN1_IRQ0_IRQHandler ; CAN1 interrupt0
|
||||
DCD CAN1_IRQ1_IRQHandler ; CAN1 interrupt1
|
||||
DCD USB1_IRQHandler ; USB1 interrupt
|
||||
DCD USB1_NEEDCLK_IRQHandler ; USB1 activity
|
||||
DCD ETHERNET_IRQHandler ; Ethernet
|
||||
DCD ETHERNET_PMT_IRQHandler ; Ethernet power management interrupt
|
||||
DCD ETHERNET_MACLP_IRQHandler ; Ethernet MAC interrupt
|
||||
DCD EEPROM_IRQHandler ; EEPROM interrupt
|
||||
DCD LCD_IRQHandler ; LCD interrupt
|
||||
DCD SHA_IRQHandler ; SHA interrupt
|
||||
DCD SMARTCARD0_IRQHandler ; Smart card 0 interrupt
|
||||
DCD SMARTCARD1_IRQHandler ; Smart card 1 interrupt
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
; Reset Handler
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
|
||||
LDR r0, =SystemInit
|
||||
BLX r0
|
||||
LDR r0, =__main
|
||||
BX r0
|
||||
ENDP
|
||||
|
||||
; Dummy Exception Handlers (infinite loops which can be modified)
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
HardFault_Handler \
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
MemManage_Handler PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
BusFault_Handler PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
UsageFault_Handler PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
DebugMon_Handler PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
PendSV_Handler PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
SysTick_Handler PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
WDT_BOD_IRQHandler\
|
||||
PROC
|
||||
EXPORT WDT_BOD_IRQHandler [WEAK]
|
||||
LDR R0, =WDT_BOD_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
DMA0_IRQHandler\
|
||||
PROC
|
||||
EXPORT DMA0_IRQHandler [WEAK]
|
||||
LDR R0, =DMA0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
GINT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT GINT0_IRQHandler [WEAK]
|
||||
LDR R0, =GINT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
GINT1_IRQHandler\
|
||||
PROC
|
||||
EXPORT GINT1_IRQHandler [WEAK]
|
||||
LDR R0, =GINT1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT0_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT1_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT1_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT2_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT2_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT2_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT3_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT3_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT3_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
UTICK0_IRQHandler\
|
||||
PROC
|
||||
EXPORT UTICK0_IRQHandler [WEAK]
|
||||
LDR R0, =UTICK0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
MRT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT MRT0_IRQHandler [WEAK]
|
||||
LDR R0, =MRT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER0_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER0_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER1_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER1_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SCT0_IRQHandler\
|
||||
PROC
|
||||
EXPORT SCT0_IRQHandler [WEAK]
|
||||
LDR R0, =SCT0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER3_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER3_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER3_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM0_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM0_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM1_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM1_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM2_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM2_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM2_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM3_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM3_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM3_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM4_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM4_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM4_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM5_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM5_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM5_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM6_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM6_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM6_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM7_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM7_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM7_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ADC0_SEQA_IRQHandler\
|
||||
PROC
|
||||
EXPORT ADC0_SEQA_IRQHandler [WEAK]
|
||||
LDR R0, =ADC0_SEQA_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ADC0_SEQB_IRQHandler\
|
||||
PROC
|
||||
EXPORT ADC0_SEQB_IRQHandler [WEAK]
|
||||
LDR R0, =ADC0_SEQB_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ADC0_THCMP_IRQHandler\
|
||||
PROC
|
||||
EXPORT ADC0_THCMP_IRQHandler [WEAK]
|
||||
LDR R0, =ADC0_THCMP_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
DMIC0_IRQHandler\
|
||||
PROC
|
||||
EXPORT DMIC0_IRQHandler [WEAK]
|
||||
LDR R0, =DMIC0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
HWVAD0_IRQHandler\
|
||||
PROC
|
||||
EXPORT HWVAD0_IRQHandler [WEAK]
|
||||
LDR R0, =HWVAD0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
USB0_NEEDCLK_IRQHandler\
|
||||
PROC
|
||||
EXPORT USB0_NEEDCLK_IRQHandler [WEAK]
|
||||
LDR R0, =USB0_NEEDCLK_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
USB0_IRQHandler\
|
||||
PROC
|
||||
EXPORT USB0_IRQHandler [WEAK]
|
||||
LDR R0, =USB0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
RTC_IRQHandler\
|
||||
PROC
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
LDR R0, =RTC_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
Reserved46_IRQHandler\
|
||||
PROC
|
||||
EXPORT Reserved46_IRQHandler [WEAK]
|
||||
LDR R0, =Reserved46_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
Reserved47_IRQHandler\
|
||||
PROC
|
||||
EXPORT Reserved47_IRQHandler [WEAK]
|
||||
LDR R0, =Reserved47_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT4_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT4_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT4_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT5_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT5_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT5_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT6_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT6_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT6_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
PIN_INT7_IRQHandler\
|
||||
PROC
|
||||
EXPORT PIN_INT7_IRQHandler [WEAK]
|
||||
LDR R0, =PIN_INT7_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER2_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER2_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER2_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CTIMER4_IRQHandler\
|
||||
PROC
|
||||
EXPORT CTIMER4_IRQHandler [WEAK]
|
||||
LDR R0, =CTIMER4_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
RIT_IRQHandler\
|
||||
PROC
|
||||
EXPORT RIT_IRQHandler [WEAK]
|
||||
LDR R0, =RIT_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SPIFI0_IRQHandler\
|
||||
PROC
|
||||
EXPORT SPIFI0_IRQHandler [WEAK]
|
||||
LDR R0, =SPIFI0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM8_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM8_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM8_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
FLEXCOMM9_IRQHandler\
|
||||
PROC
|
||||
EXPORT FLEXCOMM9_IRQHandler [WEAK]
|
||||
LDR R0, =FLEXCOMM9_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SDIO_IRQHandler\
|
||||
PROC
|
||||
EXPORT SDIO_IRQHandler [WEAK]
|
||||
LDR R0, =SDIO_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CAN0_IRQ0_IRQHandler\
|
||||
PROC
|
||||
EXPORT CAN0_IRQ0_IRQHandler [WEAK]
|
||||
LDR R0, =CAN0_IRQ0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CAN0_IRQ1_IRQHandler\
|
||||
PROC
|
||||
EXPORT CAN0_IRQ1_IRQHandler [WEAK]
|
||||
LDR R0, =CAN0_IRQ1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CAN1_IRQ0_IRQHandler\
|
||||
PROC
|
||||
EXPORT CAN1_IRQ0_IRQHandler [WEAK]
|
||||
LDR R0, =CAN1_IRQ0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
CAN1_IRQ1_IRQHandler\
|
||||
PROC
|
||||
EXPORT CAN1_IRQ1_IRQHandler [WEAK]
|
||||
LDR R0, =CAN1_IRQ1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
USB1_IRQHandler\
|
||||
PROC
|
||||
EXPORT USB1_IRQHandler [WEAK]
|
||||
LDR R0, =USB1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
USB1_NEEDCLK_IRQHandler\
|
||||
PROC
|
||||
EXPORT USB1_NEEDCLK_IRQHandler [WEAK]
|
||||
LDR R0, =USB1_NEEDCLK_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ETHERNET_IRQHandler\
|
||||
PROC
|
||||
EXPORT ETHERNET_IRQHandler [WEAK]
|
||||
LDR R0, =ETHERNET_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ETHERNET_PMT_IRQHandler\
|
||||
PROC
|
||||
EXPORT ETHERNET_PMT_IRQHandler [WEAK]
|
||||
LDR R0, =ETHERNET_PMT_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
ETHERNET_MACLP_IRQHandler\
|
||||
PROC
|
||||
EXPORT ETHERNET_MACLP_IRQHandler [WEAK]
|
||||
LDR R0, =ETHERNET_MACLP_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
EEPROM_IRQHandler\
|
||||
PROC
|
||||
EXPORT EEPROM_IRQHandler [WEAK]
|
||||
LDR R0, =EEPROM_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
LCD_IRQHandler\
|
||||
PROC
|
||||
EXPORT LCD_IRQHandler [WEAK]
|
||||
LDR R0, =LCD_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SHA_IRQHandler\
|
||||
PROC
|
||||
EXPORT SHA_IRQHandler [WEAK]
|
||||
LDR R0, =SHA_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SMARTCARD0_IRQHandler\
|
||||
PROC
|
||||
EXPORT SMARTCARD0_IRQHandler [WEAK]
|
||||
LDR R0, =SMARTCARD0_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
SMARTCARD1_IRQHandler\
|
||||
PROC
|
||||
EXPORT SMARTCARD1_IRQHandler [WEAK]
|
||||
LDR R0, =SMARTCARD1_DriverIRQHandler
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
EXPORT WDT_BOD_DriverIRQHandler [WEAK]
|
||||
EXPORT DMA0_DriverIRQHandler [WEAK]
|
||||
EXPORT GINT0_DriverIRQHandler [WEAK]
|
||||
EXPORT GINT1_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT0_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT1_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT2_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT3_DriverIRQHandler [WEAK]
|
||||
EXPORT UTICK0_DriverIRQHandler [WEAK]
|
||||
EXPORT MRT0_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER0_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER1_DriverIRQHandler [WEAK]
|
||||
EXPORT SCT0_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER3_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM0_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM1_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM2_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM3_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM4_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM5_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM6_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM7_DriverIRQHandler [WEAK]
|
||||
EXPORT ADC0_SEQA_DriverIRQHandler [WEAK]
|
||||
EXPORT ADC0_SEQB_DriverIRQHandler [WEAK]
|
||||
EXPORT ADC0_THCMP_DriverIRQHandler [WEAK]
|
||||
EXPORT DMIC0_DriverIRQHandler [WEAK]
|
||||
EXPORT HWVAD0_DriverIRQHandler [WEAK]
|
||||
EXPORT USB0_NEEDCLK_DriverIRQHandler [WEAK]
|
||||
EXPORT USB0_DriverIRQHandler [WEAK]
|
||||
EXPORT RTC_DriverIRQHandler [WEAK]
|
||||
EXPORT Reserved46_DriverIRQHandler [WEAK]
|
||||
EXPORT Reserved47_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT4_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT5_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT6_DriverIRQHandler [WEAK]
|
||||
EXPORT PIN_INT7_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER2_DriverIRQHandler [WEAK]
|
||||
EXPORT CTIMER4_DriverIRQHandler [WEAK]
|
||||
EXPORT RIT_DriverIRQHandler [WEAK]
|
||||
EXPORT SPIFI0_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM8_DriverIRQHandler [WEAK]
|
||||
EXPORT FLEXCOMM9_DriverIRQHandler [WEAK]
|
||||
EXPORT SDIO_DriverIRQHandler [WEAK]
|
||||
EXPORT CAN0_IRQ0_DriverIRQHandler [WEAK]
|
||||
EXPORT CAN0_IRQ1_DriverIRQHandler [WEAK]
|
||||
EXPORT CAN1_IRQ0_DriverIRQHandler [WEAK]
|
||||
EXPORT CAN1_IRQ1_DriverIRQHandler [WEAK]
|
||||
EXPORT USB1_DriverIRQHandler [WEAK]
|
||||
EXPORT USB1_NEEDCLK_DriverIRQHandler [WEAK]
|
||||
EXPORT ETHERNET_DriverIRQHandler [WEAK]
|
||||
EXPORT ETHERNET_PMT_DriverIRQHandler [WEAK]
|
||||
EXPORT ETHERNET_MACLP_DriverIRQHandler [WEAK]
|
||||
EXPORT EEPROM_DriverIRQHandler [WEAK]
|
||||
EXPORT LCD_DriverIRQHandler [WEAK]
|
||||
EXPORT SHA_DriverIRQHandler [WEAK]
|
||||
EXPORT SMARTCARD0_DriverIRQHandler [WEAK]
|
||||
EXPORT SMARTCARD1_DriverIRQHandler [WEAK]
|
||||
|
||||
WDT_BOD_DriverIRQHandler
|
||||
DMA0_DriverIRQHandler
|
||||
GINT0_DriverIRQHandler
|
||||
GINT1_DriverIRQHandler
|
||||
PIN_INT0_DriverIRQHandler
|
||||
PIN_INT1_DriverIRQHandler
|
||||
PIN_INT2_DriverIRQHandler
|
||||
PIN_INT3_DriverIRQHandler
|
||||
UTICK0_DriverIRQHandler
|
||||
MRT0_DriverIRQHandler
|
||||
CTIMER0_DriverIRQHandler
|
||||
CTIMER1_DriverIRQHandler
|
||||
SCT0_DriverIRQHandler
|
||||
CTIMER3_DriverIRQHandler
|
||||
FLEXCOMM0_DriverIRQHandler
|
||||
FLEXCOMM1_DriverIRQHandler
|
||||
FLEXCOMM2_DriverIRQHandler
|
||||
FLEXCOMM3_DriverIRQHandler
|
||||
FLEXCOMM4_DriverIRQHandler
|
||||
FLEXCOMM5_DriverIRQHandler
|
||||
FLEXCOMM6_DriverIRQHandler
|
||||
FLEXCOMM7_DriverIRQHandler
|
||||
ADC0_SEQA_DriverIRQHandler
|
||||
ADC0_SEQB_DriverIRQHandler
|
||||
ADC0_THCMP_DriverIRQHandler
|
||||
DMIC0_DriverIRQHandler
|
||||
HWVAD0_DriverIRQHandler
|
||||
USB0_NEEDCLK_DriverIRQHandler
|
||||
USB0_DriverIRQHandler
|
||||
RTC_DriverIRQHandler
|
||||
Reserved46_DriverIRQHandler
|
||||
Reserved47_DriverIRQHandler
|
||||
PIN_INT4_DriverIRQHandler
|
||||
PIN_INT5_DriverIRQHandler
|
||||
PIN_INT6_DriverIRQHandler
|
||||
PIN_INT7_DriverIRQHandler
|
||||
CTIMER2_DriverIRQHandler
|
||||
CTIMER4_DriverIRQHandler
|
||||
RIT_DriverIRQHandler
|
||||
SPIFI0_DriverIRQHandler
|
||||
FLEXCOMM8_DriverIRQHandler
|
||||
FLEXCOMM9_DriverIRQHandler
|
||||
SDIO_DriverIRQHandler
|
||||
CAN0_IRQ0_DriverIRQHandler
|
||||
CAN0_IRQ1_DriverIRQHandler
|
||||
CAN1_IRQ0_DriverIRQHandler
|
||||
CAN1_IRQ1_DriverIRQHandler
|
||||
USB1_DriverIRQHandler
|
||||
USB1_NEEDCLK_DriverIRQHandler
|
||||
ETHERNET_DriverIRQHandler
|
||||
ETHERNET_PMT_DriverIRQHandler
|
||||
ETHERNET_MACLP_DriverIRQHandler
|
||||
EEPROM_DriverIRQHandler
|
||||
LCD_DriverIRQHandler
|
||||
SHA_DriverIRQHandler
|
||||
SMARTCARD0_DriverIRQHandler
|
||||
SMARTCARD1_DriverIRQHandler
|
||||
|
||||
B .
|
||||
|
||||
ENDP
|
||||
|
||||
|
||||
ALIGN
|
||||
|
||||
|
||||
END
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* mbed Microcontroller Library - stackheap
|
||||
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
|
||||
*
|
||||
* Setup a fixed single stack/heap memory model,
|
||||
* between the top of the RW/ZI region and the stackpointer
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rt_misc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern char Image$$RW_IRAM1$$ZI$$Limit[];
|
||||
|
||||
extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
|
||||
uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
|
||||
uint32_t sp_limit = __current_sp();
|
||||
|
||||
zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
|
||||
|
||||
struct __initial_stackheap r;
|
||||
r.heap_base = zi_limit;
|
||||
r.heap_limit = sp_limit;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue