Newer
Older
mbed-os / targets / TARGET_Cypress / TARGET_PSOC6 / mtb-hal-cat1 / include / cyhal_scb_common.h
@Dustin Crossman Dustin Crossman on 4 Jun 2021 7 KB Fix file modes.
/***************************************************************************//**
* \file cyhal_scb_common.h
*
* \brief
* Provides a struct definitions for configuration resources in the SCB (UART, I2C, SPI).
*
********************************************************************************
* \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.
*******************************************************************************/

/** \cond INTERNAL */
/**
 * \addtogroup group_hal_impl_scb_common SCB Common Functionality
 * \ingroup group_hal_impl
 * \{
 * Code shared between the SCB resources (UART, I2C, and SPI).
 */

#pragma once

#include "cy_device.h"
#include "cy_pdl.h"
#include "cyhal_utils.h"

#if defined(__cplusplus)
extern "C" {
#endif

#if defined(CY_IP_MXSCB_INSTANCES)
#if defined(CY_DEVICE_PSOC6A256K)
//Special case for 256k device which has 6 SCBs numbered 0, 1, 2, 4, 5, 6
#define _SCB_ARRAY_SIZE                 (CY_IP_MXSCB_INSTANCES + 1)
#else
#define _SCB_ARRAY_SIZE                 (CY_IP_MXSCB_INSTANCES)
#endif /* CY_DEVICE_PSOC6A256K */
#elif defined(CY_IP_M0S8SCB_INSTANCES)
#define _SCB_ARRAY_SIZE                 (CY_IP_M0S8SCB_INSTANCES)
#endif /* CY_IP_MXSCB_INSTANCES */

/** \addtogroup group_hal_results_scb SCB HAL Results
 *  SCB specific return codes
 *  \ingroup group_hal_results
 *  \{ *//**

 */
/** Bad argument */
#define CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT                     \
    (CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_IMPL_SCB, 0))

/**
 * \}
 */

/** SCB FIFO type */
typedef enum
{
    CYHAL_SCB_FIFO_RX, //!< Set RX FIFO level
    CYHAL_SCB_FIFO_TX, //!< Set TX FIFO level
} cyhal_scb_fifo_type_t;

/** Enum of possible output signals from an SCB */
typedef enum
{
    CYHAL_SCB_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED, //!< Output the RX FIFO signal which is triggered when the receive FIFO has more entries than the configured level.
    CYHAL_SCB_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED, //!< Output the TX FIFO signal which is triggered when the transmit FIFO has less entries than the configured level.
} cyhal_scb_output_t;

/** The start address of the SCB blocks */
extern CySCB_Type* const _CYHAL_SCB_BASE_ADDRESSES[_SCB_ARRAY_SIZE];
/** The interrupt number of the SCB blocks. */
extern const IRQn_Type _CYHAL_SCB_IRQ_N[_SCB_ARRAY_SIZE];


/** Get the SCB block corresponding to an IRQn.
 *
 * @param[in] irqn The IRQn to get the corresponding block from
 * @return         The corresponding SCB block
 */
uint8_t cyhal_scb_get_block_from_irqn(IRQn_Type irqn);

/** Get the SCB object corresponding to the currently running ISR.
 *
 * @return A pointer to the SCB object corresponding to the currently running ISR.
 */
void *_cyhal_scb_get_irq_obj(void);

/** Sets the desired clocks & data rate to achieve the specified frequency
 * @param[in] base      The I2C object to configure the peri divider for
 * @param[in] block_num The SCB block number being used
 * @praam[in] clock     The clock configuration to apply
 * @praam[in] freq      The desired frequency
 * @param[in] is_slave  Is this an I2C slave (true) or master (false)
 * @return The achieved data rate in Hz, or 0 if there was an error.
 */
uint32_t _cyhal_i2c_set_peri_divider(CySCB_Type *base, uint32_t block_num, cyhal_clock_t *clock, uint32_t freq, bool is_slave);

