Initial version with support for PSoC 6 CY8C63XX and both cores using updated PDL 3.0.1 beta.

pull/8491/head
Leszek Rusinowicz 2017-10-16 16:01:40 +02:00
parent 2c533d4693
commit ec22815fee
349 changed files with 150901 additions and 37341 deletions

View File

@ -0,0 +1,330 @@
/***************************************************************************//**
* \file CY_BLE_config.h
* \version 2.0
*
* \brief
* Contains the function prototypes and constants for the BLE Component.
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#if !defined(CY_BLE_CONFIG_H)
#define CY_BLE_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
//#include "cyfitter.h"
#include "syslib/cy_syslib.h"
/**
* \addtogroup group_macros
* @{
*/
/* BLE_bless_isr */
#define BLE_bless_isr__INTC_CORTEXM0P_ASSIGNED 1
#define BLE_bless_isr__INTC_CORTEXM0P_MUX 3u
#define BLE_bless_isr__INTC_CORTEXM0P_PRIORITY 3u
#define BLE_bless_isr__INTC_CORTEXM4_ASSIGNED 1
#define BLE_bless_isr__INTC_CORTEXM4_PRIORITY 7u
#define BLE_bless_isr__INTC_NUMBER 24u
/***************************************
* Services Enable defines
***************************************/
/***************************************
* API Constants
***************************************/
/** The component operating mode. */
#define CY_BLE_CONFIG_MODE (0u)
#define CY_BLE_PROFILE (0u)
#define CY_BLE_HCI (1u)
/** The core for the Host. For DUAL core device Controller will be compiled for different core. */
#define CY_BLE_CONFIG_HOST_CORE (0u)
/** The core for the Controller in HCI mode. */
#define CY_BLE_CONFIG_HCI_CONTR_CORE (1u)
#define CY_BLE_CORE_CORTEX_M4 (0u)
#define CY_BLE_CORE_CORTEX_M0P (1u)
#define CY_BLE_CORE_CORTEX_NONE (0xffu)
#define CY_BLE_HOST_CORE ((CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M4) ? \
CY_CPU_CORTEX_M4 : CY_CPU_CORTEX_M0P)
#define CY_BLE_HCI_CONTR_CORE ((CY_BLE_CONFIG_HCI_CONTR_CORE == CY_BLE_CORE_CORTEX_M4) ? \
CY_CPU_CORTEX_M4 : CY_CPU_CORTEX_M0P)
#define CY_BLE_CONTR_CORE ((CY_BLE_CONFIG_MODE == CY_BLE_HCI) ? CY_BLE_HCI_CONTR_CORE : \
((CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M0P) ? \
CY_CPU_CORTEX_M4 : CY_CPU_CORTEX_M0P))
#define CY_BLE_MODE_PROFILE ((CY_BLE_CONFIG_MODE == CY_BLE_PROFILE) && (CY_BLE_HOST_CORE))
#define CY_BLE_MODE_HCI ((CY_BLE_CONFIG_MODE == CY_BLE_HCI) && (CY_BLE_HCI_CONTR_CORE))
#define CY_BLE_CONFIG_EXT_PA_ENABLED ((0u | \
0u | \
0u) != 0u)
/* Indicates whether deep sleep mode is used */
#define CY_BLE_CONFIG_USE_DEEP_SLEEP (1u)
/** Determines the internal stack mode. Used to switch the operation for debugging.
- ReleaseMode - Host and Controller with software interface.
- DebugMode - Host and Controller with IPC interface.
- HostOnly - Host with UART interface.
- HostContrUart - Host and Controller with a UART interface.
*/
#define CY_BLE_CONFIG_STACK_MODE (2u)
#define CY_BLE_CONFIG_STACK_HOST_ONLY (1u)
#define CY_BLE_CONFIG_STACK_DEBUG (2u)
#define CY_BLE_CONFIG_STACK_RELEASE (3u)
#define CY_BLE_CONFIG_STACK_DEBUG_UART (4u)
#define CY_BLE_CONFIG_STACK_HOST_IPC (5u)
#define CY_BLE_CONFIG_STACK_MODE_CONTR_UART ((CY_BLE_MODE_HCI) || \
((CY_BLE_CONFIG_MODE == CY_BLE_PROFILE) && \
(CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG_UART) && \
CY_BLE_CONTR_CORE))
#define CY_BLE_CONFIG_STACK_MODE_HOST_UART ((CY_BLE_MODE_PROFILE) && \
(((CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_HOST_ONLY) || \
(CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG_UART)) && \
CY_BLE_HOST_CORE))
#define CY_BLE_CONFIG_STACK_MODE_HOST_IPC ((CY_BLE_MODE_PROFILE) && \
(((CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_HOST_IPC) || \
(CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG)) && \
CY_BLE_HOST_CORE))
#define CY_BLE_CONFIG_STACK_CONTR_CORE ((CY_BLE_MODE_HCI) || \
((CY_BLE_CONFIG_MODE == CY_BLE_PROFILE) && \
((CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_RELEASE) && \
(CY_BLE_HOST_CORE)) || \
(((CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG) || \
(CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG_UART)) &&\
(CY_BLE_CONTR_CORE))))
#define CY_BLE_CONFIG_STACK_IPC_CONTR_CORE ((CY_BLE_CONFIG_MODE == CY_BLE_PROFILE) && \
(CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG) && \
(CY_BLE_CONTR_CORE))
#define CY_BLE_CONFIG_CONTR_CORE ((CY_BLE_CONFIG_MODE == CY_BLE_HCI) ? \
CY_BLE_CONFIG_HCI_CONTR_CORE : \
((CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_RELEASE) ? \
CY_BLE_CONFIG_HOST_CORE : \
(((CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG) || \
(CY_BLE_CONFIG_STACK_MODE == CY_BLE_CONFIG_STACK_DEBUG_UART)) ? \
((CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M4) ? \
CY_BLE_CORE_CORTEX_M0P : CY_BLE_CORE_CORTEX_M4) : \
CY_BLE_CORE_CORTEX_NONE)) )
#define CY_BLE_HOST_CONTR_CORE (CY_BLE_MODE_PROFILE || CY_BLE_CONFIG_STACK_CONTR_CORE)
#if(CY_BLE_CONFIG_STACK_CONTR_CORE) /* Check for the proper BLESS ISR configuration in the DWR */
#if ((CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M4) && \
(!defined BLE_bless_isr__INTC_CORTEXM4_ASSIGNED))
#error Enable BLE_bless_isr interrupt for the ARM CM4 core in the interrupt configuration tab of \
the Design-Wide Resources (DWR) file (project.cydwr)
#endif /* (CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M4) */
#if ((CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M0P) && \
(!defined BLE_bless_isr__INTC_CORTEXM0P_ASSIGNED))
#error Enable BLE_bless_isr interrupt for the ARM CM0+ core in the interrupt configuration tab of \
the Design-Wide Resources (DWR) file (project.cydwr)
#endif /* CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M0P) */
#endif /* (CY_BLE_CONFIG_STACK_CONTR_CORE) */
#if(CY_BLE_CONFIG_STACK_MODE_CONTR_UART) /* Check for the proper UART ISR configuration in the DWR */
#if((CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M4) && \
(!defined BLE_uart_isr__INTC_CORTEXM4_ASSIGNED))
#error Enable BLE_uart_isr interrupt for the ARM CM4 core in the interrupt configuration tab of \
the Design-Wide Resources (DWR) file (project.cydwr)
#endif /* CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M4 */
#if((CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M0P) && \
(!defined BLE_uart_isr__INTC_CORTEXM0P_ASSIGNED))
#error Enable BLE_uart_isr interrupt for the ARM CM0+ core in the interrupt configuration tab of \
the Design-Wide Resources (DWR) file (project.cydwr)
#endif /* CY_BLE_CONFIG_CONTR_CORE == CY_BLE_CORE_CORTEX_M0P */
#endif /* (CY_BLE_CONFIG_STACK_MODE_CONTR_UART) */
#if(CY_BLE_CONFIG_STACK_MODE_HOST_UART) /* Check for the proper HOST UART ISR configuration in the DWR */
#if((CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M4) && \
(!defined BLE_host_uart_isr__INTC_CORTEXM4_ASSIGNED))
#error Enable BLE_host_uart_isr interrupt for the ARM CM4 core in the interrupt configuration tab of \
the Design-Wide Resources (DWR) file (project.cydwr)
#endif /* CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M4 */
#if((CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M0P) && \
(!defined BLE_host_uart_isr__INTC_CORTEXM0P_ASSIGNED))
#error Enable BLE_host_uart_isr interrupt for the ARM CM0+ core in the interrupt configuration tab of \
the Design-Wide Resources (DWR) file (project.cydwr)
#endif /* CY_BLE_CONFIG_HOST_CORE == CY_BLE_CORE_CORTEX_M0P */
#endif /* (CY_BLE_CONFIG_STACK_MODE_HOST_UART) */
/** The maximum number of BLE connections */
#define CY_BLE_CONFIG_CONN_COUNT (4u)
/** The number of BLE connections */
#define CY_BLE_CONFIG_GATTC_COUNT (0x00u)
/** The number of GAP Peripheral configurations */
#define CY_BLE_CONFIG_GAP_PERIPHERAL_COUNT (0x01u)
/** The number of GAP Broadcaster configurations */
#define CY_BLE_CONFIG_GAP_BROADCASTER_COUNT (0x00u)
/** The number of GAP Central configurations */
#define CY_BLE_CONFIG_GAP_CENTRAL_COUNT (0x00u)
/** The number of GAP Observer configurations */
#define CY_BLE_CONFIG_GAP_OBSERVER_COUNT (0x00u)
/** The number of Security configurations */
#define CY_BLE_CONFIG_AUTH_INFO_COUNT (0x01u)
/** LL Privacy 1.2 feature */
#define CY_BLE_CONFIG_ENABLE_LL_PRIVACY (0x01u)
/** LE 2 Mbps feature */
#define CY_BLE_CONFIG_ENABLE_PHY_UPDATE (0u)
/** Radio power calibration */
#define CY_BLE_CONFIG_TX_POWER_CALIBRATION_ENABLE (0u)
/** The GAP security level */
#define CY_BLE_CONFIG_GAP_SECURITY_LEVEL (0x00u)
#define CY_BLE_CONFIG_SHARING_MODE (0u)
/** The GAP Role */
#define CY_BLE_CONFIG_GAP_ROLE (0x01u)
/** The Bonding Requirement */
#define CY_BLE_CONFIG_BONDING_REQUIREMENT (0x00u)
/** The maximum number of bonded devices to be supported by this device. */
#define CY_BLE_CONFIG_MAX_BONDED_DEVICES (16u)
/** The maximum number of peer devices whose addresses should be resolved by this device. */
#define CY_BLE_CONFIG_MAX_RESOLVABLE_DEVICES (16u)
/** The maximum number of devices that can be added to the whitelist. */
#define CY_BLE_CONFIG_MAX_WHITE_LIST_SIZE (16u)
#define CY_BLE_SECURITY_CONFIGURATION_0_INDEX (0x00u)
#define CY_BLE_ADV_PKT_0_INDEX_FLAGS (0x00u)
#define CY_BLE_PERIPHERAL_CONFIGURATION_0_INDEX (0x00u)
/* Additional queue depth provided from the customizer */
#define CY_BLE_CONFIG_ADD_Q_DEPTH_PER_CONN (0u)
/** GATT MTU Size */
#define CY_BLE_CONFIG_GATT_MTU (0x0017u)
/** GATT Maximum attribute length */
#define CY_BLE_CONFIG_GATT_DB_MAX_VALUE_LEN (0x000Fu)
#define CY_BLE_GATT_DB_INDEX_COUNT (0x000Fu)
/** The number of characteristics supporting a Reliable Write property */
#define CY_BLE_CONFIG_GATT_RELIABLE_CHAR_COUNT (0x0000u)
/** The total length of characteristics with Reliable Write property */
#define CY_BLE_CONFIG_GATT_RELIABLE_CHAR_LENGTH (0x0000u)
/** The parameter to enable an application to provide a dynamically allocated buffer for preparing a Write request. */
#define CY_BLE_CONFIG_GATT_ENABLE_EXTERNAL_PREP_WRITE_BUFF (0u)
/** The parameter to enable configuration of the L2CAP logical channels */
#define CY_BLE_CONFIG_L2CAP_ENABLE (1u)
#if(CY_BLE_CONFIG_L2CAP_ENABLE != 0u)
/** L2CAP MTU Size */
#define CY_BLE_CONFIG_L2CAP_MTU (23u)
/** L2CAP MPS Size */
#define CY_BLE_CONFIG_L2CAP_MPS (23u)
/** Number of L2CAP Logical channels */
#define CY_BLE_CONFIG_L2CAP_LOGICAL_CHANNEL_COUNT (1u)
/** Number of L2CAP PSMs */
#define CY_BLE_CONFIG_L2CAP_PSM_COUNT (1u)
#endif /* CY_BLE_L2CAP_ENABLE != 0u */
#define CY_BLE_CONFIG_GATT_DB_ATT_VAL_COUNT (0x07u)
/** Max Tx payload size */
#define CY_BLE_CONFIG_LL_MAX_TX_PAYLOAD_SIZE (0x1Bu)
/** Max Rx payload size */
#define CY_BLE_CONFIG_LL_MAX_RX_PAYLOAD_SIZE (0x1Bu)
/** GATT Role */
#define CY_BLE_CONFIG_GATT_ROLE (0x01u)
#define CY_BLE_CONFIG_GATT_DB_CCCD_COUNT (0x02u)
/** Max unique services in the project */
#define CY_BLE_MAX_SRVI (0x01u)
/***************************************
* API Constants for BLE services
* (using in CY_BLE_<service>.h)
***************************************/
/* HIDS */
/** The maximum supported count of HID services for the GATT Server role */
#define CY_BLE_CONFIG_HIDSS_SERVICE_COUNT (0x00u)
/** The maximum supported count of HID reports for the GATT Server role */
#define CY_BLE_CONFIG_HIDSS_REPORT_COUNT (0x00u)
/** The maximum supported count of HID services for the GATT Client role */
#define CY_BLE_CONFIG_HIDSC_SERVICE_COUNT (0x00u)
/** The maximum supported count of HID reports for the GATT Client role */
#define CY_BLE_CONFIG_HIDSC_REPORT_COUNT (0x00u)
/* BAS */
/** The maximum supported count of BAS services for the GATT Server role */
#define CY_BLE_CONFIG_BASS_SERVICE_COUNT (0x00u)
/** The maximum supported count of BAS reports for the GATT Client role */
#define CY_BLE_CONFIG_BASC_SERVICE_COUNT (0x00u)
/* ESS */
/** The maximum supported count of ESS characteristics for the GATT Client role */
#define CY_BLE_CONFIG_ES_TOTAL_CHAR_COUNT (0x00u)
/* AIOS */
/** The maximum supported count of AIOS characteristics for the GATT Client role */
#define CY_BLE_CONFIG_AIO_TOTAL_CHAR_COUNT (0x00u)
/* CUSTOM */
/** The maximum supported count of Custom services for the GATT Server role */
#define CY_BLE_CONFIG_CUSTOMS_SERVICE_COUNT (0x00u)
/** The maximum supported count of Custom services for the GATT Client role */
#define CY_BLE_CONFIG_CUSTOMC_SERVICE_COUNT (0x00u)
/** The maximum supported count of the Custom Service characteristics */
#define CY_BLE_CONFIG_CUSTOM_SERVICE_CHAR_COUNT (0x00u)
/** The maximum supported count of the Custom Service descriptors in one characteristic */
#define CY_BLE_CONFIG_CUSTOM_SERVICE_CHAR_DESCRIPTORS_COUNT (0x00u)
/* Below are the indexes and handles of the defined Custom Services and their characteristics */
/** @} group_macros */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CY_BLE_CONFIG_H */
/* [] END OF FILE */

View File

@ -1,8 +1,8 @@
/***************************************************************************//**
* \file cy8c6x7_cm0plus.ld
* \version 1.0
* \file cy8c6xx7_cm0plus.ld
* \version 2.0
*
* \brief Linker file for the GNU C compiler.
* Linker file for the GNU C compiler.
*
* \note The entry point location is fixed and starts at 0x10000000. The valid
* application image should be placed there.
@ -34,34 +34,20 @@ ENTRY(Reset_Handler)
* option.
*/
EXTERN(Reset_Handler)
EXTERN(vectors)
EXTERN(ram_vectors)
EXTERN(cychipprotect)
EXTERN(cymeta)
/* Flash */
__cy_memory_0_start = 0x10000000;
__cy_memory_0_length = 0x00100000;
__cy_memory_0_row_size = 0x200;
/* Working Flash */
__cy_memory_1_start = 0x14000000;
__cy_memory_1_length = 0x8000;
__cy_memory_1_row_size = 0x200;
/* XIP */
__cy_memory_2_start = 0x18000000;
__cy_memory_2_length = 0x08000000;
__cy_memory_2_row_size = 0x200;
/* Linker script to configure memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x10000000, LENGTH = 0x00080000
wrom (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000
xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x08000000
ram_cm0p (rwx) : ORIGIN = 0x08000000, LENGTH = 0x00024000
flash (rx) : ORIGIN = 0x10000000, LENGTH = 0x80000
wflash (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000 /* 32 KB */
sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800
sflash_nar (rx) : ORIGIN = 0x16001A00, LENGTH = 0x200
sflash_public_key (rx) : ORIGIN = 0x16005A00, LENGTH = 0xC00
sflash_toc_2 (rx) : ORIGIN = 0x16007C00, LENGTH = 0x400
xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x8000000 /* 128 MB */
efuse (r) : ORIGIN = 0x90700000, LENGTH = 0x100000 /* 1 MB */
ram (rwx) : ORIGIN = 0x08000000, LENGTH = 0x24000
}
@ -100,13 +86,17 @@ GROUP(libgcc.a libc.a libm.a libnosys.a)
* __Vectors_End
* __Vectors_Size
*/
ENTRY(Reset_Handler)
SECTIONS
{
.cy_app_header :
{
KEEP(*(.cy_app_header))
} > flash
.text :
{
/* Cortex-M0+ ROM vector table */
. = ALIGN(4);
__Vectors = . ;
KEEP(*(.vectors))
@ -139,26 +129,26 @@ SECTIONS
*(.rodata .rodata.* .constdata .constdata.* .conststring .conststring.*)
KEEP(*(.eh_frame*))
} > rom
} > flash
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > rom
} > flash
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
} > flash
__exidx_end = .;
/* To copy multiple ROM to RAM sections,
* uncomment .copy.table section and,
* define __STARTUP_COPY_MULTIPLE in startup_psoc6ble_cm0plus.S */
* define __STARTUP_COPY_MULTIPLE in startup_psoc63_cm0plus.S */
.copy.table :
{
. = ALIGN(4);
@ -175,13 +165,12 @@ SECTIONS
LONG (__data_end__ - __data_start__) /* Size */
__copy_table_end__ = .;
} > rom
} > flash
/* To clear multiple BSS sections,
* uncomment .zero.table section and,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc6ble_cm0plus.S */
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc63_cm0plus.S */
.zero.table :
{
. = ALIGN(4);
@ -189,7 +178,7 @@ SECTIONS
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
__zero_table_end__ = .;
} > rom
} > flash
__etext = . ;
@ -199,7 +188,7 @@ SECTIONS
__ram_vectors_start__ = .;
KEEP(*(.ram_vectors))
__ram_vectors_end__ = .;
} > ram_cm0p
} > ram
.data __ram_vectors_end__ : AT (__etext)
@ -233,9 +222,12 @@ SECTIONS
KEEP(*(.jcr*))
. = ALIGN(4);
KEEP(*(.cy_ramfunc*))
. = ALIGN(4);
__data_end__ = .;
} > ram_cm0p
} > ram
/* Place variables in the section that should not be initialized during the
@ -244,7 +236,7 @@ SECTIONS
.noinit (NOLOAD) : ALIGN(8)
{
KEEP(*(.noinit))
} > ram_cm0p
} > ram
/* The uninitialized global or static variables are placed in this section.
@ -267,7 +259,7 @@ SECTIONS
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > ram_cm0p
} > ram
.heap (NOLOAD):
@ -277,7 +269,8 @@ SECTIONS
end = __end__;
KEEP(*(.heap*))
__HeapLimit = .;
} > ram_cm0p
} > ram
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
@ -285,11 +278,12 @@ SECTIONS
.stack_dummy (NOLOAD):
{
KEEP(*(.stack*))
} > ram_cm0p
} > ram
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(ram_cm0p) + LENGTH(ram_cm0p);
__StackTop = ORIGIN(ram) + LENGTH(ram);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
@ -297,32 +291,88 @@ SECTIONS
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
/* The section is used for BLE bonding data storage. */
ble_bond_data 0x14000000 :
/* Work Flash */
.cy_wflash :
{
__ble_bond_data_start = . ;
KEEP(*(.ble_bond_data))
__ble_bond_data_end = . ;
} > wrom
KEEP(*(.cy_wflash))
} > wflash
/* Supervisory Flash: User data */
.cy_sflash_user_data :
{
KEEP(*(.cy_sflash_user_data))
} > sflash_user_data
/* Supervisory Flash: Normal Access Restrictions (NAR) */
.cy_sflash_nar :
{
KEEP(*(.cy_sflash_nar))
} > sflash_nar
/* Supervisory Flash: Public Key */
.cy_sflash_public_key :
{
KEEP(*(.cy_sflash_public_key))
} > sflash_public_key
/* Supervisory Flash: Table of Content # 2 */
.cy_toc_part2 :
{
KEEP(*(.cy_toc_part2))
} > sflash_toc_2
/* Places the code in the Execute in Place (XIP) section. See the smif driver
* documentation for details.
*/
.xip 0x18000000 :
.cy_xip :
{
. = ALIGN(4);
__xip_data_start = . ;
KEEP(*(.xip))
__xip_data_end = . ;
KEEP(*(.cy_xip))
} > xip
/* eFuse */
.cy_efuse :
{
KEEP(*(.cy_efuse))
} > efuse
/* These sections are used for additional metadata (silicon revision,
* Silicon/JTAG ID, etc.) storage.
*/
.cymeta 0x90500000 : { KEEP(*(.cymeta)) } :NONE
.cychipprotect 0x90600000 : { KEEP(*(.cychipprotect)) } :NONE
}
/* The following symbols used by the cypdlelftool. */
/* Flash */
__cy_memory_0_start = 0x10000000;
__cy_memory_0_length = 0x00100000;
__cy_memory_0_row_size = 0x200;
/* Working Flash */
__cy_memory_1_start = 0x14000000;
__cy_memory_1_length = 0x8000;
__cy_memory_1_row_size = 0x200;
/* Supervisory Flash */
__cy_memory_2_start = 0x16000000;
__cy_memory_2_length = 0x8000;
__cy_memory_2_row_size = 0x200;
/* XIP */
__cy_memory_3_start = 0x18000000;
__cy_memory_3_length = 0x08000000;
__cy_memory_3_row_size = 0x200;
/* eFuse */
__cy_memory_4_start = 0x90700000;
__cy_memory_4_length = 0x100000;
__cy_memory_4_row_size = 1;
/* EOF */

View File

@ -1,5 +1,5 @@
/**************************************************************************//**
* @file startup_psoc6ble_cm0plus.s
* @file startup_psoc63_cm0plus.s
* @brief CMSIS Core Device Startup File for
* ARMCM0plus Device Series
* @version V5.00
@ -26,9 +26,6 @@
/* Address of the NMI handler */
#define CY_NMI_HANLDER_ADDR 0x0000000D
/* The Cortex-M4 VTOR register */
#define CY_CORTEX_M4_VTOR_ADDR 0x402102C0
/* The CPU VTOR register */
#define CY_CPU_VTOR_ADDR 0xE000ED08
@ -79,7 +76,7 @@ __HeapLimit:
__Vectors:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long CY_NMI_HANLDER_ADDR /* NMI Handler */
.long CY_NMI_HANLDER_ADDR /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
@ -94,39 +91,39 @@ __Vectors:
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* External interrupts Power Mode Description */
.long ioss_interrupts_gpio_0_IRQHandler /* DeepSleep GPIO Port Interrupt #0 */
.long ioss_interrupts_gpio_1_IRQHandler /* DeepSleep GPIO Port Interrupt #1 */
.long ioss_interrupts_gpio_2_IRQHandler /* DeepSleep GPIO Port Interrupt #2 */
.long ioss_interrupts_gpio_3_IRQHandler /* DeepSleep GPIO Port Interrupt #3 */
.long ioss_interrupts_gpio_4_IRQHandler /* DeepSleep GPIO Port Interrupt #4 */
.long ioss_interrupts_gpio_5_IRQHandler /* DeepSleep GPIO Port Interrupt #5 */
.long ioss_interrupts_gpio_6_IRQHandler /* DeepSleep GPIO Port Interrupt #6 */
.long ioss_interrupts_gpio_7_IRQHandler /* DeepSleep GPIO Port Interrupt #7 */
.long ioss_interrupts_gpio_8_IRQHandler /* DeepSleep GPIO Port Interrupt #8 */
.long ioss_interrupts_gpio_9_IRQHandler /* DeepSleep GPIO Port Interrupt #9 */
.long ioss_interrupts_gpio_10_IRQHandler /* DeepSleep GPIO Port Interrupt #10 */
.long ioss_interrupts_gpio_11_IRQHandler /* DeepSleep GPIO Port Interrupt #11 */
.long ioss_interrupts_gpio_12_IRQHandler /* DeepSleep GPIO Port Interrupt #12 */
.long ioss_interrupts_gpio_13_IRQHandler /* DeepSleep GPIO Port Interrupt #13 */
.long ioss_interrupts_gpio_14_IRQHandler /* DeepSleep GPIO Port Interrupt #14 */
.long ioss_interrupt_gpio_IRQHandler /* DeepSleep GPIO All Ports */
.long ioss_interrupt_vdd_IRQHandler /* DeepSleep GPIO Supply Detect Interrupt */
.long lpcomp_interrupt_IRQHandler /* DeepSleep Low Power Comparator Interrupt */
.long scb_8_interrupt_IRQHandler /* DeepSleep Serial Communication Block #8 (DeepSleep capable) */
.long srss_interrupt_mcwdt_0_IRQHandler /* DeepSleep Multi Counter Watchdog Timer interrupt */
.long srss_interrupt_mcwdt_1_IRQHandler /* DeepSleep Multi Counter Watchdog Timer interrupt */
.long srss_interrupt_backup_IRQHandler /* DeepSleep Backup domain interrupt */
.long srss_interrupt_IRQHandler /* DeepSleep Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */
.long pass_interrupt_ctbs_IRQHandler /* DeepSleep CTBm Interrupt (all CTBms) */
.long bless_interrupt_IRQHandler /* DeepSleep Bluetooth Radio interrupt */
.long cpuss_interrupts_ipc_0_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #0 */
.long cpuss_interrupts_ipc_1_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #1 */
.long cpuss_interrupts_ipc_2_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #2 */
.long cpuss_interrupts_ipc_3_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #3 */
.long cpuss_interrupts_ipc_4_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #4 */
.long cpuss_interrupts_ipc_5_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #5 */
.long cpuss_interrupts_ipc_6_IRQHandler /* DeepSleep CPUSS Inter Process Communication Interrupt #6 */
/* External interrupts Description */
.long NvicMux0_IRQHandler /* CM0 + NVIC Mux input 0 */
.long NvicMux1_IRQHandler /* CM0 + NVIC Mux input 1 */
.long NvicMux2_IRQHandler /* CM0 + NVIC Mux input 2 */
.long NvicMux3_IRQHandler /* CM0 + NVIC Mux input 3 */
.long NvicMux4_IRQHandler /* CM0 + NVIC Mux input 4 */
.long NvicMux5_IRQHandler /* CM0 + NVIC Mux input 5 */
.long NvicMux6_IRQHandler /* CM0 + NVIC Mux input 6 */
.long NvicMux7_IRQHandler /* CM0 + NVIC Mux input 7 */
.long NvicMux8_IRQHandler /* CM0 + NVIC Mux input 8 */
.long NvicMux9_IRQHandler /* CM0 + NVIC Mux input 9 */
.long NvicMux10_IRQHandler /* CM0 + NVIC Mux input 10 */
.long NvicMux11_IRQHandler /* CM0 + NVIC Mux input 11 */
.long NvicMux12_IRQHandler /* CM0 + NVIC Mux input 12 */
.long NvicMux13_IRQHandler /* CM0 + NVIC Mux input 13 */
.long NvicMux14_IRQHandler /* CM0 + NVIC Mux input 14 */
.long NvicMux15_IRQHandler /* CM0 + NVIC Mux input 15 */
.long NvicMux16_IRQHandler /* CM0 + NVIC Mux input 16 */
.long NvicMux17_IRQHandler /* CM0 + NVIC Mux input 17 */
.long NvicMux18_IRQHandler /* CM0 + NVIC Mux input 18 */
.long NvicMux19_IRQHandler /* CM0 + NVIC Mux input 19 */
.long NvicMux20_IRQHandler /* CM0 + NVIC Mux input 20 */
.long NvicMux21_IRQHandler /* CM0 + NVIC Mux input 21 */
.long NvicMux22_IRQHandler /* CM0 + NVIC Mux input 22 */
.long NvicMux23_IRQHandler /* CM0 + NVIC Mux input 23 */
.long NvicMux24_IRQHandler /* CM0 + NVIC Mux input 24 */
.long NvicMux25_IRQHandler /* CM0 + NVIC Mux input 25 */
.long NvicMux26_IRQHandler /* CM0 + NVIC Mux input 26 */
.long NvicMux27_IRQHandler /* CM0 + NVIC Mux input 27 */
.long NvicMux28_IRQHandler /* CM0 + NVIC Mux input 28 */
.long NvicMux29_IRQHandler /* CM0 + NVIC Mux input 29 */
.long NvicMux30_IRQHandler /* CM0 + NVIC Mux input 30 */
.long NvicMux31_IRQHandler /* CM0 + NVIC Mux input 31 */
.size __Vectors, . - __Vectors
.equ __VectorsSize, . - __Vectors
@ -320,7 +317,7 @@ Reset_Handler:
bl SystemInit
#endif
bl _start
bl main
/* Should never get here */
b .
@ -378,44 +375,44 @@ Fault_Handler:
def_irq_handler NMI_Handler
def_fault_Handler HardFault_Handler
def_fault_Handler HardFault_Handler
def_irq_handler SVC_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
def_irq_handler ioss_interrupts_gpio_0_IRQHandler
def_irq_handler ioss_interrupts_gpio_1_IRQHandler
def_irq_handler ioss_interrupts_gpio_2_IRQHandler
def_irq_handler ioss_interrupts_gpio_3_IRQHandler
def_irq_handler ioss_interrupts_gpio_4_IRQHandler
def_irq_handler ioss_interrupts_gpio_5_IRQHandler
def_irq_handler ioss_interrupts_gpio_6_IRQHandler
def_irq_handler ioss_interrupts_gpio_7_IRQHandler
def_irq_handler ioss_interrupts_gpio_8_IRQHandler
def_irq_handler ioss_interrupts_gpio_9_IRQHandler
def_irq_handler ioss_interrupts_gpio_10_IRQHandler
def_irq_handler ioss_interrupts_gpio_11_IRQHandler
def_irq_handler ioss_interrupts_gpio_12_IRQHandler
def_irq_handler ioss_interrupts_gpio_13_IRQHandler
def_irq_handler ioss_interrupts_gpio_14_IRQHandler
def_irq_handler ioss_interrupt_gpio_IRQHandler
def_irq_handler ioss_interrupt_vdd_IRQHandler
def_irq_handler lpcomp_interrupt_IRQHandler
def_irq_handler scb_8_interrupt_IRQHandler
def_irq_handler srss_interrupt_mcwdt_0_IRQHandler
def_irq_handler srss_interrupt_mcwdt_1_IRQHandler
def_irq_handler srss_interrupt_backup_IRQHandler
def_irq_handler srss_interrupt_IRQHandler
def_irq_handler pass_interrupt_ctbs_IRQHandler
def_irq_handler bless_interrupt_IRQHandler
def_irq_handler cpuss_interrupts_ipc_0_IRQHandler
def_irq_handler cpuss_interrupts_ipc_1_IRQHandler
def_irq_handler cpuss_interrupts_ipc_2_IRQHandler
def_irq_handler cpuss_interrupts_ipc_3_IRQHandler
def_irq_handler cpuss_interrupts_ipc_4_IRQHandler
def_irq_handler cpuss_interrupts_ipc_5_IRQHandler
def_irq_handler cpuss_interrupts_ipc_6_IRQHandler
def_irq_handler NvicMux0_IRQHandler /* CM0 + NVIC Mux input 0 */
def_irq_handler NvicMux1_IRQHandler /* CM0 + NVIC Mux input 1 */
def_irq_handler NvicMux2_IRQHandler /* CM0 + NVIC Mux input 2 */
def_irq_handler NvicMux3_IRQHandler /* CM0 + NVIC Mux input 3 */
def_irq_handler NvicMux4_IRQHandler /* CM0 + NVIC Mux input 4 */
def_irq_handler NvicMux5_IRQHandler /* CM0 + NVIC Mux input 5 */
def_irq_handler NvicMux6_IRQHandler /* CM0 + NVIC Mux input 6 */
def_irq_handler NvicMux7_IRQHandler /* CM0 + NVIC Mux input 7 */
def_irq_handler NvicMux8_IRQHandler /* CM0 + NVIC Mux input 8 */
def_irq_handler NvicMux9_IRQHandler /* CM0 + NVIC Mux input 9 */
def_irq_handler NvicMux10_IRQHandler /* CM0 + NVIC Mux input 10 */
def_irq_handler NvicMux11_IRQHandler /* CM0 + NVIC Mux input 11 */
def_irq_handler NvicMux12_IRQHandler /* CM0 + NVIC Mux input 12 */
def_irq_handler NvicMux13_IRQHandler /* CM0 + NVIC Mux input 13 */
def_irq_handler NvicMux14_IRQHandler /* CM0 + NVIC Mux input 14 */
def_irq_handler NvicMux15_IRQHandler /* CM0 + NVIC Mux input 15 */
def_irq_handler NvicMux16_IRQHandler /* CM0 + NVIC Mux input 16 */
def_irq_handler NvicMux17_IRQHandler /* CM0 + NVIC Mux input 17 */
def_irq_handler NvicMux18_IRQHandler /* CM0 + NVIC Mux input 18 */
def_irq_handler NvicMux19_IRQHandler /* CM0 + NVIC Mux input 19 */
def_irq_handler NvicMux20_IRQHandler /* CM0 + NVIC Mux input 20 */
def_irq_handler NvicMux21_IRQHandler /* CM0 + NVIC Mux input 21 */
def_irq_handler NvicMux22_IRQHandler /* CM0 + NVIC Mux input 22 */
def_irq_handler NvicMux23_IRQHandler /* CM0 + NVIC Mux input 23 */
def_irq_handler NvicMux24_IRQHandler /* CM0 + NVIC Mux input 24 */
def_irq_handler NvicMux25_IRQHandler /* CM0 + NVIC Mux input 25 */
def_irq_handler NvicMux26_IRQHandler /* CM0 + NVIC Mux input 26 */
def_irq_handler NvicMux27_IRQHandler /* CM0 + NVIC Mux input 27 */
def_irq_handler NvicMux28_IRQHandler /* CM0 + NVIC Mux input 28 */
def_irq_handler NvicMux29_IRQHandler /* CM0 + NVIC Mux input 29 */
def_irq_handler NvicMux30_IRQHandler /* CM0 + NVIC Mux input 30 */
def_irq_handler NvicMux31_IRQHandler /* CM0 + NVIC Mux input 31 */
.end

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* \file system_psoc6ble_cm0plus.c
* \version 1.0
* \file system_psoc63_cm0plus.c
* \version 2.0
*
* The device system-source file.
*
@ -14,20 +14,13 @@
#include <stdint.h>
#include <stdbool.h>
#include "system_psoc6ble_cm0plus.h"
#include "system_psoc63.h"
#include "cy_device_headers.h"
#include "ipc/cy_ipc_drv.h"
#include "ipc/cy_ipc_pipe.h"
#include "ipc/cy_ipc_lock.h"
#include "sysint/cy_sysint.h"
/*******************************************************************************
* Inter Process Communication (IPC)
*******************************************************************************/
cy_stc_ipc_pipe_ep_t cy_ipc_pipe_sysEpArray[CPUSS_IPC_IPC_NR];
uint32_t ipcLockArray[CY_IPC_LOCK_COUNT/CY_IPC_LOCKS_PER_WORD];
cy_ipc_pipe_callback_ptr_t ipc_pipe_cyPipeCbArray[CY_IPC_CYPIPE_CLIENT_CNT];
#if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
#include "ipc/cy_ipc_pipe.h"
#include "ipc/cy_ipc_sema.h"
#endif /* CY_IPC_DEFAULT_CFG_DISABLE */
/*******************************************************************************
@ -35,34 +28,33 @@ cy_ipc_pipe_callback_ptr_t ipc_pipe_cyPipeCbArray[CY_IPC_CYPIPE_CLIENT_CNT];
*******************************************************************************/
/** Default HFClk frequency in Hz */
#define CY_HFCLK0_FREQ_HZ_DEFAULT ( 8000000UL)
#define CY_CLK_HFCLK0_FREQ_HZ_DEFAULT ( 8000000UL)
/** Default PeriClk frequency in Hz */
#define CY_PERICLK_FREQ_HZ_DEFAULT (4000000UL)
#define CY_CLK_PERICLK_FREQ_HZ_DEFAULT (4000000UL)
/** Default SlowClk system core frequency in Hz */
#define CY_SYSTEM_CLOCK_FREQ_HZ_DEFAULT (4000000UL)
#define CY_CLK_SYSTEM_FREQ_HZ_DEFAULT (4000000UL)
/** IMO frequency in Hz */
#define CY_CLK_IMO_FREQ_HZ (8000000UL)
#define CY_IMO_FREQ_HZ ( 8000000UL)
#ifndef CY_EXT_FREQ_HZ
#define CY_EXT_FREQ_HZ (24000000UL)
#endif
#ifndef CY_ECO_FREQ_HZ
#define CY_ECO_FREQ_HZ (24000000UL)
#endif
/** HVILO frequency in Hz */
#define CY_CLK_HVILO_FREQ_HZ (32000UL)
#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)
#ifndef CY_ALTHF_FREQ_HZ
#define CY_ALTHF_FREQ_HZ (32000000UL)
#endif
uint32_t cy_BleEcoClockFreqHz = CY_ALTHF_FREQ_HZ;
#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) */
#if (SRSS_PILO_PRESENT == 1U) || defined(CY_DOXYGEN)
/** PILO frequency in Hz */
#define CY_CLK_PILO_FREQ_HZ (32768UL)
#endif /* (SRSS_PILO_PRESENT == 1U) || defined(CY_DOXYGEN) */
/** WCO frequency in Hz */
#define CY_CLK_WCO_FREQ_HZ (32768UL)
#if (SRSS_ALTLF_PRESENT == 1U) || defined(CY_DOXYGEN)
/** ALTLF frequency in Hz */
#define CY_CLK_ALTLF_FREQ_HZ (32768UL)
#endif /* (SRSS_ALTLF_PRESENT == 1U) || defined(CY_DOXYGEN) */
#define CY_ROOT_PATH_SRC_IMO (0UL)
#define CY_ROOT_PATH_SRC_EXT (1UL)
#define CY_ROOT_PATH_SRC_ECO (2UL)
#define CY_ROOT_PATH_SRC_ALTHF (3UL)
/** Holds the SlowClk system core clock, which is the system clock frequency supplied to the SysTick timer and the
* processor core clock. This variable can be used by debuggers to query the frequency of the debug timer or to configure
@ -71,114 +63,94 @@ cy_ipc_pipe_callback_ptr_t ipc_pipe_cyPipeCbArray[CY_IPC_CYPIPE_CLIENT_CNT];
* \attention Compilers must be configured to avoid removing this variable in case the application program is not using
* it. Debugging systems require the variable to be physically present in memory so that it can be examined to configure
* the debugger. */
uint32_t SystemCoreClock = CY_SYSTEM_CLOCK_FREQ_HZ_DEFAULT;
uint32_t SystemCoreClock = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT;
/** Holds the HFClk0 clock frequency. Updated by \ref SystemCoreClockUpdate(). */
uint32_t cy_Hfclk0FreqHz = CY_HFCLK0_FREQ_HZ_DEFAULT;
uint32_t cy_Hfclk0FreqHz = CY_CLK_HFCLK0_FREQ_HZ_DEFAULT;
/** Holds the PeriClk clock frequency. Updated by \ref SystemCoreClockUpdate(). */
uint32_t cy_PeriClkFreqHz = CY_PERICLK_FREQ_HZ_DEFAULT;
uint32_t cy_PeriClkFreqHz = CY_CLK_PERICLK_FREQ_HZ_DEFAULT;
/* Do not use these definitions directly in your application */
#define CY_DELAY_MS_OVERFLOW_THRESHOLD (0x8000u)
#define CY_DELAY_1K_THRESHOLD (1000u)
#define CY_DELAY_1K_MINUS_1_THRESHOLD (CY_DELAY_1K_THRESHOLD - 1u)
#define CY_DELAY_1M_THRESHOLD (1000000u)
#define CY_DELAY_1M_MINUS_1_THRESHOLD (CY_DELAY_1M_THRESHOLD - 1u)
uint32_t cy_delayFreqHz = CY_SYSTEM_CLOCK_FREQ_HZ_DEFAULT;
uint32_t cy_delayFreqKhz = (CY_SYSTEM_CLOCK_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD;
uint8_t cy_delayFreqMhz = (uint8_t)((CY_SYSTEM_CLOCK_FREQ_HZ_DEFAULT + CY_DELAY_1M_MINUS_1_THRESHOLD) / CY_DELAY_1M_THRESHOLD);
uint32_t cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD * ((CY_SYSTEM_CLOCK_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) /
CY_DELAY_1K_THRESHOLD);
/*******************************************************************************
* Table Of Content (TOC)
*******************************************************************************/
typedef struct {
uint32_t securityImageAddr; /** Address of security image */
uint32_t flashBootAddr; /** Address of Flash Boot stored in SFLASH */
uint32_t flashBootSize; /** Size of Flash Boot (in bytes) */
uint32_t objectOneAddr; /** Address of next object (0 if none) */
uint32_t objectOneSize; /** Size of next object (0 if none) */
uint32_t objectTwoAddr; /** Address of next object (0 if none) */
uint32_t objectTwoSize; /** Size of next object (0 if none) */
uint32_t objectThreeAddr; /** Address of next object (0 if none) */
uint32_t objectThreeSize; /** Size of next object (0 if none) */
uint32_t userAppAddr; /** Address of start of User Application */
uint32_t userAppSize; /** Size of the User Application */
uint32_t keyStorageAddr; /** Address of Key Storage Flash Blocks. */
uint32_t keyStorageSize; /** Size of key storage area in bytes. */
uint32_t smifConfigAddr; /** SMIF Configuration Table */
uint32_t reserved[113u];
uint32_t crc; /** 0x1FC CRC16-CCITT */
} Cy_TOC_Type;
#define CY_TOC_BASE (0x100FFE00UL)
#define CY_TOC ((Cy_TOC_Type*) CY_TOC_BASE)
#ifndef CY_TOC_FLASH_BOOT_ADDR
#define CY_TOC_FLASH_BOOT_ADDR (0x160020D8UL)
#endif
#ifndef CY_TOC_FLASH_BOOT_SIZE
#define CY_TOC_FLASH_BOOT_SIZE (0x2000UL)
#endif
#ifndef CY_TOC_SMIF_CONFIG_ADDR
#define CY_TOC_SMIF_CONFIG_ADDR (0xFFFFFFFFUL)
#endif
#ifndef CY_TOC_USER_APP_ADDR
#define CY_TOC_USER_APP_ADDR (0x10000000UL)
#endif
#ifndef CY_TOC_USER_APP_SIZE
#define CY_TOC_USER_APP_SIZE (0x80000UL)
#endif
#ifdef CY_TOC_PRESENT
#if defined(__GNUC__) || defined(__ARMCC_VERSION)
__attribute__ ((__section__(".cy_toc"), used))
#elif defined(__ICCARM__)
#pragma location=".cy_toc"
#endif
Cy_TOC_Type cyToc = {
.flashBootAddr = CY_TOC_FLASH_BOOT_ADDR,
.flashBootSize = CY_TOC_FLASH_BOOT_SIZE,
.smifConfigAddr = CY_TOC_SMIF_CONFIG_ADDR,
.userAppAddr = CY_TOC_USER_APP_ADDR,
.userAppSize = CY_TOC_USER_APP_SIZE
};
#endif
/** Holds the Alternate high frequency clock in Hz. Updated by \ref SystemCoreClockUpdate(). */
#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)
uint32_t cy_BleEcoClockFreqHz = CY_CLK_ALTHF_FREQ_HZ;
#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) */
/*******************************************************************************
* SystemInit()
*******************************************************************************/
/* WDT lock bits */
#define CY_WDT_LOCK_BIT0 ((uint32_t)0x01u << 30u)
#define CY_WDT_LOCK_BIT1 ((uint32_t)0x01u << 31u)
/* CLK_FLL_CONFIG default values, from MXS40-IP-SRSS */
/* CLK_FLL_CONFIG default values */
#define CY_FB_CLK_FLL_CONFIG_VALUE (0x01000000u)
#define CY_FB_CLK_FLL_CONFIG2_VALUE (0x00020001u)
#define CY_FB_CLK_FLL_CONFIG3_VALUE (0x00002800u)
#define CY_FB_CLK_FLL_CONFIG4_VALUE (0x000000FFu)
/*******************************************************************************
* SystemCoreClockUpdate (void)
*******************************************************************************/
/* Do not use these definitions directly in your application */
#define CY_DELAY_MS_OVERFLOW_THRESHOLD (0x8000u)
#define CY_DELAY_1K_THRESHOLD (1000u)
#define CY_DELAY_1K_MINUS_1_THRESHOLD (CY_DELAY_1K_THRESHOLD - 1u)
#define CY_DELAY_1M_THRESHOLD (1000000u)
#define CY_DELAY_1M_MINUS_1_THRESHOLD (CY_DELAY_1M_THRESHOLD - 1u)
uint32_t cy_delayFreqHz = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT;
uint32_t cy_delayFreqKhz = (CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) /
CY_DELAY_1K_THRESHOLD;
uint8_t cy_delayFreqMhz = (uint8_t)((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1M_MINUS_1_THRESHOLD) /
CY_DELAY_1M_THRESHOLD);
uint32_t cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD *
((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD);
#define CY_ROOT_PATH_SRC_IMO (0UL)
#define CY_ROOT_PATH_SRC_EXT (1UL)
#if (SRSS_ECO_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_ECO (2UL)
#endif /* (SRSS_ECO_PRESENT == 1U) */
#if (SRSS_ALTHF_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_ALTHF (3UL)
#endif /* (SRSS_ALTHF_PRESENT == 1U) */
#define CY_ROOT_PATH_SRC_DSI_MUX (4UL)
#define CY_ROOT_PATH_SRC_DSI_MUX_HVILO (16UL)
#define CY_ROOT_PATH_SRC_DSI_MUX_WCO (17UL)
#if (SRSS_ALTLF_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_DSI_MUX_ALTLF (18UL)
#endif /* (SRSS_ALTLF_PRESENT == 1U) */
#if (SRSS_PILO_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_DSI_MUX_PILO (19UL)
#endif /* (SRSS_PILO_PRESENT == 1U) */
/*******************************************************************************
* Cy_SysEnableCM4(), Cy_SysRetainCM4(), and Cy_SysResetCM4()
*******************************************************************************/
#define CY_SYS_CM4_PWR_CTL_KEY_OPEN (0x05FAUL)
#define CY_SYS_CM4_PWR_CTL_KEY_CLOSE (0xFA05UL)
/*******************************************************************************
* Function Name: SystemInit
****************************************************************************//**
*
* Initializes the system.
* Initializes the system:
* - Restores FLL registers to the default state.
* - Unlocks and disables WDT.
* - Calls the Cy_SystemInit() function, if compiled from PSoC Creator.
* - Calls \ref SystemCoreClockUpdate().
*
*******************************************************************************/
void SystemInit(void)
{
/* Restores FLL to default state as it is not restored by ROM code */
/* Restore FLL registers to the default state as they are not restored by the ROM code */
uint32_t copy = SRSS->CLK_FLL_CONFIG;
copy &= ~SRSS_CLK_FLL_CONFIG_FLL_ENABLE_Msk;
SRSS->CLK_FLL_CONFIG = copy;
@ -201,8 +173,17 @@ void SystemInit(void)
Cy_SystemInit();
SystemCoreClockUpdate();
Cy_SystemInitIpc();
Cy_SMIF_StartupCallBack();
#if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
/* Allocate and initialize semaphores for the system operations. */
Cy_IPC_SystemSemaInit();
Cy_IPC_SystemPipeInit();
#endif /* CY_IPC_DEFAULT_CFG_DISABLE */
/* Clear data register of IPC structure #7, reserved for the Deep Sleep operations. */
IPC_STRUCT7->DATA = 0UL;
/* Release IPC structure #7 to avoid deadlocks in case of SW or WDT reset during Deep Sleep entering. */
IPC_STRUCT7->RELEASE = 0UL;
}
@ -228,30 +209,15 @@ __WEAK void Cy_SystemInit(void)
}
/*******************************************************************************
* Function Name: Cy_SMIF_StartupCallBack
****************************************************************************//**
*
* The function is called during device startup. Once SMIF functionality is
* required, user should implement the function as described by the SMIF
* documentation.
*
******************************************************************************/
__WEAK void Cy_SMIF_StartupCallBack(void)
{
/* Empty weak function. The actual implementation to be in the user's
* strong function.
*/
}
/*******************************************************************************
* Function Name: SystemCoreClockUpdate
****************************************************************************//**
*
* Get Core Clock Frequency.
* Gets core clock frequency and updates \ref SystemCoreClock, \ref
* cy_Hfclk0FreqHz, and \ref cy_PeriClkFreqHz.
*
* Update \ref SystemCoreClock, \ref cy_Hfclk0FreqHz, and \ref cy_PeriClkFreqHz.
* Updates global variables used by the \ref Cy_SysLib_Delay(), \ref
* Cy_SysLib_DelayUs(), and \ref Cy_SysLib_DelayCycles().
*
*******************************************************************************/
void SystemCoreClockUpdate (void)
@ -273,25 +239,60 @@ void SystemCoreClockUpdate (void)
switch (srcClk)
{
case CY_ROOT_PATH_SRC_IMO:
srcFreqHz = CY_IMO_FREQ_HZ;
srcFreqHz = CY_CLK_IMO_FREQ_HZ;
break;
case CY_ROOT_PATH_SRC_EXT:
srcFreqHz = CY_EXT_FREQ_HZ;
srcFreqHz = CY_CLK_EXT_FREQ_HZ;
break;
case CY_ROOT_PATH_SRC_ECO:
srcFreqHz = CY_ECO_FREQ_HZ;
break;
#if (SRSS_ECO_PRESENT == 1U)
case CY_ROOT_PATH_SRC_ECO:
srcFreqHz = CY_CLK_ECO_FREQ_HZ;
break;
#endif /* (SRSS_ECO_PRESENT == 1U) */
#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)
#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U)
case CY_ROOT_PATH_SRC_ALTHF:
srcFreqHz = cy_BleEcoClockFreqHz;
break;
#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) */
#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U) */
case CY_ROOT_PATH_SRC_DSI_MUX:
{
uint32_t dsi_src;
dsi_src = _FLD2VAL(SRSS_CLK_DSI_SELECT_DSI_MUX, SRSS->CLK_DSI_SELECT[rootPath]);
switch (dsi_src)
{
case CY_ROOT_PATH_SRC_DSI_MUX_HVILO:
srcFreqHz = CY_CLK_HVILO_FREQ_HZ;
break;
case CY_ROOT_PATH_SRC_DSI_MUX_WCO:
srcFreqHz = CY_CLK_WCO_FREQ_HZ;
break;
#if (SRSS_ALTLF_PRESENT == 1U)
case CY_ROOT_PATH_SRC_DSI_MUX_ALTLF:
srcFreqHz = CY_CLK_ALTLF_FREQ_HZ;
break;
#endif /* (SRSS_ALTLF_PRESENT == 1U) */
#if (SRSS_PILO_PRESENT == 1U)
case CY_ROOT_PATH_SRC_DSI_MUX_PILO:
srcFreqHz = CY_CLK_PILO_FREQ_HZ;
break;
#endif /* (SRSS_PILO_PRESENT == 1U) */
default:
srcFreqHz = CY_CLK_HVILO_FREQ_HZ;
break;
}
}
break;
default:
srcFreqHz = CY_EXT_FREQ_HZ;
srcFreqHz = CY_CLK_EXT_FREQ_HZ;
break;
}
@ -373,93 +374,24 @@ void SystemCoreClockUpdate (void)
}
/*******************************************************************************
* Function Name: Cy_SystemInitIpcCyPipeIsr
****************************************************************************//**
*
* This is the Interrupt Service Routine for the Cypress Pipe.
*
*******************************************************************************/
void Cy_SystemInitIpcCyPipeIsr(void)
{
Cy_IPC_PIPE_ExecCallback(&cy_ipc_pipe_sysEpArray[CY_IPC_EP_CYPIPE_ADDR]);
}
/*******************************************************************************
* Function Name: Cy_SystemInitIpc
****************************************************************************//**
*
* Performs initial IPC configuration.
*
*******************************************************************************/
void Cy_SystemInitIpc(void)
{
cy_stc_sysint_t ipc_intr_cypipeConfig;
Cy_IPC_PIPE_Config(cy_ipc_pipe_sysEpArray);
#if (CY_CPU_CORTEX_M0P)
/* Initialize the lock subsystem. Should be called only on one CPU. */
(void) Cy_IPC_LOCK_Init(CY_IPC_LOCK_COUNT, ipcLockArray);
#endif /* (CY_CPU_CORTEX_M0P) */
/* Initialize the pipe endpoints */
Cy_IPC_PIPE_Init(CY_IPC_EP_CYPIPE_ADDR, ipc_pipe_cyPipeCbArray, CY_IPC_CYPIPE_CLIENT_CNT, CY_IPC_CYPIPE_CONFIG);
/* Configure interrupts */
ipc_intr_cypipeConfig.intrSrc = CY_IPC_INTR_CYPIPE_SRC;
ipc_intr_cypipeConfig.intrCm0p = CY_IPC_INTR_CYPIPE_CM0SRC;
ipc_intr_cypipeConfig.intrPriority = CY_IPC_INTR_CYPIPE_PRIO;
Cy_SysInt_Init(&ipc_intr_cypipeConfig, &Cy_SystemInitIpcCyPipeIsr);
#if (CY_CPU_CORTEX_M0P)
NVIC_EnableIRQ((IRQn_Type)ipc_intr_cypipeConfig.intrCm0p);
#else
NVIC_EnableIRQ((IRQn_Type)ipc_intr_cypipeConfig.intrSrc);
#endif
}
#if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN)
/*******************************************************************************
* Function Name: Cy_SysGetCM4Status
****************************************************************************//**
*
* Gets the Cortex-M4 core mode.
* Returns the Cortex-M4 core power mode.
*
* \return \ref group_startup_macro
* \return \ref group_system_config_cm4_status_macro
*
*******************************************************************************/
uint32_t Cy_SysGetCM4Status(void)
{
uint32_t returnValue;
uint32_t regValue;
regValue = CPUSS->CM4_PWR_CTL & CPUSS_CM4_PWR_CTL_Msk;
switch(regValue)
{
case CPUSS_CM4_PWR_CTL_DISABLED:
returnValue = CY_SYS_CM4_STATUS_DISABLED;
break;
/* Get current power mode */
regValue = CPUSS->CM4_PWR_CTL & CPUSS_CM4_PWR_CTL_PWR_MODE_Msk;
case CPUSS_CM4_PWR_CTL_RETAINED:
returnValue = CY_SYS_CM4_STATUS_RETAINED;
break;
case CPUSS_CM4_PWR_CTL_ENABLED:
returnValue = CY_SYS_CM4_STATUS_ENABLED;
break;
case CPUSS_CM4_PWR_CTL_RESET_MODE:
returnValue = CY_SYS_CM4_STATUS_RESET;
break;
default:
returnValue = CY_SYS_CM4_STATUS_UNKNOWN;
break;
}
return (returnValue);
return (regValue);
}
@ -467,9 +399,9 @@ uint32_t Cy_SysGetCM4Status(void)
* Function Name: Cy_SysEnableCM4
****************************************************************************//**
*
* Enables the Cortex-M4 core. The CPU is enabled once if it was in the disabled
* or retained mode. If the CPU is enabled, the vector table base address is
* updated and software reset of the Cortex-M4 core is performed.
* Sets vector table base address and enables the Cortex-M4 core.
*
* \note If the CPU is already enabled, it is reset and then enabled.
*
* \param vectorTableOffset The offset of the vector table base address from
* memory address 0x00000000. The offset should be multiple to 1024 bytes.
@ -477,54 +409,28 @@ uint32_t Cy_SysGetCM4Status(void)
*******************************************************************************/
void Cy_SysEnableCM4(uint32_t vectorTableOffset)
{
uint32_t cm4Status;
uint32_t interruptState;
uint32_t regValue;
uint32_t interruptState;
uint32_t cpuState;
interruptState = Cy_SaveIRQ();
cm4Status = Cy_SysGetCM4Status();
switch(cm4Status)
cpuState = Cy_SysGetCM4Status();
if (CY_SYS_CM4_STATUS_ENABLED == cpuState)
{
case CY_SYS_CM4_STATUS_DISABLED:
CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset;
Cy_SysResetCM4();
}
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_POWER, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_ISOLATE, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
break;
CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset;
case CY_SYS_CM4_STATUS_RETAINED:
CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset;
regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
regValue |= CY_SYS_CM4_STATUS_ENABLED;
CPUSS->CM4_PWR_CTL = regValue;
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_POWER, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_RETAIN, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_ISOLATE, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
break;
case CY_SYS_CM4_STATUS_RESET:
CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset;
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
break;
case CY_SYS_CM4_STATUS_ENABLED:
CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset;
/* Move to Reset from Enabled state */
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
/* Move to Enabled from Reset state */
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
break;
default:
/* Do nothing if Cortex-M4 is already enabled. */
break;
while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL)
{
/* Wait for the power mode to take effect */
}
Cy_RestoreIRQ(interruptState);
@ -535,41 +441,32 @@ void Cy_SysEnableCM4(uint32_t vectorTableOffset)
* Function Name: Cy_SysDisableCM4
****************************************************************************//**
*
* Disables the Cortex-M4 core.
* Disables the Cortex-M4 core and waits for the mode to take the effect.
*
* \warning Do not call the function while the Cortex-M4 is executing because
* such a call may corrupt/abort a pending bus-transaction by the CPU and cause
* unexpected behavior in the system including a deadlock. Call the function
* while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use
* the \ref group_syspm Power Management (syspm) API to put the CPU into the
* low-power modes. Use the \ref SysPm_ReadStatus() to get a status of the CPU.
* low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the
* CPU.
*
*******************************************************************************/
void Cy_SysDisableCM4(void)
{
uint32_t cm4Status;
uint32_t interruptState;
uint32_t interruptState;
uint32_t regValue;
interruptState = Cy_SaveIRQ();
cm4Status = Cy_SysGetCM4Status();
switch(cm4Status)
regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
regValue |= CY_SYS_CM4_STATUS_DISABLED;
CPUSS->CM4_PWR_CTL = regValue;
while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL)
{
case CY_SYS_CM4_STATUS_ENABLED:
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_ISOLATE, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_POWER, 1UL);
break;
case CY_SYS_CM4_STATUS_RETAINED:
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_RETAIN, 1UL);
break;
default:
/* Do nothing if Cortex-M4 is already disabled. */
break;
/* Wait for the power mode to take effect */
}
Cy_RestoreIRQ(interruptState);
@ -580,7 +477,10 @@ void Cy_SysDisableCM4(void)
* Function Name: Cy_SysRetainCM4
****************************************************************************//**
*
* Retains the Cortex-M4 core.
* Retains the Cortex-M4 core and exists without waiting for the mode to take
* effect.
*
* \note The retained mode can be entered only from the enabled mode.
*
* \warning Do not call the function while the Cortex-M4 is executing because
* such a call may corrupt/abort a pending bus-transaction by the CPU and cause
@ -592,30 +492,15 @@ void Cy_SysDisableCM4(void)
*******************************************************************************/
void Cy_SysRetainCM4(void)
{
uint32_t cm4Status;
uint32_t interruptState;
uint32_t interruptState;
uint32_t regValue;
interruptState = Cy_SaveIRQ();
cm4Status = Cy_SysGetCM4Status();
switch(cm4Status)
{
case CY_SYS_CM4_STATUS_ENABLED:
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_ISOLATE, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_RETAIN, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_POWER, 1UL);
break;
case CY_SYS_CM4_STATUS_DISABLED:
/* Switch from the DISABLED to the RETAINED state is not valid.
* Do nothing in this case. */
break;
default:
/* Do nothing if Cortex-M4 is already in the RETAINED state. */
break;
}
regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
regValue |= CY_SYS_CM4_STATUS_RETAINED;
CPUSS->CM4_PWR_CTL = regValue;
Cy_RestoreIRQ(interruptState);
}
@ -625,7 +510,9 @@ void Cy_SysRetainCM4(void)
* Function Name: Cy_SysResetCM4
****************************************************************************//**
*
* Resets the Cortex-M4 core.
* Resets the Cortex-M4 core and waits for the mode to take the effect.
*
* \note The reset mode can not be entered from the retained mode.
*
* \warning Do not call the function while the Cortex-M4 is executing because
* such a call may corrupt/abort a pending bus-transaction by the CPU and cause
@ -637,31 +524,90 @@ void Cy_SysRetainCM4(void)
*******************************************************************************/
void Cy_SysResetCM4(void)
{
uint32_t cm4Status;
uint32_t interruptState;
uint32_t interruptState;
uint32_t regValue;
interruptState = Cy_SaveIRQ();
cm4Status = Cy_SysGetCM4Status();
switch(cm4Status)
regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
regValue |= CY_SYS_CM4_STATUS_RESET;
CPUSS->CM4_PWR_CTL = regValue;
while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL)
{
case CY_SYS_CM4_STATUS_ENABLED:
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_CLOCK, 1UL);
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_RESET, 1UL);
break;
case CY_SYS_CM4_STATUS_DISABLED:
CPUSS->CM4_PWR_CTL |= _VAL2FLD(CPUSS_CM4_PWR_CTL_ISOLATE, 1UL);
CPUSS->CM4_PWR_CTL &= ~_VAL2FLD(CPUSS_CM4_PWR_CTL_POWER, 1UL);
break;
default:
/* Do nothing if Cortex-M4 is already in the RETAINED state. */
break;
}
/* Wait for the power mode to take effect */
}
Cy_RestoreIRQ(interruptState);
}
#endif /* #if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN) */
/*******************************************************************************
* Function Name: Cy_MemorySymbols
****************************************************************************//**
*
* The intention of the function is to declare boundaries of the memories for the
* MDK compilers. For the rest of the supported compilers, this is done using
* linker configuration files. The following symbols used by the cypdlelftool.
*
*******************************************************************************/
#if defined (__ARMCC_VERSION)
__asm void Cy_MemorySymbols(void)
{
/* Flash */
EXPORT __cy_memory_0_start
EXPORT __cy_memory_0_length
EXPORT __cy_memory_0_row_size
/* Working Flash */
EXPORT __cy_memory_1_start
EXPORT __cy_memory_1_length
EXPORT __cy_memory_1_row_size
/* Supervisory Flash */
EXPORT __cy_memory_2_start
EXPORT __cy_memory_2_length
EXPORT __cy_memory_2_row_size
/* XIP */
EXPORT __cy_memory_3_start
EXPORT __cy_memory_3_length
EXPORT __cy_memory_3_row_size
/* eFuse */
EXPORT __cy_memory_4_start
EXPORT __cy_memory_4_length
EXPORT __cy_memory_4_row_size
/* Flash */
__cy_memory_0_start EQU __cpp(CY_FLASH_BASE)
__cy_memory_0_length EQU __cpp(CY_FLASH_SIZE)
__cy_memory_0_row_size EQU 0x200
/* Working Flash */
__cy_memory_1_start EQU __cpp(CY_WFLASH_BASE)
__cy_memory_1_length EQU __cpp(CY_WFLASH_SIZE)
__cy_memory_1_row_size EQU 0x200
/* Supervisory Flash */
__cy_memory_2_start EQU __cpp(CY_SFLASH_BASE)
__cy_memory_2_length EQU __cpp(CY_SFLASH_SIZE)
__cy_memory_2_row_size EQU 0x200
/* XIP */
__cy_memory_3_start EQU __cpp(CY_XIP_BASE)
__cy_memory_3_length EQU __cpp(CY_XIP_SIZE)
__cy_memory_3_row_size EQU 0x200
/* eFuse */
__cy_memory_4_start EQU __cpp(0x90700000)
__cy_memory_4_length EQU __cpp(0x100000)
__cy_memory_4_row_size EQU __cpp(1)
}
#endif /* defined (__ARMCC_VERSION) */
/* [] END OF FILE */

View File

@ -0,0 +1,131 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) XXX
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of ARM Limited nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#include "PeripheralNames.h"
#include "PeripheralPins.h"
#include "pinmap.h"
// //*** ADC ***
// const PinMap PinMap_ADC[] = {
// {PC_15, ADC_0, STM_PIN_DATA_EXT(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN0
// {PC_14, ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN1
// {PC_13, ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN2
// {PC_12, ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN3
// {PC_11, ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN4
// {PC_10, ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN5
// {PC_9 , ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN6
// {PC_8 , ADC_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF3)}, // ADC0_IN7
// {NC, NC, 0}
// };
// //*** DAC ***
// const PinMap PinMap_DAC[] = {
// {PA_4, DAC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // OUT1
// {PA_5, DAC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // OUT2 (Warning: LED1 is also on this pin)
// {NC, NC, 0}
// };
// //*** SERIAL ***
// const PinMap PinMap_UART_TX[] = {
// {PA_13, UART_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
// {PC_2, UART_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
// {PC_10, UART_2, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
// {NC, NC, 0}
// };
// const PinMap PinMap_UART_RX[] = {
// {PA_14, UART_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
// {PC_3, UART_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
// {PC_11, UART_2, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
// {NC, NC, 0}
// };
// //*** I2C ***
// const PinMap PinMap_I2C_SDA[] = {
// {PA_10, I2C_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_9, I2C_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PC_5, I2C_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PA_6, I2C_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC, NC, 0}
// };
// const PinMap PinMap_I2C_SCL[] = {
// {PA_9, I2C_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_8, I2C_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PC_4, I2C_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PA_5, I2C_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC, NC, 0}
// };
// //*** SPI ***
// const PinMap PinMap_SPI_SCLK[] = {
// {PA_6 , SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PB_1 , SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_13, SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PA_12, SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC , NC , 0}
// };
// const PinMap PinMap_SPI_MOSI[] = {
// {PA_8 , SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PB_3 , SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_15, SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PA_14, SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC , NC , 0}
// };
// const PinMap PinMap_SPI_MISO[] = {
// {PA_7 , SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PB_2 , SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_14, SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PA_13, SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC , NC , 0}
// };
// const PinMap PinMap_SPI_SSEL[] = {
// {PA_5 , SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PB_0 , SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_12, SPI_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PA_11, SPI_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC , NC , 0}
// };
// //*** PWM ***
// const PinMap PinMap_PWM[] = {
// {PA_0 , PWM_6, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PA_1 , PWM_7, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PA_5 , PWM_2, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF3)},
// {PA_7 , PWM_4, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF3)},
// {PA_8 , PWM_5, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF3)},
// {PA_9 , PWM_6, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF3)},
// {PA_10, PWM_7, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF3)},
// {PC_0 , PWM_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PC_2 , PWM_2, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PC_4 , PWM_4, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PC_5 , PWM_5, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {PC_8 , PWM_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)},
// {PC_10, PWM_2, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF2)},
// {NC , NC , WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_NOPULL, Px_AFSR_AF0)}
// };

View File

@ -0,0 +1,251 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) XXX
* 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_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#include "PinNamesTypes.h"
#include "PortNames.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CY_UART_RX P5_0
#define CY_UART_TX P5_1
// PinName[15-0] = Port[15-8] + Pin[7-0]
typedef enum {
P0_0 = (Port0 << 8) + 0x00,
P0_1 = (Port0 << 8) + 0x01,
P0_2 = (Port0 << 8) + 0x02,
P0_3 = (Port0 << 8) + 0x03,
P0_4 = (Port0 << 8) + 0x04,
P0_5 = (Port0 << 8) + 0x05,
P0_6 = (Port0 << 8) + 0x06,
P0_7 = (Port0 << 8) + 0x07,
P1_0 = (Port1 << 8) + 0x00,
P1_1 = (Port1 << 8) + 0x01,
P1_2 = (Port1 << 8) + 0x02,
P1_3 = (Port1 << 8) + 0x03,
P1_4 = (Port1 << 8) + 0x04,
P1_5 = (Port1 << 8) + 0x05,
P1_6 = (Port1 << 8) + 0x06,
P1_7 = (Port1 << 8) + 0x07,
P2_0 = (Port2 << 8) + 0x00,
P2_1 = (Port2 << 8) + 0x01,
P2_2 = (Port2 << 8) + 0x02,
P2_3 = (Port2 << 8) + 0x03,
P2_4 = (Port2 << 8) + 0x04,
P2_5 = (Port2 << 8) + 0x05,
P2_6 = (Port2 << 8) + 0x06,
P2_7 = (Port2 << 8) + 0x07,
P3_0 = (Port3 << 8) + 0x00,
P3_1 = (Port3 << 8) + 0x01,
P3_2 = (Port3 << 8) + 0x02,
P3_3 = (Port3 << 8) + 0x03,
P3_4 = (Port3 << 8) + 0x04,
P3_5 = (Port3 << 8) + 0x05,
P3_6 = (Port3 << 8) + 0x06,
P3_7 = (Port3 << 8) + 0x07,
P4_0 = (Port4 << 8) + 0x00,
P4_1 = (Port4 << 8) + 0x01,
P4_2 = (Port4 << 8) + 0x02,
P4_3 = (Port4 << 8) + 0x03,
P4_4 = (Port4 << 8) + 0x04,
P4_5 = (Port4 << 8) + 0x05,
P4_6 = (Port4 << 8) + 0x06,
P4_7 = (Port4 << 8) + 0x07,
P5_0 = (Port5 << 8) + 0x00,
P5_1 = (Port5 << 8) + 0x01,
P5_2 = (Port5 << 8) + 0x02,
P5_3 = (Port5 << 8) + 0x03,
P5_4 = (Port5 << 8) + 0x04,
P5_5 = (Port5 << 8) + 0x05,
P5_6 = (Port5 << 8) + 0x06,
P5_7 = (Port5 << 8) + 0x07,
P6_0 = (Port6 << 8) + 0x00,
P6_1 = (Port6 << 8) + 0x01,
P6_2 = (Port6 << 8) + 0x02,
P6_3 = (Port6 << 8) + 0x03,
P6_4 = (Port6 << 8) + 0x04,
P6_5 = (Port6 << 8) + 0x05,
P6_6 = (Port6 << 8) + 0x06,
P6_7 = (Port6 << 8) + 0x07,
P7_0 = (Port7 << 8) + 0x00,
P7_1 = (Port7 << 8) + 0x01,
P7_2 = (Port7 << 8) + 0x02,
P7_3 = (Port7 << 8) + 0x03,
P7_4 = (Port7 << 8) + 0x04,
P7_5 = (Port7 << 8) + 0x05,
P7_6 = (Port7 << 8) + 0x06,
P7_7 = (Port7 << 8) + 0x07,
P8_0 = (Port8 << 8) + 0x00,
P8_1 = (Port8 << 8) + 0x01,
P8_2 = (Port8 << 8) + 0x02,
P8_3 = (Port8 << 8) + 0x03,
P8_4 = (Port8 << 8) + 0x04,
P8_5 = (Port8 << 8) + 0x05,
P8_6 = (Port8 << 8) + 0x06,
P8_7 = (Port8 << 8) + 0x07,
P9_0 = (Port9 << 8) + 0x00,
P9_1 = (Port9 << 8) + 0x01,
P9_2 = (Port9 << 8) + 0x02,
P9_3 = (Port9 << 8) + 0x03,
P9_4 = (Port9 << 8) + 0x04,
P9_5 = (Port9 << 8) + 0x05,
P9_6 = (Port9 << 8) + 0x06,
P9_7 = (Port9 << 8) + 0x07,
P10_0 = (Port10 << 8) + 0x00,
P10_1 = (Port10 << 8) + 0x01,
P10_2 = (Port10 << 8) + 0x02,
P10_3 = (Port10 << 8) + 0x03,
P10_4 = (Port10 << 8) + 0x04,
P10_5 = (Port10 << 8) + 0x05,
P10_6 = (Port10 << 8) + 0x06,
P10_7 = (Port10 << 8) + 0x07,
P11_0 = (Port11 << 8) + 0x00,
P11_1 = (Port11 << 8) + 0x01,
P11_2 = (Port11 << 8) + 0x02,
P11_3 = (Port11 << 8) + 0x03,
P11_4 = (Port11 << 8) + 0x04,
P11_5 = (Port11 << 8) + 0x05,
P11_6 = (Port11 << 8) + 0x06,
P11_7 = (Port11 << 8) + 0x07,
P12_0 = (Port12 << 8) + 0x00,
P12_1 = (Port12 << 8) + 0x01,
P12_2 = (Port12 << 8) + 0x02,
P12_3 = (Port12 << 8) + 0x03,
P12_4 = (Port12 << 8) + 0x04,
P12_5 = (Port12 << 8) + 0x05,
P12_6 = (Port12 << 8) + 0x06,
P12_7 = (Port12 << 8) + 0x07,
P13_0 = (Port13 << 8) + 0x00,
P13_1 = (Port13 << 8) + 0x01,
P13_2 = (Port13 << 8) + 0x02,
P13_3 = (Port13 << 8) + 0x03,
P13_4 = (Port13 << 8) + 0x04,
P13_5 = (Port13 << 8) + 0x05,
P13_6 = (Port13 << 8) + 0x06,
P13_7 = (Port13 << 8) + 0x07,
P14_0 = (Port14 << 8) + 0x00,
P14_1 = (Port14 << 8) + 0x01,
P14_2 = (Port14 << 8) + 0x02,
P14_3 = (Port14 << 8) + 0x03,
P14_4 = (Port14 << 8) + 0x04,
P14_5 = (Port14 << 8) + 0x05,
P14_6 = (Port14 << 8) + 0x06,
P14_7 = (Port14 << 8) + 0x07,
P15_0 = (Port15 << 8) + 0x00,
P15_1 = (Port15 << 8) + 0x01,
P15_2 = (Port15 << 8) + 0x02,
P15_3 = (Port15 << 8) + 0x03,
P15_4 = (Port15 << 8) + 0x04,
P15_5 = (Port15 << 8) + 0x05,
P15_6 = (Port15 << 8) + 0x06,
P15_7 = (Port15 << 8) + 0x07,
// Arduino connector namings
A0 = P10_0,
A1 = P10_1,
A2 = P10_2,
A3 = P10_3,
A4 = P10_4,
A5 = P10_5,
D0 = P5_0,
D1 = P5_1,
D2 = P5_2,
D3 = P5_3,
D4 = P5_4,
D5 = P5_5,
D6 = P5_6,
D7 = P0_2,
D8 = P13_0,
D9 = P13_1,
D10 = P12_3,
D11 = P12_0,
D12 = P12_1,
D13 = P12_2,
// Generic signals namings
LED_RED = P0_3,
LED_GREEN = P1_1,
LED_BLUE = P11_1,
SWITCH2 = P0_4,
LED1 = LED_RED,
LED2 = LED_GREEN,
LED3 = LED_BLUE,
LED4 = LED_RED,
USER_BUTTON = SWITCH2,
BUTTON1 = USER_BUTTON,
// Standardized interfaces names
SERIAL_TX = CY_UART_TX,
SERIAL_RX = CY_UART_RX,
USBTX = CY_UART_TX,
USBRX = CY_UART_RX,
// I2C_SCL = PB_8,
// I2C_SDA = PB_9,
// SPI_MOSI = PA_7,
// SPI_MISO = PA_6,
// SPI_SCK = PA_5,
// SPI_CS = PB_6,
// PWM_OUT = PB_3,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,381 @@
/***************************************************************************//**
* \file cy8c6xx7_cm4_dual.ld
* \version 2.0
*
* Linker file for the GNU C compiler.
*
* \note The entry point location is fixed and starts at 0x10000000. The valid
* application image should be placed there.
*
* \note The linker files included with the PDL template projects must be generic
* and handle all common use cases. Your project may not use every section
* defined in the linker files. In that case you may see warnings during the
* build process. In your project, you can simply comment out or remove the
* relevant code in the linker file.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
ENTRY(Reset_Handler)
/* Force symbol to be entered in the output file as an undefined symbol. Doing
* this may, for example, trigger linking of additional modules from standard
* libraries. You may list several symbols for each EXTERN, and you may use
* EXTERN multiple times. This command has the same effect as the -u command-line
* option.
*/
EXTERN(Reset_Handler)
/* Linker script to configure memory regions. */
MEMORY
{
flash (rx) : ORIGIN = 0x10080000, LENGTH = 0x80000
wflash (rx) : ORIGIN = 0x14000000, LENGTH = 0x8000 /* 32 KB */
sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800
sflash_nar (rx) : ORIGIN = 0x16001A00, LENGTH = 0x200
sflash_public_key (rx) : ORIGIN = 0x16005A00, LENGTH = 0xC00
sflash_toc_2 (rx) : ORIGIN = 0x16007C00, LENGTH = 0x400
xip (rx) : ORIGIN = 0x18000000, LENGTH = 0x8000000 /* 128 MB */
efuse (r) : ORIGIN = 0x90700000, LENGTH = 0x100000 /* 1 MB */
ram (rwx) : ORIGIN = 0x08024000, LENGTH = 0x23800
}
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __copy_table_start__
* __copy_table_end__
* __zero_table_start__
* __zero_table_end__
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
* __Vectors_End
* __Vectors_Size
*/
SECTIONS
{
.text :
{
. = ALIGN(4);
__Vectors = . ;
KEEP(*(.vectors))
. = ALIGN(4);
__Vectors_End = .;
__Vectors_Size = __Vectors_End - __Vectors;
__end__ = .;
. = ALIGN(4);
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
/* Read-only code (constants). */
*(.rodata .rodata.* .constdata .constdata.* .conststring .conststring.*)
KEEP(*(.eh_frame*))
} > flash
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > flash
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > flash
__exidx_end = .;
/* To copy multiple ROM to RAM sections,
* uncomment .copy.table section and,
* define __STARTUP_COPY_MULTIPLE in startup_psoc63_cm4.S */
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
/* Copy interrupt vectors from flash to RAM */
LONG (__Vectors) /* From */
LONG (__ram_vectors_start__) /* To */
LONG (__Vectors_End - __Vectors) /* Size */
/* Copy data section to RAM */
LONG (__etext) /* From */
LONG (__data_start__) /* To */
LONG (__data_end__ - __data_start__) /* Size */
__copy_table_end__ = .;
} > flash
/* To clear multiple BSS sections,
* uncomment .zero.table section and,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_psoc63_cm4.S */
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
__zero_table_end__ = .;
} > flash
__etext = . ;
.ramVectors (NOLOAD) : ALIGN(8)
{
__ram_vectors_start__ = .;
KEEP(*(.ram_vectors))
__ram_vectors_end__ = .;
} > ram
.data __ram_vectors_end__ : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
KEEP(*(.cy_ramfunc*))
. = ALIGN(4);
__data_end__ = .;
} > ram
/* Place variables in the section that should not be initialized during the
* device startup.
*/
.noinit (NOLOAD) : ALIGN(8)
{
KEEP(*(.noinit))
} > ram
/* The uninitialized global or static variables are placed in this section.
*
* The NOLOAD attribute tells linker that .bss section does not consume
* any space in the image. The NOLOAD attribute changes the .bss type to
* NOBITS, and that makes linker to A) not allocate section in memory, and
* A) put information to clear the section with all zeros during application
* loading.
*
* Without the NOLOAD attribute, the .bss section might get PROGBITS type.
* This makes linker to A) allocate zeroed section in memory, and B) copy
* this section to RAM during application loading.
*/
.bss (NOLOAD):
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > ram
.heap (NOLOAD):
{
__HeapBase = .;
__end__ = .;
end = __end__;
KEEP(*(.heap*))
__HeapLimit = .;
} > ram
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (NOLOAD):
{
KEEP(*(.stack*))
} > ram
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(ram) + LENGTH(ram);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
/* Used for the digital signature of the secure application and the Bootloader SDK appication.
* The size of the section depends on the required data size. */
.cy_app_signature ORIGIN(flash) + LENGTH(flash) - 256 :
{
KEEP(*(.cy_app_signature))
} > flash
/* Work Flash */
.cy_wflash :
{
KEEP(*(.cy_wflash))
} > wflash
/* Supervisory Flash: User data */
.cy_sflash_user_data :
{
KEEP(*(.cy_sflash_user_data))
} > sflash_user_data
/* Supervisory Flash: Normal Access Restrictions (NAR) */
.cy_sflash_nar :
{
KEEP(*(.cy_sflash_nar))
} > sflash_nar
/* Supervisory Flash: Public Key */
.cy_sflash_public_key :
{
KEEP(*(.cy_sflash_public_key))
} > sflash_public_key
/* Supervisory Flash: Table of Content # 2 */
.cy_toc_part2 :
{
KEEP(*(.cy_toc_part2))
} > sflash_toc_2
/* Places the code in the Execute in Place (XIP) section. See the smif driver
* documentation for details.
*/
.cy_xip :
{
KEEP(*(.cy_xip))
} > xip
/* eFuse */
.cy_efuse :
{
KEEP(*(.cy_efuse))
} > efuse
/* These sections are used for additional metadata (silicon revision,
* Silicon/JTAG ID, etc.) storage.
*/
.cymeta 0x90500000 : { KEEP(*(.cymeta)) } :NONE
}
/* The following symbols used by the cypdlelftool. */
/* Flash */
__cy_memory_0_start = 0x10000000;
__cy_memory_0_length = 0x00100000;
__cy_memory_0_row_size = 0x200;
/* Working Flash */
__cy_memory_1_start = 0x14000000;
__cy_memory_1_length = 0x8000;
__cy_memory_1_row_size = 0x200;
/* Supervisory Flash */
__cy_memory_2_start = 0x16000000;
__cy_memory_2_length = 0x8000;
__cy_memory_2_row_size = 0x200;
/* XIP */
__cy_memory_3_start = 0x18000000;
__cy_memory_3_length = 0x08000000;
__cy_memory_3_row_size = 0x200;
/* eFuse */
__cy_memory_4_start = 0x90700000;
__cy_memory_4_length = 0x100000;
__cy_memory_4_row_size = 1;
/* EOF */

View File

@ -0,0 +1,646 @@
/**************************************************************************//**
* @file startup_psoc63_cm4.s
* @brief CMSIS Core Device Startup File for
* ARMCM4 Device Series
* @version V5.00
* @date 02. March 2016
******************************************************************************/
/*
* Copyright (c) 2009-2016 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* 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.
*/
/* Address of the NMI handler */
#define CY_NMI_HANLDER_ADDR 0x0000000D
/* The CPU VTOR register */
#define CY_CPU_VTOR_ADDR 0xE000ED08
/* Copy flash vectors and data section to RAM */
#define __STARTUP_COPY_MULTIPLE
/* Clear single BSS section */
#define __STARTUP_CLEAR_BSS
.syntax unified
.arch armv7-m
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0x00001000
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0x00000400
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.if Heap_Size
.space Heap_Size
.endif
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .vectors
.align 2
.globl __Vectors
__Vectors:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long CY_NMI_HANLDER_ADDR /* 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 Description */
.long ioss_interrupts_gpio_0_IRQHandler /* GPIO Port Interrupt #0 */
.long ioss_interrupts_gpio_1_IRQHandler /* GPIO Port Interrupt #1 */
.long ioss_interrupts_gpio_2_IRQHandler /* GPIO Port Interrupt #2 */
.long ioss_interrupts_gpio_3_IRQHandler /* GPIO Port Interrupt #3 */
.long ioss_interrupts_gpio_4_IRQHandler /* GPIO Port Interrupt #4 */
.long ioss_interrupts_gpio_5_IRQHandler /* GPIO Port Interrupt #5 */
.long ioss_interrupts_gpio_6_IRQHandler /* GPIO Port Interrupt #6 */
.long ioss_interrupts_gpio_7_IRQHandler /* GPIO Port Interrupt #7 */
.long ioss_interrupts_gpio_8_IRQHandler /* GPIO Port Interrupt #8 */
.long ioss_interrupts_gpio_9_IRQHandler /* GPIO Port Interrupt #9 */
.long ioss_interrupts_gpio_10_IRQHandler /* GPIO Port Interrupt #10 */
.long ioss_interrupts_gpio_11_IRQHandler /* GPIO Port Interrupt #11 */
.long ioss_interrupts_gpio_12_IRQHandler /* GPIO Port Interrupt #12 */
.long ioss_interrupts_gpio_13_IRQHandler /* GPIO Port Interrupt #13 */
.long ioss_interrupts_gpio_14_IRQHandler /* GPIO Port Interrupt #14 */
.long ioss_interrupt_gpio_IRQHandler /* GPIO All Ports */
.long ioss_interrupt_vdd_IRQHandler /* GPIO Supply Detect Interrupt */
.long lpcomp_interrupt_IRQHandler /* Low Power Comparator Interrupt */
.long scb_8_interrupt_IRQHandler /* Serial Communication Block #8 (DeepSleep capable) */
.long srss_interrupt_mcwdt_0_IRQHandler /* Multi Counter Watchdog Timer interrupt */
.long srss_interrupt_mcwdt_1_IRQHandler /* Multi Counter Watchdog Timer interrupt */
.long srss_interrupt_backup_IRQHandler /* Backup domain interrupt */
.long srss_interrupt_IRQHandler /* Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */
.long pass_interrupt_ctbs_IRQHandler /* CTBm Interrupt (all CTBms) */
.long bless_interrupt_IRQHandler /* Bluetooth Radio interrupt */
.long cpuss_interrupts_ipc_0_IRQHandler /* CPUSS Inter Process Communication Interrupt #0 */
.long cpuss_interrupts_ipc_1_IRQHandler /* CPUSS Inter Process Communication Interrupt #1 */
.long cpuss_interrupts_ipc_2_IRQHandler /* CPUSS Inter Process Communication Interrupt #2 */
.long cpuss_interrupts_ipc_3_IRQHandler /* CPUSS Inter Process Communication Interrupt #3 */
.long cpuss_interrupts_ipc_4_IRQHandler /* CPUSS Inter Process Communication Interrupt #4 */
.long cpuss_interrupts_ipc_5_IRQHandler /* CPUSS Inter Process Communication Interrupt #5 */
.long cpuss_interrupts_ipc_6_IRQHandler /* CPUSS Inter Process Communication Interrupt #6 */
.long cpuss_interrupts_ipc_7_IRQHandler /* CPUSS Inter Process Communication Interrupt #7 */
.long cpuss_interrupts_ipc_8_IRQHandler /* CPUSS Inter Process Communication Interrupt #8 */
.long cpuss_interrupts_ipc_9_IRQHandler /* CPUSS Inter Process Communication Interrupt #9 */
.long cpuss_interrupts_ipc_10_IRQHandler /* CPUSS Inter Process Communication Interrupt #10 */
.long cpuss_interrupts_ipc_11_IRQHandler /* CPUSS Inter Process Communication Interrupt #11 */
.long cpuss_interrupts_ipc_12_IRQHandler /* CPUSS Inter Process Communication Interrupt #12 */
.long cpuss_interrupts_ipc_13_IRQHandler /* CPUSS Inter Process Communication Interrupt #13 */
.long cpuss_interrupts_ipc_14_IRQHandler /* CPUSS Inter Process Communication Interrupt #14 */
.long cpuss_interrupts_ipc_15_IRQHandler /* CPUSS Inter Process Communication Interrupt #15 */
.long scb_0_interrupt_IRQHandler /* Serial Communication Block #0 */
.long scb_1_interrupt_IRQHandler /* Serial Communication Block #1 */
.long scb_2_interrupt_IRQHandler /* Serial Communication Block #2 */
.long scb_3_interrupt_IRQHandler /* Serial Communication Block #3 */
.long scb_4_interrupt_IRQHandler /* Serial Communication Block #4 */
.long scb_5_interrupt_IRQHandler /* Serial Communication Block #5 */
.long scb_6_interrupt_IRQHandler /* Serial Communication Block #6 */
.long scb_7_interrupt_IRQHandler /* Serial Communication Block #7 */
.long csd_interrupt_IRQHandler /* CSD (Capsense) interrupt */
.long cpuss_interrupts_dw0_0_IRQHandler /* CPUSS DataWire #0, Channel #0 */
.long cpuss_interrupts_dw0_1_IRQHandler /* CPUSS DataWire #0, Channel #1 */
.long cpuss_interrupts_dw0_2_IRQHandler /* CPUSS DataWire #0, Channel #2 */
.long cpuss_interrupts_dw0_3_IRQHandler /* CPUSS DataWire #0, Channel #3 */
.long cpuss_interrupts_dw0_4_IRQHandler /* CPUSS DataWire #0, Channel #4 */
.long cpuss_interrupts_dw0_5_IRQHandler /* CPUSS DataWire #0, Channel #5 */
.long cpuss_interrupts_dw0_6_IRQHandler /* CPUSS DataWire #0, Channel #6 */
.long cpuss_interrupts_dw0_7_IRQHandler /* CPUSS DataWire #0, Channel #7 */
.long cpuss_interrupts_dw0_8_IRQHandler /* CPUSS DataWire #0, Channel #8 */
.long cpuss_interrupts_dw0_9_IRQHandler /* CPUSS DataWire #0, Channel #9 */
.long cpuss_interrupts_dw0_10_IRQHandler /* CPUSS DataWire #0, Channel #10 */
.long cpuss_interrupts_dw0_11_IRQHandler /* CPUSS DataWire #0, Channel #11 */
.long cpuss_interrupts_dw0_12_IRQHandler /* CPUSS DataWire #0, Channel #12 */
.long cpuss_interrupts_dw0_13_IRQHandler /* CPUSS DataWire #0, Channel #13 */
.long cpuss_interrupts_dw0_14_IRQHandler /* CPUSS DataWire #0, Channel #14 */
.long cpuss_interrupts_dw0_15_IRQHandler /* CPUSS DataWire #0, Channel #15 */
.long cpuss_interrupts_dw1_0_IRQHandler /* CPUSS DataWire #1, Channel #0 */
.long cpuss_interrupts_dw1_1_IRQHandler /* CPUSS DataWire #1, Channel #1 */
.long cpuss_interrupts_dw1_2_IRQHandler /* CPUSS DataWire #1, Channel #2 */
.long cpuss_interrupts_dw1_3_IRQHandler /* CPUSS DataWire #1, Channel #3 */
.long cpuss_interrupts_dw1_4_IRQHandler /* CPUSS DataWire #1, Channel #4 */
.long cpuss_interrupts_dw1_5_IRQHandler /* CPUSS DataWire #1, Channel #5 */
.long cpuss_interrupts_dw1_6_IRQHandler /* CPUSS DataWire #1, Channel #6 */
.long cpuss_interrupts_dw1_7_IRQHandler /* CPUSS DataWire #1, Channel #7 */
.long cpuss_interrupts_dw1_8_IRQHandler /* CPUSS DataWire #1, Channel #8 */
.long cpuss_interrupts_dw1_9_IRQHandler /* CPUSS DataWire #1, Channel #9 */
.long cpuss_interrupts_dw1_10_IRQHandler /* CPUSS DataWire #1, Channel #10 */
.long cpuss_interrupts_dw1_11_IRQHandler /* CPUSS DataWire #1, Channel #11 */
.long cpuss_interrupts_dw1_12_IRQHandler /* CPUSS DataWire #1, Channel #12 */
.long cpuss_interrupts_dw1_13_IRQHandler /* CPUSS DataWire #1, Channel #13 */
.long cpuss_interrupts_dw1_14_IRQHandler /* CPUSS DataWire #1, Channel #14 */
.long cpuss_interrupts_dw1_15_IRQHandler /* CPUSS DataWire #1, Channel #15 */
.long cpuss_interrupts_fault_0_IRQHandler /* CPUSS Fault Structure Interrupt #0 */
.long cpuss_interrupts_fault_1_IRQHandler /* CPUSS Fault Structure Interrupt #1 */
.long cpuss_interrupt_crypto_IRQHandler /* CRYPTO Accelerator Interrupt */
.long cpuss_interrupt_fm_IRQHandler /* FLASH Macro Interrupt */
.long cpuss_interrupts_cm0_cti_0_IRQHandler /* CM0+ CTI #0 */
.long cpuss_interrupts_cm0_cti_1_IRQHandler /* CM0+ CTI #1 */
.long cpuss_interrupts_cm4_cti_0_IRQHandler /* CM4 CTI #0 */
.long cpuss_interrupts_cm4_cti_1_IRQHandler /* CM4 CTI #1 */
.long tcpwm_0_interrupts_0_IRQHandler /* TCPWM #0, Counter #0 */
.long tcpwm_0_interrupts_1_IRQHandler /* TCPWM #0, Counter #1 */
.long tcpwm_0_interrupts_2_IRQHandler /* TCPWM #0, Counter #2 */
.long tcpwm_0_interrupts_3_IRQHandler /* TCPWM #0, Counter #3 */
.long tcpwm_0_interrupts_4_IRQHandler /* TCPWM #0, Counter #4 */
.long tcpwm_0_interrupts_5_IRQHandler /* TCPWM #0, Counter #5 */
.long tcpwm_0_interrupts_6_IRQHandler /* TCPWM #0, Counter #6 */
.long tcpwm_0_interrupts_7_IRQHandler /* TCPWM #0, Counter #7 */
.long tcpwm_1_interrupts_0_IRQHandler /* TCPWM #1, Counter #0 */
.long tcpwm_1_interrupts_1_IRQHandler /* TCPWM #1, Counter #1 */
.long tcpwm_1_interrupts_2_IRQHandler /* TCPWM #1, Counter #2 */
.long tcpwm_1_interrupts_3_IRQHandler /* TCPWM #1, Counter #3 */
.long tcpwm_1_interrupts_4_IRQHandler /* TCPWM #1, Counter #4 */
.long tcpwm_1_interrupts_5_IRQHandler /* TCPWM #1, Counter #5 */
.long tcpwm_1_interrupts_6_IRQHandler /* TCPWM #1, Counter #6 */
.long tcpwm_1_interrupts_7_IRQHandler /* TCPWM #1, Counter #7 */
.long tcpwm_1_interrupts_8_IRQHandler /* TCPWM #1, Counter #8 */
.long tcpwm_1_interrupts_9_IRQHandler /* TCPWM #1, Counter #9 */
.long tcpwm_1_interrupts_10_IRQHandler /* TCPWM #1, Counter #10 */
.long tcpwm_1_interrupts_11_IRQHandler /* TCPWM #1, Counter #11 */
.long tcpwm_1_interrupts_12_IRQHandler /* TCPWM #1, Counter #12 */
.long tcpwm_1_interrupts_13_IRQHandler /* TCPWM #1, Counter #13 */
.long tcpwm_1_interrupts_14_IRQHandler /* TCPWM #1, Counter #14 */
.long tcpwm_1_interrupts_15_IRQHandler /* TCPWM #1, Counter #15 */
.long tcpwm_1_interrupts_16_IRQHandler /* TCPWM #1, Counter #16 */
.long tcpwm_1_interrupts_17_IRQHandler /* TCPWM #1, Counter #17 */
.long tcpwm_1_interrupts_18_IRQHandler /* TCPWM #1, Counter #18 */
.long tcpwm_1_interrupts_19_IRQHandler /* TCPWM #1, Counter #19 */
.long tcpwm_1_interrupts_20_IRQHandler /* TCPWM #1, Counter #20 */
.long tcpwm_1_interrupts_21_IRQHandler /* TCPWM #1, Counter #21 */
.long tcpwm_1_interrupts_22_IRQHandler /* TCPWM #1, Counter #22 */
.long tcpwm_1_interrupts_23_IRQHandler /* TCPWM #1, Counter #23 */
.long udb_interrupts_0_IRQHandler /* UDB Interrupt #0 */
.long udb_interrupts_1_IRQHandler /* UDB Interrupt #1 */
.long udb_interrupts_2_IRQHandler /* UDB Interrupt #2 */
.long udb_interrupts_3_IRQHandler /* UDB Interrupt #3 */
.long udb_interrupts_4_IRQHandler /* UDB Interrupt #4 */
.long udb_interrupts_5_IRQHandler /* UDB Interrupt #5 */
.long udb_interrupts_6_IRQHandler /* UDB Interrupt #6 */
.long udb_interrupts_7_IRQHandler /* UDB Interrupt #7 */
.long udb_interrupts_8_IRQHandler /* UDB Interrupt #8 */
.long udb_interrupts_9_IRQHandler /* UDB Interrupt #9 */
.long udb_interrupts_10_IRQHandler /* UDB Interrupt #10 */
.long udb_interrupts_11_IRQHandler /* UDB Interrupt #11 */
.long udb_interrupts_12_IRQHandler /* UDB Interrupt #12 */
.long udb_interrupts_13_IRQHandler /* UDB Interrupt #13 */
.long udb_interrupts_14_IRQHandler /* UDB Interrupt #14 */
.long udb_interrupts_15_IRQHandler /* UDB Interrupt #15 */
.long pass_interrupt_sar_IRQHandler /* SAR ADC interrupt */
.long audioss_interrupt_i2s_IRQHandler /* I2S Audio interrupt */
.long audioss_interrupt_pdm_IRQHandler /* PDM/PCM Audio interrupt */
.long profile_interrupt_IRQHandler /* Energy Profiler interrupt */
.long smif_interrupt_IRQHandler /* Serial Memory Interface interrupt */
.long usb_interrupt_hi_IRQHandler /* USB Interrupt */
.long usb_interrupt_med_IRQHandler /* USB Interrupt */
.long usb_interrupt_lo_IRQHandler /* USB Interrupt */
.long pass_interrupt_dacs_IRQHandler /* Consolidated interrrupt for all DACs */
.size __Vectors, . - __Vectors
.equ __VectorsSize, . - __Vectors
.section .ram_vectors
.align 2
.globl __ramVectors
__ramVectors:
.space __VectorsSize
.size __ramVectors, . - __ramVectors
.text
.thumb
.thumb_func
.align 2
/* Device startup customization */
.weak Cy_OnResetUser
.func Cy_OnResetUser, Cy_OnResetUser
.type Cy_OnResetUser, %function
Cy_OnResetUser:
bx lr
.size Cy_OnResetUser, . - Cy_OnResetUser
.endfunc
/* Saves and disables the interrupts */
.global Cy_SaveIRQ
.func Cy_SaveIRQ, Cy_SaveIRQ
.type Cy_SaveIRQ, %function
Cy_SaveIRQ:
mrs r0, PRIMASK
cpsid i
bx lr
.size Cy_SaveIRQ, . - Cy_SaveIRQ
.endfunc
/* Restores the interrupts */
.global Cy_RestoreIRQ
.func Cy_RestoreIRQ, Cy_RestoreIRQ
.type Cy_RestoreIRQ, %function
Cy_RestoreIRQ:
msr PRIMASK, r0
bx lr
.size Cy_RestoreIRQ, . - Cy_RestoreIRQ
.endfunc
/* Reset handler */
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
bl Cy_OnResetUser
cpsid i
/* Firstly it copies data from read only memory to RAM. There are two schemes
* to copy. One can copy more than one sections. Another can only copy
* one section. The former scheme needs more instructions and read-only
* data to implement than the latter.
* Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
#ifdef __STARTUP_COPY_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of triplets, each of which specify:
* offset 0: LMA of start of a section to copy from
* offset 4: VMA of start of a section to copy to
* offset 8: size of the section to copy. Must be multiply of 4
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r4, =__copy_table_start__
ldr r5, =__copy_table_end__
.L_loop0:
cmp r4, r5
bge .L_loop0_done
ldr r1, [r4]
ldr r2, [r4, #4]
ldr r3, [r4, #8]
.L_loop0_0:
subs r3, #4
ittt ge
ldrge r0, [r1, r3]
strge r0, [r2, r3]
bge .L_loop0_0
adds r4, #12
b .L_loop0
.L_loop0_done:
#else
/* Single section scheme.
*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
.L_loop1:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .L_loop1
#endif /*__STARTUP_COPY_MULTIPLE */
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* There are two schemes too. One can clear multiple BSS sections. Another
* can only clear one section. The former is more size expensive than the
* latter.
*
* Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
* Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
*/
#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of tuples specifying:
* offset 0: Start of a BSS section
* offset 4: Size of this BSS section. Must be multiply of 4
*/
ldr r3, =__zero_table_start__
ldr r4, =__zero_table_end__
.L_loop2:
cmp r3, r4
bge .L_loop2_done
ldr r1, [r3]
ldr r2, [r3, #4]
movs r0, 0
.L_loop2_0:
subs r2, #4
itt ge
strge r0, [r1, r2]
bge .L_loop2_0
adds r3, #8
b .L_loop2
.L_loop2_done:
#elif defined (__STARTUP_CLEAR_BSS)
/* Single BSS section scheme.
*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
.L_loop3:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .L_loop3
#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
/* Update Vector Table Offset Register. */
ldr r0, =__ramVectors
ldr r1, =CY_CPU_VTOR_ADDR
str r0, [r1]
dsb 0xF
/* Enable the FPU if used */
bl Cy_SystemInitFpuEnable
#ifndef __NO_SYSTEM_INIT
bl SystemInit
#endif
bl main
/* Should never get here */
b .
.pool
.size Reset_Handler, . - Reset_Handler
.align 1
.thumb_func
.weak Default_Handler
.type Default_Handler, %function
Default_Handler:
b .
.size Default_Handler, . - Default_Handler
.weak Cy_SysLib_FaultHandler
.type Cy_SysLib_FaultHandler, %function
Cy_SysLib_FaultHandler:
b .
.size Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler
.type Fault_Handler, %function
Fault_Handler:
/* Storing LR content for Creator call stack trace */
push {LR}
movs r0, #4
mov r1, LR
tst r0, r1
beq .L_MSP
mrs r0, PSP
b .L_API_call
.L_MSP:
mrs r0, MSP
.L_API_call:
/* Compensation of stack pointer address due to pushing 4 bytes of LR */
adds r0, r0, #4
bl Cy_SysLib_FaultHandler
b .
.size Fault_Handler, . - Fault_Handler
.macro def_fault_Handler fault_handler_name
.weak \fault_handler_name
.set \fault_handler_name, Fault_Handler
.endm
/* 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, Default_Handler
.endm
def_irq_handler NMI_Handler
def_fault_Handler HardFault_Handler
def_fault_Handler MemManage_Handler
def_fault_Handler BusFault_Handler
def_fault_Handler UsageFault_Handler
def_irq_handler SVC_Handler
def_irq_handler DebugMon_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
def_irq_handler ioss_interrupts_gpio_0_IRQHandler /* GPIO Port Interrupt #0 */
def_irq_handler ioss_interrupts_gpio_1_IRQHandler /* GPIO Port Interrupt #1 */
def_irq_handler ioss_interrupts_gpio_2_IRQHandler /* GPIO Port Interrupt #2 */
def_irq_handler ioss_interrupts_gpio_3_IRQHandler /* GPIO Port Interrupt #3 */
def_irq_handler ioss_interrupts_gpio_4_IRQHandler /* GPIO Port Interrupt #4 */
def_irq_handler ioss_interrupts_gpio_5_IRQHandler /* GPIO Port Interrupt #5 */
def_irq_handler ioss_interrupts_gpio_6_IRQHandler /* GPIO Port Interrupt #6 */
def_irq_handler ioss_interrupts_gpio_7_IRQHandler /* GPIO Port Interrupt #7 */
def_irq_handler ioss_interrupts_gpio_8_IRQHandler /* GPIO Port Interrupt #8 */
def_irq_handler ioss_interrupts_gpio_9_IRQHandler /* GPIO Port Interrupt #9 */
def_irq_handler ioss_interrupts_gpio_10_IRQHandler /* GPIO Port Interrupt #10 */
def_irq_handler ioss_interrupts_gpio_11_IRQHandler /* GPIO Port Interrupt #11 */
def_irq_handler ioss_interrupts_gpio_12_IRQHandler /* GPIO Port Interrupt #12 */
def_irq_handler ioss_interrupts_gpio_13_IRQHandler /* GPIO Port Interrupt #13 */
def_irq_handler ioss_interrupts_gpio_14_IRQHandler /* GPIO Port Interrupt #14 */
def_irq_handler ioss_interrupt_gpio_IRQHandler /* GPIO All Ports */
def_irq_handler ioss_interrupt_vdd_IRQHandler /* GPIO Supply Detect Interrupt */
def_irq_handler lpcomp_interrupt_IRQHandler /* Low Power Comparator Interrupt */
def_irq_handler scb_8_interrupt_IRQHandler /* Serial Communication Block #8 (DeepSleep capable) */
def_irq_handler srss_interrupt_mcwdt_0_IRQHandler /* Multi Counter Watchdog Timer interrupt */
def_irq_handler srss_interrupt_mcwdt_1_IRQHandler /* Multi Counter Watchdog Timer interrupt */
def_irq_handler srss_interrupt_backup_IRQHandler /* Backup domain interrupt */
def_irq_handler srss_interrupt_IRQHandler /* Other combined Interrupts for SRSS (LVD, WDT, CLKCAL) */
def_irq_handler pass_interrupt_ctbs_IRQHandler /* CTBm Interrupt (all CTBms) */
def_irq_handler bless_interrupt_IRQHandler /* Bluetooth Radio interrupt */
def_irq_handler cpuss_interrupts_ipc_0_IRQHandler /* CPUSS Inter Process Communication Interrupt #0 */
def_irq_handler cpuss_interrupts_ipc_1_IRQHandler /* CPUSS Inter Process Communication Interrupt #1 */
def_irq_handler cpuss_interrupts_ipc_2_IRQHandler /* CPUSS Inter Process Communication Interrupt #2 */
def_irq_handler cpuss_interrupts_ipc_3_IRQHandler /* CPUSS Inter Process Communication Interrupt #3 */
def_irq_handler cpuss_interrupts_ipc_4_IRQHandler /* CPUSS Inter Process Communication Interrupt #4 */
def_irq_handler cpuss_interrupts_ipc_5_IRQHandler /* CPUSS Inter Process Communication Interrupt #5 */
def_irq_handler cpuss_interrupts_ipc_6_IRQHandler /* CPUSS Inter Process Communication Interrupt #6 */
def_irq_handler cpuss_interrupts_ipc_7_IRQHandler /* CPUSS Inter Process Communication Interrupt #7 */
def_irq_handler cpuss_interrupts_ipc_8_IRQHandler /* CPUSS Inter Process Communication Interrupt #8 */
def_irq_handler cpuss_interrupts_ipc_9_IRQHandler /* CPUSS Inter Process Communication Interrupt #9 */
def_irq_handler cpuss_interrupts_ipc_10_IRQHandler /* CPUSS Inter Process Communication Interrupt #10 */
def_irq_handler cpuss_interrupts_ipc_11_IRQHandler /* CPUSS Inter Process Communication Interrupt #11 */
def_irq_handler cpuss_interrupts_ipc_12_IRQHandler /* CPUSS Inter Process Communication Interrupt #12 */
def_irq_handler cpuss_interrupts_ipc_13_IRQHandler /* CPUSS Inter Process Communication Interrupt #13 */
def_irq_handler cpuss_interrupts_ipc_14_IRQHandler /* CPUSS Inter Process Communication Interrupt #14 */
def_irq_handler cpuss_interrupts_ipc_15_IRQHandler /* CPUSS Inter Process Communication Interrupt #15 */
def_irq_handler scb_0_interrupt_IRQHandler /* Serial Communication Block #0 */
def_irq_handler scb_1_interrupt_IRQHandler /* Serial Communication Block #1 */
def_irq_handler scb_2_interrupt_IRQHandler /* Serial Communication Block #2 */
def_irq_handler scb_3_interrupt_IRQHandler /* Serial Communication Block #3 */
def_irq_handler scb_4_interrupt_IRQHandler /* Serial Communication Block #4 */
def_irq_handler scb_5_interrupt_IRQHandler /* Serial Communication Block #5 */
def_irq_handler scb_6_interrupt_IRQHandler /* Serial Communication Block #6 */
def_irq_handler scb_7_interrupt_IRQHandler /* Serial Communication Block #7 */
def_irq_handler csd_interrupt_IRQHandler /* CSD (Capsense) interrupt */
def_irq_handler cpuss_interrupts_dw0_0_IRQHandler /* CPUSS DataWire #0, Channel #0 */
def_irq_handler cpuss_interrupts_dw0_1_IRQHandler /* CPUSS DataWire #0, Channel #1 */
def_irq_handler cpuss_interrupts_dw0_2_IRQHandler /* CPUSS DataWire #0, Channel #2 */
def_irq_handler cpuss_interrupts_dw0_3_IRQHandler /* CPUSS DataWire #0, Channel #3 */
def_irq_handler cpuss_interrupts_dw0_4_IRQHandler /* CPUSS DataWire #0, Channel #4 */
def_irq_handler cpuss_interrupts_dw0_5_IRQHandler /* CPUSS DataWire #0, Channel #5 */
def_irq_handler cpuss_interrupts_dw0_6_IRQHandler /* CPUSS DataWire #0, Channel #6 */
def_irq_handler cpuss_interrupts_dw0_7_IRQHandler /* CPUSS DataWire #0, Channel #7 */
def_irq_handler cpuss_interrupts_dw0_8_IRQHandler /* CPUSS DataWire #0, Channel #8 */
def_irq_handler cpuss_interrupts_dw0_9_IRQHandler /* CPUSS DataWire #0, Channel #9 */
def_irq_handler cpuss_interrupts_dw0_10_IRQHandler /* CPUSS DataWire #0, Channel #10 */
def_irq_handler cpuss_interrupts_dw0_11_IRQHandler /* CPUSS DataWire #0, Channel #11 */
def_irq_handler cpuss_interrupts_dw0_12_IRQHandler /* CPUSS DataWire #0, Channel #12 */
def_irq_handler cpuss_interrupts_dw0_13_IRQHandler /* CPUSS DataWire #0, Channel #13 */
def_irq_handler cpuss_interrupts_dw0_14_IRQHandler /* CPUSS DataWire #0, Channel #14 */
def_irq_handler cpuss_interrupts_dw0_15_IRQHandler /* CPUSS DataWire #0, Channel #15 */
def_irq_handler cpuss_interrupts_dw1_0_IRQHandler /* CPUSS DataWire #1, Channel #0 */
def_irq_handler cpuss_interrupts_dw1_1_IRQHandler /* CPUSS DataWire #1, Channel #1 */
def_irq_handler cpuss_interrupts_dw1_2_IRQHandler /* CPUSS DataWire #1, Channel #2 */
def_irq_handler cpuss_interrupts_dw1_3_IRQHandler /* CPUSS DataWire #1, Channel #3 */
def_irq_handler cpuss_interrupts_dw1_4_IRQHandler /* CPUSS DataWire #1, Channel #4 */
def_irq_handler cpuss_interrupts_dw1_5_IRQHandler /* CPUSS DataWire #1, Channel #5 */
def_irq_handler cpuss_interrupts_dw1_6_IRQHandler /* CPUSS DataWire #1, Channel #6 */
def_irq_handler cpuss_interrupts_dw1_7_IRQHandler /* CPUSS DataWire #1, Channel #7 */
def_irq_handler cpuss_interrupts_dw1_8_IRQHandler /* CPUSS DataWire #1, Channel #8 */
def_irq_handler cpuss_interrupts_dw1_9_IRQHandler /* CPUSS DataWire #1, Channel #9 */
def_irq_handler cpuss_interrupts_dw1_10_IRQHandler /* CPUSS DataWire #1, Channel #10 */
def_irq_handler cpuss_interrupts_dw1_11_IRQHandler /* CPUSS DataWire #1, Channel #11 */
def_irq_handler cpuss_interrupts_dw1_12_IRQHandler /* CPUSS DataWire #1, Channel #12 */
def_irq_handler cpuss_interrupts_dw1_13_IRQHandler /* CPUSS DataWire #1, Channel #13 */
def_irq_handler cpuss_interrupts_dw1_14_IRQHandler /* CPUSS DataWire #1, Channel #14 */
def_irq_handler cpuss_interrupts_dw1_15_IRQHandler /* CPUSS DataWire #1, Channel #15 */
def_irq_handler cpuss_interrupts_fault_0_IRQHandler /* CPUSS Fault Structure Interrupt #0 */
def_irq_handler cpuss_interrupts_fault_1_IRQHandler /* CPUSS Fault Structure Interrupt #1 */
def_irq_handler cpuss_interrupt_crypto_IRQHandler /* CRYPTO Accelerator Interrupt */
def_irq_handler cpuss_interrupt_fm_IRQHandler /* FLASH Macro Interrupt */
def_irq_handler cpuss_interrupts_cm0_cti_0_IRQHandler /* CM0+ CTI #0 */
def_irq_handler cpuss_interrupts_cm0_cti_1_IRQHandler /* CM0+ CTI #1 */
def_irq_handler cpuss_interrupts_cm4_cti_0_IRQHandler /* CM4 CTI #0 */
def_irq_handler cpuss_interrupts_cm4_cti_1_IRQHandler /* CM4 CTI #1 */
def_irq_handler tcpwm_0_interrupts_0_IRQHandler /* TCPWM #0, Counter #0 */
def_irq_handler tcpwm_0_interrupts_1_IRQHandler /* TCPWM #0, Counter #1 */
def_irq_handler tcpwm_0_interrupts_2_IRQHandler /* TCPWM #0, Counter #2 */
def_irq_handler tcpwm_0_interrupts_3_IRQHandler /* TCPWM #0, Counter #3 */
def_irq_handler tcpwm_0_interrupts_4_IRQHandler /* TCPWM #0, Counter #4 */
def_irq_handler tcpwm_0_interrupts_5_IRQHandler /* TCPWM #0, Counter #5 */
def_irq_handler tcpwm_0_interrupts_6_IRQHandler /* TCPWM #0, Counter #6 */
def_irq_handler tcpwm_0_interrupts_7_IRQHandler /* TCPWM #0, Counter #7 */
def_irq_handler tcpwm_1_interrupts_0_IRQHandler /* TCPWM #1, Counter #0 */
def_irq_handler tcpwm_1_interrupts_1_IRQHandler /* TCPWM #1, Counter #1 */
def_irq_handler tcpwm_1_interrupts_2_IRQHandler /* TCPWM #1, Counter #2 */
def_irq_handler tcpwm_1_interrupts_3_IRQHandler /* TCPWM #1, Counter #3 */
def_irq_handler tcpwm_1_interrupts_4_IRQHandler /* TCPWM #1, Counter #4 */
def_irq_handler tcpwm_1_interrupts_5_IRQHandler /* TCPWM #1, Counter #5 */
def_irq_handler tcpwm_1_interrupts_6_IRQHandler /* TCPWM #1, Counter #6 */
def_irq_handler tcpwm_1_interrupts_7_IRQHandler /* TCPWM #1, Counter #7 */
def_irq_handler tcpwm_1_interrupts_8_IRQHandler /* TCPWM #1, Counter #8 */
def_irq_handler tcpwm_1_interrupts_9_IRQHandler /* TCPWM #1, Counter #9 */
def_irq_handler tcpwm_1_interrupts_10_IRQHandler /* TCPWM #1, Counter #10 */
def_irq_handler tcpwm_1_interrupts_11_IRQHandler /* TCPWM #1, Counter #11 */
def_irq_handler tcpwm_1_interrupts_12_IRQHandler /* TCPWM #1, Counter #12 */
def_irq_handler tcpwm_1_interrupts_13_IRQHandler /* TCPWM #1, Counter #13 */
def_irq_handler tcpwm_1_interrupts_14_IRQHandler /* TCPWM #1, Counter #14 */
def_irq_handler tcpwm_1_interrupts_15_IRQHandler /* TCPWM #1, Counter #15 */
def_irq_handler tcpwm_1_interrupts_16_IRQHandler /* TCPWM #1, Counter #16 */
def_irq_handler tcpwm_1_interrupts_17_IRQHandler /* TCPWM #1, Counter #17 */
def_irq_handler tcpwm_1_interrupts_18_IRQHandler /* TCPWM #1, Counter #18 */
def_irq_handler tcpwm_1_interrupts_19_IRQHandler /* TCPWM #1, Counter #19 */
def_irq_handler tcpwm_1_interrupts_20_IRQHandler /* TCPWM #1, Counter #20 */
def_irq_handler tcpwm_1_interrupts_21_IRQHandler /* TCPWM #1, Counter #21 */
def_irq_handler tcpwm_1_interrupts_22_IRQHandler /* TCPWM #1, Counter #22 */
def_irq_handler tcpwm_1_interrupts_23_IRQHandler /* TCPWM #1, Counter #23 */
def_irq_handler udb_interrupts_0_IRQHandler /* UDB Interrupt #0 */
def_irq_handler udb_interrupts_1_IRQHandler /* UDB Interrupt #1 */
def_irq_handler udb_interrupts_2_IRQHandler /* UDB Interrupt #2 */
def_irq_handler udb_interrupts_3_IRQHandler /* UDB Interrupt #3 */
def_irq_handler udb_interrupts_4_IRQHandler /* UDB Interrupt #4 */
def_irq_handler udb_interrupts_5_IRQHandler /* UDB Interrupt #5 */
def_irq_handler udb_interrupts_6_IRQHandler /* UDB Interrupt #6 */
def_irq_handler udb_interrupts_7_IRQHandler /* UDB Interrupt #7 */
def_irq_handler udb_interrupts_8_IRQHandler /* UDB Interrupt #8 */
def_irq_handler udb_interrupts_9_IRQHandler /* UDB Interrupt #9 */
def_irq_handler udb_interrupts_10_IRQHandler /* UDB Interrupt #10 */
def_irq_handler udb_interrupts_11_IRQHandler /* UDB Interrupt #11 */
def_irq_handler udb_interrupts_12_IRQHandler /* UDB Interrupt #12 */
def_irq_handler udb_interrupts_13_IRQHandler /* UDB Interrupt #13 */
def_irq_handler udb_interrupts_14_IRQHandler /* UDB Interrupt #14 */
def_irq_handler udb_interrupts_15_IRQHandler /* UDB Interrupt #15 */
def_irq_handler pass_interrupt_sar_IRQHandler /* SAR ADC interrupt */
def_irq_handler audioss_interrupt_i2s_IRQHandler /* I2S Audio interrupt */
def_irq_handler audioss_interrupt_pdm_IRQHandler /* PDM/PCM Audio interrupt */
def_irq_handler profile_interrupt_IRQHandler /* Energy Profiler interrupt */
def_irq_handler smif_interrupt_IRQHandler /* Serial Memory Interface interrupt */
def_irq_handler usb_interrupt_hi_IRQHandler /* USB Interrupt */
def_irq_handler usb_interrupt_med_IRQHandler /* USB Interrupt */
def_irq_handler usb_interrupt_lo_IRQHandler /* USB Interrupt */
def_irq_handler pass_interrupt_dacs_IRQHandler /* Consolidated interrrupt for all DACs */
.end
/* [] END OF FILE */

View File

@ -0,0 +1,430 @@
/***************************************************************************//**
* \file system_psoc63_cm4.c
* \version 2.0
*
* The device system-source file.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "system_psoc63.h"
#include "cy_device_headers.h"
#if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
#include "ipc/cy_ipc_pipe.h"
#include "ipc/cy_ipc_sema.h"
#endif /* CY_IPC_DEFAULT_CFG_DISABLE */
/*******************************************************************************
* SystemCoreClockUpdate()
*******************************************************************************/
/** Default HFClk frequency in Hz */
#define CY_CLK_HFCLK0_FREQ_HZ_DEFAULT ( 8000000UL)
/** Default PeriClk frequency in Hz */
#define CY_CLK_PERICLK_FREQ_HZ_DEFAULT (4000000UL)
/** Default SlowClk system core frequency in Hz */
#define CY_CLK_SYSTEM_FREQ_HZ_DEFAULT (8000000UL)
/** IMO frequency in Hz */
#define CY_CLK_IMO_FREQ_HZ (8000000UL)
/** HVILO frequency in Hz */
#define CY_CLK_HVILO_FREQ_HZ (32000UL)
#if (SRSS_PILO_PRESENT == 1U) || defined(CY_DOXYGEN)
/** PILO frequency in Hz */
#define CY_CLK_PILO_FREQ_HZ (32768UL)
#endif /* (SRSS_PILO_PRESENT == 1U) || defined(CY_DOXYGEN) */
/** WCO frequency in Hz */
#define CY_CLK_WCO_FREQ_HZ (32768UL)
#if (SRSS_ALTLF_PRESENT == 1U) || defined(CY_DOXYGEN)
/** ALTLF frequency in Hz */
#define CY_CLK_ALTLF_FREQ_HZ (32768UL)
#endif /* (SRSS_ALTLF_PRESENT == 1U) || defined(CY_DOXYGEN) */
/** Holds the FastClk system core clock, which is the system clock frequency supplied to the SysTick timer and the
* processor core clock. This variable can be used by debuggers to query the frequency of the debug timer or to configure
* the trace clock speed.
*
* \attention Compilers must be configured to avoid removing this variable in case the application program is not using
* it. Debugging systems require the variable to be physically present in memory so that it can be examined to configure
* the debugger. */
uint32_t SystemCoreClock = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT;
/** Holds the HFClk0 clock frequency. Updated by \ref SystemCoreClockUpdate(). */
uint32_t cy_Hfclk0FreqHz = CY_CLK_HFCLK0_FREQ_HZ_DEFAULT;
/** Holds the PeriClk clock frequency. Updated by \ref SystemCoreClockUpdate(). */
uint32_t cy_PeriClkFreqHz = CY_CLK_PERICLK_FREQ_HZ_DEFAULT;
#if (defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)) || defined (CY_DOXYGEN)
/** Holds the Alternate high frequency clock in Hz. Updated by \ref SystemCoreClockUpdate(). */
uint32_t cy_BleEcoClockFreqHz = CY_CLK_ALTHF_FREQ_HZ;
#endif /* (defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL)) || defined (CY_DOXYGEN) */
/* SCB->CPACR */
#define SCB_CPACR_CP10_CP11_ENABLE (0xFUL << 20u)
/*******************************************************************************
* SystemInit()
*******************************************************************************/
/* WDT lock bits */
#define CY_WDT_LOCK_BIT0 ((uint32_t)0x01u << 30u)
#define CY_WDT_LOCK_BIT1 ((uint32_t)0x01u << 31u)
/*******************************************************************************
* SystemCoreClockUpdate (void)
*******************************************************************************/
/* Do not use these definitions directly in your application */
#define CY_DELAY_MS_OVERFLOW_THRESHOLD (0x8000u)
#define CY_DELAY_1K_THRESHOLD (1000u)
#define CY_DELAY_1K_MINUS_1_THRESHOLD (CY_DELAY_1K_THRESHOLD - 1u)
#define CY_DELAY_1M_THRESHOLD (1000000u)
#define CY_DELAY_1M_MINUS_1_THRESHOLD (CY_DELAY_1M_THRESHOLD - 1u)
uint32_t cy_delayFreqHz = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT;
uint32_t cy_delayFreqKhz = (CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) /
CY_DELAY_1K_THRESHOLD;
uint8_t cy_delayFreqMhz = (uint8_t)((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1M_MINUS_1_THRESHOLD) /
CY_DELAY_1M_THRESHOLD);
uint32_t cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD *
((CY_CLK_SYSTEM_FREQ_HZ_DEFAULT + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD);
#define CY_ROOT_PATH_SRC_IMO (0UL)
#define CY_ROOT_PATH_SRC_EXT (1UL)
#if (SRSS_ECO_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_ECO (2UL)
#endif /* (SRSS_ECO_PRESENT == 1U) */
#if (SRSS_ALTHF_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_ALTHF (3UL)
#endif /* (SRSS_ALTHF_PRESENT == 1U) */
#define CY_ROOT_PATH_SRC_DSI_MUX (4UL)
#define CY_ROOT_PATH_SRC_DSI_MUX_HVILO (16UL)
#define CY_ROOT_PATH_SRC_DSI_MUX_WCO (17UL)
#if (SRSS_ALTLF_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_DSI_MUX_ALTLF (18UL)
#endif /* (SRSS_ALTLF_PRESENT == 1U) */
#if (SRSS_PILO_PRESENT == 1U)
#define CY_ROOT_PATH_SRC_DSI_MUX_PILO (19UL)
#endif /* (SRSS_PILO_PRESENT == 1U) */
/*******************************************************************************
* Function Name: SystemInit
****************************************************************************//**
*
* Initializes the system:
* - Unlocks and disables WDT.
* - Calls the Cy_SystemInit() function, if compiled from PSoC Creator.
* - Calls \ref SystemCoreClockUpdate().
*
*******************************************************************************/
void SystemInit(void)
{
/* Unlock and disable WDT */
SRSS->WDT_CTL = ((SRSS->WDT_CTL & (uint32_t)(~SRSS_WDT_CTL_WDT_LOCK_Msk)) | CY_WDT_LOCK_BIT0);
SRSS->WDT_CTL = (SRSS->WDT_CTL | CY_WDT_LOCK_BIT1);
SRSS->WDT_CTL &= (~ (uint32_t) SRSS_WDT_CTL_WDT_EN_Msk);
Cy_SystemInit();
SystemCoreClockUpdate();
#if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
/* Allocate and initialize semaphores for the system operations. */
Cy_IPC_SystemSemaInit();
Cy_IPC_SystemPipeInit();
#endif /* CY_IPC_DEFAULT_CFG_DISABLE */
}
/*******************************************************************************
* Function Name: Cy_SystemInit
****************************************************************************//**
*
* The function is called during device startup. Once project compiled as part of
* the PSoC Creator project, the Cy_SystemInit() function is generated by the
* PSoC Creator.
*
* The function generated by PSoC Creator performs all of the necessary device
* configuration based on the design settings. This includes settings from the
* Design Wide Resources (DWR) such as Clocks and Pins as well as any component
* configuration that is necessary.
*
*******************************************************************************/
__WEAK void Cy_SystemInit(void)
{
/* Empty weak function. The actual implementation to be in the PSoC Creator
* generated strong function.
*/
}
/*******************************************************************************
* Function Name: SystemCoreClockUpdate
****************************************************************************//**
*
* Gets core clock frequency and updates \ref SystemCoreClock, \ref
* cy_Hfclk0FreqHz, and \ref cy_PeriClkFreqHz.
*
* Updates global variables used by the \ref Cy_SysLib_Delay(), \ref
* Cy_SysLib_DelayUs(), and \ref Cy_SysLib_DelayCycles().
*
*******************************************************************************/
void SystemCoreClockUpdate (void)
{
uint32_t srcFreqHz;
uint32_t pathFreqHz;
uint32_t fastClkDiv;
uint32_t periClkDiv;
uint32_t rootPath;
uint32_t srcClk;
/* Get root path clock for the high-frequency clock # 0 */
rootPath = _FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_MUX, SRSS->CLK_ROOT_SELECT[0u]);
/* Get source of the root path clock */
srcClk = _FLD2VAL(SRSS_CLK_PATH_SELECT_PATH_MUX, SRSS->CLK_PATH_SELECT[rootPath]);
/* Get frequency of the source */
switch (srcClk)
{
case CY_ROOT_PATH_SRC_IMO:
srcFreqHz = CY_CLK_IMO_FREQ_HZ;
break;
case CY_ROOT_PATH_SRC_EXT:
srcFreqHz = CY_CLK_EXT_FREQ_HZ;
break;
#if (SRSS_ECO_PRESENT == 1U)
case CY_ROOT_PATH_SRC_ECO:
srcFreqHz = CY_CLK_ECO_FREQ_HZ;
break;
#endif /* (SRSS_ECO_PRESENT == 1U) */
#if defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U)
case CY_ROOT_PATH_SRC_ALTHF:
srcFreqHz = cy_BleEcoClockFreqHz;
break;
#endif /* defined (CY_IP_MXBLESS) && (CY_IP_MXBLESS == 1UL) && (SRSS_ALTHF_PRESENT == 1U) */
case CY_ROOT_PATH_SRC_DSI_MUX:
{
uint32_t dsi_src;
dsi_src = _FLD2VAL(SRSS_CLK_DSI_SELECT_DSI_MUX, SRSS->CLK_DSI_SELECT[rootPath]);
switch (dsi_src)
{
case CY_ROOT_PATH_SRC_DSI_MUX_HVILO:
srcFreqHz = CY_CLK_HVILO_FREQ_HZ;
break;
case CY_ROOT_PATH_SRC_DSI_MUX_WCO:
srcFreqHz = CY_CLK_WCO_FREQ_HZ;
break;
#if (SRSS_ALTLF_PRESENT == 1U)
case CY_ROOT_PATH_SRC_DSI_MUX_ALTLF:
srcFreqHz = CY_CLK_ALTLF_FREQ_HZ;
break;
#endif /* (SRSS_ALTLF_PRESENT == 1U) */
#if (SRSS_PILO_PRESENT == 1U)
case CY_ROOT_PATH_SRC_DSI_MUX_PILO:
srcFreqHz = CY_CLK_PILO_FREQ_HZ;
break;
#endif /* (SRSS_PILO_PRESENT == 1U) */
default:
srcFreqHz = CY_CLK_HVILO_FREQ_HZ;
break;
}
}
break;
default:
srcFreqHz = CY_CLK_EXT_FREQ_HZ;
break;
}
if (rootPath == 0UL)
{
/* FLL */
bool fllLocked = ( 0UL != _FLD2VAL(SRSS_CLK_FLL_STATUS_LOCKED, SRSS->CLK_FLL_STATUS));
bool fllOutputOutput = ( 3UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3));
bool fllOutputAuto = ((0UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3)) ||
(1UL == _FLD2VAL(SRSS_CLK_FLL_CONFIG3_BYPASS_SEL, SRSS->CLK_FLL_CONFIG3)));
if ((fllOutputAuto && fllLocked) || fllOutputOutput)
{
uint32_t fllMult;
uint32_t refDiv;
uint32_t outputDiv;
fllMult = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_MULT, SRSS->CLK_FLL_CONFIG);
refDiv = _FLD2VAL(SRSS_CLK_FLL_CONFIG2_FLL_REF_DIV, SRSS->CLK_FLL_CONFIG2);
outputDiv = _FLD2VAL(SRSS_CLK_FLL_CONFIG_FLL_OUTPUT_DIV, SRSS->CLK_FLL_CONFIG) + 1UL;
pathFreqHz = ((srcFreqHz / refDiv) * fllMult) / outputDiv;
}
else
{
pathFreqHz = srcFreqHz;
}
}
else if (rootPath == 1UL)
{
/* PLL */
bool pllLocked = ( 0UL != _FLD2VAL(SRSS_CLK_PLL_STATUS_LOCKED, SRSS->CLK_PLL_STATUS[0UL]));
bool pllOutputOutput = ( 3UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL]));
bool pllOutputAuto = ((0UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL])) ||
(1UL == _FLD2VAL(SRSS_CLK_PLL_CONFIG_BYPASS_SEL, SRSS->CLK_PLL_CONFIG[0UL])));
if ((pllOutputAuto && pllLocked) || pllOutputOutput)
{
uint32_t feedbackDiv;
uint32_t referenceDiv;
uint32_t outputDiv;
feedbackDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_FEEDBACK_DIV, SRSS->CLK_PLL_CONFIG[0UL]);
referenceDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_REFERENCE_DIV, SRSS->CLK_PLL_CONFIG[0UL]);
outputDiv = _FLD2VAL(SRSS_CLK_PLL_CONFIG_OUTPUT_DIV, SRSS->CLK_PLL_CONFIG[0UL]);
pathFreqHz = ((srcFreqHz * feedbackDiv) / referenceDiv) / outputDiv;
}
else
{
pathFreqHz = srcFreqHz;
}
}
else
{
/* Direct */
pathFreqHz = srcFreqHz;
}
/* Get frequency after hf_clk pre-divider */
pathFreqHz = pathFreqHz >> _FLD2VAL(SRSS_CLK_ROOT_SELECT_ROOT_DIV, SRSS->CLK_ROOT_SELECT[0u]);
cy_Hfclk0FreqHz = pathFreqHz;
/* Fast Clock Divider */
fastClkDiv = 1u + _FLD2VAL(CPUSS_CM4_CLOCK_CTL_FAST_INT_DIV, CPUSS->CM4_CLOCK_CTL);
/* Peripheral Clock Divider */
periClkDiv = 1u + _FLD2VAL(CPUSS_CM0_CLOCK_CTL_PERI_INT_DIV, CPUSS->CM0_CLOCK_CTL);
cy_PeriClkFreqHz = pathFreqHz / periClkDiv;
pathFreqHz = pathFreqHz / fastClkDiv;
SystemCoreClock = pathFreqHz;
/* Sets clock frequency for Delay API */
cy_delayFreqHz = SystemCoreClock;
cy_delayFreqMhz = (uint8_t)((cy_delayFreqHz + CY_DELAY_1M_MINUS_1_THRESHOLD) / CY_DELAY_1M_THRESHOLD);
cy_delayFreqKhz = (cy_delayFreqHz + CY_DELAY_1K_MINUS_1_THRESHOLD) / CY_DELAY_1K_THRESHOLD;
cy_delay32kMs = CY_DELAY_MS_OVERFLOW_THRESHOLD * cy_delayFreqKhz;
}
/*******************************************************************************
* Function Name: Cy_SystemInitFpuEnable
****************************************************************************//**
*
* Enables the FPU if it is used. The function is called from the startup file.
*
*******************************************************************************/
void Cy_SystemInitFpuEnable(void)
{
#if defined (__FPU_USED) && (__FPU_USED == 1U)
uint32_t interruptState;
interruptState = Cy_SaveIRQ();
SCB->CPACR |= SCB_CPACR_CP10_CP11_ENABLE;
__DSB();
__ISB();
Cy_RestoreIRQ(interruptState);
#endif /* (__FPU_USED) && (__FPU_USED == 1U) */
}
/*******************************************************************************
* Function Name: Cy_MemorySymbols
****************************************************************************//**
*
* The intention of the function is to declare boundaries of the memories for the
* MDK compilers. For the rest of the supported compilers, this is done using
* linker configuration files. The following symbols used by the cypdlelftool.
*
*******************************************************************************/
#if defined (__ARMCC_VERSION)
__asm void Cy_MemorySymbols(void)
{
/* Flash */
EXPORT __cy_memory_0_start
EXPORT __cy_memory_0_length
EXPORT __cy_memory_0_row_size
/* Working Flash */
EXPORT __cy_memory_1_start
EXPORT __cy_memory_1_length
EXPORT __cy_memory_1_row_size
/* Supervisory Flash */
EXPORT __cy_memory_2_start
EXPORT __cy_memory_2_length
EXPORT __cy_memory_2_row_size
/* XIP */
EXPORT __cy_memory_3_start
EXPORT __cy_memory_3_length
EXPORT __cy_memory_3_row_size
/* eFuse */
EXPORT __cy_memory_4_start
EXPORT __cy_memory_4_length
EXPORT __cy_memory_4_row_size
/* Flash */
__cy_memory_0_start EQU __cpp(CY_FLASH_BASE)
__cy_memory_0_length EQU __cpp(CY_FLASH_SIZE)
__cy_memory_0_row_size EQU 0x200
/* Working Flash */
__cy_memory_1_start EQU __cpp(CY_WFLASH_BASE)
__cy_memory_1_length EQU __cpp(CY_WFLASH_SIZE)
__cy_memory_1_row_size EQU 0x200
/* Supervisory Flash */
__cy_memory_2_start EQU __cpp(CY_SFLASH_BASE)
__cy_memory_2_length EQU __cpp(CY_SFLASH_SIZE)
__cy_memory_2_row_size EQU 0x200
/* XIP */
__cy_memory_3_start EQU __cpp(CY_XIP_BASE)
__cy_memory_3_length EQU __cpp(CY_XIP_SIZE)
__cy_memory_3_row_size EQU 0x200
/* eFuse */
__cy_memory_4_start EQU __cpp(0x90700000)
__cy_memory_4_length EQU __cpp(0x100000)
__cy_memory_4_row_size EQU __cpp(1)
}
#endif /* defined (__ARMCC_VERSION) */
/* [] END OF FILE */

View File

@ -34,6 +34,6 @@
#define MBED_DEVICE_H
#include "objects.h"
#include "project.h"
//#include "project.h"
#endif

View File

@ -32,7 +32,6 @@
#ifndef MBED_CMSIS_H
#define MBED_CMSIS_H
#include "cy8c637bzi_bld74.h" // IRQn - could include "include/cy_device_headers.h"
#include "core_cm0plus.h" // NVIC
#include "cy_device_headers.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
/***************************************************************************//**
* \file cy_device_headers.h
*
* \brief
* Common header file to be included by the drivers.
*
* \note
* Generated 9/21/2017 by CyDeviceHeaderGenerator v1.2.0.101
* from the register map configuration rev#1007711
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#ifndef _CY_DEVICE_HEADERS_H_
#define _CY_DEVICE_HEADERS_H_
#if defined (CY8C6336BZI_BLF03)
#include "cy8c6336bzi_blf03.h"
#elif defined (CY8C6316BZI_BLF03)
#include "cy8c6316bzi_blf03.h"
#elif defined (CY8C6316BZI_BLF53)
#include "cy8c6316bzi_blf53.h"
#elif defined (CY8C6336BZI_BLD13)
#include "cy8c6336bzi_bld13.h"
#elif defined (CY8C6347BZI_BLD43)
#include "cy8c6347bzi_bld43.h"
#elif defined (CY8C6347BZI_BLD33)
#include "cy8c6347bzi_bld33.h"
#elif defined (CY8C6347BZI_BLD53)
#include "cy8c6347bzi_bld53.h"
#elif defined (CY8C6347FMI_BLD13)
#include "cy8c6347fmi_bld13.h"
#elif defined (CY8C6347FMI_BLD43)
#include "cy8c6347fmi_bld43.h"
#elif defined (CY8C6347FMI_BLD33)
#include "cy8c6347fmi_bld33.h"
#elif defined (CY8C6347FMI_BLD53)
#include "cy8c6347fmi_bld53.h"
#elif defined (CY8C637BZI_MD76)
#include "cy8c637bzi_md76.h"
#elif defined (CY8C637BZI_BLD74)
#include "cy8c637bzi_bld74.h"
#elif defined (CY8C637FMI_BLD73)
#include "cy8c637fmi_bld73.h"
#elif defined (CY8C68237BZ_BLE)
#include "cy8c68237bz_ble.h"
#elif defined (CY8C68237FM_BLE)
#include "cy8c68237fm_ble.h"
#else
#error Undefined part number
#endif
#endif /* _CY_DEVICE_HEADERS_H_ */
/* [] END OF FILE */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,494 @@
/***************************************************************************//**
* \file system_psoc63.h
* \version 2.0
*
* \brief Device system header file.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#ifndef _SYSTEM_PSOC63_H_
#define _SYSTEM_PSOC63_H_
/**
* \defgroup group_system_config System Configuration Files (Startup)
* \{
* Provides device startup, system configuration, and linker script files.
* The system startup provides the followings features:
* - See \ref group_system_config_device_initialization for the:
* * \ref group_system_config_dual_core_device_initialization
* * \ref group_system_config_single_core_device_initialization
* - See \ref group_system_config_device_memory_definition for the:
* * \ref group_system_config_device_memory_dual_core_definition
* * \ref group_system_config_device_memory_single_core_definition
* - \ref group_system_config_heap_stack_config
* - \ref group_system_config_merge_apps
* - Default interrupt handlers definition
* - \ref group_system_config_device_vector_table
* - \ref group_system_config_cm4_functions
*
* \section group_system_config_configuration Configuration Considerations
*
* \subsection group_system_config_device_memory_definition Device Memory Definition
* The physical flash and RAM memory is shared between the CPU cores. The flash
* and RAM allocation for each
* CPU is defined by the linker scripts.
*
* \subsubsection group_system_config_device_memory_dual_core_definition Dual-Core Devices
* By default, the flash and RAM memory is equally divided between two cores.
* This proportion can be changed by editing
* the linker configuration files.
*
* <b>ARM GCC</b>\n
* The flash and RAM sections for the CPU are defined in the linker files:
* 'xx_yy.ld', where 'xx' is the device group, and 'yy' is the target CPU; for
* example, 'cy8c6x7_cm0plus.ld' and 'cy8c6x7_cm4_dual.ld'.
* Note: if the start of the Cortex-M4 application image is changed, the value
* of the of the \ref CY_CORTEX_M4_APPL_ADDR should also be changed. The
* \ref CY_CORTEX_M4_APPL_ADDR macro should be used as the parameter for the
* Cy_SysEnableCM4() function call.
*
* The flash and RAM sizes can be changed by editing the LENGTH value in the
* linker files for both CPUs:
* - 'xx_cm0plus.ld', where 'xx' is the device group:
* * \code rom (rx) : ORIGIN = 0x10000000, LENGTH = 0x00080000 \endcode
* * \code ram_cm0p (rwx) : ORIGIN = 0x08000000, LENGTH = 0x00024000 \endcode
* - 'xx_cm4_dual.ld', where 'xx' is the device group:
* * \code rom (rx) : ORIGIN = 0x10080000, LENGTH = 0x00080000 \endcode
* * \code ram_cm4 (rwx) : ORIGIN = 0x08024000, LENGTH = 0x00024000 \endcode
* Change the value of the \ref CY_CORTEX_M4_APPL_ADDR macro to the rom ORIGIN's
* value in the 'xx_cm4_dual.ld' file, where 'xx' is the device group. Do this
* by either:
* - Passing the following commands to the compiler:\n
* * \code -D CY_CORTEX_M4_APPL_ADDR=0x10080000 \endcode
* - Editing the \ref CY_CORTEX_M4_APPL_ADDR value in the 'system_xx.h', where 'xx' is device family:\n
* * \code #define CY_CORTEX_M4_APPL_ADDR (0x10080000u) \endcode
*
* <b>ARM MDK</b>\n
* The flash and RAM sections for the CPU are defined in the linker files:
* 'xx_yy.scat', where 'xx' is the device group, and 'yy' is the target CPU; for
* example, 'cy8c6x7_cm0plus.scat' and 'cy8c6x7_cm4_dual.scat'.
* Note: if the start of the Cortex-M4 application image is changed, the value
* of the of the \ref CY_CORTEX_M4_APPL_ADDR should also be changed. The
* \ref CY_CORTEX_M4_APPL_ADDR macro should be used as the parameter for the \ref
* Cy_SysEnableCM4() function call.
*
* The flash and RAM sizes can be changed by editing the macros value in the
* linker files for both CPUs:
* - 'xx_cm0plus.scat', where 'xx' is the device group:
* * \code #define FLASH_START 0x10000000 \endcode
* * \code #define FLASH_SIZE 0x00080000 \endcode
* - 'xx_cm4_dual.scat', where 'xx' is the device group:
* * \code #define FLASH_START 0x10080000 \endcode
* * \code #define FLASH_SIZE 0x00080000 \endcode
* Change the value of the \ref CY_CORTEX_M4_APPL_ADDR macro to the FLASH_START
* value in the 'xx_cm4_dual.scat' file,
* where 'xx' is the device group. Do this by either:
* - Passing the following commands to the compiler:\n
* * \code -D CY_CORTEX_M4_APPL_ADDR=0x10080000 \endcode
* - Editing the \ref CY_CORTEX_M4_APPL_ADDR value in the 'system_xx.h', where
* 'xx' is device family:\n
* * \code #define CY_CORTEX_M4_APPL_ADDR (0x10080000u) \endcode
*
* <b>IAR</b>\n
* The flash and RAM sections for the CPU are defined in the linker files:
* 'xx_yy.icf', where 'xx' is the device group, and 'yy' is the target CPU; for
* example, 'cy8c6x7_cm0plus.icf' and 'cy8c6x7_cm4_dual.icf'.
* Note: if the start of the Cortex-M4 application image is changed, the value
* of the of the \ref CY_CORTEX_M4_APPL_ADDR should also be changed. The
* \ref CY_CORTEX_M4_APPL_ADDR macro should be used as the parameter for the \ref
* Cy_SysEnableCM4() function call.
*
* The flash and RAM sizes can be changed by editing the macros value in the
* linker files for both CPUs:
* - 'xx_cm0plus.icf', where 'xx' is the device group:
* * \code define symbol __ICFEDIT_region_IROM_start__ = 0x10000000; \endcode
* * \code define symbol __ICFEDIT_region_IROM_end__ = 0x10080000; \endcode
* * \code define symbol __ICFEDIT_region_IRAM_CM0P_start__ = 0x08000000; \endcode
* * \code define symbol __ICFEDIT_region_IRAM_CM0P_end__ = 0x08024000; \endcode
* - 'xx_cm4_dual.icf', where 'xx' is the device group:
* * \code define symbol __ICFEDIT_region_IROM_start__ = 0x10080000; \endcode
* * \code define symbol __ICFEDIT_region_IROM_end__ = 0x10100000; \endcode
* * \code define symbol __ICFEDIT_region_IRAM_CM4_start__ = 0x08024000; \endcode
* * \code define symbol __ICFEDIT_region_IRAM_CM4_end__ = 0x08048000; \endcode
* Change the value of the \ref CY_CORTEX_M4_APPL_ADDR macro to the
* __ICFEDIT_region_IROM_start__ value in the 'xx_cm4_dual.icf' file, where 'xx'
* is the device group. Do this by either:
* - Passing the following commands to the compiler:\n
* * \code -D CY_CORTEX_M4_APPL_ADDR=0x10080000 \endcode
* - Editing the \ref CY_CORTEX_M4_APPL_ADDR value in the 'system_xx.h', where
* 'xx' is device family:\n
* * \code #define CY_CORTEX_M4_APPL_ADDR (0x10080000u) \endcode
*
* \subsubsection group_system_config_device_memory_single_core_definition Single-Core Devices
* For single-core devices, 8 KB of flash and RAM are reserved for the pre-build
* Cortex-M0+ application that is loaded for the hidden Cortex-M0+.
*
* \subsection group_system_config_device_initialization Device Initialization
* After a power-on-reset (POR), the boot process is handled by the boot code
* from the on-chip ROM that is always executed by the Cortex-M0+ core. The boot
* code passes the control to the Cortex-M0+ startup code located in flash.
*
* \subsubsection group_system_config_dual_core_device_initialization Dual-Core Devices
* The Cortex-M0+ startup code performs the device initialization by a call to
* SystemInit() and then calls the main() function. The Cortex-M4 core is disabled
* by default. Enable the core using the \ref Cy_SysEnableCM4() function.
* See \ref group_system_config_cm4_functions for more details.
*
* \subsubsection group_system_config_single_core_device_initialization Single-Core Devices
* The Cortex-M0+ core is not user-accessible on these devices. In this case the
* Cortex-M0+ pre-built application image handles setup of the CM0+ core and
* starts the Cortex-M4 core.
*
* CM0+ NVIC IRQn channels 26-31 are reserved for system use. Other IRQn channels
* are available to the user application. The pre-built application configures:
* * IRQn 26-27 for the IPC driver
* * IRQn 28-30 for the Crypto driver
* * IRQn 31 for system communication
*
* The Cortex-M0+ application image performs the following tasks:
* * Enables global interrupts on the Cortex-M0+ core.
* * Starts the crypto server. See [Cryptography (Crypto)](\ref group_crypto) for details.
* * Enables the Cortex-M4 core by calling \ref Cy_SysEnableCM4().
* * Requests Deep Sleep mode entry with wakeup on interrupt in the infinite loop.
*
* \subsection group_system_config_heap_stack_config Heap and Stack Configuration
* There are two ways to adjust heap and stack configurations:
* -# Editing source code files
* -# Specifying via command line
*
* By default, the stack size is set to 0x00001000 and the heap size is set to 0x00000400.
*
* \subsubsection group_system_config_heap_stack_config_gcc ARM GCC
* - <b>Editing source code files</b>\n
* The heap and stack sizes are defined in the assembler startup files:
* 'startup_xx_yy.S', where 'xx' is the device family, and 'yy' is the target CPU;
* for example, startup_psoc63_cm0plus.s and startup_psoc63_cm4.s.
* Change the heap and stack sizes by modifying the following lines:\n
* * \code .equ Stack_Size, 0x00001000 \endcode
* * \code .equ Heap_Size, 0x00000400 \endcode
*
* - <b>Specifying via command line</b>\n
* Change the heap and stack sizes passing the following commands to the compiler:\n
* * \code -D __STACK_SIZE=0x000000400 \endcode
* * \code -D __HEAP_SIZE=0x000000100 \endcode
*
* \subsubsection group_system_config_heap_stack_config_mdk ARM MDK
* - <b>Editing source code files</b>\n
* The heap and stack sizes are defined in the assembler startup files:
* 'startup_xx_yy.s', where 'xx' is the device family, and 'yy' is the target
* CPU; for example, startup_psoc63_cm0plus.s and startup_psoc63_cm4.s.
* Change the heap and stack sizes by modifying the following lines:\n
* * \code Stack_Size EQU 0x00001000 \endcode
* * \code Heap_Size EQU 0x00000400 \endcode
*
* - <b>Specifying via command line</b>\n
* Change the heap and stack sizes passing the following commands to the assembler:\n
* * \code "--predefine=___STACK_SIZE SETA 0x000000400" \endcode
* * \code "--predefine=__HEAP_SIZE SETA 0x000000100" \endcode
*
* \subsubsection group_system_config_heap_stack_config_iar IAR
* - <b>Editing source code files</b>\n
* The heap and stack sizes are defined in the linker scatter files: 'xx_yy.icf',
* where 'xx' is the device family, and 'yy' is the target CPU; for example,
* cy8c6x7_cm0plus.icf and cy8c6x7_cm4_dual.icf.
* Change the heap and stack sizes by modifying the following lines:\n
* * \code Stack_Size EQU 0x00001000 \endcode
* * \code Heap_Size EQU 0x00000400 \endcode
*
* - <b>Specifying via command line</b>\n
* Change the heap and stack sizes passing the following commands to the
* linker (including quotation marks):\n
* * \code --define_symbol __STACK_SIZE=0x000000400 \endcode
* * \code --define_symbol __HEAP_SIZE=0x000000100 \endcode
*
* - \subsection group_system_config_merge_apps Merging CM0+ and CM4 Executables
* The CM0+ project and linker script build the CM0+ application image. Similarly,
* the CM4 linker script builds the CM4 application image. Each specifies
* locations, sizes, and contents of sections in memory. See
* \ref group_system_config_device_memory_definition for the symbols and default
* values.
*
* The cypdlelftool is invoked by a post-build command. The precise project
* setting is IDE-specific.
*
* The cypdlelftool combines the two executables. The tool examines the
* executables to ensure that memory regions either do not overlap, or contain
* identical bytes (shared). If there are no problems, it creates a new ELF file
* with the merged image, without changing any of the addresses or data.
*
* \subsection group_system_config_device_vector_table Vectors Table Copy from Flash to RAM
* This process uses memory sections defined in the linker script. The startup
* code actually defines the contents of the vector table and performs the copy.
* \subsubsection group_system_config_device_vector_table_gcc ARM GCC
* The linker script file is 'xx_yy.ld', where 'xx' is the device family, and
* 'yy' is the target CPU; for example, cy8c6x7_cm0plus.ld and cy8c6x7_cm4_dual.ld.
* It defines sections and locations in memory.\n
* Copy interrupt vectors from flash to RAM: \n
* From: \code LONG (__Vectors) \endcode
* To: \code LONG (__ram_vectors_start__) \endcode
* Size: \code LONG (__Vectors_End - __Vectors) \endcode
* The vector table address (and the vector table itself) are defined in the
* assembler startup files: 'startup_xx_yy.S', where 'xx' is the device family,
* and 'yy' is the target CPU; for example, startup_psoc63_cm0plus.S and
* startup_psoc63_cm4.S. The code in these files copies the vector table from
* Flash to RAM.
* \subsubsection group_system_config_device_vector_table_mdk ARM MDK
* The linker script file is 'xx_yy.scat', where 'xx' is the device family,
* and 'yy' is the target CPU; for example, cy8c6x7_cm0plus.scat and
* cy8c6x7_cm4_dual.scat. The linker script specifies that the vector table
* (RESET_RAM) shall be first in the RAM section.\n
* RESET_RAM represents the vector table. It is defined in the assembler startup
* files: 'startup_xx_yy.s', where 'xx' is the device family, and 'yy' is the
* target CPU; for example, startup_psoc63_cm0plus.s and startup_psoc63_cm4.s.
* The code in these files copies the vector table from Flash to RAM.
*
* \subsubsection group_system_config_device_vector_table_iar IAR
* The linker script file is 'xx_yy.icf', where 'xx' is the device family, and
* 'yy' is the target CPU; for example, cy8c6x7_cm0plus.icf and cy8c6x7_cm4_dual.icf.
* This file defines the .intvec_ram section and its location.
* \code place at start of IRAM1_region { readwrite section .intvec_ram}; \endcode
* The vector table address (and the vector table itself) are defined in the
* assembler startup files: 'startup_xx_yy.s', where 'xx' is the device family,
* and 'yy' is the target CPU; for example, startup_psoc63_cm0plus.s and
* startup_psoc63_cm4.s. The code in these files copies the vector table
* from Flash to RAM.
*
* \section group_system_config_more_information More Information
* Refer to the <a href="..\..\pdl_user_guide.pdf">PDL User Guide</a> for the
* more details.
*
* \section group_system_config_MISRA MISRA Compliance
* The drivers violates the following MISRA-C:2004 rules:
*
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* </table>
*
*
* \section group_system_config_changelog Changelog
* <table class="doxtable">
* <tr>
* <th>Version</th>
* <th>Changes</th>
* <th>Reason for Change</th>
* </tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* </table>
*
*
* \defgroup group_system_config_macro Macro
* \{
* \defgroup group_system_config_system_macro System
* \defgroup group_system_config_cm4_status_macro Cortex-M4 Status
* \defgroup group_system_config_user_settings_macro User Settings
* \}
* \defgroup group_system_config_functions Functions
* \{
* \defgroup group_system_config_system_functions System
* \defgroup group_system_config_cm4_functions Cortex-M4 Control
* \}
* \defgroup group_system_config_globals Global Variables
*
* \}
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* Include files
*******************************************************************************/
#include <stdint.h>
/*******************************************************************************
* Global preprocessor symbols/macros ('define')
*******************************************************************************/
#if ((defined(__GNUC__) && (__ARM_ARCH == 6) && (__ARM_ARCH_6M__ == 1)) || \
(defined (__ICCARM__) && (__CORE__ == __ARM6M__)) || \
(defined(__ARMCC_VERSION) && (__TARGET_ARCH_THUMB == 3)))
#define CY_SYSTEM_CPU_CM0P 1UL
#else
#define CY_SYSTEM_CPU_CM0P 0UL
#endif
#if defined (CY_PSOC_CREATOR_USED) && (CY_PSOC_CREATOR_USED == 1U)
#include "cyfitter.h"
#endif /* (CY_PSOC_CREATOR_USED) && (CY_PSOC_CREATOR_USED == 1U) */
/*******************************************************************************
*
* START OF USER SETTINGS HERE
* ===========================
*
* All lines with '<<<' can be set by user.
*
*******************************************************************************/
/**
* \addtogroup group_system_config_user_settings_macro
* \{
*/
#if defined (CYDEV_CLK_EXTCLK__HZ)
#define CY_CLK_EXT_FREQ_HZ (CYDEV_CLK_EXTCLK__HZ)
#else
/***************************************************************************//**
* External Clock Frequency (in Hz, [value]UL). If compiled within
* PSoC Creator and the clock is enabled in the DWR, the value from DWR used.
* Otherwise, edit the value below.
* <i>(USER SETTING)</i>
*******************************************************************************/
#define CY_CLK_EXT_FREQ_HZ (24000000UL) /* <<< 24 MHz */
#endif /* (CYDEV_CLK_EXTCLK__HZ) */
#if defined (CYDEV_CLK_ECO__HZ)
#define CY_CLK_ECO_FREQ_HZ (CYDEV_CLK_ECO__HZ)
#else
/***************************************************************************//**
* \brief External crystal oscillator frequency (in Hz, [value]UL). If compiled
* within PSoC Creator and the clock is enabled in the DWR, the value from DWR
* used.
* <i>(USER SETTING)</i>
*******************************************************************************/
#define CY_CLK_ECO_FREQ_HZ (24000000UL) /* <<< 24 MHz */
#endif /* (CYDEV_CLK_ECO__HZ) */
#if defined (CYDEV_CLK_ALTHF__HZ)
#define CY_CLK_ALTHF_FREQ_HZ (CYDEV_CLK_ALTHF__HZ)
#else
/***************************************************************************//**
* \brief Alternate high frequency (in Hz, [value]UL). If compiled within
* PSoC Creator and the clock is enabled in the DWR, the value from DWR used.
* Otherwise, edit the value below.
* <i>(USER SETTING)</i>
*******************************************************************************/
#define CY_CLK_ALTHF_FREQ_HZ (32000000UL) /* <<< 32 MHz */
#endif /* (CYDEV_CLK_ALTHF__HZ) */
/***************************************************************************//**
* \brief Start address of the Cortex-M4 application ([address]UL)
* <i>(USER SETTING)</i>
*******************************************************************************/
#define CY_CORTEX_M4_APPL_ADDR (0x10080000UL) /* <<< 512 KB reserved for the Cortex-M0+ application */
/*******************************************************************************
*
* END OF USER SETTINGS HERE
* =========================
*
*******************************************************************************/
/** \} group_system_config_user_settings_macro */
/**
* \addtogroup group_system_config_system_macro
* \{
*/
#if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN)
/** The Cortex-M0+ startup driver identifier */
#define CY_STARTUP_M0P_ID ((uint32_t)((uint32_t)((0x0Eu) & 0x3FFFu) << 18u))
#endif
#if (CY_SYSTEM_CPU_CM0P != 1UL) || defined(CY_DOXYGEN)
/** The Cortex-M4 startup driver identifier */
#define CY_STARTUP_M4_ID ((uint32_t)((uint32_t)((0x0Fu) & 0x3FFFu) << 18u))
#endif
/** \} group_system_config_system_macro */
/**
* \addtogroup group_system_config_system_functions
* \{
*/
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
/** \} group_system_config_system_functions */
/**
* \addtogroup group_system_config_cm4_functions
* \{
*/
extern uint32_t Cy_SysGetCM4Status(void);
extern void Cy_SysEnableCM4(uint32_t vectorTableOffset);
extern void Cy_SysDisableCM4(void);
extern void Cy_SysRetainCM4(void);
extern void Cy_SysResetCM4(void);
/** \} group_system_config_cm4_functions */
/** \cond */
extern void Default_Handler (void);
extern uint32_t Cy_SaveIRQ(void);
extern void Cy_RestoreIRQ(uint32_t saved);
extern void Cy_SystemInit(void);
extern void Cy_SystemInitFpuEnable(void);
extern uint32_t cy_delayFreqHz;
extern uint32_t cy_delayFreqKhz;
extern uint8_t cy_delayFreqMhz;
extern uint32_t cy_delay32kMs;
/** \endcond */
#if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN)
/**
* \addtogroup group_system_config_cm4_status_macro
* \{
*/
#define CY_SYS_CM4_STATUS_ENABLED (3u) /**< The Cortex-M4 core is enabled: power on, clock on, no isolate, no reset and no retain. */
#define CY_SYS_CM4_STATUS_DISABLED (0u) /**< The Cortex-M4 core is disabled: power off, clock off, isolate, reset and no retain. */
#define CY_SYS_CM4_STATUS_RETAINED (2u) /**< The Cortex-M4 core is retained. power off, clock off, isolate, no reset and retain. */
#define CY_SYS_CM4_STATUS_RESET (1u) /**< The Cortex-M4 core is in the Reset mode: clock off, no isolated, no retain and reset. */
/** \} group_system_config_cm4_status_macro */
#endif
/** \addtogroup group_system_config_globals
* \{
*/
extern uint32_t SystemCoreClock;
extern uint32_t cy_BleEcoClockFreqHz;
extern uint32_t cy_Hfclk0FreqHz;
extern uint32_t cy_PeriClkFreqHz;
/** \} group_system_config_globals */
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_PSOC63_H_ */
/* [] END OF FILE */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,727 @@
/***************************************************************************//**
* \file cy_crypto_common.h
* \version 2.0
*
* \brief
* This file provides common constants and parameters
* for the Crypto driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#if !defined(CY_CRYPTO_COMMON_H)
#define CY_CRYPTO_COMMON_H
#include <stddef.h>
#include <stdbool.h>
#include "cy_device_headers.h"
#include "sysint/cy_sysint.h"
#include "syslib/cy_syslib.h"
#ifndef CY_IP_MXCRYPTO
#error "The CRYPTO driver is not supported on this device"
#endif
#if (CPUSS_CRYPTO_PRESENT == 1)
#define CY_CRYPTO_CORE_ENABLE (1)
/** Driver major version */
#define CY_CRYPTO_DRV_VERSION_MAJOR 2
/** Driver minor version */
#define CY_CRYPTO_DRV_VERSION_MINOR 0
/** Defines the Crypto notify interrupt number */
#define CY_CRYPTO_IPC_INTR_NOTIFY_NUM CY_IPC_INTR_CRYPTO_SRV
/** Defines the Crypto release interrupt number */
#define CY_CRYPTO_IPC_INTR_RELEASE_NUM CY_IPC_INTR_CRYPTO_CLI
/**
* \addtogroup group_crypto_macros
* \{
*/
/** Defines Crypto_Sync blocking execution type parameter */
#define CY_CRYPTO_SYNC_BLOCKING (true)
/** Defines Crypto_Sync non-blocking execution type parameter */
#define CY_CRYPTO_SYNC_NON_BLOCKING (false)
/** Defines the Crypto DES key size (in bytes) */
#define CY_CRYPTO_DES_KEY_SIZE (8u)
/** Defines the Crypto TDES key size (in bytes) */
#define CY_CRYPTO_TDES_KEY_SIZE (24u)
/** Defines the Crypto AES block size (in bytes) */
#define CY_CRYPTO_AES_BLOCK_SIZE (16u)
/** Defines the Crypto AES key maximum size (in bytes) */
#define CY_CRYPTO_AES_128_KEY_SIZE (16u)
/** Defines the Crypto AES key maximum size (in bytes) */
#define CY_CRYPTO_AES_192_KEY_SIZE (24u)
/** Defines the Crypto AES key maximum size (in bytes) */
#define CY_CRYPTO_AES_256_KEY_SIZE (32u)
/** Defines size of the AES block, in four-byte words */
#define CY_CRYPTO_AES_BLOCK_SIZE_U32 (uint32_t)(CY_CRYPTO_AES_BLOCK_SIZE / 4ul)
#if (CPUSS_CRYPTO_SHA == 1)
/** Hash size for the SHA1 mode (in bytes) */
#define CY_CRYPTO_SHA1_DIGEST_SIZE (20u)
/** Hash size for the SHA224 mode (in bytes) */
#define CY_CRYPTO_SHA224_DIGEST_SIZE (28u)
/** Hash size for the SHA256 mode (in bytes) */
#define CY_CRYPTO_SHA256_DIGEST_SIZE (32u)
/** Hash size for the SHA384 mode (in bytes) */
#define CY_CRYPTO_SHA384_DIGEST_SIZE (48u)
/** Hash size for the SHA512 mode (in bytes) */
#define CY_CRYPTO_SHA512_DIGEST_SIZE (64u)
/** Hash size for the SHA512_224 mode (in bytes) */
#define CY_CRYPTO_SHA512_224_DIGEST_SIZE (28u)
/** Hash size for the SHA512_256 mode (in bytes) */
#define CY_CRYPTO_SHA512_256_DIGEST_SIZE (32u)
#endif /* #if (CPUSS_CRYPTO_SHA == 1) */
#if (CPUSS_CRYPTO_VU == 1)
/** Processed message size for the RSA 1024Bit mode (in bytes) */
#define CY_CRYPTO_RSA1024_MESSAGE_SIZE (128)
/** Processed message size for the RSA 1536Bit mode (in bytes) */
#define CY_CRYPTO_RSA1536_MESSAGE_SIZE (192)
/** Processed message size for the RSA 2048Bit mode (in bytes) */
#define CY_CRYPTO_RSA2048_MESSAGE_SIZE (256)
#endif /* #if (CPUSS_CRYPTO_VU == 1) */
/** Crypto Driver PDL ID */
#define CY_CRYPTO_ID CY_PDL_DRV_ID(0x0Cu)
/** \} group_crypto_macros */
/**
* \addtogroup group_crypto_config_structure
* \{
*/
/** The Crypto user callback function type.
Callback is called at the end of Crypto calculation. */
typedef void (*cy_crypto_callback_ptr_t)(void);
/** The Crypto configuration structure. */
typedef struct
{
/** Defines the IPC channel used for client-server data exchange */
uint32_t ipcChannel;
/** Specifies the IPC notifier channel (IPC interrupt structure number)
to notify server that data for the operation is prepared */
uint32_t acquireNotifierChannel;
/** Specifies the IPC notifier channel (IPC interrupt structure number)
to notify client that operation is complete and data is valid */
uint32_t releaseNotifierChannel;
/** Specifies the release notifier interrupt configuration. It used for
internal purposes and user doesn't fill it. */
cy_stc_sysint_t releaseNotifierConfig;
/** User callback function.
If this field is NOT NULL, it called when Crypto operation
is complete. */
cy_crypto_callback_ptr_t userCompleteCallback;
#if (CY_CRYPTO_CORE_ENABLE)
/** Server-side user IRQ handler function, called when data for the
operation is prepared to process.
- If this field is NULL, server will use own interrupt handler
to get data.
- If this field is not NULL, server will call this interrupt handler.
This interrupt handler must call the
\ref Cy_Crypto_Server_GetDataHandler to get data to process.
Note: In the second case user should process data separately and
clear interrupt by calling \ref Cy_Crypto_Server_Process.
This model is used in the
multitasking environment (e.g. CyOS). */
cy_israddress userGetDataHandler;
/** Server-side user IRQ handler function, called when a Crypto hardware
error occurs (interrupt was raised).
- If this field is NULL - server will use own interrupt handler
for error processing.
- If this field is not NULL - server will call this interrupt handler.
This interrupt handler must call the
\ref Cy_Crypto_Server_ErrorHandler to clear the interrupt. */
cy_israddress userErrorHandler;
/** Specifies the prepared data notifier interrupt configuration. It used
for internal purposes and user doesn't fill it. */
cy_stc_sysint_t acquireNotifierConfig;
/** Specifies the hardware error processing interrupt configuration. It used
for internal purposes and user doesn't fill it. */
cy_stc_sysint_t cryptoErrorIntrConfig;
#endif /* (CY_CRYPTO_CORE_ENABLE) */
} cy_stc_crypto_config_t;
/** \} group_crypto_config_structure */
/**
* \addtogroup group_crypto_cli_data_structures
* \{
*/
#if (CPUSS_CRYPTO_VU == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the RSA public key and
* additional coefficients to accelerate RSA calculation.
*
* RSA key contained from two fields:
* - n - modulus part of the key
* - e - exponent part of the key.
*
* Other fields are accelerating coefficients and can be calculated by
* \ref Cy_Crypto_Rsa_CalcCoefs.
*/
typedef struct
{
/** The pointer to the modulus part of public key. */
uint8_t *moduloPtr;
/** The modulus length, in bits, maximum supported size is 2048Bit */
uint32_t moduloLength;
/** The pointer to the exponent part of public key */
uint8_t *pubExpPtr;
/** The exponent length, in bits, maximum supported size is 256Bit */
uint32_t pubExpLength;
/** The pointer to the Barrett coefficient. Memory for it should be
allocated by user with size moduloLength + 1. */
uint8_t *barretCoefPtr;
/** The pointer to the binary inverse of the modulo. Memory for it
should be allocated by user with size moduloLength. */
uint8_t *inverseModuloPtr;
/** The pointer to the (2^moduloLength mod modulo). Memory for it should
be allocated by user with size moduloLength */
uint8_t *rBarPtr;
} cy_stc_crypto_rsa_pub_key_t;
#endif /* #if (CPUSS_CRYPTO_VU == 1) */
/** Structure for storing a description of a Crypto hardware error */
typedef struct
{
/**
Captures error description information:
for INSTR_OPC_ERROR: - violating the instruction.
for INSTR_CC_ERROR : - violating the instruction condition code.
for BUS_ERROR : - violating the transfer address. */
uint32_t errorStatus0;
/**
[31] - Specifies if ERROR_STATUS0 and ERROR_STATUS1 capture valid
error-information.
[26..24] - The error source:
"0": INSTR_OPC_ERROR - an instruction decoder error.
"1": INSTR_CC_ERROR - an instruction condition code-error.
"2": BUS_ERROR - a bus master interface AHB-Lite bus-error.
"3": TR_AP_DETECT_ERROR.
[23..0] - Captures error description information.
For BUS_ERROR:
- violating the transfer, read the attribute (DATA23[0]).
- violating the transfer, the size attribute (DATA23[5:4]).
"0": an 8-bit transfer;
"1": 16 bits transfer;
"2": 32-bit transfer. */
uint32_t errorStatus1;
} cy_stc_crypto_hw_error_t;
/** \} group_crypto_cli_data_structures */
/** The Crypto library functionality level. */
typedef enum
{
CY_CRYPTO_NO_LIBRARY = 0x00u,
CY_CRYPTO_BASE_LIBRARY = 0x01u,
CY_CRYPTO_EXTRA_LIBRARY = 0x02u,
CY_CRYPTO_FULL_LIBRARY = 0x03u,
} cy_en_crypto_lib_info_t;
/**
* \addtogroup group_crypto_enums
* \{
*/
#if (CPUSS_CRYPTO_AES == 1)
/** The key length options for the AES method. */
typedef enum
{
CY_CRYPTO_KEY_AES_128 = 0x00u, /**< The AES key size is 128 bits */
CY_CRYPTO_KEY_AES_192 = 0x01u, /**< The AES key size is 192 bits */
CY_CRYPTO_KEY_AES_256 = 0x02u /**< The AES key size is 256 bits */
} cy_en_crypto_aes_key_length_t;
#endif /* #if (CPUSS_CRYPTO_AES == 1) */
/** Defines the direction of the Crypto methods */
typedef enum
{
/** The forward mode, plain text will be encrypted into cipher text */
CY_CRYPTO_ENCRYPT = 0x00u,
/** The reverse mode, cipher text will be decrypted into plain text */
CY_CRYPTO_DECRYPT = 0x01u
} cy_en_crypto_dir_mode_t;
#if (CPUSS_CRYPTO_SHA == 1)
/** Defines modes of SHA method */
typedef enum
{
#if (CPUSS_CRYPTO_SHA1 == 1)
CY_CRYPTO_MODE_SHA1 = 0x00u, /**< Sets the SHA1 mode */
#endif /* #if (CPUSS_CRYPTO_SHA1 == 1) */
#if (CPUSS_CRYPTO_SHA256 == 1)
CY_CRYPTO_MODE_SHA224 = 0x11u, /**< Sets the SHA224 mode */
CY_CRYPTO_MODE_SHA256 = 0x01u, /**< Sets the SHA256 mode */
#endif /* #if (CPUSS_CRYPTO_SHA256 == 1) */
#if (CPUSS_CRYPTO_SHA512 == 1)
CY_CRYPTO_MODE_SHA384 = 0x12u, /**< Sets the SHA384 mode */
CY_CRYPTO_MODE_SHA512 = 0x02u, /**< Sets the SHA512 mode */
CY_CRYPTO_MODE_SHA512_256 = 0x22u, /**< Sets the SHA512/256 mode */
CY_CRYPTO_MODE_SHA512_224 = 0x32u /**< Sets the SHA512/224 mode */
#endif /* #if (CPUSS_CRYPTO_SHA512 == 1) */
} cy_en_crypto_sha_mode_t;
#endif /* #if (CPUSS_CRYPTO_SHA == 1) */
/** Signature verification status */
typedef enum
{
CY_CRYPTO_RSA_VERIFY_SUCCESS = 0x00u, /**< PKCS1-v1.5 verify SUCCESS */
CY_CRYPTO_RSA_VERIFY_FAIL = 0x01u /**< PKCS1-v1.5 verify FAILED */
} cy_en_crypto_rsa_ver_result_t;
/** Errors of the Crypto block */
typedef enum
{
/** Operation completed successfully. */
CY_CRYPTO_SUCCESS = 0x00u,
/** A hardware error occurred, detailed information is in stc_crypto_hw_error_t. */
CY_CRYPTO_HW_ERROR = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x01u,
/** The size of input data is not multiple of 16. */
CY_CRYPTO_SIZE_NOT_X16 = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x02u,
/** The key for the DES method is weak. */
CY_CRYPTO_DES_WEAK_KEY = CY_CRYPTO_ID | CY_PDL_STATUS_WARNING | 0x03u,
/** Communication between the client and server via IPC is broken. */
CY_CRYPTO_COMM_FAIL = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x04u,
/** The Crypto server is not started. */
CY_CRYPTO_SERVER_NOT_STARTED = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x06u,
/** The Crypto server in process state. */
CY_CRYPTO_SERVER_BUSY = CY_CRYPTO_ID | CY_PDL_STATUS_INFO | 0x07u,
/** The Crypto driver is not initialized. */
CY_CRYPTO_NOT_INITIALIZED = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x08u,
/** The Crypto hardware is not enabled. */
CY_CRYPTO_HW_NOT_ENABLED = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x09u,
/** The Crypto operation is not supported. */
CY_CRYPTO_NOT_SUPPORTED = CY_CRYPTO_ID | CY_PDL_STATUS_ERROR | 0x0Au
} cy_en_crypto_status_t;
/** \} group_crypto_enums */
/** \cond INTERNAL */
/** Instruction to communicate between Client and Server */
typedef enum
{
CY_CRYPTO_INSTR_UNKNOWN = 0x00u,
CY_CRYPTO_INSTR_ENABLE = 0x01u,
CY_CRYPTO_INSTR_DISABLE = 0x02u,
#if (CPUSS_CRYPTO_PR == 1)
CY_CRYPTO_INSTR_PRNG_INIT = 0x03u,
CY_CRYPTO_INSTR_PRNG = 0x04u,
#endif /* #if (CPUSS_CRYPTO_PR == 1) */
#if (CPUSS_CRYPTO_TR == 1)
CY_CRYPTO_INSTR_TRNG_INIT = 0x05u,
CY_CRYPTO_INSTR_TRNG = 0x06u,
#endif /* #if (CPUSS_CRYPTO_PR == 1) */
#if (CPUSS_CRYPTO_AES == 1)
CY_CRYPTO_INSTR_AES_INIT = 0x07u,
CY_CRYPTO_INSTR_AES_ECB = 0x08u,
CY_CRYPTO_INSTR_AES_CBC = 0x09u,
CY_CRYPTO_INSTR_AES_CFB = 0x0Au,
CY_CRYPTO_INSTR_AES_CTR = 0x0Bu,
CY_CRYPTO_INSTR_CMAC = 0x0Cu,
#endif /* #if (CPUSS_CRYPTO_AES == 1) */
#if (CPUSS_CRYPTO_SHA == 1)
CY_CRYPTO_INSTR_SHA = 0x0Du,
#endif /* #if (CPUSS_CRYPTO_SHA == 1) */
#if (CPUSS_CRYPTO_SHA == 1)
CY_CRYPTO_INSTR_HMAC = 0x0Eu,
#endif /* #if (CPUSS_CRYPTO_SHA == 1) */
#if (CPUSS_CRYPTO_STR == 1)
CY_CRYPTO_INSTR_MEM_CPY = 0x0Fu,
CY_CRYPTO_INSTR_MEM_SET = 0x10u,
CY_CRYPTO_INSTR_MEM_CMP = 0x11u,
CY_CRYPTO_INSTR_MEM_XOR = 0x12u,
#endif /* #if (CPUSS_CRYPTO_STR == 1) */
#if (CPUSS_CRYPTO_CRC == 1)
CY_CRYPTO_INSTR_CRC_INIT = 0x13u,
CY_CRYPTO_INSTR_CRC = 0x14u,
#endif /* #if (CPUSS_CRYPTO_CRC == 1) */
#if (CPUSS_CRYPTO_DES == 1)
CY_CRYPTO_INSTR_DES = 0x15u,
CY_CRYPTO_INSTR_3DES = 0x16u,
#endif /* #if (CPUSS_CRYPTO_DES == 1) */
#if (CPUSS_CRYPTO_VU == 1)
CY_CRYPTO_INSTR_RSA_PROC = 0x17u,
CY_CRYPTO_INSTR_RSA_COEF = 0x18u,
#endif /* #if (CPUSS_CRYPTO_VU == 1) */
#if (CPUSS_CRYPTO_SHA == 1)
CY_CRYPTO_INSTR_RSA_VER = 0x19u,
#endif /* #if (CPUSS_CRYPTO_SHA == 1) */
CY_CRYPTO_INSTR_SRV_INFO = 0x55u
} cy_en_crypto_comm_instr_t;
/** \endcond */
/**
* \addtogroup group_crypto_cli_data_structures
* \{
*/
#if (CPUSS_CRYPTO_AES == 1)
/** Structure for storing the AES state */
typedef struct
{
/** Pointer to AES key */
uint32_t *key;
/** Pointer to AES inversed key */
uint32_t *invKey;
/** AES key length */
cy_en_crypto_aes_key_length_t keyLength;
/** AES processed block index (for CMAC, SHA operations) */
uint32_t blockIdx;
} cy_stc_crypto_aes_state_t;
#endif /* #if (CPUSS_CRYPTO_AES == 1) */
/** \} group_crypto_cli_data_structures */
/*************************************************************
* Structures used for communication between Client and Server
***************************************************************/
/**
* \addtogroup group_crypto_srv_data_structures
* \{
*/
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the server
* context.
*/
typedef struct
{
/** IPC communication channel number */
uint32_t ipcChannel;
/** IPC acquire interrupt channel number */
uint32_t acquireNotifierChannel;
/** IPC release interrupt channel number */
cy_israddress getDataHandlerPtr;
/** Crypto hardware errors interrupt handler */
cy_israddress errorHandlerPtr;
/** Acquire notifier interrupt configuration */
cy_stc_sysint_t acquireNotifierConfig;
/** Crypto hardware errors interrupt configuration */
cy_stc_sysint_t cryptoErrorIntrConfig;
/** Hardware error occurrence flag */
bool isHwErrorOccured;
} cy_stc_crypto_server_context_t;
/** \} group_crypto_srv_data_structures */
/**
* \addtogroup group_crypto_cli_data_structures
* \{
*/
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the global
* context.
*/
typedef struct
{
/** Operation instruction code */
cy_en_crypto_comm_instr_t instr;
/** Response from executed crypto function */
cy_en_crypto_status_t resp;
/** Hardware processing errors */
cy_stc_crypto_hw_error_t hwErrorStatus;
/** IPC communication channel number */
uint32_t ipcChannel;
/** IPC acquire interrupt channel number */
uint32_t acquireNotifierChannel;
/** IPC release interrupt channel number */
uint32_t releaseNotifierChannel;
/** User callback for Crypto HW calculation complete event */
cy_crypto_callback_ptr_t userCompleteCallback;
/** Release notifier interrupt configuration */
cy_stc_sysint_t releaseNotifierConfig;
/** Pointer to the crypto function specific context data */
void *xdata;
} cy_stc_crypto_context_t;
#if (CPUSS_CRYPTO_DES == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the DES operational
* context.
*/
typedef struct
{
/** Operation direction (Encrypt / Decrypt) */
cy_en_crypto_dir_mode_t dirMode;
/** Pointer to key data */
uint32_t *key;
/** Pointer to data destination block */
uint32_t *dst;
/** Pointer to data source block */
uint32_t *src;
} cy_stc_crypto_context_des_t;
#endif /* #if (CPUSS_CRYPTO_DES == 1) */
#if (CPUSS_CRYPTO_AES == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the AES operational
* context.
*/
typedef struct
{
/** AES state data */
cy_stc_crypto_aes_state_t aesState;
/** Operation direction (Encrypt / Decrypt) */
cy_en_crypto_dir_mode_t dirMode;
/** Operation data size */
uint32_t srcSize;
/** Size of the last non-complete block (for CTR mode only) */
uint32_t *srcOffset;
/** Initialization vector, in the CTR mode is used as nonceCounter */
uint32_t *ivPtr;
/** AES processed block pointer (for CTR mode only) */
uint32_t *streamBlock;
/** Pointer to data destination block */
uint32_t *dst;
/** Pointer to data source block */
uint32_t *src;
} cy_stc_crypto_context_aes_t;
#endif /* #if (CPUSS_CRYPTO_AES == 1) */
#if (CPUSS_CRYPTO_SHA == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the SHA operational
* context.
*/
typedef struct
{
/** Pointer to data source block */
uint32_t *message;
/** Operation data size */
uint32_t messageSize;
/** Pointer to data destination block */
uint32_t *dst;
/** SHA mode */
cy_en_crypto_sha_mode_t mode;
/** Pointer to key data (for HMAC only) */
uint32_t *key;
/** Key data length (for HMAC only) */
uint32_t keyLength;
} cy_stc_crypto_context_sha_t;
#endif /* #if (CPUSS_CRYPTO_SHA == 1) */
#if (CPUSS_CRYPTO_PR == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the PRNG operational
* context.
*/
typedef struct
{
uint32_t lfsr32InitState; /**< lfsr32 initialization data */
uint32_t lfsr31InitState; /**< lfsr31 initialization data */
uint32_t lfsr29InitState; /**< lfsr29 initialization data */
uint32_t max; /**< Maximum of the generated value */
uint32_t *prngNum; /**< Pointer to generated value */
} cy_stc_crypto_context_prng_t;
#endif /* #if (CPUSS_CRYPTO_PR == 1) */
#if (CPUSS_CRYPTO_TR == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the TRNG operational
* context.
*/
typedef struct
{
/**
The polynomial for the programmable Galois ring oscillator (TR_GARO_CTL).
The polynomial is represented WITHOUT the high order bit (this bit is
always assumed '1').
The polynomial should be aligned so that more significant bits
(bit 30 and down) contain the polynomial and less significant bits
(bit 0 and up) contain padding '0's. */
uint32_t GAROPol;
/**
The polynomial for the programmable Fibonacci ring oscillator(TR_FIRO_CTL).
The polynomial is represented WITHOUT the high order bit (this bit is
always assumed '1').
The polynomial should be aligned so that more significant bits
(bit 30 and down) contain the polynomial and less significant bits
(bit 0 and up) contain padding '0's. */
uint32_t FIROPol;
/** Maximum of the generated value */
uint32_t max;
/** Pointer to generated value */
uint32_t *trngNum;
} cy_stc_crypto_context_trng_t;
#endif /* #if (CPUSS_CRYPTO_TR == 1) */
#if (CPUSS_CRYPTO_STR == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the STR operational
* context.
*/
typedef struct
{
void const *src0; /**< Pointer to 1-st string source */
void const *src1; /**< Pointer to 2-nd string source */
void *dst; /**< Pointer to string destination */
uint32_t dataSize; /**< Operation data size */
uint32_t data; /**< Operation data value (for memory setting) */
} cy_stc_crypto_context_str_t;
#endif /* #if (CPUSS_CRYPTO_STR == 1) */
#if (CPUSS_CRYPTO_CRC == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the CRC operational
* context.
*/
typedef struct
{
void* srcData; /**< Pointer to data source block */
uint32_t dataSize; /**< Operation data size */
uint32_t *crc; /**< Pointer to CRC destination variable */
uint32_t polynomial; /**< Polynomial for CRC calculate */
uint32_t lfsrInitState; /**< CRC calculation initial value */
uint32_t dataReverse; /**< Input data reverse flag */
uint32_t dataXor; /**< Input data XOR flag */
uint32_t remReverse; /**< Output data reverse flag */
uint32_t remXor; /**< Output data XOR flag */
} cy_stc_crypto_context_crc_t;
#endif /* #if (CPUSS_CRYPTO_CRC == 1) */
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the RSA verifying
* context.
*/
typedef struct
{
/** Pointer to verification result /ref cy_en_crypto_rsa_ver_result_t */
cy_en_crypto_rsa_ver_result_t *verResult;
/** SHA digest type, used with SHA calculation of the message */
cy_en_crypto_sha_mode_t digestType;
/** SHA digest of the message, calculated with digestType */
uint32_t const *hash;
/** Previously decrypted RSA signature */
uint32_t const *decryptedSignature;
/** Length of the decrypted RSA signature */
uint32_t decryptedSignatureLength;
} cy_stc_crypto_context_rsa_ver_t;
#if (CPUSS_CRYPTO_VU == 1)
/**
* Firmware allocates memory and provides a pointer to this structure in
* function calls. Firmware does not write or read values in this structure.
* The driver uses this structure to store and manipulate the RSA operational
* context.
*/
typedef struct
{
/** Pointer to key data */
cy_stc_crypto_rsa_pub_key_t const *key;
/** Pointer to data source block */
uint32_t const *message;
/** Operation data size */
uint32_t messageSize;
/** Pointer to data destination block */
uint32_t *result;
} cy_stc_crypto_context_rsa_t;
#endif /* #if (CPUSS_CRYPTO_VU == 1) */
/** \} group_crypto_cli_data_structures */
#endif /* (CPUSS_CRYPTO_PRESENT == 1) */
#endif /* #if !defined(CY_CRYPTO_COMMON_H) */
/* [] END OF FILE */

View File

@ -0,0 +1,69 @@
/***************************************************************************//**
* \file
* \version 2.0
*
* Description:
* This C file is not intended to be part of the Crypto driver. It is the code
* required to configure the crypto driver by user.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_crypto_config.h"
#include "ipc/cy_ipc_drv.h"
#include "sysint/cy_sysint.h"
/** The Crypto configuration structure. */
const cy_stc_crypto_config_t cryptoConfig =
{
/* .ipcChannel */ CY_IPC_CHAN_CRYPTO,
/* .acquireNotifierChannel */ CY_CRYPTO_IPC_INTR_NOTIFY_NUM,
/* .releaseNotifierChannel */ CY_CRYPTO_IPC_INTR_RELEASE_NUM,
/* .releaseNotifierConfig */ {
#if (CY_CPU_CORTEX_M0P)
/* .intrSrc */ CY_CRYPTO_CM0_RELEASE_INTR_NR,
/* .cm0pSrc */ (cy_en_intr_t)CY_IPC_INTR_NUM_TO_VECT((int32_t)CY_CRYPTO_IPC_INTR_RELEASE_NUM),
#else
/* .intrSrc */ (IRQn_Type)CY_IPC_INTR_NUM_TO_VECT((int32_t)CY_CRYPTO_IPC_INTR_RELEASE_NUM),
#endif
/* .intrPriority */ CY_CRYPTO_RELEASE_INTR_PR,
},
/* .userCompleteCallback */ NULL
#if (CY_CRYPTO_CORE_ENABLE)
,
/* .userGetDataHandler */ NULL,
/* .userErrorHandler */ NULL,
/* .acquireNotifierConfig */ {
#if (CY_CPU_CORTEX_M0P)
/* .intrSrc */ CY_CRYPTO_CM0_NOTIFY_INTR_NR,
/* .cm0pSrc */ (cy_en_intr_t)CY_IPC_INTR_NUM_TO_VECT((int32_t)CY_CRYPTO_IPC_INTR_NOTIFY_NUM),
#else
/* .intrSrc */ (IRQn_Type)CY_IPC_INTR_NUM_TO_VECT((int32_t)CY_CRYPTO_IPC_INTR_NOTIFY_NUM),
#endif
/* .intrPriority */ CY_CRYPTO_NOTIFY_INTR_PR,
},
/* .cryptoErrorIntrConfig */ {
#if (CY_CPU_CORTEX_M0P)
/* .intrSrc */ CY_CRYPTO_CM0_ERROR_INTR_NR,
/* .cm0pSrc */ cpuss_interrupt_crypto_IRQn,
#else
/* .intrSrc */ cpuss_interrupt_crypto_IRQn,
#endif
/* .intrPriority */ CY_CRYPTO_ERROR_INTR_PR,
}
#endif
};
/* [] END OF FILE */

View File

@ -0,0 +1,57 @@
/***************************************************************************//**
* \file cy_crypto_config.h
* \version 2.0
*
* \brief
* This file provides user parameters for the Crypto driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#if !defined(CY_CRYPTO_CONFIG_H)
#define CY_CRYPTO_CONFIG_H
#include "cy_device_headers.h"
#include "crypto/cy_crypto_common.h"
/* Defines to configure Crypto driver */
extern const cy_stc_crypto_config_t cryptoConfig;
/**
* \addtogroup group_crypto_config_macros
* \{
*
* These constants defines an interrupts settings for IPC channel used for the
* client-server communications.
*
* On the CM4 core crypto driver uses IPC hardware depended interrupt sources.
*
* For CM0+ core user must define the multiplexed interrupt sources by yourself.
*/
/** Number of Crypto Notify interrupt mapped to CM0+ */
#define CY_CRYPTO_CM0_NOTIFY_INTR_NR (NvicMux2_IRQn)
/** Priority of Crypto Notify interrupt, equal to CM0+ and CM4 cores */
#define CY_CRYPTO_NOTIFY_INTR_PR (2u)
/** Number of Crypto Release interrupt mapped to CM0+ */
#define CY_CRYPTO_CM0_RELEASE_INTR_NR (NvicMux30_IRQn)
/** Priority of Crypto Release interrupt, equal to CM0+ and CM4 cores */
#define CY_CRYPTO_RELEASE_INTR_PR (2u)
/** Number of Crypto Error interrupt mapped to CM0+ */
#define CY_CRYPTO_CM0_ERROR_INTR_NR (NvicMux31_IRQn)
/** Priority of Crypto Error interrupt mapped to CM0+ */
#define CY_CRYPTO_ERROR_INTR_PR (2u)
/** \} group_crypto_config_macros */
#endif /* #if !defined(CY_CRYPTO_CONFIG_H) */
/* [] END OF FILE */

View File

@ -0,0 +1,125 @@
/***************************************************************************//**
* \file cy_crypto_server.h
* \version 2.0
*
* \brief
* This file provides the prototypes for common API
* in the Crypto driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#if !defined(CY_CRYPTO_SERVER_H)
#define CY_CRYPTO_SERVER_H
#include "crypto/cy_crypto_common.h"
#include "syslib/cy_syslib.h"
#if (CY_CRYPTO_CORE_ENABLE)
#if (CPUSS_CRYPTO_PRESENT == 1)
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_crypto_srv_functions
* \{
*/
/*******************************************************************************
* Function Name: Cy_Crypto_Server_Start
****************************************************************************//**
*
* This function starts the Crypto server on the CM0+ core, sets up an interrupt
* for the IPC Crypto channel on the CM0+ core, sets up an interrupt
* to catch Crypto HW errors. Should be invoked only on CM0.
*
* This function available for CM0+ core only.
*
* \param config
* The Crypto configuration structure.
*
* \param context
* The pointer to the \ref cy_stc_crypto_server_context_t structure that stores
* the Crypto server context.
*
* \return
* A Crypto status \ref cy_en_crypto_status_t.
*
*******************************************************************************/
cy_en_crypto_status_t Cy_Crypto_Server_Start(cy_stc_crypto_config_t const *config,
cy_stc_crypto_server_context_t *context);
/*******************************************************************************
* Function Name: Cy_Crypto_Server_Stop
****************************************************************************//**
*
* This function stops the Crypto server by disabling the IPC notify interrupt
* and Crypto error interrupt. Should be invoked only on CM0.
*
* This function available for CM0+ core only.
*
* \return
* A Crypto status \ref cy_en_crypto_status_t.
*
*******************************************************************************/
cy_en_crypto_status_t Cy_Crypto_Server_Stop(void);
/*******************************************************************************
* Function Name: Cy_Crypto_Server_Process
****************************************************************************//**
*
* This function parses input data received from the Crypto Client,
* runs the appropriate Crypto function and releases the Crypto IPC channel.
*
* This function available for CM0+ core only.
*
*******************************************************************************/
void Cy_Crypto_Server_Process(void);
/*******************************************************************************
* Function Name: Cy_Crypto_Server_GetDataHandler
****************************************************************************//**
*
* This function is a IPC Crypto channel notify interrupt-routine.
* It receives information from the Crypto client,
* runs the process if user not setup own handler.
*
* This function available for CM0+ core only.
*
*******************************************************************************/
void Cy_Crypto_Server_GetDataHandler(void);
/*******************************************************************************
* Function Name: Cy_Crypto_Server_ErrorHandler
****************************************************************************//**
*
* This function is a routine to handle an interrupt caused by the Crypto hardware error.
*
* This function available for CM0+ core only.
*
*******************************************************************************/
void Cy_Crypto_Server_ErrorHandler(void);
/** \} group_crypto_srv_functions */
#if defined(__cplusplus)
}
#endif
#endif /* #if (CPUSS_CRYPTO_PRESENT == 1) */
#endif /* #if (CY_CRYPTO_CORE_ENABLE) */
#endif /* #if !defined(CY_CRYPTO_SERVER_H) */
/* [] END OF FILE */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,656 @@
/***************************************************************************//**
* \file cy_ctdac.c
* \version 1.0
*
* Provides the public functions for the API for the CTDAC driver.
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "ctdac/cy_ctdac.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** Static function to configure the clock */
static void Cy_CTDAC_ConfigureClock(cy_en_ctdac_update_t updateMode, cy_en_divider_types_t dividerType,
uint32_t dividerNum, uint32_t dividerIntValue, uint32_t dividerFracValue);
const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_UnbufferedOut =
{
/*.refSource */ CY_CTDAC_REFSOURCE_VDDA,
/*.outputBuffer */ CY_CTDAC_OUTPUT_UNBUFFERED,
};
const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_BufferedOut =
{
/*.refSource */ CY_CTDAC_REFSOURCE_VDDA,
/*.outputBuffer */ CY_CTDAC_OUTPUT_BUFFERED,
};
const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_UnbufferedOut =
{
/*.refSource */ CY_CTDAC_REFSOURCE_EXTERNAL,
/*.outputBuffer */ CY_CTDAC_OUTPUT_UNBUFFERED,
};
const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_BufferedOut =
{
/*.refSource */ CY_CTDAC_REFSOURCE_EXTERNAL,
/*.outputBuffer */ CY_CTDAC_OUTPUT_BUFFERED,
};
/*******************************************************************************
* Function Name: Cy_CTDAC_Init
****************************************************************************//**
*
* Initialize all CTDAC configuration registers
*
* \param base
* Pointer to structure describing registers
*
* \param config
* Pointer to structure containing configuration data
*
* \return cy_en_ctdac_status_t
* Status of initialization, CY_CTDAC_SUCCESS or CY_CTDAC_BAD_PARAM
*
*******************************************************************************/
cy_en_ctdac_status_t Cy_CTDAC_Init(CTDAC_Type *base, const cy_stc_ctdac_config_t *config)
{
CY_ASSERT_L1(NULL != base);
CY_ASSERT_L1(NULL != config);
cy_en_ctdac_status_t result;
uint32_t ctdacCtrl = CY_CTDAC_DEINIT;
uint32_t setSwitch = CY_CTDAC_DEINIT;
uint32_t clearSwitch = CY_CTDAC_DEINIT;
if ((NULL == base) || (NULL == config))
{
result = CY_CTDAC_BAD_PARAM;
}
else
{
CY_ASSERT_L3(CY_CTDAC_REFSOURCE(config->refSource));
CY_ASSERT_L3(CY_CTDAC_FORMAT(config->formatMode));
CY_ASSERT_L3(CY_CTDAC_UPDATE(config->updateMode));
CY_ASSERT_L3(CY_CTDAC_DEGLITCH(config->deglitchMode));
CY_ASSERT_L3(CY_CTDAC_OUTPUTMODE(config->outputMode));
CY_ASSERT_L3(CY_CTDAC_OUTPUTBUFFER(config->outputBuffer));
CY_ASSERT_L3(CY_CTDAC_DEEPSLEEP(config->deepSleep));
CY_ASSERT_L2(CY_CTDAC_DEGLITCHCYCLES(config->deglitchCycles));
/* Handle the deglitch counts */
ctdacCtrl |= (config->deglitchCycles << CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Pos) & CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Msk;
/* Handle the deglitch mode */
ctdacCtrl |= (uint32_t)config->deglitchMode;
/* Handle the update mode */
if ((config->updateMode == CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE) \
|| (config->updateMode == CY_CTDAC_UPDATE_STROBE_EDGE_SYNC) \
|| (config->updateMode == CY_CTDAC_UPDATE_STROBE_LEVEL))
{
ctdacCtrl |= CTDAC_CTDAC_CTRL_DSI_STROBE_EN_Msk;
}
if (config->updateMode == CY_CTDAC_UPDATE_STROBE_LEVEL)
{
ctdacCtrl |= CTDAC_CTDAC_CTRL_DSI_STROBE_LEVEL_Msk;
}
/* Handle the sign format */
ctdacCtrl |= (uint32_t)config->formatMode;
/* Handle the Deep Sleep mode */
ctdacCtrl |= (uint32_t)config->deepSleep;
/* Handle the output mode */
ctdacCtrl |= (uint32_t)config->outputMode;
/* Handle enable bit */
ctdacCtrl |= ((uint32_t)config->enable) << CTDAC_CTDAC_CTRL_ENABLED_Pos;
/* Handle the reference source */
switch(config->refSource)
{
case CY_CTDAC_REFSOURCE_VDDA:
/* Close the CVD switch to use Vdda as the reference source */
setSwitch |= CTDAC_CTDAC_SW_CTDD_CVD_Msk;
break;
case CY_CTDAC_REFSOURCE_EXTERNAL:
default:
clearSwitch |= CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk;
break;
}
/* Handle the output buffer switch CO6 */
switch(config->outputBuffer)
{
case CY_CTDAC_OUTPUT_UNBUFFERED:
/* Close the CO6 switch to send output to a direct pin unbuffered */
setSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk;
break;
case CY_CTDAC_OUTPUT_BUFFERED:
default:
clearSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk;
break;
}
base->INTR_MASK = (uint32_t)config->enableInterrupt << CTDAC_INTR_VDAC_EMPTY_Pos;
base->CTDAC_SW = setSwitch;
base->CTDAC_SW_CLEAR = clearSwitch;
base->CTDAC_VAL = (((uint32_t)config->value) << CTDAC_CTDAC_VAL_VALUE_Pos) & CTDAC_CTDAC_VAL_VALUE_Msk;
base->CTDAC_VAL_NXT = (((uint32_t)config->nextValue) << CTDAC_CTDAC_VAL_NXT_VALUE_Pos) & CTDAC_CTDAC_VAL_NXT_VALUE_Msk;
if (config->configClock)
{
Cy_CTDAC_ConfigureClock(config->updateMode, config->dividerType, config->dividerNum, config->dividerIntValue, config->dividerFracValue);
}
base->CTDAC_CTRL = ctdacCtrl;
result = CY_CTDAC_SUCCESS;
}
return result;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_DeInit
****************************************************************************//**
*
* Reset CTDAC registers back to power on reset defaults.
*
* Does not disable or configure the clock. Call \ref Cy_CTDAC_Init or \ref Cy_CTDAC_FastInit
* to configure the CTDAC and clock.
*
* \param base
* Pointer to structure describing registers
*
* \param deInitRouting
* If true, all switches are reset to their default state.
* If false, switch registers are untouched.
*
* \return cy_en_ctdac_status_t
* Status of initialization, CY_CTDAC_SUCCESS, or CY_CTDAC_BAD_PARAM
*
*******************************************************************************/
cy_en_ctdac_status_t Cy_CTDAC_DeInit(CTDAC_Type *base, bool deInitRouting)
{
CY_ASSERT_L1(NULL != base);
cy_en_ctdac_status_t result;
if (NULL == base)
{
result = CY_CTDAC_BAD_PARAM;
}
else
{
base->CTDAC_CTRL = CY_CTDAC_DEINIT;
base->INTR_MASK = CY_CTDAC_DEINIT;
base->CTDAC_VAL = CY_CTDAC_DEINIT;
base->CTDAC_VAL_NXT = CY_CTDAC_DEINIT;
if (deInitRouting)
{
base->CTDAC_SW_CLEAR = CY_CTDAC_DEINIT;
}
result = CY_CTDAC_SUCCESS;
}
return result;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_FastInit
****************************************************************************//**
*
* Initializes the CTDAC to one of the common use modes.
* These provide a quick and easy method of configuring the CTDAC when using
* the PDL driver for device configuration.
*
* The other configuration options are set to:
* - .formatMode = CY_CTDAC_FORMAT_UNSIGNED
* - .updateMode = CY_CTDAC_UPDATE_BUFFERED_WRITE
* - .deglitchMode = CY_CTDAC_DEGLITCHMODE_NONE
* - .outputMode = CY_CTDAC_OUTPUT_VALUE
* - .deepSleep = CY_CTDAC_DEEPSLEEP_DISABLE
* - .deglitchCycles = CY_CTDAC_DEINIT
* - .value = CY_CTDAC_UNSIGNED_MID_CODE_VALUE
* - .nextValue = CY_CTDAC_UNSIGNED_MID_CODE_VALUE
* - .enableInterrupt = true
* - .configClock = true
* - .dividerType = CY_CTDAC_FAST_CLKCFG_TYPE
* - .dividerNum = CY_CTDAC_FAST_CLKCFG_NUM
* - .dividerInitValue = CY_CTDAC_FAST_CLKCFG_DIV
* - .dividerFracValue = CY_CTDAC_DEINIT
*
* \param base
* Pointer to structure describing registers
*
* \param config
* Pointer to structure containing configuration data for quick initialization
* Use one of the provided structures or define your own.
* - \ref Cy_CTDAC_Fast_VddaRef_UnbufferedOut
* - \ref Cy_CTDAC_Fast_VddaRef_BufferedOut
* - \ref Cy_CTDAC_Fast_OA1Ref_UnbufferedOut
* - \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut
*
* \return cy_en_ctdac_status_t
* Status of initialization, CY_CTDAC_SUCCESS or CY_CTDAC_BAD_PARAM
*
*******************************************************************************/
cy_en_ctdac_status_t Cy_CTDAC_FastInit(CTDAC_Type *base, const cy_stc_ctdac_fast_config_t *config)
{
CY_ASSERT_L1(NULL != base);
CY_ASSERT_L1(NULL != config);
cy_en_ctdac_status_t result;
uint32_t ctdacCtrl;
uint32_t setSwitch = CY_CTDAC_DEINIT;
uint32_t clearSwitch = CY_CTDAC_DEINIT;
if ((NULL == base) || (NULL == config))
{
result = CY_CTDAC_BAD_PARAM;
}
else
{
CY_ASSERT_L3(CY_CTDAC_REFSOURCE(config->refSource));
CY_ASSERT_L3(CY_CTDAC_OUTPUTBUFFER(config->outputBuffer));
ctdacCtrl = (uint32_t) CY_CTDAC_DEGLITCHMODE_NONE \
| (uint32_t) CY_CTDAC_UPDATE_BUFFERED_WRITE \
| (uint32_t) CY_CTDAC_FORMAT_UNSIGNED \
| (uint32_t) CY_CTDAC_DEEPSLEEP_DISABLE \
| (uint32_t) CY_CTDAC_OUTPUT_VALUE;
/* Handle the reference source */
switch(config->refSource)
{
case CY_CTDAC_REFSOURCE_VDDA:
/* Close the CVD switch to use Vdda as the reference source */
setSwitch |= CTDAC_CTDAC_SW_CTDD_CVD_Msk;
break;
case CY_CTDAC_REFSOURCE_EXTERNAL:
default:
clearSwitch |= CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk;
break;
}
/* Handle the output buffer switch CO6 */
switch(config->outputBuffer)
{
case CY_CTDAC_OUTPUT_UNBUFFERED:
/* Close the CO6 switch to send output to a direct pin unbuffered */
setSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk;
break;
case CY_CTDAC_OUTPUT_BUFFERED:
default:
clearSwitch |= CTDAC_CTDAC_SW_CTDO_CO6_Msk;
break;
}
base->INTR_MASK = CTDAC_INTR_VDAC_EMPTY_Msk;
base->CTDAC_SW = setSwitch;
base->CTDAC_SW_CLEAR = clearSwitch;
base->CTDAC_VAL = CY_CTDAC_UNSIGNED_MID_CODE_VALUE;
base->CTDAC_VAL_NXT = CY_CTDAC_UNSIGNED_MID_CODE_VALUE;
/* For fast configuration, the DAC clock is the Peri clock divided by 100 */
Cy_CTDAC_ConfigureClock(CY_CTDAC_UPDATE_BUFFERED_WRITE, CY_CTDAC_FAST_CLKCFG_TYPE, CY_CTDAC_FAST_CLKCFG_NUM, CY_CTDAC_FAST_CLKCFG_DIV, CY_CTDAC_DEINIT);
base->CTDAC_CTRL = ctdacCtrl;
result = CY_CTDAC_SUCCESS;
}
return result;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_ConfigureClock
****************************************************************************//**
*
* Private function for configuring the CTDAC clock based on the desired
* update mode. This function is called by \ref Cy_CTDAC_Init.
*
* \param updateMode
* Update mode value. See \ref cy_en_ctdac_update_t for values.
*
* \return None
*
*******************************************************************************/
static void Cy_CTDAC_ConfigureClock(cy_en_ctdac_update_t updateMode, cy_en_divider_types_t dividerType,
uint32_t dividerNum, uint32_t dividerIntValue, uint32_t dividerFracValue)
{
if (updateMode == CY_CTDAC_UPDATE_DIRECT_WRITE)
{ /* In direct mode, there is not a clock */
}
else if(updateMode == CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE)
{
/* In this mode, the Peri Clock is divided by 1 to give a constant logic high on the CTDAC clock. */
(void)Cy_SysClk_PeriphDisableDivider(dividerType, dividerNum);
(void)Cy_SysClk_PeriphAssignDivider(PCLK_PASS_CLOCK_CTDAC, dividerType, dividerNum);
if ((dividerType == CY_SYSCLK_DIV_8_BIT) || (dividerType == CY_SYSCLK_DIV_16_BIT))
{
(void)Cy_SysClk_PeriphSetDivider(dividerType, dividerNum, CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV);
}
else
{
(void)Cy_SysClk_PeriphSetFracDivider(dividerType, dividerNum, CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV, CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV_FRAC);
}
(void)Cy_SysClk_PeriphEnableDivider(dividerType, dividerNum);
}
else
{
/* All other modes, require a CTDAC clock configured to the desired user frequency */
(void)Cy_SysClk_PeriphDisableDivider(dividerType, dividerNum);
(void)Cy_SysClk_PeriphAssignDivider(PCLK_PASS_CLOCK_CTDAC, dividerType, dividerNum);
if ((dividerType == CY_SYSCLK_DIV_8_BIT) || (dividerType == CY_SYSCLK_DIV_16_BIT))
{
(void)Cy_SysClk_PeriphSetDivider(dividerType, dividerNum, dividerIntValue);
}
else
{
(void)Cy_SysClk_PeriphSetFracDivider(dividerType, dividerNum, dividerIntValue, dividerFracValue);
}
(void)Cy_SysClk_PeriphEnableDivider(dividerType, dividerNum);
}
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetSignMode
****************************************************************************//**
*
* Sets whether to interpret the DAC value as signed or unsigned.
* In unsigned mode, the DAC value register is used without any decoding.
* In signed mode, the MSB is inverted by adding 0x800 to the DAC value.
* This converts the lowest signed number, 0x800, to the lowest unsigned
* number, 0x000.
*
* \param base
* Pointer to structure describing registers
*
* \param formatMode
* Mode can be signed or unsigned. See \ref cy_en_ctdac_format_t for values.
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetSignMode(CTDAC_Type *base, cy_en_ctdac_format_t formatMode)
{
CY_ASSERT_L3(CY_CTDAC_FORMAT(formatMode));
uint32_t ctdacCtrl;
/* Clear the CTDAC_MODE bits */
ctdacCtrl = base->CTDAC_CTRL & ~CTDAC_CTDAC_CTRL_CTDAC_MODE_Msk;
base->CTDAC_CTRL = ctdacCtrl | (uint32_t)formatMode;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetDeepSleepMode
****************************************************************************//**
*
* Sets whether to allow the DAC hardware to continue to stay powered in
* Deep Sleep mode.
*
* \param base
* Pointer to structure describing registers
*
* \param deepSleep
* Enabled or disabled. See \ref cy_en_ctdac_deep_sleep_t for values.
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetDeepSleepMode(CTDAC_Type *base, cy_en_ctdac_deep_sleep_t deepSleep)
{
CY_ASSERT_L3(CY_CTDAC_DEEPSLEEP(deepSleep));
uint32_t ctdacCtrl;
ctdacCtrl = base->CTDAC_CTRL & ~CTDAC_CTDAC_CTRL_DEEPSLEEP_ON_Msk;
base->CTDAC_CTRL = ctdacCtrl | (uint32_t)deepSleep;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetOutputMode
****************************************************************************//**
*
* Set the output mode to one of the supported options.
*
* \param base
* Pointer to structure describing registers
*
* \param outputMode
* Output drive mode. See \ref cy_en_ctdac_output_mode_t for values.
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetOutputMode(CTDAC_Type *base, cy_en_ctdac_output_mode_t outputMode)
{
CY_ASSERT_L3(CY_CTDAC_OUTPUTMODE(outputMode));
uint32_t ctdacCtrl;
/* Clear out the three affected bits */
ctdacCtrl = base->CTDAC_CTRL & ~(CTDAC_CTDAC_CTRL_OUT_EN_Msk | CTDAC_CTDAC_CTRL_DISABLED_MODE_Msk | CTDAC_CTDAC_CTRL_CTDAC_RANGE_Msk);
base->CTDAC_CTRL = ctdacCtrl | (uint32_t)outputMode;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetDeglitchMode
****************************************************************************//**
*
* Set the deglitch mode or disable deglitching completely.
*
* \param base
* Pointer to structure describing registers
*
* \param deglitchMode
* Deglitching mode selection. See \ref cy_en_ctdac_deglitch_t for values.
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetDeglitchMode(CTDAC_Type *base, cy_en_ctdac_deglitch_t deglitchMode)
{
CY_ASSERT_L3(CY_CTDAC_DEGLITCH(deglitchMode));
uint32_t ctdacCtrl;
/* Clear out DEGLITCH_CO6 and DEGLITCH_C0S bits */
ctdacCtrl = base->CTDAC_CTRL & ~(CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk | CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk);
base->CTDAC_CTRL = ctdacCtrl | (uint32_t)deglitchMode;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetDeglitchCycles
****************************************************************************//**
*
* Set the number of deglitch cycles (0 to 63) that will be used.
* To calculate the deglitch time, (DEGLITCH_CNT + 1) / PERI_CLOCK_FREQ.
* The optimal deglitch time is 700 ns.
*
* \param base
* Pointer to structure describing registers
*
* \param deglitchCycles
* Number of cycles to deglitch
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetDeglitchCycles(CTDAC_Type *base, uint32_t deglitchCycles)
{
CY_ASSERT_L2(CY_CTDAC_DEGLITCHCYCLES(deglitchCycles));
uint32_t ctdacCtrl;
ctdacCtrl = (base->CTDAC_CTRL) & ~CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Msk;
base->CTDAC_CTRL = ctdacCtrl | ((deglitchCycles << CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Pos) & CTDAC_CTDAC_CTRL_DEGLITCH_CNT_Msk);
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetRef
****************************************************************************//**
*
* Set the CTDAC reference source to Vdda or an external reference.
* The external reference must come from Opamp1 of the CTB.
*
* \param base
* Pointer to structure describing registers
*
* \param refSource
* The reference source. See \ref cy_en_ctdac_ref_source_t for values.
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetRef(CTDAC_Type *base, cy_en_ctdac_ref_source_t refSource)
{
CY_ASSERT_L3(CY_CTDAC_REFSOURCE(refSource));
switch(refSource)
{
case CY_CTDAC_REFSOURCE_VDDA:
/* Close the CVD switch to use Vdda as the reference source */
base->CTDAC_SW |= CTDAC_CTDAC_SW_CTDD_CVD_Msk;
break;
case CY_CTDAC_REFSOURCE_EXTERNAL:
default:
base->CTDAC_SW_CLEAR = CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk;
break;
}
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetAnalogSwitch
****************************************************************************//**
*
* Provides firmware control of the CTDAC switches. Each call to this function
* can open a set of switches or close a set of switches.
*
* This is an advanced function. The switches will be managed by the reference
* source and output mode selections when initializing the hardware.
*
* \param base
* Pointer to structure describing registers
*
* \param switchMask
* The mask of the switches to either open or close.
* The switches can be found in the \ref cy_en_ctdac_switches_t enum.
*
* For example, to close both CVD and CO6 switches:
* switchMask = CY_CTDAC_SWITCH_CVD_MASK | CY_CTDAC_SWITCH_CO6_MASK;
*
* \param state
* Open or close the switches, see enum \ref cy_en_ctdac_switch_state_t.
*
* \return None
*
*******************************************************************************/
void Cy_CTDAC_SetAnalogSwitch(CTDAC_Type *base, uint32_t switchMask, cy_en_ctdac_switch_state_t state)
{
CY_ASSERT_L2(CY_CTDAC_SWITCHMASK(switchMask));
CY_ASSERT_L3(CY_CTDAC_SWITCHSTATE(state));
switch(state)
{
case CY_CTDAC_SWITCH_CLOSE:
base->CTDAC_SW |= switchMask;
break;
case CY_CTDAC_SWITCH_OPEN:
default:
/* Unlike the close case, do not OR the register. Set 1 to clear.*/
base->CTDAC_SW_CLEAR = switchMask;
break;
}
}
/*******************************************************************************
* Function Name: Cy_CTDAC_DeepSleepCallback
****************************************************************************//**
*
* Callback to prepare the CTDAC before entering and after exiting Deep Sleep
* mode. If deglitching is used, it is disabled before entering Deep Sleep
* to ensure the deglitch switches are closed. This is needed only
* if the CTDAC will be enabled in DeepSleep. Upon wakeup, deglitching will
* be re-enabled if it was previously used.
*
* \param callbackParams
* Pointer to structure of type \ref cy_stc_syspm_callback_params_t
*
* \return cy_en_syspm_status_t
* See \ref cy_en_syspm_status_t
*
*******************************************************************************/
cy_en_syspm_status_t Cy_CTDAC_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
/** Static variable preserved between function calls.
* Tracks the state of the deglitch mode before sleep so that it can be re-enabled after wakeup */
static uint32_t deglitchModeBeforeSleep;
cy_en_syspm_status_t returnValue = CY_SYSPM_SUCCESS;
CTDAC_Type *ctdacBase = (CTDAC_Type *)callbackParams->base;
if (CY_SYSPM_BEFORE_TRANSITION == callbackParams->mode)
{ /* Actions that should be done before entering the Deep Sleep mode */
/* Store the state of the deglitch switches before turning deglitch off */
deglitchModeBeforeSleep = ctdacBase->CTDAC_CTRL & (CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk | CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk);
/* Turn deglitch off before entering Deep Sleep */
ctdacBase->CTDAC_CTRL &= ~(CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk | CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk);
}
else if (CY_SYSPM_AFTER_TRANSITION == callbackParams->mode)
{ /* Actions that should be done after exiting the Deep Sleep mode */
/* Re-enable the deglitch mode that was configured before Deep Sleep entry */
ctdacBase->CTDAC_CTRL |= deglitchModeBeforeSleep;
}
else
{ /* Does nothing in other modes */
}
return returnValue;
}
#if defined(__cplusplus)
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,891 @@
/***************************************************************************//**
* \file cy_ctdac.h
* \version 1.0
*
* Header file for the CTDAC driver
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_ctdac Continuous Time Digital to Analog Converter (CTDAC)
* \{
* The CTDAC driver provides APIs to configure the 12-bit Continuous-Time DAC.
* The CTDAC generates a 12-bit DAC output voltage from the reference.
* The DAC reference can come from VDDA or from any signal buffered through Opamp0
* of the CTB. This can be an external signal through a GPIO or from the internal
* AREF. The CTDAC is closely integrated with the CTB block,
* which provides easy buffering of the DAC output voltage,
* buffered input reference voltage, and sample and hold for the DAC output.
* The CTDAC control interface provides control of the DAC output through CPU or DMA.
* This includes a double-buffered DAC voltage control register, clock input for programmable
* update rate, interrupt on DAC buffer empty, and trigger to DMA.
*
* \image html ctdac_block_diagram.png
* \image latex ctdac_block_diagram.png
*
* <b> Features </b>
*
* - 12-bit continuous time output
* - 2 us settling time for a 25 pF load
* - Can be enabled in Deep Sleep power mode
* - Selectable voltage reference:
* - VDDA
* - Internal analog reference buffered through Opamp1 of CTB
* - External reference buffered through Opamp1 of CTB
* - Selectable output paths:
* - Direct DAC output to a pin
* - Buffered DAC output through Opamp0 of CTB
* - Sample and hold output path through Opamp0 of CTB
* - Selectable input modes:
* - Unsigned 12-bit mode
* - Virtual signed 12-bit mode
* - Configurable update rate using clock or strobe signal
* - Double buffered DAC voltage control register
* - Interrupt and DMA trigger on DAC buffer empty
* - Configurable as PGA along with Opamp1 of the CTB
*
* The CTDAC has two switches, CO6 for configuring the output path and
* CVD for the reference source.
*
* \image html ctdac_switches.png
* \image latex ctdac_switches.png
*
* \section group_ctdac_init Initialization
*
* Configure the CTDAC hardware block by calling \ref Cy_CTDAC_Init.
* The base address of the CTDAC hardware can be found in the device-specific header file.
* If the buffers in the CTB are used for the reference source or the output,
* initialize the CTB hardware block. After both blocks are initialized,
* enable the CTB block before enabling the CTDAC block.
*
* The driver also provides a \ref Cy_CTDAC_FastInit function for fast and easy initialization of the CTDAC.
* There are four configurations that cover the four combinations of the reference and output buffers.
*
* - \ref Cy_CTDAC_Fast_VddaRef_UnbufferedOut
* - \ref Cy_CTDAC_Fast_VddaRef_BufferedOut
* - \ref Cy_CTDAC_Fast_OA1Ref_UnbufferedOut
* - \ref Cy_CTDAC_Fast_OA1Ref_BufferedOut
*
* \section group_ctdac_updatemode Update Modes
* The CTDAC contains two registers:
* -# CTDAC_VAL
*
* For direct firmware writes to update the current DAC value immediately.
* This register is written with \ref Cy_CTDAC_SetValue.
* -# CTDAC_VAL_NXT
*
* For buffered writes that can be configured to update the DAC at a
* selected periodic rate or with a strobe trigger.
* This register is written with \ref Cy_CTDAC_SetValueBuffered.
*
* The update mode is
* selected during initialization with the \ref cy_stc_ctdac_config_t.updateMode.
* Four of these modes require a dedicated clock resource and the driver
* can configure the clock during initialization (see \ref cy_stc_ctdac_config_t).
*
* Three of these modes use a strobe signal through the digital signal interface (DSI).
* This allows control of the buffered update timing from an external source, for example, by another
* chip peripheral or from an off-chip source.
*
* <b>Direct write</b>
*
* In this mode, this user writes directly into the CTDAC_VAL register
* using \ref Cy_CTDAC_SetValue. The action of writing to this register
* will update the DAC output. This mode does not generate an interrupt
* or trigger signal.
* In this mode, a clock must not be configured. Additionally, calling \ref
* Cy_CTDAC_SetValueBuffered does not update the DAC output.
*
* \image html ctdac_update_mode_direct_write.png
* \image latex ctdac_update_mode_direct_write.png
*
* <b>Buffered write</b>
*
* In this mode, the user writes to the CTDAC_VAL_NXT register using
* \ref Cy_CTDAC_SetValueBuffered. The rising edge of the clock
* will update the DAC output and generate the interrupt and trigger signals.
*
* Whenever data is transferred from the CTDAC_VAL_NXT register,
* an interrupt is asserted the same time as the trigger. But while
* the trigger is automatically cleared after two Peri Clock cycles, the
* user must clear the interrupt with \ref Cy_CTDAC_ClearInterrupt.
*
* \image html ctdac_update_mode_buffered_write.png
* \image latex ctdac_update_mode_buffered_write.png
*
* <b>Strobe edge sync</b>
*
* In this mode, the user writes to the CTDAC_VAL_NXT register using
* \ref Cy_CTDAC_SetValueBuffered.
* Each rising edge of the DSI strobe input enables
* one subsequent update from the next rising edge of the clock. The DSI
* input must remain high for two Peri Clock cycles and go low for
* another two Peri Clock cycles to allow for the next update.
* This restricts the DSI strobe input frequency to the PeriClk frequency divided by four.
*
* \image html ctdac_update_mode_strobe_edge_sync.png
* \image latex ctdac_update_mode_strobe_edge_sync.png
*
* <b>Strobe edge immediate</b>
*
* In this mode, the user writes to the CTDAC_VAL_NXT register using
* \ref Cy_CTDAC_SetValueBuffered.
* The clock resource is used but set to a logic high.
* Therefore, each rising edge of the DSI strobe input immediately
* updates the DAC output.
*
* \image html ctdac_update_mode_strobe_edge_immediate.png
* \image latex ctdac_update_mode_strobe_edge_immediate.png
*
* <b>Strobe level</b>
*
* In this mode, the user writes to the CTDAC_VAL_NXT register using
* \ref Cy_CTDAC_SetValueBuffered.
* The DSI strobe input acts as a hardware enable signal.
* While the DSI strobe input is high, the mode behaves
* like the Buffered write mode. When the DSI strobe input is low,
* updates are disabled.
*
* \image html ctdac_update_mode_strobe_level.png
* \image latex ctdac_update_mode_strobe_level.png
*
* \section group_ctdac_trigger DMA Trigger
* When data is transferred from the CTDAC_VAL_NXT to the CTDAC_VAL register
* an interrupt and an output trigger signal are generated.
* The trigger signal can be routed to DMA using the \ref group_trigmux.
* When making the required \ref Cy_TrigMux_Connect calls, use the pre-defined enums, TRIG14_IN_PASS_TR_CTDAC_EMPTY
* and TRIGGER_TYPE_PASS_TR_CTDAC_EMPTY. For example,
*
* \code
* (void)Cy_TrigMux_Connect(TRIG14_IN_PASS_TR_CTDAC_EMPTY, TRIG14_OUT_TR_GROUP0_INPUT50, CY_TR_MUX_TR_INV_DISABLE, TRIGGER_TYPE_PASS_TR_CTDAC_EMPTY);
* (void)Cy_TrigMux_Connect(TRIG0_IN_TR_GROUP14_OUTPUT7, TRIG0_OUT_CPUSS_DW0_TR_IN1, CY_TR_MUX_TR_INV_DISABLE, TRIGGER_TYPE_TR_GROUP_OUTPUT__LEVEL);
* \endcode
*
* \section group_ctdac_code_example Complete Code Example
*
* The following example code demonstrates how to generate a continuous
* sine wave using the CTDAC. The CTDAC uses both Opamps of the CTB
* to buffer the analog reference and to buffer the output to an external Pin 2.
*
* \image html ctdac_code_example.png
* \image latex ctdac_code_example.png
*
* \code
* #include "ctdac/cy_ctdac.h"
* #include "ctb/cy_ctb.h"
* #include "sysanalog/cy_sysanalog.h"
* #include "sysint/cy_sysint.h"
* \endcode
*
* \snippet ctdac_sut_01.cydsn/main_cm0p.c CTDAC_CODE_EXAMPLE
*
* \section group_ctdac_more_information More Information
*
* Refer to the technical reference manual (TRM) and the device datasheet.
*
* \section group_ctdac_MISRA MISRA-C Compliance]
*
* This driver has the following specific deviations:
*
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>11.4</td>
* <td>Advisory</td>
* <td>A cast should not be performed between a pointer to object type and a different pointer to object type.</td>
* <td>The cy_syspm driver defines the pointer to void in the \ref cy_stc_syspm_callback_params_t.base field.
* This CTDAC driver implements a Deep Sleep callback conforming to the cy_syspm driver requirements.
* When the callback is called, the base is cast to a pointer to CTDAC_Type.
* </td>
* </tr>
* </table>
*
* \section group_ctdac_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_ctdac_macros Macros
* \defgroup group_ctdac_functions Functions
* \{
* \defgroup group_ctdac_functions_switches Switch Control Functions
* \defgroup group_ctdac_functions_interrupts Interrupt Functions
* \defgroup group_ctdac_functions_syspm_callback SysPm Deep Sleep Callback
* \}
* \defgroup group_ctdac_globals Global Variables
* \defgroup group_ctdac_data_structures Data structures
* \defgroup group_ctdac_enums Enumerated Types
*/
#if !defined(CY_CTDAC_H)
#define CY_CTDAC_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "cy_device_headers.h"
#include "syspm/cy_syspm.h"
#include "syslib/cy_syslib.h"
#include "sysclk/cy_sysclk.h"
#ifndef CY_IP_MXS40PASS_CTDAC
#error "The CTDAC driver is not supported on this device"
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_ctdac_macros
* \{
*/
/** Driver major version */
#define CY_CTDAC_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_CTDAC_DRV_VERSION_MINOR 0
/** CTDAC driver identifier */
#define CY_CTDAC_ID CY_PDL_DRV_ID(0x19u)
/** \cond INTERNAL */
#define CY_CTDAC_DEINIT (0uL) /**< De-init value for CTDAC registers */
#define CY_CTDAC_DEINT_CTDAC_SW (CTDAC_CTDAC_SW_CLEAR_CTDD_CVD_Msk | CTDAC_CTDAC_SW_CLEAR_CTDO_CO6_Msk) /**< Mask for de-initializing the CTDAC switch control register */
#define CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV (0uL) /**< Clock divider value for the Strobe Edge Immediate update mode */
#define CY_CTDAC_STROBE_EDGE_IMMEDIATE_DIV_FRAC (0uL) /**< Clock fractional divider value for the Strobe Edge Immediate update mode */
#define CY_CTDAC_FAST_CLKCFG_TYPE CY_SYSCLK_DIV_8_BIT /**< Clock divider type for quick clock setup */
#define CY_CTDAC_FAST_CLKCFG_NUM (0uL) /**< Clock divider number for quick clock setup */
#define CY_CTDAC_FAST_CLKCFG_DIV (99uL) /**< Clock divider integer value for quick clock setup. Divides PERI clock by 100. */
#define CY_CTDAC_UNSIGNED_MID_CODE_VALUE (0x800uL) /**< Middle code value for unsigned values */
#define CY_CTDAC_UNSIGNED_MAX_CODE_VALUE (0xFFFuL) /**< Maximum code value for unsigned values */
#define CY_CTDAC_DEGLITCH_CYCLES_MAX (63uL)
/**< Macros for conditions used by CY_ASSERT calls */
#define CY_CTDAC_REFSOURCE(source) (((source) == CY_CTDAC_REFSOURCE_EXTERNAL) || ((source) == CY_CTDAC_REFSOURCE_VDDA))
#define CY_CTDAC_FORMAT(mode) (((mode) == CY_CTDAC_FORMAT_UNSIGNED) || ((mode) == CY_CTDAC_FORMAT_SIGNED))
#define CY_CTDAC_UPDATE(mode) ((mode) <= CY_CTDAC_UPDATE_STROBE_LEVEL)
#define CY_CTDAC_DEGLITCH(mode) (((mode) == CY_CTDAC_DEGLITCHMODE_NONE) \
|| ((mode) == CY_CTDAC_DEGLITCHMODE_UNBUFFERED) \
|| ((mode) == CY_CTDAC_DEGLITCHMODE_BUFFERED) \
|| ((mode) == CY_CTDAC_DEGLITCHMODE_BOTH))
#define CY_CTDAC_OUTPUTMODE(mode) (((mode) == CY_CTDAC_OUTPUT_HIGHZ) \
|| ((mode) == CY_CTDAC_OUTPUT_VALUE) \
|| ((mode) == CY_CTDAC_OUTPUT_VALUE_PLUS1) \
|| ((mode) == CY_CTDAC_OUTPUT_VSSA) \
|| ((mode) == CY_CTDAC_OUTPUT_VREF))
#define CY_CTDAC_OUTPUTBUFFER(buffer) (((buffer) == CY_CTDAC_OUTPUT_UNBUFFERED) || ((buffer) == CY_CTDAC_OUTPUT_BUFFERED))
#define CY_CTDAC_DEEPSLEEP(deepSleep) (((deepSleep) == CY_CTDAC_DEEPSLEEP_DISABLE) || ((deepSleep) == CY_CTDAC_DEEPSLEEP_ENABLE))
#define CY_CTDAC_DEGLITCHCYCLES(cycles) ((cycles) <= CY_CTDAC_DEGLITCH_CYCLES_MAX)
#define CY_CTDAC_SWITCHMASK(mask) ((mask) <= (uint32_t) (CY_CTDAC_SWITCH_CVD_MASK | CY_CTDAC_SWITCH_CO6_MASK))
#define CY_CTDAC_SWITCHSTATE(state) (((state) == CY_CTDAC_SWITCH_OPEN) || ((state) == CY_CTDAC_SWITCH_CLOSE))
#define CY_CTDAC_INTRMASK(mask) (((mask) == 0uL) || ((mask) == 1uL))
/** \endcond */
/** \} group_ctdac_macros */
/***************************************
* Enumerated Types
***************************************/
/**
* \addtogroup group_ctdac_enums
* \{
*/
/**
* Configure the mode for how the DAC value is updated.
* All the modes require a CTDAC clock except for CY_CTDAC_UPDATE_DIRECT_WRITE.
*/
typedef enum {
CY_CTDAC_UPDATE_DIRECT_WRITE = 0uL, /**< DAC value is updated with a direct write by calling to \ref Cy_CTDAC_SetValue */
CY_CTDAC_UPDATE_BUFFERED_WRITE = 1uL, /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on the next CTDAC clock edge */
CY_CTDAC_UPDATE_STROBE_EDGE_SYNC = 2uL, /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on the next CTDAC clock edge after a rising edge of the strobe */
CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE = 3uL, /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on the rising edge of the strobe input */
CY_CTDAC_UPDATE_STROBE_LEVEL = 4uL /**< DAC value stored with \ref Cy_CTDAC_SetValueBuffered is updated on every CTDAC clock edge while the strobe line is high */
}cy_en_ctdac_update_t;
/**
* Configure the format in which the DAC value register is decoded.
*/
typedef enum {
CY_CTDAC_FORMAT_UNSIGNED = 0uL, /**< Unsigned 12-bit DAC. No value decoding */
CY_CTDAC_FORMAT_SIGNED = 1uL << CTDAC_CTDAC_CTRL_CTDAC_MODE_Pos /**< Virtual signed. Add 0x800 to the 12-bit DAC value */
}cy_en_ctdac_format_t;
/**
* Enable or disable the CTDAC hardware during Deep Sleep.
*/
typedef enum {
CY_CTDAC_DEEPSLEEP_DISABLE = 0uL, /**< DAC is disabled during Deep Sleep power mode */
CY_CTDAC_DEEPSLEEP_ENABLE = CTDAC_CTDAC_CTRL_DEEPSLEEP_ON_Msk /**< DAC remains enabled during Deep Sleep power mode */
}cy_en_ctdac_deep_sleep_t;
/**
* Configure the output state of the CTDAC.
*/
typedef enum {
CY_CTDAC_OUTPUT_HIGHZ = 0uL, /**< DAC output is tri-state */
CY_CTDAC_OUTPUT_VALUE = CTDAC_CTDAC_CTRL_OUT_EN_Msk, /**< DAC Output is enabled and drives the programmed value */
CY_CTDAC_OUTPUT_VALUE_PLUS1 = CTDAC_CTDAC_CTRL_OUT_EN_Msk \
| CTDAC_CTDAC_CTRL_CTDAC_RANGE_Msk, /**< DAC Output enabled and drives the programmed value plus 1 */
CY_CTDAC_OUTPUT_VSSA = CTDAC_CTDAC_CTRL_DISABLED_MODE_Msk, /**< Output is pulled to Vssa through a 1.1 MOhm (typ) resistor */
CY_CTDAC_OUTPUT_VREF = CTDAC_CTDAC_CTRL_DISABLED_MODE_Msk \
| CTDAC_CTDAC_CTRL_CTDAC_RANGE_Msk /**< Output is pulled to Vref through a 1.1 MOhm (typ) resistor */
}cy_en_ctdac_output_mode_t;
/**
* The CTDAC provides an option to deglitch the output value every time it is updated.
* This prevents small glitches in the DAC output during an update to propagate to
* the pin or Opamp input. When deglitch is enabled, a switch on the output path
* is forced open for a configurable number of Peri Clock cycles. To calculate the deglitch
* time, (DEGLITCH_CNT + 1) / PERI_CLOCK_FREQ.
*
* There are two switches used for deglitching.
* - Switch COS in the CTB between the DAC output and the Opamp0 input
* - Switch CO6 in the CTDAC between the DAC output and external pin
*
* Match the deglitch path with the output buffer selection.
* If the output is buffered through the CTB, select CY_CTDAC_DEGLITCHMODE_BUFFERED.
* If the output is unbuffered to a direct pin, select CY_CTDAC_DEGLITCHMODE_UNBUFFERED.
*/
typedef enum {
CY_CTDAC_DEGLITCHMODE_NONE = 0uL, /**< Disable deglitch */
CY_CTDAC_DEGLITCHMODE_UNBUFFERED = CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk, /**< Deglitch through the CO6 switch */
CY_CTDAC_DEGLITCHMODE_BUFFERED = CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk, /**< Deglitch through the CTB COS switch */
CY_CTDAC_DEGLITCHMODE_BOTH = CTDAC_CTDAC_CTRL_DEGLITCH_COS_Msk \
| CTDAC_CTDAC_CTRL_DEGLITCH_CO6_Msk /**< Deglitch through both CO6 and CTB COS switches */
}cy_en_ctdac_deglitch_t;
/**
* Configure the reference source for the CTDAC
*
* The CVD switch is closed when Vdda is the reference source.
*/
typedef enum {
CY_CTDAC_REFSOURCE_EXTERNAL = 0uL, /**< Use an external source as the reference. CVD switch is open. */
CY_CTDAC_REFSOURCE_VDDA = 1uL /**< Use Vdda as the reference. CVD switch is closed. */
}cy_en_ctdac_ref_source_t;
/** Configure the output to be buffered or unbuffered
*
* The CO6 switch is closed when the output is unbuffered to Pin 6 of the CTDAC port.
* See the device datasheet for the CTDAC port.
*/
typedef enum {
CY_CTDAC_OUTPUT_BUFFERED = 0uL, /**< Buffer the output through the CTB OA0 */
CY_CTDAC_OUTPUT_UNBUFFERED = 1uL /**< Send output to a direct pin */
}cy_en_ctdac_output_buffer_t;
/** Switch state, either open or closed, to be used in \ref Cy_CTDAC_SetAnalogSwitch. */
typedef enum
{
CY_CTDAC_SWITCH_OPEN = 0uL, /**< Open the switch */
CY_CTDAC_SWITCH_CLOSE = 1uL /**< Close the switch */
}cy_en_ctdac_switch_state_t;
/** Switch mask to be used in \ref Cy_CTDAC_SetAnalogSwitch */
typedef enum
{
CY_CTDAC_SWITCH_CVD_MASK = CTDAC_CTDAC_SW_CTDD_CVD_Msk, /**< Switch for the reference source, Vdda or external */
CY_CTDAC_SWITCH_CO6_MASK = CTDAC_CTDAC_SW_CTDO_CO6_Msk /**< Switch for the output, buffered or direct */
}cy_en_ctdac_switches_t;
/** Return states for \ref Cy_CTDAC_Init, \ref Cy_CTDAC_DeInit, and \ref Cy_CTDAC_FastInit */
typedef enum {
CY_CTDAC_SUCCESS = 0x00uL, /**< Initialization completed successfully */
CY_CTDAC_BAD_PARAM = CY_CTDAC_ID | CY_PDL_STATUS_ERROR | 0x01uL /**< Input pointers were NULL and Initialization could not be completed */
}cy_en_ctdac_status_t;
/** \} group_ctdac_enums */
/***************************************
* Configuration Structures
***************************************/
/**
* \addtogroup group_ctdac_data_structures
* \{
*/
/** Configuration structure to set up the entire CTDAC block to be used with \ref Cy_CTDAC_Init
*/
typedef struct
{
cy_en_ctdac_ref_source_t refSource; /**< Reference source: Vdda or externally through Opamp1 of CTB */
cy_en_ctdac_format_t formatMode; /**< Format of DAC value: signed or unsigned */
cy_en_ctdac_update_t updateMode; /**< Update mode: direct or buffered writes or hardware, edge or level */
cy_en_ctdac_deglitch_t deglitchMode; /**< Deglitch mode: disabled, buffered, unbuffered, or both */
cy_en_ctdac_output_mode_t outputMode; /**< Output mode: enabled (value or value + 1), high-z, Vssa, or Vdda */
cy_en_ctdac_output_buffer_t outputBuffer; /**< Output path: Buffered through Opamp0 of CTB or connected directly to Pin 6 */
cy_en_ctdac_deep_sleep_t deepSleep; /**< Enable or disable the CTDAC during Deep Sleep */
uint32_t deglitchCycles; /**< Number of deglitch cycles from 0 to 63 */
int32_t value; /**< Current DAC value */
int32_t nextValue; /**< Next DAC value for double buffering */
bool enableInterrupt; /**< If true, enable interrupt when next value register is transferred to value register */
bool enable; /**< Enable or disable hardware after initialization */
/* Configuring the clock */
bool configClock; /**< Configure or ignore clock information */
cy_en_divider_types_t dividerType; /**< Specifies which type of divider to use. Can be integer or fractional divider. Not used if updateMode is CY_CTDAC_UPDATE_DIRECT_WRITE */
uint32_t dividerNum; /**< Specifies which divider of the selected type to configure. Not used if updateMode is CY_CTDAC_UPDATE_DIRECT_WRITE */
uint32_t dividerIntValue; /**< The integer divider value. The divider value causes integer division of (divider value + 1). Not used if updateMode is CY_CTDAC_UPDATE_DIRECT_WRITE or CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE */
uint32_t dividerFracValue; /**< The fractional divider value if using a fractional clock. Not used if updateMode is CY_CTDAC_UPDATE_DIRECT_WRITE or CY_CTDAC_UPDATE_STROBE_EDGE_IMMEDIATE */
}cy_stc_ctdac_config_t;
/** Configuration structure to quickly set up the CTDAC to be used with \ref Cy_CTDAC_FastInit
* This structure provides a selection for the CTDAC reference source and output path.
*
* The other configuration options are set to:
* - .formatMode = CY_CTDAC_FORMAT_UNSIGNED
* - .updateMode = CY_CTDAC_UPDATE_BUFFERED_WRITE
* - .deglitchMode = CY_CTDAC_DEGLITCHMODE_NONE
* - .outputMode = CY_CTDAC_OUTPUT_VALUE
* - .deepSleep = CY_CTDAC_DEEPSLEEP_DISABLE
* - .deglitchCycles = CY_CTDAC_DEINIT
* - .value = CY_CTDAC_UNSIGNED_MID_CODE_VALUE
* - .nextValue = CY_CTDAC_UNSIGNED_MID_CODE_VALUE
* - .enableInterrupt = true
* - .configClock = true
* - .dividerType = CY_CTDAC_FAST_CLKCFG_TYPE
* - .dividerNum = CY_CTDAC_FAST_CLKCFG_NUM
* - .dividerInitValue = CY_CTDAC_FAST_CLKCFG_DIV
* - .dividerFracValue = CY_CTDAC_DEINIT
*/
typedef struct
{
cy_en_ctdac_ref_source_t refSource; /**< Reference source: Vdda or externally through Opamp1 of CTB */
cy_en_ctdac_output_buffer_t outputBuffer; /**< Output path: Buffered through Opamp0 of CTB or connected directly to Pin 6 */
}cy_stc_ctdac_fast_config_t;
/** \} group_ctdac_data_structures */
/** \addtogroup group_ctdac_globals
* \{
*/
/***************************************
* Global Variables
***************************************/
/** Configure CTDAC to use Vdda reference and output unbuffered. See \ref Cy_CTDAC_FastInit. */
extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_UnbufferedOut;
/** Configure CTDAC to use Vdda reference and output buffered through Opamp0 of CTB. See \ref Cy_CTDAC_FastInit.
*
* To quickly configure Opamp0, call with \ref Cy_CTB_FastInit
* with \ref Cy_CTB_Fast_Opamp0_Vdac_Out or \ref Cy_CTB_Fast_Opamp0_Vdac_Out_SH.
*/
extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_VddaRef_BufferedOut;
/** Configure CTDAC to use a buffered reference from Opamp1 of CTB
* and output unbuffered. See \ref Cy_CTDAC_FastInit.
*
* To use the reference from the Analog Reference (AREF),
* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref.
*
* To use an external reference from a GPIO,
* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5
* for Pin 5 on the CTB port.
*/
extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_UnbufferedOut;
/** Configure CTDAC to use a buffered reference from Opamp1 of CTB
* and output buffered through Opamp0 of CTB. See \ref Cy_CTDAC_FastInit.
*
* To quickly configure Opamp0, call with \ref Cy_CTB_FastInit
* with \ref Cy_CTB_Fast_Opamp0_Vdac_Out or \ref Cy_CTB_Fast_Opamp0_Vdac_Out_SH.
*
* To use the reference from the Analog Reference (AREF),
* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Aref.
*
* To use an external reference from a GPIO,
* call \ref Cy_CTB_FastInit with \ref Cy_CTB_Fast_Opamp1_Vdac_Ref_Pin5
* for Pins 5 on the CTB port.
*/
extern const cy_stc_ctdac_fast_config_t Cy_CTDAC_Fast_OA1Ref_BufferedOut;
/** \} group_ctdac_globals */
/***************************************
* Function Prototypes
***************************************/
/**
* \addtogroup group_ctdac_functions
* \{
*/
cy_en_ctdac_status_t Cy_CTDAC_Init(CTDAC_Type *base, const cy_stc_ctdac_config_t *config);
cy_en_ctdac_status_t Cy_CTDAC_DeInit(CTDAC_Type *base, bool deInitRouting);
cy_en_ctdac_status_t Cy_CTDAC_FastInit(CTDAC_Type *base, const cy_stc_ctdac_fast_config_t *config);
__STATIC_INLINE void Cy_CTDAC_Enable(CTDAC_Type *base);
__STATIC_INLINE void Cy_CTDAC_Disable(CTDAC_Type *base);
__STATIC_INLINE void Cy_CTDAC_SetValue(CTDAC_Type *base, int32_t value);
__STATIC_INLINE void Cy_CTDAC_SetValueBuffered(CTDAC_Type *base, int32_t value);
void Cy_CTDAC_SetSignMode(CTDAC_Type *base, cy_en_ctdac_format_t formatMode);
void Cy_CTDAC_SetDeepSleepMode(CTDAC_Type *base, cy_en_ctdac_deep_sleep_t deepSleep);
void Cy_CTDAC_SetOutputMode(CTDAC_Type *base, cy_en_ctdac_output_mode_t outputMode);
void Cy_CTDAC_SetDeglitchMode(CTDAC_Type *base, cy_en_ctdac_deglitch_t deglitchMode);
void Cy_CTDAC_SetDeglitchCycles(CTDAC_Type *base, uint32_t deglitchCycles);
void Cy_CTDAC_SetRef(CTDAC_Type *base, cy_en_ctdac_ref_source_t refSource);
/** \addtogroup group_ctdac_functions_switches
*
* This set of functions is for controlling the two CTDAC analog switches, CVD, and CO6.
* These are advanced functions. The switches will be managed by the reference
* source and output mode selections when initializing the hardware.
* \{
*/
void Cy_CTDAC_SetAnalogSwitch(CTDAC_Type *base, uint32_t switchMask, cy_en_ctdac_switch_state_t state);
__STATIC_INLINE uint32_t Cy_CTDAC_GetAnalogSwitch(const CTDAC_Type *base);
__STATIC_INLINE void Cy_CTDAC_SetSwitchCO6(CTDAC_Type *base, cy_en_ctdac_switch_state_t state);
__STATIC_INLINE void Cy_CTDAC_OpenAllSwitches(CTDAC_Type *base);
/** \} */
/** \addtogroup group_ctdac_functions_interrupts
* This set of functions is related to the VDAC_EMPTY interrupt
* \{
*/
__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatus(const CTDAC_Type *base);
__STATIC_INLINE void Cy_CTDAC_ClearInterrupt(CTDAC_Type *base);
__STATIC_INLINE void Cy_CTDAC_SetSwInterrupt(CTDAC_Type *base);
__STATIC_INLINE void Cy_CTDAC_SetInterruptMask(CTDAC_Type *base, uint32_t mask);
__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptMask(const CTDAC_Type *base);
__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatusMasked(const CTDAC_Type *base);
/** \} */
/** \addtogroup group_ctdac_functions_syspm_callback
* This driver supports one SysPm callback for Deep Sleep transition.
* \{
*/
cy_en_syspm_status_t Cy_CTDAC_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams);
/** \} */
/*******************************************************************************
* Function Name: Cy_CTDAC_Enable
****************************************************************************//**
*
* Powers up the CTDAC hardware block
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_Enable(CTDAC_Type *base)
{
base->CTDAC_CTRL |= CTDAC_CTDAC_CTRL_ENABLED_Msk;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_Disable
****************************************************************************//**
*
* Turn off the hardware block.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_Disable(CTDAC_Type *base)
{
base->CTDAC_CTRL &= ~CTDAC_CTDAC_CTRL_ENABLED_Msk;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetValue
****************************************************************************//**
*
* Set the CTDAC_VAL register (DAC hardware is
* updated on the next Peri clock cycle). Only the least significant 12 bits
* have an effect. Sign extension of negative values is unnecessary and is
* ignored by the hardware. The way in which the CTDAC interprets the 12-bit
* data is controlled by \ref Cy_CTDAC_SetSignMode.
*
* \param base
* Pointer to structure describing registers
*
* \param value
* Value to write into the CTDAC_VAL register
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_SetValue(CTDAC_Type *base, int32_t value)
{
base->CTDAC_VAL = (((uint32_t)value) << CTDAC_CTDAC_VAL_VALUE_Pos) & CTDAC_CTDAC_VAL_VALUE_Msk;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetValueBuffered
****************************************************************************//**
*
* Set the CTDAC_VAL_NEXT register. The value is transferred
* to the CTDAC_VAL register on the next edge of the CTDAC clock.
* Only the least significant 12 bits
* have an effect. Sign extension of negative values is unnecessary and is
* ignored by the hardware. The way in which the CTDAC interprets the 12-bit
* data is controlled by \ref Cy_CTDAC_SetSignMode.
*
* \param base
* Pointer to structure describing registers
*
* \param value
* Value to write into the CTDAC_VAL_NEXT register
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_SetValueBuffered(CTDAC_Type *base, int32_t value){
base->CTDAC_VAL_NXT = (((uint32_t)value) << CTDAC_CTDAC_VAL_NXT_VALUE_Pos) & CTDAC_CTDAC_VAL_NXT_VALUE_Msk;
}
/**
* \addtogroup group_ctdac_functions_switches
* \{
*/
/*******************************************************************************
* Function Name: Cy_CTDAC_GetAnalogSwitch
****************************************************************************//**
*
* Gets the state (open or close) of CTDAC switches as a uint32_t value.
*
* This is an advanced function. The switches will be managed by the reference
* source and output mode selections when initializing the hardware.
* \param base
* Pointer to structure describing registers
*
* \return uint32_t
* Compare the value to the switch masks found in \ref cy_en_ctdac_switches_t.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_CTDAC_GetAnalogSwitch(const CTDAC_Type *base)
{
return base->CTDAC_SW;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetSwitchCO6
****************************************************************************//**
*
* Open or close switch CO6 that controls whether the output gets routed
* directly to a pin or through Opamp0 of the CTB.
*
* Note that this switch will temporarily
* be opened for deglitching if DEGLITCHMODE_UNBUFFERED or DEGLITCHMODE_BOTH
* is set in \ref Cy_CTDAC_SetDeglitchMode.
*
* This is an advanced function. The switches will be managed by the reference
* source and output mode selections when initializing the hardware.
*
* \param base
* Pointer to structure describing registers
*
* \param state
* State of the switch, open or close.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_SetSwitchCO6(CTDAC_Type *base, cy_en_ctdac_switch_state_t state)
{
Cy_CTDAC_SetAnalogSwitch(base, (uint32_t) CY_CTDAC_SWITCH_CO6_MASK, state);
}
/*******************************************************************************
* Function Name: Cy_CTDAC_OpenAllSwitches
****************************************************************************//**
*
* Open all switches.
*
* This is an advanced function. The switches will be managed by the reference
* source and output mode selections when initializing the hardware.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_OpenAllSwitches(CTDAC_Type *base)
{
base->CTDAC_SW_CLEAR = CY_CTDAC_DEINT_CTDAC_SW;
}
/** \} */
/**
* \addtogroup group_ctdac_functions_interrupts
* \{
*/
/*******************************************************************************
* Function Name: Cy_CTDAC_GetInterruptStatus
****************************************************************************//**
*
* Returns the interrupt status which gets set by the hardware
* when the CTDAC_VAL_NXT register value is transferred to the CTDAC_VAL register.
* Once set, the CTDAC_VAL_NXT register is ready to accept a new value.
*
* Interrupts are available in all update modes except \ref CY_CTDAC_UPDATE_DIRECT_WRITE.
*
* \param base
* Pointer to structure describing registers
*
* \return
* 0 = Value not moved from CTDAC_VAL_NXT to CTDAC_VAL
* 1 = Value moved from CTDAC_VAL_NXT to CTDAC_VAL
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatus(const CTDAC_Type *base)
{
return (base->INTR & CTDAC_INTR_VDAC_EMPTY_Msk) >> CTDAC_INTR_VDAC_EMPTY_Pos;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_ClearInterrupt
****************************************************************************//**
*
* Clears the interrupt that was set by the hardware when the
* CTDAC_VAL_NXT register value is transferred to the CTDAC_VAL register.
* The interrupt must be cleared with this function so that
* the hardware can set subsequent interrupts and those interrupts
* can be forwarded to the interrupt controller, if enabled.
*
* Interrupts are available in all update modes except \ref CY_CTDAC_UPDATE_DIRECT_WRITE.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_ClearInterrupt(CTDAC_Type *base)
{
base->INTR = CTDAC_INTR_VDAC_EMPTY_Msk;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetSwInterrupt
****************************************************************************//**
*
* Forces the CTDAC interrupt to trigger using software.
*
* Interrupts are available in all update modes except \ref CY_CTDAC_UPDATE_DIRECT_WRITE.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_SetSwInterrupt(CTDAC_Type *base)
{
base->INTR_SET = CTDAC_INTR_SET_VDAC_EMPTY_SET_Msk;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_SetInterruptMask
****************************************************************************//**
*
* Configure the CTDAC interrupt to be forwarded to the CPU interrupt
* controller.
*
* Interrupts are available in all update modes except \ref CY_CTDAC_UPDATE_DIRECT_WRITE.
*
* \param base
* Pointer to structure describing registers
*
* \param mask
* 0: Disable CTDAC interrupt request (will not be forwarded to CPU interrupt controller)
* 1: Enable CTDAC interrupt request (will be forwarded to CPU interrupt controller)
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_CTDAC_SetInterruptMask(CTDAC_Type *base, uint32_t mask)
{
CY_ASSERT_L2(CY_CTDAC_INTRMASK(mask));
base->INTR_MASK = mask & CTDAC_INTR_MASK_VDAC_EMPTY_MASK_Msk;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_GetInterruptMask
****************************************************************************//**
*
* Returns whether the CTDAC interrupt is
* forwarded to the CPU interrupt controller
* as configured by \ref Cy_CTDAC_SetInterruptMask.
*
* Interrupts are available in all update modes except \ref CY_CTDAC_UPDATE_DIRECT_WRITE.
*
* \param base
* Pointer to structure describing registers
*
* \return
* 0 = Interrupt output not forwarded to CPU interrupt controller
* 1 = Interrupt output forwarded to CPU interrupt controller
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptMask(const CTDAC_Type *base)
{
return (base->INTR_MASK & CTDAC_INTR_MASK_VDAC_EMPTY_MASK_Msk) >> CTDAC_INTR_MASK_VDAC_EMPTY_MASK_Pos;
}
/*******************************************************************************
* Function Name: Cy_CTDAC_GetInterruptStatusMasked
****************************************************************************//**
*
* Returns the bitwise AND of \ref Cy_CTDAC_GetInterruptStatus and
* \ref Cy_CTDAC_SetInterruptMask. When high, the DAC interrupt is
* asserted and the interrupt is forwarded to the CPU interrupt
* controller.
*
* Interrupts are available in all update modes except \ref CY_CTDAC_UPDATE_DIRECT_WRITE.
*
* \param base
* Pointer to structure describing registers
*
* \return
* 0 = Value not moved from CTDAC_VAL_NXT to CTDAC_VAL or not masked
* 1 = Value moved from CTDAC_VAL_NXT to CTDAC_VAL and masked
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_CTDAC_GetInterruptStatusMasked(const CTDAC_Type *base){
return (base->INTR_MASKED & CTDAC_INTR_MASKED_VDAC_EMPTY_MASKED_Msk) >> CTDAC_INTR_MASKED_VDAC_EMPTY_MASKED_Pos;
}
/** \} */
/** \} group_ctdac_functions */
#if defined(__cplusplus)
}
#endif
#endif /** !defined(CY_CTDAC_H) */
/** \} group_ctdac */
/* [] END OF FILE */

View File

@ -0,0 +1,318 @@
/***************************************************************************//**
* \file cy_dma.c
* \version 2.0
*
* \brief
* The source code file for the DMA driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_dma.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_Init
****************************************************************************//**
*
* Initializes descriptor structure in SRAM from a pre-initialized
* configuration structure.
* This function initializes only the descriptor and not the channel.
*
* \param descriptor
* A descriptor structure instance declared by user/component.
*
* \param config
* This is a configuration structure that has all initialization information for
* the descriptor.
*
* \return
* The status /ref cy_en_dma_status_t.
*
*******************************************************************************/
cy_en_dma_status_t Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor, const cy_stc_dma_descriptor_config_t * config)
{
cy_en_dma_status_t retVal = CY_DMA_BAD_PARAM;
if ((NULL != descriptor) && (NULL != config))
{
CY_ASSERT_L3(CY_DMA_IS_RETRIGGER_VALID(config->retrigger));
CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->interruptType));
CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerOutType));
CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerInType));
CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->srcTransferSize));
CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->dstTransferSize));
CY_ASSERT_L3(CY_DMA_IS_CHANNEL_STATE_VALID(config->channelState));
CY_ASSERT_L3(CY_DMA_IS_DATA_SIZE_VALID(config->dataSize));
CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(config->descriptorType));
descriptor->ctl =
_VAL2FLD(CY_DMA_CTL_RETRIG, config->retrigger) |
_VAL2FLD(CY_DMA_CTL_INTR_TYPE, config->interruptType) |
_VAL2FLD(CY_DMA_CTL_TR_OUT_TYPE, config->triggerOutType) |
_VAL2FLD(CY_DMA_CTL_TR_IN_TYPE, config->triggerInType) |
_VAL2FLD(CY_DMA_CTL_SRC_SIZE, config->srcTransferSize) |
_VAL2FLD(CY_DMA_CTL_DST_SIZE, config->dstTransferSize) |
_VAL2FLD(CY_DMA_CTL_CH_DISABLE, config->channelState) |
_VAL2FLD(CY_DMA_CTL_DATA_SIZE, config->dataSize) |
_VAL2FLD(CY_DMA_CTL_TYPE, config->descriptorType);
descriptor->src = (uint32_t)config->srcAddress;
descriptor->dst = (uint32_t)config->dstAddress;
switch(config->descriptorType)
{
case CY_DMA_SINGLE_TRANSFER:
{
descriptor->xCtl = (uint32_t)config->nextDescriptor;
break;
}
case CY_DMA_1D_TRANSFER:
{
CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->srcXincrement));
CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->dstXincrement));
CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(config->xCount));
descriptor->xCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
_VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
_VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
descriptor->yCtl = (uint32_t)config->nextDescriptor;
break;
}
case CY_DMA_2D_TRANSFER:
{
CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->srcXincrement));
CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->dstXincrement));
CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(config->xCount));
CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->srcYincrement));
CY_ASSERT_L2(CY_DMA_IS_INCR_VALID(config->dstYincrement));
CY_ASSERT_L2(CY_DMA_IS_COUNT_VALID(config->yCount));
descriptor->xCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
_VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
_VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
descriptor->yCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcYincrement) |
_VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstYincrement) |
_VAL2FLD(CY_DMA_CTL_COUNT, config->yCount - 1UL);
descriptor->nextPtr = (uint32_t)config->nextDescriptor;
break;
}
default:
{
/* Unsupported type of descriptor */
break;
}
}
retVal = CY_DMA_SUCCESS;
}
return retVal;
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_DeInit
****************************************************************************//**
*
* Clears all the content of the specified descriptor.
*
* \param descriptor
* A descriptor structure instance declared by user/component.
*
*******************************************************************************/
void Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor)
{
descriptor->ctl = 0UL;
descriptor->src = 0UL;
descriptor->dst = 0UL;
descriptor->xCtl = 0UL;
descriptor->yCtl = 0UL;
descriptor->nextPtr = 0UL;
}
/*******************************************************************************
* Function Name: Cy_DMA_Channel_Init
****************************************************************************//**
*
* Initializes the DMA channel with a descriptor and other parameters.
*
* \param base
* A pointer to the hardware DMA block.
*
* \param channel
* A channel number.
*
* \param channelConfig
* A structure that has the initialization information for the
* channel.
*
* \return
* The status /ref cy_en_dma_status_t.
*
*******************************************************************************/
cy_en_dma_status_t Cy_DMA_Channel_Init(DW_Type * base, uint32_t channel, cy_stc_dma_channel_config_t const * channelConfig)
{
cy_en_dma_status_t retVal = CY_DMA_BAD_PARAM;
if (((CY_DMA_IS_DW_CH_NR_VALID(base, channel)) && (NULL != channelConfig) && (NULL != channelConfig->descriptor)))
{
uint32_t regVal;
CY_ASSERT_L2(CY_DMA_IS_PRIORITY_VALID(channelConfig->priority));
/* Set current descriptor */
base->CH_STRUCT[channel].CH_CURR_PTR = (uint32_t)channelConfig->descriptor;
/* Set if the channel is preemtable */
regVal = base->CH_STRUCT[channel].CH_CTL & ((uint32_t) ~(DW_CH_STRUCT_CH_CTL_PREEMPTABLE_Msk |
DW_CH_STRUCT_CH_CTL_PRIO_Msk |
DW_CH_STRUCT_CH_CTL_ENABLED_Msk));
base->CH_STRUCT[channel].CH_CTL = regVal | _BOOL2FLD(DW_CH_STRUCT_CH_CTL_PREEMPTABLE, channelConfig->preemptable) |
_VAL2FLD(DW_CH_STRUCT_CH_CTL_PRIO, channelConfig->priority) |
_BOOL2FLD(DW_CH_STRUCT_CH_CTL_ENABLED, channelConfig->enable);
retVal = CY_DMA_SUCCESS;
}
return (retVal);
}
/*******************************************************************************
* Function Name: Cy_DMA_Channel_DeInit
****************************************************************************//**
*
* Clears all the content of registers corresponding to the channel.
*
* \param base
* A pointer to the hardware DMA block.
*
* \param channel
* A channel number.
*
*******************************************************************************/
void Cy_DMA_Channel_DeInit(DW_Type * base, uint32_t channel)
{
CY_ASSERT_L1(CY_DMA_IS_DW_CH_NR_VALID(base, channel));
base->CH_STRUCT[channel].CH_CTL = 0UL;
base->CH_STRUCT[channel].CH_IDX = 0UL;
base->CH_STRUCT[channel].CH_CURR_PTR = 0UL;
base->CH_STRUCT[channel].INTR_MASK = 0UL;
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_SetNextDescriptor
****************************************************************************//**
*
* Sets a Next Descriptor parameter for the specified descriptor.
*
* Based on descriptor type the offset of address for the next descriptor may
* vary. For a single transfer descriptor type, this register is at offset 0x0c.
* For a 1D transfer descriptor type, this register is at offset 0x10. For a 2D
* transfer descriptor type, this register is at offset 0x14.
*
* \param descriptor
* A descriptor structure instance declared by user/component.
*
* \param nextDescriptor
* The pointer to the next descriptor.
*
*******************************************************************************/
void Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_t const * nextDescriptor)
{
CY_ASSERT_L1(NULL != descriptor);
switch((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl))
{
case CY_DMA_SINGLE_TRANSFER:
descriptor->xCtl = (uint32_t)nextDescriptor;
break;
case CY_DMA_1D_TRANSFER:
descriptor->yCtl = (uint32_t)nextDescriptor;
break;
case CY_DMA_2D_TRANSFER:
descriptor->nextPtr = (uint32_t)nextDescriptor;
break;
default:
/* Unsupported type of descriptor */
break;
}
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_GetNextDescriptor
****************************************************************************//**
*
* Returns a next descriptor address of the specified descriptor.
*
* Based on descriptor type the offset of address for the next descriptor may
* vary. For a single transfer descriptor type, this register is at offset 0x0c.
* For a 1D transfer descriptor type, this register is at offset 0x10. For a 2D
* transfer descriptor type, this register is at offset 0x14.
*
* \param descriptor
* A descriptor structure instance declared by user/component.
*
* \return
* The pointer to the next descriptor.
*
*******************************************************************************/
cy_stc_dma_descriptor_t * Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor)
{
cy_stc_dma_descriptor_t * retVal = NULL;
CY_ASSERT_L1(NULL != descriptor);
switch((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl))
{
case CY_DMA_SINGLE_TRANSFER:
retVal = (cy_stc_dma_descriptor_t*) descriptor->xCtl;
break;
case CY_DMA_1D_TRANSFER:
retVal = (cy_stc_dma_descriptor_t*) descriptor->yCtl;
break;
case CY_DMA_2D_TRANSFER:
retVal = (cy_stc_dma_descriptor_t*) descriptor->nextPtr;
break;
default:
/* Unsupported type of descriptor */
break;
}
return (retVal);
}
#if defined(__cplusplus)
}
#endif
/* [] END OF FILE */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,886 @@
/***************************************************************************//**
* \file cy_flash.c
* \version 2.0
*
* \brief
* Provides the public functions for the API for the PSoC 6 Flash Driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_flash.h"
/** \cond INTERNAL */
/** Slow control register */
#define CY_FLASH_TST_DDFT_SLOW_CTL_REG (*(reg32 *) 0x40260108U)
/** Slow control register */
#define CY_FLASH_TST_DDFT_FAST_CTL_REG (*(reg32 *) 0x40260104U)
/** Slow output register */
#define CY_FLASH_CLK_OUTPUT_SLOW_REG (*(reg32 *) 0x40260518U)
/** Slow clock calibration register */
#define CY_FLASH_CLK_CAL_CNT1_REG (*(reg32 *) 0x4026051CU)
/** Define to set the IMO to perform a delay after the flash operation started */
#define CY_FLASH_TST_DDFT_SLOW_CTL_MASK (0x40001F1EU)
/** Slow output register */
#define CY_FLASH_CLK_OUTPUT_SLOW_MASK (0x06U)
/** Define to indicate that clock is finished counting */
#define CY_FLASH_CLK_CAL_CNT1_DONE ((uint32_t) ((uint32_t) 1U << CY_FLASH_CLK_CAL_CNT1_DONE_POS))
/** Define to indicate that clock is finished counting */
#define CY_FLASH_CLK_CAL_CNT1_DONE_POS (31U)
/* Calculates the time in microseconds to wait for the number of the CM0P ticks */
#define CY_FLASH_DEL_CORRECTIVE(ticks) ((((uint32)Cy_SysClk_ClkPeriGetDivider() + 1UL) * (Cy_SysClk_ClkSlowGetDivider() + 1UL) * (ticks) * 1000UL)\
/ ((uint32_t)cy_Hfclk0FreqHz / 1000UL))
/* Number of the CM0P ticks for StartWrite function delay corrective time */
#define CY_FLASH_START_WRITE_DEL_TICKS (19000UL)
/* Number of the CM0P ticks for StartProgram function delay corrective time */
#define CY_FLASH_START_PROGRAM_DEL_TICKS (5250UL)
/* Number of the CM0P ticks for StartErase function delay corrective time */
#define CY_FLASH_START_ERASE_DEL_TICKS (8500UL)
/* Delay time for StartWrite function in us */
#define CY_FLASH_START_WRITE_DEL_TIME (9800UL)
/* Delay time for StartProgram function in us */
#define CY_FLASH_START_PROGRAM_DEL_TIME (120UL)
/* Delay time for StartErase function in us */
#define CY_FLASH_START_ERASE_DEL_TIME (1000UL)
/** Delay time for Start Write function in us with corrective time */
#define CY_FLASH_START_WRITE_DELAY (uint32_t)(CY_FLASH_START_WRITE_DEL_TIME +\
CY_FLASH_DEL_CORRECTIVE(CY_FLASH_START_WRITE_DEL_TICKS))
/** Delay time for Start Program function in us with corrective time */
#define CY_FLASH_START_PROGRAM_DELAY (uint32_t)(CY_FLASH_START_PROGRAM_DEL_TIME +\
CY_FLASH_DEL_CORRECTIVE(CY_FLASH_START_PROGRAM_DEL_TICKS))
/** Delay time fot Start Erase function in uS with corrective time */
#define CY_FLASH_START_ERASE_DELAY (uint32_t)(CY_FLASH_START_ERASE_DEL_TIME +\
CY_FLASH_DEL_CORRECTIVE(CY_FLASH_START_ERASE_DEL_TICKS))
/** Number of ticks to wait 1 uS */
#define CY_FLASH_TICKS_FOR_1US (8U)
/** Disable delay */
#define CY_FLASH_NO_DELAY (0U)
/** Slow control register */
#define CY_FLASH_TST_DDFT_FAST_CTL_MASK (62U)
/** Command completed with no errors */
#define CY_FLASH_ROMCODE_SUCCESS (0xA0000000UL)
/** Invalid device protection state */
#define CY_FLASH_ROMCODE_INVALID_PROTECTION (0xF0000001UL)
/** Invalid flash page latch address */
#define CY_FLASH_ROMCODE_INVALID_FM_PL (0xF0000003UL)
/** Invalid flash address */
#define CY_FLASH_ROMCODE_INVALID_FLASH_ADDR (0xF0000004UL)
/** Row is write protected */
#define CY_FLASH_ROMCODE_ROW_PROTECTED (0xF0000005UL)
/** Comparison between Page Latches and FM row failed */
#define CY_FLASH_ROMCODE_PL_ROW_COMP_FA (0xF0000022UL)
/** Command in progress; no error */
#define CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR (0xA0000009UL)
/** Flash operation is successfully initiated */
#define CY_FLASH_IS_OPERATION_STARTED (0x00000010UL)
/** Flash is under operation */
#define CY_FLASH_IS_BUSY (0x00000040UL)
/** IPC structure is already locked by another process */
#define CY_FLASH_IS_IPC_BUSY (0x00000080UL)
/** Input parameters passed to Flash API are not valid */
#define CY_FLASH_IS_INVALID_INPUT_PARAMETERS (0x00000100UL)
/** Result mask */
#define CY_FLASH_RESULT_MASK (0xFFFFFFFUL)
/** Error shift */
#define CY_FLASH_ERROR_SHIFT (28UL)
/** No error */
#define CY_FLASH_ERROR_NO_ERROR (0xAUL)
/** CM4 Flash Proxy address */
#define CY_FLASH_CM4_FLASH_PROXY_ADDR (0x00007001UL)
#if (CY_CPU_CORTEX_M0P)
#define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_INTR_CYPIPE_EP1)))
#define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM4_ADDR, CY_IPC_EP_CYPIPE_CM0_ADDR, a, NULL)
#else
#define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_INTR_CYPIPE_EP0)))
#define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM0_ADDR, CY_IPC_EP_CYPIPE_CM4_ADDR, a, NULL)
#endif
/** \endcond */
/* Static functions */
static bool Cy_Flash_BoundsCheck(uint32_t flashAddr);
static uint32_t Cy_Flash_PrepareContext(uint32_t rowAddr, const uint32_t *data, uint32_t blocking);
static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode);
static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void);
static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds);
static void Cy_Flash_RAMDelay(uint32_t microseconds);
static cy_stc_flash_context_t context;
/** \cond INTERNAL */
CY_ALIGN(4) static IPC_MSG ipcWaitMessage =
{
/* .clientID */ CY_FLASH_IPC_CLIENT_ID,
/* .pktType */ CY_FLASH_ENTER_WAIT_LOOP,
/* .intrRelMask */ 0
};
/** \endcond */
/*******************************************************************************
* Function Name: Cy_Flash_SendCmd
****************************************************************************//**
*
* Sends a command to the SROM via the IPC channel. The function is placed to the
* SRAM memory to guarantee successful operation. After an IPC message is sent,
* the function waits for a defined time before exiting the function.
*
* \param mode Sets the blocking or non-blocking Flash operation.
*
* \param microseconds The number of microseconds to wait before exiting the functions.
*
* \return Returns the status of the Flash operation,
* see \ref cy_en_flashdrv_status_t.
*
*******************************************************************************/
#if defined (__ICCARM__)
__ramfunc
#else
CY_SECTION(".cy_ramfunc")
#endif
static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds)
{
uint32_t intr;
cy_en_flashdrv_status_t result = CY_FLASH_DRV_IPC_BUSY;
if (IS_CY_PIPE_FREE())
{
if (CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA))
{
if (CY_IPC_PIPE_SUCCESS == NOTIFY_PEER_CORE(&ipcWaitMessage))
{
/* Wait for SEMA lock by peer core */
while(CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA))
{
}
intr = Cy_SysLib_EnterCriticalSection();
/* Tries to acquire the IPC structure and pass the arguments to SROM API */
if (Cy_IPC_Drv_SendMsgPtr(CY_FLASH_IPC_STRUCT, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&context) == CY_IPC_DRV_SUCCESS)
{
if (mode == CY_FLASH_NON_BLOCKING_MODE)
{
Cy_Flash_RAMDelay(microseconds);
/* The Flash operation is successfully initiated */
result = CY_FLASH_DRV_OPERATION_STARTED;
}
else
{
/* Polls whether the IPC is released and the Flash operation is performed */
do
{
result = Cy_Flash_IsWriteComplete();
}
while (result == CY_FLASH_DRV_OPCODE_BUSY);
}
}
else
{
/* The IPC structure is already locked by another process */
result = CY_FLASH_DRV_IPC_BUSY;
}
while ( CY_IPC_SEMA_SUCCESS != Cy_IPC_Sema_Clear(CY_FLASH_WAIT_SEMA, false))
{
}
Cy_SysLib_ExitCriticalSection(intr);
}
}
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_EraseRow
****************************************************************************//**
*
* This function erases a single row of flash. Reports success or
* a reason for failure. Does not return until the Write operation is
* complete. Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in
* the case when another process is writing to flash or erasing the row.
* User firmware should not enter the hibernate mode until flash erase is
* complete. The Flash operation is allowed in Sleep and Deep-sleep modes.
* During the Flash operation, the device should not be reset, including the
* XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
* detect circuits should be configured to generate an interrupt instead of a
* reset. Otherwise, portions of flash may undergo unexpected changes.
*
* \param rowAddr Address of the flash row number. The number of the flash rows
* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device.
* The Read-while-Write violation occurs when the flash read operation is
* initiated in the same flash sector where the flash write operation is
* performing. Refer to the device datasheet for the details.
* Address must match row start address.
*
* \return Returns the status of the Flash operation,
* see \ref cy_en_flashdrv_status_t.
*
* \sideeffect If this function is called by the CM4 the user code on CM0P and
* the user code on CM4 are blocked until erase flash row operation is finished.
* If this function is called by the CM0P the user code on CM4 is not blocked and
* the user code on CM0P is blocked until erase flash row operation is finished.
* Plan your task allocation accordingly.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr)
{
cy_en_flashdrv_status_t result;
/* Prepares arguments to be passed to SROM API */
if (Cy_Flash_BoundsCheck(rowAddr) != false)
{
context.opcode = CY_FLASH_OPCODE_ERASE_ROW | CY_FLASH_BLOCKING_MODE;
context.arg1 = rowAddr;
context.arg2 = 0UL;
context.arg3 = 0UL;
#if (CY_CPU_CORTEX_M0P)
result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
#else
Cy_Flash_Proxy Cy_Flash_Cm4Proxy;
Cy_Flash_Cm4Proxy = (Cy_Flash_Proxy)CY_FLASH_CM4_FLASH_PROXY_ADDR;
result = Cy_Flash_Cm4Proxy(&context);
result = Cy_Flash_ProcessOpcode((uint32_t)result);
#endif /* (CY_CPU_CORTEX_M0P) */
}
else
{
result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_WriteRow
****************************************************************************//**
*
* This function writes an array of data to a single row of flash.
* Reports success or a reason for failure. Does not return until the Write
* operation is complete.
* Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case
* when another process is writing to flash. User firmware should not enter the
* hibernate mode until flash Write is complete. The Flash operation is allowed
* in Sleep and Deep-sleep modes. During the Flash operation, the device should
* not be reset, including the XRES pin, a software reset, and watchdog reset
* sources. Also, low-voltage detect circuits should be configured to generate
* an interrupt instead of a reset. Otherwise, portions of flash may undergo
* unexpected changes.
*
* \param rowAddr Address of the flash row number. The number of the flash rows
* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device.
* The Read-while-Write violation occurs when the flash read operation is
* initiated in the same flash sector where the flash write operation is
* performing. Refer to the device datasheet for the details.
* Address must match row start address.
*
* \param data The pointer to the data which has to be written to flash. The size
* of the data array must be equal to the flash row size. The flash row size for
* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
* the device datasheet for the details.
*
* \return Returns the status of the Flash operation,
* see \ref cy_en_flashdrv_status_t.
*
* \sideeffect If this function is called by the CM4 the user code on CM0P and
* the user code on CM4 are blocked until erase flash row operation is finished.
* If this function is called by the CM0P the user code on CM4 is not blocked and
* the user code on CM0P is blocked until erase flash row operation is finished.
* Plan your task allocation accordingly.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data)
{
cy_en_flashdrv_status_t result;
#if (CY_CPU_CORTEX_M0P)
/* Checks whether the input parameters are valid */
if (Cy_Flash_PrepareContext(rowAddr, data, CY_FLASH_BLOCKING_MODE) != (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS)
{
result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
}
else
{
result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
#else
if (Cy_Flash_PrepareContext(rowAddr, data, CY_FLASH_BLOCKING_MODE) != (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS)
{
Cy_Flash_Proxy Cy_Flash_Cm4Proxy;
Cy_Flash_Cm4Proxy = (Cy_Flash_Proxy)CY_FLASH_CM4_FLASH_PROXY_ADDR;
result = Cy_Flash_Cm4Proxy(&context);
result = Cy_Flash_ProcessOpcode((uint32_t)result);
}
else
{
result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
#endif /* (CY_CPU_CORTEX_M0P) */
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_StartWrite
****************************************************************************//**
*
* Starts writing an array of data to a single row of flash. Returns immediately
* and reports a successful start or reason for failure. Returns immediately and
* reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when another process is writing
* to flash. User firmware should not enter the hibernate mode until flash Write
* is complete. The Flash operation is allowed in Sleep and Deep-sleep modes.
* During the flash operation, the device should not be reset, including the
* XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
* detect circuits should be configured to generate an interrupt instead of a reset.
* Otherwise, portions of flash may undergo unexpected changes.
* \note Before reading data from previously programmed/erased flash rows, the
* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
* function.
*
* \param rowAddr Address of the flash row number. The number of the flash rows
* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device.
* The Read-while-Write violation occurs when the flash read operation is
* initiated in the same flash sector where the flash write operation is
* performing. Refer to the device datasheet for the details.
* Address must match row start address.
*
* \param data The pointer to the data to be written to flash. The size
* of the data array must be equal to the flash row size. The flash row size for
* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
* the device datasheet for the details.
*
* \return Returns the status of the Flash operation,
* see \ref cy_en_flashdrv_status_t.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data)
{
cy_en_flashdrv_status_t result;
/* Checks whether the input parameters are valid */
if (Cy_Flash_PrepareContext(rowAddr, data, CY_FLASH_NON_BLOCKING_MODE) != (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS)
{
result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_WRITE_DELAY);
}
else
{
result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_IsWriteComplete
****************************************************************************//**
*
* Reports a successful Write, reason of failure or busy status
* ( \ref CY_FLASH_DRV_OPCODE_BUSY ).
*
* \return Returns the status of the Flash operation (see \ref cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_IsWriteComplete(void)
{
return (Cy_Flash_OperationStatus());
}
/*******************************************************************************
* Function Name: Cy_Flash_StartErase
****************************************************************************//**
*
* Starts erasing a single row of flash. Returns immediately
* and reports a successful start or reason for failure. Returns immediately and
* reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
* by another process. User firmware should not enter the hibernate mode until
* flash Erase is complete. The Flash operation is allowed in Sleep and Deep-sleep modes.
* During the flash operation, the device should not be reset, including the
* XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
* detect circuits should be configured to generate an interrupt instead of a reset.
* Otherwise, portions of flash may undergo unexpected changes.
* \note Before reading data from previously programmed/erased flash rows, the
* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
* function.
*
* \param rowAddr Address of the flash row number. The number of the flash rows
* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device.
* The Read-while-Write violation occurs when the flash read operation is
* initiated in the same flash sector where the flash erase operation is
* performing. Refer to the device datasheet for the details.
* Address must match row start address.
*
* \return Returns the status of the Flash operation,
* see \ref cy_en_flashdrv_status_t.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_StartErase(uint32_t rowAddr)
{
cy_en_flashdrv_status_t retVal;
/* Prepares arguments to be passed to SROM API */
if (Cy_Flash_BoundsCheck(rowAddr) != false)
{
context.opcode = CY_FLASH_OPCODE_ERASE_ROW;
context.arg1 = rowAddr;
context.arg2 = 0UL;
context.arg3 = 0UL;
retVal = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
}
else
{
retVal = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
return (retVal);
}
/*******************************************************************************
* Function Name: Cy_Flash_IsEraseComplete
****************************************************************************//**
*
* Reports a successful Erase, reason of failure or busy status
* ( \ref CY_FLASH_DRV_OPCODE_BUSY ).
*
* \return Returns the status of the Flash operation (see \ref cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_IsEraseComplete(void)
{
return (Cy_Flash_OperationStatus());
}
/*******************************************************************************
* Function Name: Cy_Flash_StartProgram
****************************************************************************//**
* Starts writing an array of data to a single row of flash. Returns immediately
* and reports a successful start or reason for failure. Returns immediately and
* reports a \ref CY_FLASH_DRV_IPC_BUSY error if another process is writing
* to flash. The user firmware should not enter Hibernate mode until flash Write
* is complete. The Flash operation is allowed in Sleep and Deep-Sleep modes.
* During the Flash operation, the device should not be reset, including the
* XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
* detect circuits should be configured to generate an interrupt instead of a reset.
* Otherwise, portions of flash may undergo unexpected changes.\n
* Before calling this function, the target flash region must be erased by
* the StartErase/EraseRow function.\n
* Data to be programmed must be located in the SRAM memory region.
* \note Before reading data from previously programmed/erased flash rows, the
* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
* function.
*
* \param rowAddr The address of the flash row number. The number of the flash rows
* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device.
* The Read-while-Write violation occurs when the Flash Write operation is
* performing. Refer to the device datasheet for the details.
* The address must match the row start address.
*
* \param data The pointer to the data to be written to flash. The size
* of the data array must be equal to the flash row size. The flash row size for
* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
* the device datasheet for the details.
*
* \return Returns the status of the Flash operation,
* see \ref cy_en_flashdrv_status_t.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data)
{
cy_en_flashdrv_status_t result;
/* Prepares arguments to be passed to SROM API */
if (Cy_Flash_BoundsCheck(rowAddr) != false)
{
context.opcode = CY_FLASH_OPCODE_PROGRAM_ROW | CY_FLASH_NON_BLOCKING_MODE;
context.arg1 = CY_FLASH_CONFIG_DATASIZE | CY_FLASH_DATA_LOC_SRAM;
context.arg2 = rowAddr;
context.arg3 = (uint32_t)data;
result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY);
}
else
{
result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_IsProgramComplete
****************************************************************************//**
*
* Reports a successful program operation, failure or busy status
* ( \ref CY_FLASH_DRV_OPCODE_BUSY ).
*
* \return Returns the status of the Flash operation (see \ref cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_IsProgramComplete(void)
{
return (Cy_Flash_OperationStatus());
}
/*******************************************************************************
* Function Name: Cy_Flash_RowChecksum
****************************************************************************//**
*
* Returns a checksum value of the specified flash row.
*
* \param rowNum The Checksum is calculated to the flash row.
*
* \param checksumPtr The pointer to the address where checksum is to be stored
*
* \return Returns the status of the Flash operation.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_RowChecksum (uint32_t rowNum, uint32_t* checksumPtr)
{
cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
uint32_t resTmp;
/* Checks whether the input parameters are valid */
if (rowNum < CY_FLASH_NUMBER_ROWS)
{
/* Prepares arguments to be passed to SROM API */
context.opcode = CY_FLASH_OPCODE_CHECKSUM | (rowNum << CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT);
/* Tries to acquire the IPC structure and pass the arguments to SROM API */
if (Cy_IPC_Drv_SendMsgPtr(CY_FLASH_IPC_STRUCT, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&context) == CY_IPC_DRV_SUCCESS)
{
/* Polls whether IPC is released and the Flash operation is performed */
while (Cy_IPC_Drv_IsLockAcquired(CY_FLASH_IPC_STRUCT) != false)
{
/* Wait till IPC is released */
}
resTmp = context.opcode;
if((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR)
{
result = CY_FLASH_DRV_SUCCESS;
*checksumPtr = context.opcode & CY_FLASH_RESULT_MASK;
}
}
else
{
/* The IPC structure is already locked by another process */
result = CY_FLASH_DRV_IPC_BUSY;
}
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_CalculateHash
****************************************************************************//**
*
* Returns a hash value of the specified region of flash.
*
* \param data Start the data address.
*
* \param numberOfBytes The hash value is calculated for the number of bytes after the
* start data address (0 - 1 byte, 1- 2 bytes etc).
*
* \param hashPtr The pointer to the address where hash is to be stored
*
* \return Returns the status of the Flash operation.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_CalculateHash (const uint32_t* data, uint32_t numberOfBytes, uint32_t* hashPtr)
{
cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
volatile uint32_t resTmp;
/* Checks whether the input parameters are valid */
if (data != NULL)
{
/* Prepares arguments to be passed to SROM API */
context.opcode = CY_FLASH_OPCODE_HASH;
context.arg1 = (uint32_t)data;
context.arg2 = numberOfBytes;
/* Tries to acquire the IPC structure and pass the arguments to SROM API */
if (Cy_IPC_Drv_SendMsgPtr(CY_FLASH_IPC_STRUCT, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&context) == CY_IPC_DRV_SUCCESS)
{
/* Polls whether IPC is released and the Flash operation is performed */
while (Cy_IPC_Drv_IsLockAcquired(CY_FLASH_IPC_STRUCT) != false)
{
/* Wait till IPC is released */
}
resTmp = context.opcode;
if((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR)
{
result = CY_FLASH_DRV_SUCCESS;
*hashPtr = context.opcode & CY_FLASH_RESULT_MASK;
}
}
else
{
/* The IPC structure is already locked by another process */
result = CY_FLASH_DRV_IPC_BUSY;
}
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_BoundsCheck
****************************************************************************//**
*
* Returns false if Flash address is out of boundary, otherwise returns true.
*
* \param flashAddr Address to be checked
*
* \return false - out of bound, true - in flash bounds
*
*******************************************************************************/
static bool Cy_Flash_BoundsCheck(uint32_t flashAddr)
{
bool result = true;
if ((flashAddr < CY_FLASH_BASE) || (flashAddr >= (CY_FLASH_BASE + CY_FLASH_SIZE)))
{
if ((flashAddr < CY_WFLASH_BASE) || (flashAddr >= (CY_WFLASH_BASE + CY_WFLASH_SIZE)))
{
if ((flashAddr < SFLASH_BASE) || (flashAddr >= (SFLASH_BASE + SFLASH_SECTION_SIZE)))
{
result = false;
}
}
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_PrepareContext
****************************************************************************//**
*
* Returns 1 if parameters are correct and initialises context, otherwise returns
* CY_FLASH_DRV_INVALID_INPUT_PARAMETERS.
*
* \param rowAddr Address of the flash row number. The number of the flash rows
* is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device.
* The Read-while-Write violation occurs when the flash read operation is
* initiated in the same flash sector where the flash write operation is
* performing. Refer to the device datasheet for the details.
* Address must match row start address.
*
* \param data The pointer to the data which has to be written to flash. The size
* of the data array must be equal to the flash row size. The flash row size for
* the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
* the device datasheet for the details.
*
* \param blocking The parameter of how the context will be executed.
* * 1 - blocking, If this function is called by the CM4 the user code on CM0P
* and the user code on CM4 are blocked until flash write operation is finished.
* If this function is called by the CM0P the user code on CM4 is not blocked
* and the user code on CM0P is blocked until flash write operation is finished.
* * 0 - non-blocking, the user code is not blocked while flash write operation
* is executed.
*
* \return 1 - Context ready, CY_FLASH_DRV_INVALID_INPUT_PARAMETERS - Wrong
* arguments
*
*******************************************************************************/
static uint32_t Cy_Flash_PrepareContext(uint32_t rowAddr, const uint32_t* data, uint32_t blocking)
{
uint32_t result;
if ((Cy_Flash_BoundsCheck(rowAddr) == false) || (NULL == data))
{
result = (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
else
{
if ((rowAddr%CY_FLASH_SIZEOF_ROW) != 0UL)
{
result = (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
else
{
/* Prepares arguments to be passed to SROM API */
context.opcode = CY_FLASH_OPCODE_WRITE_ROW | blocking;
context.arg1 = CY_FLASH_CONFIG_DATASIZE;
context.arg2 = rowAddr;
context.arg3 = (uint32_t)data;
result = 1UL;
}
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_ProcessOpcode
****************************************************************************//**
*
* Converts System Call returns to the Flash driver return defines.
*
* \param opcode The value returned by the System Call.
*
* \return Flash driver return.
*
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode)
{
cy_en_flashdrv_status_t retVal;
switch (opcode)
{
case 0UL:
{
retVal = CY_FLASH_DRV_SUCCESS;
break;
}
case CY_FLASH_ROMCODE_SUCCESS:
{
retVal = CY_FLASH_DRV_SUCCESS;
break;
}
case CY_FLASH_ROMCODE_INVALID_PROTECTION:
{
retVal = CY_FLASH_DRV_INV_PROT;
break;
}
case CY_FLASH_ROMCODE_INVALID_FM_PL:
{
retVal = CY_FLASH_DRV_INVALID_FM_PL;
break;
}
case CY_FLASH_ROMCODE_INVALID_FLASH_ADDR:
{
retVal = CY_FLASH_DRV_INVALID_FLASH_ADDR;
break;
}
case CY_FLASH_ROMCODE_ROW_PROTECTED:
{
retVal = CY_FLASH_DRV_ROW_PROTECTED;
break;
}
case CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR:
{
retVal = CY_FLASH_DRV_PROGRESS_NO_ERROR;
break;
}
case (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
{
retVal = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
break;
}
case CY_FLASH_IS_OPERATION_STARTED :
{
retVal = CY_FLASH_DRV_OPERATION_STARTED;
break;
}
case CY_FLASH_IS_BUSY :
{
retVal = CY_FLASH_DRV_OPCODE_BUSY;
break;
}
case CY_FLASH_IS_IPC_BUSY :
{
retVal = CY_FLASH_DRV_IPC_BUSY;
break;
}
case CY_FLASH_IS_INVALID_INPUT_PARAMETERS :
{
retVal = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
break;
}
default:
{
retVal = CY_FLASH_DRV_ERR_UNC;
break;
}
}
return (retVal);
}
/*******************************************************************************
* Function Name: Cy_Flash_OperationStatus
****************************************************************************//**
*
* Checks the status of the Flash Operation, and returns it.
*
* \return Returns the status of the Flash operation
* (see \ref cy_en_flashdrv_status_t).
*
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void)
{
cy_en_flashdrv_status_t retVal = CY_FLASH_DRV_OPCODE_BUSY;
/* Checks if the IPC structure is not locked */
if (Cy_IPC_Drv_IsLockAcquired(CY_FLASH_IPC_STRUCT) == false)
{
/* The result of SROM API calling is returned to the driver context */
retVal = Cy_Flash_ProcessOpcode(context.opcode);
}
return (retVal);
}
/*******************************************************************************
* Function Name: Cy_Flash_RAMDelay
****************************************************************************//**
*
* Wait for a defined time in the SRAM memory region.
*
*******************************************************************************/
#if defined (__ICCARM__)
__ramfunc
#else
CY_SECTION(".cy_ramfunc")
#endif
static void Cy_Flash_RAMDelay(uint32_t microseconds)
{
uint32_t ticks = microseconds * CY_FLASH_TICKS_FOR_1US;
if (ticks != CY_FLASH_NO_DELAY)
{
CY_FLASH_TST_DDFT_SLOW_CTL_REG = CY_FLASH_TST_DDFT_SLOW_CTL_MASK;
CY_FLASH_CLK_OUTPUT_SLOW_REG = CY_FLASH_CLK_OUTPUT_SLOW_MASK;
CY_FLASH_TST_DDFT_FAST_CTL_REG = CY_FLASH_TST_DDFT_FAST_CTL_MASK;
/* Load the down-counter */
CY_FLASH_CLK_CAL_CNT1_REG = ticks;
/* Make sure that the counter is started */
(void) CY_FLASH_CLK_CAL_CNT1_REG;
while(0U == (CY_FLASH_CLK_CAL_CNT1_REG & CY_FLASH_CLK_CAL_CNT1_DONE))
{
/* Wait until the counter stops counting */
}
}
}
/* [] END OF FILE */

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* \file cy_flash.h
* \version 1.0
* \version 2.0
*
* Provides the API declarations of the Flash driver.
*
@ -45,10 +45,19 @@
* Use different flash sectors for code and data storage. The flash is divided
* into four equal sectors.
*
* \warning If the CM0 core triggers the Flash operation, another core must be in
* Active mode and interrupts must be enabled in both cores.
*
* \note "Warning[Ta023]: Call to a non __ramfunc function." - The warning may
* appear during the build process while using IAR IDE. The reason - some
* functions in RAM memory that use the __ramfunc keyword, may invoke
* functions located in the ROM memory. You can ignore this warning or
* disable it by adding the --diag_suppress=Ta023 option to the compiler.
*
* \section group_flash_configuration Configuration Considerations
*
* There are no specific configuration parameters for the flash operations
* outside the driver API input parameters.
* Note that to be able to perform FLASH writes, the VCCD should be more than 0.99 V.
* For more information see the technical reference manual (TRM).
*
* \section group_flash_more_information More Information
*
@ -56,20 +65,28 @@
*
* \section group_flash_MISRA MISRA-C Compliance
*
* The Flash driver has the following specific deviations:
*
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* <th style="width: 50%;">Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>19.7</td>
* <td>A</td>
* <td>A function shall be used in preference to a function-like macro</td>
* <td>Macro is used because of performance reasons</td>
* <td>5.6</td>
* <td>R</td>
* <td>No identifier in one name space can have the same spelling as an identifier in another name space, with the
* exception of structure member and union member names.</td>
* <td>The "context" is used as a structure/union member; they are a label, tag or ordinary
* identifier.</td>
* </tr>
* <tr>
* <td>8.7</td>
* <td>R</td>
* <td>Objects shall be defined at block scope if they are only accessed
* from within a single function.</td>
* <td>The driver defines an internal variable that can be accessed by
* any core through the IPC hardware.</td>
* </tr>
* </table>
*
@ -82,120 +99,97 @@
* <td>Initial version</td>
* <td></td>
* </tr>
* <tr>
* <td>2.0</td>
* <td>Added non-blocking erase functions ( Cy_Flash_StartErase() and
* Cy_Flash_IsEraseComplete() ). Removed the clear cache function
* call.</td>
* <td>The clear cache operation is removed from the blocking Write/Erase
* function because in this case it is performed by the hardware.
* Otherwise it is documented that it is the user's responsibility to
* clear the cache after executing the non-blocking Write/Erase flash
* operation.</td>
* </tr>
* </table>
*
* \defgroup group_flash_macro Macro
* \defgroup group_flash_macros Macros
* \defgroup group_flash_functions Functions
* \defgroup group_flash_data_structure Data Structures
* \defgroup group_flash_enumerated_types Enumerated Types
*/
#include <cy_device_headers.h>
#include <stddef.h>
#include <ipc/cy_ipc_drv.h>
#include <ipc/cy_ipc_sema.h>
#include <ipc/cy_ipc_pipe.h>
#include <sysclk/cy_sysclk.h>
#if defined(__cplusplus)
extern "C" {
#endif
/***************************************
* Macro definitions
***************************************/
/**
* \addtogroup group_flash_macro
* \addtogroup group_flash_macros
* \{
*/
/** Driver major version */
#define CY_FLASH_DRV_VERSION_MAJOR 1
#define CY_FLASH_DRV_VERSION_MAJOR 2
/** Driver minor version */
#define CY_FLASH_DRV_VERSION_MINOR 0
/**
* \defgroup group_flash_returns Flash return values
* \{
* Specifies return values meaning
*/
#define CY_FLASH_ID (CY_PDL_DRV_ID(0x14u)) /**< FLASH PDL ID */
#define CY_FLASH_ID (CY_PDL_DRV_ID(0x14UL)) /**< FLASH PDL ID */
#define CY_FLASH_ID_INFO (uint32_t)( CY_FLASH_ID | CY_PDL_STATUS_INFO ) /**< Return prefix for FLASH driver function status codes */
#define CY_FLASH_ID_WARNING (uint32_t)( CY_FLASH_ID | CY_PDL_STATUS_WARNING) /**< Return prefix for FLASH driver function warning return values */
#define CY_FLASH_ID_ERROR (uint32_t)( CY_FLASH_ID | CY_PDL_STATUS_ERROR) /**< Return prefix for FLASH driver function error return values */
/** This enum has the return values of the Flash driver */
typedef enum
{
CY_FLASH_DRV_SUCCESS = 0x00ul, /**< Success */
CY_FLASH_DRV_INV_PROT = ( CY_FLASH_ID_ERROR + 0ul), /**< Invalid device protection state */
CY_FLASH_DRV_INVALID_FM_PL = ( CY_FLASH_ID_ERROR + 1ul), /**< Invalid flash page latch address */
CY_FLASH_DRV_INVALID_FLASH_ADDR = ( CY_FLASH_ID_ERROR + 2ul), /**< Invalid flash address */
CY_FLASH_DRV_ROW_PROTECTED = ( CY_FLASH_ID_ERROR + 3ul), /**< Row is write protected */
CY_FLASH_DRV_IPC_BUSY = ( CY_FLASH_ID_ERROR + 5ul), /**< IPC structure is already locked by another process */
CY_FLASH_DRV_INVALID_INPUT_PARAMETERS = ( CY_FLASH_ID_ERROR + 6ul), /**< Input parameters passed to Flash API are not valid */
CY_FLASH_DRV_ERR_UNC = ( CY_FLASH_ID_ERROR + 0xFul),/**< Unknown error */
CY_FLASH_DRV_PROGRESS_NO_ERROR = ( CY_FLASH_ID_INFO + 0ul), /**< Command in progress; no error */
CY_FLASH_DRV_OPERATION_STARTED = ( CY_FLASH_ID_INFO + 1ul), /**< Flash operation is successfully initiated */
CY_FLASH_DRV_OPCODE_BUSY = ( CY_FLASH_ID_INFO + 2ul), /**< Flash is under operation */
} cy_en_flashdrv_status_t;
/** \} group_flash_returns */
/** \cond INTERNAL */
/** Command completed with no errors */
#define CY_FLASH_ROMCODE_SUCCESS (0xA0000000UL)
/** Invalid device protection state */
#define CY_FLASH_ROMCODE_INVALID_PROTECTION (0xF0000001UL)
/** Invalid flash page latch address */
#define CY_FLASH_ROMCODE_INVALID_FM_PL (0xF0000003UL)
/** Invalid flash address */
#define CY_FLASH_ROMCODE_INVALID_FLASH_ADDR (0xF0000004UL)
/** Row is write protected */
#define CY_FLASH_ROMCODE_ROW_PROTECTED (0xF0000005UL)
/** Command in progress; no error */
#define CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR (0xA0000009UL)
/** Flash operation is successfully initiated */
#define CY_FLASH_IS_OPERATION_STARTED (0x00000010UL)
/** Flash is under operation */
#define CY_FLASH_IS_BUSY (0x00000040UL)
/** IPC structure is already locked by another process */
#define CY_FLASH_IS_IPC_BUSY (0x00000080UL)
/** Input parameters passed to Flash API are not valid */
#define CY_FLASH_IS_INVALID_INPUT_PARAMETERS (0x00000100UL)
/** Result mask */
#define CY_FLASH_RESULT_MASK (0xFFFFFFFUL)
/** Error shift */
#define CY_FLASH_ERROR_SHIFT (28UL)
/** No error */
#define CY_FLASH_ERROR_NO_ERROR (0xAUL)
#define CY_FLASH_ENTER_WAIT_LOOP 0xFFU
#define CY_FLASH_IPC_CLIENT_ID 2U
/** Semaphore number reserved for flash driver */
#define CY_FLASH_WAIT_SEMA 0UL
/** \endcond */
/**
* \addtogroup group_flash_config_macro Flash configuration
* \addtogroup group_flash_config_macros Flash configuration
* \{
* Specifies the parameter values passed to SROM API
*/
/** SROM API opcode for flash write operation */
#if (CY_CPU_CORTEX_M0P) && (!defined(CY8C622PSVP) && !defined(CY8C622PSVP_DUAL))
#define CY_FLASH_OPCODE_WRITE_ROW (((0x05UL) << 24u) | ((0x01UL) << 8UL))
#else
#define CY_FLASH_OPCODE_WRITE_ROW ((0x05UL) << 24u)
#endif
/** Set SROM API in blocking mode */
#define CY_FLASH_BLOCKING_MODE ((0x01UL) << 8UL)
/** Set SROM API in non blocking mode */
#define CY_FLASH_NON_BLOCKING_MODE (0UL)
/** SROM API opcode for flash write operation */
#define CY_FLASH_OPCODE_WRITE_ROW ((0x05UL) << 24UL)
/** SROM API opcode for flash program operation */
#define CY_FLASH_OPCODE_PROGRAM_ROW ((0x06UL) << 24UL)
/** SROM API opcode for row erase operation */
#define CY_FLASH_OPCODE_ERASE_ROW ((0x1CUL) << 24UL)
/** SROM API opcode for flash checksum operation */
#define CY_FLASH_OPCODE_CHECKSUM ((0x0BUL) << 24u)
#define CY_FLASH_OPCODE_CHECKSUM ((0x0BUL) << 24UL)
/** SROM API opcode for flash hash operation */
#define CY_FLASH_OPCODE_HASH ((0x0DUL) << 24u)
#define CY_FLASH_OPCODE_HASH ((0x0DUL) << 24UL)
/** SROM API flash row shift for flash checksum operation */
#define CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT (8u)
#define CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT (8UL)
/** SROM API flash data size parameter for flash write operation */
#define CY_FLASH_CONFIG_DATASIZE (0x06UL)
/** Data to be programmed to flash is located in SRAM memory region */
#define CY_FLASH_DATA_LOC_SRAM (0x100UL)
/** SROM API flash verification option for flash write operation */
#define CY_FLASH_CONFIG_VERIFICATION_EN ((0x01UL) << 16u)
/** \} group_flash_config_macro */
/** \} group_flash_config_macros */
/**
* \addtogroup group_flash_general_macro Flash general parameters
* \addtogroup group_flash_general_macros Flash general parameters
* \{
* Provides general information about flash and IPC
*/
@ -206,23 +200,40 @@ typedef enum
#define CY_FLASH_NUMBER_ROWS (CY_FLASH_SIZE / CY_FLASH_SIZEOF_ROW)
/** Long words flash row size */
#define CY_FLASH_SIZEOF_ROW_LONG_UNITS (CY_FLASH_SIZEOF_ROW / sizeof(uint32_t))
/** Calculates the flash address for a given row of flash */
#define CY_CALCULATE_FLASH_ADDRESS(rowNum) (CY_FLASH_BASE + ((rowNum) * CY_FLASH_SIZEOF_ROW))
/** IPC channel to be used */
#define CY_FLASH_IPC_STRUCT ((IPC_STRUCT_Type*) &IPC->STRUCT[CY_IPC_CHAN_SYSCALL])
/** IPC notify bit for IPC_STRUCT0 (dedicated to flash operation) */
#define CY_FLASH_IPC_NOTIFY_STRUCT0 (0x1UL)
/** \cond INTERNAL */
#define CY_FLASH_CM4_FLASH_PROXY_ADDR (0x16001101UL)
/** \endcond */
#define CY_FLASH_IPC_NOTIFY_STRUCT0 (0x1UL << CY_IPC_INTR_SYSCALL1)
/** IPC notify interrupt structure number */
#define CY_FLASH_IPC_INTR_CM0_NOTIFY (0x1UL << CY_IPC_INTR_FLASH_NOTIFY)
/** \} group_flash_general_macro */
/** \} group_flash_general_macros */
/** \} group_flash_macro */
/** \} group_flash_macros */
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_flash_enumerated_types
* \{
*/
/** This enum has the return values of the Flash driver */
typedef enum
{
CY_FLASH_DRV_SUCCESS = 0x00UL, /**< Success */
CY_FLASH_DRV_INV_PROT = ( CY_FLASH_ID_ERROR + 0x0UL), /**< Invalid device protection state */
CY_FLASH_DRV_INVALID_FM_PL = ( CY_FLASH_ID_ERROR + 0x1UL), /**< Invalid flash page latch address */
CY_FLASH_DRV_INVALID_FLASH_ADDR = ( CY_FLASH_ID_ERROR + 0x2UL), /**< Invalid flash address */
CY_FLASH_DRV_ROW_PROTECTED = ( CY_FLASH_ID_ERROR + 0x3UL), /**< Row is write protected */
CY_FLASH_DRV_IPC_BUSY = ( CY_FLASH_ID_ERROR + 0x5UL), /**< IPC structure is already locked by another process */
CY_FLASH_DRV_INVALID_INPUT_PARAMETERS = ( CY_FLASH_ID_ERROR + 0x6UL), /**< Input parameters passed to Flash API are not valid */
CY_FLASH_DRV_PL_ROW_COMP_FA = ( CY_FLASH_ID_ERROR + 0x22UL), /**< Comparison between Page Latches and FM row failed */
CY_FLASH_DRV_ERR_UNC = ( CY_FLASH_ID_ERROR + 0xFFUL), /**< Unknown error */
CY_FLASH_DRV_PROGRESS_NO_ERROR = ( CY_FLASH_ID_INFO + 0x0UL), /**< Command in progress; no error */
CY_FLASH_DRV_OPERATION_STARTED = ( CY_FLASH_ID_INFO + 0x1UL), /**< Flash operation is successfully initiated */
CY_FLASH_DRV_OPCODE_BUSY = ( CY_FLASH_ID_INFO + 0x2UL) /**< Flash is under operation */
} cy_en_flashdrv_status_t;
/** \} group_flash_enumerated_types */
/***************************************
* Data Structure definitions
@ -253,17 +264,25 @@ typedef struct
* \addtogroup group_flash_functions
* \{
*/
cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data, cy_stc_flash_context_t* contextPtr);
cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data, cy_stc_flash_context_t* contextPtr);
cy_en_flashdrv_status_t Cy_Flash_IsWriteComplete(const cy_stc_flash_context_t* contextPtr);
cy_en_flashdrv_status_t Cy_Flash_RowChecksum (uint32_t rowNum, cy_stc_flash_context_t* contextPtr, uint32_t* cheksumPtr);
cy_en_flashdrv_status_t Cy_Flash_CalculateHash (const uint32_t* data, uint32 numberOfBytes, cy_stc_flash_context_t* contextPtr, uint32_t* hashPtr);
cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr);
cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data);
cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data);
cy_en_flashdrv_status_t Cy_Flash_IsWriteComplete(void);
cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data);
cy_en_flashdrv_status_t Cy_Flash_IsProgramComplete(void);
cy_en_flashdrv_status_t Cy_Flash_StartErase(uint32_t rowAddr);
cy_en_flashdrv_status_t Cy_Flash_IsEraseComplete(void);
cy_en_flashdrv_status_t Cy_Flash_RowChecksum(uint32_t rowNum, uint32_t* checksumPtr);
cy_en_flashdrv_status_t Cy_Flash_CalculateHash(const uint32_t* data, uint32_t numberOfBytes, uint32_t* hashPtr);
/** \cond INTERNAL */
uint32_t Cy_Flash_BoundsCheck(uint32_t flashAddr);
uint32_t Cy_Flash_PrepeareContext(uint32_t rowAddr, const uint32_t* data, cy_stc_flash_context_t *contextPtr);
cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode);
typedef cy_en_flashdrv_status_t (*Cy_Flash_Proxy)(cy_stc_flash_context_t *context);
typedef cy_en_flashdrv_status_t (*Cy_Flash_Proxy)(cy_stc_flash_context_t *contextPtr);
typedef struct _IPC_MSG
{
uint8_t clientID;
uint8_t pktType;
uint16_t intrRelMask;
} IPC_MSG;
/** \endcond */
/** \} group_flash_functions */

View File

@ -36,9 +36,9 @@ extern "C" {
* Pointer to the pin config structure base address
*
* \return
* void
* Initialization status
*
* \note
* \note
* This function modifies port registers in read-modify-write operations. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -78,7 +78,7 @@ cy_en_gpio_status_t Cy_GPIO_Pin_Init(GPIO_PRT_Type *base, uint32_t pinNum, const
{
status = CY_GPIO_BAD_PARAM;
}
return(status);
}
@ -96,7 +96,7 @@ cy_en_gpio_status_t Cy_GPIO_Pin_Init(GPIO_PRT_Type *base, uint32_t pinNum, const
* Pointer to the pin config structure base address
*
* \return
* void
* Initialization status
*
*******************************************************************************/
cy_en_gpio_status_t Cy_GPIO_Port_Init(GPIO_PRT_Type* base, const cy_stc_gpio_prt_config_t *config)
@ -124,7 +124,7 @@ cy_en_gpio_status_t Cy_GPIO_Port_Init(GPIO_PRT_Type* base, const cy_stc_gpio_prt
{
status = CY_GPIO_BAD_PARAM;
}
return(status);
}

View File

@ -22,21 +22,21 @@
*
* Initialization can be performed either at the port level or by configuring the
* individual pins. For efficient use of code space, port
* configuration should be used in the field. Refer to the product device header files
* configuration should be used in the field. Refer to the product device header files
* for the list of supported ports and pins.
*
* - Single pin configuration is performed by using \ref Cy_GPIO_Pin_FastInit
*
* - Single pin configuration is performed by using \ref Cy_GPIO_Pin_FastInit
* (provide specific values) or \ref Cy_GPIO_Pin_Init (provide a filled
* cy_stc_gpio_pin_config_t structure).
* - An entire port can be configured using \ref Cy_GPIO_Port_Init. Provide a filled
* cy_stc_gpio_prt_config_t structure. The values in the structure are
* - An entire port can be configured using \ref Cy_GPIO_Port_Init. Provide a filled
* cy_stc_gpio_prt_config_t structure. The values in the structure are
* bitfields representing the desired value for each pin in the port.
* - Pin configuration and management is based on the port address and pin number.
* \ref Cy_GPIO_PortToAddr function can optionally be used to calculate the port
* address from the port number at run-time.
*
* Once the pin/port initialization is complete, each pin can be accessed by
* specifying the port (GPIO_PRT_Type) and the pin (0-7) in the provided API
* Once the pin/port initialization is complete, each pin can be accessed by
* specifying the port (GPIO_PRT_Type) and the pin (0-7) in the provided API
* functions.
*
* \section group_gpio_configuration Configuration Considerations
@ -50,32 +50,21 @@
* registers. These functions are not thread safe and care must be taken when
* called by the application.
*
* The whole gpio port can be updated using the port mask by direct port
* register writing. The code example below shows the different ways of
* manipulating Port#1 using the Port output data register,
* the Port output data set register, and the Port output data clear register:
*
* \snippet gpio_sut_01.cydsn/main_cm4.c Cy_GPIO_Snippet
*
*
* \section group_gpio_more_information More Information
*
* Refer to the technical reference manual (TRM) and the device datasheet.
*
* \section group_gpio_MISRA MISRA-C Compliance]
* <table class="doxtable">
* <tr>
* <th>MISRA rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>14.1</td>
* <td>R</td>
* <td>Static Function '' is not used within this translation unit.</td>
* <td></td>
* </tr>
* <tr>
* <td>16.7</td>
* <td>R</td>
* <td>The object addressed by the pointer parameter 'base' is not modified
* and so the pointer could be of type 'pointer to const'.</td>
* <td></td>
* </tr>
* </table>
*
* The gpio driver does not have any specific deviations.
*
* \section group_gpio_changelog Changelog
* <table class="doxtable">
@ -87,7 +76,7 @@
* </tr>
* </table>
*
* \defgroup group_gpio_macro Macro
* \defgroup group_gpio_macros Macros
* \defgroup group_gpio_functions Functions
* \{
* \defgroup group_gpio_functions_init Initialization Functions
@ -110,7 +99,7 @@
extern "C" {
#endif
/** \addtogroup group_gpio_macro
/** \addtogroup group_gpio_macros
* \{
*/
@ -123,7 +112,7 @@ extern "C" {
/** GPIO driver ID */
#define CY_GPIO_ID CY_PDL_DRV_ID(0x16u)
/** \} group_gpio_macro */
/** \} group_gpio_macros */
/***************************************
@ -137,7 +126,7 @@ extern "C" {
/**
* GPIO Driver error codes
*/
typedef enum
typedef enum
{
CY_GPIO_SUCCESS = 0x00u, /**< Returned successful */
CY_GPIO_BAD_PARAM = CY_GPIO_ID | CY_PDL_STATUS_ERROR | 0x01u, /**< Bad parameter was passed */
@ -246,7 +235,7 @@ typedef struct {
***************************************/
/**
* \addtogroup group_gpio_macro
* \addtogroup group_gpio_macros
* \{
*/
@ -366,7 +355,7 @@ typedef struct {
#define CY_SIO_VOH_4_16 (0x07UL) /**< \brief Voh = 4.16 x Reference */
/** \} */
/** \} group_gpio_macro */
/** \} group_gpio_macros */
/***************************************
* Function Prototypes
@ -449,25 +438,30 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetInterruptEdge(GPIO_PRT_Type* base, uint32_t
__STATIC_INLINE void Cy_GPIO_SetFilter(GPIO_PRT_Type* base, uint32_t value);
__STATIC_INLINE uint32_t Cy_GPIO_GetFilter(GPIO_PRT_Type* base);
#if (IOSS_GPIO_GPIO_PORT_NR_0_31 != 0)
#if (IOSS_GPIO_GPIO_PORT_NR_0_31 != 0) || defined (CY_DOXYGEN)
__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause0(void);
#endif /* (IOSS_GPIO_GPIO_PORT_NR_0_31 != 0) */
#if (IOSS_GPIO_GPIO_PORT_NR_32_63 != 0)
#if (IOSS_GPIO_GPIO_PORT_NR_32_63 != 0) || defined (CY_DOXYGEN)
__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause1(void);
#endif /* (IOSS_GPIO_GPIO_PORT_NR_32_63 != 0) */
#if (IOSS_GPIO_GPIO_PORT_NR_64_95 != 0)
#if (IOSS_GPIO_GPIO_PORT_NR_64_95 != 0) || defined (CY_DOXYGEN)
__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause2(void);
#endif /* (IOSS_GPIO_GPIO_PORT_NR_64_95 != 0) */
#if (IOSS_GPIO_GPIO_PORT_NR_96_127 != 0)
#if (IOSS_GPIO_GPIO_PORT_NR_96_127 != 0) || defined (CY_DOXYGEN)
__STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause3(void);
#endif /* (IOSS_GPIO_GPIO_PORT_NR_96_127 != 0) */
/** \} group_gpio_functions_interrupt */
/**
* \addtogroup group_gpio_functions_init
* \{
*/
/*******************************************************************************
* Function Name: Cy_GPIO_Pin_FastInit
****************************************************************************//**
@ -494,7 +488,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause3(void);
* \return
* void
*
* \note
* \note
* This function modifies port registers in read-modify-write operations. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -583,7 +577,7 @@ __STATIC_INLINE void Cy_GPIO_Port_Deinit(GPIO_PRT_Type* base)
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -683,6 +677,12 @@ __STATIC_INLINE GPIO_PRT_Type* Cy_GPIO_PortToAddr(uint32_t portNum)
return (base);
}
/** \} group_gpio_functions_init */
/**
* \addtogroup group_gpio_functions_gpio
* \{
*/
/*******************************************************************************
* Function Name: Cy_GPIO_Read
@ -863,7 +863,7 @@ __STATIC_INLINE void Cy_GPIO_Inv(GPIO_PRT_Type* base, uint32_t pinNum)
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -919,7 +919,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetDrivemode(GPIO_PRT_Type* base, uint32_t pinN
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -973,7 +973,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetVtrip(GPIO_PRT_Type* base, uint32_t pinNum)
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1027,7 +1027,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetSlewRate(GPIO_PRT_Type* base, uint32_t pinNu
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1064,6 +1064,12 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetDriveSel(GPIO_PRT_Type* base, uint32_t pinNu
return (base->CFG_OUT >> (pinNum + CY_GPIO_CFG_OUT_DRIVE_OFFSET)) & CY_GPIO_CFG_OUT_DRIVE_SEL_MASK;
}
/** \} group_gpio_functions_gpio */
/**
* \addtogroup group_gpio_functions_sio
* \{
*/
/*******************************************************************************
* Function Name: Cy_GPIO_SetVregEn
@ -1085,7 +1091,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetDriveSel(GPIO_PRT_Type* base, uint32_t pinNu
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1145,7 +1151,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetVregEn(GPIO_PRT_Type* base, uint32_t pinNum)
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1205,7 +1211,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetIbufMode(GPIO_PRT_Type* base, uint32_t pinNu
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1265,7 +1271,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetVtripSel(GPIO_PRT_Type* base, uint32_t pinNu
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1328,7 +1334,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetVrefSel(GPIO_PRT_Type* base, uint32_t pinNum
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1367,6 +1373,12 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetVohSel(GPIO_PRT_Type* base, uint32_t pinNum)
return (base->CFG_SIO >> (((pinNum & CY_GPIO_SIO_ODD_PIN_MASK) << CY_GPIO_CFG_SIO_OFFSET) + CY_GPIO_VOH_SEL_SHIFT)) & CY_GPIO_VOH_SEL_MASK;
}
/** \} group_gpio_functions_sio */
/**
* \addtogroup group_gpio_functions_interrupt
* \{
*/
/*******************************************************************************
* Function Name: Cy_GPIO_GetInterruptStatus
@ -1438,7 +1450,7 @@ __STATIC_INLINE void Cy_GPIO_ClearInterrupt(GPIO_PRT_Type* base, uint32_t pinNum
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1539,7 +1551,7 @@ __STATIC_INLINE void Cy_GPIO_SetSwInterrupt(GPIO_PRT_Type* base, uint32_t pinNum
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1592,7 +1604,7 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetInterruptEdge(GPIO_PRT_Type* base, uint32_t
* \return
* void
*
* \note
* \note
* This function modifies a port register in a read-modify-write operation. It is
* not thread safe as the resource is shared among multiple pins on a port.
*
@ -1705,8 +1717,9 @@ __STATIC_INLINE uint32_t Cy_GPIO_GetInterruptCause3(void)
#endif
/** \} group_gpio_functions */
/** \} group_gpio_functions_interrupt */
/** \} group_gpio_functions */
#if defined(__cplusplus)
}

View File

@ -0,0 +1,275 @@
/***************************************************************************//**
* \file cy_i2s.c
* \version 2.0
*
* The source code file for the I2S driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_i2s.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* Function Name: Cy_I2S_Init
****************************************************************************//**
*
* Initializes the I2S module in accordance with a configuration structure.
*
* \pre If the I2S module is initialized previously, the \ref Cy_I2S_DeInit()
* must be called before calling this function.
*
* \param base The pointer to the I2S instance address.
* \param config The pointer to a configuration structure.
* \return error / status code. See \ref cy_en_i2s_status_t.
*
*******************************************************************************/
cy_en_i2s_status_t Cy_I2S_Init(I2S_Type * base, cy_stc_i2s_config_t const * config)
{
cy_en_i2s_status_t ret = CY_I2S_BAD_PARAM;
cy_en_i2s_ws_pw_t wsPulseWidth;
uint32_t channels, clockDiv;
cy_en_i2s_len_t channelLength;
if((NULL != base) && (NULL != config))
{
ret = CY_I2S_SUCCESS;
/* Clock setting */
clockDiv = (uint32_t)config->clkDiv - 1U;
CY_ASSERT_L2(CY_I2S_IS_CLK_DIV_VALID(clockDiv));
base->CLOCK_CTL = _VAL2FLD(I2S_CLOCK_CTL_CLOCK_DIV, clockDiv) |
_BOOL2FLD(I2S_CLOCK_CTL_CLOCK_SEL, config->extClk);
/* Tx setting */
if(config->txEnabled)
{
CY_ASSERT_L3(CY_I2S_IS_ALIGNMENT_VALID(config->txAlignment));
CY_ASSERT_L3(CY_I2S_IS_OVHDATA_VALID(config->txOverheadValue));
if((CY_I2S_TDM_MODE_A == config->txAlignment) || (CY_I2S_TDM_MODE_B == config->txAlignment))
{
channels = (uint32_t)config->txChannels - 1UL;
wsPulseWidth = CY_I2S_WS_ONE_CHANNEL_LENGTH;
channelLength = CY_I2S_LEN32;
CY_ASSERT_L2(CY_I2S_IS_CHANNELS_VALID(channels));
CY_ASSERT_L3(CY_I2S_IS_LEN_VALID(config->txWordLength));
}
else
{
channels = 1UL;
wsPulseWidth = config->txWsPulseWidth;
channelLength = config->txChannelLength;
CY_ASSERT_L3(CY_I2S_IS_WSPULSE_VALID(wsPulseWidth));
CY_ASSERT_L3(CY_I2S_IS_CHAN_WORD_VALID(channelLength, config->txWordLength));
}
CY_ASSERT_L2(CY_I2S_IS_TRIG_LEVEL_VALID(config->txFifoTriggerLevel, channels));
base->TX_WATCHDOG = config->txWatchdogValue;
base->TX_CTL = _VAL2FLD(I2S_TX_CTL_I2S_MODE, config->txAlignment) |
_BOOL2FLD(I2S_TX_CTL_B_CLOCK_INV, config->txSdoLatchingTime) |
_VAL2FLD(I2S_TX_CTL_CH_NR, channels) |
_BOOL2FLD(I2S_TX_CTL_MS, config->txMasterMode) |
_VAL2FLD(I2S_TX_CTL_WS_PULSE, wsPulseWidth) |
_BOOL2FLD(I2S_TX_CTL_WD_EN, config->txWatchdogEnable) |
_BOOL2FLD(I2S_TX_CTL_SCKO_POL, config->txSckoInversion) |
_BOOL2FLD(I2S_TX_CTL_SCKI_POL, config->txSckiInversion) |
_VAL2FLD(I2S_TX_CTL_CH_LEN, channelLength) |
_VAL2FLD(I2S_TX_CTL_WORD_LEN, config->txWordLength) |
_VAL2FLD(I2S_TX_CTL_OVHDATA, config->txOverheadValue);
}
/* Rx setting */
if(config->rxEnabled)
{
CY_ASSERT_L3(CY_I2S_IS_ALIGNMENT_VALID(config->rxAlignment));
if((CY_I2S_TDM_MODE_A == config->rxAlignment) || (CY_I2S_TDM_MODE_B == config->rxAlignment))
{
channels = (uint32_t)config->rxChannels - 1UL;
wsPulseWidth = CY_I2S_WS_ONE_CHANNEL_LENGTH;
channelLength = CY_I2S_LEN32;
CY_ASSERT_L2(CY_I2S_IS_CHANNELS_VALID(channels));
CY_ASSERT_L3(CY_I2S_IS_LEN_VALID(config->rxWordLength));
}
else
{
channels = 1UL;
wsPulseWidth = config->rxWsPulseWidth;
channelLength = config->rxChannelLength;
CY_ASSERT_L3(CY_I2S_IS_WSPULSE_VALID(wsPulseWidth));
CY_ASSERT_L3(CY_I2S_IS_CHAN_WORD_VALID(channelLength, config->rxWordLength));
}
CY_ASSERT_L2(CY_I2S_IS_TRIG_LEVEL_VALID(config->rxFifoTriggerLevel, channels));
base->RX_WATCHDOG = config->rxWatchdogValue;
base->RX_CTL = _VAL2FLD(I2S_RX_CTL_I2S_MODE, config->rxAlignment) |
_BOOL2FLD(I2S_RX_CTL_B_CLOCK_INV, config->rxSdiLatchingTime) |
_VAL2FLD(I2S_RX_CTL_CH_NR, channels) |
_BOOL2FLD(I2S_RX_CTL_MS, config->rxMasterMode) |
_VAL2FLD(I2S_RX_CTL_WS_PULSE, wsPulseWidth) |
_BOOL2FLD(I2S_RX_CTL_WD_EN, config->rxWatchdogEnable) |
_BOOL2FLD(I2S_RX_CTL_SCKO_POL, config->rxSckoInversion) |
_BOOL2FLD(I2S_RX_CTL_SCKI_POL, config->rxSckiInversion) |
_VAL2FLD(I2S_RX_CTL_CH_LEN, channelLength) |
_VAL2FLD(I2S_RX_CTL_WORD_LEN, config->rxWordLength) |
_BOOL2FLD(I2S_RX_CTL_BIT_EXTENSION, config->rxSignExtension);
}
/* I2S enable setting */
if(config->txEnabled)
{
base->CTL |= I2S_CTL_TX_ENABLED_Msk;
}
if(config->rxEnabled)
{
base->CTL |= I2S_CTL_RX_ENABLED_Msk;
}
/* FIFO setting */
if(config->txEnabled)
{
base->TX_FIFO_CTL = _VAL2FLD(I2S_TX_FIFO_CTL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
base->TR_CTL |= _BOOL2FLD(I2S_TR_CTL_TX_REQ_EN, config->txDmaTrigger);
}
if(config->rxEnabled)
{
base->RX_FIFO_CTL = _VAL2FLD(I2S_RX_FIFO_CTL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
base->TR_CTL |= _BOOL2FLD(I2S_TR_CTL_RX_REQ_EN, config->rxDmaTrigger);
}
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_I2S_DeInit
****************************************************************************//**
*
* Uninitializes the I2S module (reverts default register values).
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
void Cy_I2S_DeInit(I2S_Type * base)
{
base->INTR_MASK = 0UL; /* Disable interrupts prior to stopping the operation */
base->CMD = 0UL;
base->TR_CTL = 0UL;
base->TX_FIFO_CTL = 0UL;
base->RX_FIFO_CTL = 0UL;
base->CTL = 0UL;
base->TX_CTL = CY_I2S_TX_CTL_DEFAULT;
base->RX_CTL = CY_I2S_RX_CTL_DEFAULT;
base->TX_WATCHDOG = 0UL;
base->RX_WATCHDOG = 0UL;
base->CLOCK_CTL = 0UL;
}
/*******************************************************************************
* Function Name: Cy_I2S_DeepSleepCallback
****************************************************************************//**
*
* This is a callback function that can be used at the application layer to
* manage an I2S operation before entering into/after exiting from the Deep Sleep
* mode.
*
* \param
* callbackParams - A pointer to the callback parameters structure,
* see \ref cy_stc_syspm_callback_params_t.
*
* \return the SysPm callback status \ref cy_en_syspm_status_t.
*
* \note Use the \ref cy_stc_i2s_context_t data type for definition of the
* *context element of the \ref cy_stc_syspm_callback_params_t strusture.
*
*******************************************************************************/
cy_en_syspm_status_t Cy_I2S_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams)
{
cy_en_syspm_status_t ret = CY_SYSPM_SUCCESS;
CY_ASSERT_L1(NULL != callbackParams->context);
I2S_Type * locBase = (I2S_Type*) callbackParams->base;
uint32_t * locInterruptMask = (uint32_t*) &(((cy_stc_i2s_context_t*)(callbackParams->context))->interruptMask);
uint32_t * locState = (uint32_t*) &(((cy_stc_i2s_context_t*)(callbackParams->context))->enableState);
switch(callbackParams->mode)
{
case CY_SYSPM_CHECK_READY:
case CY_SYSPM_CHECK_FAIL:
break;
case CY_SYSPM_BEFORE_TRANSITION:
*locInterruptMask = Cy_I2S_GetInterruptMask(locBase); /* Store I2S interrupts */
Cy_I2S_SetInterruptMask(locBase, 0UL); /* Disable I2S interrupts */
*locState = Cy_I2S_GetCurrentState(locBase); /* Store I2S state */
if(0UL != (*locState & I2S_CMD_TX_START_Msk))
{
Cy_I2S_DisableTx(locBase); /* Stop TX operation */
}
if(0UL != (*locState & I2S_CMD_RX_START_Msk))
{
Cy_I2S_DisableRx(locBase); /* Stop RX operation */
}
/* Unload FIFOs to do not lost any data (if needed) */
break;
case CY_SYSPM_AFTER_TRANSITION:
if(0UL != (*locState & I2S_CMD_RX_START_Msk))
{
Cy_I2S_ClearRxFifo (locBase); /* Clear RX FIFO */
Cy_I2S_EnableRx (locBase); /* Start RX operation */
}
if(0UL != (*locState & I2S_CMD_TX_START_Msk))
{
Cy_I2S_ClearTxFifo (locBase); /* Clear TX FIFO */
Cy_I2S_WriteTxData (locBase, 0UL); /* Fill first TX frame */
Cy_I2S_WriteTxData (locBase, 0UL);
if(0UL != (*locState & I2S_CMD_TX_PAUSE_Msk))
{
Cy_I2S_PauseTx(locBase); /* Restore TX paused state */
}
Cy_I2S_EnableTx(locBase); /* Start TX operation */
}
Cy_I2S_SetInterruptMask (locBase, *locInterruptMask); /* Restore I2S interrupts */
break;
default:
ret = CY_SYSPM_FAIL;
break;
}
return(ret);
}
#ifdef __cplusplus
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,974 @@
/***************************************************************************//**
* \file cy_i2s.h
* \version 2.0
*
* The header file of the I2S driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_i2s Inter-IC Sound (I2S)
* \{
* The I2S driver provides a function API to manage Inter-IC Sound. I2S is used
* to send digital audio streaming data to external I2S devices, such as audio
* codecs or simple DACs. It can also receive digital audio streaming data.
*
* Features:
* * An industry-standard NXP I2S interface
* * Supports master/slave TX/RX operation
* * Programmable Channel/Word Lengths
* * Supports External Clock operation
*
* The I2S bus is an industry standard. The hardware interface was
* developed by Philips Semiconductors (now NXP Semiconductors).
*
* \section group_i2s_configuration_considerations Configuration Considerations
*
* To set up an I2S, provide the configuration parameters in the
* \ref cy_stc_i2s_config_t structure.
*
* For example, for TX configuration, set txEnabled to true, configure
* txDmaTrigger (depending on whether DMA is going to be used or not), set
* extClk (if an external clock is used), provide clkDiv, txMasterMode,
* txAlignment, txChannels (only 2 is supported in I2S and Left Justified modes)
* txSdoLatchingTime (for slave mode only), txChannelLength, txWordLength,
* txWsPulseWidth (for TMD modes only), txWatchdogEnable and txWatchdogValue
* (both for slave mode only, and when the watchdog interrupt will be used),
* either txSckoInversion or txSckiInversion (based on txMasterMode setting),
* txFifoTriggerLevel (when the Trig interrupt will be used) and txOverheadValue
* (only when word length is less than channel length).
* The similar setup is for RX configuration.
*
* To initialize the I2S block, call the \ref Cy_I2S_Init function, providing the
* filled \ref cy_stc_i2s_config_t structure.
* Before starting the transmission, clear the FIFO \ref Cy_I2S_ClearTxFifo, then
* fill the first TX data frame by calling \ref Cy_I2S_WriteTxData once for each
* channel (e.g. twice for I2S mode with only two channels) with zero data. Then
* call the \ref Cy_I2S_EnableTx itself.
* For the reception the sequence is the same except of filling the first data
* frame, just RX FIFO clearing is enough.
*
* For example:
* \snippet i2s/i2s_v2_0_sut_00.cydsn/main_cm4.c Cy_I2S_Snippet
*
* If you use DMA, the DMA channel should be previously configured. I2S interrupts
* (if applicable) can be enabled by calling \ref Cy_I2S_SetInterruptMask.
*
* For example, if the trigger interrupt is used, during operation the ISR
* should call the \ref Cy_I2S_WriteTxData as many times as required for your
* FIFO payload, but not more than FIFO size. Then call \ref Cy_I2S_ClearInterrupt
* with appropriate parameters.
*
* The I2S/Left Justified data formats always contains two data channels.
* They are ordered one-by-one in the FIFOs, left always goes first.
* So in case of mono audio stream transmission, each sample can be put twice
* into the TX FIFO (in this case both channels will sound the same),
* or combined with zeroes: sample1-zero-sample2-zero (in this case only the
* left channel will finally sound, for right-only case zero should go first).
* The TDM frame word order in FIFOs is similar, one-by-one.
*
* If DMA is used and a DMA channel is properly configured - no CPU activity
* (or any application code) is needed for I2S operation.
*
* The I2S frame looks like the next:
* \image html i2s_frame.png
* This is an example for channel length = 32. The similar is for all the rest
* channel lengths, with only limitation: the word length could be less or equal
* to the channel length. See the device Technical Reference Manual (TRM)
* for more details.
*
* \section group_i2s_more_information More Information
* See the the I2S chapter of the device technical reference manual (TRM).
* Also, see I2S_PDL Component datasheet.
*
* \section group_i2s_MISRA MISRA-C Compliance
* The I2S driver has the following specific deviations:
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>11.4</td>
* <td>A</td>
* <td>A cast should not be performed between a pointer to object type and
* a different pointer to object type.</td>
* <td>The function \ref Cy_I2S_DeepSleepCallback is a callback of
* \ref cy_en_syspm_status_t type. The cast operation safety in this
* function becomes the user responsibility because pointer are
* initialized when callback is registered in SysPm driver.</td>
* </tr>
* </table>
*
* \section group_i2s_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* <tr>
* <td>2.0</td>
* <td>The slave operation is added, Left Justified and TDM modes are added</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_i2s_macros Macros
* \defgroup group_i2s_functions Functions
* \defgroup group_i2s_data_structures Data Structures
* \defgroup group_i2s_enums Enumerated types
*/
#if !defined CY_I2S_H
#define CY_I2S_H
#include <stddef.h>
#include <stdbool.h>
#include "syslib/cy_syslib.h"
#include "syspm/cy_syspm.h"
#ifndef CY_IP_MXAUDIOSS
#error "The I2S driver is not supported on this device"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \addtogroup group_i2s_macros
* \{
*/
/** Driver major version */
#define CY_I2S_DRV_VERSION_MAJOR 2
/** Driver minor version */
#define CY_I2S_DRV_VERSION_MINOR 0
/** I2S driver identifier */
#define CY_I2S_ID (CY_PDL_DRV_ID(0x20U))
/**
* \defgroup group_i2s_macros_intrerrupt_masks Interrupt Masks
* \{
*/
/** Bit 0: Less entries in the TX FIFO than specified by Trigger Level. */
#define CY_I2S_INTR_TX_TRIGGER (I2S_INTR_TX_TRIGGER_Msk)
/** Bit 1: TX FIFO is not full. */
#define CY_I2S_INTR_TX_NOT_FULL (I2S_INTR_TX_NOT_FULL_Msk)
/** Bit 4: TX FIFO is empty, i.e. it has 0 entries. */
#define CY_I2S_INTR_TX_EMPTY (I2S_INTR_TX_EMPTY_Msk)
/** Bit 5: Attempt to write to a full TX FIFO. */
#define CY_I2S_INTR_TX_OVERFLOW (I2S_INTR_TX_OVERFLOW_Msk)
/** Bit 6: Attempt to read from an empty TX FIFO.
* This happens when the IP is ready to transfer data and TX_EMPTY is '1'. */
#define CY_I2S_INTR_TX_UNDERFLOW (I2S_INTR_TX_UNDERFLOW_Msk)
/** Bit 8: Tx watchdog event occurs. */
#define CY_I2S_INTR_TX_WD (I2S_INTR_TX_WD_Msk)
/** Bit 16: More entries in the RX FIFO than specified by Trigger Level. */
#define CY_I2S_INTR_RX_TRIGGER (I2S_INTR_RX_TRIGGER_Msk)
/** Bit 18: RX FIFO is not empty. */
#define CY_I2S_INTR_RX_NOT_EMPTY (I2S_INTR_RX_NOT_EMPTY_Msk)
/** Bit 19: RX FIFO is full. */
#define CY_I2S_INTR_RX_FULL (I2S_INTR_RX_FULL_Msk)
/** Bit 21: Attempt to write to a full RX FIFO. */
#define CY_I2S_INTR_RX_OVERFLOW (I2S_INTR_RX_OVERFLOW_Msk)
/** Bit 22: Attempt to read from an empty RX FIFO. */
#define CY_I2S_INTR_RX_UNDERFLOW (I2S_INTR_RX_UNDERFLOW_Msk)
/** Bit 24: Rx watchdog event occurs. */
#define CY_I2S_INTR_RX_WD (I2S_INTR_RX_WD_Msk)
/** \} group_i2s_macros_intrerrupt_masks */
/**
* \defgroup group_i2s_macros_current_state Current State
* \{
*/
/** Transmission is active */
#define CY_I2S_TX_START (I2S_CMD_TX_START_Msk)
/** Transmission is paused */
#define CY_I2S_TX_PAUSE (I2S_CMD_TX_PAUSE_Msk)
/** Reception is active */
#define CY_I2S_RX_START (I2S_CMD_RX_START_Msk)
/** \} group_i2s_macros_current_state */
/** \} group_i2s_macros */
/**
* \addtogroup group_i2s_enums
* \{
*/
/**
* I2S status definitions.
*/
typedef enum
{
CY_I2S_SUCCESS = 0x00UL, /**< Successful. */
CY_I2S_BAD_PARAM = CY_I2S_ID | CY_PDL_STATUS_ERROR | 0x01UL /**< One or more invalid parameters. */
} cy_en_i2s_status_t;
/**
* I2S data alignment.
*/
typedef enum
{
CY_I2S_LEFT_JUSTIFIED = 0U, /**< Left justified. */
CY_I2S_I2S_MODE = 1U, /**< I2S mode. */
CY_I2S_TDM_MODE_A = 2U, /**< TDM mode A. */
CY_I2S_TDM_MODE_B = 3U /**< TDM mode B. */
} cy_en_i2s_alignment_t;
/**
* I2S channel/word length.
*/
typedef enum
{
CY_I2S_LEN8 = 0U, /**< Channel/word length: 8 bit. */
CY_I2S_LEN16 = 1U, /**< Channel/Word length: 16 bit. */
CY_I2S_LEN18 = 2U, /**< Channel/Word length: 18 bit. */
CY_I2S_LEN20 = 3U, /**< Channel/Word length: 20 bit. */
CY_I2S_LEN24 = 4U, /**< Channel/Word length: 24 bit. */
CY_I2S_LEN32 = 5U /**< Channel/Word length: 32 bit. */
} cy_en_i2s_len_t;
/**
* I2S TX overhead value.
*/
typedef enum
{
CY_I2S_OVHDATA_ZERO = 0U, /**< Fill overhead bits by zeroes. */
CY_I2S_OVHDATA_ONE = 1U, /**< Fill overhead bits by ones. */
} cy_en_i2s_overhead_t;
/**
* I2S WS pulse width.
*/
typedef enum
{
CY_I2S_WS_ONE_SCK_CYCLE = 0U, /**< WS pulse width is one SCK cycle. */
CY_I2S_WS_ONE_CHANNEL_LENGTH = 1U, /**< WS pulse width is one channel length. */
} cy_en_i2s_ws_pw_t;
/** \} group_i2s_enums */
/**
* \addtogroup group_i2s_data_structures
* \{
*/
/**
* I2S initialization configuration.
*/
typedef struct
{
bool txEnabled; /**< Enables the I2S TX component: 'false': disabled. 'true': enabled. */
bool rxEnabled; /**< Enables the I2S RX component: 'false': disabled. 'true': enabled. */
bool txDmaTrigger; /**< 'false': TX DMA trigger disable, 'true': TX DMA trigger enable. */
bool rxDmaTrigger; /**< 'false': RX DMA trigger disable, 'true': RX DMA trigger enable. */
uint8_t clkDiv; /**< CLK_SEL divider: 1: Bypass, 2: 1/2, 3: 1/3, ..., 64: 1/64. */
bool extClk; /**< 'false': internal clock, 'true': external clock. */
bool txMasterMode; /**< 'false': TX in slave mode, 'true': TX in master mode. */
cy_en_i2s_alignment_t txAlignment; /**< TX data alignment, see: #cy_en_i2s_alignment_t. */
cy_en_i2s_ws_pw_t txWsPulseWidth; /**< TX Word Select pulse width.
The value of this parameter is ignored in TDM modes - the WS pulse
width is always "one channel length" is these modes. */
bool txWatchdogEnable; /**< 'false': TX watchdog disabled, 'true': TX watchdog enabled. */
uint32_t txWatchdogValue; /**< TX watchdog counter value (32 bit). */
bool txSdoLatchingTime; /**< 'false': SDO bit starts at falling edge (accordingly to the I2S
Standard, if txSckoInversion is false),
'true': SDO bit starts at rising edge which goes before the above
mentioned falling edge, i.e. the SDO signal is advanced by 0.5 SCK
period (if txSckoInversion is false).
If txSckoInversion is true - the rising/falling edges just swaps
in above explanations.
Effective only in slave mode, must be false in master mode.*/
bool txSckoInversion; /**< TX SCKO polarity:
'false': When transmitter is in master mode, serial data is
transmitted off the falling bit clock edge (accordingly to
the I2S Standard);
'true': When transmitter is in master mode, serial data is
transmitted off the rising bit clock edge.
Effective only in master mode. */
bool txSckiInversion; /**< TX SCKI polarity:
'false': When transmitter is in slave mode, serial data is
transmitted off the falling bit clock edge (accordingly to
the I2S Standard);
'true': When transmitter is in slave mode, serial data is
transmitted off the rising bit clock edge.
Effective only in slave mode. */
uint8_t txChannels; /**< Number of TX channels, valid range is 1...8 for TDM modes.
In the I2S and Left Justified modes the value of this parameter is
ignored - the real number of channels is always 2 in these modes. */
cy_en_i2s_len_t txChannelLength; /**< TX channel length, see #cy_en_i2s_len_t,
the value of this parameter is ignored in TDM modes, the real
channel length is 32 bit in these modes. */
cy_en_i2s_len_t txWordLength; /**< TX word length, see #cy_en_i2s_len_t,
must be less or equal to txChannelLength. */
cy_en_i2s_overhead_t txOverheadValue; /**< TX overhead bits value
when the word length is less than the channel length. */
uint8_t txFifoTriggerLevel; /**< TX FIFO interrupt trigger level (0, 1, ..., 255). */
bool rxMasterMode; /**< 'false': RX in slave mode, 'true': RX in master mode. */
cy_en_i2s_alignment_t rxAlignment; /**< RX data alignment, see: #cy_en_i2s_alignment_t. */
cy_en_i2s_ws_pw_t rxWsPulseWidth; /**< RX Word Select pulse width.
The value of this parameter is ignored in TDM modes - the WS pulse
width is always "one channel length" is these modes. */
bool rxWatchdogEnable; /**< 'false': RX watchdog disabled, 'true': RX watchdog enabled. */
uint32_t rxWatchdogValue; /**< RX watchdog counter value (32 bit). */
bool rxSdiLatchingTime; /**< 'false': SDI bit starts at falling edge (accordingly to the I2S
Standard if rxSckoInversion is false),
'true': SDI bit starts at rising edge which goes after the above
mentioned falling edge, i.e. the SDI signal is delayed by 0.5 SCK
period (if rxSckoInversion is false).
If rxSckoInversion is true - the rising/falling edges just swaps
in above explanations.
Effective only in master mode, must be false in slave mode. */
bool rxSckoInversion; /**< RX SCKO polarity:
'false': When receiver is in master mode, serial data is
captured by the rising bit clock edge (accordingly to the
I2S Standard);
'true': When receiver is in master mode, serial data is
captured by the falling bit clock edge.
Effective only in master mode. */
bool rxSckiInversion; /**< RX SCKI polarity:
'false': When receiver is in slave mode, serial data is
captured by the rising bit clock edge (accordingly to the
I2S Standard);
'true': When receiver is in slave mode, serial data is
captured by the falling bit clock edge.
Effective only in slave mode. */
uint8_t rxChannels; /**< Number of RX channels, valid range is 1...8 for TDM modes.
In the I2S and Left Justified modes the value of this parameter is
ignored - the real number of channels is always 2 in these modes. */
cy_en_i2s_len_t rxChannelLength; /**< RX channel length, see #cy_en_i2s_len_t,
the value of this parameter is ignored in TDM modes, the real
channel length is 32 bit in these modes. */
cy_en_i2s_len_t rxWordLength; /**< RX word length, see #cy_en_i2s_len_t,
must be less or equal to rxChannelLength. */
bool rxSignExtension; /**< RX value sign extension (when the word length is less than 32 bits),
'false': all MSB are filled by zeroes,
'true': all MSB are filled by the original sign bit value. */
uint8_t rxFifoTriggerLevel; /**< RX FIFO interrupt trigger level
(0, 1, ..., (255 - (number of channels))). */
} cy_stc_i2s_config_t;
/**
* I2S backup structure type to be used for SysPm callback
* \ref Cy_I2S_DeepSleepCallback context definition.
*
* \cond Also can be used for another purposes to store the current TX/RX
* operation state and interrupt settings - the factors that are usually
* being changed on the fly. \endcond
*/
typedef struct
{
uint32_t enableState; /**< Stores I2S state */
uint32_t interruptMask; /**< Stores I2S interrupt mask */
} cy_stc_i2s_context_t;
/** \} group_i2s_data_structures */
/** \cond INTERNAL */
/******************************************************************************
* Local definitions
*******************************************************************************/
#define CY_I2S_INTR_MASK (CY_I2S_INTR_TX_TRIGGER | \
CY_I2S_INTR_TX_NOT_FULL | \
CY_I2S_INTR_TX_EMPTY | \
CY_I2S_INTR_TX_OVERFLOW | \
CY_I2S_INTR_TX_UNDERFLOW | \
CY_I2S_INTR_TX_WD | \
CY_I2S_INTR_RX_TRIGGER | \
CY_I2S_INTR_RX_NOT_EMPTY | \
CY_I2S_INTR_RX_FULL | \
CY_I2S_INTR_RX_OVERFLOW | \
CY_I2S_INTR_RX_UNDERFLOW | \
CY_I2S_INTR_RX_WD)
/* Non-zero default values */
#define CY_I2S_TX_CTL_CH_NR_DEFAULT (0x1U)
#define CY_I2S_TX_CTL_I2S_MODE_DEFAULT (0x2U)
#define CY_I2S_TX_CTL_WS_PULSE_DEFAULT (0x1U)
#define CY_I2S_TX_CTL_CH_LEN_DEFAULT (0x4U)
#define CY_I2S_TX_CTL_WORD_LEN_DEFAULT (0x4U)
#define CY_I2S_TX_CTL_DEFAULT (_VAL2FLD(I2S_TX_CTL_CH_NR, CY_I2S_TX_CTL_CH_NR_DEFAULT) | \
_VAL2FLD(I2S_TX_CTL_I2S_MODE, CY_I2S_TX_CTL_I2S_MODE_DEFAULT) | \
_VAL2FLD(I2S_TX_CTL_WS_PULSE, CY_I2S_TX_CTL_WS_PULSE_DEFAULT) | \
_VAL2FLD(I2S_TX_CTL_CH_LEN, CY_I2S_TX_CTL_CH_LEN_DEFAULT) | \
_VAL2FLD(I2S_TX_CTL_WORD_LEN, CY_I2S_TX_CTL_WORD_LEN_DEFAULT))
#define CY_I2S_RX_CTL_CH_NR_DEFAULT (0x1U)
#define CY_I2S_RX_CTL_I2S_MODE_DEFAULT (0x2U)
#define CY_I2S_RX_CTL_WS_PULSE_DEFAULT (0x1U)
#define CY_I2S_RX_CTL_CH_LEN_DEFAULT (0x4U)
#define CY_I2S_RX_CTL_WORD_LEN_DEFAULT (0x4U)
#define CY_I2S_RX_CTL_DEFAULT (_VAL2FLD(I2S_RX_CTL_CH_NR, CY_I2S_RX_CTL_CH_NR_DEFAULT) | \
_VAL2FLD(I2S_RX_CTL_I2S_MODE, CY_I2S_RX_CTL_I2S_MODE_DEFAULT) | \
_VAL2FLD(I2S_RX_CTL_WS_PULSE, CY_I2S_RX_CTL_WS_PULSE_DEFAULT) | \
_VAL2FLD(I2S_RX_CTL_CH_LEN, CY_I2S_RX_CTL_CH_LEN_DEFAULT) | \
_VAL2FLD(I2S_RX_CTL_WORD_LEN, CY_I2S_RX_CTL_WORD_LEN_DEFAULT))
/* Macros for conditions used by CY_ASSERT calls */
#define CY_I2S_IS_ALIGNMENT_VALID(alignment) ((CY_I2S_LEFT_JUSTIFIED == (alignment)) || \
(CY_I2S_I2S_MODE == (alignment)) || \
(CY_I2S_TDM_MODE_A == (alignment)) || \
(CY_I2S_TDM_MODE_B == (alignment)))
#define CY_I2S_IS_LEN_VALID(length) ((CY_I2S_LEN8 == (length)) || \
(CY_I2S_LEN16 == (length)) || \
(CY_I2S_LEN18 == (length)) || \
(CY_I2S_LEN20 == (length)) || \
(CY_I2S_LEN24 == (length)) || \
(CY_I2S_LEN32 == (length)))
#define CY_I2S_IS_OVHDATA_VALID(overhead) ((CY_I2S_OVHDATA_ZERO == (overhead)) || \
(CY_I2S_OVHDATA_ONE == (overhead)))
#define CY_I2S_IS_WSPULSE_VALID(wsPulse) ((CY_I2S_WS_ONE_SCK_CYCLE == (wsPulse)) || \
(CY_I2S_WS_ONE_CHANNEL_LENGTH == (wsPulse)))
#define CY_I2S_IS_CLK_DIV_VALID(clkDiv) ((clkDiv) <= 63U)
#define CY_I2S_IS_CHANNELS_VALID(channels) ((channels) <= 7UL)
#define CY_I2S_IS_INTR_MASK_VALID(interrupt) (0UL == ((interrupt) & ((uint32_t) ~CY_I2S_INTR_MASK)))
#define CY_I2S_IS_CHAN_WORD_VALID(channel, word) ((CY_I2S_IS_LEN_VALID(channel)) && \
(CY_I2S_IS_LEN_VALID(word)) && \
((channel) >= (word)))
#define CY_I2S_IS_TRIG_LEVEL_VALID(trigLevel, channels) ((trigLevel) <= (255U - (channels)))
/** \endcond */
/**
* \addtogroup group_i2s_functions
* \{
*/
cy_en_i2s_status_t Cy_I2S_Init(I2S_Type * base, cy_stc_i2s_config_t const * config);
void Cy_I2S_DeInit(I2S_Type * base);
cy_en_syspm_status_t Cy_I2S_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams);
__STATIC_INLINE void Cy_I2S_EnableTx(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_PauseTx(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_ResumeTx(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_DisableTx(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_EnableRx(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_DisableRx(I2S_Type * base);
__STATIC_INLINE uint32_t Cy_I2S_GetCurrentState(I2S_Type const * base);
__STATIC_INLINE void Cy_I2S_ClearTxFifo(I2S_Type * base);
__STATIC_INLINE uint32_t Cy_I2S_GetNumInTxFifo(I2S_Type const * base);
__STATIC_INLINE void Cy_I2S_WriteTxData(I2S_Type * base, uint32_t data);
__STATIC_INLINE uint8_t Cy_I2S_GetTxReadPointer(I2S_Type const * base);
__STATIC_INLINE uint8_t Cy_I2S_GetTxWritePointer(I2S_Type const * base);
__STATIC_INLINE void Cy_I2S_FreezeTxFifo(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_UnfreezeTxFifo(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_ClearRxFifo(I2S_Type * base);
__STATIC_INLINE uint32_t Cy_I2S_GetNumInRxFifo(I2S_Type const * base);
__STATIC_INLINE uint32_t Cy_I2S_ReadRxData(I2S_Type const * base);
__STATIC_INLINE uint32_t Cy_I2S_ReadRxDataSilent(I2S_Type const * base);
__STATIC_INLINE uint8_t Cy_I2S_GetRxReadPointer(I2S_Type const * base);
__STATIC_INLINE uint8_t Cy_I2S_GetRxWritePointer(I2S_Type const * base);
__STATIC_INLINE void Cy_I2S_FreezeRxFifo(I2S_Type * base);
__STATIC_INLINE void Cy_I2S_UnfreezeRxFifo(I2S_Type * base);
__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatus(I2S_Type const * base);
__STATIC_INLINE void Cy_I2S_ClearInterrupt(I2S_Type * base, uint32_t interrupt);
__STATIC_INLINE void Cy_I2S_SetInterrupt(I2S_Type * base, uint32_t interrupt);
__STATIC_INLINE uint32_t Cy_I2S_GetInterruptMask(I2S_Type const * base);
__STATIC_INLINE void Cy_I2S_SetInterruptMask(I2S_Type * base, uint32_t interrupt);
__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatusMasked(I2S_Type const * base);
/*******************************************************************************
* Function Name: Cy_I2S_EnableTx
****************************************************************************//**
*
* Starts an I2S transmission. Interrupts enabling (by the
* \ref Cy_I2S_SetInterruptMask) is required after this function call, in case
* if any I2S interrupts are used in the application.
*
* \pre Cy_I2S_Init() must be called before.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_EnableTx(I2S_Type * base)
{
base->CMD |= I2S_CMD_TX_START_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_PauseTx
****************************************************************************//**
*
* Pauses an I2S transmission.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_PauseTx(I2S_Type * base)
{
base->CMD |= I2S_CMD_TX_PAUSE_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_ResumeTx
****************************************************************************//**
*
* Resumes an I2S transmission.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_ResumeTx(I2S_Type * base)
{
base->CMD &= (uint32_t) ~I2S_CMD_TX_PAUSE_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_DisableTx
****************************************************************************//**
*
* Stops an I2S transmission.
*
* \pre TX interrupts disabling (by the \ref Cy_I2S_SetInterruptMask) is required
* prior to this function call, in case if any TX I2S interrupts are used.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_DisableTx(I2S_Type * base)
{
base->CMD &= (uint32_t) ~I2S_CMD_TX_START_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_EnableRx
****************************************************************************//**
*
* Starts an I2S reception. Interrupts enabling (by the
* \ref Cy_I2S_SetInterruptMask) is required after this function call, in case
* if any I2S interrupts are used in the application.
*
* \pre \ref Cy_I2S_Init() must be called before.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_EnableRx(I2S_Type * base)
{
base->CMD |= I2S_CMD_RX_START_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_DisableRx
****************************************************************************//**
*
* Stops an I2S reception.
*
* \pre RX interrupts disabling (by the \ref Cy_I2S_SetInterruptMask) is required
* prior to this function call, in case if any RX I2S interrupts are used.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_DisableRx(I2S_Type * base)
{
base->CMD &= (uint32_t) ~I2S_CMD_RX_START_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetCurrentState
****************************************************************************//**
*
* Returns the current I2S state (TX/RX running/paused/stopped).
*
* \param base The pointer to the I2S instance address.
* \return The current state \ref group_i2s_macros_current_state.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_GetCurrentState(I2S_Type const * base)
{
return (base->CMD & (I2S_CMD_TX_START_Msk | I2S_CMD_TX_PAUSE_Msk | I2S_CMD_RX_START_Msk));
}
/*******************************************************************************
* Function Name: Cy_I2S_ClearTxFifo
****************************************************************************//**
*
* Clears TX FIFO (resets the Read/Write FIFO pointers).
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_ClearTxFifo(I2S_Type * base)
{
base->TX_FIFO_CTL |= I2S_TX_FIFO_CTL_CLEAR_Msk;
base->TX_FIFO_CTL &= (uint32_t) ~I2S_TX_FIFO_CTL_CLEAR_Msk;
(void) base->TX_FIFO_CTL;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetNumInTxFifo
****************************************************************************//**
*
* Gets the number of used words in the TX FIFO.
*
* \param base The pointer to the I2S instance address.
* \return The current number of used words in rge TX FIFO.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_GetNumInTxFifo(I2S_Type const * base)
{
return (_FLD2VAL(I2S_TX_FIFO_STATUS_USED, base->TX_FIFO_STATUS));
}
/*******************************************************************************
* Function Name: Cy_I2S_WriteTxData
****************************************************************************//**
*
* Writes data to the TX FIFO. Increases the TX FIFO level.
*
* \param base The pointer to the I2S instance address.
* \param data Data to be written to the TX FIFO.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_WriteTxData(I2S_Type * base, uint32_t data)
{
base->TX_FIFO_WR = data;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetTxReadPointer
****************************************************************************//**
*
* Gets the TX FIFO Read pointer. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
* \return The current TX Read pointer value.
*
*******************************************************************************/
__STATIC_INLINE uint8_t Cy_I2S_GetTxReadPointer(I2S_Type const * base)
{
return ((uint8_t) _FLD2VAL(I2S_TX_FIFO_STATUS_RD_PTR, base->TX_FIFO_STATUS));
}
/*******************************************************************************
* Function Name: Cy_I2S_GetTxWritePointer
****************************************************************************//**
*
* Gets the TX FIFO Write pointer. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
* \return The current TX Write pointer value.
*
*******************************************************************************/
__STATIC_INLINE uint8_t Cy_I2S_GetTxWritePointer(I2S_Type const * base)
{
return ((uint8_t) _FLD2VAL(I2S_TX_FIFO_STATUS_WR_PTR, base->TX_FIFO_STATUS));
}
/*******************************************************************************
* Function Name: Cy_I2S_FreezeTxFifo
****************************************************************************//**
*
* Freezes the TX FIFO. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_FreezeTxFifo(I2S_Type * base)
{
base->TX_FIFO_CTL |= I2S_TX_FIFO_CTL_FREEZE_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_UnfreezeTxFifo
****************************************************************************//**
*
* Unfreezes the TX FIFO. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_UnfreezeTxFifo(I2S_Type * base)
{
base->TX_FIFO_CTL &= (uint32_t) ~I2S_TX_FIFO_CTL_FREEZE_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_ClearRxFifo
****************************************************************************//**
*
* Clears the RX FIFO (resets the Read/Write FIFO pointers).
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_ClearRxFifo(I2S_Type * base)
{
base->RX_FIFO_CTL |= I2S_RX_FIFO_CTL_CLEAR_Msk;
base->RX_FIFO_CTL &= (uint32_t) ~I2S_RX_FIFO_CTL_CLEAR_Msk;
(void) base->RX_FIFO_CTL;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetNumInRxFifo
****************************************************************************//**
*
* Gets the number of used words in the RX FIFO.
*
* \param base The pointer to the I2S instance address.
* \return The current number of used words in rge RX FIFO.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_GetNumInRxFifo(I2S_Type const * base)
{
return (_FLD2VAL(I2S_RX_FIFO_STATUS_USED, base->RX_FIFO_STATUS));
}
/*******************************************************************************
* Function Name: Cy_I2S_ReadRxData
****************************************************************************//**
*
* Reads data from the RX FIFO. Decreases the TX FIFO level.
*
* \param base The pointer to the I2S instance address.
* \return The read data.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_ReadRxData(I2S_Type const * base)
{
return (base->RX_FIFO_RD);
}
/*******************************************************************************
* Function Name: Cy_I2S_ReadRxDataSilent
****************************************************************************//**
*
* Reads data from the RX FIFO without updating the RX FIFO read pointer.
* This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
* \return The read data.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_ReadRxDataSilent(I2S_Type const * base)
{
return (base->RX_FIFO_RD_SILENT);
}
/*******************************************************************************
* Function Name: Cy_I2S_GetRxReadPointer
****************************************************************************//**
*
* Gets the RX FIFO Read pointer. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
* \return The current RX Read pointer value.
*
*******************************************************************************/
__STATIC_INLINE uint8_t Cy_I2S_GetRxReadPointer(I2S_Type const * base)
{
return ((uint8_t) _FLD2VAL(I2S_RX_FIFO_STATUS_RD_PTR, base->RX_FIFO_STATUS));
}
/*******************************************************************************
* Function Name: Cy_I2S_GetRxWritePointer
****************************************************************************//**
*
* Gets the RX FIFO Write pointer. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
* \return The current RX Write pointer value.
*
*******************************************************************************/
__STATIC_INLINE uint8_t Cy_I2S_GetRxWritePointer(I2S_Type const * base)
{
return ((uint8_t) _FLD2VAL(I2S_RX_FIFO_STATUS_WR_PTR, base->RX_FIFO_STATUS));
}
/*******************************************************************************
* Function Name: Cy_I2S_FreezeRxFifo
****************************************************************************//**
*
* Freezes the RX FIFO. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_FreezeRxFifo(I2S_Type * base)
{
base->RX_FIFO_CTL |= I2S_RX_FIFO_CTL_FREEZE_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_UnfreezeRxFifo
****************************************************************************//**
*
* Unfreezes the RX FIFO. This function is rather for debug purposes.
*
* \param base The pointer to the I2S instance address.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_UnfreezeRxFifo(I2S_Type * base)
{
base->RX_FIFO_CTL &= (uint32_t) ~I2S_RX_FIFO_CTL_FREEZE_Msk;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetInterruptStatus
****************************************************************************//**
*
* Gets an interrupt status (returns a content of the INTR register).
*
* \param base The pointer to the I2S instance address.
* \return The interrupt bit mask \ref group_i2s_macros_intrerrupt_masks.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatus(I2S_Type const * base)
{
return (base->INTR);
}
/*******************************************************************************
* Function Name: Cy_I2S_ClearInterrupt
****************************************************************************//**
*
* Clears one or more interrupt factors (sets the INTR register).
*
* \param base The pointer to the I2S instance address.
* \param interrupt Interrupt bit mask \ref group_i2s_macros_intrerrupt_masks.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_ClearInterrupt(I2S_Type * base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_I2S_IS_INTR_MASK_VALID(interrupt));
base->INTR = interrupt;
(void) base->INTR;
}
/*******************************************************************************
* Function Name: Cy_I2S_SetInterrupt
****************************************************************************//**
*
* Sets one or more interrupt factors (sets the INTR_SET register).
*
* \param base The pointer to the I2S instance address.
* \param interrupt Interrupt bit mask \ref group_i2s_macros_intrerrupt_masks.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_SetInterrupt(I2S_Type * base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_I2S_IS_INTR_MASK_VALID(interrupt));
base->INTR_SET = interrupt;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetInterruptMask
****************************************************************************//**
*
* Returns the interrupt mask (a content of the INTR_MASK register).
*
* \param base The pointer to the I2S instance address.
* \return The interrupt bit mask \ref group_i2s_macros_intrerrupt_masks.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_GetInterruptMask(I2S_Type const * base)
{
return (base->INTR_MASK);
}
/*******************************************************************************
* Function Name: Cy_I2S_SetInterruptMask
****************************************************************************//**
*
* Sets one or more interrupt factor masks (the INTR_MASK register).
*
* \param base The pointer to the I2S instance address.
* \param interrupt Interrupt bit mask \ref group_i2s_macros_intrerrupt_masks.
*
*******************************************************************************/
__STATIC_INLINE void Cy_I2S_SetInterruptMask(I2S_Type * base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_I2S_IS_INTR_MASK_VALID(interrupt));
base->INTR_MASK = interrupt;
}
/*******************************************************************************
* Function Name: Cy_I2S_GetInterruptStatusMasked
****************************************************************************//**
*
* Returns the interrupt status masked (a content of the INTR_MASKED register).
*
* \param base The pointer to the I2S instance address.
* \return The interrupt bit mask(s) \ref group_i2s_macros_intrerrupt_masks.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_I2S_GetInterruptStatusMasked(I2S_Type const * base)
{
return (base->INTR_MASKED);
}
/** \} group_i2s_functions */
#ifdef __cplusplus
}
#endif
#endif /* CY_I2S_H */
/** \} group_i2s */
/* [] END OF FILE */

View File

@ -0,0 +1,143 @@
/***************************************************************************//**
* \file cy_ipc_config.c
* \version 1.10
*
* Description:
* This C file is not intended to be part of the IPC driver. It is the code
* required to configure the device specific IPC channels for semaphores
* and pipes.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "flash/cy_flash.h"
#include "ipc/cy_ipc_drv.h"
#include "ipc/cy_ipc_pipe.h"
#include "ipc/cy_ipc_sema.h"
#include "sysint/cy_sysint.h"
#include "cy_ipc_config.h"
static void Cy_Flash_NotifyHandler(uint32_t * msgPtr);
/* Create an array of endpoint structures */
static cy_stc_ipc_pipe_ep_t cy_ipc_pipe_sysEpArray[CY_IPC_MAX_ENDPOINTS];
#define CY_CYPIPE_DEFAULT_CONFIG \
{\
/* .ep0ConfigData */ {\
/* .ipcNotifierNumber */ CY_IPC_INTR_CYPIPE_EP0,\
/* .ipcNotifierPriority */ CY_IPC_INTR_CYPIPE_PRIOR_EP0,\
/* .ipcNotifierMuxNumber */ CY_IPC_INTR_CYPIPE_MUX_EP0,\
/* .epAddress */ CY_IPC_EP_CYPIPE_CM0_ADDR,\
/* .epConfig */ CY_IPC_CYPIPE_CONFIG_EP0\
},\
/* .ep1ConfigData */ {\
/* .ipcNotifierNumber */ CY_IPC_INTR_CYPIPE_EP1,\
/* .ipcNotifierPriority */ CY_IPC_INTR_CYPIPE_PRIOR_EP1,\
/* .ipcNotifierMuxNumber */ 0u,\
/* .epAddress */ CY_IPC_EP_CYPIPE_CM4_ADDR,\
/* .epConfig */ CY_IPC_CYPIPE_CONFIG_EP1\
},\
/* .endpointClientsCount */ CY_IPC_CYPIPE_CLIENT_CNT,\
/* .endpointsCallbacksArray */ cy_ipc_pipe_sysCbArray,\
/* .userPipeIsrHandler */ &Cy_IPC_SystemPipeIsr\
}
/*******************************************************************************
* Function Name: Cy_IPC_SystemSemaInit
****************************************************************************//**
*
* Initializes the system semaphores.
*
*******************************************************************************/
void Cy_IPC_SystemSemaInit(void)
{
/* Create array used for semaphores */
#if !(CY_CPU_CORTEX_M0P)
(void) Cy_IPC_Sema_Init(CY_IPC_CHAN_SEMA, 0ul, NULL);
#else
static uint32_t ipcSemaArray[CY_IPC_SEMA_COUNT / CY_IPC_SEMA_PER_WORD];
(void) Cy_IPC_Sema_Init(CY_IPC_CHAN_SEMA, CY_IPC_SEMA_COUNT, ipcSemaArray);
#endif
}
/*******************************************************************************
* Function Name: Cy_IPC_SystemPipeInit
****************************************************************************//**
*
* Initializes the system pipes. The system pipes are used by BLE.
* \note The function should be called on all CPUs.
*
*******************************************************************************/
void Cy_IPC_SystemPipeInit(void)
{
uint32_t intr;
intr = Cy_SysLib_EnterCriticalSection();
static cy_ipc_pipe_callback_ptr_t cy_ipc_pipe_sysCbArray[CY_IPC_CYPIPE_CLIENT_CNT];
static const cy_stc_ipc_pipe_config_t systemPipeConfig = CY_CYPIPE_DEFAULT_CONFIG;
Cy_IPC_Pipe_Config(cy_ipc_pipe_sysEpArray);
Cy_IPC_Pipe_Init(&systemPipeConfig);
(void)Cy_IPC_Pipe_RegisterCallback(CY_IPC_EP_CYPIPE_ADDR, &Cy_Flash_NotifyHandler, (uint32_t)CY_FLASH_IPC_CLIENT_ID);
Cy_SysLib_ExitCriticalSection(intr);
}
/*******************************************************************************
* Function Name: Cy_IPC_SystemPipeIsr
****************************************************************************//**
*
* This is the interrupt service routine for the system pipe.
*
*******************************************************************************/
void Cy_IPC_SystemPipeIsr(void)
{
Cy_IPC_Pipe_ExecCallback(&cy_ipc_pipe_sysEpArray[CY_IPC_EP_CYPIPE_ADDR]);
}
/*******************************************************************************
* Function Name: Cy_Flash_NotifyHandler
****************************************************************************//**
*
* This is the interrupt service routine for the pipe notifications.
*
*******************************************************************************/
#if defined (__ICCARM__)
__ramfunc
#else
CY_SECTION(".cy_ramfunc")
#endif
static void Cy_Flash_NotifyHandler(uint32_t * msgPtr)
{
uint32_t intr;
IPC_MSG *ipcMsgPtr = (IPC_MSG *)msgPtr;
if (CY_FLASH_ENTER_WAIT_LOOP == ipcMsgPtr->pktType)
{
intr = Cy_SysLib_EnterCriticalSection();
/* Notification to the Flash driver to start the current operation */
(void) Cy_IPC_Sema_Set(CY_FLASH_WAIT_SEMA, true);
/* Notification to me about the end of the operation */
while (CY_IPC_SEMA_STATUS_LOCKED == Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA))
{
}
Cy_SysLib_ExitCriticalSection(intr);
}
}
/* [] END OF FILE */

View File

@ -0,0 +1,137 @@
/***************************************************************************//**
* \file cy_ipc_config.h
* \version 1.10
*
* \brief
* This header file is not intended to be part of the IPC driver since it defines
* a device specific configuration for the IPC channels and pipes.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#ifndef CY_IPC_CONFIG_H
#define CY_IPC_CONFIG_H
/* IPC Resources */
#define CY_IPC_CHANNELS (uint32_t)(CPUSS_IPC_IPC_NR)
#define CY_IPC_INTERRUPTS (uint32_t)(CPUSS_IPC_IPC_IRQ_NR)
/* IPC channel definitions */
#define CY_IPC_CHAN_SYSCALL_CM0 (0u) /* System calls for the CM0 processor */
#define CY_IPC_CHAN_SYSCALL_CM4 (1u) /* System calls for the 1st non-CM0 processor */
#if (CY_CPU_CORTEX_M0P)
#define CY_IPC_CHAN_SYSCALL CY_IPC_CHAN_SYSCALL_CM0
#define Cy_IPC_SystemPipeIsr NvicMux1_IRQHandler
#else
#define CY_IPC_CHAN_SYSCALL CY_IPC_CHAN_SYSCALL_CM4
#define Cy_IPC_SystemPipeIsr cpuss_interrupts_ipc_4_IRQHandler
#endif /* (CY_CPU_CORTEX_M0P) */
#define CY_IPC_CHAN_SYSCALL_DAP (uint32_t)(2u) /**< System calls for the DAP */
#define CY_IPC_CHAN_CRYPTO (uint32_t)(3u) /**< IPC data channel for the Crypto */
#define CY_IPC_CHAN_SEMA (uint32_t)(4u) /**< IPC data channel for the Semaphores */
#define CY_IPC_CHAN_CYPIPE_EP0 (uint32_t)(5u) /**< IPC data channel for CYPIPE EP0 */
#define CY_IPC_CHAN_CYPIPE_EP1 (uint32_t)(6u) /**< IPC data channel for CYPIPE EP1 */
/* IPC Notify interrupts definitions */
#define CY_IPC_INTR_SYSCALL1 (uint32_t)(0u)
#define CY_IPC_INTR_CRYPTO_SRV (uint32_t)(1u) /**< IPC interrupt structure for the Crypto server */
#define CY_IPC_INTR_CRYPTO_CLI (uint32_t)(2u) /**< IPC interrupt structure for the Crypto client */
#define CY_IPC_INTR_SPARE (uint32_t)(7u)
/* IPC Semaphores allocation
This will allow 128 (4*32) semaphores */
#define CY_IPC_SEMA_COUNT (uint32_t)(128u)
/* System IPC Notify Masks */
#define CY_IPC_SEMA_NOTIFY_MASK (uint32_t)(0x0001ul << CY_IPC_CHAN_SEMA)
/* System IPC channel release Masks */
#define CY_IPC_SEM_RELEASE_MASK (uint32_t)(0x0001ul << CY_IPC_CHAN_SEMA)
/* IPC Pipe definitions */
#define CY_IPC_MAX_ENDPOINTS (uint32_t)(8u)
/*******************************************************************************
** CY_PIPE default configuration
*******************************************************************************/
#define CY_IPC_CYPIPE_CLIENT_CNT (uint32_t)(8u)
#define CY_IPC_USRPIPE_CLIENT_CNT (uint32_t)(8u)
#if (CY_CPU_CORTEX_M0P)
#define CY_IPC_EP_CYPIPE_ADDR CY_IPC_EP_CYPIPE_CM0_ADDR
#else
#define CY_IPC_EP_CYPIPE_ADDR CY_IPC_EP_CYPIPE_CM4_ADDR
#endif /* (CY_CPU_CORTEX_M0P) */
#define CY_IPC_INTR_CYPIPE_MUX_EP0 (uint32_t)(1u) /* IPC CYPRESS PIPE */
#define CY_IPC_INTR_CYPIPE_EP0 (uint32_t)(3u) /* Notifier EP0 */
#define CY_IPC_INTR_CYPIPE_PRIOR_EP0 (uint32_t)(1u) /* Notifier Priority */
#define CY_IPC_INTR_CYPIPE_EP1 (uint32_t)(4u) /* Notifier EP1 */
#define CY_IPC_INTR_CYPIPE_PRIOR_EP1 (uint32_t)(1u) /* Notifier Priority */
#define CY_IPC_CYPIPE_CHAN_MASK_EP0 (uint32_t)(0x0001ul << CY_IPC_CHAN_CYPIPE_EP0)
#define CY_IPC_CYPIPE_CHAN_MASK_EP1 (uint32_t)(0x0001ul << CY_IPC_CHAN_CYPIPE_EP1)
/* Endpoint indexes in the pipe array */
#define CY_IPC_EP_CYPIPE_CM0_ADDR (uint32_t)(0u)
#define CY_IPC_EP_CYPIPE_CM4_ADDR (uint32_t)(1u)
/******************************************************************************/
/*
* The System pipe configuration defines the IPC channel number, interrupt
* number, and the pipe interrupt mask for the endpoint.
*
* The format of the endPoint configuration
* Bits[31:16] Interrupt Mask
* Bits[15:8 ] IPC interrupt
* Bits[ 7:0 ] IPC channel
*/
/* System Pipe addresses */
/* CyPipe defines */
#define CY_IPC_CYPIPE_CONFIG_EP0 (uint32_t)( (CY_IPC_CYPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \
| (CY_IPC_INTR_CYPIPE_EP0 << CY_IPC_PIPE_CFG_INTR_Pos) \
| CY_IPC_CHAN_CYPIPE_EP0)
#define CY_IPC_CYPIPE_CONFIG_EP1 (uint32_t)( (CY_IPC_CYPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos) \
| (CY_IPC_INTR_CYPIPE_EP1 << CY_IPC_PIPE_CFG_INTR_Pos) \
| CY_IPC_CHAN_CYPIPE_EP1)
#define CY_IPC_CYPIPE_INTR_MASK (uint32_t)( CY_IPC_CYPIPE_CHAN_MASK_EP0 | CY_IPC_CYPIPE_CHAN_MASK_EP1 )
/******************************************************************************/
#define CY_IPC_CHAN_USRPIPE_CM0 (uint32_t)(8u)
#define CY_IPC_CHAN_USRPIPE_CM4 (uint32_t)(9u)
#define CY_IPC_INTR_USRPIPE_CM0 (uint32_t)(8u)
#define CY_IPC_INTR_USRPIPE_CM4 (uint32_t)(9u)
#define CY_IPC_EP_USRPIPE_ADDR_EP0 (uint32_t)(2u)
#define CY_IPC_EP_USRPIPE_ADDR_EP1 (uint32_t)(3u)
#ifdef __cplusplus
extern "C" {
#endif
void Cy_IPC_SystemSemaInit(void);
void Cy_IPC_SystemPipeInit(void);
void Cy_IPC_SystemPipeIsr(void);
#ifdef __cplusplus
}
#endif
#endif /* CY_IPC_CONFIG_H */
/* [] END OF FILE */

View File

@ -0,0 +1,172 @@
/***************************************************************************//**
* \file cy_ipc_drv.c
* \version 1.10
*
* \breif
* IPC Driver - This source file contains the low-level driver code for
* the IPC hardware.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_ipc_drv.h"
/*******************************************************************************
* Function Name: Cy_IPC_Drv_LockRelease
****************************************************************************//**
*
* The function is used to release an IPC channel from the locked state.
* The function also has a way to specify through a parameter which IPC
* interrupts must be notified during the release event.
*
* This function is internal and should not be called directly by user software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param releaseEventIntr
* Bit encoded list of IPC interrupt lines that are triggered by a release event.
*
* \return Status of the operation
* \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC channel
* was released.
* \retval CY_IPC_DRV_ERROR: The IPC channel was not acquired before the
* function call.
*
*******************************************************************************/
#if defined (__ICCARM__)
__ramfunc
#else
CY_SECTION(".cy_ramfunc")
#endif
cy_en_ipcdrv_status_t Cy_IPC_Drv_LockRelease (IPC_STRUCT_Type* base, uint32_t releaseEventIntr)
{
cy_en_ipcdrv_status_t retStatus;
/* Check to make sure the IPC is Acquired */
if( Cy_IPC_Drv_IsLockAcquired(base) )
{
/* The IPC was acquired, release the IPC channel */
Cy_IPC_Drv_ReleaseNotify(base, releaseEventIntr);
retStatus = CY_IPC_DRV_SUCCESS;
}
else /* The IPC channel was already released (not acquired) */
{
retStatus = CY_IPC_DRV_ERROR;
}
return (retStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_SendMsgWord
****************************************************************************//**
*
* This function is used to send a 32-bit word message through an IPC channel.
* The function also has an associated notification field that will let the
* message notify one or multiple IPC interrupts. The IPC channel is locked and
* remains locked after the function returns. The receiver of the message should
* release the channel.
*
* This function is internal and should not be called directly by user software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param notifyEventIntr
* Bit encoded list of IPC interrupt lines that are triggered by a notification.
*
* \param message
* The message word that is the data placed in the IPC data register.
*
* \return Status of the operation:
* \retval CY_IPC_DRV_SUCCESS: The send operation was successful.
* \retval CY_IPC_DRV_ERROR: The IPC channel is unavailable because it is already locked.
*
*******************************************************************************/
cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgWord (IPC_STRUCT_Type* base, uint32_t notifyEventIntr, uint32_t message)
{
cy_en_ipcdrv_status_t retStatus;
if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire(base) )
{
/* If the channel was acquired, send the message. */
Cy_IPC_Drv_WriteDataValue(base, message);
Cy_IPC_Drv_AcquireNotify(base, notifyEventIntr);
retStatus = CY_IPC_DRV_SUCCESS;
}
else
{
/* Channel was already acquired, return Error */
retStatus = CY_IPC_DRV_ERROR;
}
return (retStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ReadMsgWord
****************************************************************************//**
*
* This function is used to read a 32-bit word message through an IPC channel.
* This function assumes that the channel is locked (for a valid message).
* If the channel is not locked, the message is invalid. The user must call
* Cy_IPC_Drv_Release() function after reading the message to release the
* IPC channel.
*
* This function is internal and should not be called directly by user software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param message
* A variable where the read data is copied.
*
* \return Status of the operation
* \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC
* was acquired.
* \retval CY_IPC_DRV_ERROR: The function encountered an error because the IPC
* channel was already in a released state, meaning the data
* may be invalid.
*
*******************************************************************************/
cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgWord (IPC_STRUCT_Type const * base, uint32_t * message)
{
cy_en_ipcdrv_status_t retStatus;
CY_ASSERT_L1(NULL != message);
if ( Cy_IPC_Drv_IsLockAcquired(base) )
{
/* The channel is locked; message is valid. */
*message = Cy_IPC_Drv_ReadDataValue(base);
retStatus = CY_IPC_DRV_SUCCESS;
}
else
{
/* The channel is not locked so channel is invalid. */
retStatus = CY_IPC_DRV_ERROR;
}
return(retStatus);
}
/* [] END OF FILE */

View File

@ -0,0 +1,900 @@
/***************************************************************************//**
* \file cy_ipc_drv.h
* \version 1.10
*
* Provides an API declaration of the IPC driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#ifndef CY_IPC_DRV_H
#define CY_IPC_DRV_H
/**
* \defgroup group_ipc Inter Process Communication (IPC)
* \{
* The inter-processor communication (IPC) driver provides a safe and reliable
* method to transfer data between CPUs. Hardware locking ensures that only one
* device can acquire and transfer data at a time so no data is lost or
* overwritten by asynchronous processes or CPUs.
*
* There are three parts to the API:
* - Driver-level (DRV) API - used internally by Semaphore and Pipe levels
* - Pipe-level (PIPE) API - establishes a communication channel between
* processors
* - Semaphore-level (SEMA) API - enables users to set and clear flags to
* synchronize operations.
*
* Firmware does not need to use the DRV API. It can implement IPC functionality
* entirely with the PIPE and SEMA APIs.
*
* \note "Warning[Ta023]: Call to a non __ramfunc function." - The warning may
* appear during the build process while using IAR IDE. The reason - some
* functions in RAM memory that use the __ramfunc keyword, may invoke
* functions located in the ROM memory. You can ignore this warning or
* disable it by adding the --diag_suppress=Ta023 option to the compiler.
*
* \section group_ipc_background Background
*
* IPC is implemented in hardware as a collection of individual communication
* channels, each with a set of 32-bit registers. The IPC design implements a set
* of interrupts that enable each processor to notify the other that data is
* available, or has been processed. There is also a locking mechanism that
* allows only one CPU to gain access at a time.
*
* The Driver-level API manages each channel's registers to implement IPC
* functionality. For information on the IPC registers, see the IPC chapter of
* the Technical Reference Manual (TRM).
*
* At the hardware level, communication is a five-step process.
* -# The sending processor acquires a channel
* -# It puts data into the channel
* -# The sender generates a notify event (interrupt)
* -# The receiving processor identifies the sender and retrieves the data
* -# The receiving processor generates a release event (interrupt)
*
* \image html ipc_driver.png
*
* These transactions are handled transparently by the DRV-level API. Use the
* PIPE and SEMA layers of the API to implement communication in your application.
* The data transferred is limited to a single 32-bit value. As implemented by
* the PIPE API, that value is a pointer to a data structure of arbitrary size
* and complexity.
*
* \section group_ipc_overview Overview
*
* The Pipe is the key element in the PDL design. A pipe is typically a
* full-duplex communication channel between CPU cores. A pipe allows a single
* conduit to transfer messages or data to and from multiple processes or CPUs.
*
* A pipe has two endpoints, one on each core. Each endpoint contains a dedicated
* IPC channel and an interrupt. IPC channels 0-7 and IPC interrupts 0-7 are
* reserved for system use.
*
* The pipe also contains the number of clients it supports, and for each client
* a callback function. So the pipe can service a number of clients, each with a
* separate callback function, on either endpoint. The number of clients a pipe
* supports is the sum of each endpoint's clients.
*
* This design enables any number of processes on the sending core to put
* arbitrary data into a single pipe. The first element of that data is the
* client ID of the client that should handle the data.
*
* An interrupt notifies the receiving core that data is available. The receiving
* core parses the data to identify the client, and then dispatches the event to
* the appropriate client via the client callback function. An interrupt notifies
* the sending core that the receiver is finished. In this way a single pipe can
* manage arbitrary data transfers between cores with data flowing in either
* direction.
*
* \image html ipc_ints.png
*
* The application can use semaphores to control access to shared resources, as
* required by the application's logic.
*
* The PDL provides two specific files that set up default IPC functionality.
* They are cy_ipc_config.h and cy_ipc_config.c. You can modify these files based
* on the requirements of your design. If you use PSoC Creator as a development
* environment, it will not overwrite your changes when you generate the
* application or build your code.
*
* \section group_ipc_pipe_layer PIPE layer
*
* A pipe is a communication channel between two endpoints. PSoC 6 devices support
* 16 IPC channels, and 16 IPC interrupts, each numbered 0-15. IPC Channels 0-7
* and IPC interrupts 0-7 are reserved for system use. Channels 8-15 and
* interrupts 8-15 are available for application use.
*
* A full duplex pipe uses two IPC channels, one per endpoint. Each endpoint
* specifies all the information required to process a message (either sent or
* received). Each endpoint is configured to use an IPC channel, and an IPC
* interrupt. Common practice is to use the interrupt with the same number as
* the IPC channel. However, IPC Interrupts are not directly associated with the
* IPC channels, so any channel can use any interrupt. Any IPC channel can
* trigger 0, 1 or all the IPC interrupts at once, depending on the Notify or
* Release masks used.
*
* It is also possible to set up a one-directional pipe, using a single IPC
* channel. In this design one processor is always the sender, and the other is
* always the receiver. However, there are still two endpoints.
*
* A pipe supports an arbitrary number of clients with an array of callback
* functions, one per client. The client ID is the index number into the array
* for the client. After a pipe is configured and initialized, the application
* calls Cy_IPC_Pipe_RegisterCallback() once per client to register each client's
* callback function. Multiple clients can use the same callback function. The
* endpoints in a pipe share the callback array.
*
* Use Cy_IPC_Pipe_SendMessage() to send data. You specify both the "to" and
* "from" endpoints, and a callback function to be used when the data transfer is
* complete. The data is a 32-bit void pointer. The data pointed to is arbitrary,
* and can be an array, a structure, or a location in memory. The only limitation
* is that the first element of the data must be a 32-bit unsigned word containing
* a client ID number. The ID number is the index into the callback array.
*
* When a message is sent, the receiving endpoint's interrupt handler is called.
* The ISR can perform any task required by the design. However, as part of its
* function it calls \ref Cy_IPC_Pipe_ExecCallback. This function retrieves the
* client ID from the data and calls the associated callback function.
* The user-supplied callback function handles the data in whatever way is
* appropriate based on the application logic.
*
* After the callback function is returned by the receiver, it invokes the release
* callback function defined by the sender of the message.
*
* \section group_ipc_sema_layer SEMA Layer
*
* A semaphore is a flag the application uses to control access to a shared
* resource. The SEMA-level API uses an IPC channel to implement
* semaphores. Startup code sets up a default semaphore system. The
* default system creates an array of 128 semaphores (four 32-bit values).
* Semaphores 0-15 are reserved for system use. See
* Configuration Considerations - SEMA.
*
* Functions are available to initialize the semaphore system, to set or
* clear a semaphore, or to get the semaphore's current status. Application
* logic uses SEMA functions to relate a particular semaphore to a particular
* shared resource, and set, clear, or check the flag when accessing the
* shared resource.
*
* \section group_ipc_configuration_cypipe Configuration Considerations - CYPIPE
*
* There are none. The cy_ipc_config files set up the required CYPIPE for system
* use. Do not modify the CYPIPE. It uses IPC channels 5 and 6 to implement full
* duplex communication between cores. On the CM0+ the notify interrupt is
* assigned to NVIC IRQn 27. See System Interrupt (SysInt) for background.
*
* \section group_ipc_configuration_sema Configuration Considerations - SEMA
*
* Startup code calls Cy_IPC_SystemSemaInit (in cy_ipc_config.c) to set up
* semaphore functionality. This function calls the PDL init function
* Cy_IPC_Sema_Init() with default values. By default the semaphore system
* uses IPC channel 4, and creates 128 semaphores. Do <b>not</b> change the IPC
* channel. You can change the number of semaphores.
*
* To change the number of semaphores, modify this line of code in cy_ipc_config.h.
*
* \code
* #define CY_IPC_SEMA_COUNT (uint32_t)(128u)
* \endcode
*
* The file cy_ipc_config.c declares array ipcSemaArray to hold the semaphore
* flags based on the size defined for this symbol. Use increments of 32. You
* must have at least 32 semaphores. Semaphores 0-15 are reserved for
* system use. Your application can use semaphores greater than 15.
*
* \section group_ipc_more_information More Information
*
* See the technical reference manual(TRM) for more information on the IPC.
*
* \section group_ipc_MISRA MISRA-C Compliance
*
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th style="width: 50%;">Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>10.3</td>
* <td>R</td>
* <td>The value of a complex expression of integer type shall be cast
* only to a type of the same signedness that is no wider than the underlying
* type of the expression.</td>
* <td>The cast from integer to enumeration value is used to calculate
* the interrupt vector source from the integer number of the IPC interrupt
* structure, so there is no way to avoid this cast.</td>
* </tr>
* <tr>
* <td>11.4</td>
* <td>A</td>
* <td>A cast should not be performed between a pointer to the void to a
* pointer to the object type.</td>
* <td>The cast from the void to pointer and vice versa is used to transmit
* data via the \ref group_ipc channel by exchanging the pointer. We
* exchange only one pointer, so there is no way to avoid this cast.</td>
* </tr>
* </table>
*
* \defgroup group_ipc_drv IPC driver layer (IPC_DRV)
* \{
* The functions of this layer are used in the higher IPC levels
* (Semaphores and Pipes).
* Users should not call any of these IPC functions directly.
*
* \defgroup group_ipc_macros Macros
* Macro definitions are used in the driver
*
* \defgroup group_ipc_functions Functions
* Functions are used in the driver
*
* \defgroup group_ipc_data_structures Data Structures
* Data structures are used in the driver
*
* \defgroup group_ipc_enums Enumerated Types
* Enumerations are used in the driver
* \}
*
* \defgroup group_ipc_sema IPC semaphores layer (IPC_SEMA)
* \defgroup group_ipc_pipe IPC pipes layer (IPC_PIPE)
*
*/
/******************************************************************************/
/* Include files */
/******************************************************************************/
#include "syslib/cy_syslib.h"
#include "cy_device_headers.h"
#include "cy_ipc_config.h"
#include <stddef.h>
/**
* \addtogroup group_ipc_macros
* \{
*/
/** Driver major version */
#define CY_IPC_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_IPC_DRV_VERSION_MINOR 10
/** Defines a value to indicate that no notification events are needed */
#define CY_IPC_NO_NOTIFICATION (uint32_t)(0x00000000ul)
/* Error Code constants */
#define CY_IPC_ID CY_PDL_DRV_ID(0x22u) /**< Software PDL driver ID for IPC */
/** Return prefix for IPC driver function status codes */
#define CY_IPC_ID_INFO (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_INFO )
/** Return prefix for IPC driver function warning return values */
#define CY_IPC_ID_WARNING (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_WARNING)
/** Return prefix for IPC driver function error return values */
#define CY_IPC_ID_ERROR (uint32_t)( CY_IPC_ID | CY_PDL_STATUS_ERROR)
/** Converts the IPC interrupt channel number to interrupt vector */
#define CY_IPC_INTR_NUM_TO_VECT(x) ((int32_t)cpuss_interrupts_ipc_0_IRQn + (x))
/** \} group_ipc_macros */
/* end of definition in device.h */
/**
* \addtogroup group_ipc_enums
* \{
*/
/**
* This is a list of ENUMs used for function return status.
*/
typedef enum
{
/** Function was successfully executed */
CY_IPC_DRV_SUCCESS = (0x00u),
/** Function was not executed due to an error.
Typical conditions for the error explained
in the function description */
CY_IPC_DRV_ERROR = ( CY_IPC_ID_ERROR + 1ul),
} cy_en_ipcdrv_status_t;
/** \} group_ipc_enums */
#ifdef __cplusplus
extern "C" {
#endif
/** \cond INTERNAL */
__STATIC_INLINE void Cy_IPC_Drv_WriteDataValue (IPC_STRUCT_Type* base, uint32_t dataValue);
__STATIC_INLINE uint32_t Cy_IPC_Drv_ReadDataValue (IPC_STRUCT_Type const * base);
__STATIC_INLINE void Cy_IPC_Drv_ReleaseNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr);
__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractAcquireMask (uint32_t intMask);
__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractReleaseMask (uint32_t intMask);
/** \endcond */
/**
* \addtogroup group_ipc_functions
* \{
*/
__STATIC_INLINE IPC_STRUCT_Type* Cy_IPC_Drv_GetIpcBaseAddress (uint32_t ipcIndex);
__STATIC_INLINE IPC_INTR_STRUCT_Type* Cy_IPC_Drv_GetIntrBaseAddr (uint32_t ipcIntrIndex);
__STATIC_INLINE void Cy_IPC_Drv_AcquireNotify (IPC_STRUCT_Type * base, uint32_t notifyEventIntr);
__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_LockAcquire (IPC_STRUCT_Type const * base);
cy_en_ipcdrv_status_t Cy_IPC_Drv_LockRelease (IPC_STRUCT_Type * base, uint32_t releaseEventIntr);
__STATIC_INLINE bool Cy_IPC_Drv_IsLockAcquired (IPC_STRUCT_Type const * base);
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetLockStatus (IPC_STRUCT_Type const * base);
cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgWord (IPC_STRUCT_Type * base, uint32_t notifyEventIntr, uint32_t message);
cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgWord (IPC_STRUCT_Type const * base, uint32_t * message);
__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgPtr (IPC_STRUCT_Type* base, uint32_t notifyEventIntr, void const * msgPtr);
__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgPtr (IPC_STRUCT_Type const * base, void ** msgPtr);
__STATIC_INLINE void Cy_IPC_Drv_SetInterruptMask (IPC_INTR_STRUCT_Type * base,
uint32_t ipcReleaseMask, uint32_t ipcNotifyMask);
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptMask (IPC_INTR_STRUCT_Type const * base);
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatusMasked (IPC_INTR_STRUCT_Type const * base);
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatus (IPC_INTR_STRUCT_Type const * base);
__STATIC_INLINE void Cy_IPC_Drv_SetInterrupt (IPC_INTR_STRUCT_Type * base,
uint32_t ipcReleaseMask, uint32_t ipcNotifyMask);
__STATIC_INLINE void Cy_IPC_Drv_ClearInterrupt (IPC_INTR_STRUCT_Type * base,
uint32_t ipcReleaseMask, uint32_t ipcNotifyMask);
/*******************************************************************************
* Function Name: Cy_IPC_Drv_GetIpcBaseAddress
****************************************************************************//**
*
* This function takes an IPC channel index as a parameter and returns the base
* address the IPC registers corresponding to the IPC channel.
*
* This function is internal and should not be called directly by user
* software.
*
* \note The user is responsible for ensuring that ipcIndex does not exceed the
* limits.
*
* \param ipcIndex
* Represents the number of IPC structure. This is converted to the base address of
* the IPC channel registers.
*
* \return
* Returns a pointer to the base of the IPC registers.
*
*******************************************************************************/
__STATIC_INLINE IPC_STRUCT_Type* Cy_IPC_Drv_GetIpcBaseAddress (uint32_t ipcIndex)
{
CY_ASSERT_L1((uint32_t)CY_IPC_CHANNELS > ipcIndex);
return ( (IPC_STRUCT_Type*) ( &IPC->STRUCT[ipcIndex] ) );
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_GetIntrBaseAddr
****************************************************************************//**
*
* This function takes an IPC interrupt structure index and returns the base
* address of the IPC interrupt registers corresponding to the IPC Interrupt.
*
* This function is internal and should not be called directly by user
* software.
*
* \note The user is responsible for ensuring that ipcIntrIndex does not exceed the
* limits.
*
* \param ipcIntrIndex
* Represents the number of IPC interrupt structure. This is converted to the
* base address of the IPC interrupt registers.
*
* \return
* Returns a pointer to the base of the IPC interrupt registers.
*
*******************************************************************************/
__STATIC_INLINE IPC_INTR_STRUCT_Type* Cy_IPC_Drv_GetIntrBaseAddr (uint32_t ipcIntrIndex)
{
CY_ASSERT_L1((uint32_t)CY_IPC_INTERRUPTS > ipcIntrIndex);
return ( (IPC_INTR_STRUCT_Type*) ( &IPC->INTR_STRUCT[ipcIntrIndex] ) );
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_SetInterruptMask
****************************************************************************//**
*
* This function is used to set the interrupt mask for an IPC Interrupt.
* The mask sets release or acquire notification events for all IPC channels.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This is a handle to the IPC interrupt. This handle can be calculated from the
* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr.
*
* \param ipcReleaseMask
* An encoded list of all IPC channels that can trigger the interrupt on a
* release event.
*
* \param ipcNotifyMask
* An encoded list of all IPC channels that can trigger the interrupt on a
* notify event.
*
*******************************************************************************/
__STATIC_INLINE void Cy_IPC_Drv_SetInterruptMask (IPC_INTR_STRUCT_Type* base,
uint32_t ipcReleaseMask, uint32_t ipcNotifyMask)
{
CY_ASSERT_L1(0ul == (ipcNotifyMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk)));
CY_ASSERT_L1(0ul == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk)));
base->INTR_MASK = _VAL2FLD( IPC_INTR_STRUCT_INTR_MASK_NOTIFY, ipcNotifyMask) |
_VAL2FLD( IPC_INTR_STRUCT_INTR_MASK_RELEASE, ipcReleaseMask);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_GetInterruptMask
****************************************************************************//**
*
* This function is used to read the interrupt mask.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This is a handle to the IPC interrupt. This handle can be calculated from
* the IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr.
*
* \return
* The return value is encoded as follows
* <table>
* <tr><th>Interrupt sources <th>Value
* <tr><td>Ipc_PORTX_RELEASE <td>Xth bit set
* <tr><td>Ipc_PORTX_NOTIFY <td>X+16th bit set
* </table>
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptMask(IPC_INTR_STRUCT_Type const * base)
{
return (base->INTR_MASK);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_GetInterruptStatusMasked
****************************************************************************//**
*
* This function is used to read the active unmasked interrupt. This function
* can be used in the interrupt service routine to find which source triggered
* the interrupt.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This is a handle to the IPC interrupt. This handle can be calculated from the
* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr.
*
* \return
* The return value is encoded as follows
* <table>
* <tr><th>Interrupt sources <th>Value
* <tr><td>Ipc_PORTX_RELEASE <td>Xth bit set
* <tr><td>Ipc_PORTX_NOTIFY <td>X+16th bit set
* </table>
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatusMasked (IPC_INTR_STRUCT_Type const * base)
{
return (base->INTR_MASKED);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_GetInterruptStatus
****************************************************************************//**
*
* This function is used to read the pending interrupts. Note that this read is
* an unmasked read of the interrupt status. Interrupt sources read as active by
* this function would generate interrupts only if they were not masked.
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This is a handle to the IPC interrupt. This handle can be calculated from the
* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr.
*
* \return
* The return value is encoded as follows
* <table>
* <tr><th>Interrupt sources <th>Value
* <tr><td>Ipc_PORTX_RELEASE <td>Xth bit set
* <tr><td>Ipc_PORTX_NOTIFY <td>X+16th bit set
* </table>
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetInterruptStatus(IPC_INTR_STRUCT_Type const * base)
{
return (base->INTR);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_SetInterrupt
****************************************************************************//**
*
* This function is used to set the interrupt source. This function can be used
* to activate interrupts through software.
* \note That interrupt sources set using this interrupt would generate interrupts
* only if they are not masked.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This is a handle to the IPC interrupt. This handle can be calculated from the
* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr.
*
* \param ipcReleaseMask
* An encoded list of all IPC channels that can trigger the interrupt on a
* release event.
*
* \param ipcNotifyMask
* An encoded list of all IPC channels that can trigger the interrupt on a
* notify event.
*
*******************************************************************************/
__STATIC_INLINE void Cy_IPC_Drv_SetInterrupt(IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcNotifyMask)
{
CY_ASSERT_L1(0ul == (ipcNotifyMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk)));
CY_ASSERT_L1(0ul == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk)));
base->INTR_SET = _VAL2FLD( IPC_INTR_STRUCT_INTR_NOTIFY, ipcNotifyMask ) |
_VAL2FLD( IPC_INTR_STRUCT_INTR_RELEASE, ipcReleaseMask );
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ClearInterrupt
****************************************************************************//**
*
* This function is used to clear the interrupt source. Use this function to clear
* a pending interrupt source in the interrupt status.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This is a handle to the IPC interrupt. This handle can be calculated from the
* IPC interrupt number using \ref Cy_IPC_Drv_GetIntrBaseAddr.
*
* \param ipcReleaseMask
* An encoded list of all IPC channels that can trigger the interrupt on a
* release event.
*
* \param ipcNotifyMask
* An encoded list of all IPC channels that can trigger the interrupt on a
* notify event.
*
*******************************************************************************/
__STATIC_INLINE void Cy_IPC_Drv_ClearInterrupt(IPC_INTR_STRUCT_Type* base, uint32_t ipcReleaseMask, uint32_t ipcNotifyMask)
{
CY_ASSERT_L1(0ul == (ipcNotifyMask & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk)));
CY_ASSERT_L1(0ul == (ipcReleaseMask & ~(uint32_t)(IPC_STRUCT_RELEASE_INTR_RELEASE_Msk)));
base->INTR = _VAL2FLD(IPC_INTR_STRUCT_INTR_NOTIFY, ipcNotifyMask) |
_VAL2FLD(IPC_INTR_STRUCT_INTR_RELEASE, ipcReleaseMask);
(void)base->INTR; /* Read the register to flush the cache */
}
/** \} group_ipc_functions */
/** \} group_ipc */
/*******************************************************************************
* Function Name: Cy_IPC_Drv_AcquireNotify
****************************************************************************//**
*
* The function generates a notify event by IPC interrupt structures.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param notifyEventIntr
* Bit encoded list of IPC interrupt structures that are triggered
* by a notification. Bit number correspond to number of the IPC interrupt
* structure.
*
*******************************************************************************/
__STATIC_INLINE void Cy_IPC_Drv_AcquireNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr)
{
CY_ASSERT_L1(0ul == (notifyEventIntr & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk)));
base->NOTIFY = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, notifyEventIntr);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ReleaseNotify
****************************************************************************//**
*
* The function generates a notify event to an IPC interrupt structure.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param notifyEventIntr
* Bit encoded list of IPC interrupt lines that are triggered by a notification.
*
*******************************************************************************/
__STATIC_INLINE void Cy_IPC_Drv_ReleaseNotify (IPC_STRUCT_Type* base, uint32_t notifyEventIntr)
{
CY_ASSERT_L1(0ul == (notifyEventIntr & ~(uint32_t)(IPC_STRUCT_NOTIFY_INTR_NOTIFY_Msk)));
base->RELEASE = _VAL2FLD(IPC_INTR_STRUCT_INTR_RELEASE, notifyEventIntr);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_WriteDataValue
****************************************************************************//**
*
* The function writes a value to the DATA register of the IPC channel.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param dataValue
* Value to be written.
*
*******************************************************************************/
__STATIC_INLINE void Cy_IPC_Drv_WriteDataValue (IPC_STRUCT_Type* base, uint32_t dataValue)
{
base->DATA = dataValue;
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ReadDataValue
****************************************************************************//**
*
* The function reads a value from the DATA register of the IPC channel.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \return
* Value from DATA register.
*
*******************************************************************************/
#if defined (__ICCARM__)
__ramfunc
#else
CY_SECTION(".cy_ramfunc")
#endif
__STATIC_INLINE uint32_t Cy_IPC_Drv_ReadDataValue (IPC_STRUCT_Type const * base)
{
return (base->DATA);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_IsLockAcquired
****************************************************************************//**
*
* The function is used to test the status of an IPC channel. The function
* tells the reader if the IPC channel was in the locked or released state.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \return
* Status for the function:
* true: The IPC channel is in the Locked state.
* false: The IPC channel is in the Released state.
*
*******************************************************************************/
__STATIC_INLINE bool Cy_IPC_Drv_IsLockAcquired (IPC_STRUCT_Type const * base)
{
return ( 0u != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, base->LOCK_STATUS) );
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_GetLockStatus
****************************************************************************//**
*
* The function is used to get the status of an IPC channel.
*
* This function is internal and should not be called directly by user
* software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \return
* Value from LOCK_STATUS register.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_IPC_Drv_GetLockStatus (IPC_STRUCT_Type const * base)
{
return (base->LOCK_STATUS);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ExtractAcquireMask
****************************************************************************//**
*
* The function extracts an Acquire mask part from full interrupt mask value.
*
* This function is internal and should not be called directly by user
* software.
*
* \param intMask
* Interrupt mask value to be processed.
*
* \return
* Acquire mask value.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractAcquireMask (uint32_t intMask)
{
return _FLD2VAL(IPC_INTR_STRUCT_INTR_MASK_NOTIFY, intMask);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ExtractReleaseMask
****************************************************************************//**
*
* The function extracts a Release mask part from full interrupt mask value.
*
* This function is internal and should not be called directly by user
* software.
*
* \param intMask
* Interrupt mask value to be processed.
*
* \return
* Release mask value.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_IPC_Drv_ExtractReleaseMask (uint32_t intMask)
{
return _FLD2VAL(IPC_INTR_STRUCT_INTR_MASK_RELEASE, intMask);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_SendMsgPtr
****************************************************************************//**
*
* This function is used to send a message pointer through an IPC channel.
* The message structure may hold a generic pointer that may contain the address
* of any user data type or structure. This parameter could be a pointer to a 32-bit
* integer, an array, or even a data structure defined in the user code. This
* function acts as a transfer engine for sending the pointer. Any memory
* management of the pointer allocation and deallocation is up to the application
* code.
* The function also has an associated notification field that will let the
* message notify one or multiple interrupts.
*
* This function is internal and should not be called directly by user software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param notifyEventIntr
* Bit encoded list of IPC interrupt lines that are triggered during the release
* action.
*
* \param msgPtr
* The message pointer that is being sent over the IPC channel.
*
* \return Status of the operation:
* \retval CY_IPC_DRV_SUCCESS: The send operation was successful.
* \retval CY_IPC_DRV_ERROR: The IPC channel is unavailable because
* it is already locked.
*
*******************************************************************************/
__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_SendMsgPtr(IPC_STRUCT_Type* base, uint32_t notifyEventIntr, void const * msgPtr)
{
CY_ASSERT_L1(NULL != msgPtr);
return Cy_IPC_Drv_SendMsgWord(base, notifyEventIntr, (uint32_t)msgPtr);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_ReadMsgPtr
****************************************************************************//**
*
* This function is used to read a 32-bit pointer message through an IPC channel.
*
* This function is internal and should not be called directly by user software.
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress.
*
* \param msgPtr
* Pointer variable to hold the data pointer that is being read from the IPC
* channel.
*
*
* \return Status of the operation
* \retval CY_IPC_DRV_SUCCESS: The function executed successfully and the IPC
* was acquired.
* \retval CY_IPC_DRV_ERROR: The function encountered an error because the IPC
* channel was already in a released state meaning the data
* in it is invalid.
*
*******************************************************************************/
__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_ReadMsgPtr (IPC_STRUCT_Type const * base, void ** msgPtr)
{
CY_ASSERT_L1(NULL != msgPtr);
return Cy_IPC_Drv_ReadMsgWord(base, (uint32_t *)msgPtr);
}
/*******************************************************************************
* Function Name: Cy_IPC_Drv_LockAcquire
****************************************************************************//**
*
* This function is used to acquire the IPC channel.
*
* This function is internal and should not be called directly by user software
*
* \param base
* This parameter is a handle that represents the base address of the registers
* of the IPC channel.
* The parameter is generally returned from a call to the \ref
* Cy_IPC_Drv_GetIpcBaseAddress
*
* \return Status of the operation
* \retval CY_IPC_DRV_SUCCESS: The IPC was successfully acquired
* \retval CY_IPC_DRV_ERROR: The IPC was not acquired because it was already acquired
* by another master
*
*******************************************************************************/
__STATIC_INLINE cy_en_ipcdrv_status_t Cy_IPC_Drv_LockAcquire (IPC_STRUCT_Type const * base)
{
return ( 0ul != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, base->ACQUIRE)) ? CY_IPC_DRV_SUCCESS : CY_IPC_DRV_ERROR;
}
#ifdef __cplusplus
}
#endif
#endif /* !defined(CY_IPC_DRV_H) */
/* [] END OF FILE */

View File

@ -0,0 +1,515 @@
/***************************************************************************//**
* \file cy_ipc_pipe.c
* \version 1.10
*
* Description:
* IPC Pipe Driver - This source file includes code for the Pipe layer on top
* of the IPC driver.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_ipc_pipe.h"
/* Define a pointer to array of endPoints. */
static cy_stc_ipc_pipe_ep_t * cy_ipc_pipe_epArray = NULL;
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_Config
****************************************************************************//**
*
* This function stores a copy of a pointer to the array of endpoints. All
* access to endpoints will be via the index of the endpoint in this array.
*
* \param theEpArray
* This is the pointer to an array of endpoint structures that the designer
* created and will be used to reference all endpoints.
*
*******************************************************************************/
void Cy_IPC_Pipe_Config(cy_stc_ipc_pipe_ep_t * theEpArray)
{
/* Keep copy of this endpoint */
if (cy_ipc_pipe_epArray == NULL)
{
cy_ipc_pipe_epArray = theEpArray;
}
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_Init
****************************************************************************//**
*
* Initializes the system pipes. The system pipes are used by BLE.
* \note The function should be called on all CPUs.
*
* \param config
* This is the pointer to the pipe configuration structure
*
*******************************************************************************/
void Cy_IPC_Pipe_Init(cy_stc_ipc_pipe_config_t const *config)
{
/* Create the interrupt structures and arrays needed */
cy_stc_sysint_t ipc_intr_cypipeConfig;
cy_stc_ipc_pipe_ep_config_t epConfigDataA;
cy_stc_ipc_pipe_ep_config_t epConfigDataB;
/* Parameters checking begin */
CY_ASSERT_L1(NULL != config);
#if (CY_CPU_CORTEX_M0P)
CY_ASSERT_L2((uint32_t)(1UL << __NVIC_PRIO_BITS) > config->ep0ConfigData.ipcNotifierPriority);
#else
CY_ASSERT_L2((uint32_t)(1UL << __NVIC_PRIO_BITS) > config->ep1ConfigData.ipcNotifierPriority);
#endif
CY_ASSERT_L1(NULL != config->endpointsCallbacksArray);
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > config->ep0ConfigData.epAddress);
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > config->ep1ConfigData.epAddress);
CY_ASSERT_L1(NULL != config->userPipeIsrHandler);
/* Parameters checking end */
#if (CY_CPU_CORTEX_M0P)
/* Receiver endpoint = EP0, Sender endpoint = EP1 */
epConfigDataA = config->ep0ConfigData;
epConfigDataB = config->ep1ConfigData;
/* Configure CM0 interrupts */
ipc_intr_cypipeConfig.intrSrc = (IRQn_Type)epConfigDataA.ipcNotifierMuxNumber;
ipc_intr_cypipeConfig.cm0pSrc = (cy_en_intr_t)((int32_t)cpuss_interrupts_ipc_0_IRQn + (int32_t)epConfigDataA.ipcNotifierNumber);
ipc_intr_cypipeConfig.intrPriority = epConfigDataA.ipcNotifierPriority;
#else
/* Receiver endpoint = EP1, Sender endpoint = EP0 */
epConfigDataA = config->ep1ConfigData;
epConfigDataB = config->ep0ConfigData;
/* Configure interrupts */
ipc_intr_cypipeConfig.intrSrc = (IRQn_Type)(cpuss_interrupts_ipc_0_IRQn + epConfigDataA.ipcNotifierNumber);
ipc_intr_cypipeConfig.intrPriority = epConfigDataA.ipcNotifierPriority;
#endif
/* Initialize the pipe endpoints */
Cy_IPC_Pipe_EndpointInit(epConfigDataA.epAddress,
config->endpointsCallbacksArray,
config->endpointClientsCount,
epConfigDataA.epConfig,
&ipc_intr_cypipeConfig);
/* Create the endpoints for the CM4 just for reference */
Cy_IPC_Pipe_EndpointInit(epConfigDataB.epAddress, NULL, 0ul, epConfigDataB.epConfig, NULL);
(void)Cy_SysInt_Init(&ipc_intr_cypipeConfig, config->userPipeIsrHandler);
/* Enable the interrupts */
NVIC_EnableIRQ(ipc_intr_cypipeConfig.intrSrc);
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_EndpointInit
****************************************************************************//**
*
* This function initializes the endpoint of a pipe for the current CPU. The
* current CPU is the CPU that is executing the code. An endpoint of a pipe
* is for the IPC channel that receives a message for the current CPU.
*
* After this function is called, the callbackArray needs to be populated
* with the callback functions for that endpoint using the
* Cy_IPC_Pipe_RegisterCallback() function.
*
* \param epAddr
* This parameter is the address (or index in the array of endpoint structures)
* that designates the endpoint you want to initialize.
*
* \param cbArray
* This is a pointer to the callback function array. Based on the client ID, one
* of the functions in this array is called to process the message.
*
* \param cbCnt
* This is the size of the callback array, or the number of defined clients.
*
* \param epConfig
* This value defines the IPC channel, IPC interrupt number, and the interrupt
* mask for the entire pipe.
* The format of the endpoint configuration
* Bits[31:16] Interrupt Mask
* Bits[15:8 ] IPC interrupt
* Bits[ 7:0 ] IPC channel
*
* \param epInterrupt
* This is a pointer to the endpoint interrupt description structure.
*
*******************************************************************************/
void Cy_IPC_Pipe_EndpointInit(uint32_t epAddr, cy_ipc_pipe_callback_array_ptr_t cbArray,
uint32_t cbCnt, uint32_t epConfig, cy_stc_sysint_t const *epInterrupt)
{
cy_stc_ipc_pipe_ep_t * endpoint;
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr);
endpoint = &cy_ipc_pipe_epArray[epAddr];
/* Extract the channel, interrupt and interrupt mask */
endpoint->ipcChan = _FLD2VAL(CY_IPC_PIPE_CFG_CHAN, epConfig);
endpoint->intrChan = _FLD2VAL(CY_IPC_PIPE_CFG_INTR, epConfig);
endpoint->pipeIntMask = _FLD2VAL(CY_IPC_PIPE_CFG_IMASK, epConfig);
/* Assign IPC channel to this endpoint */
endpoint->ipcPtr = Cy_IPC_Drv_GetIpcBaseAddress (endpoint->ipcChan);
/* Assign interrupt structure to endpoint and Initialize the interrupt mask for this endpoint */
endpoint->ipcIntrPtr = Cy_IPC_Drv_GetIntrBaseAddr(endpoint->intrChan);
/* Only allow notify and release interrupts from endpoints in this pipe. */
Cy_IPC_Drv_SetInterruptMask(endpoint->ipcIntrPtr, endpoint->pipeIntMask, endpoint->pipeIntMask);
/* Save the Client count and the callback array pointer */
endpoint->clientCount = cbCnt;
endpoint->callbackArray = cbArray;
endpoint->busy = CY_IPC_PIPE_ENDPOINT_NOTBUSY;
if (NULL != epInterrupt)
{
endpoint->pipeIntrSrc = epInterrupt->intrSrc;
}
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_SendMessage
****************************************************************************//**
*
* This function is used to send a message from one endpoint to another. It
* generates an interrupt on the endpoint that receives the message and a
* release interrupt to the sender to acknowledge the message has been processed.
*
* \param toAddr
* This parameter is the address (or index in the array of endpoint structures)
* of the endpoint to which you are sending the message.
*
* \param fromAddr
* This parameter is the address (or index in the array of endpoint structures)
* of the endpoint from which the message is being sent.
*
* \param msgPtr
* Pointer to the message structure to be sent.
*
* \param callBackPtr
* Pointer to the Release callback function.
*
* \return
* CY_IPC_PIPE_SUCCESS: Message was sent to the other end of the pipe
* CY_IPC_PIPE_ERROR_BAD_HANDLE: The handle provided for the pipe was not valid
* CY_IPC_PIPE_ERROR_SEND_BUSY: The pipe is already busy sending a message
*
*******************************************************************************/
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_SendMessage(uint32_t toAddr, uint32_t fromAddr,
void * msgPtr, cy_ipc_pipe_relcallback_ptr_t callBackPtr)
{
cy_en_ipc_pipe_status_t returnStatus;
uint32_t releaseMask;
uint32_t notifyMask;
cy_stc_ipc_pipe_ep_t * fromEp;
cy_stc_ipc_pipe_ep_t * toEp;
CY_ASSERT_L1(NULL != msgPtr);
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > toAddr);
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > fromAddr);
toEp = &(cy_ipc_pipe_epArray[toAddr]);
fromEp = &cy_ipc_pipe_epArray[fromAddr];
/* Create the release mask for the "fromAddr" channel's interrupt channel */
releaseMask = (uint32_t)(1ul << (fromEp->intrChan));
/* Shift into position */
releaseMask = _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, releaseMask);
/* Create the notify mask for the "toAddr" channel's interrupt channel */
notifyMask = (uint32_t)(1ul << (toEp->intrChan));
/* Check if IPC channel valid */
if( toEp->ipcPtr != NULL)
{
if(fromEp->busy == CY_IPC_PIPE_ENDPOINT_NOTBUSY)
{
/* Attempt to acquire the channel */
if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire(toEp->ipcPtr) )
{
/* Mask out the release mask area */
* (uint32_t *) msgPtr &= ~(CY_IPC_PIPE_MSG_RELEASE_Msk);
* (uint32_t *) msgPtr |= releaseMask;
/* If the channel was acquired, write the message. */
Cy_IPC_Drv_WriteDataValue(toEp->ipcPtr, (uint32_t) msgPtr);
/* Set the busy flag. The ISR clears this after the release */
fromEp->busy = CY_IPC_PIPE_ENDPOINT_BUSY;
/* Setup release callback function */
fromEp->releaseCallbackPtr = callBackPtr;
/* Cause notify event/interrupt */
Cy_IPC_Drv_AcquireNotify(toEp->ipcPtr, notifyMask);
returnStatus = CY_IPC_PIPE_SUCCESS;
}
else
{
/* Channel was already acquired, return Error */
returnStatus = CY_IPC_PIPE_ERROR_SEND_BUSY;
}
}
else
{
/* Channel may not be acquired, but the release interrupt has not executed yet */
returnStatus = CY_IPC_PIPE_ERROR_SEND_BUSY;
}
}
else
{
/* Null pipe handle. */
returnStatus = CY_IPC_PIPE_ERROR_BAD_HANDLE;
}
return (returnStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_RegisterCallback
****************************************************************************//**
*
* This function registers a callback that is called when a message is received
* on a pipe.
* The client_ID is the same as the index of the callback function array.
* The callback may be a real function pointer or NULL if no callback is required.
*
* \param epAddr
* This parameter is the address (or index in the array of endpoint structures)
* that designates the endpoint to which you want to add callback functions.
*
* \param callBackPtr
* Pointer to the callback function called when the endpoint has received a message.
*
* \param clientId
* The index in the callback array (Client ID) where the function pointer is saved.
*
* \return
* CY_IPC_PIPE_SUCCESS: Callback registered successfully
* CY_IPC_PIPE_ERROR_BAD_CLIENT: Client ID out of range, callback not registered.
*******************************************************************************/
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_RegisterCallback(uint32_t epAddr, cy_ipc_pipe_callback_ptr_t callBackPtr, uint32_t clientId)
{
cy_en_ipc_pipe_status_t returnStatus;
cy_stc_ipc_pipe_ep_t * thisEp;
CY_ASSERT_L1(NULL != callBackPtr);
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr);
thisEp = &cy_ipc_pipe_epArray[epAddr];
/* Check if clientId is between 0 and less than client count */
if (clientId < thisEp->clientCount)
{
/* Copy callback function into callback function pointer array */
thisEp->callbackArray[clientId] = callBackPtr;
returnStatus = CY_IPC_PIPE_SUCCESS;
}
else
{
returnStatus = CY_IPC_PIPE_ERROR_BAD_CLIENT;
}
return (returnStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_RegisterCallbackRel
****************************************************************************//**
*
* This function registers a default callback if a release interrupt
* is generated but the current release callback function is null.
*
*
* \param epAddr
* This parameter is the address (or index in the array of endpoint structures)
* that designates the endpoint to which you want to add a release callback function.
*
* \param callBackPtr
* Pointer to the callback executed when the endpoint has received a message.
*
* \return
* None
*******************************************************************************/
void Cy_IPC_Pipe_RegisterCallbackRel(uint32_t epAddr, cy_ipc_pipe_relcallback_ptr_t callBackPtr)
{
cy_stc_ipc_pipe_ep_t * endpoint;
CY_ASSERT_L1(NULL != callBackPtr);
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr);
endpoint = &cy_ipc_pipe_epArray[epAddr];
/* Copy callback function into callback function pointer array */
endpoint->defaultReleaseCallbackPtr = callBackPtr;
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_ExecCallback
****************************************************************************//**
*
* This function is called by the ISR for a given pipe endpoint to dispatch
* the appropriate callback function based on the client ID for that endpoint.
*
* \param endpoint
* Pointer to endpoint structure.
*
* \return
* None
*******************************************************************************/
void Cy_IPC_Pipe_ExecCallback(cy_stc_ipc_pipe_ep_t * endpoint)
{
uint32_t *msgPtr = NULL;
uint32_t clientID;
uint32_t shadowIntr;
uint32_t releaseMask = (uint32_t)0;
cy_ipc_pipe_callback_ptr_t callbackPtr;
/* Parameters checking begin */
CY_ASSERT_L1(NULL != endpoint);
CY_ASSERT_L1(NULL != endpoint->ipcPtr);
CY_ASSERT_L1(NULL != endpoint->ipcIntrPtr);
CY_ASSERT_L1(NULL != endpoint->callbackArray);
/* Parameters checking end */
shadowIntr = Cy_IPC_Drv_GetInterruptStatusMasked(endpoint->ipcIntrPtr);
/* Check to make sure the interrupt was a notify interrupt */
if (0ul != Cy_IPC_Drv_ExtractAcquireMask(shadowIntr))
{
/* Clear the notify interrupt. */
Cy_IPC_Drv_ClearInterrupt(endpoint->ipcIntrPtr, CY_IPC_NO_NOTIFICATION, Cy_IPC_Drv_ExtractAcquireMask(shadowIntr));
if ( Cy_IPC_Drv_IsLockAcquired (endpoint->ipcPtr) )
{
/* Extract Client ID */
if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_ReadMsgPtr (endpoint->ipcPtr, (void **)&msgPtr))
{
/* Get release mask */
releaseMask = _FLD2VAL(CY_IPC_PIPE_MSG_RELEASE, *msgPtr);
clientID = _FLD2VAL(CY_IPC_PIPE_MSG_CLIENT, *msgPtr);
/* Make sure client ID is within valid range */
if (endpoint->clientCount > clientID)
{
callbackPtr = endpoint->callbackArray[clientID]; /* Get the callback function */
if (callbackPtr != NULL)
{
callbackPtr(msgPtr); /* Call the function pointer for "clientID" */
}
}
}
/* Must always release the IPC channel */
(void)Cy_IPC_Drv_LockRelease (endpoint->ipcPtr, releaseMask);
}
}
/* Check to make sure the interrupt was a release interrupt */
if (0ul != Cy_IPC_Drv_ExtractReleaseMask(shadowIntr)) /* Check for a Release interrupt */
{
/* Clear the release interrupt */
Cy_IPC_Drv_ClearInterrupt(endpoint->ipcIntrPtr, Cy_IPC_Drv_ExtractReleaseMask(shadowIntr), CY_IPC_NO_NOTIFICATION);
if (endpoint->releaseCallbackPtr != NULL)
{
endpoint->releaseCallbackPtr();
/* Clear the pointer after it was called */
endpoint->releaseCallbackPtr = NULL;
}
else
{
if (endpoint->defaultReleaseCallbackPtr != NULL)
{
endpoint->defaultReleaseCallbackPtr();
}
}
/* Clear the busy flag when release is detected */
endpoint->busy = CY_IPC_PIPE_ENDPOINT_NOTBUSY;
}
(void)Cy_IPC_Drv_GetInterruptStatus(endpoint->ipcIntrPtr);
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_EndpointPause
****************************************************************************//**
*
* This function sets the receiver endpoint to paused state.
*
* \param epAddr
* This parameter is the address (or index in the array of endpoint structures)
* that designates the endpoint to pause.
*
* \return
* CY_IPC_PIPE_SUCCESS: Callback registered successfully
*
*******************************************************************************/
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointPause(uint32_t epAddr)
{
cy_stc_ipc_pipe_ep_t * endpoint;
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr);
endpoint = &cy_ipc_pipe_epArray[epAddr];
/* Disable the interrupts */
NVIC_DisableIRQ(endpoint->pipeIntrSrc);
return (CY_IPC_PIPE_SUCCESS);
}
/*******************************************************************************
* Function Name: Cy_IPC_Pipe_EndpointResume
****************************************************************************//**
*
* This function sets the receiver endpoint to active state.
*
* \param epAddr
* This parameter is the address (or index in the array of endpoint structures)
* that designates the endpoint to resume.
*
* \return
* CY_IPC_PIPE_SUCCESS: Callback registered successfully
*
*******************************************************************************/
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointResume(uint32_t epAddr)
{
cy_stc_ipc_pipe_ep_t * endpoint;
CY_ASSERT_L2(CY_IPC_MAX_ENDPOINTS > epAddr);
endpoint = &cy_ipc_pipe_epArray[epAddr];
/* Enable the interrupts */
NVIC_EnableIRQ(endpoint->pipeIntrSrc);
return (CY_IPC_PIPE_SUCCESS);
}
/* [] END OF FILE */

View File

@ -0,0 +1,266 @@
/***************************************************************************//**
* \file cy_ipc_pipe.h
* \version 1.10
*
* Description:
* IPC Pipe Driver - This header file contains all the function prototypes,
* structure definitions, pipe constants, and pipe endpoint address definitions.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#ifndef CY_IPC_PIPE_H
#define CY_IPC_PIPE_H
/******************************************************************************/
/* Include files */
/******************************************************************************/
#include "ipc/cy_ipc_drv.h"
#include "syslib/cy_syslib.h"
#include "sysint/cy_sysint.h"
/**
* \addtogroup group_ipc_pipe IPC pipes layer (IPC_PIPE)
* \{
* The Pipe functions provide a method to transfer one or more words of data
* between CPUs or tasks. The data can be defined as a single 32-bit unsigned
* word, an array of data, or a user-defined structure. The only limitation is
* that the first word in the array or structure must be a 32-bit unsigned word
* in which a client ID number is passed. The client ID dictates the callback
* function that will be called by the receiver of the message. After the
* callback function returns by the receiver, it will invoke a release callback
* function defined by the sender of the message.
*
* A User Pipe is provided for the user to transfer data between CPUs and
* tasks.
*
* \defgroup group_ipc_pipe_macros Macros
* Macro definitions are used in the driver
*
* \defgroup group_ipc_pipe_functions Functions
* Functions are used in the driver
*
* \defgroup group_ipc_pipe_data_structures Data Structures
* Data structures are used in the driver
*
* \defgroup group_ipc_pipe_enums Enumerated Types
* Enumerations are used in the driver
* \}
*
*/
/*
* This section defines the system level constants required to define
* callback arrays for the Cypress pipe and the user pipe. These defines
* are used for both the max callback count and maximum clients.
*/
/** Typedef for pipe callback function pointer */
typedef void (* cy_ipc_pipe_callback_ptr_t)(uint32_t * msgPtr);
/** Typedef for a pipe release callback function pointer */
typedef void (* cy_ipc_pipe_relcallback_ptr_t)(void);
/** Typedef for array of callback function pointers */
typedef cy_ipc_pipe_callback_ptr_t *cy_ipc_pipe_callback_array_ptr_t;
/**
* \addtogroup group_ipc_pipe_macros
* \{
*/
/*
* The System pipe address is what is used to send a message to one of the
* endpoints of a pipe. Currently the Cypress pipe and the User pipe
* are supported. For parts with extra IPC channels users may create
* their own custom pipes and create their own pipe addresses.
*
* The format of the endpoint configuration
* Bits[31:16] Interrupt Mask
* Bits[15:8 ] IPC interrupt
* Bits[ 7:0 ] IPC channel
*/
#define CY_IPC_PIPE_CFG_IMASK_Pos (16UL) /**< Interrupts shift value for endpoint address */
#define CY_IPC_PIPE_CFG_IMASK_Msk (0xFFFF0000UL) /**< Interrupts mask for endpoint address */
#define CY_IPC_PIPE_CFG_INTR_Pos (8UL) /**< IPC Interrupt shift value for endpoint address */
#define CY_IPC_PIPE_CFG_INTR_Msk (0x0000FF00UL) /**< IPC Interrupt mask for endpoint address */
#define CY_IPC_PIPE_CFG_CHAN_Pos (0UL) /**< IPC Channel shift value for endpoint address */
#define CY_IPC_PIPE_CFG_CHAN_Msk (0x000000FFUL) /**< IPC Channel mask for endpoint address */
#define CY_IPC_PIPE_MSG_CLIENT_Msk (0x000000FFul) /**< Client mask for first word of Pipe message */
#define CY_IPC_PIPE_MSG_CLIENT_Pos (0ul) /**< Client shift for first word of Pipe message */
#define CY_IPC_PIPE_MSG_USR_Msk (0x0000FF00ul) /**< User data mask for first word of Pipe message */
#define CY_IPC_PIPE_MSG_USR_Pos (8ul) /**< User data shift for first word of Pipe message */
#define CY_IPC_PIPE_MSG_RELEASE_Msk (0xFFFF0000ul) /**< Mask for message release mask */
#define CY_IPC_PIPE_MSG_RELEASE_Pos (16UL) /**< Shift require to line up mask to LSb */
/** Use to set the busy flag when waiting for a release interrupt */
#define CY_IPC_PIPE_ENDPOINT_BUSY (1UL)
/** Denotes that a release interrupt is not pending */
#define CY_IPC_PIPE_ENDPOINT_NOTBUSY (0UL)
/** \} group_ipc_pipe_macros */
/**
* \addtogroup group_ipc_pipe_data_structures
* \{
*/
/**
* This is the definition of a pipe endpoint. There is one endpoint structure
* for each CPU in a pipe. It contains all the information to process a message
* send to other CPUs in the pipe.
*/
typedef struct
{
uint32_t ipcChan; /**< IPC channel number used for this endpoint to receive messages */
uint32_t intrChan; /**< IPC interrupt channel number used for this endpoint to receive interrupts */
uint32_t pipeIntMask; /**< Release/Notify interrupt mask that includes all endpoints on pipe */
IRQn_Type pipeIntrSrc; /**< Interrupt vector number that includes all endpoints on pipe */
IPC_STRUCT_Type *ipcPtr; /**< Pointer to receive IPC channel ( If ipcPtr == NULL, cannot receive ) */
IPC_INTR_STRUCT_Type *ipcIntrPtr; /**< Pointer to IPC interrupt, needed to clear the interrupt */
uint32_t busy; /**< Endpoint busy flag. If sent no messages can be sent from this endpoint */
uint32_t clientCount; /**< Client count and size of MsgCallback array */
cy_ipc_pipe_callback_array_ptr_t callbackArray; /**< Pointer to array of callback functions, one for each Client */
cy_ipc_pipe_relcallback_ptr_t releaseCallbackPtr; /**< Pointer to release callback function */
cy_ipc_pipe_relcallback_ptr_t defaultReleaseCallbackPtr; /**< Pointer to default release callback function */
} cy_stc_ipc_pipe_ep_t;
/** The Pipe endpoint configuration structure. */
typedef struct
{
uint32_t ipcNotifierNumber; /**< Notifier */
uint32_t ipcNotifierPriority; /**< Notifier Priority */
uint32_t ipcNotifierMuxNumber; /**< CM0+ interrupt multiplexer number */
uint32_t epAddress; /**< Index in the array of endpoint structure */
uint32_t epConfig; /**< Configuration mask, contains IPC channel, IPC interrupt number,
and the interrupt mask */
} cy_stc_ipc_pipe_ep_config_t;
/** The Pipe channel configuration structure. */
typedef struct
{
/** Specifies the notify interrupt number for the first endpoint */
cy_stc_ipc_pipe_ep_config_t ep0ConfigData;
/** Specifies the notify interrupt number for the second endpoint */
cy_stc_ipc_pipe_ep_config_t ep1ConfigData;
/** Client count and size of MsgCallback array */
uint32_t endpointClientsCount;
/** Pipes callback function array. */
cy_ipc_pipe_callback_array_ptr_t endpointsCallbacksArray;
/** User IRQ handler function that is called when IPC receive data to process (interrupt was raised). */
cy_israddress userPipeIsrHandler;
} cy_stc_ipc_pipe_config_t;
/** \} goup_ipc_pipe_data_structures */
/**
* \addtogroup group_ipc_pipe_macros
* \{
*/
/* Status and error types */
#define CY_IPC_PIPE_RTN (0x0200ul) /**< Software PDL driver ID for IPC pipe functions */
#define CY_IPC_PIPE_ID_INFO (uint32_t)( CY_IPC_ID_INFO | CY_IPC_PIPE_RTN) /**< Return prefix for IPC pipe function status codes */
#define CY_IPC_PIPE_ID_WARNING (uint32_t)( CY_IPC_ID_WARNING | CY_IPC_PIPE_RTN) /**< Return prefix for IPC pipe function warning return values */
#define CY_IPC_PIPE_ID_ERROR (uint32_t)( CY_IPC_ID_ERROR | CY_IPC_PIPE_RTN) /**< Return prefix for IPC pipe function error return values */
/** \} group_ipc_pipe_macros */
/**
* \addtogroup group_ipc_pipe_enums
* \{
*/
/** Return constants for IPC pipe functions. */
typedef enum
{
CY_IPC_PIPE_SUCCESS =(uint32_t)(0x00u), /**< Pipe API return for no error */
CY_IPC_PIPE_ERROR_NO_IPC =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 1ul), /**< Pipe API return for no valid IPC channel */
CY_IPC_PIPE_ERROR_NO_INTR =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 2ul), /**< Pipe API return for no valid interrupt */
CY_IPC_PIPE_ERROR_BAD_PRIORITY =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 3ul), /**< Pipe API return for bad priority parameter */
CY_IPC_PIPE_ERROR_BAD_HANDLE =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 4ul), /**< Pipe API return for bad pipe handle */
CY_IPC_PIPE_ERROR_BAD_ID =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 5ul), /**< Pipe API return for bad pipe ID */
CY_IPC_PIPE_ERROR_DIR_ERROR =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 6ul), /**< Pipe API return for invalid direction (Not used at this time) */
CY_IPC_PIPE_ERROR_SEND_BUSY =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 7ul), /**< Pipe API return for pipe is currently busy */
CY_IPC_PIPE_ERROR_NO_MESSAGE =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 8ul), /**< Pipe API return for no message indicated */
CY_IPC_PIPE_ERROR_BAD_CPU =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 9ul), /**< Pipe API return for invalid CPU value */
CY_IPC_PIPE_ERROR_BAD_CLIENT =(uint32_t)(CY_IPC_PIPE_ID_ERROR | 10ul) /**< Pipe API return for client out of range */
} cy_en_ipc_pipe_status_t;
/** \} group_ipc_pipe_enums */
/**
* \addtogroup group_ipc_pipe_data_structures
* \{
*/
/** \cond
* NOTE: This doxygen comment must be placed before some code entity, or else
* it will belong to a random entity that follows it, e.g. group_ipc_functions
*
* Client identifier for a message.
* For a given pipe, traffic across the pipe can be multiplexed with multiple
* senders on one end and multiple receivers on the other end.
*
* The first 32-bit word of the message is used to identify the client that owns
* the message.
*
* The upper 16 bits are the client ID.
*
* The lower 16 bits are for use by the client in any way desired.
*
* The lower 16 bits are preserved (not modified) and not interpreted in any way.
* \endcond
*/
/** \} group_ipc_pipe_data_structures */
/******************************************************************************/
/* Global function prototypes (definition in C source) */
/******************************************************************************/
/**
* \addtogroup group_ipc_pipe_functions
* \{
*/
#ifdef __cplusplus
extern "C" {
#endif
void Cy_IPC_Pipe_EndpointInit(uint32_t epAddr, cy_ipc_pipe_callback_array_ptr_t cbArray,
uint32_t cbCnt, uint32_t epConfig, cy_stc_sysint_t const *epInterrupt);
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_SendMessage(uint32_t toAddr, uint32_t fromAddr, void *msgPtr,
cy_ipc_pipe_relcallback_ptr_t callBackPtr);
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_RegisterCallback(uint32_t epAddr,
cy_ipc_pipe_callback_ptr_t callBackPtr, uint32_t clientId);
void Cy_IPC_Pipe_ExecCallback(cy_stc_ipc_pipe_ep_t * endpoint);
void Cy_IPC_Pipe_RegisterCallbackRel(uint32_t epAddr, cy_ipc_pipe_relcallback_ptr_t callBackPtr);
void Cy_IPC_Pipe_Config(cy_stc_ipc_pipe_ep_t * theEpArray);
void Cy_IPC_Pipe_Init(cy_stc_ipc_pipe_config_t const *config);
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointPause(uint32_t epAddr);
cy_en_ipc_pipe_status_t Cy_IPC_Pipe_EndpointResume(uint32_t epAddr);
#ifdef __cplusplus
}
#endif
/** \} group_ipc_pipe_functions */
#endif /* CY_IPC_PIPE_H */
/* [] END OF FILE */

View File

@ -0,0 +1,369 @@
/***************************************************************************//**
* \file cy_ipc_sema.c
* \version 1.10
*
* Description:
* IPC Semaphore Driver - This source file contains the source code for the
* semaphore level APIs for the IPC interface.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "ipc/cy_ipc_drv.h"
#include "ipc/cy_ipc_sema.h"
#include "syslib/cy_syslib.h"
#include <string.h> /* The memset() definition */
/* Defines a mask to Check if semaphore count is a multiple of 32 */
#define CY_IPC_SEMA_PER_WORD_MASK (CY_IPC_SEMA_PER_WORD - 1ul)
/* Pointer to IPC structure used for semaphores */
static IPC_STRUCT_Type* cy_semaIpcStruct;
/*
* Internal IPC semaphore control data structure.
*/
typedef struct {
uint32_t maxSema; /* Maximum semaphores in system */
uint32_t *arrayPtr; /* Pointer to semaphores array */
} cy_stc_ipc_sema_t;
/*******************************************************************************
* Function Name: Cy_IPC_Sema_Init
****************************************************************************//**
*
* This function initializes the semaphores subsystem. The user must create an
* array of unsigned 32-bit words to hold the semaphore bits. The number
* of semaphores will be the size of the array * 32. The total semaphores count
* will always be a multiple of 32.
*
* \note In a multi-CPU system this init function should be called with all
* initialized parameters on one CPU only to provide a pointer to SRAM that can
* be shared between all the CPUs in the system that will use semaphores.
* On other CPUs user must specify the IPC semaphores channel and pass 0 / NULL
* to count and memPtr parameters correspondingly.
*
* \param ipcChannel
* The IPC channel number used for semaphores
*
* \param count
* The maximum number of semaphores to be supported (multiple of 32).
*
* \param memPtr
* This points to the array of (count/32) words that contain the semaphore data.
*
* \return
* \retval CY_IPC_SEMA_SUCCESS: Successfully initialized
* \retval CY_IPC_SEMA_BAD_PARAM: Memory pointer is NULL and count is not zero,
* or count not multiple of 32
* \retval CY_IPC_SEMA_ERROR_LOCKED: Could not acquire semaphores IPC channel
*
*******************************************************************************/
cy_en_ipcsema_status_t Cy_IPC_Sema_Init(uint32_t ipcChannel,
uint32_t count, uint32_t memPtr[])
{
/* Structure containing semaphores control data */
static cy_stc_ipc_sema_t cy_semaData;
cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_BAD_PARAM;
if (ipcChannel >= CY_IPC_CHANNELS)
{
retStatus = CY_IPC_SEMA_BAD_PARAM;
}
else
{
if( (NULL == memPtr) && (0u == count))
{
cy_semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipcChannel);
retStatus = CY_IPC_SEMA_SUCCESS;
}
/* Check for non Null pointers and count value */
else if ((NULL != memPtr) && (0u != count))
{
/* Check if semaphore count is a multiple of 32 */
if( 0ul == (count & CY_IPC_SEMA_PER_WORD_MASK))
{
cy_semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipcChannel);
cy_semaData.maxSema = count;
cy_semaData.arrayPtr = memPtr;
/* Initialize all semaphores to released */
(void)memset(cy_semaData.arrayPtr, 0, (count /8u));
/* Make sure semaphores start out released. */
/* Ignore the return value since it is OK if it was already released. */
(void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
/* Set the IPC Data with the pointer to the array. */
if( CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_SendMsgPtr (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION, &cy_semaData))
{
if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION))
{
retStatus = CY_IPC_SEMA_SUCCESS;
}
else
{
/* IPC channel not released, still semaphored */
retStatus = CY_IPC_SEMA_ERROR_LOCKED;
}
}
else
{
/* Could not acquire semaphore channel */
retStatus = CY_IPC_SEMA_ERROR_LOCKED;
}
}
else
{
retStatus = CY_IPC_SEMA_BAD_PARAM;
}
}
else
{
retStatus = CY_IPC_SEMA_BAD_PARAM;
}
}
return(retStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Sema_Set
****************************************************************************//**
*
* This function tries to acquire a semaphore. If the
* semaphore is not available, this function returns immediately with
* CY_IPC_SEMA_LOCKED.
*
* It first acquires the IPC channel that is used for all the semaphores, sets
* the semaphore if it is cleared, then releases the IPC channel used for the semaphore.
*
* \param semaNumber
* The semaphore number to acquire.
*
* \param preemptable
* When this parameter is enabled the function can be preempted by another
* task or other forms of context switching in an RTOS environment.
*
* \return
* \retval CY_IPC_SEMA_SUCCESS: The semaphore was set successfully
* \retval CY_IPC_SEMA_LOCKED: The semaphore channel is busy or locked
* by another process
* \retval CY_IPC_SEMA_NOT_ACQUIRED: Semaphore was already set
* \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid
*
*
*******************************************************************************/
cy_en_ipcsema_status_t Cy_IPC_Sema_Set(uint32_t semaNumber, bool preemptable)
{
uint32_t semaIndex;
uint32_t semaMask;
uint32_t interruptState = 0ul;
cy_stc_ipc_sema_t *semaStruct;
cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_LOCKED;
/* Get pointer to structure */
semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
if (semaNumber < semaStruct->maxSema)
{
semaIndex = semaNumber / CY_IPC_SEMA_PER_WORD;
semaMask = (uint32_t)(1ul << (semaNumber - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
if (!preemptable)
{
interruptState = Cy_SysLib_EnterCriticalSection();
}
/* Check to make sure the IPC channel is released
If so, check if specific channel can be locked. */
if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct))
{
if((semaStruct->arrayPtr[semaIndex] & semaMask) == 0ul)
{
semaStruct->arrayPtr[semaIndex] |= semaMask;
retStatus = CY_IPC_SEMA_SUCCESS;
}
else
{
retStatus = CY_IPC_SEMA_NOT_ACQUIRED;
}
/* Release, but do not trigger a release event */
(void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
}
if (!preemptable)
{
Cy_SysLib_ExitCriticalSection(interruptState);
}
}
else
{
retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
}
return(retStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Sema_Clear
****************************************************************************//**
*
* This functions tries to releases a semaphore.
*
* It first acquires the IPC channel that is used for all the semaphores, clears
* the semaphore if it is set, then releases the IPC channel used for the semaphores.
*
* \param semaNumber
* The index of the semaphore to release.
*
* \param preemptable
* When this parameter is enabled the function can be preempted by another
* task or other forms of context switching in an RTOS environment.
*
* \return
* \retval CY_IPC_SEMA_SUCCESS: The semaphore was cleared successfully
* \retval CY_IPC_SEMA_NOT_ACQUIRED: The semaphore was already cleared
* \retval CY_IPC_SEMA_LOCKED: The semaphore channel was semaphored or busy
* \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid
*
*
*******************************************************************************/
cy_en_ipcsema_status_t Cy_IPC_Sema_Clear(uint32_t semaNumber, bool preemptable)
{
uint32_t semaIndex;
uint32_t semaMask;
uint32_t interruptState = 0ul;
cy_stc_ipc_sema_t *semaStruct;
cy_en_ipcsema_status_t retStatus = CY_IPC_SEMA_LOCKED;
/* Get pointer to structure */
semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
if (semaNumber < semaStruct->maxSema)
{
semaIndex = semaNumber / CY_IPC_SEMA_PER_WORD;
semaMask = (uint32_t)(1ul << (semaNumber - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
if (!preemptable)
{
interruptState = Cy_SysLib_EnterCriticalSection();
}
/* Check to make sure the IPC channel is released
If so, check if specific channel can be locked. */
if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_LockAcquire (cy_semaIpcStruct))
{
if((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul)
{
semaStruct->arrayPtr[semaIndex] &= ~semaMask;
retStatus = CY_IPC_SEMA_SUCCESS;
}
else
{
retStatus = CY_IPC_SEMA_NOT_ACQUIRED;
}
/* Release, but do not trigger a release event */
(void) Cy_IPC_Drv_LockRelease (cy_semaIpcStruct, CY_IPC_NO_NOTIFICATION);
}
if (!preemptable)
{
Cy_SysLib_ExitCriticalSection(interruptState);
}
}
else
{
retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
}
return(retStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Sema_Status
****************************************************************************//**
*
* This function returns the status of the semaphore.
*
* \param semaNumber
* The index of the semaphore to return status.
*
* \return
* \retval CY_IPC_SEMA_STATUS_LOCKED: The semaphore is in the set state.
* \retval CY_IPC_SEMA_STATUS_UNLOCKED: The semaphore is in the cleared state.
* \retval CY_IPC_SEMA_OUT_OF_RANGE: The semaphore number is not valid
*
*
*******************************************************************************/
#if defined (__ICCARM__)
__ramfunc
#else
CY_SECTION(".cy_ramfunc")
#endif
cy_en_ipcsema_status_t Cy_IPC_Sema_Status(uint32_t semaNumber)
{
cy_en_ipcsema_status_t retStatus;
uint32_t semaIndex;
uint32_t semaMask;
cy_stc_ipc_sema_t *semaStruct;
/* Get pointer to structure */
semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
if (semaNumber < semaStruct->maxSema)
{
/* Get the index into the semaphore array and calculate the mask */
semaIndex = semaNumber / CY_IPC_SEMA_PER_WORD;
semaMask = (uint32_t)(1ul << (semaNumber - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
if((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul)
{
retStatus = CY_IPC_SEMA_STATUS_LOCKED;
}
else
{
retStatus = CY_IPC_SEMA_STATUS_UNLOCKED;
}
}
else
{
retStatus = CY_IPC_SEMA_OUT_OF_RANGE;
}
return(retStatus);
}
/*******************************************************************************
* Function Name: Cy_IPC_Sema_GetMaxSems
****************************************************************************//**
*
* This function returns the number of semaphores in the semaphores subsystem.
*
* \return
* Returns the semaphores quantity.
*
*******************************************************************************/
uint32_t Cy_IPC_Sema_GetMaxSems(void)
{
cy_stc_ipc_sema_t *semaStruct;
/* Get pointer to structure */
semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(cy_semaIpcStruct);
return (semaStruct->maxSema);
}
/* [] END OF FILE */

View File

@ -0,0 +1,116 @@
/***************************************************************************//**
* \file cy_ipc_sema.h
* \version 1.10
*
* \brief
* Header file for IPC SEM functions
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#ifndef CY_IPC_SEMA_H
#define CY_IPC_SEMA_H
/******************************************************************************/
/* Include files */
/******************************************************************************/
#include "cy_ipc_drv.h"
#include <stdbool.h>
/**
* \addtogroup group_ipc_sema IPC semaphores layer (IPC_SEMA)
* \{
* The semaphores layer functions made use of a single IPC channel to allow
* multiple semaphores that can be used by system or user function calls.
* By default there are 128 semaphores provided, although the user may modify
* the default value to any number, limited only by SRAM.
*
* \defgroup group_ipc_sema_macros Macros
* Macro definitions are used in the driver
*
* \defgroup group_ipc_sema_functions Functions
* Functions are used in the driver
*
* \defgroup group_ipc_sema_enums Enumerated Types
* Enumerations are used in the driver
* \}
*
* \addtogroup group_ipc_sema_macros
* \{
*/
/** Software PDL driver ID for IPC semaphore functions */
#define CY_IPC_SEMA_RTN (0x0100ul)
/** Return prefix for IPC semaphore function status codes */
#define CY_IPC_SEMA_ID_INFO (uint32_t)( CY_IPC_ID_INFO | CY_IPC_SEMA_RTN)
/** Return prefix for IPC semaphore function warning return values */
#define CY_IPC_SEMA_ID_WARNING (uint32_t)( CY_IPC_ID_WARNING | CY_IPC_SEMA_RTN)
/** Return prefix for IPC semaphore function error return values */
#define CY_IPC_SEMA_ID_ERROR (uint32_t)( CY_IPC_ID_ERROR | CY_IPC_SEMA_RTN)
#define CY_IPC_SEMA_PER_WORD (uint32_t)32u /**< 32 semaphores per word */
/** \} group_ipc_sema_macros */
/**
* \addtogroup group_ipc_sema_enums
* \{
*/
/** Return constants for IPC semaphores functions. */
typedef enum
{
/** No error has occurred */
CY_IPC_SEMA_SUCCESS = (uint32_t)(0ul),
/** Semaphores IPC channel has already been locked */
CY_IPC_SEMA_ERROR_LOCKED = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 1ul),
/** Semaphores IPC channel is unlocked */
CY_IPC_SEMA_ERROR_UNLOCKED = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 2ul),
/** Semaphore API bad parameter */
CY_IPC_SEMA_BAD_PARAM = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 3ul),
/** Semaphore API return when semaphore number is out of the range */
CY_IPC_SEMA_OUT_OF_RANGE = (uint32_t)(CY_IPC_SEMA_ID_ERROR | 4ul),
/** Semaphore API return when IPC channel was not acquired */
CY_IPC_SEMA_NOT_ACQUIRED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 2ul),
/** Semaphore API return status when semaphore channel is busy or locked
* by another process */
CY_IPC_SEMA_LOCKED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 3ul),
/** Semaphore status return that the semaphore is set */
CY_IPC_SEMA_STATUS_LOCKED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 1ul),
/** Semaphore status return that the semaphore is cleared */
CY_IPC_SEMA_STATUS_UNLOCKED = (uint32_t)(CY_IPC_SEMA_ID_INFO | 0ul)
} cy_en_ipcsema_status_t;
/** \} group_ipc_sema_enums */
/**
* \addtogroup group_ipc_sema_functions
* \{
*/
#ifdef __cplusplus
extern "C" {
#endif
cy_en_ipcsema_status_t Cy_IPC_Sema_Init (uint32_t ipcChannel, uint32_t count, uint32_t memPtr[]);
cy_en_ipcsema_status_t Cy_IPC_Sema_Set (uint32_t semaNumber, bool preemptable);
cy_en_ipcsema_status_t Cy_IPC_Sema_Clear (uint32_t semaNumber, bool preemptable);
cy_en_ipcsema_status_t Cy_IPC_Sema_Status (uint32_t semaNumber);
uint32_t Cy_IPC_Sema_GetMaxSems(void);
#ifdef __cplusplus
}
#endif
/** \} group_ipc_sema_functions */
#endif /* CY_IPC_SEMA_H */
/* [] END OF FILE */

View File

@ -0,0 +1,545 @@
/*******************************************************************************
* \file cy_lpcomp.c
* \version 1.10
*
* \brief
* This file provides the driver code to the API for the Low Power Comparator
* component.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_lpcomp.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* Function Name: Cy_LPComp_Init
****************************************************************************//**
*
* Initializes LPCOMP and returns the LPCOMP register address.
*
* \param *base
* LPCOMP registers structure pointer.
*
* \param *config
* The pointer to the configuration structure for PDL.
*
* \param channel
* The LPCOMP channel index.
*
* \return cy_en_lpcomp_status_t
* *base checking result. If the pointer is NULL, returns error.
*
*******************************************************************************/
cy_en_lpcomp_status_t Cy_LPComp_Init(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, const cy_stc_lpcomp_config_t* config)
{
cy_en_lpcomp_status_t ret = CY_LPCOMP_BAD_PARAM;
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
CY_ASSERT_L3(CY_LPCOMP_IS_OUT_MODE_VALID(config->outputMode));
CY_ASSERT_L3(CY_LPCOMP_IS_HYSTERESIS_VALID(config->hysteresis));
if ((base != NULL) && (config != NULL))
{
Cy_LPComp_GlobalEnable(base);
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_CTRL = _VAL2FLD(LPCOMP_CMP0_CTRL_HYST0, (uint32_t)config->hysteresis) |
_VAL2FLD(LPCOMP_CMP0_CTRL_DSI_BYPASS0, (uint32_t)config->outputMode) |
_VAL2FLD(LPCOMP_CMP0_CTRL_DSI_LEVEL0, (uint32_t)config->outputMode >> 1u);
}
else
{
base->CMP1_CTRL = _VAL2FLD(LPCOMP_CMP1_CTRL_HYST1, (uint32_t)config->hysteresis) |
_VAL2FLD(LPCOMP_CMP1_CTRL_DSI_BYPASS1, (uint32_t)config->outputMode) |
_VAL2FLD(LPCOMP_CMP1_CTRL_DSI_LEVEL1, (uint32_t)config->outputMode >> 1u);
}
ret = CY_LPCOMP_SUCCESS;
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetInterruptTriggerMode
****************************************************************************//**
*
* Sets the interrupt edge-detect mode.
* This also controls the value provided on the output.
* Note: Interrupts can be enabled after the block is enabled and the appropriate
* start-up time has elapsed:
* 3 us for the normal power mode;
* 6 us for the LP mode;
* 50 us for the ULP mode.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param channel
* The LPCOMP channel index.
*
* \param intType
* Interrupt edge trigger selection
* CY_LPCOMP_INTR_DISABLE (=0) - Disabled, no interrupt will be detected
* CY_LPCOMP_INTR_RISING (=1) - Rising edge
* CY_LPCOMP_INTR_FALLING (=2) - Falling edge
* CY_LPCOMP_INTR_BOTH (=3) - Both rising and falling edges.
*
* \return None
*
*******************************************************************************/
void Cy_LPComp_SetInterruptTriggerMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_int_t intType)
{
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
CY_ASSERT_L3(CY_LPCOMP_IS_INTR_MODE_VALID(intType));
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, LPCOMP_CMP0_CTRL_INTTYPE0, (uint32_t)intType);
}
else
{
base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL, LPCOMP_CMP1_CTRL_INTTYPE1, (uint32_t)intType);
}
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetPower
****************************************************************************//**
*
* Sets the drive power and speeds to one of the four settings.
* Note: The comparator interrupt should be enabled after enabling of the
* comparator itself. Otherwise, unexpected interrupts events can occur.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param channel
* The LPCOMP channel index.
*
* \param power
* The power setting sets an operation mode of the component:
* CY_LPCOMP_OFF_POWER (=0) - Off power
* CY_LPCOMP_MODE_ULP (=1) - Slow/ultra low power
* CY_LPCOMP_MODE_LP (=2) - Medium/low power
* CY_LPCOMP_MODE_NORMAL(=3) - Fast/normal power
*
* \return None
*
*******************************************************************************/
void Cy_LPComp_SetPower(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_pwr_t power)
{
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
CY_ASSERT_L3(CY_LPCOMP_IS_POWER_VALID(power));
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, LPCOMP_CMP0_CTRL_MODE0, (uint32_t)power);
}
else
{
base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL, LPCOMP_CMP1_CTRL_MODE1, (uint32_t)power);
}
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetHysteresis
****************************************************************************//**
*
* Adds the 30mV hysteresis to the comparator.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param channel
* The LPCOMP channel index.
*
* \param hysteresis
* Sets an operation mode of the component
* CY_LPCOMP_HYST_ENABLE (=1) - Enables HYST
* CY_LPCOMP_HYST_DISABLE(=0) - Disable HYST.
*
* \return None
*
*******************************************************************************/
void Cy_LPComp_SetHysteresis(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_hyst_t hysteresis)
{
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
CY_ASSERT_L3(CY_LPCOMP_IS_HYSTERESIS_VALID(hysteresis));
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, LPCOMP_CMP0_CTRL_HYST0, (uint32_t)hysteresis);
}
else
{
base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL , LPCOMP_CMP1_CTRL_HYST1, (uint32_t)hysteresis);
}
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetInputs
****************************************************************************//**
*
* Sets the comparator input sources. The comparator inputs can be connected
* to the dedicated GPIO pins or AMUXBUSA/AMUXBUSB. Additionally, the negative
* comparator input can be connected to the local VREF.
* At least one unconnected input causes a comparator undefined output.
*
* Note: Connection to AMUXBUSA/AMUXBUSB requires closing the additional
* switches which are a part of the IO system. These switches can be configured
* using the HSIOM->AMUX_SPLIT_CTL[3] register.
* Refer to the appropriate Technical Reference Manual (TRM) of a device
* for a detailed description.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param channel
* The LPCOMP channel index.
*
* \param inputP
* Positive input selection
* CY_LPCOMP_SW_GPIO (0x01u)
* CY_LPCOMP_SW_AMUXBUSA (0x02u) - Hi-Z in hibernate mode
* CY_LPCOMP_SW_AMUXBUSB (0x04u) - Hi-Z in the hibernate mode.
*
* \param inputN
* Negative input selection
* CY_LPCOMP_SW_GPIO (0x01u)
* CY_LPCOMP_SW_AMUXBUSA (0x02u) - Hi-Z in hibernate mode
* CY_LPCOMP_SW_AMUXBUSB (0x04u) - Hi-Z in hibernate mode
* CY_LPCOMP_SW_LOCAL_VREF (0x08u) - the negative input only for a crude REF.
*
* \return None
*
*******************************************************************************/
void Cy_LPComp_SetInputs(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_inputs_t inputP, cy_en_lpcomp_inputs_t inputN)
{
uint32_t input;
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
CY_ASSERT_L3(CY_LPCOMP_IS_INPUT_P_VALID(inputP));
CY_ASSERT_L3(CY_LPCOMP_IS_INPUT_N_VALID(inputN));
switch(inputP)
{
case CY_LPCOMP_SW_AMUXBUSA:
{
input = (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_AP0_Msk : LPCOMP_CMP1_SW_CMP1_AP1_Msk;
HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR, 3u);
break;
}
case CY_LPCOMP_SW_AMUXBUSB:
{
input = (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_BP0_Msk : LPCOMP_CMP1_SW_CMP1_BP1_Msk;
HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR, 3u);
break;
}
default:
{
input = (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_IP0_Msk : LPCOMP_CMP1_SW_CMP1_IP1_Msk;
break;
}
}
switch(inputN)
{
case CY_LPCOMP_SW_AMUXBUSA:
{
input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_AN0_Msk : LPCOMP_CMP1_SW_CMP1_AN1_Msk;
HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR, 3u);
break;
}
case CY_LPCOMP_SW_AMUXBUSB:
{
input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_BN0_Msk : LPCOMP_CMP1_SW_CMP1_BN1_Msk;
HSIOM->AMUX_SPLIT_CTL[3] = _CLR_SET_FLD32U(HSIOM->AMUX_SPLIT_CTL[3], CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR, 3u);
break;
}
case CY_LPCOMP_SW_LOCAL_VREF:
{
input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_VN0_Msk : LPCOMP_CMP1_SW_CMP1_VN1_Msk;
break;
}
default:
{
input |= (channel == CY_LPCOMP_CHANNEL_0) ? LPCOMP_CMP0_SW_CMP0_IN0_Msk : LPCOMP_CMP1_SW_CMP1_IN1_Msk;
break;
}
}
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_SW_CLEAR = CY_LPCOMP_CMP0_SW_POS_Msk | CY_LPCOMP_CMP0_SW_NEG_Msk;
base->CMP0_SW = input;
}
else
{
base->CMP1_SW_CLEAR = CY_LPCOMP_CMP1_SW_POS_Msk | CY_LPCOMP_CMP1_SW_NEG_Msk;
base->CMP1_SW = input;
}
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetOutputMode
****************************************************************************//**
*
* Sets the type of the comparator DSI output.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param channel
* The LPCOMP channel index.
*
* \param outType
* Interrupt edge trigger selection
* CY_LPCOMP_OUT_PULSE (=0) - the DSI output with the pulse option, no bypass
* CY_LPCOMP_OUT_DIRECT (=1) - the bypass mode, the direct output of the comparator
* CY_LPCOMP_OUT_SYNC (=2) - DSI output with the level option, it is similar to the
* bypass mode but it is 1 cycle slow than the bypass.
* [DSI_LEVELx : DSI_BYPASSx] = [Bit11 : Bit10]
* 0 : 0 = 0x00 -> Pulse (PULSE)
* 1 : 0 = 0x02 -> Level (SYNC)
* x : 1 = 0x01 -> Bypass (Direct).
*
* \return None
*
*******************************************************************************/
void Cy_LPComp_SetOutputMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_out_t outType)
{
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
CY_ASSERT_L3(CY_LPCOMP_IS_OUT_MODE_VALID(outType));
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_CTRL = _CLR_SET_FLD32U(base->CMP0_CTRL, CY_LPCOMP_CMP0_OUTPUT_CONFIG, (uint32_t)outType);
}
else
{
base->CMP1_CTRL = _CLR_SET_FLD32U(base->CMP1_CTRL, CY_LPCOMP_CMP1_OUTPUT_CONFIG, (uint32_t)outType);
}
}
/*******************************************************************************
* Function Name: Cy_LPComp_DeepSleepCallback
****************************************************************************//**
*
* This function checks the current power mode of LPComp and then disables the
* LPComp block if there is no wake-up source from LPComp in the deep-sleep mode.
* It stores the state of the LPComp enable and then disables the LPComp block
* before going to the low power modes, and recovers the LPComp power state after
* wake-up using the stored value.
* The function attribution has a weak linkage, so the user can override this
* function for a custom lower-power callback.
*
* \param *callbackParams
* The \ref cy_stc_syspm_callback_params_t structure with the callback
* parameters which consists of mode, base and context fields:
* *base - LPComp register structure pointer;
* *context - Context for the call-back function;
* mode
* CY_SYSPM_CHECK_READY - No action for this state.
* CY_SYSPM_CHECK_FAIL - No action for this state.
* CY_SYSPM_BEFORE_TRANSITION - Checks the LPComp interrupt mask and the power
* mode, and then disables or enables the LPComp block
* according to the condition.
* Stores the LPComp state to recover the state after
* wake up.
* CY_SYSPM_AFTER_TRANSITION - Enables the LPComp block, if it was disabled
* before the sleep mode.
*
* \return
* \ref cy_en_syspm_status_t
*
*******************************************************************************/
cy_en_syspm_status_t Cy_LPComp_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
cy_en_syspm_status_t ret = CY_SYSPM_FAIL;
LPCOMP_Type *locBase = (LPCOMP_Type *) (callbackParams->base);
static uint32_t enabled_status;
switch(callbackParams->mode)
{
case CY_SYSPM_CHECK_READY:
{
ret = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_CHECK_FAIL:
{
ret = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_BEFORE_TRANSITION:
{
/* Save the LPComp the enabled/disabled status. */
enabled_status = _FLD2VAL(LPCOMP_CONFIG_ENABLED, locBase->CONFIG);
if (0u != enabled_status)
{
/* Disable the LPComp block when there is no wake-up source from any channel. */
if( !(((_FLD2VAL(LPCOMP_CMP0_CTRL_MODE0, locBase->CMP0_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) &&
_FLD2BOOL(LPCOMP_INTR_MASK_COMP0_MASK, locBase->INTR_MASK)) ||
((_FLD2VAL(LPCOMP_CMP1_CTRL_MODE1, locBase->CMP1_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) &&
_FLD2BOOL(LPCOMP_INTR_MASK_COMP1_MASK, locBase->INTR_MASK))) )
{
/* Disable the LPComp block to avoid leakage. */
Cy_LPComp_GlobalDisable(locBase);
}
else
{
/* Set LPComp the status to the not changed state. */
enabled_status = 0u;
}
}
else
{
/* The LPComp block was already disabled and
* the system is allowed to go to the low power mode.
*/
}
ret = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_AFTER_TRANSITION:
{
/* Enable LPComp to operate if it was enabled
* before entering to the low power mode.
*/
if (0u != enabled_status)
{
Cy_LPComp_GlobalEnable(locBase);
}
else
{
/* The LPComp block was disabled before calling this API
* with mode = CY_SYSPM_CHECK_READY.
*/
}
ret = CY_SYSPM_SUCCESS;
}
break;
default:
break;
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_LPComp_HibernateCallback
****************************************************************************//**
*
* This function checks the current power mode of LPComp and then disable the
* LPComp block, if there is no wake-up source from LPComp in the hibernate mode.
* The function attribution has a weak linkage, so the user can override this
* function for a custom lower-power callback.
*
* \param *callbackParams
* The \ref cy_stc_syspm_callback_params_t structure with the callback
* parameters which consists of mode, base and context fields:
* *base - LPComp register structure pointer;
* *context - Context for the call-back function;
* mode
* CY_SYSPM_CHECK_READY - No action for this state.
* CY_SYSPM_CHECK_FAIL - No action for this state.
* CY_SYSPM_BEFORE_TRANSITION - Checks the wake-up source from the hibernate mode
* of the LPComp block, and then disables or enables
* the LPComp block according to the condition.
*
* \return
* \ref cy_en_syspm_status_t
*
*******************************************************************************/
cy_en_syspm_status_t Cy_LPComp_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
cy_en_syspm_status_t ret = CY_SYSPM_FAIL;
LPCOMP_Type *locBase = (LPCOMP_Type *) (callbackParams->base);
static uint32_t enabled_status;
switch(callbackParams->mode)
{
case CY_SYSPM_CHECK_READY:
{
ret = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_CHECK_FAIL:
{
ret = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_BEFORE_TRANSITION:
{
/* Save the LPComp the enabled/disabled status. */
enabled_status = _FLD2VAL(LPCOMP_CONFIG_ENABLED, locBase->CONFIG);
if (0u != enabled_status)
{
/* Disable the LPComp block when there is no wake-up source from any channel. */
if( !(((_FLD2VAL(LPCOMP_CMP0_CTRL_MODE0, locBase->CMP0_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) &&
_FLD2BOOL(CY_LPCOMP_WAKEUP_PIN0, SRSS->PWR_HIBERNATE)) ||
((_FLD2VAL(LPCOMP_CMP1_CTRL_MODE1, locBase->CMP1_CTRL) == (uint32_t)CY_LPCOMP_MODE_ULP) &&
_FLD2BOOL(CY_LPCOMP_WAKEUP_PIN1, SRSS->PWR_HIBERNATE))) )
{
/* Disable the LPComp block to avoid leakage. */
Cy_LPComp_GlobalDisable(locBase);
}
else
{
/* Set LPComp the status to the not changed state. */
enabled_status = 0u;
}
}
else
{
/* The LPComp block was already disabled and
* the system is allowed to go to the low power mode.
*/
}
ret = CY_SYSPM_SUCCESS;
}
break;
default:
break;
}
return (ret);
}
#if defined(__cplusplus)
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,687 @@
/***************************************************************************//**
* \file cy_lpcomp.h
* \version 1.10
*
* This file provides constants and parameter values for the Low Power Comparator driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_lpcomp Low Power Comparator (LPComp)
* \{
* Provides access to the low-power comparators implemented using the fixed-function
* LP comparator block that is present in PSoC 6.
*
* These comparators can perform fast analog signal comparison of internal
* and external analog signals in all system power modes. Low-power comparator
* output can be inspected by the CPU, used as an interrupt/wakeup source to the
* CPU when in low-power mode (Sleep, Low-Power Sleep, or Deep-Sleep), used as
* a wakeup source to system resources when in Hibernate mode, or fed to DSI as
* an asynchronous or synchronous signal (level or pulse).
*
* \section group_lpcomp_section_Configuration_Considerations Configuration Considerations
* To set up an LPComp, the inputs, the output, the mode, the interrupts and
* other configuration parameters should be configured. Power the LPComp to operate.
*
* The sequence recommended for the LPComp operation:
*
* 1) To initialize the driver, call the Cy_LPComp_Init() function providing
* the filled cy_stc_lpcomp_config_t structure, the LPComp channel number,
* and the LPCOMP registers structure pointer.
*
* 2) Optionally, configure the interrupt requests if the interrupt event
* triggering is needed. Use the Cy_LPComp_SetInterruptMask() function with
* the parameter for the mask available in the configuration file.
* Additionally, enable the Global interrupts and initialize the referenced
* interrupt by setting the priority and the interrupt vector using
* the \ref Cy_SysInt_Init() function of the sysint driver.
*
* 3) Configure the inputs and the output using the \ref Cy_GPIO_Pin_Init()
* functions of the GPIO driver.
* The High Impedance Analog drive mode is for the inputs and
* the Strong drive mode is for the output.
* Use the Cy_LPComp_SetInputs() function to connect the comparator inputs
* to the dedicated IO pins, AMUXBUSA/AMUXBUSB or Vref:
* \image html lpcomp_inputs.png
*
* 4) Power on the comparator using the Cy_LPComp_SetPower() function.
*
* 5) Optionally, enable the comparator interrupt using
* Cy_LPComp_SetInterruptTriggerMode() with the corresponding parameter
* for the interrupt mode (Rising edge, Falling edge, or Both edges).
*
* 6) The comparator output can be monitored using
* the Cy_LPComp_GetCompare() function or using the LPComp interrupt
* (if the interrupt is enabled).
*
* NOTE 1: To prevent false triggering, a delay before enabling
* the comparator interrupt is required. The recommended delay is
* 10 us for the Normal power mode and 50 us for the Ultra low-power mode.
*
* NOTE 2: The interrupt is not cleared automatically.
* It is the user's responsibility to do that.
* The interrupt is cleared by writing a 1 in the corresponding interrupt
* register bit position. The preferred way to clear interrupt sources
* is using the Cy_LPComp_ClearInterrupt() function.
*
* NOTE 3: Individual comparator interrupt outputs are ORed together
* as a single asynchronous interrupt source before it is sent out and
* used to wake up the system in the low-power mode.
* For PSoC 6 devices, the individual comparator interrupt is masked
* by the INTR_MASK register. The masked result is captured in
* the INTR_MASKED register.
* Writing a 1 to the INTR register bit will clear the interrupt.
*
* \section group_lpcomp_more_information More Information
*
* Refer to the appropriate device technical reference manual (TRM) for
* a detailed description of the registers.
*
* \section group_lpcomp_MISRA MISRA-C Compliance
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>11.4</td>
* <td>A</td>
* <td>A cast should not be performed between a pointer to object type and
* a different pointer to object type.</td>
* <td>
* The pointer to the buffer memory is void to allow handling different
* different data types: uint8_t (4-8 bits) or uint16_t (9-16 bits).
* The cast operation is safe because the configuration is verified
* before operation is performed.
* The function \ref Cy_LPComp_DeepSleepCallback is a callback of
* the \ref cy_en_syspm_status_t type. The cast operation safety in this
* function becomes the user's responsibility because the pointers are
* initialized when a callback is registered in the SysPm driver.</td>
* </tr>
* </table>
*
* \section group_lpcomp_Changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* <tr>
* <td>1.10</td>
* <td>The CY_WEAK keyword is removed from Cy_LPComp_DeepSleepCallback()
* and Cy_LPComp_HibernateCallback() functions<br>
* Added input parameter validation to the API functions.</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_lpcomp_macros Macros
* \defgroup group_lpcomp_functions Functions
* \defgroup group_lpcomp_data_structures Data structures
* \defgroup group_lpcomp_enums Enumerated Types
*/
#ifndef CY_LPCOMP_PDL_H
#define CY_LPCOMP_PDL_H
/******************************************************************************/
/* Include files */
/******************************************************************************/
#include <stdbool.h>
#include <stddef.h>
#include "cy_device_headers.h"
#include "syslib/cy_syslib.h"
#include "syspm/cy_syspm.h"
#ifndef CY_IP_MXLPCOMP
#error "The LPCOMP driver is not supported on this device"
#endif
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/**
* \addtogroup group_lpcomp_macros
* \{
*/
/** Driver major version */
#define CY_LPCOMP_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_LPCOMP_DRV_VERSION_MINOR 10
/******************************************************************************
* API Constants
******************************************************************************/
/**< LPCOMP PDL ID */
#define CY_LPCOMP_ID CY_PDL_DRV_ID(0x23u)
/** The LPCOMP's number of channels. */
#define CY_LPCOMP_MAX_CHANNEL_NUM (2u)
/** LPCOMP's comparator 1 interrupt mask. */
#define CY_LPCOMP_COMP0 (0x01u)
/** LPCOMP's comparator 2 interrupt mask. */
#define CY_LPCOMP_COMP1 (0x02u)
/** \cond INTERNAL_MACROS */
/******************************************************************************
* Registers Constants
******************************************************************************/
#define CY_LPCOMP_MODE_ULP_Pos (0x0uL)
#define CY_LPCOMP_MODE_ULP_Msk (0x1uL)
#define CY_LPCOMP_INTR_Pos (LPCOMP_INTR_COMP0_Pos)
#define CY_LPCOMP_INTR_Msk (LPCOMP_INTR_COMP0_Msk | LPCOMP_INTR_COMP1_Msk)
#define CY_LPCOMP_CMP0_SW_POS_Msk (LPCOMP_CMP0_SW_CMP0_IP0_Msk | \
LPCOMP_CMP0_SW_CMP0_AP0_Msk | \
LPCOMP_CMP0_SW_CMP0_BP0_Msk)
#define CY_LPCOMP_CMP0_SW_NEG_Msk (LPCOMP_CMP0_SW_CMP0_IN0_Msk | \
LPCOMP_CMP0_SW_CMP0_AN0_Msk | \
LPCOMP_CMP0_SW_CMP0_BN0_Msk | \
LPCOMP_CMP0_SW_CMP0_VN0_Msk)
#define CY_LPCOMP_CMP1_SW_POS_Msk (LPCOMP_CMP1_SW_CMP1_IP1_Msk | \
LPCOMP_CMP1_SW_CMP1_AP1_Msk | \
LPCOMP_CMP1_SW_CMP1_BP1_Msk)
#define CY_LPCOMP_CMP1_SW_NEG_Msk (LPCOMP_CMP1_SW_CMP1_IN1_Msk | \
LPCOMP_CMP1_SW_CMP1_AN1_Msk | \
LPCOMP_CMP1_SW_CMP1_BN1_Msk | \
LPCOMP_CMP1_SW_CMP1_VN1_Msk)
#define CY_LPCOMP_CMP0_OUTPUT_CONFIG_Pos LPCOMP_CMP0_CTRL_DSI_BYPASS0_Pos
#define CY_LPCOMP_CMP1_OUTPUT_CONFIG_Pos LPCOMP_CMP1_CTRL_DSI_BYPASS1_Pos
#define CY_LPCOMP_CMP0_OUTPUT_CONFIG_Msk (LPCOMP_CMP0_CTRL_DSI_BYPASS0_Msk | \
LPCOMP_CMP0_CTRL_DSI_LEVEL0_Msk)
#define CY_LPCOMP_CMP1_OUTPUT_CONFIG_Msk (LPCOMP_CMP1_CTRL_DSI_BYPASS1_Msk | \
LPCOMP_CMP1_CTRL_DSI_LEVEL1_Msk)
#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR_Pos HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_Pos
#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_SR_Msk (HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_Msk | \
HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SR_Msk)
#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR_Pos HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_Pos
#define CY_HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_SR_Msk (HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_Msk | \
HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SR_Msk)
#define CY_LPCOMP_REF_CONNECTED (1u)
#define CY_LPCOMP_WAKEUP_PIN0_Msk CY_SYSPM_WAKEUP_LPCOMP0
#define CY_LPCOMP_WAKEUP_PIN1_Msk CY_SYSPM_WAKEUP_LPCOMP1
/** \endcond */
/** \} group_lpcomp_macros */
/**
* \addtogroup group_lpcomp_enums
* \{
*/
/******************************************************************************
* Enumerations
*****************************************************************************/
/** The LPCOMP output modes. */
typedef enum
{
CY_LPCOMP_OUT_PULSE = 0u, /**< The LPCOMP DSI output with the pulse option, no bypass. */
CY_LPCOMP_OUT_DIRECT = 1u, /**< The LPCOMP bypass mode, the direct output of a comparator. */
CY_LPCOMP_OUT_SYNC = 2u /**< The LPCOMP DSI output with the level option, it is similar
to the bypass mode but it is 1 cycle slow than the bypass. */
} cy_en_lpcomp_out_t;
/** The LPCOMP hysteresis modes. */
typedef enum
{
CY_LPCOMP_HYST_ENABLE = 1u, /**< The LPCOMP enable hysteresis. */
CY_LPCOMP_HYST_DISABLE = 0u /**< The LPCOMP disable hysteresis. */
} cy_en_lpcomp_hyst_t;
/** The LPCOMP's channel number. */
typedef enum
{
CY_LPCOMP_CHANNEL_0 = 0x1u, /**< The LPCOMP Comparator 0. */
CY_LPCOMP_CHANNEL_1 = 0x2u /**< The LPCOMP Comparator 1. */
} cy_en_lpcomp_channel_t;
/** The LPCOMP interrupt modes. */
typedef enum
{
CY_LPCOMP_INTR_DISABLE = 0u, /**< The LPCOMP interrupt disabled, no interrupt will be detected. */
CY_LPCOMP_INTR_RISING = 1u, /**< The LPCOMP interrupt on the rising edge. */
CY_LPCOMP_INTR_FALLING = 2u, /**< The LPCOMP interrupt on the falling edge. */
CY_LPCOMP_INTR_BOTH = 3u /**< The LPCOMP interrupt on both rising and falling edges. */
} cy_en_lpcomp_int_t;
/** The LPCOMP power-mode selection. */
typedef enum
{
CY_LPCOMP_MODE_OFF = 0u, /**< The LPCOMP's channel power-off. */
CY_LPCOMP_MODE_ULP = 1u, /**< The LPCOMP's channel ULP mode. */
CY_LPCOMP_MODE_LP = 2u, /**< The LPCOMP's channel LP mode. */
CY_LPCOMP_MODE_NORMAL = 3u /**< The LPCOMP's channel normal mode. */
} cy_en_lpcomp_pwr_t;
/** The LPCOMP inputs. */
typedef enum
{
CY_LPCOMP_SW_GPIO = 0x01u, /**< The LPCOMP input connects to GPIO pin. */
CY_LPCOMP_SW_AMUXBUSA = 0x02u, /**< The LPCOMP input connects to AMUXBUSA. */
CY_LPCOMP_SW_AMUXBUSB = 0x04u, /**< The LPCOMP input connects to AMUXBUSB. */
CY_LPCOMP_SW_LOCAL_VREF = 0x08u /**< The LPCOMP input connects to local VREF. */
} cy_en_lpcomp_inputs_t;
/** The LPCOMP error codes. */
typedef enum
{
CY_LPCOMP_SUCCESS = 0x00u, /**< Successful */
CY_LPCOMP_BAD_PARAM = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0x01u, /**< One or more invalid parameters */
CY_LPCOMP_TIMEOUT = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0x02u, /**< Operation timed out */
CY_LPCOMP_INVALID_STATE = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0x03u, /**< Operation not setup or is in an improper state */
CY_LPCOMP_UNKNOWN = CY_LPCOMP_ID | CY_PDL_STATUS_ERROR | 0xFFu, /**< Unknown failure */
} cy_en_lpcomp_status_t;
/** \} group_lpcomp_enums */
/**
* \addtogroup group_lpcomp_data_structures
* \{
*/
/******************************************************************************
* Structures
*****************************************************************************/
/** The LPCOMP configuration structure. */
typedef struct {
cy_en_lpcomp_out_t outputMode; /**< The LPCOMP's outputMode: Direct output,
Synchronized output or Pulse output */
cy_en_lpcomp_hyst_t hysteresis; /**< Enables or disables the LPCOMP's hysteresis */
} cy_stc_lpcomp_config_t;
/** \} group_lpcomp_data_structures */
/** \cond INTERNAL_MACROS */
/******************************************************************************
* Macros
*****************************************************************************/
#define CY_LPCOMP_IS_CHANNEL_VALID(channel) (((channel) == CY_LPCOMP_CHANNEL_0) || \
((channel) == CY_LPCOMP_CHANNEL_1))
#define CY_LPCOMP_IS_OUT_MODE_VALID(mode) (((mode) == CY_LPCOMP_OUT_PULSE) || \
((mode) == CY_LPCOMP_OUT_DIRECT) || \
((mode) == CY_LPCOMP_OUT_SYNC))
#define CY_LPCOMP_IS_HYSTERESIS_VALID(hyst) (((hyst) == CY_LPCOMP_HYST_ENABLE) || \
((hyst) == CY_LPCOMP_HYST_DISABLE))
#define CY_LPCOMP_IS_INTR_MODE_VALID(intr) (((intr) == CY_LPCOMP_INTR_DISABLE) || \
((intr) == CY_LPCOMP_INTR_RISING) || \
((intr) == CY_LPCOMP_INTR_FALLING) || \
((intr) == CY_LPCOMP_INTR_BOTH))
#define CY_LPCOMP_IS_POWER_VALID(power) (((power) == CY_LPCOMP_MODE_OFF) || \
((power) == CY_LPCOMP_MODE_ULP) || \
((power) == CY_LPCOMP_MODE_LP) || \
((power) == CY_LPCOMP_MODE_NORMAL))
#define CY_LPCOMP_IS_INTR_VALID(intr) (((intr) == CY_LPCOMP_COMP0) || \
((intr) == CY_LPCOMP_COMP1) || \
((intr) == (CY_LPCOMP_COMP0 | CY_LPCOMP_COMP1)))
#define CY_LPCOMP_IS_INPUT_P_VALID(input) (((input) == CY_LPCOMP_SW_GPIO) || \
((input) == CY_LPCOMP_SW_AMUXBUSA) || \
((input) == CY_LPCOMP_SW_AMUXBUSB))
#define CY_LPCOMP_IS_INPUT_N_VALID(input) (((input) == CY_LPCOMP_SW_GPIO) || \
((input) == CY_LPCOMP_SW_AMUXBUSA) || \
((input) == CY_LPCOMP_SW_AMUXBUSB) || \
((input) == CY_LPCOMP_SW_LOCAL_VREF))
/** \endcond */
/**
* \addtogroup group_lpcomp_functions
* \{
*/
/******************************************************************************
* Functions
*******************************************************************************/
cy_en_lpcomp_status_t Cy_LPComp_Init(LPCOMP_Type *base, cy_en_lpcomp_channel_t channel, const cy_stc_lpcomp_config_t *config);
__STATIC_INLINE void Cy_LPComp_GlobalEnable(LPCOMP_Type *base);
__STATIC_INLINE void Cy_LPComp_GlobalDisable(LPCOMP_Type *base);
__STATIC_INLINE void Cy_LPComp_UlpReferenceEnable(LPCOMP_Type *base);
__STATIC_INLINE void Cy_LPComp_UlpReferenceDisable(LPCOMP_Type *base);
__STATIC_INLINE uint32_t Cy_LPComp_GetCompare(LPCOMP_Type const * base, cy_en_lpcomp_channel_t channel);
void Cy_LPComp_SetPower(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_pwr_t power);
void Cy_LPComp_SetHysteresis(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_hyst_t hysteresis);
void Cy_LPComp_SetInputs(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_inputs_t inputP, cy_en_lpcomp_inputs_t inputN);
void Cy_LPComp_SetOutputMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_out_t outType);
void Cy_LPComp_SetInterruptTriggerMode(LPCOMP_Type* base, cy_en_lpcomp_channel_t channel, cy_en_lpcomp_int_t intType);
__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatus(LPCOMP_Type const * base);
__STATIC_INLINE void Cy_LPComp_ClearInterrupt(LPCOMP_Type* base, uint32_t interrupt);
__STATIC_INLINE void Cy_LPComp_SetInterrupt(LPCOMP_Type* base, uint32_t interrupt);
__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptMask(LPCOMP_Type const * base);
__STATIC_INLINE void Cy_LPComp_SetInterruptMask(LPCOMP_Type* base, uint32_t interrupt);
__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatusMasked(LPCOMP_Type const * base);
__STATIC_INLINE void Cy_LPComp_ConnectULPReference(LPCOMP_Type *base, cy_en_lpcomp_channel_t channel);
cy_en_syspm_status_t Cy_LPComp_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams);
cy_en_syspm_status_t Cy_LPComp_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams);
/*******************************************************************************
* Function Name: Cy_LPComp_GlobalEnable
****************************************************************************//**
*
* Activates the IP of the LPCOMP hardware block. This API should be enabled
* before operating any channel of comparators.
* Note: Interrupts can be enabled after the block is enabled and the appropriate
* start-up time has elapsed:
* 3 us for the normal power mode;
* 6 us for the LP mode;
* 50 us for the ULP mode.
*
* \param *base
* The structure of the channel pointer.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_GlobalEnable(LPCOMP_Type* base)
{
base->CONFIG |= LPCOMP_CONFIG_ENABLED_Msk;
}
/*******************************************************************************
* Function Name: Cy_LPComp_GlobalDisable
****************************************************************************//**
*
* Deactivates the IP of the LPCOMP hardware block.
* (Analog in power down, open all switches, all clocks off).
*
* \param *base
* The structure of the channel pointer.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_GlobalDisable(LPCOMP_Type *base)
{
base->CONFIG &= (uint32_t) ~LPCOMP_CONFIG_ENABLED_Msk;
}
/*******************************************************************************
* Function Name: Cy_LPComp_UlpReferenceEnable
****************************************************************************//**
*
* Enables the local reference-generator circuit.
*
* \param *base
* The structure of the channel pointer.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_UlpReferenceEnable(LPCOMP_Type *base)
{
base->CONFIG |= LPCOMP_CONFIG_LPREF_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_LPComp_UlpReferenceDisable
****************************************************************************//**
*
* Disables the local reference-generator circuit.
*
* \param *base
* The structure of the channel pointer.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_UlpReferenceDisable(LPCOMP_Type *base)
{
base->CONFIG &= (uint32_t) ~LPCOMP_CONFIG_LPREF_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_LPComp_GetCompare
****************************************************************************//**
*
* This function returns a nonzero value when the voltage connected to the
* positive input is greater than the negative input voltage.
* This function reads the direct (unflopped) comparator output, which can
* also be metastable (since it may result in incorrect data).
*
* \param *base
* The LPComp register structure pointer.
*
* \param channel
* The LPComp channel index.
*
* \return LPComp compare result.
* The value is a nonzero value when the voltage connected to the positive
* input is greater than the negative input voltage.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LPComp_GetCompare(LPCOMP_Type const * base, cy_en_lpcomp_channel_t channel)
{
uint32_t result;
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
if (CY_LPCOMP_CHANNEL_0 == channel)
{
result = _FLD2VAL(LPCOMP_STATUS_OUT0, base->STATUS);
}
else
{
result = _FLD2VAL(LPCOMP_STATUS_OUT1, base->STATUS);
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetInterruptMask
****************************************************************************//**
*
* Configures which bits of the interrupt request register will trigger an
* interrupt event.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param interrupt
* uint32_t interruptMask: Bit Mask of interrupts to set.
* Bit 0: COMP0 Interrupt Mask
* Bit 1: COMP1 Interrupt Mask
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_SetInterruptMask(LPCOMP_Type* base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_LPCOMP_IS_INTR_VALID(interrupt));
base->INTR_MASK |= interrupt;
}
/*******************************************************************************
* Function Name: Cy_LPComp_GetInterruptMask
****************************************************************************//**
*
* Returns an interrupt mask.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \return bit mapping information
* Bit 0: COMP0 Interrupt Mask
* Bit 1: COMP1 Interrupt Mask
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptMask(LPCOMP_Type const * base)
{
return (base->INTR_MASK);
}
/*******************************************************************************
* Function Name: Cy_LPComp_GetInterruptStatusMasked
****************************************************************************//**
*
* Returns an interrupt request register masked by an interrupt mask.
* Returns the result of the bitwise AND operation between the corresponding
* interrupt request and mask bits.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \return bit mapping information
* Bit 0: COMP0 Interrupt Masked
* Bit 1: COMP1 Interrupt Masked
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatusMasked(LPCOMP_Type const * base)
{
return (base->INTR_MASKED);
}
/*******************************************************************************
* Function Name: Cy_LPComp_GetInterruptStatus
****************************************************************************//**
*
* Returns the status of 2 different LPCOMP interrupt requests.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \return bit mapping information
* Bit 0: COMP0 Interrupt status
* Bit 1: COMP1 Interrupt status
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LPComp_GetInterruptStatus(LPCOMP_Type const * base)
{
return (_FLD2VAL(CY_LPCOMP_INTR, base->INTR));
}
/*******************************************************************************
* Function Name: Cy_LPComp_ClearInterrupt
****************************************************************************//**
*
* Clears LPCOMP interrupts by setting each bit.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param interrupt
* Bit 0: COMP0 Interrupt status
* Bit 1: COMP1 Interrupt status
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_ClearInterrupt(LPCOMP_Type* base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_LPCOMP_IS_INTR_VALID(interrupt));
base->INTR |= interrupt;
(void) LPCOMP->INTR;
}
/*******************************************************************************
* Function Name: Cy_LPComp_SetInterrupt
****************************************************************************//**
*
* Sets a software interrupt request.
* This function is used in the case of combined interrupt signal from the global
* signal reference. This function from either component instance can be used
* to trigger either or both software interrupts. It sets the INTR_SET interrupt mask.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param interrupt
* Bit 0: COMP0 Interrupt status
* Bit 1: COMP1 Interrupt status
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_SetInterrupt(LPCOMP_Type* base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_LPCOMP_IS_INTR_VALID(interrupt));
base->INTR_SET = interrupt;
}
/*******************************************************************************
* Function Name: Cy_LPComp_ConnectULPReference
****************************************************************************//**
*
* Connects the local reference generator output to the comparator negative input.
*
* \param *base
* The LPCOMP register structure pointer.
*
* \param channel
* The LPCOMP channel index.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_LPComp_ConnectULPReference(LPCOMP_Type *base, cy_en_lpcomp_channel_t channel)
{
CY_ASSERT_L3(CY_LPCOMP_IS_CHANNEL_VALID(channel));
if (CY_LPCOMP_CHANNEL_0 == channel)
{
base->CMP0_SW_CLEAR = CY_LPCOMP_CMP0_SW_NEG_Msk;
base->CMP0_SW = _CLR_SET_FLD32U(base->CMP0_SW, LPCOMP_CMP0_SW_CMP0_VN0, CY_LPCOMP_REF_CONNECTED);
}
else
{
base->CMP1_SW_CLEAR = CY_LPCOMP_CMP1_SW_NEG_Msk;
base->CMP1_SW = _CLR_SET_FLD32U(base->CMP1_SW, LPCOMP_CMP1_SW_CMP1_VN1, CY_LPCOMP_REF_CONNECTED);
}
}
/** \} group_lpcomp_functions */
#ifdef __cplusplus
}
#endif
#endif /* CY_LPCOMP_PDL_H */
/** \} group_lpcomp */
/* [] END OF FILE */

View File

@ -0,0 +1,64 @@
/***************************************************************************//**
* \file cy_lvd.c
* \version 1.0
*
* The source code file for the LVD driver.
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_lvd.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* Function Name: Cy_LVD_DeepSleepCallback
****************************************************************************//**
*
* When this function is registered by \ref Cy_SysPm_RegisterCallback - it
* automatically enables the LVD after wake up from DeepSleep mode.
*
* \param callbackParams a pointer to the callback parameters structure,
* see \ref cy_stc_syspm_callback_params_t.
*
* \return the SysPm callback status \ref cy_en_syspm_status_t.
*
*******************************************************************************/
cy_en_syspm_status_t Cy_LVD_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams)
{
cy_en_syspm_status_t ret = CY_SYSPM_SUCCESS;
switch(callbackParams->mode)
{
case CY_SYSPM_CHECK_READY:
case CY_SYSPM_CHECK_FAIL:
case CY_SYSPM_BEFORE_TRANSITION:
break;
case CY_SYSPM_AFTER_TRANSITION:
Cy_LVD_Enable();
break;
default:
ret = CY_SYSPM_FAIL;
break;
}
return(ret);
}
#ifdef __cplusplus
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,423 @@
/***************************************************************************//**
* \file cy_lvd.h
* \version 1.0
*
* The header file of the LVD driver.
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \addtogroup group_lvd
* \{
* The LVD driver provides an API to manage the Low Voltage Detection block.
* The LVD block provides a status of currently observed VDDD voltage
* and triggers an interrupt when the observed voltage crosses an adjusted
* threshold.
*
* \section group_lvd_configuration_considerations Configuration Considerations
* To set up an LVD, configure the voltage threshold by the
* \ref Cy_LVD_SetThreshold function, ensure that the LVD block itself and LVD
* interrupt are disabled (by the \ref Cy_LVD_Disable and
* \ref Cy_LVD_ClearInterruptMask functions correspondingly) before changing the
* threshold to prevent propagating a false interrupt.
* Then configure interrupts by the \ref Cy_LVD_SetInterruptConfig function, do
* not forget to initialise an interrupt handler (the interrupt source number
* is srss_interrupt_IRQn).
* Then enable LVD by the \ref Cy_LVD_Enable function, then wait for at least 8us
* to get the circuit stabilized and clear the possible false interrupts by the
* \ref Cy_LVD_ClearInterrupt, and finally the LVD interrupt can be enabled by
* the \ref Cy_LVD_SetInterruptMask function.
*
* For example:
* \snippet lvd_1_0_sut_00.cydsn/main_cm4.c Cy_LVD_Snippet
*
* Note that the LVD circuit is available only in Active, LPACTIVE, Sleep, and
* LPSLEEP power modes. If an LVD is required in Deep-Sleep mode, then the device
* should be configured to periodically wake up from deep sleep using a
* Deep-Sleep wakeup source. This makes sure a LVD check is performed during
* Active/LPACTIVE mode.
*
* \section group_lvd_more_information More Information
* See the LVD chapter of the device technical reference manual (TRM).
*
* \section group_lvd_MISRA MISRA-C Compliance
* The LVD driver has the following specific deviations:
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>10.3</td>
* <td>R</td>
* <td>A composite expression of 'essentially unsigned' type (%1s) is being
* cast to a different type category, '%2s'.</td>
* <td>The value got from the bitfield physically can't exceed the enumeration
* that describes this bitfield. So the code is safety by design.</td>
* </tr>
* <tr>
* <td>16.7</td>
* <td>A</td>
* <td>The object addressed by the pointer parameter '%s' is not modified and
* so the pointer could be of type 'pointer to const'.</td>
* <td>The pointer parameter is not used or modified, as there is no need
* to do any actions with it. However, such parameter is
* required to be presented in the function, because the
* \ref Cy_LVD_DeepSleepCallback is a callback
* of \ref cy_en_syspm_status_t type.
* The SysPM driver callback function type requires implementing the
* function with the next parameters and return value: <br>
* cy_en_syspm_status_t (*Cy_SysPmCallback)
* (cy_stc_syspm_callback_params_t *callbackParams);</td>
* </tr>
* </table>
*
* \section group_lvd_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason of Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial Version</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_lvd_macros Macros
* \defgroup group_lvd_functions Functions
* \defgroup group_lvd_enums Enumerated types
*/
#if !defined CY_LVD_H
#define CY_LVD_H
#include "syspm/cy_syspm.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \addtogroup group_lvd_macros
* \{
*/
/** Driver major version */
#define CY_LVD_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_LVD_DRV_VERSION_MINOR 0
/** LVD driver identifier */
#define CY_LVD_ID (CY_PDL_DRV_ID(0x39U))
/** Interrupt mask for \ref Cy_LVD_GetInterruptStatus(),
\ref Cy_LVD_GetInterruptMask() and
\ref Cy_LVD_GetInterruptStatusMasked() */
#define CY_LVD_INTR (SRSS_SRSS_INTR_HVLVD1_Msk)
/** \} group_lvd_macros */
/** \addtogroup group_lvd_enums
* \{
*/
/**
* LVD reference voltage select.
*/
typedef enum
{
CY_LVD_THRESHOLD_1_2_V = 0x0U, /**<Select LVD reference voltage: 1.2V */
CY_LVD_THRESHOLD_1_4_V = 0x1U, /**<Select LVD reference voltage: 1.4V */
CY_LVD_THRESHOLD_1_6_V = 0x2U, /**<Select LVD reference voltage: 1.6V */
CY_LVD_THRESHOLD_1_8_V = 0x3U, /**<Select LVD reference voltage: 1.8V */
CY_LVD_THRESHOLD_2_0_V = 0x4U, /**<Select LVD reference voltage: 2.0V */
CY_LVD_THRESHOLD_2_1_V = 0x5U, /**<Select LVD reference voltage: 2.1V */
CY_LVD_THRESHOLD_2_2_V = 0x6U, /**<Select LVD reference voltage: 2.2V */
CY_LVD_THRESHOLD_2_3_V = 0x7U, /**<Select LVD reference voltage: 2.3V */
CY_LVD_THRESHOLD_2_4_V = 0x8U, /**<Select LVD reference voltage: 2.4V */
CY_LVD_THRESHOLD_2_5_V = 0x9U, /**<Select LVD reference voltage: 2.5V */
CY_LVD_THRESHOLD_2_6_V = 0xAU, /**<Select LVD reference voltage: 2.6V */
CY_LVD_THRESHOLD_2_7_V = 0xBU, /**<Select LVD reference voltage: 2.7V */
CY_LVD_THRESHOLD_2_8_V = 0xCU, /**<Select LVD reference voltage: 2.8V */
CY_LVD_THRESHOLD_2_9_V = 0xDU, /**<Select LVD reference voltage: 2.9V */
CY_LVD_THRESHOLD_3_0_V = 0xEU, /**<Select LVD reference voltage: 3.0V */
CY_LVD_THRESHOLD_3_1_V = 0xFU /**<Select LVD reference voltage: 3.1V */
} cy_en_lvd_tripsel_t;
/**
* LVD interrupt configuration select.
*/
typedef enum
{
CY_LVD_INTR_DISABLE = 0x0U, /**<Select LVD interrupt: disabled */
CY_LVD_INTR_RISING = 0x1U, /**<Select LVD interrupt: rising edge */
CY_LVD_INTR_FALLING = 0x2U, /**<Select LVD interrupt: falling edge */
CY_LVD_INTR_BOTH = 0x3U, /**<Select LVD interrupt: both edges */
} cy_en_lvd_intr_config_t;
/**
* LVD output status.
*/
typedef enum
{
CY_LVD_STATUS_BELOW = 0x0U, /**<The voltage is below the threshold */
CY_LVD_STATUS_ABOVE = 0x1U, /**<The voltage is above the threshold */
} cy_en_lvd_status_t;
/** \} group_lvd_enums */
/** \cond internal */
/* Macros for conditions used by CY_ASSERT calls */
#define CY_LVD_CHECK_TRIPSEL(threshold) (((threshold) == CY_LVD_THRESHOLD_1_2_V) || \
((threshold) == CY_LVD_THRESHOLD_1_4_V) || \
((threshold) == CY_LVD_THRESHOLD_1_6_V) || \
((threshold) == CY_LVD_THRESHOLD_1_8_V) || \
((threshold) == CY_LVD_THRESHOLD_2_0_V) || \
((threshold) == CY_LVD_THRESHOLD_2_1_V) || \
((threshold) == CY_LVD_THRESHOLD_2_2_V) || \
((threshold) == CY_LVD_THRESHOLD_2_3_V) || \
((threshold) == CY_LVD_THRESHOLD_2_4_V) || \
((threshold) == CY_LVD_THRESHOLD_2_5_V) || \
((threshold) == CY_LVD_THRESHOLD_2_6_V) || \
((threshold) == CY_LVD_THRESHOLD_2_7_V) || \
((threshold) == CY_LVD_THRESHOLD_2_8_V) || \
((threshold) == CY_LVD_THRESHOLD_2_9_V) || \
((threshold) == CY_LVD_THRESHOLD_3_0_V) || \
((threshold) == CY_LVD_THRESHOLD_3_1_V))
#define CY_LVD_CHECK_INTR_CFG(intrCfg) (((intrCfg) == CY_LVD_INTR_DISABLE) || \
((intrCfg) == CY_LVD_INTR_RISING) || \
((intrCfg) == CY_LVD_INTR_FALLING) || \
((intrCfg) == CY_LVD_INTR_BOTH))
/** \endcond */
/**
* \addtogroup group_lvd_functions
* \{
*/
__STATIC_INLINE void Cy_LVD_Enable(void);
__STATIC_INLINE void Cy_LVD_Disable(void);
__STATIC_INLINE void Cy_LVD_SetThreshold(cy_en_lvd_tripsel_t threshold);
__STATIC_INLINE cy_en_lvd_status_t Cy_LVD_GetStatus(void);
__STATIC_INLINE uint32_t Cy_LVD_GetInterruptStatus(void);
__STATIC_INLINE void Cy_LVD_ClearInterrupt(void);
__STATIC_INLINE void Cy_LVD_SetInterrupt(void);
__STATIC_INLINE uint32_t Cy_LVD_GetInterruptMask(void);
__STATIC_INLINE void Cy_LVD_SetInterruptMask(void);
__STATIC_INLINE void Cy_LVD_ClearInterruptMask(void);
__STATIC_INLINE uint32_t Cy_LVD_GetInterruptStatusMasked(void);
__STATIC_INLINE void Cy_LVD_SetInterruptConfig(cy_en_lvd_intr_config_t lvdInterruptConfig);
cy_en_syspm_status_t Cy_LVD_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams);
/*******************************************************************************
* Function Name: Cy_LVD_Enable
****************************************************************************//**
*
* Enables the output of the LVD block when the VDDD voltage is
* at or below the threshold.
* See the Configuration Considerations section for details.
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_Enable(void)
{
SRSS->PWR_LVD_CTL |= SRSS_PWR_LVD_CTL_HVLVD1_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_LVD_Disable
****************************************************************************//**
*
* Disables the LVD block. A low voltage detection interrupt is disabled.
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_Disable(void)
{
SRSS->PWR_LVD_CTL &= (uint32_t) ~SRSS_PWR_LVD_CTL_HVLVD1_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_LVD_SetThreshold
****************************************************************************//**
*
* Sets a threshold for monitoring the VDDD voltage.
* To prevent propagating a false interrupt, before changing the threshold
* ensure that the LVD block itself and LVD interrupt are disabled by the
* \ref Cy_LVD_Disable and \ref Cy_LVD_ClearInterruptMask functions
* correspondingly.
*
* \param threshold
* Threshold selection for Low Voltage Detect circuit, \ref cy_en_lvd_tripsel_t.
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_SetThreshold(cy_en_lvd_tripsel_t threshold)
{
CY_ASSERT_L3(CY_LVD_CHECK_TRIPSEL(threshold));
SRSS->PWR_LVD_CTL = _CLR_SET_FLD32U(SRSS->PWR_LVD_CTL, SRSS_PWR_LVD_CTL_HVLVD1_TRIPSEL, threshold);
}
/*******************************************************************************
* Function Name: Cy_LVD_GetStatus
****************************************************************************//**
*
* Returns the status of LVD.
* SRSS LVD Status Register (PWR_LVD_STATUS).
*
* \return LVD status, \ref cy_en_lvd_status_t.
*
*******************************************************************************/
__STATIC_INLINE cy_en_lvd_status_t Cy_LVD_GetStatus(void)
{
return ((cy_en_lvd_status_t) _FLD2VAL(SRSS_PWR_LVD_STATUS_HVLVD1_OK, SRSS->PWR_LVD_STATUS));
}
/*******************************************************************************
* Function Name: Cy_LVD_GetInterruptStatus
****************************************************************************//**
*
* Returns the status of LVD interrupt.
* SRSS Interrupt Register (SRSS_INTR).
*
* \return SRSS Interrupt status, \ref CY_LVD_INTR.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LVD_GetInterruptStatus(void)
{
return (SRSS->SRSS_INTR & SRSS_SRSS_INTR_HVLVD1_Msk);
}
/*******************************************************************************
* Function Name: Cy_LVD_ClearInterrupt
****************************************************************************//**
*
* Clears LVD interrupt.
* SRSS Interrupt Register (SRSS_INTR).
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_ClearInterrupt(void)
{
SRSS->SRSS_INTR = SRSS_SRSS_INTR_HVLVD1_Msk;
(void) SRSS->SRSS_INTR;
}
/*******************************************************************************
* Function Name: Cy_LVD_SetInterrupt
****************************************************************************//**
*
* Triggers the device to generate interrupt for LVD.
* SRSS Interrupt Set Register (SRSS_INTR_SET).
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_SetInterrupt(void)
{
SRSS->SRSS_INTR_SET = SRSS_SRSS_INTR_SET_HVLVD1_Msk;
}
/*******************************************************************************
* Function Name: Cy_LVD_GetInterruptMask
****************************************************************************//**
*
* Returns the mask value of LVD interrupts.
* SRSS Interrupt Mask Register (SRSS_INTR_MASK).
*
* \return SRSS Interrupt Mask value, \ref CY_LVD_INTR.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LVD_GetInterruptMask(void)
{
return (SRSS->SRSS_INTR_MASK & SRSS_SRSS_INTR_MASK_HVLVD1_Msk);
}
/*******************************************************************************
* Function Name: Cy_LVD_SetInterruptMask
****************************************************************************//**
*
* Enables LVD interrupts.
* Sets the LVD interrupt mask in the SRSS_INTR_MASK register.
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_SetInterruptMask(void)
{
SRSS->SRSS_INTR_MASK |= SRSS_SRSS_INTR_MASK_HVLVD1_Msk;
}
/*******************************************************************************
* Function Name: Cy_LVD_ClearInterruptMask
****************************************************************************//**
*
* Disables LVD interrupts.
* Clears the LVD interrupt mask in the SRSS_INTR_MASK register.
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_ClearInterruptMask(void)
{
SRSS->SRSS_INTR_MASK &= (uint32_t) ~SRSS_SRSS_INTR_MASK_HVLVD1_Msk;
}
/*******************************************************************************
* Function Name: Cy_LVD_GetInterruptStatusMasked
****************************************************************************//**
*
* Returns the masked interrupt status which is a bitwise AND between the
* interrupt status and interrupt mask registers.
* SRSS Interrupt Masked Register (SRSS_INTR_MASKED).
*
* \return SRSS Interrupt Masked value, \ref CY_LVD_INTR.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_LVD_GetInterruptStatusMasked(void)
{
return (SRSS->SRSS_INTR_MASKED & SRSS_SRSS_INTR_MASKED_HVLVD1_Msk);
}
/*******************************************************************************
* Function Name: Cy_LVD_SetInterruptConfig
****************************************************************************//**
*
* Sets a configuration for LVD interrupt.
* SRSS Interrupt Configuration Register (SRSS_INTR_CFG).
*
* \param lvdInterruptConfig \ref cy_en_lvd_intr_config_t.
*
*******************************************************************************/
__STATIC_INLINE void Cy_LVD_SetInterruptConfig(cy_en_lvd_intr_config_t lvdInterruptConfig)
{
CY_ASSERT_L3(CY_LVD_CHECK_INTR_CFG(lvdInterruptConfig));
SRSS->SRSS_INTR_CFG = _CLR_SET_FLD32U(SRSS->SRSS_INTR_CFG, SRSS_SRSS_INTR_CFG_HVLVD1_EDGE_SEL, lvdInterruptConfig);
}
/** \} group_lvd_functions */
#ifdef __cplusplus
}
#endif
#endif /* CY_LVD_H */
/** \} group_lvd */
/* [] END OF FILE */

View File

@ -0,0 +1,100 @@
/***************************************************************************//**
* \file cy_mcwdt.c
* \version 1.0
*
* Description:
* Provides a system API for the MCWDT driver.
*
********************************************************************************
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_mcwdt.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* Function Name: Cy_MCWDT_Init
****************************************************************************//**
*
* Initializes the MCWDT block.
*
* \param base
* The base pointer to a structure that describes the registers.
*
* \param config
* The pointer to a structure that contains component configuration data.
*
* \return cy_en_mcwdt_status_t
* *base checking result. If the pointer is NULL, returns error.
*
* \note
* This API should not be called when the counters are running. Prior to calling
* this API the counter should be disabled.
*
*******************************************************************************/
cy_en_mcwdt_status_t Cy_MCWDT_Init(MCWDT_STRUCT_Type *base, cy_stc_mcwdt_config_t const *config)
{
cy_en_mcwdt_status_t ret = CY_MCWDT_BAD_PARAM;
if ((base != NULL) && (config != NULL))
{
base->MCWDT_MATCH = _VAL2FLD(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH1, config->c1Match) |
_VAL2FLD(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0, config->c0Match);
base->MCWDT_CONFIG = _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_BITS2, config->c2ToggleBit) |
_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MODE2, config->c2Mode) |
_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR0, config->c0ClearOnMatch) |
_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR1, config->c1ClearOnMatch) |
(config->c1c2Cascade ? MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE1_2_Msk : 0UL) |
_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MODE1, config->c1Mode) |
(config->c0c1Cascade ? MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE0_1_Msk : 0UL) |
_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MODE0, config->c0Mode);
ret = CY_MCWDT_SUCCESS;
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_DeInit
****************************************************************************//**
*
* De-initializes the MCWDT block, returns register values to their default state.
*
* \param base
* The base pointer to a structure that describes the registers.
*
* \note
* This API should not be called when the counters are running. Prior to calling
* this API the counter should be disabled.
*
*******************************************************************************/
void Cy_MCWDT_DeInit(MCWDT_STRUCT_Type *base)
{
Cy_MCWDT_Unlock(base);
base->MCWDT_CNTLOW = 0UL;
base->MCWDT_CNTHIGH = 0UL;
base->MCWDT_MATCH = 0UL;
base->MCWDT_CONFIG = 0UL;
base->MCWDT_CTL = 0UL;
base->MCWDT_INTR = 0UL;
base->MCWDT_INTR_SET = 0UL;
base->MCWDT_INTR_MASK = 0UL;
}
#if defined(__cplusplus)
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,997 @@
/***************************************************************************//**
* \file cy_mcwdt.h
* \version 1.0
*
* Provides an API declaration of the Cypress PDL 3.0 MCWDT driver
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_mcwdt Multi-Counter Watchdog (MCWDT)
* \{
* MCWDT has two 16-bit counters and one 32-bit counter.
* You can use this driver to create a free-running
* timer or generate periodic interrupts. The driver also
* includes support for the watchdog function to recover from CPU or
* firmware failures.
*
* There are two primary use cases for MCWDT: generating periodic CPU interrupts;
* and implementing a free-running timer. Both have many applications in
* embedded systems:
* * Measuring time between events
* * Generating periodic events
* * Synchronizing actions
* * Real-time clocking
* * Polling
*
* An additional use case is to implement a watchdog used for recovering from a CPU or
* firmware failure.
*
* \section group_mcwdt_configuration Configuration Considerations
*
* Each MCWDT may be configured for a particular product.
* One MCWDT block can be associated with only one CPU during runtime.
* A single MCWDT is not intended to be used by multiple CPUs simultaneously.
* Each block contains three sub-counters, each of which can be configured for
* various system utility functions - free running counter, periodic interrupts,
* watchdog reset, or three interrupts followed by a watchdog reset.
* All counters are clocked by either LFCLK (nominal 32 kHz) or by a cascaded
* counter.
* A simplified diagram of the MCWDT hardware is shown below:
* \image html mcwdt.png
* The frequency of the periodic interrupts can be configured using the Match
* value with combining Clear on match option, which can be set individually
* for each counter using Cy_MCWDT_SetClearOnMatch(). When the Clear on match option
* is not set, the periodic interrupts of the C0 and C1 16-bit sub-counters occur
* after 65535 counts and the match value defines the shift between interrupts
* (see the figure below). The enabled Clear on match option
* resets the counter when the interrupt occurs.
* \image html mcwdt_counters.png
* 32-bit sub-counter C2 does not have Clear on match option.
* The interrupt of counter C2 occurs when the counts equal
* 2<sup>Toggle bit</sup> value.
* \image html mcwdt_subcounters.png
* To set up an MCWDT, provide the configuration parameters in the
* cy_stc_mcwdt_config_t structure. Then call
* Cy_MCWDT_Init() to initialize the driver.
* Call Cy_MCWDT_Enable() to enable all specified counters.
*
* You can also set the mode of operation for any counter. If you choose
* interrupt mode, use Cy_MCWDT_SetInterruptMask() with the
* parameter for the masks described in Macro Section.
* Additionally, enable the Global interrupts and initialize the referenced
* interrupt by setting the priority and the interrupt vector using
* \ref Cy_SysInt_Init() of the sysint driver.
*
* The values of the MCWDT counters can be monitored using
* Cy_MCWDT_GetCount().
*
* \note In addition to the MCWDTs, each device has a separate watchdog timer
* (WDT) that can also be used to generate a watchdog reset or periodic
* interrupts. For more information on the WDT, see the appropriate section
* of the PDL.
*
* \section group_mcwdt_more_information More Information
*
* For more information on the MCWDT peripheral, refer to
* the technical reference manual (TRM).
*
* \section group_mcwdt_MISRA MISRA-C Compliance]
* The mcwdt driver does not have any specific deviations.
*
* \section group_mcwdt_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_mcwdt_macros Macros
* \defgroup group_mcwdt_functions Functions
* \defgroup group_mcwdt_data_structures Data structures
* \defgroup group_mcwdt_enums Enumerated Types
*/
#ifndef CY_MCWDT_H
#define CY_MCWDT_H
#if defined(__cplusplus)
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include "cy_device_headers.h"
#include "syslib/cy_syslib.h"
#ifndef CY_IP_MXS40SRSS_MCWDT
#error "The MCWDT driver is not supported on this device"
#endif
/**
* \addtogroup group_mcwdt_data_structures
* \{
*/
/** The MCWDT component configuration structure. */
typedef struct
{
uint16_t c0Match; /**< The sub-counter#0 match comparison value, for interrupt or watchdog timeout.
Range: 0 - 65535 for c0ClearOnMatch = 0 and 1 - 65535 for
c0ClearOnMatch = 1. */
uint16_t c1Match; /**< The sub-counter#1 match comparison value, for interrupt or watchdog timeout.
Range: 0 - 65535 for c1ClearOnMatch = 0 and 1 - 65535 for
c1ClearOnMatch = 1. */
uint8_t c0Mode; /**< The sub-counter#0 mode. It can have the following values: \ref CY_MCWDT_MODE_NONE,
\ref CY_MCWDT_MODE_INT, \ref CY_MCWDT_MODE_RESET and \ref CY_MCWDT_MODE_INT_RESET. */
uint8_t c1Mode; /**< The sub-counter#1 mode. It can have the following values: \ref CY_MCWDT_MODE_NONE,
\ref CY_MCWDT_MODE_INT, \ref CY_MCWDT_MODE_RESET and \ref CY_MCWDT_MODE_INT_RESET. */
uint8_t c2ToggleBit; /**< The sub-counter#2 Period / Toggle Bit value.
Range: 0 - 31. */
uint8_t c2Mode; /**< The sub-counter#2 mode. It can have the following values: \ref CY_MCWDT_MODE_NONE
and \ref CY_MCWDT_MODE_INT. */
bool c0ClearOnMatch; /**< The sub-counter#0 Clear On Match parameter enabled/disabled.
Range: FALSE - TRUE. */
bool c1ClearOnMatch; /**< The sub-counter#1 Clear On Match parameter enabled/disabled.
Range: FALSE - TRUE. */
bool c0c1Cascade; /**< The sub-counter#1 is clocked by LFCLK or from sub-counter#0 cascade.
Range: FALSE - TRUE. */
bool c1c2Cascade; /**< The sub-counter#2 is clocked by LFCLK or from sub-counter#1 cascade.
Range: FALSE - TRUE. */
} cy_stc_mcwdt_config_t;
/** \} group_mcwdt_data_structures */
/**
* \addtogroup group_mcwdt_macros
* \{
*/
/** Driver major version */
#define CY_MCWDT_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_MCWDT_DRV_VERSION_MINOR 0
/** \cond INTERNAL_MACROS */
/***************************************
* Registers Constants
***************************************/
#define CY_MCWDT_LOCK_CLR0 (1u)
#define CY_MCWDT_LOCK_CLR1 (2u)
#define CY_MCWDT_LOCK_SET01 (3u)
#define CY_MCWDT_BYTE_SHIFT (8u)
#define CY_MCWDT_C0C1_MODE_MASK (3u)
#define CY_MCWDT_C2_MODE_MASK (1u)
/***************************************
* API Constants
***************************************/
#define CY_MCWDT_ALL_WDT_ENABLE_Msk (MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE0_Msk | MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE1_Msk | \
MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE2_Msk)
#define CY_MCWDT_CTR0_Pos (0u)
#define CY_MCWDT_CTR1_Pos (1u)
#define CY_MCWDT_CTR2_Pos (2u)
#define CY_MCWDT_CTR_Pos (0UL)
/** \endcond */
#define CY_MCWDT_ID CY_PDL_DRV_ID(0x35u) /**< MCWDT PDL ID */
#define CY_MCWDT_CTR0 (1UL << CY_MCWDT_CTR0_Pos) /**< The sub-counter#0 mask. This macro is used with functions
that handle multiple counters, including Cy_MCWDT_Enable(),
Cy_MCWDT_Disable(), Cy_MCWDT_ClearInterrupt() and Cy_MCWDT_ResetCounters(). */
#define CY_MCWDT_CTR1 (1UL << CY_MCWDT_CTR1_Pos) /**< The sub-counter#1 mask. This macro is used with functions
that handle multiple counters, including Cy_MCWDT_Enable(),
Cy_MCWDT_Disable(), Cy_MCWDT_ClearInterrupt() and Cy_MCWDT_ResetCounters(). */
#define CY_MCWDT_CTR2 (1UL << CY_MCWDT_CTR2_Pos) /**< The sub-counter#2 mask. This macro is used with functions
that handle multiple counters, including Cy_MCWDT_Enable(),
Cy_MCWDT_Disable(), Cy_MCWDT_ClearInterrupt() and Cy_MCWDT_ResetCounters(). */
#define CY_MCWDT_CTR_Msk (CY_MCWDT_CTR0 | CY_MCWDT_CTR1 | CY_MCWDT_CTR2) /**< The mask for all sub-counters. This macro is used with functions
that handle multiple counters, including Cy_MCWDT_Enable(),
Cy_MCWDT_Disable(), Cy_MCWDT_ClearInterrupt() and Cy_MCWDT_ResetCounters(). */
/** \} group_mcwdt_macros */
/**
* \addtogroup group_mcwdt_enums
* \{
*/
/** The mcwdt sub-counter identifiers. */
typedef enum
{
CY_MCWDT_COUNTER0, /**< Sub-counter#0 identifier. */
CY_MCWDT_COUNTER1, /**< Sub-counter#1 identifier. */
CY_MCWDT_COUNTER2 /**< Sub-counter#2 identifier. */
} cy_en_mcwdtctr_t;
/** The mcwdt modes. */
typedef enum
{
CY_MCWDT_MODE_NONE, /**< The No action mode. It is used for Set/GetMode functions. */
CY_MCWDT_MODE_INT, /**< The Interrupt mode. It is used for Set/GetMode functions. */
CY_MCWDT_MODE_RESET, /**< The Reset mode. It is used for Set/GetMode functions. */
CY_MCWDT_MODE_INT_RESET /**< The Three interrupts then watchdog reset mode. It is used for
Set/GetMode functions. */
} cy_en_mcwdtmode_t;
/** The mcwdt cascading. */
typedef enum
{
CY_MCWDT_CASCADE_NONE, /**< The cascading is disabled. It is used for Set/GetCascade functions. */
CY_MCWDT_CASCADE_C0C1, /**< The sub-counter#1 is clocked by LFCLK or from sub-counter#0 cascade.
It is used for Set/GetCascade functions. */
CY_MCWDT_CASCADE_C1C2, /**< The sub-counter#2 is clocked by LFCLK or from sub-counter#1 cascade.
It is used for Set/GetCascade functions. */
CY_MCWDT_CASCADE_BOTH /**< The sub-counter#1 is clocked by LFCLK or from sub-counter#0 cascade
and the sub-counter#2 is clocked by LFCLK or from sub-counter#1 cascade.
It is used for Set/GetCascade functions. */
} cy_en_mcwdtcascade_t;
/** The MCWDT error codes. */
typedef enum
{
CY_MCWDT_SUCCESS = 0x00u, /**< Successful */
CY_MCWDT_BAD_PARAM = CY_MCWDT_ID | CY_PDL_STATUS_ERROR | 0x01u, /**< One or more invalid parameters */
} cy_en_mcwdt_status_t;
/** \} group_mcwdt_enums */
/*******************************************************************************
* Function Prototypes
*******************************************************************************/
/**
* \addtogroup group_mcwdt_functions
* \{
*/
cy_en_mcwdt_status_t Cy_MCWDT_Init(MCWDT_STRUCT_Type *base, cy_stc_mcwdt_config_t const *config);
void Cy_MCWDT_DeInit(MCWDT_STRUCT_Type *base);
__STATIC_INLINE void Cy_MCWDT_Enable(MCWDT_STRUCT_Type *base, uint32_t counters, uint16_t waitUs);
__STATIC_INLINE void Cy_MCWDT_Disable(MCWDT_STRUCT_Type *base, uint32_t counters, uint16_t waitUs);
__STATIC_INLINE uint32_t Cy_MCWDT_GetEnabledStatus(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter);
__STATIC_INLINE void Cy_MCWDT_Lock(MCWDT_STRUCT_Type *base);
__STATIC_INLINE void Cy_MCWDT_Unlock(MCWDT_STRUCT_Type *base);
__STATIC_INLINE uint32_t Cy_MCWDT_GetLockedStatus(MCWDT_STRUCT_Type const *base);
__STATIC_INLINE void Cy_MCWDT_SetMode(MCWDT_STRUCT_Type *base, cy_en_mcwdtctr_t counter, cy_en_mcwdtmode_t mode);
__STATIC_INLINE cy_en_mcwdtmode_t Cy_MCWDT_GetMode(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter);
__STATIC_INLINE void Cy_MCWDT_SetClearOnMatch(MCWDT_STRUCT_Type *base, cy_en_mcwdtctr_t counter, uint32_t enable);
__STATIC_INLINE uint32_t Cy_MCWDT_GetClearOnMatch(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter);
__STATIC_INLINE void Cy_MCWDT_SetCascade(MCWDT_STRUCT_Type *base, cy_en_mcwdtcascade_t cascade);
__STATIC_INLINE cy_en_mcwdtcascade_t Cy_MCWDT_GetCascade(MCWDT_STRUCT_Type const *base);
__STATIC_INLINE void Cy_MCWDT_SetMatch(MCWDT_STRUCT_Type *base, cy_en_mcwdtctr_t counter, uint32_t match, uint16_t waitUs);
__STATIC_INLINE uint32_t Cy_MCWDT_GetMatch(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter);
__STATIC_INLINE void Cy_MCWDT_SetToggleBit(MCWDT_STRUCT_Type *base, uint32_t bit);
__STATIC_INLINE uint32_t Cy_MCWDT_GetToggleBit(MCWDT_STRUCT_Type const *base);
__STATIC_INLINE uint32_t Cy_MCWDT_GetCount(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter);
__STATIC_INLINE void Cy_MCWDT_ResetCounters(MCWDT_STRUCT_Type *base, uint32_t counters, uint16_t waitUs);
__STATIC_INLINE uint32_t Cy_MCWDT_GetInterruptStatus(MCWDT_STRUCT_Type const *base);
__STATIC_INLINE void Cy_MCWDT_ClearInterrupt(MCWDT_STRUCT_Type *base, uint32_t counters);
__STATIC_INLINE void Cy_MCWDT_SetInterrupt(MCWDT_STRUCT_Type *base, uint32_t counters);
__STATIC_INLINE uint32_t Cy_MCWDT_GetInterruptMask(MCWDT_STRUCT_Type const *base);
__STATIC_INLINE void Cy_MCWDT_SetInterruptMask(MCWDT_STRUCT_Type *base, uint32_t counters);
__STATIC_INLINE uint32_t Cy_MCWDT_GetInterruptStatusMasked(MCWDT_STRUCT_Type const *base);
/*******************************************************************************
* Function Name: Cy_MCWDT_Enable
****************************************************************************//**
*
* Enables all specified counters.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counters
* OR of all counters to enable. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
* \param waitUs
* The function waits for some delay in microseconds before returning,
* because the counter begins counting after two lf_clk cycles pass.
* The recommended value is 93 us.
* \note
* Setting this parameter to a zero means No wait. In this case, it is
* the user's responsibility to check whether the selected counters were enabled
* immediately after the function call. This can be done by the
* Cy_MCWDT_GetEnabledStatus() API.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_Enable(MCWDT_STRUCT_Type *base, uint32_t counters, uint16_t waitUs)
{
uint32_t enableCounters;
/* Extract particular counters for enable */
enableCounters = ((0UL != (counters & CY_MCWDT_CTR0)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE0_Msk : 0UL) |
((0UL != (counters & CY_MCWDT_CTR1)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE1_Msk : 0UL) |
((0UL != (counters & CY_MCWDT_CTR2)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE2_Msk : 0UL);
base->MCWDT_CTL |= enableCounters;
Cy_SysLib_DelayUs(waitUs);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_Disable
****************************************************************************//**
*
* Disables all specified counters.
*
* \param base
* The base pointer to a structure describing registers.
*
* \param counters
* OR of all counters to disable. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
* \param waitUs
* The function waits for some delay in microseconds before returning,
* because the counter stops counting after two lf_clk cycles pass.
* The recommended value is 93 us.
* \note
* Setting this parameter to a zero means No wait. In this case, it is
* the user's responsibility to check whether the selected counters were disabled
* immediately after the function call. This can be done by the
* Cy_MCWDT_GetEnabledStatus() API.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_Disable(MCWDT_STRUCT_Type *base, uint32_t counters, uint16_t waitUs)
{
uint32_t disableCounters;
/* Extract particular counters for disable */
disableCounters = ((0UL != (counters & CY_MCWDT_CTR0)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE0_Msk : 0UL) |
((0UL != (counters & CY_MCWDT_CTR1)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE1_Msk : 0UL) |
((0UL != (counters & CY_MCWDT_CTR2)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLE2_Msk : 0UL);
base->MCWDT_CTL &= ~disableCounters;
Cy_SysLib_DelayUs(waitUs);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetEnabledStatus
****************************************************************************//**
*
* Reports the enabled status of the specified counter.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the MCWDT counter. The valid range is [0-2].
*
* \return
* The status of the MCWDT counter: 0 = disabled, 1 = enabled.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetEnabledStatus(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter)
{
uint32_t status = 0u;
switch (counter)
{
case CY_MCWDT_COUNTER0:
status = _FLD2VAL(MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLED0, base->MCWDT_CTL);
break;
case CY_MCWDT_COUNTER1:
status = _FLD2VAL(MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLED1, base->MCWDT_CTL);
break;
case CY_MCWDT_COUNTER2:
status = _FLD2VAL(MCWDT_STRUCT_MCWDT_CTL_WDT_ENABLED2, base->MCWDT_CTL);
break;
default:
CY_ASSERT(0u != 0u);
break;
}
return (status);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_Lock
****************************************************************************//**
*
* Locks out configuration changes to all MCWDT registers.
*
* \param base
* The base pointer to a structure that describes registers.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_Lock(MCWDT_STRUCT_Type *base)
{
uint32_t interruptState;
interruptState = Cy_SysLib_EnterCriticalSection();
base->MCWDT_LOCK = _CLR_SET_FLD32U(base->MCWDT_LOCK, MCWDT_STRUCT_MCWDT_LOCK_MCWDT_LOCK, (uint32_t)CY_MCWDT_LOCK_SET01);
Cy_SysLib_ExitCriticalSection(interruptState);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_Unlock
****************************************************************************//**
*
* Unlocks the MCWDT configuration registers.
*
* \param base
* The base pointer to a structure that describes registers.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_Unlock(MCWDT_STRUCT_Type *base)
{
uint32_t interruptState;
interruptState = Cy_SysLib_EnterCriticalSection();
base->MCWDT_LOCK = _CLR_SET_FLD32U(base->MCWDT_LOCK, MCWDT_STRUCT_MCWDT_LOCK_MCWDT_LOCK, (uint32_t)CY_MCWDT_LOCK_CLR0);
base->MCWDT_LOCK = _CLR_SET_FLD32U(base->MCWDT_LOCK, MCWDT_STRUCT_MCWDT_LOCK_MCWDT_LOCK, (uint32_t)CY_MCWDT_LOCK_CLR1);
Cy_SysLib_ExitCriticalSection(interruptState);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetLockStatus
****************************************************************************//**
*
* Reports the locked/unlocked state of the MCWDT.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \return
* The state of the MCWDT counter: 0 = unlocked, 1 = locked.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetLockedStatus(MCWDT_STRUCT_Type const *base)
{
return ((0UL != (base->MCWDT_LOCK & MCWDT_STRUCT_MCWDT_LOCK_MCWDT_LOCK_Msk)) ? 1UL : 0UL);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetMode
****************************************************************************//**
*
* Sets the mode of the specified counter.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-2].
*
* \param mode
* The mode of operation for the counter. See enum typedef cy_en_mcwdtmode_t.
*
* \note
* The mode for Counter 2 can be set only to CY_MCWDT_MODE_NONE or CY_MCWDT_MODE_INT.
*
* \note
* This API must not be called while the counters are running.
* Prior to calling this API, the counter must be disabled.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetMode(MCWDT_STRUCT_Type *base, cy_en_mcwdtctr_t counter, cy_en_mcwdtmode_t mode)
{
uint32_t mask, shift;
shift = CY_MCWDT_BYTE_SHIFT * counter;
mask = (counter == CY_MCWDT_COUNTER2) ? CY_MCWDT_C2_MODE_MASK : CY_MCWDT_C0C1_MODE_MASK;
mask = mask << shift;
base->MCWDT_CONFIG = (base->MCWDT_CONFIG & ~mask) | ((uint32_t) mode << shift);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetMode
****************************************************************************//**
*
* Reports the mode of the specified counter.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-2].
*
* \return
* The current mode of the counter. See enum typedef cy_en_mcwdtmode_t.
*
*******************************************************************************/
__STATIC_INLINE cy_en_mcwdtmode_t Cy_MCWDT_GetMode(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter)
{
uint32_t mode, mask;
mask = (counter == CY_MCWDT_COUNTER2) ? CY_MCWDT_C2_MODE_MASK : CY_MCWDT_C0C1_MODE_MASK;
mode = (base->MCWDT_CONFIG >> (CY_MCWDT_BYTE_SHIFT * counter)) & mask;
return ((cy_en_mcwdtmode_t) mode);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetClearOnMatch
****************************************************************************//**
*
* Sets the Clear on match option for the specified counter.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-1].
*
* \note
* The match values are not supported by Counter 2.
*
* \param enable
* Set 0 to disable; 1 to enable.
*
* \note
* This API must not be called while the counters are running.
* Prior to calling this API, the counter must be disabled.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetClearOnMatch(MCWDT_STRUCT_Type *base, cy_en_mcwdtctr_t counter, uint32_t enable)
{
if (CY_MCWDT_COUNTER0 == counter)
{
base->MCWDT_CONFIG = _CLR_SET_FLD32U(base->MCWDT_CONFIG, MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR0, enable);
}
else
{
base->MCWDT_CONFIG = _CLR_SET_FLD32U(base->MCWDT_CONFIG, MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR1, enable);
}
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetClearOnMatch
****************************************************************************//**
*
* Reports the Clear on match setting for the specified counter.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-1].
*
* \return
* The Clear on match status: 1 = enabled, 0 = disabled.
*
* \note
* The match value is not supported by Counter 2.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetClearOnMatch(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter)
{
uint32_t getClear;
if (CY_MCWDT_COUNTER0 == counter)
{
getClear = _FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR0, base->MCWDT_CONFIG);
}
else
{
getClear = _FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR1, base->MCWDT_CONFIG);
}
return (getClear);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetCascade
****************************************************************************//**
*
* Sets all the counter cascade options.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param cascade
* Sets or clears each of the cascade options.
*
* \note
* This API must not be called when the counters are running.
* Prior to calling this API, the counter must be disabled.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetCascade(MCWDT_STRUCT_Type *base, cy_en_mcwdtcascade_t cascade)
{
base->MCWDT_CONFIG = _CLR_SET_FLD32U(base->MCWDT_CONFIG, MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE0_1,
(uint32_t) cascade);
base->MCWDT_CONFIG = _CLR_SET_FLD32U(base->MCWDT_CONFIG, MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE1_2,
((uint32_t) cascade >> 1u));
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetCascade
****************************************************************************//**
*
* Reports all the counter cascade option settings.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \return
* The current cascade option values.
*
*******************************************************************************/
__STATIC_INLINE cy_en_mcwdtcascade_t Cy_MCWDT_GetCascade(MCWDT_STRUCT_Type const *base)
{
uint32_t cascade;
cascade = (_FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE1_2, base->MCWDT_CONFIG) << 1u) |
_FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE0_1, base->MCWDT_CONFIG);
return ((cy_en_mcwdtcascade_t) cascade);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetMatch
****************************************************************************//**
*
* Sets the match comparison value for the specified counter (0 or 1).
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-1].
*
* \param match
* The value to match against the counter.
* The valid range is [0-65535] for c0ClearOnMatch = 0 and [1-65535] for
* c0ClearOnMatch = 1.
*
* \note
* The match value is not supported by Counter 2.
*
* \note
* Action on match is taken on the next increment after the counter value
* equal to match value.
*
* \param waitUs
* The function waits for some delay in microseconds before returning,
* because the match affects after two lf_clk cycles pass. The recommended
* value is 93 us.
* \note
* Setting this parameter to a zero means No wait. This must be taken
* into account when changing the match values on the running counters.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetMatch(MCWDT_STRUCT_Type *base, cy_en_mcwdtctr_t counter, uint32_t match, uint16_t waitUs)
{
base->MCWDT_MATCH = (counter == CY_MCWDT_COUNTER0) ?
_CLR_SET_FLD32U(base->MCWDT_MATCH, MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0,
(match & MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0_Msk)) :
_CLR_SET_FLD32U(base->MCWDT_MATCH, MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH1,
(match & MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0_Msk));
Cy_SysLib_DelayUs(waitUs);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetMatch
****************************************************************************//**
*
* Reports the match comparison value for the specified counter (0 or 1).
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-1].
*
* \note
* The match values are not supported by Counter 2.
*
* \return
* A 16-bit match value.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetMatch(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter)
{
uint32_t match;
match = (counter == CY_MCWDT_COUNTER0) ? _FLD2VAL(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0, base->MCWDT_MATCH) :
_FLD2VAL(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH1, base->MCWDT_MATCH);
return (match);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetToggleBit
****************************************************************************//**
*
* Sets a bit in Counter 2 to monitor for a toggle.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param bit
* The Counter 2 bit is set to monitor for a toggle. The valid range [0-31].
*
* \note
* This API must not be called when counters are running.
* Prior to calling this API, the counter must be disabled.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetToggleBit(MCWDT_STRUCT_Type *base, uint32_t bit)
{
base->MCWDT_CONFIG = _CLR_SET_FLD32U(base->MCWDT_CONFIG, MCWDT_STRUCT_MCWDT_CONFIG_WDT_BITS2, bit);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetToggleBit
****************************************************************************//**
*
* Reports which bit in Counter 2 is monitored for a toggle.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \return
* The bit that is monitored (range 0 to 31).
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetToggleBit(MCWDT_STRUCT_Type const *base)
{
return (_FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_BITS2, base->MCWDT_CONFIG));
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetCount
****************************************************************************//**
*
* Reports the current counter value of the specified counter.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counter
* The number of the WDT counter. The valid range is [0-2].
*
* \return
* A live counter value. Counters 0 and 1 are 16-bit counters and Counter 2 is
* a 32-bit counter.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetCount(MCWDT_STRUCT_Type const *base, cy_en_mcwdtctr_t counter)
{
uint32_t countVal = 0u;
switch (counter)
{
case CY_MCWDT_COUNTER0:
countVal = _FLD2VAL(MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR0, base->MCWDT_CNTLOW);
break;
case CY_MCWDT_COUNTER1:
countVal = _FLD2VAL(MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR1, base->MCWDT_CNTLOW);
break;
case CY_MCWDT_COUNTER2:
countVal = _FLD2VAL(MCWDT_STRUCT_MCWDT_CNTHIGH_WDT_CTR2, base->MCWDT_CNTHIGH);
break;
default:
CY_ASSERT(0u != 0u);
break;
}
return (countVal);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_ResetCounters
****************************************************************************//**
*
* Resets all specified counters.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counters
* OR of all counters to reset. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
* \param waitUs
* The function waits for some delay in microseconds before returning, because
* a reset occurs after one lf_clk cycle passes. The recommended value is 62 us.
* \note
* Setting this parameter to a zero means No wait. In this case, it is the
* user's responsibility to check whether the selected counters were reset
* immediately after the function call. This can be done by the
* Cy_MCWDT_GetCount() API.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_ResetCounters(MCWDT_STRUCT_Type *base, uint32_t counters, uint16_t waitUs)
{
uint32_t resetCounters;
/* Extract particular counters for reset */
resetCounters = ((0UL != (counters & CY_MCWDT_CTR0)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_RESET0_Msk : 0UL) |
((0UL != (counters & CY_MCWDT_CTR1)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_RESET1_Msk : 0UL) |
((0UL != (counters & CY_MCWDT_CTR2)) ? MCWDT_STRUCT_MCWDT_CTL_WDT_RESET2_Msk : 0UL);
base->MCWDT_CTL |= resetCounters;
Cy_SysLib_DelayUs(waitUs);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetInterruptStatus
****************************************************************************//**
*
* Reports the state of all MCWDT interrupts.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \return
* The OR'd state of the interrupts. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetInterruptStatus(MCWDT_STRUCT_Type const *base)
{
return (base->MCWDT_INTR);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_ClearInterrupt
****************************************************************************//**
*
* Clears all specified MCWDT interrupts.
*
* All the WDT interrupts must be cleared by the firmware; otherwise
* interrupts are generated continuously.
*
* \param base
* The base pointer to a structure describes registers.
*
* \param counters
* OR of all interrupt sources to clear. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_ClearInterrupt(MCWDT_STRUCT_Type *base, uint32_t counters)
{
base->MCWDT_INTR = counters;
(void) base->MCWDT_INTR;
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetInterrupt
****************************************************************************//**
*
* Sets MCWDT interrupt sources in the interrupt request register.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counters
* OR of all interrupt sources to set. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetInterrupt(MCWDT_STRUCT_Type *base, uint32_t counters)
{
base->MCWDT_INTR_SET = counters;
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetInterruptMask
****************************************************************************//**
*
* Returns the CWDT interrupt mask register. This register specifies which bits
* from the MCWDT interrupt request register will trigger an interrupt event.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \return
* The OR'd state of the interrupt masks. See the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetInterruptMask(MCWDT_STRUCT_Type const *base)
{
return (base->MCWDT_INTR_MASK);
}
/*******************************************************************************
* Function Name: Cy_MCWDT_SetInterruptMask
****************************************************************************//**
*
* Writes MCWDT interrupt mask register. This register configures which bits
* from MCWDT interrupt request register will trigger an interrupt event.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \param counters
* OR of all interrupt masks to set. See \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and
* CY_MCWDT_CTR2 macros.
*
*******************************************************************************/
__STATIC_INLINE void Cy_MCWDT_SetInterruptMask(MCWDT_STRUCT_Type *base, uint32_t counters)
{
base->MCWDT_INTR_MASK = counters;
}
/*******************************************************************************
* Function Name: Cy_MCWDT_GetInterruptStatusMasked
****************************************************************************//**
*
* Returns the MCWDT interrupt masked request register. This register contains
* the logical AND of corresponding bits from the MCWDT interrupt request and
* mask registers.
* In the interrupt service routine, this function identifies which of the
* enabled MCWDT interrupt sources caused an interrupt event.
*
* \param base
* The base pointer to a structure that describes registers.
*
* \return
* The current status of enabled MCWDT interrupt sources. See
* the \ref CY_MCWDT_CTR0, CY_MCWDT_CTR1, and CY_MCWDT_CTR2 macros.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_MCWDT_GetInterruptStatusMasked(MCWDT_STRUCT_Type const *base)
{
return (base->MCWDT_INTR_MASKED);
}
/** \} group_mcwdt_functions */
#if defined(__cplusplus)
}
#endif
#endif /* CY_MCWDT_H */
/** \} group_mcwdt */
/* [] END OF FILE */

View File

@ -0,0 +1,240 @@
/***************************************************************************//**
* \file cy_pdm_pcm.c
* \version 2.0
*
* The source code file for the PDM_PCM driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_pdm_pcm.h"
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/**
* \addtogroup group_pdm_pcm_functions
* \{
*/
/******************************************************************************
* Function Name: Cy_PDM_PCM_Init
***************************************************************************//**
*
* Initialize PDM-PCM module
*
* \pre If the PDM-PCM module is initialized previously, the
* \ref Cy_PDM_PCM_DeInit() must be called before calling this function.
*
* \param base Pointer to PDM-PCM instance address
* \param config Pointer to configuration structure
* \return error / status code. See \ref cy_en_pdm_pcm_status_t.
*
* Example of the configuration structure:
* \snippet PDM_PCM_PDL_sut_00.cydsn/main_cm4.c PDM_PCM Configuration
*
*******************************************************************************/
cy_en_pdm_pcm_status_t Cy_PDM_PCM_Init(PDM_Type * base, cy_stc_pdm_pcm_config_t const * config)
{
cy_en_pdm_pcm_status_t ret = CY_PDM_PCM_BAD_PARAM;
if((NULL != base) && (NULL != config))
{
CY_ASSERT_L3(CY_PDM_PCM_IS_CLK_DIV_VALID(config->clkDiv));
CY_ASSERT_L3(CY_PDM_PCM_IS_CLK_DIV_VALID(config->mclkDiv));
CY_ASSERT_L3(CY_PDM_PCM_IS_CKO_CLOCK_DIV_VALID(config->ckoDiv));
CY_ASSERT_L3(CY_PDM_PCM_IS_SINC_RATE_VALID(config->sincDecRate));
CY_ASSERT_L3(CY_PDM_PCM_IS_GAIN_VALID(config->gainRight));
CY_ASSERT_L3(CY_PDM_PCM_IS_GAIN_VALID(config->gainLeft));
CY_ASSERT_L3(CY_PDM_PCM_IS_STEP_SEL_VALID(config->softMuteFineGain));
CY_ASSERT_L3(CY_PDM_PCM_IS_CH_SET_VALID(config->chanSelect));
CY_ASSERT_L3(CY_PDM_PCM_IS_S_CYCLES_VALID(config->softMuteCycles));
CY_ASSERT_L3(CY_PDM_PCM_IS_CKO_DELAY_VALID(config->ckoDelay));
CY_ASSERT_L3(CY_PDM_PCM_IS_HPF_GAIN_VALID(config->highPassFilterGain));
CY_ASSERT_L3(CY_PDM_PCM_IS_WORD_LEN_VALID(config->wordLen));
CY_ASSERT_L3(CY_PDM_PCM_IS_TRIG_LEVEL(config->rxFifoTriggerLevel, config->chanSelect));
ret = CY_PDM_PCM_SUCCESS;
base->CTL &= (uint32_t) ~PDM_CTL_ENABLED_Msk; /* Disable PDM_PCM block */
/* Clock setting */
base->CLOCK_CTL = _VAL2FLD(PDM_CLOCK_CTL_CLK_CLOCK_DIV, config->clkDiv) |
_VAL2FLD(PDM_CLOCK_CTL_MCLKQ_CLOCK_DIV, config->mclkDiv) |
_VAL2FLD(PDM_CLOCK_CTL_CKO_CLOCK_DIV, config->ckoDiv) |
_VAL2FLD(PDM_CLOCK_CTL_SINC_RATE, config->sincDecRate);
/* Enable PDM-PCM block */
base->CTL = _VAL2FLD(PDM_CTL_PGA_R, config->gainRight) |
_VAL2FLD(PDM_CTL_PGA_L, config->gainLeft) |
_VAL2FLD(PDM_CTL_STEP_SEL, config->softMuteFineGain) |
_BOOL2FLD(PDM_CTL_SOFT_MUTE, config->softMuteEnable) |
_BOOL2FLD(PDM_CTL_ENABLED, true);
base->MODE_CTL = _VAL2FLD(PDM_MODE_CTL_PCM_CH_SET, config->chanSelect) |
_BOOL2FLD(PDM_MODE_CTL_SWAP_LR, config->chanSwapEnable) |
_VAL2FLD(PDM_MODE_CTL_S_CYCLES, config->softMuteCycles) |
_VAL2FLD(PDM_MODE_CTL_CKO_DELAY, config->ckoDelay) |
_VAL2FLD(PDM_MODE_CTL_HPF_GAIN, config->highPassFilterGain) |
_BOOL2FLD(PDM_MODE_CTL_HPF_EN_N, config->highPassDisable);
base->DATA_CTL = _VAL2FLD(PDM_DATA_CTL_WORD_LEN, config->wordLen) |
_BOOL2FLD(PDM_DATA_CTL_BIT_EXTENSION, config->signExtension);
base->RX_FIFO_CTL = _VAL2FLD(PDM_RX_FIFO_CTL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
base->TR_CTL = _BOOL2FLD(PDM_TR_CTL_RX_REQ_EN, config->dmaTriggerEnable);
Cy_PDM_PCM_SetInterruptMask(base, config->interruptMask);
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_PDM_PCM_DeInit
****************************************************************************//**
*
* Uninitializes the PDM-PCM module.
*
* \param base The pointer to the PDM-PCM instance address.
*
*******************************************************************************/
void Cy_PDM_PCM_DeInit(PDM_Type * base)
{
base->CMD = 0UL; /* Stop PDM-PCM operation */
base->INTR_MASK = 0UL; /* Disable interrupts */
base->RX_FIFO_CTL = 0UL;
base->TR_CTL = 0UL;
base->DATA_CTL = 0UL;
base->MODE_CTL = CY_PDM_PCM_MODE_CTL_DEFAULT;
base->CTL = CY_PDM_PCM_CTL_DEFAULT; /* Disable PDM_PCM IP block */
base->CLOCK_CTL = CY_PDM_PCM_CLOCK_CTL_DEFAULT; /* Default clock settings */
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_SetGain
***************************************************************************//**
*
* Sets the gain factor to left or right channel.
*
* \param base
* Pointer to PDM-PCM instance address
*
* \param chan
* Channel selector for gain setting \ref cy_en_pdm_pcm_chan_select_t.
*
* \param gain
* Gain for the selected channel \ref cy_en_pdm_pcm_gain_t.
*
******************************************************************************/
void Cy_PDM_PCM_SetGain(PDM_Type * base, cy_en_pdm_pcm_chan_select_t chan, cy_en_pdm_pcm_gain_t gain)
{
CY_ASSERT_L3(CY_PDM_PCM_IS_CHAN_VALID(chan));
CY_ASSERT_L3(CY_PDM_PCM_IS_GAIN_VALID(gain));
if (chan == CY_PDM_PCM_CHAN_LEFT)
{
base->CTL = _CLR_SET_FLD32U(base->CTL, PDM_CTL_PGA_L, ((uint32_t) gain));
}
else
{
base->CTL = _CLR_SET_FLD32U(base->CTL, PDM_CTL_PGA_R, ((uint32_t) gain));
}
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_GetGain
***************************************************************************//**
*
* Retrieve the current gain factor of left or right channel.
*
* \param base
* Pointer to PDM-PCM instance address
*
* \param chan
* Channel selector for gain setting \ref cy_en_pdm_pcm_chan_select_t.
*
* \return
* Gain of the selected channel \ref cy_en_pdm_pcm_gain_t.
*
******************************************************************************/
cy_en_pdm_pcm_gain_t Cy_PDM_PCM_GetGain(PDM_Type const * base, cy_en_pdm_pcm_chan_select_t chan)
{
cy_en_pdm_pcm_gain_t ret;
CY_ASSERT_L3(CY_PDM_PCM_IS_CHAN_VALID(chan));
if (chan == CY_PDM_PCM_CHAN_LEFT)
{
ret = (cy_en_pdm_pcm_gain_t) (_FLD2VAL(PDM_CTL_PGA_L, base->CTL));
}
else
{
ret = (cy_en_pdm_pcm_gain_t) (_FLD2VAL(PDM_CTL_PGA_R, base->CTL));
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_PDM_PCM_DeepSleepCallback
****************************************************************************//**
*
* This is an example callback function that can be used the application layer to
* manage PDM-PCM operation before entering and after exiting Deep-Sleep mode.
*
* \param callbackParams
* structure with the syspm callback parameters,
* see \ref cy_stc_syspm_callback_params_t.
*
* \return
* syspm return status, see \ref cy_en_syspm_status_t
*
*******************************************************************************/
cy_en_syspm_status_t Cy_PDM_PCM_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams)
{
cy_en_syspm_status_t ret = CY_SYSPM_SUCCESS;
switch(callbackParams->mode)
{
case CY_SYSPM_CHECK_READY:
case CY_SYSPM_CHECK_FAIL:
break;
case CY_SYSPM_BEFORE_TRANSITION:
Cy_PDM_PCM_Disable((PDM_Type*) callbackParams->base); /* Stop PDM-PCM operation */
/* Unload FIFO to do not lost any data (if needed) */
break;
case CY_SYSPM_AFTER_TRANSITION:
Cy_PDM_PCM_ClearFifo((PDM_Type*) callbackParams->base); /* Clear FIFO */
Cy_PDM_PCM_Enable((PDM_Type*) callbackParams->base); /* Start PDM-PCM operation */
break;
default:
ret = CY_SYSPM_FAIL;
break;
}
return(ret);
}
/** \} group_pdm_pcm_functions */
#ifdef __cplusplus
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,729 @@
/***************************************************************************//**
* \file cy_pdm_pcm.h
* \version 2.0
*
* The header file of the PDM_PCM driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_pdm_pcm PDM-PCM Converter (PDM_PCM)
* \{
*
* The pulse-density modulation to pulse-code modulation (PDM-PCM) driver provides an
* API to manage PDM-PCM conversion. A PDM-PCM converter is used
* to convert 1-bit digital audio streaming data to PCM data.
*
* Features:
* * Supports FIFO buffer for Incoming Data
* * Supports Software Mute Mode
* * Programmable Gain Settings
* * Programmable Word Length
*
* Pulse-density modulation, or PDM, represents
* an analog signal with a binary signal. In a PDM signal, specific amplitude values
* are not encoded into codewords of pulses of different weight as they would be
* in pulse-code modulation (PCM); rather, the relative density of the pulses corresponds
* to the analog signal's amplitude. The output of a 1-bit DAC is the same
* as the PDM encoding of the signal.
*
* Pulse-code modulation (PCM) is a method used to digitally represent sampled analog signals.
* It is the standard form of digital audio in computers, compact discs, digital telephony,
* and other digital audio applications. In a PCM stream, the amplitude of the analog signal
* is sampled regularly at uniform intervals, and each sample is quantized
* to the nearest value within a range of digital steps.
*
* \section group_pdm_pcm_configuration_considerations Configuration Considerations
*
* To set up a PDM-PCM, provide the configuration parameters in the
* \ref cy_stc_pdm_pcm_config_t structure.
*
* For example, set dataStreamingEnable to true, configure rxFifoTriggerLevel,
* dmaTriggerEnable (depending on whether DMA is going to be used),
* provide clock settings (clkDiv, mclkDiv and ckoDiv), set sincDecRate
* to the appropriate decimation rate, wordLen, and wordBitExtension.
* No other parameters are necessary for this example.
*
* To initialize the PDM-PCM block, call the \ref Cy_PDM_PCM_Init function, providing the
* filled \ref cy_stc_pdm_pcm_config_t structure.
*
* If you use DMA, the DMA channel should be previously configured. PDM-PCM interrupts
* (if applicable) can be enabled by calling \ref Cy_PDM_PCM_SetInterruptMask.
*
* For example, if the trigger interrupt is used during operation, the ISR
* should call the \ref Cy_PDM_PCM_ReadFifo as many times as required for your
* FIFO payload. Then call \ref Cy_PDM_PCM_ClearInterrupt with appropriate parameters.
*
* If DMA is used and a DMA channel is properly configured, no CPU activity
* (or application code) is needed for PDM-PCM operation.
*
* \section group_pdm_pcm_more_information More Information
* See the PDM_PCM_PDL Component datasheet.
* Also, see the PDM-PCM chapter of the device technical reference manual (TRM).
*
* \section group_pdm_pcm_MISRA MISRA-C Compliance
* The PDM-PCM driver has the following specific deviations:
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>10.3</td>
* <td>R</td>
* <td>A composite expression of 'essentially unsigned' type is being
* cast to a different type category.</td>
* <td>The value got from the bitfield physically can't exceed the enumeration
* that describes this bitfield. So the code is safety by design.</td>
* </tr>
* <tr>
* <td>11.4</td>
* <td>A</td>
* <td>A cast should not be performed between a pointer to object type and
* a different pointer to object type.</td>
* <td>The function \ref Cy_I2S_DeepSleepCallback is a callback of
* \ref cy_en_syspm_status_t type. The cast operation safety in this
* function becomes the user responsibility because pointer are
* initialized when callback is registered in SysPm driver.</td>
* </tr>
* </table>
*
* \section group_pdm_pcm_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* <tr>
* <td>2.0</td>
* <td>User-friendliness enhancement</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_pdm_pcm_macros Macros
* \defgroup group_pdm_pcm_functions Functions
* \defgroup group_pdm_pcm_data_structures Data structures
* \defgroup group_pdm_pcm_enums Enumerated Types
*
*/
#if !defined(CY_PDM_PCM_H__)
#define CY_PDM_PCM_H__
/******************************************************************************/
/* Include files */
/******************************************************************************/
#include "cy_device_headers.h"
#include "syslib/cy_syslib.h"
#include "syspm/cy_syspm.h"
#include <stddef.h>
#include <stdbool.h>
#ifndef CY_IP_MXAUDIOSS
#error "The PDM-PCM driver is not supported on this device"
#endif
/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif
/******************************************************************************
* Global definitions
******************************************************************************/
/* Macros */
/**
* \addtogroup group_pdm_pcm_macros
* \{
*/
/** Driver major version */
#define CY_PDM_PCM_DRV_VERSION_MAJOR 2
/** Driver minor version */
#define CY_PDM_PCM_DRV_VERSION_MINOR 0
/** PDM-PCM driver identifier */
#define CY_PDM_PCM_ID CY_PDL_DRV_ID(0x26u)
/**
* \defgroup group_pdm_pcm_macros_intrerrupt_masks Interrupt Masks
* \{
*/
/** Bit 16: More entries in the RX FIFO than specified by Trigger Level. */
#define CY_PDM_PCM_INTR_RX_TRIGGER (PDM_INTR_RX_TRIGGER_Msk)
/** Bit 18: RX FIFO is not empty. */
#define CY_PDM_PCM_INTR_RX_NOT_EMPTY (PDM_INTR_RX_NOT_EMPTY_Msk)
/** Bit 21: Attempt to write to a full RX FIFO. */
#define CY_PDM_PCM_INTR_RX_OVERFLOW (PDM_INTR_RX_OVERFLOW_Msk)
/** Bit 22: Attempt to read from an empty RX FIFO. */
#define CY_PDM_PCM_INTR_RX_UNDERFLOW (PDM_INTR_RX_UNDERFLOW_Msk)
/** \} group_pdm_pcm_macros_intrerrupt_masks */
/** \} group_pdm_pcm_macros */
/**
* \addtogroup group_pdm_pcm_enums
* \{
*/
/** PDM Word Length. */
typedef enum
{
CY_PDM_PCM_WLEN_16_BIT = 0U, /**< Word length: 16 bit. */
CY_PDM_PCM_WLEN_18_BIT = 1U, /**< Word length: 18 bit. */
CY_PDM_PCM_WLEN_20_BIT = 2U, /**< Word length: 20 bit. */
CY_PDM_PCM_WLEN_24_BIT = 3U /**< Word length: 24 bit. */
} cy_en_pdm_pcm_word_len_t;
/** PDM Clock Divider. */
typedef enum
{
CY_PDM_PCM_CLK_DIV_BYPASS = 0U, /**< Clock 1/1. */
CY_PDM_PCM_CLK_DIV_1_2 = 1U, /**< Clock 1/2 (no 50% duty cycle). */
CY_PDM_PCM_CLK_DIV_1_3 = 2U, /**< Clock 1/3 (no 50% duty cycle). */
CY_PDM_PCM_CLK_DIV_1_4 = 3U /**< Clock 1/4 (no 50% duty cycle). */
} cy_en_pdm_pcm_clk_div_t;
/** PDM Output Mode. */
typedef enum
{
CY_PDM_PCM_OUT_CHAN_LEFT = 1U, /**< Channel mono left. */
CY_PDM_PCM_OUT_CHAN_RIGHT = 2U, /**< Channel mono right. */
CY_PDM_PCM_OUT_STEREO = 3U /**< Channel stereo. */
} cy_en_pdm_pcm_out_t;
/** PDM Channel selector. */
typedef enum
{
CY_PDM_PCM_CHAN_LEFT = 0U, /**< Channel left. */
CY_PDM_PCM_CHAN_RIGHT = 1U /**< Channel right. */
} cy_en_pdm_pcm_chan_select_t;
/** PDM Gain. */
typedef enum
{
CY_PDM_PCM_ATTN_12_DB = 0U, /**< -12 dB (attenuation). */
CY_PDM_PCM_ATTN_10_5_DB = 1U, /**< -10.5 dB (attenuation). */
CY_PDM_PCM_ATTN_9_DB = 2U, /**< -9 dB (attenuation). */
CY_PDM_PCM_ATTN_7_5_DB = 3U, /**< -7.5 dB (attenuation). */
CY_PDM_PCM_ATTN_6_DB = 4U, /**< -6 dB (attenuation). */
CY_PDM_PCM_ATTN_4_5_DB = 5U, /**< -4.5 dB (attenuation). */
CY_PDM_PCM_ATTN_3_DB = 6U, /**< -3 dB (attenuation). */
CY_PDM_PCM_ATTN_1_5_DB = 7U, /**< -1.5 dB (attenuation). */
CY_PDM_PCM_BYPASS = 8U, /**< 0 dB (bypass). */
CY_PDM_PCM_GAIN_1_5_DB = 9U, /**< +1.5 dB (amplification). */
CY_PDM_PCM_GAIN_3_DB = 10U, /**< +3 dB (amplification). */
CY_PDM_PCM_GAIN_4_5_DB = 12U, /**< +4.5 dB (amplification). */
CY_PDM_PCM_GAIN_6_DB = 13U, /**< +6 dB (amplification). */
CY_PDM_PCM_GAIN_7_5_DB = 14U, /**< +7.5 dB (amplification). */
CY_PDM_PCM_GAIN_9_DB = 15U, /**< +9 dB (amplification). */
CY_PDM_PCM_GAIN_10_5_DB = 16U /**< +10.5 dB (amplification). */
} cy_en_pdm_pcm_gain_t;
/** The time step for gain change during PGA or soft mute operation in
* number of 1/a sampling rate. */
typedef enum
{
CY_PDM_PCM_SOFT_MUTE_CYCLES_64 = 0U, /**< 64 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_96 = 1U, /**< 96 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_128 = 2U, /**< 128 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_160 = 3U, /**< 160 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_192 = 4U, /**< 192 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_256 = 5U, /**< 256 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_384 = 6U, /**< 384 steps. */
CY_PDM_PCM_SOFT_MUTE_CYCLES_512 = 7U /**< 512 steps. */
} cy_en_pdm_pcm_s_cycles_t;
/** The PDM-PCM status codes. */
typedef enum
{
CY_PDM_PCM_SUCCESS = 0x00UL, /**< Success status code */
CY_PDM_PCM_BAD_PARAM = CY_PDM_PCM_ID | CY_PDL_STATUS_ERROR | 0x01UL /**< Bad parameter status code */
} cy_en_pdm_pcm_status_t;
/** \} group_pdm_pcm_enums */
/**
* \addtogroup group_pdm_pcm_data_structures
* \{
*/
/******************************************************************************
* Global type definitions
******************************************************************************/
/** PDM-PCM initialization configuration */
typedef struct
{
cy_en_pdm_pcm_clk_div_t clkDiv; /**< PDM Clock Divider (1st divider), see #cy_en_pdm_pcm_clk_div_t
This configures a frequency of PDM CLK. The configured frequency
is used to operate PDM core. I.e. the frequency is input to
MCLKQ_CLOCK_DIV register. */
cy_en_pdm_pcm_clk_div_t mclkDiv; /**< MCLKQ divider (2nd divider), see #cy_en_pdm_pcm_clk_div_t */
uint8_t ckoDiv; /**< PDM CKO (FPDM_CKO) clock divider (3rd divider):
- if CKO_CLOCK_DIV >= 1 - *F(PDM_CKO) = F(PDM_CLK / (mclkDiv + 1))
- if CKO_CLOCK_DIV = 0 - *F(PDM_CKO) = MCLKQ / 2 */
uint8_t ckoDelay; /**< Extra PDM_CKO delay to internal sampler:
- 0: Three extra PDM_CLK period advance
- 1: Two extra PDM_CLK period advance
- 2: One extra PDM_CLK period advance
- 3: No delay
- 4: One extra PDM_CLK period delay
- 5: Two extra PDM_CLK period delay
- 6: Three extra PDM_CLK period delay
- 7: Four extra PDM_CLK clock delay */
uint8_t sincDecRate; /**< F(MCLK_L_R) = Fs * 2 * sincDecRate * mclkDiv,
Fs is a sampling frequency, 8kHz - 48kHz */
cy_en_pdm_pcm_out_t chanSelect; /**< see #cy_en_pdm_pcm_out_t */
bool chanSwapEnable; /**< Audio channels swapping */
uint8_t highPassFilterGain; /**< High pass filter gain:
H(Z) = (1 - Z^-1) / (1 - (1 - 2^highPassFilterGain) * Z^-1) */
bool highPassDisable; /**< High pass filter disable */
cy_en_pdm_pcm_s_cycles_t softMuteCycles; /**< The time step for gain change during PGA or soft mute operation in
number of 1/a sampling rate, see #cy_en_pdm_pcm_s_cycles_t. */
uint32_t softMuteFineGain; /**< Soft mute fine gain: 0 = 0.13dB, 1 = 0.26dB */
bool softMuteEnable; /**< Soft mute enable */
cy_en_pdm_pcm_word_len_t wordLen; /**< see #cy_en_pdm_pcm_word_len_t */
bool signExtension; /**< Word extension type:
- 0: extension by zero
- 1: extension by sign bits */
cy_en_pdm_pcm_gain_t gainLeft; /**< Gain for left channel, see #cy_en_pdm_pcm_gain_t */
cy_en_pdm_pcm_gain_t gainRight; /**< Gain for right channel, see #cy_en_pdm_pcm_gain_t */
uint8_t rxFifoTriggerLevel; /**< Fifo interrupt trigger level (in words),
range: 0 - 253 for stereo and 0 - 254 for mono mode */
bool dmaTriggerEnable; /**< DMA trigger enable */
uint32_t interruptMask; /**< Interrupts enable mask */
} cy_stc_pdm_pcm_config_t;
/** \} group_pdm_pcm_data_structures */
/** \cond INTERNAL */
/******************************************************************************
* Local definitions
*******************************************************************************/
/** Define bit mask for all available interrupt sources */
#define CY_PDM_PCM_INTR_MASK (CY_PDM_PCM_INTR_RX_TRIGGER | \
CY_PDM_PCM_INTR_RX_NOT_EMPTY | \
CY_PDM_PCM_INTR_RX_OVERFLOW | \
CY_PDM_PCM_INTR_RX_UNDERFLOW)
/* Non-zero default values */
#define CY_PDM_PCM_CTL_PGA_R_DEFAULT (0x8U)
#define CY_PDM_PCM_CTL_PGA_L_DEFAULT (0x8U)
#define CY_PDM_PCM_CTL_STEP_SEL_DEFAULT (0x1U)
#define CY_PDM_PCM_CTL_DEFAULT (_VAL2FLD(PDM_CTL_PGA_R, CY_PDM_PCM_CTL_PGA_R_DEFAULT) | \
_VAL2FLD(PDM_CTL_PGA_L, CY_PDM_PCM_CTL_PGA_L_DEFAULT) | \
_VAL2FLD(PDM_CTL_STEP_SEL, CY_PDM_PCM_CTL_STEP_SEL_DEFAULT))
#define CY_PDM_PCM_CLOCK_CTL_MCLKQ_CLOCK_DIV_DEFAULT (0x1U)
#define CY_PDM_PCM_CLOCK_CTL_CKO_CLOCK_DIV_DEFAULT (0x3U)
#define CY_PDM_PCM_CLOCK_CTL_SINC_RATE_DEFAULT (0x20U)
#define CY_PDM_PCM_CLOCK_CTL_DEFAULT (_VAL2FLD(PDM_CLOCK_CTL_MCLKQ_CLOCK_DIV, CY_PDM_PCM_CLOCK_CTL_MCLKQ_CLOCK_DIV_DEFAULT) | \
_VAL2FLD(PDM_CLOCK_CTL_CKO_CLOCK_DIV, CY_PDM_PCM_CLOCK_CTL_CKO_CLOCK_DIV_DEFAULT) | \
_VAL2FLD(PDM_CLOCK_CTL_SINC_RATE, CY_PDM_PCM_CLOCK_CTL_SINC_RATE_DEFAULT))
#define CY_PDM_PCM_MODE_CTL_PCM_CH_SET_DEFAULT (0x3U)
#define CY_PDM_PCM_MODE_CTL_S_CYCLES_DEFAULT (0x1U)
#define CY_PDM_PCM_MODE_CTL_HPF_GAIN_DEFAULT (0xBU)
#define CY_PDM_PCM_MODE_CTL_HPF_EN_N_DEFAULT (0x1U)
#define CY_PDM_PCM_MODE_CTL_DEFAULT (_VAL2FLD(PDM_MODE_CTL_PCM_CH_SET, CY_PDM_PCM_MODE_CTL_PCM_CH_SET_DEFAULT) | \
_VAL2FLD(PDM_MODE_CTL_S_CYCLES, CY_PDM_PCM_MODE_CTL_S_CYCLES_DEFAULT) | \
_VAL2FLD(PDM_MODE_CTL_HPF_GAIN, CY_PDM_PCM_MODE_CTL_HPF_GAIN_DEFAULT) | \
_VAL2FLD(PDM_MODE_CTL_HPF_EN_N, CY_PDM_PCM_MODE_CTL_HPF_EN_N_DEFAULT))
/* Macros for conditions used by CY_ASSERT calls */
#define CY_PDM_PCM_IS_CLK_DIV_VALID(clkDiv) (((clkDiv) == CY_PDM_PCM_CLK_DIV_BYPASS) || \
((clkDiv) == CY_PDM_PCM_CLK_DIV_1_2) || \
((clkDiv) == CY_PDM_PCM_CLK_DIV_1_3) || \
((clkDiv) == CY_PDM_PCM_CLK_DIV_1_4))
#define CY_PDM_PCM_IS_CH_SET_VALID(chanSelect) (((chanSelect) == CY_PDM_PCM_OUT_CHAN_LEFT) || \
((chanSelect) == CY_PDM_PCM_OUT_CHAN_RIGHT) || \
((chanSelect) == CY_PDM_PCM_OUT_STEREO))
#define CY_PDM_PCM_IS_GAIN_VALID(gain) (((gain) == CY_PDM_PCM_ATTN_12_DB) || \
((gain) == CY_PDM_PCM_ATTN_10_5_DB) || \
((gain) == CY_PDM_PCM_ATTN_9_DB) || \
((gain) == CY_PDM_PCM_ATTN_7_5_DB) || \
((gain) == CY_PDM_PCM_ATTN_6_DB) || \
((gain) == CY_PDM_PCM_ATTN_4_5_DB) || \
((gain) == CY_PDM_PCM_ATTN_3_DB) || \
((gain) == CY_PDM_PCM_ATTN_1_5_DB) || \
((gain) == CY_PDM_PCM_BYPASS) || \
((gain) == CY_PDM_PCM_GAIN_1_5_DB) || \
((gain) == CY_PDM_PCM_GAIN_3_DB) || \
((gain) == CY_PDM_PCM_GAIN_4_5_DB) || \
((gain) == CY_PDM_PCM_GAIN_6_DB) || \
((gain) == CY_PDM_PCM_GAIN_7_5_DB) || \
((gain) == CY_PDM_PCM_GAIN_9_DB) || \
((gain) == CY_PDM_PCM_GAIN_10_5_DB))
#define CY_PDM_PCM_IS_WORD_LEN_VALID(wordLen) (((wordLen) == CY_PDM_PCM_WLEN_16_BIT) || \
((wordLen) == CY_PDM_PCM_WLEN_18_BIT) || \
((wordLen) == CY_PDM_PCM_WLEN_20_BIT) || \
((wordLen) == CY_PDM_PCM_WLEN_24_BIT))
#define CY_PDM_PCM_IS_CHAN_VALID(chan) (((chan) == CY_PDM_PCM_CHAN_LEFT) || \
((chan) == CY_PDM_PCM_CHAN_RIGHT))
#define CY_PDM_PCM_IS_S_CYCLES_VALID(sCycles) (((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_64) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_96) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_128) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_160) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_192) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_256) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_384) || \
((sCycles) == CY_PDM_PCM_SOFT_MUTE_CYCLES_512))
#define CY_PDM_PCM_IS_INTR_MASK_VALID(interrupt) (0UL == ((interrupt) & ((uint32_t) ~CY_PDM_PCM_INTR_MASK)))
#define CY_PDM_PCM_IS_SINC_RATE_VALID(sincRate) ((sincRate) <= 127U)
#define CY_PDM_PCM_IS_STEP_SEL_VALID(stepSel) ((stepSel) <= 1UL)
#define CY_PDM_PCM_IS_CKO_DELAY_VALID(ckoDelay) ((ckoDelay) <= 7U)
#define CY_PDM_PCM_IS_HPF_GAIN_VALID(hpfGain) ((hpfGain) <= 15U)
#define CY_PDM_PCM_IS_CKO_CLOCK_DIV_VALID(ckoDiv) (((ckoDiv) >= 1U) && ((ckoDiv) <= 15U))
#define CY_PDM_PCM_IS_TRIG_LEVEL(trigLevel, chanSelect) ((trigLevel) <= (((chanSelect) == CY_PDM_PCM_OUT_STEREO)? 253U : 254U))
/** \endcond */
/**
* \addtogroup group_pdm_pcm_functions
* \{
*/
cy_en_pdm_pcm_status_t Cy_PDM_PCM_Init(PDM_Type * base, cy_stc_pdm_pcm_config_t const * config);
void Cy_PDM_PCM_DeInit(PDM_Type * base);
void Cy_PDM_PCM_SetGain(PDM_Type * base, cy_en_pdm_pcm_chan_select_t chan, cy_en_pdm_pcm_gain_t gain);
cy_en_pdm_pcm_gain_t Cy_PDM_PCM_GetGain(PDM_Type const * base, cy_en_pdm_pcm_chan_select_t chan);
cy_en_syspm_status_t Cy_PDM_PCM_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams);
__STATIC_INLINE void Cy_PDM_PCM_Enable(PDM_Type * base);
__STATIC_INLINE void Cy_PDM_PCM_Disable(PDM_Type * base);
__STATIC_INLINE void Cy_PDM_PCM_SetInterruptMask(PDM_Type * base, uint32_t interrupt);
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetInterruptMask(PDM_Type const * base);
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetInterruptStatusMasked(PDM_Type const * base);
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetInterruptStatus(PDM_Type const * base);
__STATIC_INLINE void Cy_PDM_PCM_ClearInterrupt(PDM_Type * base, uint32_t interrupt);
__STATIC_INLINE void Cy_PDM_PCM_SetInterrupt(PDM_Type * base, uint32_t interrupt);
__STATIC_INLINE uint8_t Cy_PDM_PCM_GetNumInFifo(PDM_Type const * base);
__STATIC_INLINE void Cy_PDM_PCM_ClearFifo(PDM_Type * base);
__STATIC_INLINE uint32_t Cy_PDM_PCM_ReadFifo(PDM_Type const * base);
__STATIC_INLINE void Cy_PDM_PCM_EnableSoftMute(PDM_Type * base);
__STATIC_INLINE void Cy_PDM_PCM_DisableSoftMute(PDM_Type * base);
__STATIC_INLINE void Cy_PDM_PCM_FreezeFifo(PDM_Type * base);
__STATIC_INLINE void Cy_PDM_PCM_UnfreezeFifo(PDM_Type * base);
__STATIC_INLINE uint32_t Cy_PDM_PCM_ReadFifoSilent(PDM_Type const * base);
/** \} group_pdm_pcm_functions */
/**
* \addtogroup group_pdm_pcm_functions
* \{
*/
/******************************************************************************
* Function Name: Cy_PDM_PCM_Enable
***************************************************************************//**
*
* Enables the PDM-PCM data conversion.
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_Enable(PDM_Type * base)
{
base->CMD |= PDM_CMD_STREAM_EN_Msk;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_Disable
***************************************************************************//**
*
* Disables the PDM-PCM data conversion.
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_Disable(PDM_Type * base)
{
base->CMD &= (uint32_t) ~PDM_CMD_STREAM_EN_Msk;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_GetCurrentState
***************************************************************************//**
*
* Returns the current PDM-PCM state (running/stopped).
*
* \param base Pointer to PDM-PCM instance address.
* \return The current state (CMD register).
*
******************************************************************************/
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetCurrentState(PDM_Type const * base)
{
return (base->CMD);
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_SetInterruptMask
***************************************************************************//**
*
* Sets one or more PDM-PCM interrupt factor bits (sets the INTR_MASK register).
*
* \param base Pointer to PDM-PCM instance address
* \param interrupt Interrupt bit mask \ref group_pdm_pcm_macros_intrerrupt_masks.
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_SetInterruptMask(PDM_Type * base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_PDM_PCM_IS_INTR_MASK_VALID(interrupt));
base->INTR_MASK = interrupt;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_GetInterruptMask
***************************************************************************//**
*
* Returns the PDM-PCM interrupt mask (a content of the INTR_MASK register).
*
* \param base Pointer to PDM-PCM instance address
* \return The interrupt bit mask \ref group_pdm_pcm_macros_intrerrupt_masks.
*
******************************************************************************/
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetInterruptMask(PDM_Type const * base)
{
return (base->INTR_MASK);
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_GetInterruptStatusMasked
***************************************************************************//**
*
* Reports status of enabled (masked) PDM-PCM interrupt sources
* (an INTR_MASKED register).
*
* \param base Pointer to PDM-PCM instance address
* \return The interrupt bit mask \ref group_pdm_pcm_macros_intrerrupt_masks.
*
*****************************************************************************/
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetInterruptStatusMasked(PDM_Type const * base)
{
return (base->INTR_MASKED);
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_GetInterruptStatus
***************************************************************************//**
*
* Reports status of PDM-PCM interrupt sources (an INTR register).
*
* \param base Pointer to PDM-PCM instance address
* \return The interrupt bit mask \ref group_pdm_pcm_macros_intrerrupt_masks.
*
******************************************************************************/
__STATIC_INLINE uint32_t Cy_PDM_PCM_GetInterruptStatus(PDM_Type const * base)
{
return (base->INTR);
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_ClearInterrupt
***************************************************************************//**
*
* Clears one or more PDM-PCM interrupt status (sets an INTR register's bits).
*
* \param base Pointer to PDM-PCM instance address
* \param interrupt
* The interrupt bit mask \ref group_pdm_pcm_macros_intrerrupt_masks.
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_ClearInterrupt(PDM_Type * base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_PDM_PCM_IS_INTR_MASK_VALID(interrupt));
base->INTR = interrupt;
(void) base->INTR;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_SetInterrupt
***************************************************************************//**
*
* Sets one or more interrupt source status (sets an INTR_SET register).
*
* \param base Pointer to PDM-PCM instance address
* \param interrupt
* The interrupt bit mask \ref group_pdm_pcm_macros_intrerrupt_masks.
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_SetInterrupt(PDM_Type * base, uint32_t interrupt)
{
CY_ASSERT_L2(CY_PDM_PCM_IS_INTR_MASK_VALID(interrupt));
base->INTR_SET = interrupt;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_GetNumInFifo
***************************************************************************//**
*
* Reports the current number of used words in the output data FIFO.
*
* \param base Pointer to PDM-PCM instance address
* \return Current number of used FIFO words (range is 0 - 254)
*
******************************************************************************/
__STATIC_INLINE uint8_t Cy_PDM_PCM_GetNumInFifo(PDM_Type const * base)
{
return (uint8_t) (_FLD2VAL(PDM_RX_FIFO_STATUS_USED, base->RX_FIFO_STATUS));
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_ClearFifo
***************************************************************************//**
*
* Resets the output data FIFO, removing all data words from the FIFO.
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_ClearFifo(PDM_Type * base)
{
base->RX_FIFO_CTL |= PDM_RX_FIFO_CTL_CLEAR_Msk; /* clear FIFO and disable it */
base->RX_FIFO_CTL &= (uint32_t) ~PDM_RX_FIFO_CTL_CLEAR_Msk; /* enable FIFO */
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_ReadFifo
***************************************************************************//**
*
* Reads ("pops") one word from the output data FIFO.
*
* \param base Pointer to PDM-PCM instance address.
* \return Data word.
*
******************************************************************************/
__STATIC_INLINE uint32_t Cy_PDM_PCM_ReadFifo(PDM_Type const * base)
{
return (base->RX_FIFO_RD);
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_EnableSoftMute
***************************************************************************//**
*
* Enables soft mute
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_EnableSoftMute(PDM_Type * base)
{
base->CTL |= PDM_CTL_SOFT_MUTE_Msk;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_DisableSoftMute
***************************************************************************//**
*
* Disables soft mute
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_DisableSoftMute(PDM_Type * base)
{
base->CTL &= (uint32_t) ~PDM_CTL_SOFT_MUTE_Msk;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_FreezeFifo
***************************************************************************//**
*
* Freezes RX FIFO (Debug purpose)
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_FreezeFifo(PDM_Type * base)
{
base->RX_FIFO_CTL |= PDM_RX_FIFO_CTL_FREEZE_Msk;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_UnfreezeFifo
***************************************************************************//**
*
* Unfreezes RX FIFO (Debug purpose)
*
* \param base Pointer to PDM-PCM instance address
*
******************************************************************************/
__STATIC_INLINE void Cy_PDM_PCM_UnfreezeFifo(PDM_Type * base)
{
base->RX_FIFO_CTL &= (uint32_t) ~PDM_RX_FIFO_CTL_FREEZE_Msk;
}
/******************************************************************************
* Function Name: Cy_PDM_PCM_ReadFifoSilent
***************************************************************************//**
*
* Reads RX FIFO silent (without touching the FIFO function)
*
* \param base Pointer to PDM-PCM instance address.
* \return FIFO value.
*
******************************************************************************/
__STATIC_INLINE uint32_t Cy_PDM_PCM_ReadFifoSilent(PDM_Type const * base)
{
return (base->RX_FIFO_RD_SILENT);
}
/** \} group_pdm_pcm_functions */
#ifdef __cplusplus
}
#endif /* of __cplusplus */
#endif /* CY_PDM_PCM_H__ */
/** \} group_pdm_pcm */
/* [] END OF FILE */

View File

@ -1,14 +1,14 @@
/***************************************************************************//**
/***************************************************************************//**
* \file cy_profile.c
* \version 1.0
*
* Provides an API declaration of the energy profiler (EP) driver.
*
* Provides an API implementation of the energy profiler (EP) driver.
*
********************************************************************************
* \copyright
* Copyright 2016, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
@ -22,7 +22,7 @@ extern "C" {
/* # of elements in an array */
#define CY_N_ELMTS(a) (sizeof(a)/sizeof((a)[0]))
static uint32_t Cy_Profile_IsPtrValid(const cy_stc_profile_ctr_ptr_t ctrAddr);
static cy_en_profile_status_t Cy_Profile_IsPtrValid(const cy_stc_profile_ctr_ptr_t ctrAddr);
/* control and status information for each counter */
static cy_stc_profile_ctr_t cy_ep_ctrs[PROFILE_PRFL_CNT_NR];
@ -39,24 +39,25 @@ static cy_stc_profile_ctr_t cy_ep_ctrs[PROFILE_PRFL_CNT_NR];
* the cy_ep_ctrs[] array, and (2) whether the counter has been assigned.
*
* \param ctrAddr The handle to (address of) the assigned counter
*
*
* \return CY_PROFILE_SUCCESS, or CY_PROFILE_BAD_PARAM for invalid ctrAddr or counter not
* in use.
*
*******************************************************************************/
static uint32_t Cy_Profile_IsPtrValid(const cy_stc_profile_ctr_ptr_t ctrAddr)
static cy_en_profile_status_t Cy_Profile_IsPtrValid(const cy_stc_profile_ctr_ptr_t ctrAddr)
{
uint32_t retVal = CY_PROFILE_BAD_PARAM;
cy_en_profile_status_t retStatus = CY_PROFILE_BAD_PARAM;
/* check for valid ctrAddr */
uint32_t p_epCtrs = (uint32_t)cy_ep_ctrs;
if ((p_epCtrs <= (uint32_t)ctrAddr) && ((uint32_t)ctrAddr < (p_epCtrs + (uint32_t)sizeof(cy_ep_ctrs))))
{
if (ctrAddr->used != 0u) /* check for counter being used */
{
retVal = CY_PROFILE_SUCCESS;
retStatus = CY_PROFILE_SUCCESS;
}
}
return (retVal);
return (retStatus);
}
@ -70,12 +71,12 @@ static uint32_t Cy_Profile_IsPtrValid(const cy_stc_profile_ctr_ptr_t ctrAddr)
* EP interrupt handler: Increments the overflow member of the counter structure,
* for each counter that is in use and has an overflow.
*
* This handler is not configured or used automatically. You must configure the
* interrupt handler for the EP, using Cy_SysInt_Init(). Typically you configure
* This handler is not configured or used automatically. You must configure the
* interrupt handler for the EP, using Cy_SysInt_Init(). Typically you configure
* the system to use \ref Cy_Profile_ISR() as the overflow interrupt handler. You
* can provide a custom interrupt handler to perform additional operations if
* required. Your handler can call \ref Cy_Profile_ISR() to handle counter
* overflow.
* overflow.
*
*******************************************************************************/
void Cy_Profile_ISR(void)
@ -111,7 +112,7 @@ void Cy_Profile_ISR(void)
*
* Starts profiling.
*
* \note Before calling this function, the user must enable the EP interrupt.
* \note Before calling this function, the user must enable the profiler interrupt.
*******************************************************************************/
void Cy_Profile_StartProfiling(void)
{
@ -148,6 +149,9 @@ void Cy_Profile_ClearConfiguration(void)
* Assigns a given monitor source to a counter, and loads the CTL register
* bitfields of an assigned counter.
*
* The available monitor sources vary per device series. Refer to the series-specific
* configuration header file for the list of available monitor sources.
*
* \param monitor The monitor source #
*
* \param duration Events are monitored (0), or duration is monitored (1)
@ -156,16 +160,16 @@ void Cy_Profile_ClearConfiguration(void)
* In general, it is recommended to use CY_PROFILE_CLK_HF to maximize resolution.
*
* \param weight Weighting factor for the counter value
*
*
* \return A pointer to the counter data structure. NULL if no counter is
* available.
*
* \note The counter is not enabled by this function. See functions
* \ref Cy_Profile_EnableCounter() and \ref Cy_Profile_DisableCounter(). See the
* Technical Reference Manual chapter on the EP for reference clock considerations.
*
* Technical Reference Manual (TRM) chapter on the EP for reference clock considerations.
*
*******************************************************************************/
cy_stc_profile_ctr_ptr_t Cy_Profile_ConfigureCounter(en_ep_mon_sel_t monitor, uint32_t duration,
cy_stc_profile_ctr_ptr_t Cy_Profile_ConfigureCounter(en_ep_mon_sel_t monitor, cy_en_profile_duration_t duration,
cy_en_profile_ref_clk_t refClk, uint32_t weight)
{
cy_stc_profile_ctr_ptr_t retVal = NULL; /* error value if no counter is available */
@ -177,14 +181,14 @@ cy_stc_profile_ctr_ptr_t Cy_Profile_ConfigureCounter(en_ep_mon_sel_t monitor, ui
cy_ep_ctrs[i].ctrNum = i;
cy_ep_ctrs[i].used = 1u;
cy_ep_ctrs[i].cntAddr = (PROFILE_CNT_STRUCT_Type *)&(PROFILE->CNT_STRUCT[i]);
cy_ep_ctrs[i].ctlRegVals.cntDuration = (uint8_t)duration;
cy_ep_ctrs[i].ctlRegVals.cntDuration = duration;
cy_ep_ctrs[i].ctlRegVals.refClkSel = refClk;
cy_ep_ctrs[i].ctlRegVals.monSel = monitor;
cy_ep_ctrs[i].overflow = 0UL;
cy_ep_ctrs[i].weight = weight;
/* pass back the handle to (address of) the counter data structure */
retVal = &cy_ep_ctrs[i];
/* Load the CTL register bitfields of the assigned counter. */
retVal->cntAddr->CTL =
_VAL2FLD(PROFILE_CNT_STRUCT_CTL_CNT_DURATION, retVal->ctlRegVals.cntDuration) |
@ -204,21 +208,23 @@ cy_stc_profile_ctr_ptr_t Cy_Profile_ConfigureCounter(en_ep_mon_sel_t monitor, ui
* calling this function.
*
* \param ctrAddr The handle to (address of) the assigned counter, which is
* obtained by a call to \ref Cy_Profile_ConfigureCounter()
*
* obtained by a call to \ref Cy_Profile_ConfigureCounter().
*
* \return \ref CY_PROFILE_SUCCESS, or \ref CY_PROFILE_BAD_PARAM for counter not in use.
*
* \note The counter is not disabled by this function. See functions
* \ref Cy_Profile_EnableCounter() and \ref Cy_Profile_DisableCounter().
*******************************************************************************/
uint32_t Cy_Profile_FreeCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
cy_en_profile_status_t Cy_Profile_FreeCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
{
uint32_t retVal = Cy_Profile_IsPtrValid(ctrAddr);
if (retVal == CY_PROFILE_SUCCESS)
cy_en_profile_status_t retStatus = CY_PROFILE_BAD_PARAM;
retStatus = Cy_Profile_IsPtrValid(ctrAddr);
if (retStatus == CY_PROFILE_SUCCESS)
{
ctrAddr->used = 0u;
}
return (retVal);
return (retStatus);
}
/*******************************************************************************
@ -229,22 +235,24 @@ uint32_t Cy_Profile_FreeCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
* called for this counter before calling this function.
*
* \param ctrAddr The handle to (address of) the assigned counter, which is
* obtained by a call to \ref Cy_Profile_ConfigureCounter()
*
* obtained by a call to \ref Cy_Profile_ConfigureCounter().
*
* \return \ref CY_PROFILE_SUCCESS, or \ref CY_PROFILE_BAD_PARAM for counter not in use.
*
*******************************************************************************/
uint32_t Cy_Profile_EnableCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
cy_en_profile_status_t Cy_Profile_EnableCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
{
uint32_t retVal = Cy_Profile_IsPtrValid(ctrAddr);
if (retVal == CY_PROFILE_SUCCESS)
cy_en_profile_status_t retStatus = CY_PROFILE_BAD_PARAM;
retStatus = Cy_Profile_IsPtrValid(ctrAddr);
if (retStatus == CY_PROFILE_SUCCESS)
{
/* set the ENABLED bit */
ctrAddr->cntAddr->CTL |= _VAL2FLD(PROFILE_CNT_STRUCT_CTL_ENABLED, 1UL);
/* set the INTR_MASK bit for the counter being used */
PROFILE->INTR_MASK |= (1UL << (ctrAddr->ctrNum));
}
return (retVal);
return (retStatus);
}
/*******************************************************************************
@ -255,22 +263,22 @@ uint32_t Cy_Profile_EnableCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
* called for this counter before calling this function.
*
* \param ctrAddr The handle to (address of) the assigned counter, which is
* obtained by a call to \ref Cy_Profile_ConfigureCounter()
*
* obtained by a call to \ref Cy_Profile_ConfigureCounter().
*
* \return \ref CY_PROFILE_SUCCESS, or \ref CY_PROFILE_BAD_PARAM for counter not in use.
*
*******************************************************************************/
uint32_t Cy_Profile_DisableCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
cy_en_profile_status_t Cy_Profile_DisableCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
{
uint32_t retVal = Cy_Profile_IsPtrValid(ctrAddr);
if (retVal == CY_PROFILE_SUCCESS)
cy_en_profile_status_t retStatus = Cy_Profile_IsPtrValid(ctrAddr);
if (retStatus == CY_PROFILE_SUCCESS)
{
/* clear the ENABLED bit */
ctrAddr->cntAddr->CTL &= ~(_VAL2FLD(PROFILE_CNT_STRUCT_CTL_ENABLED, 1UL));
/* clear the INTR_MASK bit for the counter being used */
PROFILE->INTR_MASK &= ~(1UL << (ctrAddr->ctrNum));
}
return (retVal);
return (retStatus);
}
@ -284,17 +292,17 @@ uint32_t Cy_Profile_DisableCounter(cy_stc_profile_ctr_ptr_t ctrAddr)
* Reports the count value for a specified counter.
*
* \param ctrAddr the handle to (address of) the assigned counter, which is
* obtained by a call to \ref Cy_Profile_ConfigureCounter()
*
* \param result the address to which to write the result
* obtained by a call to \ref Cy_Profile_ConfigureCounter().
*
* \param result The address to which to write the result.
*
* \return \ref CY_PROFILE_SUCCESS, or \ref CY_PROFILE_BAD_PARAM for counter not in use.
*
*******************************************************************************/
uint32_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result)
cy_en_profile_status_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result)
{
uint32_t retVal = Cy_Profile_IsPtrValid(ctrAddr);
if (retVal == CY_PROFILE_SUCCESS)
cy_en_profile_status_t retStatus = Cy_Profile_IsPtrValid(ctrAddr);
if (retStatus == CY_PROFILE_SUCCESS)
{
/* read the counter control register, and the counter current value */
ctrAddr->ctlReg = ctrAddr->cntAddr->CTL;
@ -303,7 +311,7 @@ uint32_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *resu
/* report the count with overflow */
*result = ((uint64_t)(ctrAddr->overflow) << 32) | (uint64_t)(ctrAddr->cntReg);
}
return (retVal);
return (retStatus);
}
/*******************************************************************************
@ -314,23 +322,23 @@ uint32_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *resu
* factor set in \ref Cy_Profile_ConfigureCounter() for that counter.
*
* \param ctrAddr the handle to (address of) the assigned counter, which is
* obtained by a call to \ref Cy_Profile_ConfigureCounter()
*
* \param result the address to which to write the result
* obtained by a call to \ref Cy_Profile_ConfigureCounter().
*
* \param result The address to which to write the result.
*
* \return \ref CY_PROFILE_SUCCESS, or \ref CY_PROFILE_BAD_PARAM for counter not in use.
*
*******************************************************************************/
uint32_t Cy_Profile_GetWeightedCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result)
cy_en_profile_status_t Cy_Profile_GetWeightedCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result)
{
uint64_t temp;
uint32_t retVal = Cy_Profile_GetRawCount(ctrAddr, &temp);
if (retVal == CY_PROFILE_SUCCESS)
cy_en_profile_status_t retStatus = Cy_Profile_GetRawCount(ctrAddr, &temp);
if (retStatus == CY_PROFILE_SUCCESS)
{
/* calculate weighted count */
*result = temp * (uint64_t)(ctrAddr->weight);
}
return (retVal);
return (retStatus);
}
/*******************************************************************************
@ -340,14 +348,14 @@ uint32_t Cy_Profile_GetWeightedCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t
* Calls \ref Cy_Profile_GetWeightedCount() for all specified counters. Reports the sum
* across all valid counters.
*
* \param ptrsArray array of handles to (addresses of) assigned counters
* \param ptrsArray Array of handles to (addresses of) assigned counters
*
* \param numCounters number of scanned elements in ptrsArray[]
* \param numCounters Number of scanned elements in ptrsArray[]
*
* \return The sum
* \return The sum
*
*******************************************************************************/
uint64_t Cy_Profile_GetSumWeightedCounts(const cy_stc_profile_ctr_ptr_t ptrsArray[],
uint64_t Cy_Profile_GetSumWeightedCounts(cy_stc_profile_ctr_ptr_t ptrsArray[],
uint32_t numCounters)
{
uint64_t daSum = (uint64_t)0ul;
@ -362,7 +370,7 @@ uint64_t Cy_Profile_GetSumWeightedCounts(const cy_stc_profile_ctr_ptr_t ptrsArra
daSum += num;
}
}
return (daSum);
}

View File

@ -0,0 +1,376 @@
/***************************************************************************//**
* \file cy_profile.h
* \version 1.0
*
* Provides an API declaration of the profiler driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_energy_profiler Energy Profiler (Profile)
* \{
*
* The profiler driver contains an API for configuring and using the
* profiler hardware. The profiler enables measurement of the relative
* amount of energy consumed by particular peripherals. Traditional
* profilers correlate energy consumption to the program counter, which helps you
* understand when power is consumed. The profiler provides additional insight into the
* device so you can identify an asynchronous activity that causes energy
* consumption. In other words, the profiler helps you understand where power is consumed.
*
* The profiler does not measure or report actual energy consumption. It measures either
* clock cycles or the number of events that have occurred in the profiling window.
* To derive relative energy consumption for each source, you can multiply the
* absolute count (clock cycles or events) for that source by a coefficient.
*
* Many of the sources available for monitoring are asynchronous operations where
* the cause of energy consumption may be difficult to identify using external hardware.
*
* \section group_profile_configuration Configuration Considerations
*
* There is no PSoC Creator component for this peripheral. To use the profiler you
* include the header file and configure the counters by writing code and calling
* the Profiler API functions.
*
* At the highest level, you perform these tasks:
* - Initialize the profiling block
* - Set up the profiling interrupt
* - Configure, initialize, and enable the counters
* - Start and stop profiling
* - Get the results
* - Exit gracefully
*
* The profiler manages a set of counters. For each counter you use, you assign the source
* you want monitored, a reference clock, and a coefficient used to calculate results.
* You can also get the raw count for any counter.
*
* Each counter is a 32-bit register that counts either a number of clock cycles,
* or a number of events. It is possible to overflow the 32-bit register. The
* firmware implements a 32-bit overflow counter. Combined with the 32-bit register,
* this gives you a 64-bit counter for each monitored source. The profiler generates
* an interrupt when an overflow occurs. You must configure the interrupt handler
* using Cy_SysInt_Init(). You can use Cy_Profile_ISR() as the interrupt handler. It
* increments the overflow counter for each profiling counter that is in use.
*
* When finished profiling, disable the profiler -- do the following:
* - Stop profiling. See \ref Cy_Profile_StopProfiling().
* - Clear all profiling configuration. See \ref Cy_Profile_ClearConfiguration().
* - Disable the profiling interrupt.
* - Disable the profiler. See \ref Cy_Profile_DeInit().
*
* See notes on individual function definitions.
*
* \section group_profile_more_information More Information
*
* See the profiler chapter of the device technical reference manual (TRM).
*
* \section group_profile_MISRA MISRA-C Compliance
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>12.4</td>
* <td>R</td>
* <td>Right hand operand of '&&' or '||' is an expression with possible side effects.</td>
* <td>Function-like macros are used to achieve more efficient code.</td>
* </tr>
* <tr>
* <td>16.7</td>
* <td>A</td>
* <td>A pointer parameter can be of type 'pointer to const'.</td>
* <td>The pointer is cast for comparison purposes and thus can't be a const.</td>
* </tr>
* </table>
*
* \section group_profile_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_profile_macros Macros
* \defgroup group_profile_functions Functions
* \{
* \defgroup group_profile_functions_interrupt Interrupt Functions
* \defgroup group_profile_functions_general General Functions
* \defgroup group_profile_functions_counter Counter Functions
* \defgroup group_profile_functions_calculation Calculation Functions
* \}
* \defgroup group_profile_data_structures Data Structures
* \defgroup group_profile_enums Enumerated Types
*/
#if !defined(CY_PROFILE_H)
#define CY_PROFILE_H
#include "cy_device_headers.h"
#include "syslib/cy_syslib.h"
#include <stddef.h>
#ifndef CY_IP_MXPROFILE
#error "The PROFILE driver is not supported on this device"
#endif
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/** \addtogroup group_profile_macros
* \{
*/
/** Driver major version */
#define CY_PROFILE_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_PROFILE_DRV_VERSION_MINOR 0
/** Profile driver identifier */
#define CY_PROFILE_ID CY_PDL_DRV_ID(0x1EU)
/** Start profiling command for the CMD register */
#define CY_PROFILE_START_TR 1UL
/** Stop profiling command for the CMD register */
#define CY_PROFILE_STOP_TR 2UL
/** Command to clear all counter registers to 0 */
#define CY_PROFILE_CLR_ALL_CNT 0x100UL
/** \} group_profile_macros */
/**
* \addtogroup group_profile_enums
* \{
*/
/**
* The possible values for CTR register, REF_CLK_SEL bitfield. See the
* technical reference manual (TRM) for reference clock considerations.
*/
typedef enum
{
CY_PROFILE_CLK_TIMER = 0, /**< See SRSS register CLK_TIMER_CTL.TIMER_SEL */
CY_PROFILE_CLK_IMO = 1, /**< Internal main oscillator */
CY_PROFILE_CLK_ECO = 2, /**< External crystal oscillator */
CY_PROFILE_CLK_LF = 3, /**< See SRSS register CLK_SELECT.LFCLK_SEL */
CY_PROFILE_CLK_HF = 4, /**< See SRSS registers CLK_ROOT_SELECT[0].ROOT_MUX and CLK_ROOT_SELECT[0].ROOT_DIV */
CY_PROFILE_CLK_PERI = 5, /**< See CPUSS register CM0_CLOCK_CTL.PERI_INT_DIV */
} cy_en_profile_ref_clk_t;
/**
* The possible values for CTR register, CNT_DURATION bitfield. See the
* technical reference manual (TRM) event / duration considerations.
*/
typedef enum
{
CY_PROFILE_EVENT = 0, /**< count module events */
CY_PROFILE_DURATION = 1, /**< count duration in clock cycles */
} cy_en_profile_duration_t;
/** Profiler status codes */
typedef enum
{
/** Operation completed successfully */
CY_PROFILE_SUCCESS = 0x00U,
/** One or more of input parameters are invalid */
CY_PROFILE_BAD_PARAM = CY_PROFILE_ID | CY_PDL_STATUS_ERROR | 1UL
} cy_en_profile_status_t;
/** \} group_profile_enums */
/**
* \addtogroup group_profile_data_structures
* \{
*/
/**
* Profiler counter control register structure. For each counter, holds the CTL register fields.
*/
typedef struct
{
cy_en_profile_duration_t cntDuration; /**< 0 = events are monitored; 1 = duration is monitored */
cy_en_profile_ref_clk_t refClkSel; /**< The reference clock used by this counter; 3 bits */
en_ep_mon_sel_t monSel; /**< The monitor signal to be observed by this counter; # bits = PROFILE_CNT_STRUCT_PRFL_MONITOR_NR_LOG2 */
} cy_stc_profile_ctr_ctl_t;
/**
* Structure holding all information for an profiler counter.
*/
typedef struct
{
uint8_t ctrNum; /**< hardware counter # */
uint8_t used; /**< used 0 = available, 1 = being used */
cy_stc_profile_ctr_ctl_t ctlRegVals; /**< counter CTL reg bitfield values */
PROFILE_CNT_STRUCT_Type * cntAddr; /**< base MMIO addr of counter registers */
uint32_t ctlReg; /**< also includes enabled/disabled status */
uint32_t cntReg; /**< current counter value */
uint32_t overflow; /**< this register and cntReg form a 64-bit counter value */
uint32_t weight; /**< counter weighting factor */
} cy_stc_profile_ctr_t;
/**
* Pointer to structure holding all information for an profiler counter.
*/
typedef cy_stc_profile_ctr_t * cy_stc_profile_ctr_ptr_t;
/** \} group_profile_data_structures */
/**
* \addtogroup group_profile_functions
* \{
*/
/**
* \addtogroup group_profile_functions_interrupt
* \{
*/
/* ========================================================================== */
/* ==================== INTERRUPT FUNCTION SECTION ==================== */
/* ========================================================================== */
void Cy_Profile_ISR(void);
/** \} group_profile_functions_interrupt */
/**
* \addtogroup group_profile_functions_general
* \{
*/
__STATIC_INLINE void Cy_Profile_Init(void);
__STATIC_INLINE void Cy_Profile_DeInit(void);
void Cy_Profile_StartProfiling(void);
__STATIC_INLINE void Cy_Profile_DeInit(void);
__STATIC_INLINE void Cy_Profile_StopProfiling(void);
__STATIC_INLINE uint32_t Cy_Profile_IsProfiling(void);
/* ========================================================================== */
/* =============== GENERAL PROFILER FUNCTIONS SECTION ================= */
/* ========================================================================== */
/*******************************************************************************
* Function Name: Cy_Profile_Init
****************************************************************************//**
*
* Turns on the profiler for profiling. It must be called once when energy profiling is
* desired. This does not start a profiling session. Use Cy_Profile_StartProfiling()
* to start a profiling session.
*
* \note Before calling this function, the user must configure the profiler interrupt
* so that \ref Cy_Profile_ISR() is executed.
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_Init(void)
{
PROFILE->CTL = _VAL2FLD(PROFILE_CTL_ENABLED, 1UL/*enabled */) |
_VAL2FLD(PROFILE_CTL_WIN_MODE, 0UL/*start/stop mode*/);
PROFILE->INTR_MASK = 0UL; /* clear all counter interrupt mask bits */
}
/*******************************************************************************
* Function Name: Cy_Profile_DeInit
****************************************************************************//**
*
* Turns off the profiler. It should be called when energy profiling is no longer
* desired.
*
* \note When calling this function, the user should consider also deallocating
* the profiler interrupt.
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_DeInit(void)
{
PROFILE->CTL = _VAL2FLD(PROFILE_CTL_ENABLED, 0UL/*disabled */);
PROFILE->INTR_MASK = 0UL; /* clear all counter interrupt mask bits */
}
/*******************************************************************************
* Function Name: Cy_Profile_StopProfiling
****************************************************************************//**
*
* Stops profiling.
*
* \note When calling this function, the user should also disable the profiler
* interrupt.
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_StopProfiling(void)
{
PROFILE->CMD = CY_PROFILE_STOP_TR;
}
/*******************************************************************************
* Function Name: Cy_Profile_IsProfiling
****************************************************************************//**
*
* Reports whether or not profiling is active.
*
* \return 0 = profiling is not active; 1 = profiling is active
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_Profile_IsProfiling(void)
{
return _FLD2VAL(PROFILE_STATUS_WIN_ACTIVE, PROFILE->STATUS);
}
/** \} group_profile_functions_general */
/**
* \addtogroup group_profile_functions_counter
* \{
*/
void Cy_Profile_ClearConfiguration(void);
__STATIC_INLINE void Cy_Profile_ClearCounters(void);
cy_stc_profile_ctr_ptr_t Cy_Profile_ConfigureCounter(en_ep_mon_sel_t monitor, cy_en_profile_duration_t duration, cy_en_profile_ref_clk_t refClk, uint32_t weight);
cy_en_profile_status_t Cy_Profile_FreeCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
cy_en_profile_status_t Cy_Profile_EnableCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
cy_en_profile_status_t Cy_Profile_DisableCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
/* ========================================================================== */
/* =================== COUNTER FUNCTIONS SECTION ====================== */
/* ========================================================================== */
/*******************************************************************************
* Function Name: Cy_Profile_ClearCounters
****************************************************************************//**
*
* Clears all hardware counters to 0.
*
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_ClearCounters(void)
{
PROFILE->CMD = CY_PROFILE_CLR_ALL_CNT;
}
/** \} group_profile_functions_counter */
/**
* \addtogroup group_profile_functions_calculation
* \{
*/
/* ========================================================================== */
/* ================== CALCULATION FUNCTIONS SECTION =================== */
/* ========================================================================== */
cy_en_profile_status_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result);
cy_en_profile_status_t Cy_Profile_GetWeightedCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result);
uint64_t Cy_Profile_GetSumWeightedCounts(cy_stc_profile_ctr_ptr_t ptrsArray[], uint32_t numCounters);
/** \} group_profile_functions_calculation */
/** \} group_profile_functions */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* CY_PROFILE_H */
/** \} group_profile */
/* [] END OF FILE */

View File

@ -20,22 +20,22 @@
* The Protection Unit driver provides an API to configure the Memory Protection
* Units (MPU), Shared Memory Protection Units (SMPU), and Peripheral Protection
* Units (PPU). These are separate from the ARM Core MPUs and provide additional
* mechanisms for securing resource accesses. The Protection units address the
* mechanisms for securing resource accesses. The Protection units address the
* following concerns in an embedded design:
* - Security requirements. This includes the prevention of malicious attacks
* to access secure memory or peripherals.
* - Safety requirements. This includes detection of accidental (non-malicious)
* SW errors and random HW errors. It is important to enable failure analysis
* to investigate the root cause of a safety violation.
*
*
* \n
* <b> Memory Protection </b>
*
* Memory protection is provided by MPUs and SMPUs and allows control of
* Memory protection is provided by MPUs and SMPUs and allows control of
* memory accesses by bus masters (e.g., CM0+, CM4, Crypto):
* - MPUs are used to distinguish user and privileged accesses from a single bus
* master such as task switching in an OS/kernel. For ARM core MPUs, the
* assigned Cypress MPUs for those cores provide additional functionality
* - MPUs are used to distinguish user and privileged accesses from a single bus
* master such as task switching in an OS/kernel. For ARM core MPUs, the
* assigned Cypress MPUs for those cores provide additional functionality
* such as protection contexts (PC) and security attributes.
* - SMPUs are used to distinguish memory accesses between bus masters. This is
* achieved by using protection contexts and secure-/non-secure attributes.
@ -50,19 +50,19 @@
* type of peripheral protection unit.
* - Fixed Group (GR) PPUs are used to protect an entire peripheral MMIO group
* from invalid bus master accesses. The MMIO grouping information and which
* resource belongs to which group is device specific and can be obtained
* resource belongs to which group is device specific and can be obtained
* from the device technical reference manual (TRM).
* - Fixed Region (RG) PPUs are used to protect an entire peripheral slave
* instance from invalid bus master accesses. For example, TCPWM0, TCPWM1,
* - Fixed Region (RG) PPUs are used to protect an entire peripheral slave
* instance from invalid bus master accesses. For example, TCPWM0, TCPWM1,
* SCB0, and SCB1, etc.
* - Fixed Slave (SL) PPUs are used to protect specified regions of peripheral
* instances. For example, individual DW channel structs, SMPU structs, and
* instances. For example, individual DW channel structs, SMPU structs, and
* IPC structs, etc.
*
* \n
* <b> Driver Usage </b>
*
* Each protection unit is distinguished by its type (e.g.
* Each protection unit is distinguished by its type (e.g.
* PROT_MPU_MPU_STRUCT_Type). The list of supported protection units can be
* obtained from the device header file. Choose a protection unit of interest,
* and call its corresponding Cy_Prot_Config<X>Struct() function with its
@ -70,8 +70,8 @@
* protection unit by calling the Cy_Prot_Enable<X>Struct() function.
*
* Each bus master can be configured to allow/disallow certain types of accesses
* by calling the Cy_Prot_ConfigBusMaster() function. For example, CM0+ core
* is a bus master. By configuring it to allow only protection contexts (PC)
* by calling the Cy_Prot_ConfigBusMaster() function. For example, CM0+ core
* is a bus master. By configuring it to allow only protection contexts (PC)
* 2 and 3, the bus master will be able to set its protection context only to
* 2 or 3. In a thread execution, the CM0+ core can set its protection context
* to 2 by calling Cy_Prot_SetActivePC() and access all regions of memory that
@ -80,7 +80,7 @@
*
* \section group_prot_configuration Configuration Considerations
*
* With the exception of MPUs, Protection structures are implemented in
* With the exception of MPUs, Protection structures are implemented in
* hardware as master and slave pairs. The master protection structure protects
* the slave protection structure. The slave protection structure protects the
* memory region that is to be protected.
@ -121,7 +121,7 @@
* </tr>
* </table>
*
* \defgroup group_prot_macro Macro
* \defgroup group_prot_macros Macros
* \defgroup group_prot_functions Functions
* \{
* \defgroup group_prot_functions_busmaster Bus Master and PC Functions
@ -147,7 +147,7 @@
extern "C" {
#endif
/** \addtogroup group_prot_macro
/** \addtogroup group_prot_macros
* \{
*/
@ -160,7 +160,7 @@ extern "C" {
/** Prot driver ID */
#define CY_PROT_ID CY_PDL_DRV_ID(0x30u)
/** \} group_prot_macro */
/** \} group_prot_macros */
/**
* \addtogroup group_prot_enums
@ -170,7 +170,7 @@ extern "C" {
/**
* Prot Driver error codes
*/
typedef enum
typedef enum
{
CY_PROT_SUCCESS = 0x00u, /**< Returned successful */
CY_PROT_BAD_PARAM = CY_PROT_ID | CY_PDL_STATUS_ERROR | 0x01u, /**< Bad parameter was passed */
@ -180,7 +180,7 @@ typedef enum
/**
* User/Privileged permission
*/
typedef enum
typedef enum
{
CY_PROT_PERM_DISABLED = 0x00u, /**< Read, Write and Execute disabled */
CY_PROT_PERM_R = 0x01u, /**< Read enabled */
@ -195,7 +195,7 @@ typedef enum
/**
* Memory region size
*/
typedef enum
typedef enum
{
CY_PROT_SIZE_256B = 7u, /**< 256 bytes */
CY_PROT_SIZE_512B = 8u, /**< 512 bytes */
@ -262,7 +262,7 @@ enum cy_en_prot_subreg_t
};
/**
* Protection context mask (PC_MASK)
* Protection context mask (PC_MASK)
*/
enum cy_en_prot_pcmask_t
{
@ -292,6 +292,9 @@ enum cy_en_prot_pcmask_t
/** \cond INTERNAL */
/* Helper function for finding max */
#define CY_PROT_MAX(x,y) (((x)>(y))?(x):(y))
/* General Masks and shifts */
#define CY_PROT_MSX_CTL_SHIFT (0x02UL) /**< Shift for MSx_CTL register */
#define CY_PROT_STRUCT_ENABLE (0x01UL) /**< Enable protection unit struct */
@ -302,8 +305,26 @@ enum cy_en_prot_pcmask_t
#define CY_PROT_ATT_USER_PERMISSION_SHIFT (0x00UL) /**< Protection Unit user attribute permission shift */
#define CY_PROT_ATT_PRIV_PERMISSION_SHIFT (0x03UL) /**< Protection Unit priliged attribute permission shift */
/* Maximum Master Protection Context */
#define CY_PROT_MS_PC_NR_MAX CY_PROT_MAX(CPUSS_PROT_SMPU_MS0_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS1_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS2_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS3_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS4_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS5_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS6_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS7_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS8_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS9_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS10_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS11_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS12_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS13_PC_NR_MINUS1, \
CY_PROT_MAX(CPUSS_PROT_SMPU_MS14_PC_NR_MINUS1, \
CPUSS_PROT_SMPU_MS15_PC_NR_MINUS1)))))))))))))))
/* Protection Context limit masks */
#define CY_PROT_MPU_PC_LIMIT_MASK (0xFFFFFFFFUL << CPUSS_PROT_SMPU_MS0_PC_NR_MINUS1)
#define CY_PROT_MPU_PC_LIMIT_MASK (0xFFFFFFFFUL << CY_PROT_MS_PC_NR_MAX)
#define CY_PROT_SMPU_PC_LIMIT_MASK (0xFFFFFFFFUL << CPUSS_SMPU_STRUCT_PC_NR_MINUS1)
#define CY_PROT_PPU_PROG_PC_LIMIT_MASK (0xFFFFFFFFUL << PERI_PPU_PROG_STRUCT_PC_NR_MINUS1)
#define CY_PROT_PPU_FIXED_PC_LIMIT_MASK (0xFFFFFFFFUL << PERI_PPU_FIXED_STRUCT_PC_NR_MINUS1)
@ -378,7 +399,7 @@ enum cy_en_prot_pcmask_t
*/
/** Configuration structure for MPU Struct initialization */
typedef struct
typedef struct
{
uint32_t* address; /**< Base address of the memory region */
cy_en_prot_size_t regionSize; /**< Size of the memory region */
@ -389,7 +410,7 @@ typedef struct
} cy_stc_mpu_cfg_t;
/** Configuration structure for SMPU struct initialization */
typedef struct
typedef struct
{
uint32_t* address; /**< Base address of the memory region (Only applicable to slave) */
cy_en_prot_size_t regionSize; /**< Size of the memory region (Only applicable to slave) */
@ -402,7 +423,7 @@ typedef struct
} cy_stc_smpu_cfg_t;
/** Configuration structure for Programmable (PROG) PPU (PPU_PR) struct initialization */
typedef struct
typedef struct
{
uint32_t* address; /**< Base address of the memory region (Only applicable to slave) */
cy_en_prot_size_t regionSize; /**< Size of the memory region (Only applicable to slave) */
@ -415,7 +436,7 @@ typedef struct
} cy_stc_ppu_prog_cfg_t;
/** Configuration structure for Fixed Group (GR) PPU (PPU_GR) struct initialization */
typedef struct
typedef struct
{
cy_en_prot_perm_t userPermission; /**< User permissions for the region */
cy_en_prot_perm_t privPermission; /**< Privileged permissions for the region */
@ -425,7 +446,7 @@ typedef struct
} cy_stc_ppu_gr_cfg_t;
/** Configuration structure for Fixed Slave (SL) PPU (PPU_SL) struct initialization */
typedef struct
typedef struct
{
cy_en_prot_perm_t userPermission; /**< User permissions for the region */
cy_en_prot_perm_t privPermission; /**< Privileged permissions for the region */
@ -435,7 +456,7 @@ typedef struct
} cy_stc_ppu_sl_cfg_t;
/** Configuration structure for Fixed Region (RG) PPU (PPU_RG) struct initialization */
typedef struct
typedef struct
{
cy_en_prot_perm_t userPermission; /**< User permissions for the region */
cy_en_prot_perm_t privPermission; /**< Privileged permissions for the region */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* \file cy_scb_common.c
* \version 1.0
* \version 2.0
*
* Provides common API implementation of the SCB driver.
*
@ -30,7 +30,7 @@ extern "C" {
* \param base
* The pointer to the SCB instance.
*
* \param rxBuf
* \param buffer
* The pointer to location to place data read from the receive FIFO.
* The size of the data element defined by the configured data width.
*
@ -38,13 +38,13 @@ extern "C" {
* The number of data elements read from the receive FIFO.
*
*******************************************************************************/
void Cy_SCB_ReadArrayNoCheck(CySCB_Type const *base, void *rxBuf, uint32_t size)
void Cy_SCB_ReadArrayNoCheck(CySCB_Type const *base, void *buffer, uint32_t size)
{
uint32_t idx;
if (Cy_SCB_IsRxDataWidthByte(base))
{
uint8_t *buf = (uint8_t *) rxBuf;
uint8_t *buf = (uint8_t *) buffer;
/* Get data available in RX FIFO */
for (idx = 0UL; idx < size; ++idx)
@ -54,7 +54,7 @@ void Cy_SCB_ReadArrayNoCheck(CySCB_Type const *base, void *rxBuf, uint32_t size)
}
else
{
uint16_t *buf = (uint16_t *) rxBuf;
uint16_t *buf = (uint16_t *) buffer;
/* Get data available in RX FIFO */
for (idx = 0UL; idx < size; ++idx)
@ -76,7 +76,7 @@ void Cy_SCB_ReadArrayNoCheck(CySCB_Type const *base, void *rxBuf, uint32_t size)
* \param base
* The pointer to the SCB instance.
*
* \param rxBuf
* \param buffer
* The pointer to location to place data read from receive FIFO.
* The item size is defined by the data type which depends on the configured
* data width.
@ -88,7 +88,7 @@ void Cy_SCB_ReadArrayNoCheck(CySCB_Type const *base, void *rxBuf, uint32_t size)
* The number of data elements read from the receive FIFO.
*
*******************************************************************************/
uint32_t Cy_SCB_ReadArray(CySCB_Type const *base, void *rxBuf, uint32_t size)
uint32_t Cy_SCB_ReadArray(CySCB_Type const *base, void *buffer, uint32_t size)
{
/* Get available items in RX FIFO */
uint32_t numToCopy = Cy_SCB_GetNumInRxFifo(base);
@ -100,7 +100,7 @@ uint32_t Cy_SCB_ReadArray(CySCB_Type const *base, void *rxBuf, uint32_t size)
}
/* Get data available in RX FIFO */
Cy_SCB_ReadArrayNoCheck(base, rxBuf, numToCopy);
Cy_SCB_ReadArrayNoCheck(base, buffer, numToCopy);
return (numToCopy);
}
@ -117,7 +117,7 @@ uint32_t Cy_SCB_ReadArray(CySCB_Type const *base, void *rxBuf, uint32_t size)
* \param base
* The pointer to the SCB instance.
*
* \param rxBuf
* \param buffer
* The pointer to location to place data read from receive FIFO.
* The item size is defined by the data type which depends on the configured
* data width.
@ -126,17 +126,18 @@ uint32_t Cy_SCB_ReadArray(CySCB_Type const *base, void *rxBuf, uint32_t size)
* The number of data elements to read from receive FIFO.
*
*******************************************************************************/
void Cy_SCB_ReadArrayBlocking(CySCB_Type const *base, void *rxBuf, uint32_t size)
void Cy_SCB_ReadArrayBlocking(CySCB_Type const *base, void *buffer, uint32_t size)
{
uint32_t numCopied;
uint8_t *buf = (uint8_t *) rxBuf;
uint8_t *buf = (uint8_t *) buffer;
bool byteMode = Cy_SCB_IsRxDataWidthByte(base);
/* Get data from RX FIFO. Stop when the requested size is read. */
while (size > 0UL)
{
numCopied = Cy_SCB_ReadArray(base, (void *) buf, size);
buf = &buf[(Cy_SCB_IsRxDataWidthByte(base) ? (numCopied) : (2UL * numCopied))];
buf = &buf[(byteMode ? (numCopied) : (2UL * numCopied))];
size -= numCopied;
}
}
@ -189,7 +190,7 @@ uint32_t Cy_SCB_Write(CySCB_Type *base, uint32_t data)
* \param base
* The pointer to the SCB instance.
*
* \param txBuf
* \param buffer
* The pointer to data to place in the transmit FIFO.
* The item size is defined by the data type which depends on the configured
* TX data width.
@ -201,13 +202,13 @@ uint32_t Cy_SCB_Write(CySCB_Type *base, uint32_t data)
* The number of data elements placed in the transmit FIFO.
*
*******************************************************************************/
void Cy_SCB_WriteArrayNoCheck(CySCB_Type *base, void *txBuf, uint32_t size)
void Cy_SCB_WriteArrayNoCheck(CySCB_Type *base, void *buffer, uint32_t size)
{
uint32_t idx;
if (Cy_SCB_IsTxDataWidthByte(base))
{
uint8_t *buf = (uint8_t *) txBuf;
uint8_t *buf = (uint8_t *) buffer;
/* Put data into TX FIFO */
for (idx = 0UL; idx < size; ++idx)
@ -217,7 +218,7 @@ void Cy_SCB_WriteArrayNoCheck(CySCB_Type *base, void *txBuf, uint32_t size)
}
else
{
uint16_t *buf = (uint16_t *) txBuf;
uint16_t *buf = (uint16_t *) buffer;
/* Put data into TX FIFO */
for (idx = 0UL; idx < size; ++idx)
@ -239,7 +240,7 @@ void Cy_SCB_WriteArrayNoCheck(CySCB_Type *base, void *txBuf, uint32_t size)
* \param base
* The pointer to the SCB instance.
*
* \param txBuf
* \param buffer
* The pointer to data to place in the transmit FIFO.
* The item size is defined by the data type which depends on the configured
* TX data width.
@ -251,7 +252,7 @@ void Cy_SCB_WriteArrayNoCheck(CySCB_Type *base, void *txBuf, uint32_t size)
* The number of data elements placed in the transmit FIFO.
*
*******************************************************************************/
uint32_t Cy_SCB_WriteArray(CySCB_Type *base, void *txBuf, uint32_t size)
uint32_t Cy_SCB_WriteArray(CySCB_Type *base, void *buffer, uint32_t size)
{
/* Get free entries in TX FIFO */
uint32_t numToCopy = Cy_SCB_GetFifoSize(base) - Cy_SCB_GetNumInTxFifo(base);
@ -262,7 +263,7 @@ uint32_t Cy_SCB_WriteArray(CySCB_Type *base, void *txBuf, uint32_t size)
numToCopy = size;
}
Cy_SCB_WriteArrayNoCheck(base, txBuf, numToCopy);
Cy_SCB_WriteArrayNoCheck(base, buffer, numToCopy);
return (numToCopy);
}
@ -279,7 +280,7 @@ uint32_t Cy_SCB_WriteArray(CySCB_Type *base, void *txBuf, uint32_t size)
* \param base
* The pointer to the SCB instance.
*
* \param txBuf
* \param buffer
* The pointer to data to place in transmit FIFO.
* The item size is defined by the data type which depends on the configured
* data width.
@ -288,17 +289,18 @@ uint32_t Cy_SCB_WriteArray(CySCB_Type *base, void *txBuf, uint32_t size)
* The number of data elements to write into the transmit FIFO.
*
*******************************************************************************/
void Cy_SCB_WriteArrayBlocking(CySCB_Type *base, void *txBuf, uint32_t size)
void Cy_SCB_WriteArrayBlocking(CySCB_Type *base, void *buffer, uint32_t size)
{
uint32_t numCopied;
uint8_t *buf = (uint8_t *) txBuf;
uint8_t *buf = (uint8_t *) buffer;
bool byteMode = Cy_SCB_IsTxDataWidthByte(base);
/* Get data from RX FIFO. Stop when the requested size is read. */
while (size > 0UL)
{
numCopied = Cy_SCB_WriteArray(base, (void *) buf, size);
buf = &buf[(Cy_SCB_IsTxDataWidthByte(base) ? (numCopied) : (2UL * numCopied))];
buf = &buf[(byteMode ? (numCopied) : (2UL * numCopied))];
size -= numCopied;
}
}

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* \file cy_scb_common.h
* \version 1.0
* \version 2.0
*
* Provides common API declarations of the SCB driver.
*
@ -57,6 +57,8 @@
* a different pointer to object type.</td>
* <td>The pointer to the buffer memory is void to allow handling of
* different data types: uint8_t (4-8 bits) or uint16_t (9-16 bits).
* The cast operation is safe because the configuration is verified
* before operation is performed.
* </td>
* </tr>
* </table>
@ -65,13 +67,23 @@
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td rowspan="2"> 2.0</td>
* <td>Added parameters validation for public API.
* <td></td>
* </tr>
* <tr>
* <td>Fixed functions which return interrupt status to return only defined
* set of interrupt statuses.</td>
* <td></td>
* </tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td>Initial version.</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_scb_common_macro Macro
* \defgroup group_scb_common_macros Macros
* \defgroup group_scb_common_functions Functions
* \defgroup group_scb_common_data_structures Data Structures
*
@ -85,6 +97,11 @@
#include <stdbool.h>
#include "cy_device_headers.h"
#include "syslib/cy_syslib.h"
#include "syspm/cy_syspm.h"
#ifndef CY_IP_MXSCB
#error "The SCB driver is not supported on this device"
#endif
#if defined(__cplusplus)
extern "C" {
@ -100,13 +117,13 @@ extern "C" {
* \{
*/
__STATIC_INLINE uint32_t Cy_SCB_ReadRxFifo (CySCB_Type const *base);
__STATIC_INLINE void Cy_SCB_SetRxFifoLevel(CySCB_Type *base, uint32_t rxLevel);
__STATIC_INLINE void Cy_SCB_SetRxFifoLevel(CySCB_Type *base, uint32_t level);
__STATIC_INLINE uint32_t Cy_SCB_GetNumInRxFifo(CySCB_Type const *base);
__STATIC_INLINE uint32_t Cy_SCB_GetRxSrValid (CySCB_Type const *base);
__STATIC_INLINE void Cy_SCB_ClearRxFifo (CySCB_Type *base);
__STATIC_INLINE void Cy_SCB_WriteTxFifo (CySCB_Type *base, uint32_t data);
__STATIC_INLINE void Cy_SCB_SetTxFifoLevel(CySCB_Type *base, uint32_t txLevel);
__STATIC_INLINE void Cy_SCB_SetTxFifoLevel(CySCB_Type *base, uint32_t level);
__STATIC_INLINE uint32_t Cy_SCB_GetNumInTxFifo(CySCB_Type const *base);
__STATIC_INLINE uint32_t Cy_SCB_GetTxSrValid (CySCB_Type const *base);
__STATIC_INLINE bool Cy_SCB_IsTxComplete (CySCB_Type const *base);
@ -162,13 +179,13 @@ __STATIC_INLINE void Cy_SCB_ClearSpiInterrupt (CySCB_Type *base, uint32_t
***************************************/
/** \cond INTERNAL */
void Cy_SCB_ReadArrayNoCheck (CySCB_Type const *base, void *rxBuf, uint32_t size);
uint32_t Cy_SCB_ReadArray (CySCB_Type const *base, void *rxBuf, uint32_t size);
void Cy_SCB_ReadArrayBlocking (CySCB_Type const *base, void *rxBuf, uint32_t size);
void Cy_SCB_ReadArrayNoCheck (CySCB_Type const *base, void *buffer, uint32_t size);
uint32_t Cy_SCB_ReadArray (CySCB_Type const *base, void *buffer, uint32_t size);
void Cy_SCB_ReadArrayBlocking (CySCB_Type const *base, void *buffer, uint32_t size);
uint32_t Cy_SCB_Write (CySCB_Type *base, uint32_t data);
void Cy_SCB_WriteArrayNoCheck (CySCB_Type *base, void *txBuf, uint32_t size);
uint32_t Cy_SCB_WriteArray (CySCB_Type *base, void *txBuf, uint32_t size);
void Cy_SCB_WriteArrayBlocking(CySCB_Type *base, void *txBuf, uint32_t size);
void Cy_SCB_WriteArrayNoCheck (CySCB_Type *base, void *buffer, uint32_t size);
uint32_t Cy_SCB_WriteArray (CySCB_Type *base, void *buffer, uint32_t size);
void Cy_SCB_WriteArrayBlocking(CySCB_Type *base, void *buffer, uint32_t size);
void Cy_SCB_WriteString (CySCB_Type *base, char_t const string[]);
void Cy_SCB_WriteDefaultArrayNoCheck(CySCB_Type *base, uint32_t txData, uint32_t size);
uint32_t Cy_SCB_WriteDefaultArray (CySCB_Type *base, uint32_t txData, uint32_t size);
@ -187,21 +204,21 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
***************************************/
/**
* \addtogroup group_scb_common_macro
* \addtogroup group_scb_common_macros
* \{
*/
/** Driver major version */
#define CY_SCB_DRV_VERSION_MAJOR (1)
#define CY_SCB_DRV_VERSION_MAJOR (2)
/** Driver minor version */
#define CY_SCB_DRV_VERSION_MINOR (0)
/** SCB driver identifier */
#define CY_SCB_ID CY_PDL_DRV_ID(0x2AU)
#define CY_SCB_ID CY_PDL_DRV_ID(0x2AU)
/** Position for SCB driver sub mode */
#define CY_SCB_SUB_MODE_Pos (14UL)
#define CY_SCB_SUB_MODE_Pos (13UL)
/** EZI2C mode identifier */
#define CY_SCB_EZI2C_ID (0x0UL << CY_SCB_SUB_MODE_Pos)
@ -216,7 +233,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
#define CY_SCB_UART_ID (0x3UL << CY_SCB_SUB_MODE_Pos)
/**
* \defgroup group_scb_common_macro_intr_cause SCB Interrupt Causes
* \defgroup group_scb_common_macros_intr_cause SCB Interrupt Causes
* \{
*/
/** Interrupt from Master interrupt sources */
@ -236,10 +253,10 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
/** Interrupt from SPI externally clocked interrupt sources */
#define CY_SCB_SPI_INTR SCB_INTR_CAUSE_SPI_EC_Msk
/** \} group_scb_common_macro_intr_cause */
/** \} group_scb_common_macros_intr_cause */
/**
* \defgroup group_scb_common_macro_tx_intr TX Interrupt Statuses
* \defgroup group_scb_common_macros_tx_intr TX Interrupt Statuses
* \{
*/
/**
@ -272,10 +289,10 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
* value on the RX line
*/
#define CY_SCB_TX_INTR_UART_ARB_LOST SCB_INTR_TX_UART_ARB_LOST_Msk
/** \} group_scb_common_macro_tx_intr */
/** \} group_scb_common_macros_tx_intr */
/**
* \defgroup group_scb_common_macro_rx_intr RX Interrupt Statuses
* \defgroup group_scb_common_macros_rx_intr RX Interrupt Statuses
* \{
*/
/**
@ -304,10 +321,10 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
/** A UART break detected */
#define CY_SCB_RX_INTR_UART_BREAK_DETECT SCB_INTR_RX_BREAK_DETECT_Msk
/** \} group_scb_common_macro_rx_intr */
/** \} group_scb_common_macros_rx_intr */
/**
* \defgroup group_scb_common_macro_slave_intr Slave Interrupt Statuses
* \defgroup group_scb_common_macros_slave_intr Slave Interrupt Statuses
* \{
*/
/**
@ -348,10 +365,10 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
* SPI transfer.
*/
#define CY_SCB_SLAVE_INTR_SPI_BUS_ERROR SCB_INTR_S_SPI_BUS_ERROR_Msk
/** \} group_scb_common_macro_slave_intr */
/** \} group_scb_common_macros_slave_intr */
/**
* \defgroup group_scb_common_macro_master_intr Master Interrupt Statuses
* \defgroup group_scb_common_macros_master_intr Master Interrupt Statuses
* \{
*/
/** The I2C master's lost arbitration */
@ -375,10 +392,10 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
* TX FIFO and TX shift register.
*/
#define CY_SCB_MASTER_INTR_SPI_DONE SCB_INTR_M_SPI_DONE_Msk
/** \} group_scb_common_macro_master_intr */
/** \} group_scb_common_macros_master_intr */
/**
* \defgroup group_scb_common_macro_i2c_intr I2C Interrupt Statuses
* \defgroup group_scb_common_macros_i2c_intr I2C Interrupt Statuses
* \{
*/
/**
@ -386,10 +403,10 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
* Note that this interrupt source triggers in active mode.
*/
#define CY_SCB_I2C_INTR_WAKEUP SCB_INTR_I2C_EC_WAKE_UP_Msk
/** \} group_scb_common_macro_i2c_intr */
/** \} group_scb_common_macros_i2c_intr */
/**
* \defgroup group_scb_common_macro_SpiIntrStatuses SPI Interrupt Statuses
* \defgroup group_scb_common_macros_SpiIntrStatuses SPI Interrupt Statuses
* \{
*/
/**
@ -397,7 +414,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
* signal. Note that this interrupt source triggers in active mode.
*/
#define CY_SCB_SPI_INTR_WAKEUP SCB_INTR_SPI_EC_WAKE_UP_Msk
/** \} group_scb_common_macro_SpiIntrStatuses */
/** \} group_scb_common_macros_SpiIntrStatuses */
/***************************************
@ -407,54 +424,127 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxFifoLevel (CySCB_Type const *base);
/** \cond INTERNAL */
/* Default registers values */
#define CY_SCB_CTRL_DEF_VAL (0x0300000FUL)
#define CY_SCB_I2C_CTRL_DEF_VAL (0x00003F88UL)
#define CY_SCB_SPI_CTRL_DEF_VAL (0x03000000UL)
#define CY_SCB_UART_CTRL_DEF_VAL (0x00300000UL)
#define CY_SCB_UART_RX_CTRL_DEF_VAL (0x000A0002UL)
#define CY_SCB_UART_TX_CTRL_DEF_VAL (0x00000002UL)
#define CY_SCB_RX_CTRL_DEF_VAL (0x00000107UL)
#define CY_SCB_TX_CTRL_DEF_VAL (0x00000107UL)
#define CY_SCB_CTRL_DEF_VAL (_VAL2FLD(SCB_CTRL_OVS, 15UL) | \
_VAL2FLD(SCB_CTRL_MODE, 3UL))
#define CY_SCB_I2C_CTRL_DEF_VAL (_VAL2FLD(SCB_I2C_CTRL_HIGH_PHASE_OVS, 8UL) | \
_VAL2FLD(SCB_I2C_CTRL_HIGH_PHASE_OVS, 8UL) | \
_VAL2FLD(SCB_I2C_CTRL_M_READY_DATA_ACK, 1UL) | \
_VAL2FLD(SCB_I2C_CTRL_M_NOT_READY_DATA_NACK, 1UL) | \
_VAL2FLD(SCB_I2C_CTRL_S_GENERAL_IGNORE, 1UL) | \
_VAL2FLD(SCB_I2C_CTRL_S_READY_ADDR_ACK, 1UL) | \
_VAL2FLD(SCB_I2C_CTRL_S_READY_DATA_ACK, 1UL) | \
_VAL2FLD(SCB_I2C_CTRL_S_NOT_READY_ADDR_NACK, 1UL) | \
_VAL2FLD(SCB_I2C_CTRL_S_NOT_READY_DATA_NACK, 1UL))
#define CY_SCB_I2C_CFG_DEF_VAL (_VAL2FLD(SCB_I2C_CFG_SDA_IN_FILT_TRIM, 3UL) | \
_VAL2FLD(SCB_I2C_CFG_SDA_IN_FILT_SEL, 1UL) | \
_VAL2FLD(SCB_I2C_CFG_SCL_IN_FILT_SEL, 1UL) | \
_VAL2FLD(SCB_I2C_CFG_SDA_OUT_FILT0_TRIM, 2UL) | \
_VAL2FLD(SCB_I2C_CFG_SDA_OUT_FILT1_TRIM, 2UL) | \
_VAL2FLD(SCB_I2C_CFG_SDA_OUT_FILT2_TRIM, 2UL))
#define CY_SCB_SPI_CTRL_DEF_VAL _VAL2FLD(SCB_SPI_CTRL_MODE, 3UL)
#define CY_SCB_UART_CTRL_DEF_VAL _VAL2FLD(SCB_UART_CTRL_MODE, 3UL)
#define CY_SCB_UART_RX_CTRL_DEF_VAL (_VAL2FLD(SCB_UART_RX_CTRL_STOP_BITS, 2UL) | \
_VAL2FLD(SCB_UART_RX_CTRL_BREAK_WIDTH, 10UL))
#define CY_SCB_UART_TX_CTRL_DEF_VAL _VAL2FLD(SCB_UART_TX_CTRL_STOP_BITS, 2UL)
#define CY_SCB_RX_CTRL_DEF_VAL (_VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, 7UL) | \
_VAL2FLD(SCB_RX_CTRL_MSB_FIRST, 1UL))
#define CY_SCB_TX_CTRL_DEF_VAL (_VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, 7UL) | \
_VAL2FLD(SCB_TX_CTRL_MSB_FIRST, 1UL))
/* SCB CTRL modes */
#define CY_SCB_CTRL_MODE_I2C (0UL)
#define CY_SCB_CTRL_MODE_SPI (1UL)
#define CY_SCB_CTRL_MODE_UART (2UL)
/* The position and mask to set the I2C mode */
#define CY_SCB_I2C_CTRL_MODE_Pos SCB_I2C_CTRL_SLAVE_MODE_Pos
#define CY_SCB_I2C_CTRL_MODE_Msk (SCB_I2C_CTRL_SLAVE_MODE_Msk | \
SCB_I2C_CTRL_MASTER_MODE_Msk)
/* I2C has fixed data width */
#define CY_SCB_I2C_DATA_WIDTH (7UL)
/* RX and TX control register values */
#define CY_SCB_I2C_RX_CTRL (_VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, CY_SCB_I2C_DATA_WIDTH) | \
SCB_RX_CTRL_MSB_FIRST_Msk)
#define CY_SCB_I2C_TX_CTRL (_VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, CY_SCB_I2C_DATA_WIDTH) | \
SCB_TX_CTRL_MSB_FIRST_Msk | SCB_TX_CTRL_OPEN_DRAIN_Msk)
/* The position and mask to make an address byte */
#define CY_SCB_I2C_ADDRESS_Pos (1UL)
#define CY_SCB_I2C_ADDRESS_Msk (0xFEUL)
/* SPI slave select polarity */
#define CY_SCB_SPI_CTRL_SSEL_POLARITY_Pos SCB_SPI_CTRL_SSEL_POLARITY0_Pos
#define CY_SCB_SPI_CTRL_SSEL_POLARITY_Msk (SCB_SPI_CTRL_SSEL_POLARITY0_Msk | \
SCB_SPI_CTRL_SSEL_POLARITY1_Msk | \
SCB_SPI_CTRL_SSEL_POLARITY2_Msk | \
SCB_SPI_CTRL_SSEL_POLARITY3_Msk)
#define CY_SCB_SPI_CTRL_SSEL_POLARITY_Pos SCB_SPI_CTRL_SSEL_POLARITY0_Pos
#define CY_SCB_SPI_CTRL_SSEL_POLARITY_Msk (SCB_SPI_CTRL_SSEL_POLARITY0_Msk | \
SCB_SPI_CTRL_SSEL_POLARITY1_Msk | \
SCB_SPI_CTRL_SSEL_POLARITY2_Msk | \
SCB_SPI_CTRL_SSEL_POLARITY3_Msk)
/* SPI clock modes: CPHA and CPOL */
#define CY_SCB_SPI_CTRL_CLK_MODE_Pos SCB_SPI_CTRL_CPHA_Pos
#define CY_SCB_SPI_CTRL_CLK_MODE_Msk (SCB_SPI_CTRL_CPHA_Msk | SCB_SPI_CTRL_CPOL_Msk)
/* UART parity and parity enable combination */
#define CY_SCB_UART_RX_CTRL_SET_PARITY_Msk (SCB_UART_RX_CTRL_PARITY_ENABLED_Msk | \
SCB_UART_RX_CTRL_PARITY_Msk)
#define CY_SCB_UART_RX_CTRL_SET_PARITY_Pos (SCB_UART_RX_CTRL_PARITY_Pos)
#define CY_SCB_UART_RX_CTRL_SET_PARITY_Msk (SCB_UART_RX_CTRL_PARITY_ENABLED_Msk | \
SCB_UART_RX_CTRL_PARITY_Msk)
#define CY_SCB_UART_RX_CTRL_SET_PARITY_Pos SCB_UART_RX_CTRL_PARITY_Pos
#define CY_SCB_UART_TX_CTRL_SET_PARITY_Msk (SCB_UART_TX_CTRL_PARITY_ENABLED_Msk | \
SCB_UART_TX_CTRL_PARITY_Msk)
#define CY_SCB_UART_TX_CTRL_SET_PARITY_Pos (SCB_UART_TX_CTRL_PARITY_Pos)
#define CY_SCB_UART_TX_CTRL_SET_PARITY_Msk (SCB_UART_TX_CTRL_PARITY_ENABLED_Msk | \
SCB_UART_TX_CTRL_PARITY_Msk)
#define CY_SCB_UART_TX_CTRL_SET_PARITY_Pos SCB_UART_TX_CTRL_PARITY_Pos
/* Max number of bits for byte mode */
#define CY_SCB_BYTE_WIDTH (8UL)
#define CY_SCB_BYTE_WIDTH (8UL)
/* Single unit to wait */
#define CY_SCB_WAIT_1_UNIT (1U)
#define CY_SCB_WAIT_1_UNIT (1U)
/* Clear interrupt sources */
#define CY_SCB_CLEAR_ALL_INTR_SRC (0UL)
#define CY_SCB_CLEAR_ALL_INTR_SRC (0UL)
/* Hardware FIFO size */
#define CY_SCB_FIFO_SIZE (128UL)
#define CY_SCB_FIFO_SIZE(base) (SCB_GET_EZ_DATA_NR(base) / 2UL)
/* Provides a list of allowed sources */
#define CY_SCB_TX_INTR_MASK (CY_SCB_TX_INTR_LEVEL | CY_SCB_TX_INTR_NOT_FULL | CY_SCB_TX_INTR_EMPTY | \
CY_SCB_TX_INTR_OVERFLOW | CY_SCB_TX_INTR_UNDERFLOW | CY_SCB_TX_INTR_UART_DONE | \
CY_SCB_TX_INTR_UART_NACK | CY_SCB_TX_INTR_UART_ARB_LOST)
#define CY_SCB_RX_INTR_MASK (CY_SCB_RX_INTR_LEVEL | CY_SCB_RX_INTR_NOT_EMPTY | CY_SCB_RX_INTR_FULL | \
CY_SCB_RX_INTR_OVERFLOW | CY_SCB_RX_INTR_UNDERFLOW | \
CY_SCB_RX_INTR_UART_FRAME_ERROR | CY_SCB_RX_INTR_UART_PARITY_ERROR | \
CY_SCB_RX_INTR_UART_BREAK_DETECT)
#define CY_SCB_SLAVE_INTR_MASK (CY_SCB_SLAVE_INTR_I2C_ARB_LOST | CY_SCB_SLAVE_INTR_I2C_NACK | CY_SCB_SLAVE_INTR_I2C_ACK | \
CY_SCB_SLAVE_INTR_I2C_WRITE_STOP | CY_SCB_SLAVE_INTR_I2C_STOP | CY_SCB_SLAVE_INTR_I2C_START | \
CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH | CY_SCB_SLAVE_INTR_I2C_GENERAL_ADDR | \
CY_SCB_SLAVE_INTR_I2C_BUS_ERROR | CY_SCB_SLAVE_INTR_SPI_BUS_ERROR)
#define CY_SCB_MASTER_INTR_MASK (CY_SCB_MASTER_INTR_I2C_ARB_LOST | CY_SCB_MASTER_INTR_I2C_NACK | \
CY_SCB_MASTER_INTR_I2C_ACK | CY_SCB_MASTER_INTR_I2C_STOP | \
CY_SCB_MASTER_INTR_I2C_BUS_ERROR | CY_SCB_MASTER_INTR_SPI_DONE)
#define CY_SCB_I2C_INTR_MASK CY_SCB_I2C_INTR_WAKEUP
#define CY_SCB_SPI_INTR_MASK CY_SCB_SPI_INTR_WAKEUP
#define CY_SCB_IS_INTR_VALID(intr, mask) ( 0UL == ((intr) & ((uint32_t) ~(mask))) )
#define CY_SCB_IS_TRIGGER_LEVEL_VALID(base, level) ((level) < Cy_SCB_GetFifoSize(base))
#define CY_SCB_IS_I2C_ADDR_VALID(addr) ( (0U == ((addr) & 0x80U)) )
#define CY_SCB_IS_BUFFER_VALID(buffer, size) ( (NULL != (buffer)) && ((size) > 0UL) )
#define CY_SCB_IS_I2C_BUFFER_VALID(buffer, size) ( (0UL == (size)) ? true : (NULL != (buffer)) )
/** \endcond */
/** \} group_scb_common_macro */
/** \} group_scb_common_macros */
/***************************************
@ -495,14 +585,16 @@ __STATIC_INLINE uint32_t Cy_SCB_ReadRxFifo(CySCB_Type const *base)
* \param base
* The pointer to the SCB instance.
*
* \param rxLevel
* \param level
* When there are more data elements in the FIFO than this level, the RX level
* interrupt is triggered.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetRxFifoLevel(CySCB_Type *base, uint32_t rxLevel)
__STATIC_INLINE void Cy_SCB_SetRxFifoLevel(CySCB_Type *base, uint32_t level)
{
base->RX_FIFO_CTRL = _CLR_SET_FLD32U(base->RX_FIFO_CTRL, SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, rxLevel);
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, level));
base->RX_FIFO_CTRL = _CLR_SET_FLD32U(base->RX_FIFO_CTRL, SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, level);
}
@ -597,14 +689,16 @@ __STATIC_INLINE void Cy_SCB_WriteTxFifo(CySCB_Type* base, uint32_t data)
* \param base
* The pointer to the SCB instance.
*
* \param txLevel
* \param level
* When there are fewer data elements in the FIFO than this level, the TX level
* interrupt is triggered.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetTxFifoLevel(CySCB_Type *base, uint32_t txLevel)
__STATIC_INLINE void Cy_SCB_SetTxFifoLevel(CySCB_Type *base, uint32_t level)
{
base->TX_FIFO_CTRL = _CLR_SET_FLD32U(base->TX_FIFO_CTRL, SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, txLevel);
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, level));
base->TX_FIFO_CTRL = _CLR_SET_FLD32U(base->TX_FIFO_CTRL, SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, level);
}
@ -731,7 +825,7 @@ __STATIC_INLINE void Cy_SCB_SetByteMode(CySCB_Type *base, bool byteMode)
*
* \return
* The mask with the OR of the following conditions that have been triggered.
* See \ref group_scb_common_macro_intr_cause for the set of constants.
* See \ref group_scb_common_macros_intr_cause for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetInterruptCause(CySCB_Type const *base)
@ -754,12 +848,12 @@ __STATIC_INLINE uint32_t Cy_SCB_GetInterruptCause(CySCB_Type const *base)
* The current status of the RX interrupt sources. Each constant is a bit field
* value. The value returned may have multiple bits set to indicate the
* current status.
* See \ref group_scb_common_macro_rx_intr for the set of constants.
* See \ref group_scb_common_macros_rx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptStatus(CySCB_Type const *base)
{
return (base->INTR_RX);
return (base->INTR_RX & CY_SCB_RX_INTR_MASK);
}
@ -775,11 +869,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptStatus(CySCB_Type const *base)
*
* \param interruptMask
* Enabled RX interrupt sources.
* See \ref group_scb_common_macro_rx_intr.
* See \ref group_scb_common_macros_rx_intr.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetRxInterruptMask(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_RX_INTR_MASK));
base->INTR_RX_MASK = interruptMask;
}
@ -796,7 +892,7 @@ __STATIC_INLINE void Cy_SCB_SetRxInterruptMask(CySCB_Type *base, uint32_t interr
*
* \return
* Enabled RX interrupt sources.
* See \ref group_scb_common_macro_rx_intr for the set of constants.
* See \ref group_scb_common_macros_rx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptMask(CySCB_Type const *base)
@ -820,7 +916,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptMask(CySCB_Type const *base)
*
* \return
* The current status of enabled RX interrupt sources.
* See \ref group_scb_common_macro_rx_intr for the set of constants.
* See \ref group_scb_common_macros_rx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptStatusMasked(CySCB_Type const *base)
@ -840,7 +936,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptStatusMasked(CySCB_Type const *bas
*
* \param interruptMask
* The RX interrupt sources to be cleared.
* See \ref group_scb_common_macro_rx_intr for the set of constants.
* See \ref group_scb_common_macros_rx_intr for the set of constants.
*
* \note
* - CY_SCB_INTR_RX_FIFO_LEVEL interrupt source is not cleared when
@ -853,6 +949,8 @@ __STATIC_INLINE uint32_t Cy_SCB_GetRxInterruptStatusMasked(CySCB_Type const *bas
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_ClearRxInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_RX_INTR_MASK));
base->INTR_RX = interruptMask;
(void) base->INTR_RX;
}
@ -869,11 +967,13 @@ __STATIC_INLINE void Cy_SCB_ClearRxInterrupt(CySCB_Type *base, uint32_t interrup
*
* \param interruptMask
* The RX interrupt sources to set in the RX interrupt request register.
* See \ref group_scb_common_macro_rx_intr for the set of constants.
* See \ref group_scb_common_macros_rx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetRxInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_RX_INTR_MASK));
base->INTR_RX_SET = interruptMask;
}
@ -892,12 +992,12 @@ __STATIC_INLINE void Cy_SCB_SetRxInterrupt(CySCB_Type *base, uint32_t interruptM
* The current status of TX interrupt sources.
* Each constant is a bit field value. The value returned may have multiple
* bits set to indicate the current status.
* See \ref group_scb_common_macro_tx_intr for the set of constants.
* See \ref group_scb_common_macros_tx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptStatus(CySCB_Type const *base)
{
return (base->INTR_TX);
return (base->INTR_TX & CY_SCB_TX_INTR_MASK);
}
@ -913,11 +1013,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptStatus(CySCB_Type const *base)
*
* \param interruptMask
* Enabled TX interrupt sources.
* See \ref group_scb_common_macro_tx_intr for the set of constants.
* See \ref group_scb_common_macros_tx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetTxInterruptMask(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_TX_INTR_MASK));
base->INTR_TX_MASK = interruptMask;
}
@ -934,7 +1036,7 @@ __STATIC_INLINE void Cy_SCB_SetTxInterruptMask(CySCB_Type *base, uint32_t interr
*
* \return
* Enabled TX interrupt sources.
* See \ref group_scb_common_macro_tx_intr for the set of constants.
* See \ref group_scb_common_macros_tx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptMask(CySCB_Type const *base)
@ -958,7 +1060,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptMask(CySCB_Type const *base)
*
* \return
* The current status of enabled TX interrupt sources.
* See \ref group_scb_common_macro_tx_intr for the set of constants.
* See \ref group_scb_common_macros_tx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptStatusMasked(CySCB_Type const *base)
@ -978,14 +1080,14 @@ __STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptStatusMasked(CySCB_Type const *bas
*
* \param interruptMask
* The TX interrupt sources to be cleared.
* See \ref group_scb_common_macro_tx_intr for the set of constants.
* See \ref group_scb_common_macros_tx_intr for the set of constants.
*
* \note
* - CY_SCB_INTR_TX_FIFO_LEVEL interrupt source is not cleared when the
* TX FIFO has less entries than the TX level.
* - CY_SCB_INTR_TX_NOT_FULL interrupt source is not cleared when the
* TX FIFO has empty entries in the TX FIFO.
* - CY_SCB_INTR_TX_EMPTY nterrupt source is not cleared when the
* - CY_SCB_INTR_TX_EMPTY interrupt source is not cleared when the
* TX FIFO is empty.
* - CY_SCB_INTR_TX_UNDERFLOW interrupt source is not cleared when the
* TX FIFO is empty. Put data into the TX FIFO before clearing it.
@ -993,6 +1095,8 @@ __STATIC_INLINE uint32_t Cy_SCB_GetTxInterruptStatusMasked(CySCB_Type const *bas
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_ClearTxInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_TX_INTR_MASK));
base->INTR_TX = interruptMask;
(void) base->INTR_TX;
}
@ -1009,11 +1113,13 @@ __STATIC_INLINE void Cy_SCB_ClearTxInterrupt(CySCB_Type *base, uint32_t interrup
*
* \param interruptMask
* The TX interrupt sources to set in the TX interrupt request register.
* See \ref group_scb_common_macro_tx_intr for the set of constants.
* See \ref group_scb_common_macros_tx_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetTxInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_TX_INTR_MASK));
base->INTR_TX_SET = interruptMask;
}
@ -1032,12 +1138,12 @@ __STATIC_INLINE void Cy_SCB_SetTxInterrupt(CySCB_Type *base, uint32_t interruptM
* The current status of the master interrupt sources.
* Each constant is a bit field value. The value returned may have multiple
* bits set to indicate the current status.
* See \ref group_scb_common_macro_master_intr for the set of constants.
* See \ref group_scb_common_macros_master_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptStatus (CySCB_Type const *base)
__STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptStatus(CySCB_Type const *base)
{
return (base->INTR_M);
return (base->INTR_M & CY_SCB_MASTER_INTR_MASK);
}
@ -1053,11 +1159,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptStatus (CySCB_Type const *base
*
* \param interruptMask
* The master interrupt sources to be enable.
* See \ref group_scb_common_macro_master_intr for the set of constants.
* See \ref group_scb_common_macros_master_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetMasterInterruptMask(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_MASTER_INTR_MASK));
base->INTR_M_MASK = interruptMask;
}
@ -1074,7 +1182,7 @@ __STATIC_INLINE void Cy_SCB_SetMasterInterruptMask(CySCB_Type *base, uint32_t in
*
* \return
* Enabled master interrupt sources.
* See \ref group_scb_common_macro_master_intr for the set of constants.
* See \ref group_scb_common_macros_master_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptMask(CySCB_Type const *base)
@ -1099,7 +1207,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptMask(CySCB_Type const *base)
*
* \return
* The current status of enabled master interrupt sources.
* See \ref group_scb_common_macro_master_intr for the set of constants.
* See \ref group_scb_common_macros_master_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptStatusMasked(CySCB_Type const *base)
@ -1119,11 +1227,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetMasterInterruptStatusMasked(CySCB_Type const
*
* \param interruptMask
* The master interrupt sources to be cleared.
* See \ref group_scb_common_macro_master_intr for the set of constants.
* See \ref group_scb_common_macros_master_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_ClearMasterInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_MASTER_INTR_MASK));
base->INTR_M = interruptMask;
(void) base->INTR_M;
}
@ -1140,11 +1250,13 @@ __STATIC_INLINE void Cy_SCB_ClearMasterInterrupt(CySCB_Type *base, uint32_t inte
*
* \param interruptMask
* The master interrupt sources to set in the master interrupt request register.
* See \ref group_scb_common_macro_master_intr for the set of constants.
* See \ref group_scb_common_macros_master_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetMasterInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_MASTER_INTR_MASK));
base->INTR_M_SET = interruptMask;
}
@ -1163,12 +1275,12 @@ __STATIC_INLINE void Cy_SCB_SetMasterInterrupt(CySCB_Type *base, uint32_t interr
* The current status of the slave interrupt sources.
* Each constant is a bit field value. The value returned may have multiple
* bits set to indicate the current status.
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetSlaveInterruptStatus(CySCB_Type const *base)
{
return (base->INTR_S);
return (base->INTR_S & CY_SCB_SLAVE_INTR_MASK);
}
@ -1185,11 +1297,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetSlaveInterruptStatus(CySCB_Type const *base)
*
* \param interruptMask
* Enabled slave interrupt sources.
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetSlaveInterruptMask(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_SLAVE_INTR_MASK));
base->INTR_S_MASK = interruptMask;
}
@ -1207,7 +1321,7 @@ __STATIC_INLINE void Cy_SCB_SetSlaveInterruptMask(CySCB_Type *base, uint32_t int
*
* \return
* Enabled slave interrupt sources.
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetSlaveInterruptMask(CySCB_Type const *base)
@ -1232,7 +1346,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetSlaveInterruptMask(CySCB_Type const *base)
*
* \return
* The current status of enabled slave interrupt sources.
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetSlaveInterruptStatusMasked(CySCB_Type const *base)
@ -1252,11 +1366,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetSlaveInterruptStatusMasked(CySCB_Type const *
*
* \param interruptMask
* Slave interrupt sources to be cleared.
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_ClearSlaveInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_SLAVE_INTR_MASK));
base->INTR_S = interruptMask;
(void) base->INTR_S;
}
@ -1273,11 +1389,13 @@ __STATIC_INLINE void Cy_SCB_ClearSlaveInterrupt(CySCB_Type *base, uint32_t inter
*
* \param interruptMask
* The slave interrupt sources to set in the slave interrupt request register
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetSlaveInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_SLAVE_INTR_MASK));
base->INTR_S_SET = interruptMask;
}
@ -1296,12 +1414,12 @@ __STATIC_INLINE void Cy_SCB_SetSlaveInterrupt(CySCB_Type *base, uint32_t interru
* The current status of the I2C interrupt sources. Each constant is a bit
* field value.
* The value returned may have multiple bits set to indicate the current status.
* See \ref group_scb_common_macro_slave_intr for the set of constants.
* See \ref group_scb_common_macros_slave_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetI2CInterruptStatus(CySCB_Type const *base)
{
return (base->INTR_I2C_EC);
return (base->INTR_I2C_EC & CY_SCB_I2C_INTR_MASK);
}
@ -1317,11 +1435,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetI2CInterruptStatus(CySCB_Type const *base)
*
* \param interruptMask
* Enabled I2C interrupt sources.
* See \ref group_scb_common_macro_i2c_intr for the set of constants.
* See \ref group_scb_common_macros_i2c_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetI2CInterruptMask(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_I2C_INTR_MASK));
base->INTR_I2C_EC_MASK = interruptMask;
}
@ -1338,7 +1458,7 @@ __STATIC_INLINE void Cy_SCB_SetI2CInterruptMask(CySCB_Type *base, uint32_t inter
*
* \return
* Enabled I2C interrupt sources.
* See \ref group_scb_common_macro_i2c_intr.
* See \ref group_scb_common_macros_i2c_intr.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetI2CInterruptMask(CySCB_Type const *base)
@ -1362,7 +1482,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetI2CInterruptMask(CySCB_Type const *base)
*
* \return
* The current status of enabled I2C interrupt sources.
* See \ref group_scb_common_macro_i2c_intr for the set of constants.
* See \ref group_scb_common_macros_i2c_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetI2CInterruptStatusMasked(CySCB_Type const *base)
@ -1382,11 +1502,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetI2CInterruptStatusMasked(CySCB_Type const *ba
*
* \param interruptMask
* The I2C interrupt sources to be cleared.
* See \ref group_scb_common_macro_i2c_intr for the set of constants.
* See \ref group_scb_common_macros_i2c_intr for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_ClearI2CInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_I2C_INTR_MASK));
base->INTR_I2C_EC = interruptMask;
(void) base->INTR_I2C_EC;
}
@ -1405,12 +1527,12 @@ __STATIC_INLINE void Cy_SCB_ClearI2CInterrupt(CySCB_Type *base, uint32_t interru
* \return
* The current status of SPI interrupt sources. Each constant is a bit field value.
* The value returned may have multiple bits set to indicate the current status
* See \ref group_scb_common_macro_SpiIntrStatuses for the set of constants.
* See \ref group_scb_common_macros_SpiIntrStatuses for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetSpiInterruptStatus(CySCB_Type const *base)
{
return (base->INTR_SPI_EC);
return (base->INTR_SPI_EC & CY_SCB_SPI_INTR_MASK);
}
@ -1426,11 +1548,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetSpiInterruptStatus(CySCB_Type const *base)
*
* \param interruptMask
* Enabled SPI interrupt sources.
* See \ref group_scb_common_macro_SpiIntrStatuses for the set of constants.
* See \ref group_scb_common_macros_SpiIntrStatuses for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_SetSpiInterruptMask(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_SPI_INTR_MASK));
base->INTR_SPI_EC_MASK = interruptMask;
}
@ -1447,7 +1571,7 @@ __STATIC_INLINE void Cy_SCB_SetSpiInterruptMask(CySCB_Type *base, uint32_t inter
*
* \return
* Enabled SPI interrupt sources.
* See \ref group_scb_common_macro_SpiIntrStatuses for the set of constants.
* See \ref group_scb_common_macros_SpiIntrStatuses for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetSpiInterruptMask(CySCB_Type const *base)
@ -1471,7 +1595,7 @@ __STATIC_INLINE uint32_t Cy_SCB_GetSpiInterruptMask(CySCB_Type const *base)
*
* \return
* The current status of enabled SPI interrupt sources.
* See \ref group_scb_common_macro_SpiIntrStatuses for the set of constants.
* See \ref group_scb_common_macros_SpiIntrStatuses for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetSpiInterruptStatusMasked(CySCB_Type const *base)
@ -1491,11 +1615,13 @@ __STATIC_INLINE uint32_t Cy_SCB_GetSpiInterruptStatusMasked(CySCB_Type const *ba
*
* \param interruptMask
* The SPI interrupt sources to be cleared.
* See \ref group_scb_common_macro_SpiIntrStatuses for the set of constants.
* See \ref group_scb_common_macros_SpiIntrStatuses for the set of constants.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_ClearSpiInterrupt(CySCB_Type *base, uint32_t interruptMask)
{
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(interruptMask, CY_SCB_SPI_INTR_MASK));
base->INTR_SPI_EC = interruptMask;
(void) base->INTR_SPI_EC;
}
@ -1516,8 +1642,8 @@ __STATIC_INLINE void Cy_SCB_ClearSpiInterrupt(CySCB_Type *base, uint32_t interru
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SCB_GetFifoSize(CySCB_Type const *base)
{
return ((0UL != (SCB_CTRL_BYTE_MODE_Msk & base->CTRL)) ?
(CY_SCB_FIFO_SIZE) : (CY_SCB_FIFO_SIZE / 2UL));
return (_FLD2BOOL(SCB_CTRL_BYTE_MODE, base->CTRL) ?
(CY_SCB_FIFO_SIZE(base)) : (CY_SCB_FIFO_SIZE(base) / 2UL));
}
@ -1550,7 +1676,7 @@ __STATIC_INLINE bool Cy_SCB_IsRxDataWidthByte(CySCB_Type const *base)
* The pointer to the SCB instance.
*
* \return
* If ture, the TX data width is a byte (8 bits). Othewise, false.
* If ture, the TX data width is a byte (8 bits). Otherwise, false.
*
*******************************************************************************/
__STATIC_INLINE bool Cy_SCB_IsTxDataWidthByte(CySCB_Type const *base)

View File

@ -0,0 +1,491 @@
/***************************************************************************//**
* \file cy_scb_ezi2c.h
* \version 2.0
*
* Provides EZI2C API declarations of the SCB driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \addtogroup group_scb_ezi2c
* \{
* Driver API for EZI2C slave Peripheral
*
* I2C - The Inter-Integrated Circuit (I2C) bus is an industry-standard.
* The two-wire hardware interface was developed by Philips Semiconductors
* (now NXP Semiconductors).
*
* The EZI2C slave peripheral driver provides an API to implement the I2C slave
* device based on the SCB hardware block. This slave device emulates a common
* I2C EEPROM interface that acts like dual-port memory between the external
* master and your code. I2C devices based on the SCB hardware are compatible
* with the I2C Standard mode, Fast mode, and Fast mode Plus specifications as
* defined in the I2C bus specification.
*
* Features:
* * An industry-standard I2C bus interface
* * Supports standard data rates of 100/400/1000 kbps
* * Emulates a common I2C EEPROM Interface
* * Acts like dual-port memory between the external master and your code
* * Supports Hardware Address Match
* * Supports two hardware addresses with separate buffers
* * Supports Wake from Deep Sleep on address match
* * Simple to set up and use, does not require calling EZI2C API
* at run time.
*
* \section group_scb_ezi2c_configuration Configuration Considerations
*
* To set up the EZI2C slave driver, provide the configuration parameters in the
* \ref cy_stc_scb_ezi2c_config_t structure. For the slave, the primary slave
* address slaveAddress1 must be provided. The other parameters are optional
* for operation.
* To get EZI2C slave operate with desired data rate the SCB clock frequency
* must be configured. Use the SysClk driver API to do that. Refer to the
* technical reference manual (TRM) to get information how to select SCB
* frequency in I2C mode to support desired data rate.
* To initialize the driver, call the \ref Cy_SCB_EZI2C_Init function providing
* a pointer to the filled \ref cy_stc_scb_ezi2c_config_t structure and
* allocated \ref cy_stc_scb_ezi2c_context_t. The \ref Cy_SCB_EZI2C_Interrupt
* function must be called in the interrupt handler for the selected
* SCB instance and this interrupt must be enabled in the NVIC. Set up the
* EZI2C slave buffers before calling \ref Cy_SCB_EZI2C_Enable using
* \ref Cy_SCB_EZI2C_SetBuffer1 for the primary slave address and
* \ref Cy_SCB_EZI2C_SetBuffer2 for the secondary if it is enabled. Finally,
* enable the EZI2C slave operation calling \ref Cy_SCB_EZI2C_Enable.
*
* The following operation might not require calling any EZI2C slave function
* because the I2C master is able to access the slave buffer and the application
* can directly access it as well. Note that this is an application level task
* to ensure the buffer content integrity.
*
* The master can access the buffer:
* * Master Write operation starts with sending a base address which is 1
* or 2 bytes depending on the sub-address size configuration. This base
* address is retained and will be used for later read operations. Following
* the base address, there is a sequence of bytes written into the buffer
* starting from the base address location. The buffer index is incremented
* for each written byte, but this does not affect the base address which is
* retained. The length of a write operation is limited by the maximum buffer
* read/write region size.\n
* When a master attempts to write outside the read/write region or past the
* end of the buffer, the last byte is NACKed.
* * Master Read operation always starts from the base address set by the most
* recent Write operation. The buffer index is incremented for each read byte.
* Two sequential read operations start from the same base address no matter
* how many bytes were read. The length of a read operation is not limited by
* the maximum size of the data buffer. The EZI2C slave returns 0xFF bytes
* if the read operation passes the end of the buffer.\n
* Typically, a read operation requires the base address to be updated before
* starting the read. In this case, the write and read operations must be
* combined together. The I2C master may use the ReStart or Stop/Start
* conditions to combine the operations. The write operation sets only the
* base address and the following read operation will start from the new base
* address. In cases where the base address remains the same, there is no need
* for a write operation.
*
* The EZI2C driver provides the callback functions to facilitate the low-power
* mode transition. The callback \ref Cy_SCB_EZI2C_DeepSleepCallback can be called
* during execution of \ref Cy_SysPm_DeepSleep; \ref Cy_SCB_EZI2C_HibernateCallback
* can be called during execution of \ref Cy_SysPm_Hibernate. To trigger the
* callback execution, the callback must be registered before calling the
* mode transition function. Refer to SysPm driver for more information about
* low-power mode transitions.
*
* \section group_scb_ezi2c_more_information More Information
*
* For more information on the SCB peripheral, refer to the technical reference
* manual (TRM).
*
* \section group_scb_ezi2c_MISRA MISRA-C Compliance
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required / Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>11.4</td>
* <td>A</td>
* <td>A cast should not be performed between a pointer to object type and
* a different pointer to object type.</td>
* <td>The functions \ref Cy_SCB_EZI2C_DeepSleepCallback and
* \ref Cy_SCB_EZI2C_HibernateCallback are callback of
* \ref cy_en_syspm_status_t type. The cast operation safety in these
* functions becomes the user's responsibility because pointers are
* initialized when callback is registered in SysPm driver.</td>
* </tr>
* <tr>
* <td>14.1</td>
* <td>R</td>
* <td>There shall be no unreachable code.</td>
* <td>The SCB block parameters can be a constant false or true depends on
* the selected device and cause code to be unreachable.</td>
* </tr>
* <tr>
* <td>14.2</td>
* <td>R</td>
* <td>All non-null statements shall either: a) have at least one side-effect
* however executed, or b) cause control flow to change.</td>
* <td>The unused function parameters are cast to void. This statement
* has no side-effect and is used to suppress a compiler warning.</td>
* </tr>
* <tr>
* <td>14.7</td>
* <td>R</td>
* <td>A function shall have a single point of exit at the end of the
* function.</td>
* <td>The functions can return from several points. This is done to improve
* code clarity when returning error status code if input parameters
* validation is failed.</td>
* </tr>
* </table>
*
* \section group_scb_ezi2c_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td rowspan="2"> 2.0</td>
* <td>Added parameters validation for public API.</td>
* <td></td>
* </tr>
* <tr>
* <td>Replaced variables which have limited range of values with enumerated
* types.</td>
* <td></td>
* </tr>
* <tr>
* <td>1.0</td>
* <td>Initial version.</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_scb_ezi2c_macros Macros
* \defgroup group_scb_ezi2c_functions Functions
* \{
* \defgroup group_scb_ezi2c_general_functions General
* \defgroup group_scb_ezi2c_slave_functions Slave
* \defgroup group_scb_ezi2c_low_power_functions Low Power Callbacks
* \}
* \defgroup group_scb_ezi2c_data_structures Data Structures
* \defgroup group_scb_ezi2c_enums Enumerated Types
*/
#if !defined(CY_SCB_EZI2C_H)
#define CY_SCB_EZI2C_H
#include "cy_scb_common.h"
#if defined(__cplusplus)
extern "C" {
#endif
/***************************************
* Enumerated Types
***************************************/
/**
* \addtogroup group_scb_ezi2c_enums
* \{
*/
/** EZI2C slave status codes */
typedef enum
{
/** Operation completed successfully */
CY_SCB_EZI2C_SUCCESS = 0U,
/** One or more of input parameters are invalid */
CY_SCB_EZI2C_BAD_PARAM = (CY_SCB_ID | CY_PDL_STATUS_ERROR | CY_SCB_EZI2C_ID | 1U),
} cy_en_scb_ezi2c_status_t;
/** Number of Addresses */
typedef enum
{
CY_SCB_EZI2C_ONE_ADDRESS, /**< Only one address */
CY_SCB_EZI2C_TWO_ADDRESSES /**< Two addresses */
} cy_en_scb_ezi2c_num_of_addr_t;
/** Size of Sub-Address */
typedef enum
{
CY_SCB_EZI2C_SUB_ADDR8_BITS, /**< Sub-address is 8 bits */
CY_SCB_EZI2C_SUB_ADDR16_BITS /**< Sub-address is 16 bits */
} cy_en_scb_ezi2c_sub_addr_size_t;
/** \cond INTERNAL */
/** EZI2C slave FSM states */
typedef enum
{
CY_SCB_EZI2C_STATE_IDLE,
CY_SCB_EZI2C_STATE_RX_OFFSET_MSB,
CY_SCB_EZI2C_STATE_RX_OFFSET_LSB,
CY_SCB_EZI2C_STATE_RX_DATA0,
CY_SCB_EZI2C_STATE_RX_DATA1,
CY_SCB_EZI2C_STATE_TX_DATA
} cy_en_scb_ezi2c_state_t;
/** \endcond */
/** \} group_scb_ezi2c_enums */
/***************************************
* Type Definitions
***************************************/
/**
* \addtogroup group_scb_ezi2c_data_structures
* \{
*/
/** EZI2C slave configuration structure */
typedef struct cy_stc_scb_ezi2c_config
{
/** The number of supported addresses either */
cy_en_scb_ezi2c_num_of_addr_t numberOfAddresses;
/** The 7-bit right justified primary slave address */
uint8_t slaveAddress1;
/** The 7-bit right justified secondary slave address */
uint8_t slaveAddress2;
/** The size of the sub-address, can either be 8 or 16 bits */
cy_en_scb_ezi2c_sub_addr_size_t subAddressSize;
/**
* When set, the slave will wake the device from deep sleep on an address
* match (The device datasheet must be consulted to determine which SCBs
* support this mode)
*/
bool enableWakeFromSleep;
} cy_stc_scb_ezi2c_config_t;
/** EZI2C slave context structure.
* All fields for the context structure are internal. Firmware never reads or
* writes these values. Firmware allocates the structure and provides the
* address of the structure to the driver in function calls. Firmware must
* ensure that the defined instance of this structure remains in scope while
* while the drive is in use.
*/
typedef struct cy_stc_scb_ezi2c_context
{
/** \cond INTERNAL */
volatile cy_en_scb_ezi2c_state_t state; /**< The driver state */
volatile uint32_t status; /**< The slave status */
uint8_t address1; /**< The primary slave address (7-bits right justified) */
uint8_t address2; /**< The secondary slave address (7-bits right justified) */
cy_en_scb_ezi2c_sub_addr_size_t subAddrSize; /**< The sub-address size */
uint32_t idx; /**< The index within the buffer during operation */
uint32_t baseAddr1; /**< The valid base address for the primary slave address */
uint32_t baseAddr2; /**< The valid base address for the secondary slave address */
bool addr1Active; /**< Defines whether the request is intended for the primary slave address */
uint8_t *curBuf; /**< The pointer to the current location in the buffer (while it is accessed) */
uint32_t bufSize; /**< Specifies how many bytes are left in the current buffer */
uint8_t *buf1; /**< The pointer to the buffer exposed on the request intended for the primary slave address */
uint32_t buf1Size; /**< The buffer size assigned to the primary slave address */
uint32_t buf1rwBondary; /**< The Read/Write boundary within the buffer assigned to the primary slave address */
uint8_t *buf2; /**< The pointer to the buffer exposed on the request intended for the secondary slave address */
uint32_t buf2Size; /**< The buffer size assigned to the secondary slave address */
uint32_t buf2rwBondary; /**< The Read/Write boundary within the buffer assigned for the secondary slave address */
/** \endcond */
} cy_stc_scb_ezi2c_context_t;
/** \} group_scb_ezi2c_data_structures */
/***************************************
* Function Prototypes
***************************************/
/**
* \addtogroup group_scb_ezi2c_general_functions
* \{
*/
cy_en_scb_ezi2c_status_t Cy_SCB_EZI2C_Init(CySCB_Type *base, cy_stc_scb_ezi2c_config_t const *config,
cy_stc_scb_ezi2c_context_t *context);
void Cy_SCB_EZI2C_DeInit(CySCB_Type *base);
__STATIC_INLINE void Cy_SCB_EZI2C_Enable(CySCB_Type *base);
void Cy_SCB_EZI2C_Disable(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
void Cy_SCB_EZI2C_SetAddress1(CySCB_Type *base, uint8_t addr, cy_stc_scb_ezi2c_context_t *context);
uint32_t Cy_SCB_EZI2C_GetAddress1(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t const *context);
void Cy_SCB_EZI2C_SetAddress2(CySCB_Type *base, uint8_t addr, cy_stc_scb_ezi2c_context_t *context);
uint32_t Cy_SCB_EZI2C_GetAddress2(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t const *context);
/** \} group_scb_ezi2c_general_functions */
/**
* \addtogroup group_scb_ezi2c_slave_functions
* \{
*/
void Cy_SCB_EZI2C_SetBuffer1(CySCB_Type const *base, uint8_t *buffer, uint32_t size, uint32_t rwBoundary,
cy_stc_scb_ezi2c_context_t *context);
void Cy_SCB_EZI2C_SetBuffer2(CySCB_Type const *base, uint8_t *buffer, uint32_t size, uint32_t rwBoundary,
cy_stc_scb_ezi2c_context_t *context);
uint32_t Cy_SCB_EZI2C_GetActivity(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t *context);
void Cy_SCB_EZI2C_Interrupt(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
/** \} group_scb_ezi2c_slave_functions */
/**
* \addtogroup group_scb_ezi2c_low_power_functions
* \{
*/
cy_en_syspm_status_t Cy_SCB_EZI2C_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams);
cy_en_syspm_status_t Cy_SCB_EZI2C_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams);
/** \} group_scb_ezi2c_low_power_functions */
/***************************************
* API Constants
***************************************/
/**
* \addtogroup group_scb_ezi2c_macros
* \{
*/
/**
* \defgroup group_scb_ezi2c_macros_get_activity EZI2C Activity Status
* Each EZI2C slave status is encoded in a separate bit, therefore multiple bits
* may be set to indicate the current status.
* \{
*/
/**
* The Read transfer intended for the primary slave address is complete.
* The error condition status bit must be checked to ensure that the Read
* transfer was completed successfully.
*/
#define CY_SCB_EZI2C_STATUS_READ1 (0x01UL)
/**
* The Write transfer intended for the primary slave address is complete.
* The buffer content was modified.
* The error condition status bit must be checked to ensure that the Write
* transfer was completed successfully.
*/
#define CY_SCB_EZI2C_STATUS_WRITE1 (0x02UL)
/**
* The Read transfer intended for the secondary slave address is complete.
* The error condition status bit must be checked to ensure that the Read
* transfer was completed successfully.
*/
#define CY_SCB_EZI2C_STATUS_READ2 (0x04UL)
/**
* The Write transfer intended for the secondary slave address is complete.
* The buffer content was modified.
* The error condition status bit must be checked to ensure that the Write
* transfer was completed successfully.
*/
#define CY_SCB_EZI2C_STATUS_WRITE2 (0x08UL)
/**
* A transfer intended for the primary address or secondary address is in
* progress. The status bit is set after an address match and cleared
* on a Stop or ReStart condition.
*/
#define CY_SCB_EZI2C_STATUS_BUSY (0x10UL)
/**
* An error occurred during a transfer intended for the primary or secondary
* slave address. The sources of the error are: a misplaced Start or Stop
* condition or lost arbitration while the slave drives SDA.
* When CY_SCB_EZI2C_STATUS_ERR is set, the slave buffer may contain an
* invalid byte. It is recommended to discard the buffer content in this case.
*/
#define CY_SCB_EZI2C_STATUS_ERR (0x20UL)
/** \} group_scb_ezi2c_macros_get_activity */
/**
* This value is returned by the slave when the buffer is not configured or
* the master requests more bytes than available in the buffer.
*/
#define CY_SCB_EZI2C_DEFAULT_TX (0xFFUL)
/***************************************
* Internal Constants
***************************************/
/** \cond INTERNAL */
/* Default registers values */
#define CY_SCB_EZI2C_I2C_CTRL (SCB_I2C_CTRL_S_GENERAL_IGNORE_Msk | SCB_I2C_CTRL_SLAVE_MODE_Msk)
#define CY_SCB_EZI2C_RX_CTRL (CY_SCB_I2C_RX_CTRL)
#define CY_SCB_EZI2C_TX_CTRL (CY_SCB_I2C_TX_CTRL)
#define CY_SCB_EZI2C_SLAVE_INTR (CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH | CY_SCB_SLAVE_INTR_I2C_STOP | \
CY_SCB_SLAVE_INTR_I2C_BUS_ERROR | CY_SCB_SLAVE_INTR_I2C_ARB_LOST)
/* Error interrupt sources */
#define CY_SCB_EZI2C_SLAVE_INTR_ERROR (CY_SCB_SLAVE_INTR_I2C_BUS_ERROR | CY_SCB_SLAVE_INTR_I2C_ARB_LOST)
/* Disables Stop interrupt source */
#define CY_SCB_EZI2C_SLAVE_INTR_NO_STOP (CY_SCB_EZI2C_SLAVE_INTR & ((uint32_t) ~CY_SCB_SLAVE_INTR_I2C_STOP))
/* Disable Address interrupt source */
#define CY_SCB_EZI2C_SLAVE_INTR_NO_ADDR (CY_SCB_EZI2C_SLAVE_INTR & ((uint32_t) ~CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH))
/* FIFO size */
#define CY_SCB_EZI2C_FIFO_SIZE(base) CY_SCB_FIFO_SIZE(base)
#define CY_SCB_EZI2C_HALF_FIFO_SIZE(base) (CY_SCB_FIFO_SIZE(base) / 2UL)
#define CY_SCB_EZI2C_ONE_ADDRESS_MASK (0xFFUL)
#define CY_SCB_EZI2C_IS_NUM_OF_ADDR_VALID(numAddr) ( (CY_SCB_EZI2C_ONE_ADDRESS == (numAddr)) || \
(CY_SCB_EZI2C_TWO_ADDRESSES == (numAddr)) )
#define CY_SCB_EZI2C_IS_SUB_ADDR_SIZE_VALID(subAddrSize) ( (CY_SCB_EZI2C_SUB_ADDR8_BITS == (subAddrSize)) || \
(CY_SCB_EZI2C_SUB_ADDR16_BITS == (subAddrSize)) )
/** \endcond */
/** \} group_scb_ezi2c_macros */
/***************************************
* Inline Function Implementation
***************************************/
/**
* \addtogroup group_scb_ezi2c_general_functions
* \{
*/
/*******************************************************************************
* Function Name: Cy_SCB_EZI2C_Enable
****************************************************************************//**
*
* Enables the SCB block for the EZI2C operation
*
* \param base
* The pointer to the EZI2C SCB instance.
*
*******************************************************************************/
__STATIC_INLINE void Cy_SCB_EZI2C_Enable(CySCB_Type *base)
{
base->CTRL |= SCB_CTRL_ENABLED_Msk;
}
/** \} group_scb_ezi2c_general_functions */
#if defined(__cplusplus)
}
#endif
/** \} group_scb_ezi2c */
#endif /* (CY_SCB_EZI2C_H) */
/* [] END OF FILE */

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* \file cy_scb_spi.c
* \version 1.0
* \version 2.0
*
* Provides SPI API implementation of the SCB driver.
*
@ -38,7 +38,7 @@ static void DiscardArrayNoCheck(CySCB_Type const *base, uint32_t size);
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
* If only SPI functions which do not require context will be used pass NULL
* as pointer to context.
@ -52,72 +52,103 @@ static void DiscardArrayNoCheck(CySCB_Type const *base, uint32_t size);
*******************************************************************************/
cy_en_scb_spi_status_t Cy_SCB_SPI_Init(CySCB_Type *base, cy_stc_scb_spi_config_t const *config, cy_stc_scb_spi_context_t *context)
{
cy_en_scb_spi_status_t retStatus = CY_SCB_SPI_BAD_PARAM;
if ((NULL != base) && (NULL != config))
/* Input parameters verification */
if ((NULL == base) && (NULL == config))
{
/* Set SCLK mode for TI - CY_SCB_SPI_CPHA1_CPOL0, NS - CY_SCB_SPI_CPHA0_CPOL0, Motorola - take from config */
uint32_t locSclkMode = (CY_SCB_SPI_MOTOROLA == config->subMode) ? config->sclkMode :
((CY_SCB_SPI_NATIONAL == config->subMode) ? CY_SCB_SPI_CPHA0_CPOL0 : CY_SCB_SPI_CPHA1_CPOL0);
/* Configure an SPI interface */
base->CTRL = (((config->rxDataWidth <= CY_SCB_BYTE_WIDTH) && (config->txDataWidth <= CY_SCB_BYTE_WIDTH)) ?
SCB_CTRL_BYTE_MODE_Msk : 0UL) |
(config->enableWakeFromSleep ? SCB_CTRL_EC_AM_MODE_Msk : 0UL) |
_VAL2FLD(SCB_CTRL_OVS, (config->oversample - 1UL)) |
_VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_SPI);
base->SPI_CTRL = (config->enableTransferSeperation ? 0UL : SCB_SPI_CTRL_SSEL_CONTINUOUS_Msk) |
((0UL != (CY_SCB_SPI_TI_PRECEDE & config->subMode)) ? SCB_SPI_CTRL_SELECT_PRECEDE_Msk : 0UL) |
(config->enableMisoLateSample ? SCB_SPI_CTRL_LATE_MISO_SAMPLE_Msk : 0UL) |
(config->enableFreeRunSclk ? SCB_SPI_CTRL_SCLK_CONTINUOUS_Msk : 0UL) |
((CY_SCB_SPI_MASTER == config->spiMode) ? SCB_SPI_CTRL_MASTER_MODE_Msk : 0UL) |
_VAL2FLD(CY_SCB_SPI_CTRL_CLK_MODE, locSclkMode) |
_VAL2FLD(CY_SCB_SPI_CTRL_SSEL_POLARITY, config->ssPolarity) |
_VAL2FLD(SCB_SPI_CTRL_MODE, config->subMode);
/* Configure the RX direction */
base->RX_CTRL = (config->enableMsbFirst ? SCB_RX_CTRL_MSB_FIRST_Msk : 0UL) |
(config->enableInputFilter ? SCB_RX_CTRL_MEDIAN_Msk : 0UL) |
_VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, (config->rxDataWidth - 1UL));
base->RX_FIFO_CTRL = _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
/* Configure the TX direction */
base->TX_CTRL = (config->enableMsbFirst ? SCB_RX_CTRL_MSB_FIRST_Msk : 0UL) |
_VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, (config->txDataWidth - 1UL));
base->TX_FIFO_CTRL = _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
/* Set up interrupt sources */
base->INTR_TX_MASK = config->txFifoIntEnableMask;
base->INTR_RX_MASK = config->rxFifoIntEnableMask;
base->INTR_M = (config->masterSlaveIntEnableMask & SCB_INTR_M_MASK_SPI_DONE_Msk);
base->INTR_S = (config->masterSlaveIntEnableMask & SCB_INTR_S_MASK_SPI_BUS_ERROR_Msk);
base->INTR_SPI_EC_MASK = 0UL;
/* Initialize the context */
if (NULL != context)
{
context->status = 0UL;
context->txBufIdx = 0UL;
context->rxBufIdx = 0UL;
context->cbEvents = NULL;
#if !defined(NDEBUG)
/* Put an initialization key into the initKey variable to verify
* context initialization in the transfer API.
*/
context->initKey = CY_SCB_SPI_INIT_KEY;
#endif /* !(NDEBUG) */
}
retStatus = CY_SCB_SPI_SUCCESS;
return CY_SCB_SPI_BAD_PARAM;
}
return (retStatus);
if ((config->spiMode == CY_SCB_SPI_SLAVE) && (!SCB_IS_SPI_SLAVE_CAPABLE(base)))
{
return CY_SCB_SPI_BAD_PARAM;
}
if ((config->spiMode == CY_SCB_SPI_MASTER) && (!SCB_IS_SPI_MASTER_CAPABLE(base)))
{
return CY_SCB_SPI_BAD_PARAM;
}
if ((config->enableWakeFromSleep) && (!SCB_IS_SPI_DS_CAPABLE(base)))
{
return CY_SCB_SPI_BAD_PARAM;
}
CY_ASSERT_L3(CY_SCB_SPI_IS_MODE_VALID (config->spiMode));
CY_ASSERT_L3(CY_SCB_SPI_IS_SUB_MODE_VALID (config->subMode));
CY_ASSERT_L3(CY_SCB_SPI_IS_SCLK_MODE_VALID(config->sclkMode));
CY_ASSERT_L2(CY_SCB_SPI_IS_OVERSAMPLE_VALID (config->oversample, config->spiMode));
CY_ASSERT_L2(CY_SCB_SPI_IS_SS_POLARITY_VALID(config->ssPolarity));
CY_ASSERT_L2(CY_SCB_SPI_IS_DATA_WIDTH_VALID (config->rxDataWidth));
CY_ASSERT_L2(CY_SCB_SPI_IS_DATA_WIDTH_VALID (config->txDataWidth));
CY_ASSERT_L2(CY_SCB_SPI_IS_BOTH_DATA_WIDTH_VALID(config->subMode, config->rxDataWidth, config->txDataWidth));
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->rxFifoIntEnableMask, CY_SCB_SPI_RX_INTR_MASK));
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->txFifoIntEnableMask, CY_SCB_SPI_TX_INTR_MASK));
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->masterSlaveIntEnableMask, CY_SCB_SPI_MASTER_SLAVE_INTR_MASK));
uint32_t locSclkMode = CY_SCB_SPI_GetSclkMode(config->subMode, config->sclkMode);
bool byteMode = (config->rxDataWidth <= CY_SCB_BYTE_WIDTH) && (config->txDataWidth <= CY_SCB_BYTE_WIDTH);
/* Configure an SPI interface */
base->CTRL = _BOOL2FLD(SCB_CTRL_BYTE_MODE, byteMode) |
_BOOL2FLD(SCB_CTRL_EC_AM_MODE, config->enableWakeFromSleep) |
_VAL2FLD(SCB_CTRL_OVS, (config->oversample - 1UL)) |
_VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_SPI);
/* Configure SCB_CTRL.BYTE_MODE then verify levels */
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->rxFifoTriggerLevel));
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->txFifoTriggerLevel));
base->SPI_CTRL = _BOOL2FLD(SCB_SPI_CTRL_SSEL_CONTINUOUS, (!config->enableTransferSeperation)) |
_BOOL2FLD(SCB_SPI_CTRL_SELECT_PRECEDE, (CY_SCB_SPI_TI_PRECEDES == config->subMode)) |
_BOOL2FLD(SCB_SPI_CTRL_LATE_MISO_SAMPLE, config->enableMisoLateSample) |
_BOOL2FLD(SCB_SPI_CTRL_SCLK_CONTINUOUS, config->enableFreeRunSclk) |
_BOOL2FLD(SCB_SPI_CTRL_MASTER_MODE, (CY_SCB_SPI_MASTER == config->spiMode)) |
_VAL2FLD(CY_SCB_SPI_CTRL_CLK_MODE, locSclkMode) |
_VAL2FLD(CY_SCB_SPI_CTRL_SSEL_POLARITY, config->ssPolarity) |
_VAL2FLD(SCB_SPI_CTRL_MODE, (uint32_t) config->subMode);
/* Configure the RX direction */
base->RX_CTRL = _BOOL2FLD(SCB_RX_CTRL_MSB_FIRST, config->enableMsbFirst) |
_BOOL2FLD(SCB_RX_CTRL_MEDIAN, config->enableInputFilter) |
_VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, (config->rxDataWidth - 1UL));
base->RX_FIFO_CTRL = _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
/* Configure the TX direction */
base->TX_CTRL = _BOOL2FLD(SCB_TX_CTRL_MSB_FIRST, config->enableMsbFirst) |
_VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, (config->txDataWidth - 1UL));
base->TX_FIFO_CTRL = _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
/* Set up interrupt sources */
base->INTR_RX_MASK = (config->rxFifoIntEnableMask & CY_SCB_SPI_RX_INTR_MASK);
base->INTR_TX_MASK = (config->txFifoIntEnableMask & CY_SCB_SPI_TX_INTR_MASK);
base->INTR_M = (config->masterSlaveIntEnableMask & CY_SCB_SPI_MASTER_DONE);
base->INTR_S = (config->masterSlaveIntEnableMask & CY_SCB_SPI_SLAVE_ERR);
base->INTR_SPI_EC_MASK = 0UL;
/* Initialize the context */
if (NULL != context)
{
context->status = 0UL;
context->txBufIdx = 0UL;
context->rxBufIdx = 0UL;
context->cbEvents = NULL;
#if !defined(NDEBUG)
/* Put an initialization key into the initKey variable to verify
* context initialization in the transfer API.
*/
context->initKey = CY_SCB_SPI_INIT_KEY;
#endif /* !(NDEBUG) */
}
return CY_SCB_SPI_SUCCESS;
}
@ -174,7 +205,7 @@ void Cy_SCB_SPI_DeInit(CySCB_Type *base)
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
* If only SPI functions which do not require context will be used pass NULL
* as pointer to context.
@ -182,7 +213,7 @@ void Cy_SCB_SPI_DeInit(CySCB_Type *base)
* \note
* Calling this function when the SPI is busy (master preforms data transfer or
* slave communicates with the master) may cause transfer corruption because the
* hardware stops driving the output and ignores the input.
* hardware stops driving the outputs and ignores the inputs.
* It is recommenced to ensure that the SPI is not busy before calling this
* function.
*
@ -212,58 +243,266 @@ void Cy_SCB_SPI_Disable(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
/*******************************************************************************
* Function Name: Cy_SCB_SPI_DeepSleep
* Function Name: Cy_SCB_SPI_DeepSleepCallback
****************************************************************************//**
*
* Prepares the SPI for deep sleep operation: clears the SPI wake up interrupt
* history and enables it. The wake-up event is the activation of the
* slave select line.
* This function does nothing if the deep sleep option has not been enabled.
* This function handles the transition of the SCB SPI into and out of
* Deep-Sleep mode. It prevents the device from entering Deep-Sleep if the
* SPI slave or master is actively communicating, or there is any data in the
* TX or RX FIFOs.
* The following behavior of the SPI SCB depends on if the SCB block is
* wakeup-capable or not:
* * The SCB wakeup-capable: any transfer intended to the slave wakes up the
* device from Deep-Sleep mode. The slave responds with 0xFF to the transfer.
* If the transfer occurs before the device enters Deep-Sleep mode, the device
* will not enter Deep-Sleep mode and incoming data is stored in the RX FIFO,
* otherwise incoming data is ignored.
* Only the SPI slave can be configured to be a wakeup source from Deep-Sleep
* mode.
* * The SCB is not wakeup-capable: the SPI is disabled. It is enabled when the
* device failed to enter Deep-Sleep mode or it is awaken from Deep-Sleep mode.
* During the SPI is disabled, it stops driving the outputs and ignores the
* inputs. Any incoming data is ignored.
*
* \param base
* The pointer to the SPI SCB instance.
* This function can be called during execution of \ref Cy_SysPm_DeepSleep,
* to do it, register this function as a callback before calling
* \ref Cy_SysPm_DeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
* type and call \ref Cy_SysPm_RegisterCallback.
*
* \note
* Not all SCBs support the deep sleep operation, consult the device
* datasheet to determine which SCBs support deep sleep operation.
* \param callbackParams
* The pointer to the callback parameters structure
* \ref cy_stc_syspm_callback_params_t.
*
* \return
* \ref cy_en_syspm_status_t
*
*******************************************************************************/
void Cy_SCB_SPI_DeepSleep(CySCB_Type *base)
cy_en_syspm_status_t Cy_SCB_SPI_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, base->CTRL))
CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
cy_stc_scb_spi_context_t *locContext = (cy_stc_scb_spi_context_t *) callbackParams->context;
cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
switch(callbackParams->mode)
{
/* Clear and enable the SPI wakeup source */
Cy_SCB_ClearSpiInterrupt (base, CY_SCB_SPI_INTR_WAKEUP);
Cy_SCB_SetSpiInterruptMask(base, CY_SCB_SPI_INTR_WAKEUP);
case CY_SYSPM_CHECK_READY:
{
/* Check if the High-level API is not busy executing the transfer
* operation.
*/
if (0UL == (CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(locBase, locContext)))
{
/* If the SPI bus is not busy, all data elements are transferred
* on the bus from the TX FIFO and shifter and the RX FIFOs are
* empty - the SPI is ready to enter Deep-Sleep mode.
*/
if (!Cy_SCB_SPI_IsBusBusy(locBase))
{
if (Cy_SCB_SPI_IsTxComplete(locBase))
{
if (0UL == Cy_SCB_SPI_GetNumInRxFifo(locBase))
{
if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, locBase->CTRL))
{
/* The SCB is wakeup-capable: clear the SPI
* wakeup interrupt source because it triggers
* during Active mode communication and make
* sure that a new transfer is not started after
* clearing.
*/
Cy_SCB_ClearSpiInterrupt(locBase, CY_SCB_SPI_INTR_WAKEUP);
if (!Cy_SCB_SPI_IsBusBusy(locBase))
{
retStatus = CY_SYSPM_SUCCESS;
}
}
else
{
/* The SCB is NOT wakeup-capable: disable the
* SPI. The master and slave stop driving the
* bus until the SPI is enabled. This happens
* when the device failed to enter Deep-Sleep
* mode or it is awaken from Deep-Sleep mode.
*/
Cy_SCB_SPI_Disable(locBase, locContext);
retStatus = CY_SYSPM_SUCCESS;
}
}
}
}
}
}
break;
case CY_SYSPM_CHECK_FAIL:
{
/* The other driver is not ready for Deep-Sleep mode. Restore
* Active mode configuration.
*/
if (!_FLD2BOOL(SCB_CTRL_EC_AM_MODE, locBase->CTRL))
{
/* The SCB is NOT wakeup-capable: enable the SPI to operate */
Cy_SCB_SPI_Enable(locBase);
}
retStatus = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_BEFORE_TRANSITION:
{
/* This code executes inside the critical section and enabling the
* active interrupt source makes the interrupt pending in the NVIC.
* However, the interrupt processing is delayed until the code exists
* the critical section. The pending interrupt force WFI instruction
* does nothing and the device remains in Active mode.
*/
if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, locBase->CTRL))
{
/* The SCB is wakeup-capable: enable the SPI wakeup interrupt
* source. If any transaction happened, the wakeup interrupt
* becomes pending and prevents entering Deep-Sleep mode.
*/
Cy_SCB_SetSpiInterruptMask(locBase, CY_SCB_I2C_INTR_WAKEUP);
}
retStatus = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_AFTER_TRANSITION:
{
if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, locBase->CTRL))
{
/* The SCB is wakeup-capable: disable the SPI wakeup interrupt
* source
*/
Cy_SCB_SetSpiInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
}
else
{
/* The SCB is NOT wakeup-capable: enable the SPI to operate */
Cy_SCB_SPI_Enable(locBase);
}
retStatus = CY_SYSPM_SUCCESS;
}
break;
default:
break;
}
return (retStatus);
}
/*******************************************************************************
* Function Name: Cy_SCB_SPI_Wakeup
* Function Name: Cy_SCB_SPI_HibernateCallback
****************************************************************************//**
*
* Disables the wakeup interrupt.
* This function does nothing if the deep sleep option has not been enabled.
* This function handles the transition of the SCB SPI into Hibernate mode.
* It prevents the device from entering Hibernate mode if the SPI slave or master
* is actively communicating, or there is any data in the TX or RX FIFOs.
* If the SPI is ready to enter Hibernate mode, it is disabled. If the device
* failed to enter Hibernate mode, the SPI is enabled. During the SPI is
* disabled, it stops driving the outputs and ignores the inputs.
* Any incoming data is ignored.
*
* \param base
* The pointer to the SPI SCB instance.
* This function can be called during execution of \ref Cy_SysPm_Hibernate,
* to do it, register this function as a callback before calling
* \ref Cy_SysPm_Hibernate : specify \ref CY_SYSPM_HIBERNATE as the callback
* type and call \ref Cy_SysPm_RegisterCallback.
*
* \param callbackParams
* The pointer to the callback parameters structure
* \ref cy_stc_syspm_callback_params_t.
*
* \return
* \ref cy_en_syspm_status_t
*
*******************************************************************************/
void Cy_SCB_SPI_Wakeup(CySCB_Type *base)
cy_en_syspm_status_t Cy_SCB_SPI_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, base->CTRL))
CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
cy_stc_scb_spi_context_t *locContext = (cy_stc_scb_spi_context_t *) callbackParams->context;
cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
switch(callbackParams->mode)
{
/* Disable the SPI wakeup source */
Cy_SCB_SetSpiInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
case CY_SYSPM_CHECK_READY:
{
/* Check if the High-level API is not busy executing the transfer
* operation.
*/
if (0UL == (CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(locBase, locContext)))
{
/* If the SPI bus is not busy, all data elements are transferred
* on the bus from the TX FIFO and shifter and the RX FIFOs are
* empty - the SPI is ready to enter Hibernate mode.
*/
if (!Cy_SCB_SPI_IsBusBusy(locBase))
{
if (Cy_SCB_SPI_IsTxComplete(locBase))
{
if (0UL == Cy_SCB_SPI_GetNumInRxFifo(locBase))
{
/* Disable the SPI. The master or slave stops
* driving the bus until the SPI is enabled.
* This happens if the device failed to enter
* Hibernate mode.
*/
Cy_SCB_SPI_Disable(locBase, locContext);
retStatus = CY_SYSPM_SUCCESS;
}
}
}
}
}
break;
case CY_SYSPM_CHECK_FAIL:
{
/* The other driver is not ready for Deep-Sleep mode. Restore Active
* mode configuration.
*/
/* Enable the SPI to operate */
Cy_SCB_SPI_Enable(locBase);
retStatus = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_BEFORE_TRANSITION:
case CY_SYSPM_AFTER_TRANSITION:
{
/* The SCB is not capable of waking up from Hibernate mode:
* do nothing.
*/
retStatus = CY_SYSPM_SUCCESS;
}
break;
default:
break;
}
return (retStatus);
}
/************************* High-Level Functions ********************************
* The following functions are considered high-level. They provide the layer of
* intelligence to the SCB. These functions require interrupts.
* Low-level and high-level functions should not be mixed because low-level API
* Low-level and high-level functions must not be mixed because low-level API
* can adversely affect the operation of high-level functions.
*******************************************************************************/
@ -274,9 +513,10 @@ void Cy_SCB_SPI_Wakeup(CySCB_Type *base)
*
* This function starts an SPI transfer operation.
* It configures transmit and receive buffers for an SPI transfer.
* If the data that will be received is not important, pass NULL as rxBuf.
* If the data that will be transmitted is not important, pass NULL as txBuf
* If the data that will be received is not important, pass NULL as rxBuffer.
* If the data that will be transmitted is not important, pass NULL as txBuffer
* and then the \ref CY_SCB_SPI_DEFAULT_TX is sent out as each data element.
* Note that passing NULL as rxBuffer and txBuffer considered invalid case.
*
* After the function configures TX and RX interrupt sources, it returns and
* \ref Cy_SCB_SPI_Interrupt manages further data transfer.
@ -293,12 +533,12 @@ void Cy_SCB_SPI_Wakeup(CySCB_Type *base)
* \param base
* The pointer to the SPI SCB instance.
*
* \param txBuf
* \param txBuffer
* The pointer of the buffer with data to transmit.
* The item size is defined by the data type which depends on the configured
* TX data width.
*
* \param rxBuf
* \param rxBuffer
* The pointer to the buffer to store received data.
* The item size is defined by the data type which depends on the configured
* RX data width.
@ -309,7 +549,7 @@ void Cy_SCB_SPI_Wakeup(CySCB_Type *base)
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -322,15 +562,14 @@ void Cy_SCB_SPI_Wakeup(CySCB_Type *base)
* the RX and TX FIFO level.
*
*******************************************************************************/
cy_en_scb_spi_status_t Cy_SCB_SPI_Transfer(CySCB_Type *base, void *txBuf, void *rxBuf, uint32_t size, cy_stc_scb_spi_context_t *context)
cy_en_scb_spi_status_t Cy_SCB_SPI_Transfer(CySCB_Type *base, void *txBuffer, void *rxBuffer, uint32_t size,
cy_stc_scb_spi_context_t *context)
{
cy_en_scb_spi_status_t retStatus = CY_SCB_SPI_TRANSFER_BUSY;
CY_ASSERT_L1(NULL != context);
CY_ASSERT_L1(CY_SCB_SPI_INIT_KEY == context->initKey);
CY_ASSERT_L1(CY_SCB_SPI_IS_BUFFER_VALID(txBuffer, rxBuffer, size));
#if !defined(NDEBUG)
/* Check that the initialization key was set before using the context */
CY_ASSERT(NULL != context);
CY_ASSERT(CY_SCB_SPI_INIT_KEY == context->initKey);
#endif /* !(NDEBUG) */
cy_en_scb_spi_status_t retStatus = CY_SCB_SPI_TRANSFER_BUSY;
/* Check if there are no active transfer requests */
if (0UL == (CY_SCB_SPI_TRANSFER_ACTIVE & context->status))
@ -340,11 +579,11 @@ cy_en_scb_spi_status_t Cy_SCB_SPI_Transfer(CySCB_Type *base, void *txBuf, void *
/* Set up the context */
context->status = CY_SCB_SPI_TRANSFER_ACTIVE;
context->txBuf = txBuf;
context->txBuf = txBuffer;
context->txBufSize = size;
context->txBufIdx = 0UL;
context->rxBuf = rxBuf;
context->rxBuf = rxBuffer;
context->rxBufSize = size;
context->rxBufIdx = 0UL;
@ -401,7 +640,7 @@ cy_en_scb_spi_status_t Cy_SCB_SPI_Transfer(CySCB_Type *base, void *txBuf, void *
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \note
@ -456,7 +695,7 @@ void Cy_SCB_SPI_AbortTransfer(CySCB_Type *base, cy_stc_scb_spi_context_t *contex
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -486,11 +725,11 @@ uint32_t Cy_SCB_SPI_GetNumTransfered(CySCB_Type const *base, cy_stc_scb_spi_cont
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
* \ref group_scb_spi_macro_xfer_status.
* \ref group_scb_spi_macros_xfer_status.
*
* \note
* The status is cleared by calling \ref Cy_SCB_SPI_Transfer or
@ -520,7 +759,7 @@ uint32_t Cy_SCB_SPI_GetTransferStatus(CySCB_Type const *base, cy_stc_scb_spi_con
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -615,7 +854,7 @@ void Cy_SCB_SPI_Interrupt(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -680,7 +919,7 @@ static void HandleReceive(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
* \param context
* The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
* by the user. The structure is used during the SPI operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* \file cy_scb_uart.c
* \version 1.0
* \version 2.0
*
* Provides UART API implementation of the SCB driver.
*
@ -39,7 +39,7 @@ static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *cont
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
* If only UART functions which do not require context will be used pass NULL
* as pointer to context.
@ -53,95 +53,124 @@ static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *cont
*******************************************************************************/
cy_en_scb_uart_status_t Cy_SCB_UART_Init(CySCB_Type *base, cy_stc_scb_uart_config_t const *config, cy_stc_scb_uart_context_t *context)
{
cy_en_scb_uart_status_t retStatus = CY_SCB_UART_BAD_PARAM;
if ((NULL != base) && (NULL != config))
if ((NULL == base) && (NULL == config))
{
uint32_t ovs;
if ((CY_SCB_UART_IRDA == config->uartMode) && (!config->irdaEnableLowPowerReceiver))
{
/* For Normal IrDA mode oversampling is always zero */
ovs = 0UL;
}
else
{
ovs = (config->oversample - 1UL);
}
/* Configure the UART interface */
base->CTRL = (config->enableMutliProcessorMode ? SCB_CTRL_ADDR_ACCEPT_Msk : 0UL) |
((config->dataWidth <= CY_SCB_BYTE_WIDTH) ? SCB_CTRL_BYTE_MODE_Msk : 0UL) |
_VAL2FLD(SCB_CTRL_OVS, ovs) |
_VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_UART);
base->UART_CTRL = _VAL2FLD(SCB_UART_CTRL_MODE, config->uartMode);
/* Configure the RX direction */
base->UART_RX_CTRL = (config->irdaInvertRx ? SCB_UART_RX_CTRL_POLARITY_Msk : 0UL) |
(config->enableMutliProcessorMode ? SCB_UART_RX_CTRL_MP_MODE_Msk : 0UL) |
(config->dropOnParityError ? SCB_UART_RX_CTRL_DROP_ON_PARITY_ERROR_Msk : 0UL) |
(config->dropOnFrameError ? SCB_UART_RX_CTRL_DROP_ON_FRAME_ERROR_Msk : 0UL) |
_VAL2FLD(SCB_UART_RX_CTRL_BREAK_WIDTH, (config->breakWidth - 1UL)) |
_VAL2FLD(SCB_UART_RX_CTRL_STOP_BITS, (config->stopBits - 1UL)) |
_VAL2FLD(CY_SCB_UART_RX_CTRL_SET_PARITY, config->parity);
base->RX_CTRL = (config->enableMsbFirst ? SCB_RX_CTRL_MSB_FIRST_Msk : 0UL) |
(config->enableInputFilter ? SCB_RX_CTRL_MEDIAN_Msk : 0UL) |
_VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, (config->dataWidth - 1UL));
base->RX_MATCH = _VAL2FLD(SCB_RX_MATCH_ADDR, config->receiverAddress) |
_VAL2FLD(SCB_RX_MATCH_MASK, config->receiverAddressMask);
/* Configure the TX direction */
base->UART_TX_CTRL = (config->smartCardRetryOnNack ? SCB_UART_TX_CTRL_RETRY_ON_NACK_Msk : 0UL) |
_VAL2FLD(SCB_UART_TX_CTRL_STOP_BITS, (config->stopBits - 1UL)) |
_VAL2FLD(CY_SCB_UART_RX_CTRL_SET_PARITY, config->parity);
base->TX_CTRL = (config->enableMsbFirst ? SCB_RX_CTRL_MSB_FIRST_Msk : 0UL) |
_VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, (config->dataWidth - 1UL));
base->RX_FIFO_CTRL = _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
/* Configure the flow control */
base->UART_FLOW_CTRL = (config->enableCts ? SCB_UART_FLOW_CTRL_CTS_ENABLED_Msk : 0UL) |
((CY_SCB_UART_ACTIVE_HIGH == config->ctsPolarity) ? SCB_UART_FLOW_CTRL_CTS_POLARITY_Msk : 0UL) |
((CY_SCB_UART_ACTIVE_HIGH == config->rtsPolarity) ? SCB_UART_FLOW_CTRL_RTS_POLARITY_Msk : 0UL) |
_VAL2FLD(SCB_UART_FLOW_CTRL_TRIGGER_LEVEL, config->rtsRxFifoLevel);
base->TX_FIFO_CTRL = _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
/* Set up interrupt sources */
base->INTR_TX_MASK = config->txFifoIntEnableMask;
base->INTR_RX_MASK = config->rxFifoIntEnableMask;
/* Initialize context */
if (NULL != context)
{
context->rxStatus = 0UL;
context->txStatus = 0UL;
context->rxRingBuf = NULL;
context->rxRingBufSize = 0UL;
context->rxBufIdx = 0UL;
context->txLeftToTransmit = 0UL;
context->cbEvents = NULL;
#if !defined(NDEBUG)
/* Put an initialization key into the initKey variable to verify
* context initialization in the transfer API.
*/
context->initKey = CY_SCB_UART_INIT_KEY;
#endif /* !(NDEBUG) */
}
retStatus = CY_SCB_UART_SUCCESS;
return CY_SCB_UART_BAD_PARAM;
}
return (retStatus);
if (!SCB_IS_UART_CAPABLE(base))
{
return CY_SCB_UART_BAD_PARAM;
}
CY_ASSERT_L3(CY_SCB_UART_IS_MODE_VALID (config->uartMode));
CY_ASSERT_L3(CY_SCB_UART_IS_STOP_BITS_VALID(config->stopBits));
CY_ASSERT_L3(CY_SCB_UART_IS_PARITY_VALID (config->parity));
CY_ASSERT_L3(CY_SCB_UART_IS_POLARITY_VALID (config->ctsPolarity));
CY_ASSERT_L3(CY_SCB_UART_IS_POLARITY_VALID (config->rtsPolarity));
CY_ASSERT_L2(CY_SCB_UART_IS_OVERSAMPLE_VALID (config->oversample, config->uartMode, config->irdaEnableLowPowerReceiver));
CY_ASSERT_L2(CY_SCB_UART_IS_DATA_WIDTH_VALID (config->dataWidth));
CY_ASSERT_L2(CY_SCB_UART_IS_ADDRESS_VALID (config->receiverAddress));
CY_ASSERT_L2(CY_SCB_UART_IS_ADDRESS_MASK_VALID(config->receiverAddressMask));
CY_ASSERT_L2(CY_SCB_UART_IS_MUTLI_PROC_VALID (config->enableMutliProcessorMode, config->uartMode, config->dataWidth,
config->parity));
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->rxFifoIntEnableMask, CY_SCB_UART_RX_INTR_MASK));
CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->txFifoIntEnableMask, CY_SCB_UART_TX_INTR_MASK));
uint32_t ovs;
if ((CY_SCB_UART_IRDA == config->uartMode) && (!config->irdaEnableLowPowerReceiver))
{
/* For Normal IrDA mode oversampling is always zero */
ovs = 0UL;
}
else
{
ovs = (config->oversample - 1UL);
}
/* Configure the UART interface */
base->CTRL = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, config->acceptAddrInFifo) |
_BOOL2FLD(SCB_CTRL_BYTE_MODE, (config->dataWidth <= CY_SCB_BYTE_WIDTH)) |
_VAL2FLD(SCB_CTRL_OVS, ovs) |
_VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_UART);
/* Configure SCB_CTRL.BYTE_MODE then verify levels */
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->rxFifoTriggerLevel));
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->txFifoTriggerLevel));
CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->rtsRxFifoLevel));
base->UART_CTRL = _VAL2FLD(SCB_UART_CTRL_MODE, (uint32_t) config->uartMode);
/* Configure the RX direction */
base->UART_RX_CTRL = _BOOL2FLD(SCB_UART_RX_CTRL_POLARITY, config->irdaInvertRx) |
_BOOL2FLD(SCB_UART_RX_CTRL_MP_MODE, config->enableMutliProcessorMode) |
_BOOL2FLD(SCB_UART_RX_CTRL_DROP_ON_PARITY_ERROR, config->dropOnParityError) |
_BOOL2FLD(SCB_UART_RX_CTRL_DROP_ON_FRAME_ERROR, config->dropOnFrameError) |
_VAL2FLD(SCB_UART_RX_CTRL_BREAK_WIDTH, (config->breakWidth - 1UL)) |
_VAL2FLD(SCB_UART_RX_CTRL_STOP_BITS, ((uint32_t) config->stopBits) - 1UL) |
_VAL2FLD(CY_SCB_UART_RX_CTRL_SET_PARITY, (uint32_t) config->parity);
base->RX_CTRL = _BOOL2FLD(SCB_RX_CTRL_MSB_FIRST, config->enableMsbFirst) |
_BOOL2FLD(SCB_RX_CTRL_MEDIAN, ((config->enableInputFilter) || \
(config->uartMode == CY_SCB_UART_IRDA))) |
_VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, (config->dataWidth - 1UL));
base->RX_MATCH = _VAL2FLD(SCB_RX_MATCH_ADDR, config->receiverAddress) |
_VAL2FLD(SCB_RX_MATCH_MASK, config->receiverAddressMask);
/* Configure SCB_CTRL.RX_CTRL then verify break width */
CY_ASSERT_L2(CY_SCB_UART_IS_RX_BREAK_WIDTH_VALID(base, config->breakWidth));
/* Configure the TX direction */
base->UART_TX_CTRL = _BOOL2FLD(SCB_UART_TX_CTRL_RETRY_ON_NACK, ((config->smartCardRetryOnNack) && \
(config->uartMode == CY_SCB_UART_SMARTCARD))) |
_VAL2FLD(SCB_UART_TX_CTRL_STOP_BITS, ((uint32_t) config->stopBits) - 1UL) |
_VAL2FLD(CY_SCB_UART_TX_CTRL_SET_PARITY, (uint32_t) config->parity);
base->TX_CTRL = _BOOL2FLD(SCB_TX_CTRL_MSB_FIRST, config->enableMsbFirst) |
_VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, (config->dataWidth - 1UL)) |
_BOOL2FLD(SCB_TX_CTRL_OPEN_DRAIN, (config->uartMode == CY_SCB_UART_SMARTCARD));
base->RX_FIFO_CTRL = _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
/* Configure the flow control */
base->UART_FLOW_CTRL = _BOOL2FLD(SCB_UART_FLOW_CTRL_CTS_ENABLED, config->enableCts) |
_BOOL2FLD(SCB_UART_FLOW_CTRL_CTS_POLARITY, (CY_SCB_UART_ACTIVE_HIGH == config->ctsPolarity)) |
_BOOL2FLD(SCB_UART_FLOW_CTRL_RTS_POLARITY, (CY_SCB_UART_ACTIVE_HIGH == config->rtsPolarity)) |
_VAL2FLD(SCB_UART_FLOW_CTRL_TRIGGER_LEVEL, config->rtsRxFifoLevel);
base->TX_FIFO_CTRL = _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
/* Set up interrupt sources */
base->INTR_RX_MASK = (config->rxFifoIntEnableMask & CY_SCB_UART_RX_INTR_MASK);
base->INTR_TX_MASK = (config->txFifoIntEnableMask & CY_SCB_UART_TX_INTR_MASK);
/* Initialize context */
if (NULL != context)
{
context->rxStatus = 0UL;
context->txStatus = 0UL;
context->rxRingBuf = NULL;
context->rxRingBufSize = 0UL;
context->rxBufIdx = 0UL;
context->txLeftToTransmit = 0UL;
context->cbEvents = NULL;
#if !defined(NDEBUG)
/* Put an initialization key into the initKey variable to verify
* context initialization in the transfer API.
*/
context->initKey = CY_SCB_UART_INIT_KEY;
#endif /* !(NDEBUG) */
}
return CY_SCB_UART_SUCCESS;
}
@ -203,7 +232,7 @@ void Cy_SCB_UART_DeInit(CySCB_Type *base)
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
* If only UART functions which do not require context will be used pass NULL
* as pointer to context.
@ -211,8 +240,8 @@ void Cy_SCB_UART_DeInit(CySCB_Type *base)
* \note
* Calling this function when the UART is busy (transmitter preforms data
* transfer or receiver is in the middle of data reception) may result transfer
* corruption because the hardware stops driving the output and ignores
* the input.
* corruption because the hardware stops driving the outputs and ignores
* the inputs.
* Ensure that the UART is not busy before calling this function.
*
*******************************************************************************/
@ -231,10 +260,141 @@ void Cy_SCB_UART_Disable(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
}
/*******************************************************************************
* Function Name: Cy_SCB_UART_DeepSleepCallback
****************************************************************************//**
*
* This function handles the transition of the SCB UART into and out of
* Deep-Sleep mode. It prevents the device from entering Deep-Sleep mode if
* the UART is transmitting data or has any data in the RX FIFO. If the UART
* is ready to enter Deep-Sleep mode, it is disabled. The UART is enabled
* when the device failed to enter Deep-Sleep mode or it is awaken from
* Deep-Sleep mode. During the UART is disabled, it stops driving the outputs
* and ignores the inputs. Any incoming data is ignored.
*
* This function can be called during execution of \ref Cy_SysPm_DeepSleep,
* to do it, register this function as a callback before calling
* \ref Cy_SysPm_DeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
* type and call \ref Cy_SysPm_RegisterCallback.
*
* \param callbackParams
* The pointer to the callback parameters structure
* \ref cy_stc_syspm_callback_params_t.
*
* \return
* \ref cy_en_syspm_status_t
*
*******************************************************************************/
cy_en_syspm_status_t Cy_SCB_UART_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
cy_stc_scb_uart_context_t *locContext = (cy_stc_scb_uart_context_t *) callbackParams->context;
switch(callbackParams->mode)
{
case CY_SYSPM_CHECK_READY:
{
/* Check if the High-level API is not busy executing the transmit
* or receive operation.
*/
if ((0UL == (CY_SCB_UART_TRANSMIT_ACTIVE & Cy_SCB_UART_GetTransmitStatus(locBase, locContext))) &&
(0UL == (CY_SCB_UART_RECEIVE_ACTIVE & Cy_SCB_UART_GetReceiveStatus (locBase, locContext))))
{
/* If all data elements are transmitted from the TX FIFO and
* shifter and the RX FIFO is empty: the UART is ready to enter
* Deep-Sleep mode.
*/
if (Cy_SCB_UART_IsTxComplete(locBase))
{
if (0UL == Cy_SCB_UART_GetNumInRxFifo(locBase))
{
/* Disable the UART. The transmitter stops driving the
* lines and the receiver stops receiving data until
* the UART is enabled.
* This happens when the device failed to enter Deep
* Sleep or it is awaken from Deep-Sleep mode.
*/
Cy_SCB_UART_Disable(locBase, locContext);
retStatus = CY_SYSPM_SUCCESS;
}
}
}
}
break;
case CY_SYSPM_CHECK_FAIL:
{
/* The other driver is not ready for Deep-Sleep mode. Restore the
* Active mode configuration.
*/
/* Enable the UART to operate */
Cy_SCB_UART_Enable(locBase);
retStatus = CY_SYSPM_SUCCESS;
}
break;
case CY_SYSPM_BEFORE_TRANSITION:
/* Do noting: the UART is not capable of waking up from
* Deep-Sleep mode.
*/
break;
case CY_SYSPM_AFTER_TRANSITION:
{
/* Enable the UART to operate */
Cy_SCB_UART_Enable(locBase);
retStatus = CY_SYSPM_SUCCESS;
}
break;
default:
break;
}
return (retStatus);
}
/*******************************************************************************
* Function Name: Cy_SCB_UART_HibernateCallback
****************************************************************************//**
*
* This function handles the transition of the SCB UART into Hibernate mode.
* It prevents the device from entering Hibernate mode if the UART is
* transmitting data or has any data in the RX FIFO. If the UART is ready
* to enter Hibernate mode, it is disabled. If the device failed to enter
* Hibernate mode, the UART is enabled. During the UART is disabled, it stops
* driving the outputs and ignores the inputs. Any incoming data is ignored.
*
* This function can be called during execution of \ref Cy_SysPm_Hibernate,
* to do it, register this function as a callback before calling
* \ref Cy_SysPm_Hibernate : specify \ref CY_SYSPM_HIBERNATE as the callback type
* and call \ref Cy_SysPm_RegisterCallback.
*
* \param callbackParams
* The pointer to the callback parameters structure
* \ref cy_stc_syspm_callback_params_t.
*
* \return
* \ref cy_en_syspm_status_t
*
*******************************************************************************/
cy_en_syspm_status_t Cy_SCB_UART_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams)
{
return Cy_SCB_UART_DeepSleepCallback(callbackParams);
}
/************************* High-Level Functions ********************************
* The following functions are considered high-level. They provide the layer of
* intelligence to the SCB. These functions require interrupts.
* Low-level and high-level functions should not be mixed because low-level API
* Low-level and high-level functions must not be mixed because low-level API
* can adversely affect the operation of high-level functions.
*******************************************************************************/
@ -250,7 +410,7 @@ void Cy_SCB_UART_Disable(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
* \param base
* The pointer to the UART SCB instance.
*
* \param ringBuffer
* \param buffer
* Pointer to the user defined ring buffer.
* The item size is defined by the data type which depends on the configured
* data width.
@ -263,7 +423,7 @@ void Cy_SCB_UART_Disable(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \note
@ -273,19 +433,17 @@ void Cy_SCB_UART_Disable(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
* RX FIFO level.
*
*******************************************************************************/
void Cy_SCB_UART_StartRingBuffer(CySCB_Type *base, void *ringBuffer, uint32_t size, cy_stc_scb_uart_context_t *context)
void Cy_SCB_UART_StartRingBuffer(CySCB_Type *base, void *buffer, uint32_t size, cy_stc_scb_uart_context_t *context)
{
#if !defined(NDEBUG)
/* Check that the initialization key was set before using the context */
CY_ASSERT(NULL != context);
CY_ASSERT(CY_SCB_UART_INIT_KEY == context->initKey);
#endif /* !(NDEBUG) */
CY_ASSERT_L1(NULL != context);
CY_ASSERT_L1(CY_SCB_UART_INIT_KEY == context->initKey);
CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID(buffer, size));
if ((NULL != ringBuffer) && (size > 0UL))
if ((NULL != buffer) && (size > 0UL))
{
uint32_t halfFifoSize = (Cy_SCB_GetFifoSize(base) / 2UL);
context->rxRingBuf = ringBuffer;
context->rxRingBuf = buffer;
context->rxRingBufSize = size;
context->rxRingBufHead = 0UL;
context->rxRingBufTail = 0UL;
@ -310,13 +468,13 @@ void Cy_SCB_UART_StartRingBuffer(CySCB_Type *base, void *ringBuffer, uint32_t si
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
void Cy_SCB_UART_StopRingBuffer(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
{
Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
Cy_SCB_SetRxInterruptMask (base, CY_SCB_CLEAR_ALL_INTR_SRC);
Cy_SCB_UART_ClearRingBuffer(base, context);
context->rxRingBuf = NULL;
@ -336,7 +494,7 @@ void Cy_SCB_UART_StopRingBuffer(CySCB_Type *base, cy_stc_scb_uart_context_t *con
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -380,7 +538,7 @@ uint32_t Cy_SCB_UART_GetNumInRingBuffer(CySCB_Type const *base, cy_stc_scb_uart_
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -413,7 +571,7 @@ void Cy_SCB_UART_ClearRingBuffer(CySCB_Type const *base, cy_stc_scb_uart_context
* \param base
* The pointer to the UART SCB instance.
*
* \param rxBuf
* \param buffer
* Pointer to buffer to store received data.
* The item size is defined by the data type which depends on the configured
* data width.
@ -424,7 +582,7 @@ void Cy_SCB_UART_ClearRingBuffer(CySCB_Type const *base, cy_stc_scb_uart_context
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -437,20 +595,18 @@ void Cy_SCB_UART_ClearRingBuffer(CySCB_Type const *base, cy_stc_scb_uart_context
* RX FIFO level.
*
*******************************************************************************/
cy_en_scb_uart_status_t Cy_SCB_UART_Receive(CySCB_Type *base, void *rxBuf, uint32_t size, cy_stc_scb_uart_context_t *context)
cy_en_scb_uart_status_t Cy_SCB_UART_Receive(CySCB_Type *base, void *buffer, uint32_t size, cy_stc_scb_uart_context_t *context)
{
cy_en_scb_uart_status_t retStatus = CY_SCB_UART_RECEIVE_BUSY;
CY_ASSERT_L1(NULL != context);
CY_ASSERT_L1(CY_SCB_UART_INIT_KEY == context->initKey);
CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID(buffer, size));
#if !defined(NDEBUG)
/* Check that the initialization key was set before using the context */
CY_ASSERT(NULL != context);
CY_ASSERT(CY_SCB_UART_INIT_KEY == context->initKey);
#endif /* !(NDEBUG) */
cy_en_scb_uart_status_t retStatus = CY_SCB_UART_RECEIVE_BUSY;
/* Check if there are no active transfer requests */
if (0UL == (context->rxStatus & CY_SCB_UART_RECEIVE_ACTIVE))
{
uint8_t *tmpBuf = (uint8_t *) rxBuf;
uint8_t *tmpBuf = (uint8_t *) buffer;
uint32_t numToCopy = 0UL;
/* Disable the RX interrupt source to stop the ring buffer update */
@ -485,12 +641,12 @@ cy_en_scb_uart_status_t Cy_SCB_UART_Receive(CySCB_Type *base, void *rxBuf, uint3
if (byteMode)
{
uint8_t *buf = (uint8_t *) rxBuf;
uint8_t *buf = (uint8_t *) buffer;
buf[idx] = ((uint8_t *) context->rxRingBuf)[locTail];
}
else
{
uint16_t *buf = (uint16_t *) rxBuf;
uint16_t *buf = (uint16_t *) buffer;
buf[idx] = ((uint16_t *) context->rxRingBuf)[locTail];
}
}
@ -570,7 +726,7 @@ cy_en_scb_uart_status_t Cy_SCB_UART_Receive(CySCB_Type *base, void *rxBuf, uint3
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \note
@ -610,7 +766,7 @@ void Cy_SCB_UART_AbortReceive(CySCB_Type *base, cy_stc_scb_uart_context_t *conte
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -639,11 +795,11 @@ uint32_t Cy_SCB_UART_GetNumReceived(CySCB_Type const *base, cy_stc_scb_uart_cont
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
* \ref group_scb_uart_macro_receive_status.
* \ref group_scb_uart_macros_receive_status.
*
* \note
* The status is only cleared by calling \ref Cy_SCB_UART_Receive again.
@ -673,7 +829,7 @@ uint32_t Cy_SCB_UART_GetReceiveStatus(CySCB_Type const *base, cy_stc_scb_uart_co
* \param base
* The pointer to the UART SCB instance.
*
* \param txBuf
* \param buffer
* Pointer to user data to place in transmit buffer.
* The item size is defined by the data type which depends on the configured
* data width.
@ -684,7 +840,7 @@ uint32_t Cy_SCB_UART_GetReceiveStatus(CySCB_Type const *base, cy_stc_scb_uart_co
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -697,15 +853,13 @@ uint32_t Cy_SCB_UART_GetReceiveStatus(CySCB_Type const *base, cy_stc_scb_uart_co
* TX FIFO level.
*
*******************************************************************************/
cy_en_scb_uart_status_t Cy_SCB_UART_Transmit(CySCB_Type *base, void *txBuf, uint32_t size, cy_stc_scb_uart_context_t *context)
cy_en_scb_uart_status_t Cy_SCB_UART_Transmit(CySCB_Type *base, void *buffer, uint32_t size, cy_stc_scb_uart_context_t *context)
{
cy_en_scb_uart_status_t retStatus = CY_SCB_UART_TRANSMIT_BUSY;
CY_ASSERT_L1(NULL != context);
CY_ASSERT_L1(CY_SCB_UART_INIT_KEY == context->initKey);
CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID(buffer, size));
#if !defined(NDEBUG)
/* Check that the initialization key was set before using the context */
CY_ASSERT(NULL != context);
CY_ASSERT(CY_SCB_UART_INIT_KEY == context->initKey);
#endif /* !(NDEBUG) */
cy_en_scb_uart_status_t retStatus = CY_SCB_UART_TRANSMIT_BUSY;
/* Check if there are no active transfer requests */
if (0UL == (CY_SCB_UART_TRANSMIT_ACTIVE & context->txStatus))
@ -713,14 +867,14 @@ cy_en_scb_uart_status_t Cy_SCB_UART_Transmit(CySCB_Type *base, void *txBuf, uint
/* Set up context */
context->txStatus = CY_SCB_UART_TRANSMIT_ACTIVE;
context->txBuf = txBuf;
context->txBuf = buffer;
context->txBufSize = size;
/* Set the level in TX FIFO to start a transfer */
Cy_SCB_SetTxFifoLevel(base, (Cy_SCB_GetFifoSize(base) / 2UL));
/* Enable the interrupt sources */
if (CY_SCB_UART_SMARTCARD == _FLD2VAL(SCB_UART_CTRL_MODE, base->UART_CTRL))
if (((uint32_t) CY_SCB_UART_SMARTCARD) == _FLD2VAL(SCB_UART_CTRL_MODE, base->UART_CTRL))
{
/* Transfer data into TX FIFO and track SmartCard-specific errors */
Cy_SCB_SetTxInterruptMask(base, CY_SCB_UART_TX_INTR);
@ -752,7 +906,7 @@ cy_en_scb_uart_status_t Cy_SCB_UART_Transmit(CySCB_Type *base, void *txBuf, uint
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \sideeffect
@ -788,7 +942,7 @@ void Cy_SCB_UART_AbortTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *cont
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
@ -817,11 +971,11 @@ uint32_t Cy_SCB_UART_GetNumLeftToTransmit(CySCB_Type const *base, cy_stc_scb_uar
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
* \return
* \ref group_scb_uart_macro_transmit_status.
* \ref group_scb_uart_macros_transmit_status.
*
* \note
* The status is only cleared by calling \ref Cy_SCB_UART_Transmit or
@ -837,6 +991,64 @@ uint32_t Cy_SCB_UART_GetTransmitStatus(CySCB_Type const *base, cy_stc_scb_uart_c
}
/*******************************************************************************
* Function Name: Cy_SCB_UART_SendBreakBlocking
****************************************************************************//**
*
* Sends a break condition (logic low) of specified width on UART TX line.
* Blocks until break is completed. Only call this function when UART TX FIFO
* and shifter are empty.
*
* \param base
* The pointer to the UART SCB instance.
*
* \param breakWidth
* Width of break condition. Valid range is the TX data width (4 to 16 bits)
*
* \note
* Before sending break all UART TX interrurpt sources are disabled. The state
* of UART TX interrurpt sources is restored before function retuns.
*
* \sideeffect
* If this function is called while there is data in the TX FIFO or shifter that
* data will be shifted out in packets the size of breakWidth.
*
*******************************************************************************/
void Cy_SCB_UART_SendBreakBlocking(CySCB_Type *base, uint32_t breakWidth)
{
uint32_t txCtrlReg;
uint32_t txIntrReg;
CY_ASSERT_L2(CY_SCB_UART_IS_TX_BREAK_WIDTH_VALID(breakWidth));
/* Disable all UART TX interurpt sources and clear UART TX Done history */
txIntrReg = Cy_SCB_GetTxInterruptMask(base);
Cy_SCB_SetTxInterruptMask(base, 0UL);
Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UART_DONE);
/* Store TX_CTRL configuration */
txCtrlReg = base->TX_CTRL;
/* Set break width: start bit adds one 0 bit */
base->TX_CTRL = _CLR_SET_FLD32U(base->TX_CTRL, SCB_TX_CTRL_DATA_WIDTH, (breakWidth - 1UL));
/* Generate break */
Cy_SCB_WriteTxFifo(base, 0UL);
/* Wait for break completion */
while (0UL == (Cy_SCB_GetTxInterruptStatus(base) & CY_SCB_TX_INTR_UART_DONE))
{
}
/* Clear all UART TX interrupt sources */
Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_MASK);
/* Restore TX data width and interrupt sources */
base->TX_CTRL = txCtrlReg;
Cy_SCB_SetTxInterruptMask(base, txIntrReg);
}
/*******************************************************************************
* Function Name: Cy_SCB_UART_Interrupt
****************************************************************************//**
@ -852,7 +1064,7 @@ uint32_t Cy_SCB_UART_GetTransmitStatus(CySCB_Type const *base, cy_stc_scb_uart_c
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -959,7 +1171,7 @@ void Cy_SCB_UART_Interrupt(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -1027,7 +1239,7 @@ static void HandleDataReceive(CySCB_Type *base, cy_stc_scb_uart_context_t *conte
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -1111,7 +1323,7 @@ static void HandleRingBuffer(CySCB_Type *base, cy_stc_scb_uart_context_t *contex
* \param context
* The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
* by the user. The structure is used during the UART operation for internal
* configuration and data keeping. The user should not modify anything
* configuration and data keeping. The user must not modify anything
* in this structure.
*
*******************************************************************************/
@ -1172,6 +1384,7 @@ static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *cont
}
}
#if defined(__cplusplus)
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,425 @@
/***************************************************************************//**
* \file cy_smif_memslot.h
* \version 1.10
*
* \brief
* This file provides the constants and parameter values for the memory-level
* APIs of the SMIF driver.
*
* Note:
*
********************************************************************************
* \copyright
* Copyright 2016-2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#if !defined(CY_SMIF_MEMORYSLOT_H)
#define CY_SMIF_MEMORYSLOT_H
#include <stdint.h>
#include <stdbool.h>
#include "syslib/cy_syslib.h"
#include "cy_device_headers.h"
#include "cy_smif.h"
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_smif_macros_status
* \{
*/
/***************************************
* Constants
****************************************/
#define CY_SMIF_DEVICE_BUSY (1U) /**< The external memory is busy */
#define CY_SMIF_DEVICE_READY (0U) /**< The external memory is ready */
/** \} group_smif_macros_status */
/**
* \addtogroup group_smif_macros_cmd
* \{
*/
#define CY_SMIF_CMD_WITHOUT_PARAM (0U) /**< No parameter */
#define CY_SMIF_TX_LAST_BYTE (1U) /**< The last byte in the command transmission
* (SS is set high after the transmission)
*/
#define CY_SMIF_TX_NOT_LAST_BYTE (0U) /**< Not the last byte in the command transmission
* (SS remains low after the transmission)
*/
#define CY_SMIF_READ_ONE_BYTE (1U) /**< Read 1 byte */
#define CY_SMIF_WRITE_ONE_BYTE (1U) /**< Write 1 byte */
#define CY_SMIF_WRITE_TWO_BYTES (2U) /**< Write 2 bytes */
#define CY_SMIF_ONE_WORD (4U) /**< 4 bytes */
#define CY_SMIF_DUAL_QUAD_DISABLED (0U) /**< The dual quad transmission mode is disabled */
#define CY_SMIF_DUAL_QUAD_ENABLED (1U) /**< The dual quad transmission mode is enabled */
/** \} group_smif_macros_status */
/**
* \addtogroup group_smif_macros_flags
* \{
*/
#define CY_SMIF_FLAG_ALL_DISABLED (0U) /**< All memory configuration flags are disabled */
/** Enables the write capability for the memory slave in the memory-mapped
* mode. Valid when the memory-mapped mode is enabled */
#define CY_SMIF_FLAG_WR_EN (SMIF_DEVICE_CTL_WR_EN_Msk)
/** Determines if the device is memory-mapped. If enabled, this memory slot will
* be initialized in System init */
#define CY_SMIF_FLAG_MEMORY_MAPPED (2U)
#define CY_SMIF_FLAG_DETECT_SFDP (4U) /**< Enables the Autodetect using the SFDP */
/** Enables the crypto support for this memory slave. All access to the
* memory device goes through the encryption/decryption
* Valid when the memory-mapped mode is enabled */
#define CY_SMIF_FLAG_CRYPTO_EN (SMIF_DEVICE_CTL_CRYPTO_EN_Msk)
/** \} group_smif_macros_flags */
/**
* \addtogroup group_smif_macros_sfdp
* \{
*/
/***************************************
* SFDP constants
****************************************/
#define CY_SMIF_SFDP_ADDRESS_LENGTH (0x03U) /**< The length of the SFDP address */
#define CY_SMIF_SFDP_LENGTH (0xFFU) /**< The length of the SFDP */
#define CY_SMIF_SFDP_SING_BYTE_00 (0x00U) /**< The SFDP Signature byte 0x00. Should be "S" */
#define CY_SMIF_SFDP_SING_BYTE_01 (0x01U) /**< The SFDP Signature byte 0x01. Should be "F" */
#define CY_SMIF_SFDP_SING_BYTE_02 (0x02U) /**< The SFDP Signature byte 0x02. Should be "D" */
#define CY_SMIF_SFDP_SING_BYTE_03 (0x03U) /**< The SFDP Signature byte 0x03. Should be "P" */
#define CY_SMIF_SFDP_MINOR_REV (0x04U) /**< The SFDP Header byte 0x04. Defines the JEDEC JESD216 Revision */
#define CY_SMIF_SFDP_MAJOR_REV (0x05U) /**< The SFDP Header byte 0x05. Defines the SFDP Major Revision */
#define CY_SMIF_SFDP_MAJOR_REV_1 (0x01U) /**< The SFDP Major Revision is 1 */
#define CY_SMIF_SFDP_JEDEC_REV_B (0x06U) /**< The JEDEC JESD216 Revision is B */
#define CY_SMIF_SFDP_PARAM_TABLE_PTR (0x0CU) /**< Specifies the start of the JEDEC Basic Flash
* Parameter Table in the SFDP structure
*/
#define CY_SMIF_SFDP_THREE_BYTES_ADDR_CODE (0x00U) /**< Code for the SFDP Address Bytes Number 3 */
#define CY_SMIF_SFDP_THREE_OR_FOUR_BYTES_ADDR_CODE (0x01U) /**< Code for the SFDP Address Bytes Number 3 or 4 */
#define CY_SMIF_SFDP_FOUR_BYTES_ADDR_CODE (0x02U) /**< Code for the SFDP Address Bytes Number 4 */
#define CY_SMIF_THREE_BYTES_ADDR (0x03U) /**< The address Bytes Number is 3 */
#define CY_SMIF_FOUR_BYTES_ADDR (0x04U) /**< The address Bytes Number is 4 */
#define CY_SMIF_READ_MODE_BYTE (0x5AU) /**< The mode byte for the SMIF read */
#define CY_SMIF_WR_STS_REG1_CMD (0x01U) /**< The write status register 1 command */
#define CY_SMIF_SINGLE_PROGRAM_CMD (0x02U) /**< The command for a single SMIF program */
#define CY_SMIF_SINGLE_READ_CMD (0x03U) /**< The command for a single SMIF read */
#define CY_SMIF_WR_DISABLE_CMD (0x04U) /**< The Write Disable command */
#define CY_SMIF_RD_STS_REG1_CMD (0x05U) /**< The read status register 1 command */
#define CY_SMIF_WR_ENABLE_CMD (0x06U) /**< The Write Enable command */
#define CY_SMIF_RD_STS_REG2_T1_CMD (0x35U) /**< The read status register 2 type 1 command */
#define CY_SMIF_WR_STS_REG2_CMD (0x3EU) /**< The write status register 2 command */
#define CY_SMIF_RD_STS_REG2_T2_CMD (0x3FU) /**< The read status register 2 type 2 command */
#define CY_SMIF_CHIP_ERASE_CMD (0x60U) /**< The Chip Erase command */
#define CY_SMIF_QE_BIT_STS_REG2_T1 (0x02U) /**< The QE bit is in status register 2 type 1.
* It should be written as the second byte.
*/
#define CY_SMIF_SFDP_ERASE_TIME_1MS (1U) /**< Units of Erase Typical Time in ms */
#define CY_SMIF_SFDP_ERASE_TIME_16MS (16U) /**< Units of Erase Typical Time in ms */
#define CY_SMIF_SFDP_ERASE_TIME_128MS (128U) /**< Units of Erase Typical Time in ms */
#define CY_SMIF_SFDP_ERASE_TIME_1S (1000U) /**< Units of Erase Typical Time in ms */
#define CY_SMIF_SFDP_CHIP_ERASE_TIME_16MS (16U) /**< Units of Chip Erase Typical Time in ms */
#define CY_SMIF_SFDP_CHIP_ERASE_TIME_256MS (256U) /**< Units of Chip Erase Typical Time in ms */
#define CY_SMIF_SFDP_CHIP_ERASE_TIME_4S (4000U) /**< Units of Chip Erase Typical Time in ms */
#define CY_SMIF_SFDP_CHIP_ERASE_TIME_64S (64000U) /**< Units of Chip Erase Typical Time in ms */
#define CY_SMIF_SFDP_PROG_TIME_8US (8U) /**< Units of Page Program Typical Time in us */
#define CY_SMIF_SFDP_PROG_TIME_64US (64U) /**< Units of Page Program Typical Time in us */
#define CY_SMIF_SFDP_UNIT_0 (0U) /**< Units of Basic Flash Parameter Table Time Parameters */
#define CY_SMIF_SFDP_UNIT_1 (1U) /**< Units of Basic Flash Parameter Table Time Parameters */
#define CY_SMIF_SFDP_UNIT_2 (2U) /**< Units of Basic Flash Parameter Table Time Parameters */
#define CY_SMIF_SFDP_UNIT_3 (3U) /**< Units of Basic Flash Parameter Table Time Parameters */
#define CY_SMIF_STS_REG_BUSY_MASK (0x01U) /**< The busy mask for the status registers */
#define CY_SMIF_NO_COMMAND_OR_MODE (0xFFFFFFFFUL) /**< No command or mode present */
#define CY_SMIF_SFDP_QER_0 (0x00UL) /**< The quad Enable Requirements case 0 */
#define CY_SMIF_SFDP_QER_1 (0x01UL) /**< The quad Enable Requirements case 1 */
#define CY_SMIF_SFDP_QER_2 (0x02UL) /**< The quad Enable Requirements case 2 */
#define CY_SMIF_SFDP_QER_3 (0x03UL) /**< The quad Enable Requirements case 3 */
#define CY_SMIF_SFDP_QER_4 (0x04UL) /**< The quad Enable Requirements case 4 */
#define CY_SMIF_SFDP_QER_5 (0x05UL) /**< The quad Enable Requirements case 5 */
#define CY_SMIF_SFDP_QE_BIT_1_OF_SR_2 (0x02UL) /**< The QE is bit 1 of the status register 2 */
#define CY_SMIF_SFDP_QE_BIT_6_OF_SR_1 (0x40UL) /**< The QE is bit 6 of the status register 1 */
#define CY_SMIF_SFDP_QE_BIT_7_OF_SR_2 (0x80UL) /**< The QE is bit 7 of the status register 2 */
#define CY_SMIF_SFDP_BFPT_BYTE_02 (0x02U) /**< The byte 0x02 of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_04 (0x04U) /**< The byte 0x04 of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_08 (0x08U) /**< The byte 0x08 of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_09 (0x09U) /**< The byte 0x09 of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_0A (0x0AU) /**< The byte 0x0A of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_0B (0x0BU) /**< The byte 0x0B of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_0C (0x0CU) /**< The byte 0x0C of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_0D (0x0DU) /**< The byte 0x0D of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_0E (0x0EU) /**< The byte 0x0E of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_0F (0x0FU) /**< The byte 0x0F of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_1C (0x1CU) /**< The byte 0x1C of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_1D (0x1DU) /**< The byte 0x1D of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_28 (0x28U) /**< The byte 0x28 of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_BYTE_3A (0x3AU) /**< The byte 0x3A of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_SFDP_BFPT_ERASE_BYTE (36U) /**< The byte 36 of the JEDEC Basic Flash Parameter Table */
#define CY_SMIF_JEDEC_BFPT_10TH_DWORD (9U) /**< Offset to JEDEC Basic Flash Parameter Table: 10th DWORD */
#define CY_SMIF_JEDEC_BFPT_11TH_DWORD (10U) /**< Offset to JEDEC Basic Flash Parameter Table: 11th DWORD */
/* ---------------------------- 1st DWORD ---------------------------- */
#define CY_SMIF_SFDP_FAST_READ_1_1_4_Pos (6UL) /**< The SFDP 1-1-4 fast read support (Bit 6) */
#define CY_SMIF_SFDP_FAST_READ_1_1_4_Msk (0x40UL) /**< The SFDP 1-1-4 fast read support (Bitfield-Mask: 0x01) */
#define CY_SMIF_SFDP_FAST_READ_1_4_4_Pos (5UL) /**< The SFDP 1-4-4 fast read support (Bit 5) */
#define CY_SMIF_SFDP_FAST_READ_1_4_4_Msk (0x20UL) /**< The SFDP 1-4-4 fast read support (Bitfield-Mask: 0x01) */
#define CY_SMIF_SFDP_FAST_READ_1_2_2_Pos (4UL) /**< The SFDP 1-2-2 fast read support (Bit 4) */
#define CY_SMIF_SFDP_FAST_READ_1_2_2_Msk (0x10UL) /**< The SFDP 1-2-2 fast read support (Bitfield-Mask: 0x01) */
#define CY_SMIF_SFDP_ADDRESS_BYTES_Pos (1UL) /**< The SFDP number of address bytes (Bit 1) */
#define CY_SMIF_SFDP_ADDRESS_BYTES_Msk (0x06UL) /**< The SFDP number of address bytes (Bitfield-Mask: 0x03) */
#define CY_SMIF_SFDP_FAST_READ_1_1_2_Pos (0UL) /**< The SFDP 1-1-2 fast read support (Bit 0) */
#define CY_SMIF_SFDP_FAST_READ_1_1_2_Msk (0x01UL) /**< The SFDP 1-1-2 fast read support (Bitfield-Mask: 0x01) */
/* ---------------------------- 2nd DWORD ---------------------------- */
#define CY_SMIF_SFDP_SIZE_ABOVE_4GB_Msk (0x80000000UL) /**< Flash memory density bit define if it >= 4 Gbit or <= 2Gbit*/
/* ---------------------------- 3rd DWORD ---------------------------- */
#define CY_SMIF_SFDP_1_4_4_DUMMY_CYCLES_Pos (0UL) /**< The SFDP number of 1-4-4 fast read dummy cycles (Bit 0) */
#define CY_SMIF_SFDP_1_4_4_DUMMY_CYCLES_Msk (0x1FUL) /**< The SFDP number of 1-4-4 fast read dummy cycles (Bitfield-Mask: 0x1F) */
#define CY_SMIF_SFDP_1_4_4_MODE_CYCLES_Pos (5UL) /**< The SFDP number of 1-4-4 fast read mode cycles (Bit 5) */
#define CY_SMIF_SFDP_1_4_4_MODE_CYCLES_Msk (0xE0UL) /**< The SFDP number of 1-4-4 fast read mode cycles (Bitfield-Mask: 0x07) */
#define CY_SMIF_SFDP_1_1_4_DUMMY_CYCLES_Pos (0UL) /**< The SFDP number of 1-1-4 fast read dummy cycles (Bit 0) */
#define CY_SMIF_SFDP_1_1_4_DUMMY_CYCLES_Msk (0x1FUL) /**< The SFDP number of 1-1-4 fast read dummy cycles (Bitfield-Mask: 0x1F) */
#define CY_SMIF_SFDP_1_1_4_MODE_CYCLES_Pos (5UL) /**< The SFDP number of 1-1-4 fast read mode cycles (Bit 5) */
#define CY_SMIF_SFDP_1_1_4_MODE_CYCLES_Msk (0xE0UL) /**< The SFDP number of 1-1-4 fast read mode cycles (Bitfield-Mask: 0x07) */
/* ---------------------------- 4th DWORD ---------------------------- */
#define CY_SMIF_SFDP_1_1_2_DUMMY_CYCLES_Pos (0UL) /**< The SFDP number of 1_1_2 fast read dummy cycles (Bit 0) */
#define CY_SMIF_SFDP_1_1_2_DUMMY_CYCLES_Msk (0x1FUL) /**< The SFDP number of 1_1_2 fast read dummy cycles (Bitfield-Mask: 0x1F) */
#define CY_SMIF_SFDP_1_1_2_MODE_CYCLES_Pos (5UL) /**< The SFDP number of 1_1_2 fast read mode cycles (Bit 5) */
#define CY_SMIF_SFDP_1_1_2_MODE_CYCLES_Msk (0xE0UL) /**< The SFDP number of 1_1_2 fast read mode cycles (Bitfield-Mask: 0x07) */
#define CY_SMIF_SFDP_1_2_2_DUMMY_CYCLES_Pos (0UL) /**< The SFDP number of 1_2_2 fast read dummy cycles (Bit 0) */
#define CY_SMIF_SFDP_1_2_2_DUMMY_CYCLES_Msk (0x1FUL) /**< The SFDP number of 1_2_2 fast read dummy cycles (Bitfield-Mask: 0x1F) */
#define CY_SMIF_SFDP_1_2_2_MODE_CYCLES_Pos (5UL) /**< The SFDP number of 1_2_2 fast read mode cycles (Bit 5) */
#define CY_SMIF_SFDP_1_2_2_MODE_CYCLES_Msk (0xE0UL) /**< The SFDP number of 1_2_2 fast read mode cycles (Bitfield-Mask: 0x07) */
/* ---------------------------- 10th DWORD --------------------------- */
#define CY_SMIF_SFDP_ERASE_T1_COUNT_Pos (4UL) /**< Erase Type 1 Erase, Typical time: count (Bits 8:4) */
#define CY_SMIF_SFDP_ERASE_T1_COUNT_Msk (0x1F0UL) /**< Erase Type 1 Erase, Typical time: count (Bitfield-Mask ) */
#define CY_SMIF_SFDP_ERASE_T1_UNITS_Pos (9UL) /**< Erase Type 1 Erase, Typical time: units (Bits 10:9) */
#define CY_SMIF_SFDP_ERASE_T1_UNITS_Msk (0x600UL) /**< Erase Type 1 Erase, Typical time: units (Bitfield-Mask ) */
#define CY_SMIF_SFDP_ERASE_MUL_COUNT_Pos (0UL) /**< Multiplier from typical erase time to maximum erase time (Bits 3:0) */
#define CY_SMIF_SFDP_ERASE_MUL_COUNT_Msk (0x0FUL) /**< Multiplier from typical erase time to maximum erase time (Bitfield-Mask ) */
/* ---------------------------- 11th DWORD --------------------------- */
#define CY_SMIF_SFDP_PAGE_SIZE_Pos (4UL) /**< The SFDP page size (Bit 4) */
#define CY_SMIF_SFDP_PAGE_SIZE_Msk (0xF0UL) /**< The SFDP page size (Bitfield-Mask: 0x0F) */
#define CY_SMIF_SFDP_PAGE_PROG_COUNT_Pos (8UL) /**< The SFDP Chip Page Program Typical time: count (Bits 12:8) */
#define CY_SMIF_SFDP_PAGE_PROG_COUNT_Msk (0x1F00UL) /**< The SFDP Chip Page Program Typical time: count (Bitfield-Mask)*/
#define CY_SMIF_SFDP_PAGE_PROG_UNITS_Pos (13UL) /**< The SFDP Chip Page Program Typical time: units (Bit 13) */
#define CY_SMIF_SFDP_PAGE_PROG_UNITS_Msk (0x2000UL) /**< The SFDP Chip Page Program Typical time: units (Bitfield-Mask)*/
#define CY_SMIF_SFDP_CHIP_ERASE_COUNT_Pos (24UL) /**< The SFDP Chip Erase Typical time: count (Bits 28:24) */
#define CY_SMIF_SFDP_CHIP_ERASE_COUNT_Msk (0x1F000000UL) /**< The SFDP Chip Erase Typical time: count (Bitfield-Mask) */
#define CY_SMIF_SFDP_CHIP_ERASE_UNITS_Pos (29UL) /**< The SFDP Chip Erase Typical time: units (Bits 29:30) */
#define CY_SMIF_SFDP_CHIP_ERASE_UNITS_Msk (0x60000000UL) /**< The SFDP Chip Erase Typical time: units (Bitfield-Mask) */
#define CY_SMIF_SFDP_PROG_MUL_COUNT_Pos (0UL) /**< Multiplier from typical time to max time for Page or byte program (Bits 3:0) */
#define CY_SMIF_SFDP_PROG_MUL_COUNT_Msk (0x0FUL) /**< Multiplier from typical time to max time for Page or byte program (Bitfield-Mask) */
/* ---------------------------- 15th DWORD --------------------------- */
#define CY_SMIF_SFDP_QE_REQUIREMENTS_Pos (4UL) /**< The SFDP quad enable requirements field (Bit 4) */
#define CY_SMIF_SFDP_QE_REQUIREMENTS_Msk (0x70UL) /**< The SFDP quad enable requirements field (Bitfield-Mask: 0x07) */
/** \cond INTERNAL */
#define CY_SMIF_BYTES_IN_WORD (4U)
#define CY_SMIF_BITS_IN_BYTE (8U)
#define CY_SMIF_BITS_IN_BYTE_ABOVE_4GB (3U) /** density of memory above 4GBit stored as poser of 2 */
#define CY_SMIF_MEM_ADDR_VALID(addr, size) (0U == ((addr)%(size))) /* This address must be a multiple of the SMIF XIP memory size */
#define CY_SMIF_MEM_MAPPED_SIZE_VALID(size) (((size) >= 0x10000U) && (0U == ((size)&((size)-1U))) ) /* must be a power of 2 and greater or equal than 64 KB */
#define CY_SMIF_MEM_ADDR_SIZE_VALID(addrSize) ((0U < (addrSize)) && ((addrSize) <= 4U))
/** \endcond*/
/** \} group_smif_macros_sfdp */
/**
* \addtogroup group_smif_data_structures_memslot
* \{
*/
/** This command structure is used to store the Read/Write command
* configuration. */
typedef struct
{
uint32_t command; /**< The 8-bit command. This value is 0xFFFFFFFF when there is no command present */
cy_en_smif_txfr_width_t cmdWidth; /**< The width of the command transfer */
cy_en_smif_txfr_width_t addrWidth; /**< The width of the address transfer */
uint32_t mode; /**< The 8-bit mode byte. This value is 0xFFFFFFFF when there is no mode present */
cy_en_smif_txfr_width_t modeWidth; /**< The width of the mode transfer */
uint32_t dummyCycles; /**< The number of the dummy cycles. A zero value suggests no dummy cycles */
cy_en_smif_txfr_width_t dataWidth; /**< The width of the data transfer */
} cy_stc_smif_mem_cmd_t;
/**
*
* This configuration structure of the SMIF memory device is used to store
* device-specific parameters.
* These parameters are used to set up the memory mode initialization and the
* memory API.
*/
typedef struct
{
uint32_t numOfAddrBytes; /**< This specifies the number of address bytes used by the
* memory slave device, valid values 1-4 */
uint32_t memSize; /**< The size of the memory */
cy_stc_smif_mem_cmd_t* readCmd; /**< This specifies the Read command */
cy_stc_smif_mem_cmd_t* writeEnCmd; /**< This specifies the Write Enable command */
cy_stc_smif_mem_cmd_t* writeDisCmd; /**< This specifies the Write Disable command */
cy_stc_smif_mem_cmd_t* eraseCmd; /**< This specifies the Erase command */
uint32_t eraseSize; /**< This specifies the sector size of each Erase */
cy_stc_smif_mem_cmd_t* chipEraseCmd; /**< This specifies the Chip Erase command */
cy_stc_smif_mem_cmd_t* programCmd; /**< This specifies the Program command */
uint32_t programSize; /**< This specifies the page size for programming */
cy_stc_smif_mem_cmd_t* readStsRegWipCmd; /**< This specifies the command to read the WIP-containing status register */
cy_stc_smif_mem_cmd_t* readStsRegQeCmd; /**< This specifies the command to read the QE-containing status register */
cy_stc_smif_mem_cmd_t* writeStsRegQeCmd; /**< This specifies the command to write into the QE-containing status register */
cy_stc_smif_mem_cmd_t* readSfdpCmd; /**< This specifies the read SFDP command */
uint32_t stsRegBusyMask; /**< The Busy mask for the status registers */
uint32_t stsRegQuadEnableMask; /**< The QE mask for the status registers */
uint32_t eraseTime; /**< Max time for erase type 1 cycle time in ms */
uint32_t chipEraseTime; /**< Max time for chip erase cycle time in ms */
uint32_t programTime; /**< Max time for page program cycle time in us */
} cy_stc_smif_mem_device_cfg_t;
/**
*
* This SMIF memory configuration structure is used to store the memory configuration for the memory mode of operation.
* This data structure is stored in a fixed location in the flash. The data structure is required
* for the initialization of the SMIF in the SystemInit.
*/
typedef struct
{
/** Determines the slave select where the memory device is placed */
cy_en_smif_slave_select_t slaveSelect;
/** Determines if the device is memory-mapped, enables the Autodetect
* using the SFDP, enables the write capability, or enables the crypto
* support for this memory slave */
uint32_t flags;
/** The data-line selection options for a slave device */
cy_en_smif_data_select_t dataSelect;
/** The base address the memory slave is mapped to in the PSoC memory map.
* This address must be a multiple of the SMIF XIP memory size/capacity. The
* SMIF XIP memory region should NOT overlap with other memory regions
* (with exception to dual quad mode). Valid when the memory-mapped mode is
* enabled.
*/
uint32_t baseAddress;
/** The size/capacity allocated in the PSoC memory map for the memory slave
* device. The capacity is allocated from the base address. The capacity
* must be a power of 2 and greater or equal than 64 KB. Valid when
* memory-mapped mode is enabled
*/
uint32_t memMappedSize;
/** Defines if this memory device is one of the devices in the dual quad SPI
* configuration. Equals the sum of the slave-slot numbers. */
uint32_t dualQuadSlots;
cy_stc_smif_mem_device_cfg_t* deviceCfg; /**< The configuration of the device */
} cy_stc_smif_mem_config_t;
/**
*
* This SMIF memory configuration structure is used to store the memory configuration for the memory mode of operation.
* This data structure is stored in a fixed location in the flash. The data structure is required
* for the initialization of the SMIF in the SystemInit.
*/
typedef struct
{
uint32_t memCount; /**< The number of SMIF memory defined */
cy_stc_smif_mem_config_t** memConfig; /**< The pointer to the array of the memory configuration structures of size Memory_count */
uint32_t majorVersion; /**< The version of the SMIF driver */
uint32_t minorVersion; /**< The version of the SMIF Driver */
} cy_stc_smif_block_config_t;
/** \} group_smif_data_structures_memslot */
/**
* \addtogroup group_smif_mem_slot_functions
* \{
*/
cy_en_smif_status_t Cy_SMIF_Memslot_Init(SMIF_Type *base,
cy_stc_smif_block_config_t * const blockConfig,
cy_stc_smif_context_t *context);
void Cy_SMIF_Memslot_DeInit(SMIF_Type *base);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdWriteEnable( SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdWriteDisable(SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
cy_stc_smif_context_t const *context);
bool Cy_SMIF_Memslot_IsBusy(SMIF_Type *base, cy_stc_smif_mem_config_t *memDevice,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_QuadEnable(SMIF_Type *base,
cy_stc_smif_mem_config_t *memDevice,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdReadSts(SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
uint8_t *status, uint8_t command,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdWriteSts(SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
void const *status, uint8_t command,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdChipErase(SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdSectorErase(SMIF_Type *base,
cy_stc_smif_mem_config_t *memDevice,
uint8_t const *sectorAddr,
cy_stc_smif_context_t const *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdProgram(SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
uint8_t const *addr,
uint8_t *writeBuff,
uint32_t size,
cy_smif_event_cb_t cmdCmpltCb,
cy_stc_smif_context_t *context);
cy_en_smif_status_t Cy_SMIF_Memslot_CmdRead(SMIF_Type *base,
cy_stc_smif_mem_config_t const *memDevice,
uint8_t const *addr,
uint8_t *readBuff,
uint32_t size,
cy_smif_event_cb_t cmdCmpltCb,
cy_stc_smif_context_t *context);
cy_en_smif_status_t Cy_SMIF_Memslot_SfdpDetect(SMIF_Type *base,
cy_stc_smif_mem_device_cfg_t *device,
cy_en_smif_slave_select_t slaveSelect,
cy_en_smif_data_select_t dataSelect,
cy_stc_smif_context_t *context);
/** \} group_smif_mem_slot_functions */
#if defined(__cplusplus)
}
#endif
#endif /* (CY_SMIF_MEMORYSLOT_H) */
/* [] END OF FILE */

View File

@ -0,0 +1,102 @@
/***************************************************************************//**
* \file cy_sysanalog.c
* \version 1.0
*
* Provides the public functions for the API for the SAR driver.
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_sysanalog.h"
#if defined(__cplusplus)
extern "C" {
#endif
/* Configure the AREF to use the local Vref and local IZTAT. Can be used with \ref Cy_SysAnalog_Init. */
const cy_stc_sysanalog_config_t Cy_SysAnalog_Fast_Local =
{
/*.startup */ CY_SYSANALOG_STARTUP_FAST,
/*.iztat */ CY_SYSANALOG_IZTAT_SOURCE_LOCAL,
/*.vref */ CY_SYSANALOG_VREF_SOURCE_LOCAL_1_2V,
/*.deepSleep */ CY_SYSANALOG_DEEPSLEEP_DISABLE,
/*.enable */ true,
};
/* Configure the AREF to use the SRSS Vref and SRSS IZTAT. Can be used with \ref Cy_SysAnalog_Init. */
const cy_stc_sysanalog_config_t Cy_SysAnalog_Fast_SRSS =
{
/*.startup */ CY_SYSANALOG_STARTUP_FAST,
/*.iztat */ CY_SYSANALOG_IZTAT_SOURCE_SRSS,
/*.vref */ CY_SYSANALOG_VREF_SOURCE_SRSS,
/*.deepSleep */ CY_SYSANALOG_DEEPSLEEP_DISABLE,
/*.enable */ true,
};
/* Configure the AREF to use the external Vref and local IZTAT. Can be used with \ref Cy_SysAnalog_Init. */
const cy_stc_sysanalog_config_t Cy_SysAnalog_Fast_External =
{
/*.startup */ CY_SYSANALOG_STARTUP_FAST,
/*.iztat */ CY_SYSANALOG_IZTAT_SOURCE_LOCAL,
/*.vref */ CY_SYSANALOG_VREF_SOURCE_EXTERNAL,
/*.deepSleep */ CY_SYSANALOG_DEEPSLEEP_DISABLE,
/*.enable */ true,
};
/*******************************************************************************
* Function Name: Cy_SysAnalog_Init
****************************************************************************//**
*
* Initialize the AREF configuration register.
*
* \param config
* Pointer to structure containing configuration data. See \ref cy_stc_sysanalog_config_t
*
* \return cy_en_sysanalog_status_t
* - CY_SYSANALOG_SUCCESS: initialization complete
* - CY_SYSANALOG_BAD_PARAM: input pointers are null, initialization incomplete
*
*******************************************************************************/
cy_en_sysanalog_status_t Cy_SysAnalog_Init(const cy_stc_sysanalog_config_t *config)
{
CY_ASSERT_L1(NULL != config);
cy_en_sysanalog_status_t result;
uint32_t ctrlReg = CY_SYSANALOG_DEINIT;
if (NULL == config)
{
result = CY_SYSANALOG_BAD_PARAM;
}
else
{
CY_ASSERT_L3(CY_SYSANALOG_STARTUP(config->startup));
CY_ASSERT_L3(CY_SYSANALOG_DEEPSLEEP(config->deepSleep));
CY_ASSERT_L3(CY_SYSANALOG_VREF(config->vref));
CY_ASSERT_L3(CY_SYSANALOG_IZTAT(config->iztat));
ctrlReg = (uint32_t) config->startup \
| CY_SYSANALOG_DEFAULT_BIAS_SCALE \
| (uint32_t) config->iztat \
| (uint32_t) config->vref \
| (uint32_t) config->deepSleep \
| ((uint32_t) config->enable << PASS_AREF_AREF_CTRL_ENABLED_Pos);
PASS_AREF->AREF_CTRL = ctrlReg;
result = CY_SYSANALOG_SUCCESS;
}
return result;
}
#if defined(__cplusplus)
}
#endif
/* [] END OF FILE */

View File

@ -0,0 +1,561 @@
/***************************************************************************//**
* \file cy_sysanalog.h
* \version 1.0
*
* Header file for the system level analog reference driver.
*
********************************************************************************
* \copyright
* Copyright 2017, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
/**
* \defgroup group_sysanalog System Analog Reference Block (SysAnalog)
* \{
*
* This driver provides an interface for configuring the Analog Reference (AREF) block
* and querying the INTR_CAUSE register of the PASS.
*
* <b> AREF Block </b>
*
* - Generates a voltage reference (VREF) from one of three sources:
* - Local 1.2 V reference (<b>low noise, optimized for analog performance</b>)
* - Reference from the SRSS (high noise, not recommended for analog performance)
* - An external pin
* - Generates a 1 uA "zero dependency to absolute temperature" (IZTAT) current reference
* that is independent of temperature variations. It can come from one of two sources:
* - Local reference (<b>low noise, optimized for analog performance</b>)
* - Reference from the SRSS (high noise, not recommended for analog performance)
* - Generates a "proportional to absolute temperature" (IPTAT) current reference
* - Option to enable local references in Deep Sleep mode
*
* The locally generated references are the recommended sources for blocks in the PASS because
* they have tighter accuracy, temperature stability, and lower noise than the SRSS references.
*
* \image html aref_block_diagram.png
* \image latex aref_block_diagram.png
*
* The outputs of the AREF are consumed by multiple blocks in the PASS and by the CapSense (CSDv2) block.
* In some cases, these blocks have the option of using the references from the AREF. This selection would be
* in the respective drivers for these blocks. In some cases, these blocks require the references from the
* AREF to function.
*
* <table class="doxtable">
* <tr><th>AREF Output</th><th>\ref group_sar "SAR"</th><th>\ref group_ctdac "CTDAC"</th><th>\ref group_ctb "CTB"</th><th>CSDv2</th></tr>
* <tr>
* <td>VREF</td>
* <td>optional</td>
* <td>optional</td>
* <td>--</td>
* <td>optional</td>
* </tr>
* <tr>
* <td>IZTAT</td>
* <td><b>required</b></td>
* <td>--</td>
* <td>optional</td>
* <td>optional</td>
* </tr>
* <tr>
* <td>IPTAT</td>
* <td>--</td>
* <td>--</td>
* <td><b>required</b></td>
* <td>--</td>
* </tr>
* </table>
*
* <b> PASS INTR_CAUSE </b>
*
* This driver provides a function to query the INTR_CAUSE register of the PASS.
* There are two interrupts in the PASS:
*
* -# one global interrupt for all CTBs (up to 4)
* -# one global interrupt for all CTDACs (up to 4)
*
* Because the interrupts are global, the INTR_CAUSE register is needed to query which hardware instance
* triggered the interrupt.
*
* \section group_sysanalog_usage Usage
*
* <b> Initialization </b>
*
* To configure the AREF, call \ref Cy_SysAnalog_Init and provide a pointer
* to the configuration structure, \ref cy_stc_sysanalog_config_t. Three predefined structures
* are provided in this driver to cover a majority of use cases:
*
* - \ref Cy_SysAnalog_Fast_Local <b>(recommended for analog performance)</b>
* - \ref Cy_SysAnalog_Fast_SRSS
* - \ref Cy_SysAnalog_Fast_External
*
* <b> Enable </b>
*
* If the \ref cy_stc_sysanalog_config_t.enable field of the configuration structure is set to true,
* the hardware will be enabled after initialization.
* If set to false, a separate call to \ref Cy_SysAnalog_Enable is required to enable the hardware.
*
* <b> Deep Sleep Operation </b>
*
* The AREF current and voltage references can be enabled to operate in Deep Sleep mode
* with \ref Cy_SysAnalog_SetDeepSleepMode. There are four options for Deep Sleep operation:
*
* - \ref CY_SYSANALOG_DEEPSLEEP_DISABLE : Disable AREF IP block
* - \ref CY_SYSANALOG_DEEPSLEEP_IPTAT_1 : Enable IPTAT generator for fast wakeup from Deep Sleep mode. IPTAT outputs for CTBs are disabled.
* - \ref CY_SYSANALOG_DEEPSLEEP_IPTAT_2 : Enable IPTAT generator and IPTAT outputs for CTB
* - \ref CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF : Enable all generators and outputs: IPTAT, IZTAT, and VREF
*
* Recall that the CTB requires the IPTAT reference. For the CTB to operate at the 1 uA current mode in Deep Sleep mode,
* the AREF must be enabled for \ref CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF. For the CTB to operate at the 100 nA
* current mode in Deep Sleep mode, the AREF must be enabled for \ref CY_SYSANALOG_DEEPSLEEP_IPTAT_2 minimum. In this
* lower current mode, the AREF IPTAT must be redirected to the CTB IZTAT. See the high level function \ref
* Cy_CTB_SetCurrentMode in the CTB PDL driver.
*
* If the CTDAC is configured to use the VREF in Deep Sleep mode, the AREF must be enabled for \ref CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF.
*
* Note that the SRSS references are not available to the AREF in Deep Sleep mode. When operating
* in Deep Sleep mode, the local or external references must be selected.
*
* \section group_sysanalog_more_information More Information
*
* For more information on the AREF, refer to the technical reference manual (TRM).
*
* \section group_sysanalog_MISRA MISRA-C Compliance]
*
* This driver does not have any specific deviations.
*
* \section group_sysanalog_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_sysanalog_macros Macros
* \defgroup group_sysanalog_functions Functions
* \defgroup group_sysanalog_globals Global Variables
* \defgroup group_sysanalog_data_structures Data structures
* \defgroup group_sysanalog_enums Enumerated Types
*/
#if !defined(CY_SYSANALOG_H)
#define CY_SYSANALOG_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "cy_device_headers.h"
#include "syslib/cy_syslib.h"
#include "syspm/cy_syspm.h"
#ifndef CY_IP_MXS40PASS
#error "The SysAnalog driver is not supported on this device"
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_sysanalog_macros
* \{
*/
/** Driver major version */
#define CY_SYSANALOG_DRV_VERSION_MAJOR 1
/** Driver minor version */
#define CY_SYSANALOG_DRV_VERSION_MINOR 0
/** PASS driver identifier */
#define CY_SYSANALOG_ID CY_PDL_DRV_ID(0x17u)
/** \cond INTERNAL */
#define CY_SYSANALOG_DEINIT (0uL) /**< De-init value for PASS register */
#define CY_SYSANALOG_DEFAULT_BIAS_SCALE (1uL << PASS_AREF_AREF_CTRL_AREF_BIAS_SCALE_Pos) /**< Default AREF bias current scale of 250 nA */
/**< Macros for conditions used in CY_ASSERT calls */
#define CY_SYSANALOG_STARTUP(startup) (((startup) == CY_SYSANALOG_STARTUP_NORMAL) || ((startup) == CY_SYSANALOG_STARTUP_FAST))
#define CY_SYSANALOG_DEEPSLEEP(deepSleep) (((deepSleep) == CY_SYSANALOG_DEEPSLEEP_DISABLE) \
|| ((deepSleep) == CY_SYSANALOG_DEEPSLEEP_IPTAT_1) \
|| ((deepSleep) == CY_SYSANALOG_DEEPSLEEP_IPTAT_2) \
|| ((deepSleep) == CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF))
#define CY_SYSANALOG_VREF(vref) (((vref) == CY_SYSANALOG_VREF_SOURCE_SRSS) \
|| ((vref) == CY_SYSANALOG_VREF_SOURCE_LOCAL_1_2V) \
|| ((vref) == CY_SYSANALOG_VREF_SOURCE_EXTERNAL))
#define CY_SYSANALOG_IZTAT(iztat) (((iztat) == CY_SYSANALOG_IZTAT_SOURCE_SRSS) || ((iztat) == CY_SYSANALOG_IZTAT_SOURCE_LOCAL))
/** \endcond */
/** \} group_sysanalog_macros */
/** \addtogroup group_sysanalog_enums
* \{
*/
/******************************************************************************
* Enumerations
*****************************************************************************/
/** The AREF status/error code definitions */
typedef enum
{
CY_SYSANALOG_SUCCESS = 0x00uL, /**< Successful */
CY_SYSANALOG_BAD_PARAM = CY_SYSANALOG_ID | CY_PDL_STATUS_ERROR | 0x01uL /**< Invalid input parameters */
}cy_en_sysanalog_status_t;
/** Aref startup timing modes
*
* The AREF block supports a fast 10 us startup time with a noise trade off.
* This fast startup time is during wakeup from Deep Sleep mode only.
* To achieve the fast startup from Deep Sleep mode, the IPTAT must be enabled in Deep Sleep mode
* (see \ref cy_en_sysanalog_deep_sleep_t).
*
* The fast startup is the recommended mode.
*/
typedef enum
{
CY_SYSANALOG_STARTUP_NORMAL = 0u, /**< Normal startup with nominal noise */
CY_SYSANALOG_STARTUP_FAST = 1u << PASS_AREF_AREF_CTRL_AREF_MODE_Pos /**< Fast startup from Deep Sleep mode with high noise */
}cy_en_sysanalog_startup_t;
/** AREF voltage reference sources
*
* The voltage reference can come from three sources:
* - the locally generated 1.2 V reference
* - the SRSS which provides a 0.8 V reference (not available in Deep Sleep mode)
* - an external device pin
*/
typedef enum
{
CY_SYSANALOG_VREF_SOURCE_SRSS = 0u, /**< Use 0.8 V Vref from SRSS. Low accuracy high noise source that is not intended for analog subsystems. */
CY_SYSANALOG_VREF_SOURCE_LOCAL_1_2V = 1u << PASS_AREF_AREF_CTRL_VREF_SEL_Pos, /**< Use locally generated 1.2 V Vref */
CY_SYSANALOG_VREF_SOURCE_EXTERNAL = 2u << PASS_AREF_AREF_CTRL_VREF_SEL_Pos /**< Use externally supplied Vref */
}cy_en_sysanalog_vref_source_t;
/** AREF IZTAT sources
*
* The AREF generates a 1 uA "Zero dependency To Absolute Temperature" (IZTAT) current reference
* that is independent of temperature variations. It can come from one of two sources:
* - Local reference (1 uA)
* - Reference from the SRSS (250 nA that is gained by 4. Not available in Deep Sleep mode)
*/
typedef enum
{
CY_SYSANALOG_IZTAT_SOURCE_SRSS = 0u, /**< Use 250 nA IZTAT from SRSS and gain by 4 to output 1 uA*/
CY_SYSANALOG_IZTAT_SOURCE_LOCAL = 1u << PASS_AREF_AREF_CTRL_IZTAT_SEL_Pos /**< Use locally generated 1 uA IZTAT */
}cy_en_sysanalog_iztat_source_t;
/** AREF Deep Sleep mode
*
* Configure what part of the AREF block is enabled in Deep Sleep mode.
* - Disable AREF IP block
* - Enable IPTAT generator for fast wakeup from Deep Sleep mode.
* IPTAT outputs for CTBs are disabled.
* - Enable IPTAT generator and IPTAT outputs for CTB
* - Enable all generators and outputs: IPTAT, IZTAT, and VREF
*/
typedef enum
{
CY_SYSANALOG_DEEPSLEEP_DISABLE = 0u, /**< Disable AREF IP block */
CY_SYSANALOG_DEEPSLEEP_IPTAT_1 = PASS_AREF_AREF_CTRL_DEEPSLEEP_ON_Msk | \
(1uL << PASS_AREF_AREF_CTRL_DEEPSLEEP_MODE_Pos), /**< Enable IPTAT generator for fast wakeup from Deep Sleep mode
IPTAT outputs for CTBs are disabled. */
CY_SYSANALOG_DEEPSLEEP_IPTAT_2 = PASS_AREF_AREF_CTRL_DEEPSLEEP_ON_Msk | \
(2uL << PASS_AREF_AREF_CTRL_DEEPSLEEP_MODE_Pos), /**< Enable IPTAT generator and IPTAT outputs for CTB */
CY_SYSANALOG_DEEPSLEEP_IPTAT_IZTAT_VREF = PASS_AREF_AREF_CTRL_DEEPSLEEP_ON_Msk | \
(3uL << PASS_AREF_AREF_CTRL_DEEPSLEEP_MODE_Pos) /**< Enable all generators and outputs: IPTAT, IZTAT, and VREF */
}cy_en_sysanalog_deep_sleep_t;
/** Interrupt cause sources
*
* There are two interrupts in the PASS:
* -# one global interrupt for all CTBs
* -# one global interrupt for all CTDACs
*
* A device could potentially have more than one instance of each IP block,
* CTB or CTDAC. To find out which instance
* caused the interrupt, call \ref Cy_SysAnalog_GetIntrCause and compare the returned
* result with one of these enum values.
*/
typedef enum
{
CY_SYSANALOG_INTR_CAUSE_CTB0 = PASS_INTR_CAUSE_CTB0_INT_Msk, /**< Interrupt cause mask for CTB0 */
CY_SYSANALOG_INTR_CAUSE_CTB1 = PASS_INTR_CAUSE_CTB1_INT_Msk, /**< Interrupt cause mask for CTB1 */
CY_SYSANALOG_INTR_CAUSE_CTB2 = PASS_INTR_CAUSE_CTB2_INT_Msk, /**< Interrupt cause mask for CTB2 */
CY_SYSANALOG_INTR_CAUSE_CTB3 = PASS_INTR_CAUSE_CTB3_INT_Msk, /**< Interrupt cause mask for CTB3 */
CY_SYSANALOG_INTR_CAUSE_CTDAC0 = PASS_INTR_CAUSE_CTDAC0_INT_Msk, /**< Interrupt cause mask for CTDAC0 */
CY_SYSANALOG_INTR_CAUSE_CTDAC1 = PASS_INTR_CAUSE_CTDAC1_INT_Msk, /**< Interrupt cause mask for CTDAC1 */
CY_SYSANALOG_INTR_CAUSE_CTDAC2 = PASS_INTR_CAUSE_CTDAC2_INT_Msk, /**< Interrupt cause mask for CTDAC2 */
CY_SYSANALOG_INTR_CAUSE_CTDAC3 = PASS_INTR_CAUSE_CTDAC3_INT_Msk /**< Interrupt cause mask for CTDAC3 */
}cy_en_sysanalog_intr_cause_t;
/** \} group_sysanalog_enums */
/** \addtogroup group_sysanalog_data_structures
* \{
*/
/***************************************
* Configuration Structures
***************************************/
/** Structure to configure the entire AREF block */
typedef struct
{
cy_en_sysanalog_startup_t startup; /**< AREF normal or fast start */
cy_en_sysanalog_iztat_source_t iztat; /**< AREF 1uA IZTAT source: Local or SRSS */
cy_en_sysanalog_vref_source_t vref; /**< AREF Vref: Local, SRSS, or external pin */
cy_en_sysanalog_deep_sleep_t deepSleep; /**< AREF Deep Sleep mode */
bool enable; /**< Enable or disable PASS AREF clock */
}cy_stc_sysanalog_config_t;
/** \} group_sysanalog_data_structures */
/** \addtogroup group_sysanalog_globals
* \{
*/
/***************************************
* Global Constants
***************************************/
/** Configure the AREF to use the local Vref and local IZTAT. Can be used with \ref Cy_SysAnalog_Init.
* Other configuration options are set to:
* - .startup = CY_PASS_AREF_MODE_FAST
* - .deepSleep = CY_PASS_AREF_DEEPSLEEP_DISABLE
* - .enable = true
*/
extern const cy_stc_sysanalog_config_t Cy_SysAnalog_Fast_Local;
/** Configure the AREF to use the SRSS Vref and SRSS IZTAT. Can be used with \ref Cy_SysAnalog_Init.
* Other configuration options are set to:
* - .startup = CY_PASS_AREF_MODE_FAST
* - .deepSleep = CY_PASS_AREF_DEEPSLEEP_DISABLE
* - .enable = true
*/
extern const cy_stc_sysanalog_config_t Cy_SysAnalog_Fast_SRSS;
/** Configure the AREF to use the external Vref and local IZTAT. Can be used with \ref Cy_SysAnalog_Init.
* Other configuration options are set to:
* - .startup = CY_PASS_AREF_MODE_FAST
* - .deepSleep = CY_PASS_AREF_DEEPSLEEP_DISABLE
* - .enable = true
*/
extern const cy_stc_sysanalog_config_t Cy_SysAnalog_Fast_External;
/** \} group_sysanalog_globals */
/** \addtogroup group_sysanalog_functions
* \{
*/
/***************************************
* Function Prototypes
***************************************/
cy_en_sysanalog_status_t Cy_SysAnalog_Init(const cy_stc_sysanalog_config_t *config);
__STATIC_INLINE void Cy_SysAnalog_DeInit(void);
__STATIC_INLINE uint32_t Cy_SysAnalog_GetIntrCause(void);
__STATIC_INLINE void Cy_SysAnalog_SetDeepSleepMode(cy_en_sysanalog_deep_sleep_t deepSleep);
__STATIC_INLINE cy_en_sysanalog_deep_sleep_t Cy_SysAnalog_GetDeepSleepMode(void);
__STATIC_INLINE void Cy_SysAnalog_Enable(void);
__STATIC_INLINE void Cy_SysAnalog_Disable(void);
__STATIC_INLINE void Cy_SysAnalog_SetArefMode(cy_en_sysanalog_startup_t startup);
__STATIC_INLINE void Cy_SysAnalog_VrefSelect(cy_en_sysanalog_vref_source_t vref);
__STATIC_INLINE void Cy_SysAnalog_IztatSelect(cy_en_sysanalog_iztat_source_t iztat);
/*******************************************************************************
* Function Name: Cy_SysAnalog_DeInit
****************************************************************************//**
*
* Reset AREF configuration back to power on reset defaults.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_DeInit(void)
{
PASS_AREF->AREF_CTRL = CY_SYSANALOG_DEINIT;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_GetIntrCause
****************************************************************************//**
*
* Return the PASS interrupt cause register value.
*
* There are two interrupts in the PASS:
* -# A global interrupt for all CTBs (up to 4)
* -# A global interrupt for all CTDACs (up to 4)
*
* Compare this returned value with the enum values in \ref cy_en_sysanalog_intr_cause_t
* to determine which block caused/triggered the interrupt.
*
* \return uint32_t
* Interrupt cause register value.
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_SysAnalog_GetIntrCause(void)
{
return PASS->INTR_CAUSE;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_SetDeepSleepMode
****************************************************************************//**
*
* Set what parts of the AREF are enabled in Deep Sleep mode.
* - Disable AREF IP block
* - Enable IPTAT generator for fast wakeup from Deep Sleep mode.
* IPTAT outputs for CTBs are disabled.
* - Enable IPTAT generator and IPTAT outputs for CTB
* - Enable all generators and outputs: IPTAT, IZTAT, and VREF
*
* Note that the SRSS references are not available to the AREF in Deep Sleep mode. When operating
* in Deep Sleep mode, the local or external references must be selected.
*
* \param deepSleep
* value from enum \ref cy_en_sysanalog_deep_sleep_t
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_SetDeepSleepMode(cy_en_sysanalog_deep_sleep_t deepSleep)
{
CY_ASSERT_L3(CY_SYSANALOG_DEEPSLEEP(deepSleep));
PASS_AREF->AREF_CTRL = (PASS_AREF->AREF_CTRL & ~(PASS_AREF_AREF_CTRL_DEEPSLEEP_ON_Msk | PASS_AREF_AREF_CTRL_DEEPSLEEP_MODE_Msk)) | \
(uint32_t) deepSleep;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_GetDeepSleepMode
****************************************************************************//**
*
* Return Deep Sleep mode configuration as set by \ref Cy_SysAnalog_SetDeepSleepMode
*
* \return cy_en_sysanalog_deep_sleep_t
*
*******************************************************************************/
__STATIC_INLINE cy_en_sysanalog_deep_sleep_t Cy_SysAnalog_GetDeepSleepMode(void)
{
return (cy_en_sysanalog_deep_sleep_t) (uint32_t) (PASS_AREF->AREF_CTRL & (PASS_AREF_AREF_CTRL_DEEPSLEEP_ON_Msk | PASS_AREF_AREF_CTRL_DEEPSLEEP_MODE_Msk));
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_Enable
****************************************************************************//**
*
* Enable the AREF hardware block.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_Enable(void)
{
PASS_AREF->AREF_CTRL |= PASS_AREF_AREF_CTRL_ENABLED_Msk;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_Disable
****************************************************************************//**
*
* Disable the AREF hardware block.
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_Disable(void)
{
PASS_AREF->AREF_CTRL &= ~PASS_AREF_AREF_CTRL_ENABLED_Msk;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_SetArefMode
****************************************************************************//**
*
* Set the AREF start up mode from Deep Sleep mode.
* The AREF can start up in a normal or fast mode. If fast start up
* is desired, the AREF must be enabled in Deep Sleep mode with the IPTAT
* generator enabled. See \ref Cy_SysAnalog_SetDeepSleepMode.
*
* \param startup
* Value from enum \ref cy_en_sysanalog_startup_t
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_SetArefMode(cy_en_sysanalog_startup_t startup)
{
CY_ASSERT_L3(CY_SYSANALOG_STARTUP(startup));
PASS_AREF->AREF_CTRL = (PASS_AREF->AREF_CTRL & ~PASS_AREF_AREF_CTRL_AREF_MODE_Msk) | (uint32_t) startup;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_VrefSelect
****************************************************************************//**
*
* Set the source for the Vref. The Vref can come from:
* - the locally generated 1.2 V reference
* - the SRSS, which provides a 0.8 V reference (not available to the AREF in Deep Sleep mode)
* - an external device pin
*
* The locally generated reference has higher accuracy, more stability over temperature,
* and lower noise than the SRSS reference.
*
* \param vref
* Value from enum \ref cy_en_sysanalog_vref_source_t
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_VrefSelect(cy_en_sysanalog_vref_source_t vref)
{
CY_ASSERT_L3(CY_SYSANALOG_VREF(vref));
PASS_AREF->AREF_CTRL = (PASS_AREF->AREF_CTRL & ~PASS_AREF_AREF_CTRL_VREF_SEL_Msk) | (uint32_t) vref;
}
/*******************************************************************************
* Function Name: Cy_SysAnalog_IztatSelect
****************************************************************************//**
*
* Set the source for the 1 uA IZTAT. The IZTAT can come from:
* - the locally generated IZTAT
* - the SRSS (not available to the AREF in Deep Sleep mode)
*
* The locally generated reference has higher accuracy, more stability over temperature,
* an lower noise than the SRSS reference.
*
* \param iztat
* Value from enum \ref cy_en_sysanalog_iztat_source_t
*
* \return None
*
*******************************************************************************/
__STATIC_INLINE void Cy_SysAnalog_IztatSelect(cy_en_sysanalog_iztat_source_t iztat)
{
CY_ASSERT_L3(CY_SYSANALOG_IZTAT(iztat));
PASS_AREF->AREF_CTRL = (PASS_AREF->AREF_CTRL & ~PASS_AREF_AREF_CTRL_IZTAT_SEL_Msk) | (uint32_t) iztat;
}
/** \} group_sysanalog_functions */
#if defined(__cplusplus)
}
#endif
#endif /** !defined(CY_SYSANALOG_H) */
/** \} group_sysanalog */
/* [] END OF FILE */

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