Files
mbed-os/targets/TARGET_Cypress/TARGET_PSOC6/mtb-hal-cat1/source/cyhal_hwmgr.c
Beslan 0ef1717155
Some checks failed
Basic Checks / license-check (push) Has been cancelled
Basic Checks / include-check (push) Has been cancelled
Basic Checks / style-check (push) Has been cancelled
Basic Checks / docs-check (push) Has been cancelled
Basic Checks / python-tests (push) Has been cancelled
Basic Checks / pin-validation (push) Has been cancelled
Basic Checks / cmake-checks (push) Has been cancelled
Basic Checks / frozen-tools-check (push) Has been cancelled
Publish or Update docker image for head of branch / prepare-tags (push) Has been cancelled
Release or update docker image for a released mbed-os version / prepare-tags (push) Has been cancelled
Publish or Update docker image for head of branch / build-container (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/amd64) (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/arm64) (push) Has been cancelled
Publish or Update docker image for head of branch / deploy-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / build-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/amd64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/arm64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / deploy-container (push) Has been cancelled
Prune temporary docker images / prune-images (push) Has been cancelled
Mirror mbed-os-6.15.0
2026-07-10 18:42:39 +03:00

895 lines
34 KiB
C

/***************************************************************************//**
* \file cyhal_hwmgr.c
*
* \brief
* Provides a high level interface for managing hardware resources. This is
* used to track what hardware blocks are already being used so they are not over
* allocated.
*
********************************************************************************
* \copyright
* Copyright 2018-2021 Cypress Semiconductor Corporation
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "cyhal_hwmgr.h"
#include "cyhal_hwmgr_impl.h"
#include "cyhal_interconnect.h"
#include "cyhal_system.h"
#include "cmsis_compiler.h"
#include "cyhal_scb_common.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/*******************************************************************************
* Defines
*******************************************************************************/
#if defined(CY_IP_MXS40PASS_SAR_INSTANCES)
#define CY_BLOCK_COUNT_ADC (CY_IP_MXS40PASS_SAR_INSTANCES)
#elif defined (CY_IP_M0S8PASS4A_INSTANCES)
#define CY_BLOCK_COUNT_ADC (CY_IP_M0S8PASS4A_INSTANCES)
#else
#define CY_BLOCK_COUNT_ADC (0)
#endif
#if defined(CY_IP_MXBLESS_INSTANCES)
#define CY_BLOCK_COUNT_BLE CY_IP_MXBLESS_INSTANCES
#else
#define CY_BLOCK_COUNT_BLE (0)
#endif
#if defined(CY_IP_MXTTCANFD_INSTANCES)
#define CY_BLOCK_COUNT_CAN (CY_IP_MXTTCANFD_INSTANCES)
#if (CY_IP_MXTTCANFD_INSTANCES == 0)
#define CY_CHANNEL_COUNT_CAN (0u)
#elif (CY_IP_MXTTCANFD_INSTANCES == 1)
#define CY_CHANNEL_COUNT_CAN (CANFD_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 2)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 3)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 4)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 5)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 6)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 7)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 8)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR + CANFD7_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 9)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR + CANFD7_CAN_NR + CANFD8_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES == 10)
#define CY_CHANNEL_COUNT_CAN (CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR + CANFD7_CAN_NR + CANFD8_CAN_NR + CANFD9_CAN_NR)
#elif (CY_IP_MXTTCANFD_INSTANCES > 10)
#warning Unhandled CAN instance count
#endif
#elif defined(CY_IP_M0S8CAN_INSTANCES)
#define CY_BLOCK_COUNT_CAN (CY_IP_M0S8CAN_INSTANCES)
#define CY_CHANNEL_COUNT_CAN (1)
#else
#define CY_BLOCK_COUNT_CAN (0)
#define CY_CHANNEL_COUNT_CAN (0)
#endif
#if defined(COMPONENT_CAT1A)
// 12 dedicated = IMO, EXT, ILO, FLL, LF, Pump, BAK, Timer, AltSysTick, Slow, Fast, Peri
// 7 optional = ECO, ALTHF, ALTLF, PILO, WCO, MFO, MF
#define CY_CHANNEL_COUNT_CLOCK (12 + 7 + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + \
PERI_DIV_8_NR + PERI_DIV_16_NR + PERI_DIV_16_5_NR + PERI_DIV_24_5_NR)
#elif defined(COMPONENT_CAT2)
// 7 dedicated = IMO, EXT, ILO, HF, LF, PUMP, SYSCLK
// 3 optional = ECO, WCO, PLL, PLLSEL, WDCSEL
#define CY_CHANNEL_COUNT_CLOCK (7 + 5 + PERI_PCLK_CLOCK_NR)
#endif
#if defined(CY_IP_MXCRYPTO_INSTANCES)
#define CY_BLOCK_COUNT_CRYPTO (CY_IP_MXCRYPTO_INSTANCES)
#elif defined(CPUSS_CRYPTO_PRESENT)
#define CY_BLOCK_COUNT_CRYPTO (CPUSS_CRYPTO_PRESENT)
#else
#define CY_BLOCK_COUNT_CRYPTO (0)
#endif
#if defined(CY_IP_MXS40PASS_CTDAC_INSTANCES)
#define CY_BLOCK_COUNT_DAC (CY_IP_MXS40PASS_CTDAC_INSTANCES)
#else
#define CY_BLOCK_COUNT_DAC (0)
#endif
#if defined(CY_IP_M4CPUSS_DMAC_INSTANCES)
#define CY_BLOCK_COUNT_DMA (CY_IP_M4CPUSS_DMAC_INSTANCES)
#define CY_CHANNEL_COUNT_DMA (CPUSS_DMAC_CH_NR)
#elif defined(CPUSS_CPUMEMSS_DMAC_PRESENT)
#define CY_BLOCK_COUNT_DMA (CPUSS_CPUMEMSS_DMAC_PRESENT)
#define CY_CHANNEL_COUNT_DMA (CPUSS_DMAC_CH_NR)
#else
#define CY_BLOCK_COUNT_DMA (0)
#define CY_CHANNEL_COUNT_DMA (0)
#endif
#if defined(CY_IP_M4CPUSS_DMA_INSTANCES)
#define CY_BLOCK_COUNT_DW (CY_IP_M4CPUSS_DMA_INSTANCES)
#define CY_CHANNEL_COUNT_DW (CPUSS_DW0_CH_NR + CPUSS_DW1_CH_NR)
#else
#define CY_BLOCK_COUNT_DW (0)
#define CY_CHANNEL_COUNT_DW (0)
#endif
#if defined(IOSS_GPIO_GPIO_PORT_NR)
#define CY_BLOCK_COUNT_GPIO (IOSS_GPIO_GPIO_PORT_NR)
#define CY_CHANNEL_COUNT_GPIO (8 * IOSS_GPIO_GPIO_PORT_NR)
#else
#define CY_BLOCK_COUNT_GPIO (0)
#define CY_CHANNEL_COUNT_GPIO (0)
#endif
#if defined(CY_IP_MXAUDIOSS_INSTANCES)
#define CY_BLOCK_COUNT_I2S (CY_IP_MXAUDIOSS_INSTANCES)
#else
#define CY_BLOCK_COUNT_I2S (0)
#endif
#if defined(CY_IP_MXLCD_INSTANCES)
#define CY_BLOCK_COUNT_LCD (CY_IP_MXLCD_INSTANCES)
#elif defined(CY_IP_M0S8LCD_INSTANCES)
#define CY_BLOCK_COUNT_LCD (CY_IP_M0S8LCD_INSTANCES)
#else
#define CY_BLOCK_COUNT_LCD (0)
#endif
#if defined(CY_IP_MXLPCOMP_INSTANCES)
#define CY_BLOCK_COUNT_LPCOMP (2 * CY_IP_MXLPCOMP_INSTANCES)
#elif defined(CY_IP_M0S8LPCOMP_INSTANCES)
#define CY_BLOCK_COUNT_LPCOMP (2 * CY_IP_M0S8LPCOMP_INSTANCES)
#else
#define CY_BLOCK_COUNT_LPCOMP (0)
#endif
#if defined(PASS_NR_CTBS)
#define CY_BLOCK_COUNT_OPAMP (2 * PASS_NR_CTBS)
#else
#define CY_BLOCK_COUNT_OPAMP (0)
#endif
#if defined(CY_IP_MXAUDIOSS_INSTANCES)
#define CY_BLOCK_COUNT_PDMPCM (CY_IP_MXAUDIOSS_INSTANCES)
#else
#define CY_BLOCK_COUNT_PDMPCM (0)
#endif
#if defined(CY_IP_MXSMIF_INSTANCES)
#define CY_BLOCK_COUNT_QSPI (CY_IP_MXSMIF_INSTANCES)
#else
#define CY_BLOCK_COUNT_QSPI (0)
#endif
#if defined(CY_IP_MXS40SRSS_RTC_INSTANCES)
#define CY_BLOCK_COUNT_RTC (CY_IP_MXS40SRSS_RTC_INSTANCES)
#else
#define CY_BLOCK_COUNT_RTC (0)
#endif
#if defined(CY_IP_MXSCB_INSTANCES) || defined(CY_IP_M0S8SCB_INSTANCES)
#define CY_BLOCK_COUNT_SCB (_SCB_ARRAY_SIZE)
#else
#define CY_BLOCK_COUNT_SCB (0)
#endif
#if defined(CY_IP_MXSDHC_INSTANCES)
#define CY_BLOCK_COUNT_SDHC (CY_IP_MXSDHC_INSTANCES)
#else
#define CY_BLOCK_COUNT_SDHC (0)
#endif
#if defined(CY_IP_MXTCPWM_INSTANCES)
#define CY_BLOCK_COUNT_TCPWM CY_IP_MXTCPWM_INSTANCES
#if (CY_IP_MXTCPWM_VERSION == 1)
#if (CY_IP_MXTCPWM_INSTANCES == 0)
#define CY_CHANNEL_COUNT_TCPWM (0u)
#elif (CY_IP_MXTCPWM_INSTANCES == 1)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 2)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 3)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 4)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 5)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 6)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 7)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 8)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR + TCPWM7_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 9)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR + TCPWM7_CNT_NR + TCPWM8_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES == 10)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR + TCPWM7_CNT_NR + TCPWM8_CNT_NR + TCPWM9_CNT_NR)
#elif (CY_IP_MXTCPWM_INSTANCES > 10)
#warning Unhandled TCPWM instance count
#endif
#elif (CY_IP_MXTCPWM_VERSION == 2)
#if (CY_IP_MXTCPWM_INSTANCES == 1)
#if (TCPWM_GRP_NR == 0)
#define CY_CHANNEL_COUNT_TCPWM (0u)
#elif (TCPWM_GRP_NR == 1)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM_GRP_NR0_GRP_GRP_CNT_NR)
#elif (TCPWM_GRP_NR == 2)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR)
#elif (TCPWM_GRP_NR == 3)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR)
#elif (TCPWM_GRP_NR == 4)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR + TCPWM_GRP_NR3_GRP_GRP_CNT_NR)
#elif (TCPWM_GRP_NR > 4)
#warning Unhandled TCPWM instance count
#endif
#elif (CY_IP_MXTCPWM_INSTANCES > 1)
#warning Unhandled TCPWM instance count
#endif
#else
#warning Unrecognized TCPWM IP version
#endif
#elif defined(CY_IP_M0S8TCPWM_INSTANCES)
#define CY_BLOCK_COUNT_TCPWM (CY_IP_M0S8TCPWM_INSTANCES)
#if (CY_IP_M0S8TCPWM_INSTANCES == 0)
#define CY_CHANNEL_COUNT_TCPWM (0u)
#elif (CY_IP_M0S8TCPWM_INSTANCES == 1)
#define CY_CHANNEL_COUNT_TCPWM (TCPWM_CNT_NR)
#else
#warning Unhandled TCPWM instance count
#endif
#else
#define CY_BLOCK_COUNT_TCPWM (0)
#define CY_CHANNEL_COUNT_TCPWM (0)
#endif
#if defined(CY_IP_MXUDB_INSTANCES)
#define CY_BLOCK_COUNT_UDB CY_IP_MXUDB_INSTANCES
#else
#define CY_BLOCK_COUNT_UDB (0)
#endif
#if defined(CY_IP_MXUSBFS_INSTANCES)
#define CY_BLOCK_COUNT_USB CY_IP_MXUSBFS_INSTANCES
#else
#define CY_BLOCK_COUNT_USB (0)
#endif
#if defined(CY_IP_MXUSBPD_INSTANCES)
#define CY_BLOCK_COUNT_USBPD CY_IP_MXUSBPD_INSTANCES
#else
#define CY_BLOCK_COUNT_USBPD (0)
#endif
#if defined(CY_IP_MXS40SRSS_MCWDT_INSTANCES)
#define CY_BLOCK_COUNT_MCWDT CY_IP_MXS40SRSS_MCWDT_INSTANCES
#elif (defined(CY_IP_S8SRSSLT_INSTANCES) && defined(CY_IP_M0S8WCO))
#define CY_BLOCK_COUNT_MCWDT CY_IP_M0S8WCO_INSTANCES
#else
#define CY_BLOCK_COUNT_MCWDT (0)
#endif
/*
All resources have an offset and a size, offsets are stored in an array
Subsequent resource offset equals the preceding offset + size
Offsets are bit indexes in the arrays that track used, configured etc.
Channel based resources have an extra array for block offsets
Note these are NOT offsets into the device's MMIO address space;
they are bit offsets into arrays that are internal to the HW mgr.
*/
#define CY_OFFSET_ADC 0
#define CY_SIZE_ADC CY_BLOCK_COUNT_ADC
#define CY_OFFSET_BLE (CY_OFFSET_ADC + CY_SIZE_ADC)
#define CY_SIZE_BLE CY_BLOCK_COUNT_BLE
#define CY_OFFSET_CAN (CY_OFFSET_BLE + CY_SIZE_BLE)
#define CY_SIZE_CAN CY_CHANNEL_COUNT_CAN
#define CY_OFFSET_CLOCK (CY_OFFSET_CAN + CY_SIZE_CAN)
#define CY_SIZE_CLOCK CY_CHANNEL_COUNT_CLOCK
#define CY_OFFSET_CRYPTO (CY_OFFSET_CLOCK + CY_SIZE_CLOCK)
#define CY_SIZE_CRYPTO CY_BLOCK_COUNT_CRYPTO
#define CY_OFFSET_DAC (CY_OFFSET_CRYPTO + CY_SIZE_CRYPTO)
#define CY_SIZE_DAC CY_BLOCK_COUNT_DAC
#define CY_OFFSET_DMA (CY_OFFSET_DAC + CY_SIZE_DAC)
#define CY_SIZE_DMA CY_CHANNEL_COUNT_DMA
#define CY_OFFSET_DW (CY_OFFSET_DMA + CY_SIZE_DMA)
#define CY_SIZE_DW CY_CHANNEL_COUNT_DW
#define CY_OFFSET_GPIO (CY_OFFSET_DW + CY_SIZE_DW)
#define CY_SIZE_GPIO CY_CHANNEL_COUNT_GPIO
#define CY_OFFSET_I2S (CY_OFFSET_GPIO + CY_SIZE_GPIO)
#define CY_SIZE_I2S CY_BLOCK_COUNT_I2S
#define CY_OFFSET_LCD (CY_OFFSET_I2S + CY_SIZE_I2S)
#define CY_SIZE_LCD CY_BLOCK_COUNT_LCD
#define CY_OFFSET_LPCOMP (CY_OFFSET_LCD + CY_SIZE_LCD)
#define CY_SIZE_LPCOMP CY_BLOCK_COUNT_LPCOMP
#define CY_OFFSET_LPTIMER (CY_OFFSET_LPCOMP + CY_SIZE_LPCOMP)
#define CY_SIZE_LPTIMER CY_BLOCK_COUNT_MCWDT
#define CY_OFFSET_OPAMP (CY_OFFSET_LPTIMER + CY_SIZE_LPTIMER)
#define CY_SIZE_OPAMP CY_BLOCK_COUNT_OPAMP
#define CY_OFFSET_PDMPCM (CY_OFFSET_OPAMP + CY_SIZE_OPAMP)
#define CY_SIZE_PDMPCM CY_BLOCK_COUNT_PDMPCM
#define CY_OFFSET_QSPI (CY_OFFSET_PDMPCM + CY_SIZE_PDMPCM)
#define CY_SIZE_QSPI CY_BLOCK_COUNT_QSPI
#define CY_OFFSET_RTC (CY_OFFSET_QSPI + CY_SIZE_QSPI)
#define CY_SIZE_RTC CY_BLOCK_COUNT_RTC
#define CY_OFFSET_SCB (CY_OFFSET_RTC + CY_SIZE_RTC)
#define CY_SIZE_SCB CY_BLOCK_COUNT_SCB
#define CY_OFFSET_SDHC (CY_OFFSET_SCB + CY_SIZE_SCB)
#define CY_SIZE_SDHC CY_BLOCK_COUNT_SDHC
#define CY_OFFSET_TCPWM (CY_OFFSET_SDHC + CY_SIZE_SDHC)
#define CY_SIZE_TCPWM CY_CHANNEL_COUNT_TCPWM
#define CY_OFFSET_UDB (CY_OFFSET_TCPWM + CY_SIZE_TCPWM)
#define CY_SIZE_UDB CY_BLOCK_COUNT_UDB
#define CY_OFFSET_USB (CY_OFFSET_UDB + CY_SIZE_UDB)
#define CY_SIZE_USB CY_BLOCK_COUNT_USB
#define CY_OFFSET_USBPD (CY_OFFSET_USB + CY_SIZE_USB)
#define CY_SIZE_USBPD CY_BLOCK_COUNT_USBPD
#define CY_TOTAL_ALLOCATABLE_ITEMS (CY_OFFSET_USBPD + CY_SIZE_USBPD)
#define CY_BYTE_NUM_SHIFT (3)
#define CY_BIT_NUM_MASK (0x07)
/*******************************************************************************
* Variables
*******************************************************************************/
#if defined(COMPONENT_CAT1A)
#define PERI_DIV_NR (PERI_DIV_8_NR + PERI_DIV_16_NR + PERI_DIV_16_5_NR + PERI_DIV_24_5_NR)
#if ((PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 18) >= 256)
#error "Too many clocks to use uint8_t as offset type"
#endif
/* The order of items here must match the order in cyhal_clock_impl.h
*
* Each entry in the array below is the prior entry plus the number of clocks that exist
* of the prior type. When there is only 1 clock (e.g: IMO/ECO) the next number is simply
* one higher than the previous value. When there are multiple clocks (e.g.: PathMux/PLL)
* the subsequent value is increased by the define that specifies how many clocks are
* actually present. */
static const uint8_t cyhal_block_offsets_clock[26] =
{
0, // 8-bit dividers
PERI_DIV_8_NR, // 16-bit dividers
PERI_DIV_8_NR + PERI_DIV_16_NR, // 16.5 bit dividers
PERI_DIV_8_NR + PERI_DIV_16_NR + PERI_DIV_16_5_NR, // 24.5 bit dividers
PERI_DIV_NR, // IMO
PERI_DIV_NR + 1, // ECO
PERI_DIV_NR + 2, // EXT
PERI_DIV_NR + 3, // ALTHF
PERI_DIV_NR + 4, // ALTLF
PERI_DIV_NR + 5, // ILO
PERI_DIV_NR + 6, // PILO
PERI_DIV_NR + 7, // WCO
PERI_DIV_NR + 8, // MFO
PERI_DIV_NR + 9, // PathMux
PERI_DIV_NR + SRSS_NUM_CLKPATH + 9, // FLL
PERI_DIV_NR + SRSS_NUM_CLKPATH + 10, // PLL
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + 10, // LF
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + 11, // MF
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + 12, // HF
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 12, // PUMP
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 13, // BAK
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 14, // TIMER
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 15, // AltSysTick
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 16, // Fast
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 17, // Peri
PERI_DIV_NR + SRSS_NUM_CLKPATH + SRSS_NUM_PLL + SRSS_NUM_HFROOT + 18, // Slow
};
#elif defined(COMPONENT_CAT2)
/* The order of items here must match the order in cyhal_clock_impl.h
*
* Each entry in the array below is the prior entry plus the number of clocks that exist
* of the prior type. When there is only 1 clock (e.g: IMO/ECO) the next number is simply
* one higher than the previous value. When there are multiple clocks (e.g.: PCLK)
* the subsequent value is increased by the define that specifies how many clocks are
* actually present. */
static const uint8_t cyhal_block_offsets_clock[16] =
{
0, // 8-bit dividers
PERI_PCLK_DIV_8_NR, // 16-bit dividers
PERI_PCLK_DIV_8_NR + PERI_PCLK_DIV_16_NR, // 16.5 bit dividers
PERI_PCLK_DIV_8_NR + PERI_PCLK_DIV_16_NR + PERI_PCLK_DIV_16_5_NR, // 24.5 bit dividers
PERI_PCLK_CLOCK_NR, // IMO
PERI_PCLK_CLOCK_NR + 1, // ECO
PERI_PCLK_CLOCK_NR + 2, // EXT
PERI_PCLK_CLOCK_NR + 3, // ILO
PERI_PCLK_CLOCK_NR + 4, // WCO
PERI_PCLK_CLOCK_NR + 5, // WDCSEL
PERI_PCLK_CLOCK_NR + 6, // PLLSEL
PERI_PCLK_CLOCK_NR + 7, // PLL
PERI_PCLK_CLOCK_NR + 8, // LF
PERI_PCLK_CLOCK_NR + 9, // HF
PERI_PCLK_CLOCK_NR + 10, // PUMP
PERI_PCLK_CLOCK_NR + 11, // SYS
};
#endif
static const uint8_t cyhal_block_offsets_dma[] =
{
0,
};
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
static const uint8_t cyhal_block_offsets_dw[] =
{
0,
CPUSS_DW0_CH_NR,
};
#endif
static const uint8_t cyhal_block_offsets_gpio[] =
{
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,
};
static const uint8_t cyhal_block_offsets_can[] =
{
#ifdef CY_IP_MXTTCANFD_INSTANCES
#if (CY_IP_MXTTCANFD_INSTANCES > 0)
0,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 1)
CANFD0_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 2)
CANFD0_CAN_NR + CANFD1_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 3)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 4)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 5)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 6)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 7)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 8)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR + CANFD7_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 9)
CANFD0_CAN_NR + CANFD1_CAN_NR + CANFD2_CAN_NR + CANFD3_CAN_NR + CANFD4_CAN_NR + CANFD5_CAN_NR + CANFD6_CAN_NR + CANFD7_CAN_NR + CANFD8_CAN_NR,
#endif
#if (CY_IP_MXTTCANFD_INSTANCES > 10)
#warning Unhandled CAN instance count
#endif
#else
0
#endif
};
static const uint8_t cyhal_block_offsets_tcpwm[] =
{
0,
#ifdef CY_IP_MXTCPWM_INSTANCES
#if CY_IP_MXTCPWM_VERSION == 1
#if (CY_IP_MXTCPWM_INSTANCES > 1)
TCPWM0_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 2)
TCPWM0_CNT_NR + TCPWM1_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 3)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 4)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 5)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 6)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 7)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 8)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR + TCPWM7_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 9)
TCPWM0_CNT_NR + TCPWM1_CNT_NR + TCPWM2_CNT_NR + TCPWM3_CNT_NR + TCPWM4_CNT_NR + TCPWM5_CNT_NR + TCPWM6_CNT_NR + TCPWM7_CNT_NR + TCPWM8_CNT_NR,
#endif
#if (CY_IP_MXTCPWM_INSTANCES > 10)
#warning Unhandled TCPWM instance count
#endif
#else // CY_IP_MXTCPWM_VERSION >= 2
#if (CY_IP_MXTCPWM_INSTANCES == 1)
#if (TCPWM_GRP_NR > 1)
TCPWM_GRP_NR0_GRP_GRP_CNT_NR,
#endif
#if (TCPWM_GRP_NR > 2)
TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR,
#endif
#if (TCPWM_GRP_NR > 3)
TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR,
#endif
#else
#warning Unhandled TCPWM instance count
#endif
#endif
#endif
};
static uint8_t cyhal_used[(CY_TOTAL_ALLOCATABLE_ITEMS + 7) / 8] = {0};
// Note: the ordering here needs to be parallel to that of cyhal_resource_t
static const uint16_t cyhal_resource_offsets[] =
{
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
CY_OFFSET_ADC,
CY_OFFSET_BLE,
CY_OFFSET_CAN,
CY_OFFSET_CLOCK, /* Placeholder for ClockPath which is deprecated */
CY_OFFSET_CLOCK,
CY_OFFSET_CRYPTO,
CY_OFFSET_DAC,
CY_OFFSET_DMA,
CY_OFFSET_DW,
CY_OFFSET_GPIO,
CY_OFFSET_I2S,
CY_OFFSET_LCD,
CY_OFFSET_LPCOMP,
CY_OFFSET_LPTIMER,
CY_OFFSET_OPAMP,
CY_OFFSET_PDMPCM,
CY_OFFSET_QSPI,
CY_OFFSET_RTC,
CY_OFFSET_SCB,
CY_OFFSET_SDHC,
CY_OFFSET_TCPWM,
CY_OFFSET_UDB,
CY_OFFSET_USB,
#elif defined(COMPONENT_CAT2)
CY_OFFSET_ADC,
CY_OFFSET_CAN,
CY_OFFSET_CLOCK,
CY_OFFSET_CRYPTO,
CY_OFFSET_DMA,
CY_OFFSET_GPIO,
CY_OFFSET_I2S,
CY_OFFSET_LCD,
CY_OFFSET_LPCOMP,
CY_OFFSET_LPTIMER,
CY_OFFSET_OPAMP,
CY_OFFSET_SCB,
CY_OFFSET_TCPWM,
CY_OFFSET_USB,
CY_OFFSET_USBPD,
#endif
};
static const uint32_t cyhal_has_channels =
(1 << CYHAL_RSC_CAN) |
(1 << CYHAL_RSC_CLOCK) |
(1 << CYHAL_RSC_DMA) |
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
(1 << CYHAL_RSC_DW) |
#endif
(1 << CYHAL_RSC_GPIO) |
(1 << CYHAL_RSC_TCPWM) ;
/*
* This function is designed to verify that the number of valid resources in the cyhal_resource_t
* enum and the number entries in the cyhal_resource_offsets array are identical. Any mismatch
* between the two will lead to runtime failures. This will produce a divide by 0 error if they
* get of of sync.
* NOTE: This function should never be called, it is only for a compile time error check
* NOTE: The Supress is to temporaraly disable the IAR warning about an uncalled function
*/
static inline void check_array_size(void) __attribute__ ((deprecated));
#if __ICCARM__
#pragma diag_suppress=Pe177
#elif __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#endif
static inline void check_array_size(void)
{
uint32_t dummy = 1 / (sizeof(cyhal_resource_offsets) == (sizeof(uint16_t) * CYHAL_RSC_INVALID));
(void)dummy;
}
#if __ICCARM__
#pragma diag_default=Pe177
#elif __clang__
#pragma clang diagnostic pop
#endif
/*******************************************************************************
* Utility helper functions
*******************************************************************************/
static inline uint16_t cyhal_uses_channels(cyhal_resource_t type)
{
return (cyhal_has_channels & (1 << type)) > 0;
}
static inline uint16_t cyhal_get_resource_offset(cyhal_resource_t type)
{
return cyhal_resource_offsets[type];
}
static inline const uint8_t* cyhal_get_block_offsets(cyhal_resource_t type)
{
switch (type)
{
case CYHAL_RSC_CAN:
return cyhal_block_offsets_can;
case CYHAL_RSC_CLOCK:
return cyhal_block_offsets_clock;
case CYHAL_RSC_DMA:
return cyhal_block_offsets_dma;
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
case CYHAL_RSC_DW:
return cyhal_block_offsets_dw;
#endif
case CYHAL_RSC_GPIO:
return cyhal_block_offsets_gpio;
case CYHAL_RSC_TCPWM:
return cyhal_block_offsets_tcpwm;
default:
CY_ASSERT(false);
return NULL;
}
}
// Gets the number of block offset entries, only valid for blocks which have channels.
static inline uint8_t cyhal_get_block_offset_length(cyhal_resource_t type)
{
switch (type)
{
case CYHAL_RSC_CAN:
return sizeof(cyhal_block_offsets_can)/sizeof(cyhal_block_offsets_can[0]);
case CYHAL_RSC_CLOCK:
return sizeof(cyhal_block_offsets_clock)/sizeof(cyhal_block_offsets_clock[0]);
case CYHAL_RSC_DMA:
return sizeof(cyhal_block_offsets_dma)/sizeof(cyhal_block_offsets_dma[0]);
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
case CYHAL_RSC_DW:
return sizeof(cyhal_block_offsets_dw)/sizeof(cyhal_block_offsets_dw[0]);
#endif
case CYHAL_RSC_GPIO:
return sizeof(cyhal_block_offsets_gpio)/sizeof(cyhal_block_offsets_gpio[0]);
case CYHAL_RSC_TCPWM:
return sizeof(cyhal_block_offsets_tcpwm)/sizeof(cyhal_block_offsets_tcpwm[0]);
default:
CY_ASSERT(false);
return 0;
}
}
static cy_rslt_t cyhal_get_bit_position(cyhal_resource_t type, uint8_t block, uint8_t channel, uint16_t* bitPosition)
{
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
/* For backwards compatability. */
if (type == CYHAL_RSC_CLKPATH)
{
channel = block;
block = CYHAL_CLOCK_BLOCK_PATHMUX;
type = CYHAL_RSC_CLOCK;
}
#endif
uint16_t offsetRsc = cyhal_get_resource_offset(type);
// Offset that is one past the beginning of the next resource (or one past the end of the array).
// Our offset must be strictly less than that
uint16_t offsetEndOfRsc = ((1u + type) < sizeof(cyhal_resource_offsets)/sizeof(cyhal_resource_offsets[0]))
? cyhal_get_resource_offset((cyhal_resource_t)(type + 1))
: CY_TOTAL_ALLOCATABLE_ITEMS;
if (cyhal_uses_channels(type))
{
const uint8_t* blockOffsets = cyhal_get_block_offsets(type);
*bitPosition = offsetEndOfRsc;
if (blockOffsets != NULL)
{
// Offset (from the beginning of the section for this block type) that is one past the end of
// the requested block index. The channel number must be strictly less than that.
uint16_t blocks = cyhal_get_block_offset_length(type);
if (block < blocks)
{
*bitPosition = offsetRsc + blockOffsets[block] + channel;
if ((block + 1) < blocks)
{
offsetEndOfRsc = offsetRsc + blockOffsets[block + 1];
}
}
}
}
else
{
*bitPosition = offsetRsc + block;
}
return (*bitPosition < offsetEndOfRsc)
? CY_RSLT_SUCCESS
: CYHAL_HWMGR_RSLT_ERR_INVALID;
}
static inline cy_rslt_t cyhal_is_set(const uint8_t* used, cyhal_resource_t type, uint8_t block, uint8_t channel, bool* isSet)
{
uint16_t bitPosition;
cy_rslt_t status = cyhal_get_bit_position(type, block, channel, &bitPosition);
if (status == CY_RSLT_SUCCESS)
{
uint8_t byte = (uint8_t)(bitPosition >> CY_BYTE_NUM_SHIFT);
uint8_t bit = bitPosition & CY_BIT_NUM_MASK;
*isSet = (used[byte] & (1 << bit));
}
return status;
}
static inline cy_rslt_t cyhal_set_bit(uint8_t* used, cyhal_resource_t type, uint8_t block, uint8_t channel)
{
uint16_t bitPosition;
cy_rslt_t status = cyhal_get_bit_position(type, block, channel, &bitPosition);
if (status == CY_RSLT_SUCCESS)
{
uint8_t byte = (uint8_t)(bitPosition >> CY_BYTE_NUM_SHIFT);
uint8_t bit = bitPosition & CY_BIT_NUM_MASK;
used[byte] |= (1 << bit);
}
return status;
}
static inline cy_rslt_t cyhal_clear_bit(uint8_t* used, cyhal_resource_t type, uint8_t block, uint8_t channel)
{
uint16_t bitPosition;
cy_rslt_t status = cyhal_get_bit_position(type, block, channel, &bitPosition);
if (status == CY_RSLT_SUCCESS)
{
uint8_t byte = (uint8_t)(bitPosition >> CY_BYTE_NUM_SHIFT);
uint8_t bit = bitPosition & CY_BIT_NUM_MASK;
used[byte] &= ~(1 << bit);
}
return status;
}
/*******************************************************************************
* Hardware Manager API
*******************************************************************************/
cy_rslt_t cyhal_hwmgr_init(void)
{
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_hwmgr_reserve(const cyhal_resource_inst_t* obj)
{
bool isSet;
uint32_t state = cyhal_system_critical_section_enter();
cy_rslt_t rslt = cyhal_is_set(cyhal_used, obj->type, obj->block_num, obj->channel_num, &isSet);
if (rslt == CY_RSLT_SUCCESS && isSet)
{
rslt = CYHAL_HWMGR_RSLT_ERR_INUSE;
}
if (rslt == CY_RSLT_SUCCESS)
{
rslt = cyhal_set_bit(cyhal_used, obj->type, obj->block_num, obj->channel_num);
}
cyhal_system_critical_section_exit(state);
return rslt;
}
void cyhal_hwmgr_free(const cyhal_resource_inst_t* obj)
{
uint32_t state = cyhal_system_critical_section_enter();
cy_rslt_t rslt = cyhal_clear_bit(cyhal_used, obj->type, obj->block_num, obj->channel_num);
CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
CY_ASSERT(CY_RSLT_SUCCESS == rslt);
cyhal_system_critical_section_exit(state);
}
cy_rslt_t _cyhal_hwmgr_allocate_with_connection(cyhal_resource_t type, const cyhal_source_t *src, const cyhal_dest_t *dest,
_cyhal_hwmgr_get_output_source_t get_src, _cyhal_hwmgr_get_input_dest_t get_dest, cyhal_resource_inst_t *obj)
{
uint16_t offsetStartOfRsc = cyhal_get_resource_offset(type);
uint16_t offsetEndOfRsc = ((1u + type) < sizeof(cyhal_resource_offsets)/sizeof(cyhal_resource_offsets[0]))
? cyhal_get_resource_offset((cyhal_resource_t)(type + 1))
: CY_TOTAL_ALLOCATABLE_ITEMS;
bool usesChannels = cyhal_uses_channels(type);
uint16_t count = offsetEndOfRsc - offsetStartOfRsc;
uint8_t block = 0;
uint8_t channel = 0;
for (uint16_t i = 0; i < count; i++)
{
bool valid = true;
if (NULL != src)
{
cyhal_dest_t destination = get_dest(block, channel);
valid = _cyhal_can_connect_signal(*src, destination);
}
if (valid && NULL != dest)
{
cyhal_source_t source = get_src(block, channel);
valid = _cyhal_can_connect_signal(source, *dest);
}
if (valid)
{
cyhal_resource_inst_t rsc = { type, block, channel };
if (CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(&rsc))
{
obj->type = type;
obj->block_num = block;
obj->channel_num = channel;
return CY_RSLT_SUCCESS;
}
}
if (usesChannels)
{
const uint8_t* blockOffsets = cyhal_get_block_offsets(type);
uint16_t blocks = cyhal_get_block_offset_length(type);
if ((block + 1) < blocks && blockOffsets[block + 1] <= (i + 1))
{
channel = 0;
do
{
block++;
}
while (block < blocks && blockOffsets[block] < (i + 1));
}
else
{
channel++;
}
}
else
{
block++;
}
}
return CYHAL_HWMGR_RSLT_ERR_NONE_FREE;
}
cy_rslt_t cyhal_hwmgr_allocate(cyhal_resource_t type, cyhal_resource_inst_t* obj)
{
return _cyhal_hwmgr_allocate_with_connection(type, NULL, NULL, NULL, NULL, obj);
}
#if defined(__cplusplus)
}
#endif