/** Find an available SCB instance that matches 'pin'.
 * @param pin Pin
 * @param pin_map Pin mapping array
 * @param count Number of entries in pin_map
 * @return Pin map pointer or NULL if none found
 */
const cyhal_resource_pin_mapping_t* _cyhal_scb_find_map(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map,
                    size_t count, const cyhal_resource_inst_t *block_res);

/** Sets a threshold level for a FIFO that will generate an interrupt and a
 * trigger output. The RX FIFO interrupt and trigger will be activated when
 * the receive FIFO has more entries than the threshold. The TX FIFO interrupt
 * and trigger will be activated when the transmit FIFO has less entries than
 * the threshold.
 *
 * @param[in]  base       SCB base
 * @param[in]  type       FIFO type to set level for
 * @param[in]  level      Level threshold to set
 * @return The status of the level set
 * */
cy_rslt_t _cyhal_scb_set_fifo_level(CySCB_Type *base, cyhal_scb_fifo_type_t type, uint16_t level);

/** Enables the specified output signal from an scb.
 *
 * @param[in]  base       SCB base
 * @param[in]  resource   SCB resource
 * @param[in]  output     Which output signal to enable
 * @param[out] source     Pointer to user-allocated source signal object which
 * will be initialized by enable_output. source should be passed to
 * (dis)connect_digital functions to (dis)connect the associated endpoints.
 * @return The status of the output enable
 * */
cy_rslt_t _cyhal_scb_enable_output(CySCB_Type *base, cyhal_resource_inst_t resource, cyhal_scb_output_t output, cyhal_source_t *source);

/** Disables the specified output signal from an scb
 *
 * @param[in]  base       SCB base
 * @param[in]  resource   SCB resource
 * @param[in]  output     Which output signal to disable
 * @return The status of the output disable
 * */
cy_rslt_t _cyhal_scb_disable_output(CySCB_Type *base, cyhal_resource_inst_t resource, cyhal_scb_output_t output);

#define _CYHAL_SCB_FIND_MAP(pin, pin_map) \
                    _cyhal_scb_find_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t), NULL)
#define _CYHAL_SCB_FIND_MAP_BLOCK(pin, pin_map, block) \
                    _cyhal_scb_find_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t), block)

/**
 * Function pointer to determine a specific scb instance can is ready for low power transition.
 */
typedef bool (*cyhal_scb_instance_pm_callback)(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode);

/** Updates data in cyhal_scb_config_structs and cyhal_scb_config_modes_t structs based on block_num proveded
 * @param[in] block_num Index of SCB block which data to be updated
 * @param[in] obj       SCB-based driver object (cyhal_uart_t, cyhal_spi_t, cyhal_i2c_t or cyhal_ezi2c_t)
 */
void _cyhal_scb_update_instance_data(uint8_t block_num, void *obj, cyhal_scb_instance_pm_callback pm_callback);

/** Whether power management transition is pending and communication should be suspended. */
bool _cyhal_scb_pm_transition_pending(void);

/** Finds the en_clk_dst_t clock connection index for provided SCB block number
 *
 * @param[in] block_num Index of SCB block
 * @return en_clk_dst_t clock connection index
 */
static inline en_clk_dst_t _cyhal_scb_get_clock_index(uint32_t block_num)
{
    en_clk_dst_t clk;
    // PSOC6A256K does not have SCB 3
    #if defined(CY_DEVICE_PSOC6A256K)
    if (block_num < 3)
        clk = (en_clk_dst_t)((uint32_t)PCLK_SCB0_CLOCK + block_num);
    else
        clk = (en_clk_dst_t)((uint32_t)PCLK_SCB0_CLOCK + block_num -1);
    #else
        clk = (en_clk_dst_t)((uint32_t)PCLK_SCB0_CLOCK + block_num);
    #endif
    return clk;
}

#if defined(__cplusplus)
}
#endif

/** \} group_hal_impl_scb_common */
/** \endcond */