Update PSoC 6 HAL to v1.2.1

pull/12943/head
Kyle Kearney 2020-04-30 13:39:32 -07:00
parent f38e21fa6c
commit bff67a931f
114 changed files with 17818 additions and 9623 deletions

View File

@ -34,38 +34,49 @@
* limitations under the License.
*******************************************************************************/
/**
* \addtogroup group_hal_types HAL General Types/Macros
* This section documents the basic types and macros that are used by multiple HAL drivers.
*/
/**
* \addtogroup group_result Result Type
* \ingroup group_hal_types
*/
/**
* \addtogroup group_hal HAL Drivers
* This section documents the drivers which form the stable API of the Cypress HAL.
* In order to remain portable across platforms and HAL versions, applications should
* rely only on functionality documented in this section.
* \{
* \defgroup group_result Result Type
* \}
*/
#pragma once
#include "cyhal_modules.h"
#include "cyhal_general_types.h"
#include "cyhal_hw_types.h"
#include "cyhal_adc.h"
#include "cyhal_clock.h"
#include "cyhal_crc.h"
#include "cyhal_dac.h"
#include "cyhal_dma.h"
#include "cyhal_ezi2c.h"
#include "cyhal_flash.h"
#include "cyhal_gpio.h"
#include "cyhal_hwmgr.h"
#include "cyhal_i2c.h"
#include "cyhal_ezi2c.h"
#include "cyhal_i2s.h"
#include "cyhal_interconnect.h"
#include "cyhal_lptimer.h"
#include "cyhal_pdmpcm.h"
#include "cyhal_pwm.h"
#include "cyhal_qspi.h"
#include "cyhal_rtc.h"
#include "cyhal_sdhc.h"
#include "cyhal_sdio.h"
#include "cyhal_spi.h"
#include "cyhal_syspm.h"
#include "cyhal_system.h"
#include "cyhal_timer.h"
#include "cyhal_trng.h"

View File

@ -35,17 +35,31 @@
* of which can perform conversions on a different pin.
* See the device datasheet for details about which pins support ADC conversion.
*
* In order to use the ADC, first call cyhal_adc_init to initialize an ADC instance.
* Then call cyhal_adc_channel_init to initialize one or more channels associated with
* that instance.
* All channels are single-ended. The values returned by the read API are relative
* to the ADC's voltage range, which is device specific.
*
* All channels are single-ended.
* The values returned by the read API are relative to the ADC's voltage range, which
* is device specific.
* \section cyhal_adc_quickstart Quickstart
* Call \ref cyhal_adc_init to initialize an ADC instance by providing the ADC
* object (<b>obj</b>), input pin (<b>pin</b>) and clock (<b>clk</b>).<br> The input
* pin argument is just to signify which ADC instance to initialize. It does not
* actually reserve the pin or create an ADC channel for it. The clock parameter can
* be left NULL to use an available clock resource with a default frequency.<br>
* Use \ref cyhal_adc_channel_init to initialize one or more channels associated
* with that instance.<br>
* Use \ref cyhal_adc_read_u16 for reading the results.<br>
* See \ref subsection_adc_snippet_1.
*
* \defgroup group_hal_adc_common Common
* \defgroup group_hal_adc_functions ADC Functions
* \defgroup group_hal_adc_channel_functions ADC Channel Functions
* \note \ref cyhal_adc_read_u16 always returns a 16 bit value in the range
* 0x0000-0xFFFF. If the underlying hardware does not support 16 bit resolution the
* value is scaled linearly to cover the full 16 bits.
*
* \section subsection_adc_snippets Code snippets
* \subsection subsection_adc_snippet_1 Snippet 1: Simple ADC initialization and
* reading conversion result
* The following snippet initializes an ADC and one channel.
* One ADC conversion result is returned corresponding to the input at the specified
* pin.
* \snippet adc.c snippet_cyhal_adc_simple_init
*/
#pragma once
@ -54,36 +68,52 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name ADC Results
*/
/** Bad argument */
#define CYHAL_ADC_RSLT_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 0))
/** Failed to initialize ADC clock */
#define CYHAL_ADC_RSLT_FAILED_CLOCK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 1))
/** Failed to initialize ADC */
#define CYHAL_ADC_RSLT_FAILED_INIT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 2))
/** No channels available */
#define CYHAL_ADC_RSLT_NO_CHANNELS \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 3))
/**
* \} \}
*/
/** Maximum value that the ADC can return */
#define CYHAL_ADC_MAX_VALUE 0xFFFF
/** Bad argument */
#define CYHAL_ADC_RSLT_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 0))
/** Failed to initialize ADC clock */
#define CYHAL_ADC_RSLT_FAILED_CLOCK (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 1))
/** Failed to initialize ADC */
#define CYHAL_ADC_RSLT_FAILED_INIT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 2))
/** No channels available */
#define CYHAL_ADC_RSLT_NO_CHANNELS (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_ADC, 3))
/** Initialize ADC peripheral
*
* @param[out] obj The adc object to initialize
* @param[out] obj Pointer to an ADC object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] pin A pin corresponding to the ADC block to initialize
* Note: This pin is not reserved, it is just used to identify which ADC block to allocate.
* If multiple channels will be allocated for a single ADC instance, only one pin should be
* passed here; it does not matter which one. After calling this function once, call
* cyhal_adc_channel_init once for each pin whose value should be measured.
* @param[in] clk The clock to use can be shared, if not provided a new clock will be allocated
* @return The status of the init request
* @return The status of the init request. \ref CY_RSLT_SUCCESS is returned on success.
* On failure, a problem specific error code will be returned.
* This error could be from the HAL or lower level driver.<br>
* For all other return codes, please refer to device driver documentation available in the BSP landing page
*/
cy_rslt_t cyhal_adc_init(cyhal_adc_t *obj, cyhal_gpio_t pin, const cyhal_clock_divider_t *clk);
cy_rslt_t cyhal_adc_init(cyhal_adc_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk);
/** Uninitialize the ADC peripheral and cyhal_adc_t object
*
@ -97,7 +127,11 @@ void cyhal_adc_free(cyhal_adc_t *obj);
* @param[out] obj The adc channel object to initialize
* @param[in] adc The adc for which the channel should be initialized
* @param[in] pin The adc pin name
* @return The status of the init request
* @return The status of the init request. The status of the init request.
* \ref CY_RSLT_SUCCESS is returned on success.<br>
* On failure, a problem specific error code will be returned.
* This error could be from the HAL or lower level driver.<br>
* For all other return codes, please refer to device driver documentation available in the BSP landing page
*/
cy_rslt_t cyhal_adc_channel_init(cyhal_adc_channel_t *obj, cyhal_adc_t* adc, cyhal_gpio_t pin);
@ -110,12 +144,14 @@ void cyhal_adc_channel_free(cyhal_adc_channel_t *obj);
/** Read the value from ADC pin, represented as an unsigned 16bit value
* where 0x0000 represents the minimum value in the ADC's range, and 0xFFFF
* represents the maximum value in the ADC's range.
* Depending on the ADC speed this function may block for some time.
*
* @param[in] obj The ADC object
* @return An unsigned 16bit value representing the current input voltage
*/
uint16_t cyhal_adc_read_u16(const cyhal_adc_channel_t *obj);
#if defined(__cplusplus)
}
#endif

View File

@ -33,13 +33,13 @@ extern "C" {
* Initialize the programmable analog. This utilizes reference counting to avoid
* repeatedly initializing the analog subsystem when multiple analog blocks are in use
* */
void cyhal_analog_init();
void cyhal_analog_init(void);
/**
* Uninitialize the programmable analog. This utilizes reference counting to avoid
* disabling the analog subsystem until all blocks which require it have been freed.
*/
void cyhal_analog_free();
void cyhal_analog_free(void);
#if defined(__cplusplus)
}

View File

@ -0,0 +1,337 @@
/*******************************************************************************
* File Name: cyhal_clock.h
*
* Description:
* Provides a high level interface for interacting with the Clocks on the device.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
/**
* \addtogroup group_hal_clock Clock
* \ingroup group_hal
* \{
* Interface for getting and changing clock configuration.
*
* The clock driver is a single API designed to allow reading and configuring
* any clock in the system. The driver works the same to configure System clocks
* as it does for Peripheral clocks. It supports both a readonly mode where any
* number of items can get information about the clock. Alternatively, each
* clock can have a single owner that is able to adjust the configuration of the
* clock.
*
* This driver supports source clocks, clock dividers, and clock signal muxes.
* All clock objects support the get() functions. Only some clocks support
* setting specific attributes. Use the \ref cyhal_clock_get_features() function
* to determine which features are settable for a specific clock. Calling a set()
* function on a clock that does not support it will return an error.
*
* This driver makes no assumptions about how the device is currently configured.
* It can be used from a completely unconfigured system (eg: device just booted)
* to a fully pre-configured (eg: setup by the Device Configurator). The drivers
* query and modify the actual state of the hardware, there is no caching or
* remembering of state. To maximize portability of code, it is often convenient
* to place all system clock configuration into a Board Support Package (BSP) so
* the main application code is flexible and can port between devices.
*
* \ref cyhal_clock_get allows for getting access to a specific clock object.
* This clock reference can be used to call any of the get() functions at any
* time. If a clock needs to be modified, either \ref cyhal_clock_allocate or
* \ref cyhal_clock_init must be called to obtain a lock on the clock object
* and to ensure that nothing else in the application is currently using it or
* assuming its configuration is stable. If exclusive control of a clock is no
* longer needed \ref cyhal_clock_free can be called to release it. This will
* remove the lock allowing something else in the system to potentially modify
* its state.
*
* \ref cyhal_clock_init and \ref cyhal_clock_allocate are very similar. They both
* reserve a clock object that can then be modified. The difference between them
* is the argument that is passed in. \ref cyhal_clock_init takes a specific
* instance that it will attemt to reserve. \ref cyhal_clock_allocate takes in a
* type of clock that it will attempt to find a free instance for and reserve that.
*
* \note After calling \ref cyhal_clock_free the clock object can still be used to
* call any of the get() functions just as is possible from the instance returned
* by \ref cyhal_clock_get.
*
* \note A clock only needs to be allocated ( \ref cyhal_clock_allocate ) or
* initialized ( \ref cyhal_clock_init ) if its configuration needs to be changed
* by calling one of the set() functions.
*
* \note While the API is generic, the specific clock resource instances
* (\ref cyhal_resource_inst_t) are device specific. See the implementation
* specific sections for more details on what clocks and hardware resources are
* available.
*
* \section section_clock_features Features
* * Queryable clock features
* * Configurable clock enablement
* * Configurable clock frequency/divider
* * Configurable clock sources
* * Reserve or share clock objects
*
* \section section_clock_quickstart Quick Start
*
* See \ref subsection_clock_snippet_1 for a code snippet that shows how to reserve
* and configure a clock object.
*
* \section section_clock_snippets Code snippets
* \note Error handling code has been intentionally left out of snippets to highlight API usage.
*
* \subsection subsection_clock_snippet_1 Snippet 1: Simple clock read only access
* The following snippet shows how get details about a clock if there is no need to adjust any of its
* settings (e.g. read only access). This does not require initializing a clock object.
* \snippet clock.c snippet_cyhal_clock_simple_access
*
* \subsection subsection_clock_snippet_2 Snippet 2: Simple clock reservation and configuration
* The following snippet initializes a clock object, updates its frequency then enables it.
* \snippet clock.c snippet_cyhal_clock_simple_init
*
* \subsection subsection_clock_snippet_3 Snippet 3: Clock allocation and reuse
* The following snippet shows how a clock can be allocated and reused for multiple peripheral instances.
* \snippet clock.c snippet_cyhal_clock_simple_allocate
*
* \subsection subsection_clock_snippet_4 Snippet 4: Change clock source
* The following snippet shows how a to change the source of a clock.
* \snippet clock.c snippet_cyhal_clock_change_source
*
* \subsection subsection_clock_snippet_5 Snippet 5: System initialization
* The following snippet shows the clock driver can be used to initialize all clocks in the system.
* \note This example is device specific.
* \snippet clock.c snippet_cyhal_clock_system_init
*
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name Clock Results
*/
/** Error configuring clock frequency, divider, or multiplier. */
#define CYHAL_CLOCK_RSLT_ERR_FREQ \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CLOCK, 0))
/** Invalid source clock. */
#define CYHAL_CLOCK_RSLT_ERR_SOURCE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CLOCK, 1))
/** Specified operation is not supported by the current clock. */
#define CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CLOCK, 2))
/** The specified resource is not valid. */
#define CYHAL_CLOCK_RSLT_ERR_RESOURCE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CLOCK, 3))
/**
* \} \}
*/
/** Enum defining the different features each clock can support of clocks. These are bit masks.
* These can be used to determine which set() APIs are legal for a particular clock. */
typedef enum
{
CYHAL_CLOCK_FEATURE_NONE = (0), //!< No features of the clock are configurable.
CYHAL_CLOCK_FEATURE_ENABLE = (1 << 0), //!< The clock can be enabled & disabled \ref cyhal_clock_set_enabled.
CYHAL_CLOCK_FEATURE_FREQUENCY = (1 << 1), //!< The clock frequency can be adjusted \ref cyhal_clock_set_frequency.
CYHAL_CLOCK_FEATURE_DIVIDER = (1 << 2), //!< The clock divider can be adjusted \ref cyhal_clock_set_divider.
// Not available on any supported device yet.
// CYHAL_CLOCK_FEATURE_MULTIPLIER = (1 << 3), //!< The clock multiplier can be adjusted \ref cyhal_clock_set_multiplier.
CYHAL_CLOCK_FEATURE_SOURCE = (1 << 4), //!< The clock source can be adjusted \ref cyhal_clock_set_source.
} cyhal_clock_feature_t;
/** Allocates and Initializes a Clock instance, of the provided block type, for use.
* This should be used when needing a specific type of clock but the exact instance
* does not matter. This does everything that is done by \ref cyhal_clock_get and
* \ref cyhal_clock_init. Once the clock has been allocated the get() and set()
* functions can be used. If at any time the clock is no longer needed, it can be
* released by calling \ref cyhal_clock_free.
* \note This does not change the clock configuration or connections.
*
* @param[out] clock The clock object to initialize. The caller must allocate
* the memory for this object but the init function will initialize its contents.
* @param[in] block The specific type of clock to allocate
* @return The status of the allocate request.
*/
cy_rslt_t cyhal_clock_allocate(cyhal_clock_t *clock, cyhal_clock_block_t block);
/** Get a Clock instance for readonly use. This clock object can be used to call
* any of the get() functions. To call any of the set() functions, \ref
* cyhal_clock_init must be called to get exclusive access to the clock object
* to allow it to be modified.
*
* @param[out] clock The clock object to store the initialized data into. The
* caller must allocate the memory for this object but the init function will
* initialize its contents.
* @param[in] resource The clock resource instance to initialize.
* @return The status of the get request. This will only return an error if the provided
* resource instance is not a valid clock object.
*/
cy_rslt_t cyhal_clock_get(cyhal_clock_t *clock, const cyhal_resource_inst_t *resource);
/** Initialize a Clock instance for read/write use. This instance should be what was
* returned from \ref cyhal_clock_get.
* \note This does not change the behavior (e.g.: enablement) of the clock.
*
* @param[in,out] clock The clock object to store the initialized data into.
* @return The status of the init request.
*/
cy_rslt_t cyhal_clock_init(cyhal_clock_t *clock);
/** Gets the features supported by the specified clock. This can be used to determine which
* set() APIs are legal to be called for this clock.
*
* @param[in] clock The clock object to get features for.
* @return The feature set that can be configured by this clock. Features are bit mask values.
*/
cyhal_clock_feature_t cyhal_clock_get_features(const cyhal_clock_t *clock);
/** Gets whether the specified clock is currently enabled and locked, if appropriate. While
* most clocks simply have an enabled state, Crystals, PLL, and a few others may also check
* to make sure the clock has locked and is stable before returning true.
*
* \note External clocks which cannot be enabled/disabled directly will return true
* if a frequency has been set for them, and false otherwise
*
* @param[in] clock The clock object to check if it is enabled.
* @return Whether the specified clock is enabled or not.
*/
bool cyhal_clock_is_enabled(const cyhal_clock_t *clock);
/** Attempts to update the enablement of the specified clock. This is only legal to call
* if the \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_ENABLE.
*
* \note \ref cyhal_clock_allocate or \ref cyhal_clock_init must be called on the <b>clock</b>
* instace before using this function.
*
* \note If disabled, any clocks or peripherals that are using this will stop working. Make sure
* to switch the clock source (\ref cyhal_clock_set_source) of any downstream clocks if necessary
* to keep them running prior to disabling their source.
*
* @param[in] clock The clock object to update the enablement of.
* @param[in] enabled Whether the clock should be enabled (true) or disabled (false).
* @param[in] wait_for_lock Whether to wait for the clock to enable & lock (true), or just send
* the request and return (false). Most clocks behave the same either
* way, however Crystals, PLLs, and similar require time to lock. If
* false, \ref cyhal_clock_is_enabled needs to be used to check that
* it is running before using the clock.
* @return The status of the requested to change the clocks enablement.
*/
cy_rslt_t cyhal_clock_set_enabled(cyhal_clock_t *clock, bool enabled, bool wait_for_lock);
/** Gets the frequency (in Hz) the clock is currently operating at.
*
* @param[in] clock The clock object to get the frequency of.
* @return The frequency the clock is currently running at. 0 if the clock is disabled.
*/
uint32_t cyhal_clock_get_frequency(const cyhal_clock_t *clock);
/** Attempts to update the operating frequency of the clock. This is only legal to call
* if the \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_FREQUENCY.
*
* \note \ref cyhal_clock_allocate or \ref cyhal_clock_init must be called on the <b>clock</b>
* instace before using this function.
*
* \note Some clocks (eg: FLLs & PLLs) may need to be stopped before their frequency can
* be changed. This function will take care of disabling & re-enabling as necessary, however,
* this can cause a temporary glitch on anything that is running off of the clock at the time.
* If glitch free operation is required, change the source of any downstream clocks the
* application before changing the clock frequency.
*
* @param[in] clock The clock object to set the frequency for.
* @param[in] hz The frequency, in hertz, to set the clock to.
* @param[in] tolerance The allowed tolerance from the desired hz that is acceptable, use NULL if no
* tolerance check is required.
* @return The status of the request to set the clock frequency.
*/
cy_rslt_t cyhal_clock_set_frequency(cyhal_clock_t *clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance);
/** Attempts to update the divider, and by extension the operating frequency, of the clock. This is only
* legal to call if the \ref cyhal_clock_get_features API indicates support for
* \ref CYHAL_CLOCK_FEATURE_DIVIDER.
*
* \note \ref cyhal_clock_allocate or \ref cyhal_clock_init must be called on the <b>clock</b>
* instace before using this function.
*
* @param[in] clock The clock object to set the divider for.
* @param[in] divider The divider value to use.
* @return The status of the request to set the clock divider.
*/
cy_rslt_t cyhal_clock_set_divider(cyhal_clock_t *clock, uint32_t divider);
/** Gets the clocks that can serve as inputs to the current clock.
*
* @param[in] clock The clock object to get legal sources for.
* @param[out] sources The sources that are legal for the current clock.
* \note the array does not need to be allocated before calling this
* the pointer will be updated to point to an existing const array.
* @param[out] count The number of clock sources contained in the <b>sources</b> variable.
* @return The status of the request to get clock sources.
*/
cy_rslt_t cyhal_clock_get_sources(const cyhal_clock_t *clock, const cyhal_resource_inst_t **sources[], uint32_t *count);
/** Attempts to update the source for the specified clock. This is only legal to call if the
* \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_SOURCE.
*
* \note \ref cyhal_clock_allocate or \ref cyhal_clock_init must be called on the <b>clock</b>
* instace before using this function.
*
* \note Some clocks (eg: FLLs & PLLs) may need to be stopped before their source can be changed.
* This function will take care of disabling & re-enabling as necessary, however, this can cause
* a temporary glitch on anything that is running off of the clock at the time. If glitch free
* operation is required, change the source for any downstream clocks in the application before
* changing the source clock.
*
* \note No checking is done to verify that the source clock is running. This needs to be done
* by the caller.
*
* @param[in] clock The clock object to set a new source for.
* @param[in] source The source clock to update to.
* @return The status of the request to set the source of the clock
*/
cy_rslt_t cyhal_clock_set_source(cyhal_clock_t *clock, const cyhal_clock_t *source);
/** Releases the exclusive lock the clock. This instance can no longer be used to with any set()
* functions. It can still be used for readonly access to Clock APIs just like is possible after
* calling \ref cyhal_clock_get.
*
* \note This does not change the behavior (e.g.: enablement) of the clock.
*
* @param[in,out] clock The clock object to free
*/
void cyhal_clock_free(cyhal_clock_t *clock);
#if defined(__cplusplus)
}
#endif
#ifdef CYHAL_CLOCK_IMPL_HEADER
#include CYHAL_CLOCK_IMPL_HEADER
#endif /* CYHAL_CLOCK_IMPL_HEADER */
/** \} group_hal_clock */

View File

@ -0,0 +1,120 @@
/*******************************************************************************
* File Name: cyhal_clock_impl.h
*
* Description:
* PSoC 6 specific implementation for clocks API.
*
********************************************************************************
* \copyright
* Copyright 2018-2019 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.
*******************************************************************************/
#pragma once
#include "cyhal_hw_resources.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/**
* \addtogroup group_hal_psoc6_clock Clocks
* \ingroup group_hal_psoc6
* \{
* Implementation specific interface for using the Clock driver. These items, while usable
* within the HAL, are <b>not</b> necessarily portable between devices. The diagram below
* shows how the clocks relate to each other. This is a superset of what is available. See
* the device specific Data Sheet for the exact set of clocks that are available on a
* specific device.
*
* \image html psoc6_clock_tree.png
*/
/** \cond INTERNAL */
#define SRSS_MFO_PRESENT (SRSS_VER1P3)
/** \endcond */
/** Internal Main Oscillator: This is a fixed-frequency clock that is commonly used as a general purpose source for clocks that do not require specific frequencies or very high accuracy. This clock is stopped in the deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_IMO;
/** External Clock: This is an off-chip clock (not an oscillator). This clock is stopped in the deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_EXT;
/** Internal Low Speed Oscillator: This is a low accuracy fixed-frequency clock in the kilohertz range that is available in sleep, deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_ILO;
#if SRSS_ECO_PRESENT
/** External Crystal Oscillator: This is an off-chip clock source that is used when specific frequencies and/or very high accuracy is required. This clock is stopped in the deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_ECO;
#endif
#if SRSS_ALTHF_PRESENT
/** Alternate High Frequency Clock: A high speed clock input provided by a subsystem outside the clocking system. This clock is stopped in the deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_ALTHF;
#endif
#if SRSS_ALTLF_PRESENT
/** Alternate Low Frequency Clock: A low speed clock input provided by a subsystem outside the clocking system. This clock is the hibernate power mode. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_ALTLF;
#endif
#if SRSS_PILO_PRESENT
/** Precision ILO: An additional source that can provide a much more accurate 32.768kHz clock than ILO when periodically calibrated using a high-accuracy clock such as the ECO. This clock is stopped in the hibernate power mode. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_PILO;
#endif
#if SRSS_BACKUP_PRESENT
/** Watch Crystal Oscillator: This source is driven from an off-chip watch crystal that provides an extremely accurate source. This clock is stopped in the hibernate power mode. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_WCO;
#endif
#if SRSS_MFO_PRESENT
/** Medium Frequency Oscillator: This source produced by dividing the IMO by 4. The MFO works down to DeepSleep, and the IMO does not turn off if this clock requires it. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_MFO;
/** Medium Frequency Clock: This clock is a medium frequency, between the Low Frequency Clock (LF) and High Frequency Clock (HF). */
extern const cyhal_resource_inst_t CYHAL_CLOCK_MF;
#endif
/** Low Frequency Clock: This clock is the source for the multi-counter watchdog timers (MCWDT), and can also be a source for the RTC. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_LF;
/** Analog Pump Clock: This clock ensures precision analog performance in low voltage applications. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_PUMP;
/** Backup Clock: This clock is available to the backup domain. Typically useful if an external WCO is not available. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_BAK;
/** Fast Clock: This clock is used for the CM4 and associated AHB-Lite bus infrastructure. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_FAST;
/** Peripheral Clock: This is the source clock for any divided clock in the design. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_PERI;
/** Timer Clock: This clock is intended as a source for high-frequency timers, such as the Energy Profiler and CPU SysTick clock. This clock is stopped in the hibernate power mode. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_TIMER;
/** Slow Clock: This clock is used for the CM0+ CPU, Datawire and CRYPTO components and the associated CPUSS slow infrastructure. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_SLOW;
/** AltSysTickClk: Provides an optional external source for the CM4/CM0+ SysTick timers. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_ALT_SYS_TICK;
#if (SRSS_NUM_CLKPATH > 0)
/** Path mux selection: A clock source for high frequency clocks. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_PATHMUX[SRSS_NUM_CLKPATH];
#endif
/** Frequency-Locked Loop: This is a high-frequency clock suitable for most on-chip purposes. It is similar to a PLL, but starts up much faster and consumes less current. This clock is stopped in the deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_FLL;
#if (SRSS_NUM_PLL > 0)
/** Phase-Locked Loop: A high-frequency clock able to generate a wide range of clock frequencies making it suitable for most on-chip purposes. This clock is stopped in the deep sleep and hibernate power modes. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_PLL[SRSS_NUM_PLL];
#endif
/** High Frequency Clock: A high-frequency clock output driving specific peripherals. */
extern const cyhal_resource_inst_t CYHAL_CLOCK_HF[SRSS_NUM_HFROOT];
/** \} group_hal_psoc6_clock */
#if defined(__cplusplus)
}
#endif

View File

@ -2,7 +2,7 @@
* \file cyhal_crc.h
*
* \brief
* Provides a high level interface for interacting with the Cypress CRC accelerator.
* Provides a high level interface for interacting with the CRC hardware accelerator.
* This interface abstracts out the chip specific details. If any chip specific
* functionality is necessary, or performance is critical the low level functions
* can be used directly.
@ -29,15 +29,26 @@
* \addtogroup group_hal_crc CRC (Cyclic Redundancy Check)
* \ingroup group_hal
* \{
* High level interface for interacting with the cyclic redundancy check (CRC), which provides hardware
* High level interface for interacting with the CRC, which provides hardware
* accelerated CRC computations.
* The CRC APIs are structured to enable usage in situations where the entire input data
* set is not available in memory at one time. Therefore, each conversion consists of three steps:
* * A single call to cyhal_crc_start, to initialize data structures for this computation
* * One or more calls to cyhal_crc_compute, to provide chunks of data.
* * A single call to cyhal_crc_finish, to finalize the computation and retrieve the result.
* set is not available in memory at the same time. Therefore, each conversion consists of three steps:
* * A single call to \ref cyhal_crc_start, to initialize data structures used to compute CRC
* * One or more calls to \ref cyhal_crc_compute, to provide chunks of data
* * A single call to \ref cyhal_crc_finish, to finalize the computation and retrieve the result
*
* Many of the algorithm parameters can be customized; see crc_algorithm_t for more details.
* Many of the algorithm parameters can be customized.
*
* See \ref crc_algorithm_t and \ref subsection_crc_snippet_1 for more details.
*
* \section subsection_crc_quickstart Quick Start
*
* \ref cyhal_crc_init initializes the CRC generator and passes the pointer to the CRC block through the **obj** object of type \ref cyhal_crc_t.
*
* \subsection subsection_crc_snippet_1 Snippet1: CRC Generation
* The following snippet initializes a CRC generator and computes the CRC for a sample message.
*
* \snippet crc.c snippet_cyhal_crc_simple_init
*/
#pragma once
@ -46,14 +57,23 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name CRC Results
*/
/** Invalid argument */
#define CYHAL_CRC_RSLT_ERR_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CRC, 0))
#define CYHAL_CRC_RSLT_ERR_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CRC, 0))
/**
* \} \}
*/
/** @brief CRC algorithm parameters */
typedef struct
@ -74,8 +94,11 @@ typedef struct
/** Initialize the CRC generator. This function reserves the CRYPTO block for CRC calculations.
*
* @param[out] obj The CRC generator object
* @param[out] obj Pointer to a CRC generator object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @return The status of the init request.
*
* Returns \ref CY_RSLT_SUCCESS if the operation was successful. Refer \ref subsection_crc_snippet_1 for more information.
*/
cy_rslt_t cyhal_crc_init(cyhal_crc_t *obj);
@ -85,31 +108,36 @@ cy_rslt_t cyhal_crc_init(cyhal_crc_t *obj);
*/
void cyhal_crc_free(cyhal_crc_t *obj);
/** Initializes a CRC calculation.
/** The CRC block is setup to perform CRC computation
*
* @param[in,out] obj The CRC generator object
* @param[in] algorithm The CRC algorithm to use for computations
* @param[in] algorithm The CRC algorithm to use for computations Refer \ref crc_algorithm_t.
* @return The status of the compute request
*
* Returns \ref CY_RSLT_SUCCESS if the operation was successful.
*/
cy_rslt_t cyhal_crc_start(cyhal_crc_t *obj, const crc_algorithm_t *algorithm);
/** Computes the CRC for the given data. This function can be called multiple times to
* provide addtional data. This CRC generator will compute the CRC for including all data
* that was provided during previous calls.
*
/** Computes the CRC for the given data and accumulates the CRC with the CRC generated from previous calls.
* This function can be called multiple times to provide additional data.
* \note Input data must be 4-byte aligned. Refer \ref subsection_crc_snippet_1 for more details.
* @param[in] obj The CRC generator object
* @param[in] data The data to compute a CRC over
* @param[in] length The number of bytes of data to process
* @param[in] data The input data
* @param[in] length The number of bytes in the data
* @return The status of the compute request
*
* Returns \ref CY_RSLT_SUCCESS if the operation was successful.
*/
cy_rslt_t cyhal_crc_compute(const cyhal_crc_t *obj, const uint8_t *data, size_t length);
/** Provides final result for a CRC calculation. This will compute the CRC for all data that
* was provided when during the diffrent calls to cyhal_crc_compute.
/** Finalizes the CRC computation and returns the CRC for the complete set of data passed through a single call or multiple calls to \ref cyhal_crc_compute.
* \note The computed CRC pointer provided must be 4 byte aligned. Refer \ref subsection_crc_snippet_1 for more details.
*
* @param[in] obj The CRC generator object
* @param[out] crc The computed CRC
* @return The status of the compute request
*
* Returns \ref CY_RSLT_SUCCESS if the operation was successful.
*/
cy_rslt_t cyhal_crc_finish(const cyhal_crc_t *obj, uint32_t *crc);

View File

@ -1,8 +1,8 @@
/***************************************************************************//**
/***************************************************************************//**
* \file cyhal_crc_impl.h
*
* Description:
* Provides a high level interface for interacting with the Cypress CRC accelerator.
* Provides a high level interface for interacting with the Cypress CRC accelerator.
* This is a wrapper around the lower level PDL API.
*
********************************************************************************

View File

@ -2,7 +2,7 @@
* \file cyhal_crypto_common.h
*
* Description:
* This file provides common defines, addresses, and functions required by drivers
* This file provides common defines, addresses, and functions required by drivers
* using the Crypto block.
*
********************************************************************************

View File

@ -34,8 +34,29 @@
* This block drives a pin with a firmware configurable voltage. See the device datasheet
* for details on which pins support DAC output.
*
* The cyhal_dac_write and cyhal_dac_read APIs are defined relative to the DAC's output
* voltage range, which is device dependent.
* \section subsection_dac_features Features
* The DAC driver provides APIs to:
* * Configure and work with the DAC hardware
* * Update the DAC output value
* * Read the DAC output voltage setting
*
* \note The \ref cyhal_dac_write and \ref cyhal_dac_read APIs are defined as 16-bit, which may not match the underlying hardware.
* The functions will linearly scale the 16-bit value to and from a resolution that hardware is capable of outputting.
* For instance, if the device supports 12-bit resolution, only the 12 MSBs of the 16-bit value will be used.
* Refer to BSP Settings section in the kit's BSP API Reference Manual for details on the DAC's output range.
*
* \section subsection_dac_quickstart Quick Start
* Call \ref cyhal_dac_init to initialize a DAC instance by providing the DAC
* object ( <b> obj </b> ) and an output pin (<b> pin </b>).
*
* See \ref subsection_dac_use_case_1.
*
* \section subsection_dac_snippets Code Snippets
*
* \subsection subsection_dac_use_case_1 Use case 1: Simple DAC initialization
* The following snippet initializes a DAC resource and assigns the output to the specified <b>pin</b> using \ref cyhal_dac_init.
* \ref cyhal_dac_write is used to set the DAC output value. \ref cyhal_dac_read is used to read back DAC register.
* \snippet dac.c snippet_cyhal_dac_simple_init
*/
#pragma once
@ -44,23 +65,38 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name DAC Results
*/
/** Bad argument */
#define CYHAL_DAC_RSLT_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DAC, 0))
#define CYHAL_DAC_RSLT_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DAC, 0))
/** Failed to initialize DAC */
#define CYHAL_DAC_RSLT_FAILED_INIT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DAC, 1))
#define CYHAL_DAC_RSLT_FAILED_INIT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DAC, 1))
/**
* \} \}
*/
/** Initialize the DAC peripheral
*
* Configures the pin used by dac.
* @param[in] obj The dac object to initialize
*
* @param[out] obj Pointer to a DAC object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] pin The dac pin name
* @return The status of the init request
* @return The status of the init request. On success returns \ref CY_RSLT_SUCCESS.<br>
* On failure, a problem specific error code will be returned.
* This error could be from the HAL or lower level driver. <br>
* For all other return codes, please refer to device driver documentation available in the BSP landing page
*/
cy_rslt_t cyhal_dac_init(cyhal_dac_t *obj, cyhal_gpio_t pin);

View File

@ -0,0 +1,136 @@
/***************************************************************************//**
* \file cyhal_deprecated.h
*
* \brief
* Provides access to items that are device specific and no longer part of the
* common HAL API.
*
********************************************************************************
* \copyright
* Copyright 2018-2019 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.
*******************************************************************************/
#pragma once
#include "cy_pdl.h"
#include "cyhal_general_types.h"
#include "cyhal_hw_resources.h"
#include "cy_result.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup group_hal_psoc6_deprecated Deprecated
* \ingroup group_hal_psoc6
* \{
* The following PSoC 6 specific items have been deprecated and replaced by more generic item. Each item
* will continue to work for now, but will be removed in a future release. All deprecated items reference
* the item that replaces it.
*/
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_INVALID_CLK_DIVIDER (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 1))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_UNABLE_TO_SET_CLK_FREQ (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 2))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_SRC_CLK_DISABLED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 3))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_NO_VALID_DIVIDER (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 4))
/** Enum for clock type to configure. HFCLKs are configured using different APIs and does not using this enum.
* \warning This type is deprecated. Use \ref cyhal_clock_block_t instead.
*/
typedef enum
{
CYHAL_SYSTEM_CLOCK_CM4,
CYHAL_SYSTEM_CLOCK_CM0,
CYHAL_SYSTEM_CLOCK_PERI,
} cyhal_system_clock_t;
/** Available clock divider types.
* \warning This type is deprecated. Use \ref cyhal_clock_block_t instead.
*/
typedef cy_en_divider_types_t cyhal_clock_divider_types_t;
/** Divider for CM4, CM0 and Peri clock. Supports values between [1, 256]
* \warning This type is deprecated. Use \ref cyhal_clock_t instead.
*/
typedef uint16_t cyhal_system_divider_t;
/** Peripheral clock divider type.
* \warning This type is deprecated. Use \ref cyhal_clock_t instead.
*/
typedef cyhal_clock_t cyhal_clock_divider_t;
/** Allocate (pick and reserve) an Clock Divider resource and provide a reference to it.
*
* \warning This function is deprecated. Use \ref cyhal_clock_allocate() instead.
*
* @param[out] obj The resource object that was allocated
* @param[in] div The type of divider to allocate
* @param[in] accept_larger Whether a larger type can be provided if there are none of the requested size available
* @return The status of the reserve request
*/
cy_rslt_t cyhal_hwmgr_allocate_clock(cyhal_clock_divider_t* obj, cyhal_clock_divider_types_t div, bool accept_larger) /* __attribute__ ((deprecated)) */;
/** Free the specified Clock Divider resource and allow it be used by something else.
*
* \warning This function is deprecated. Use \ref cyhal_clock_free() instead.
*
* @param[in] obj The resource object that was allocated
*/
void cyhal_hwmgr_free_clock(cyhal_clock_divider_t* obj) /* __attribute__ ((deprecated)) */;
/** Gets the specified clock's current frequency.
*
* \warning This function is deprecated. Use \ref cyhal_clock_get_frequency() instead.
*
* @param[in] clock ID of clock to configure
* @param[out] frequency_hz The frequency the clock is currently running at
* @return The status of the get_frequency request
*/
cy_rslt_t cyhal_system_clock_get_frequency(uint8_t clock, uint32_t *frequency_hz) /* __attribute__ ((deprecated)) */;
/** Sets the specified clock's frequency and enables it. This will turn on any
* additional clocks needed to drive this.
*
* \warning This function is deprecated. Use \ref cyhal_clock_set_frequency() instead.
*
* @param[in] clock ID of clock to configure
* @param[in] frequency_hz The frequency to run the clock at
* @return The status of the set_frequency request
*/
cy_rslt_t cyhal_system_clock_set_frequency(uint8_t clock, uint32_t frequency_hz) /* __attribute__ ((deprecated)) */;
/** Divides the clock frequency by the divider.
*
* \warning This function is deprecated. Use \ref cyhal_clock_set_divider() instead.
*
* @param[in] clock The clock to configure divider value for
* @param[in] divider The divider value to divide the frequency by
* @return The status of the set_divider request
*/
cy_rslt_t cyhal_system_clock_set_divider(cyhal_system_clock_t clock, cyhal_system_divider_t divider) /* __attribute__ ((deprecated)) */;
/** \} group_hal_psoc6_deprecated */
#if defined(__cplusplus)
}
#endif /* __cplusplus */

View File

@ -9,11 +9,7 @@
*
********************************************************************************
* \copyright
<<<<<<< HEAD
* Copyright 2018-2019 Cypress Semiconductor Corporation
=======
* Copyright 2018-2020 Cypress Semiconductor Corporation
>>>>>>> Minor consistancy cleanup for HAL documentation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,15 +26,56 @@
*******************************************************************************/
/**
* \addtogroup group_hal_dma DMA (Direct Memory Access)
* \ingroup group_hal
* \{
* High level interface for interacting with the direct memory access (DMA). Allows the user to
* initialize and configure a DMA channel in order to trigger data transfers to
* and from memory and peripherals. The transfers occur independently of the CPU
* and are triggered in software. Multiple channels are available with
* user-selectable priority and transfer characteristics.
*/
* \addtogroup group_hal_dma DMA (Direct Memory Access)
* \ingroup group_hal
* \{
* High level interface for interacting with the direct memory access (DMA).
* The DMA driver allows for initializing and configuring a DMA channel in
* order to trigger data transfers to and from memory and peripherals. The
* transfers occur independently of the CPU and are triggered in software.
* Multiple channels are available with user-selectable priority and transfer
* characteristics.
*
* \section section_dma_features Features
* * CPU independent memory access
* * Access to memory and peripherals
* * Multiple independent channels
* * Configurable transer sizes and bursts
* * Configurable priorities
* * Event completion notification
*
* \section section_dma_quickstart Quick Start
*
* See \ref subsection_dma_snippet_1 for a code snippet that sets up a DMA
* transfer to move memory from one location to another.
*
* \section section_dma_snippets Code snippets
* \note Error handling code has been intentionally left out of snippets to highlight API usage.
*
* \subsection subsection_dma_snippet_1 Snippet 1: Simple DMA initialization and transfer
* The following snippet initializes a DMA channel and uses it to transfer a a single block of memory.
* The DMA channel is reserved by calling \ref cyhal_dma_init. It then needs to be configured with
* \ref cyhal_dma_configure and then the transfer is started with \ref cyhal_dma_start_transfer.<br>
* If the DMA channel is not needed anymore, it can be released by calling \ref cyhal_dma_free
*
* \snippet dma.c snippet_cyhal_dma_simple_init
*
*
* \subsection subsection_dma_snippet_2 Snippet 2: Configuring the DMA channel based on memory requirements
* \ref cyhal_dma_configure can be used after DMA initialization to handle a variety of memory layouts.
*
* \snippet dma.c snippet_cyhal_dma_configure
*
*
* \subsection subsection_dma_snippet_3 Snippet 3: Interrupts and retriggering DMA transfers
* DMA events like transfer complete or error events can be used to trigger a callback function. <br>
* This snippet uses \ref cyhal_dma_configure to break the full transfer into multiple bursts. This
* allows higher priority items access to the memory bus if necessary while the DMA operation is still
* in progress. It then uses \ref cyhal_dma_enable_event() to enable the transfer complete event to
* trigger the callback function registered by \ref cyhal_dma_register_callback().
*
* \snippet dma.c snippet_cyhal_dma_events
*/
#pragma once
@ -51,22 +88,39 @@
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name DMA Results
*/
/** Invalid transfer width parameter error */
#define CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 0))
#define CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 0))
/** Invalid parameter error */
#define CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 1))
#define CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 1))
/** Invalid priority parameter error */
#define CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 2))
#define CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 2))
/** Invalid src or dst addr alignment error */
#define CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 3))
#define CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 3))
/** Invalid burst_size paramenter error */
#define CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 4))
#define CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 4))
/** Channel busy error */
#define CYHAL_DMA_RSLT_ERR_CHANNEL_BUSY (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 5))
#define CYHAL_DMA_RSLT_ERR_CHANNEL_BUSY \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 5))
/** Transfer has already been started warning */
#define CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED (CY_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_DMA, 6))
#define CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_DMA, 6))
/** Unsupported hardware error */
#define CYHAL_DMA_RSLT_FATAL_UNSUPPORTED_HARDWARE (CY_RSLT_CREATE(CY_RSLT_TYPE_FATAL, CYHAL_RSLT_MODULE_DMA, 7))
#define CYHAL_DMA_RSLT_FATAL_UNSUPPORTED_HARDWARE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_FATAL, CYHAL_RSLT_MODULE_DMA, 7))
/**
* \} \}
*/
/** Direction for DMA transfers. */
typedef enum
@ -121,8 +175,9 @@ typedef void (*cyhal_dma_event_callback_t)(void *callback_arg, cyhal_dma_event_t
/** Initialize the DMA peripheral.
*
* @param[out] obj The DMA object to initialize
* @param[in] priority The priority of this DMA operation relative to others. The number of priority levels which are supported is hardware dependent. All implementations define a CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will also define CYHAL_DMA_PRIORITY_HIGH, CYHAL_DMA_PRIORITY_MEDIUM, and CYHAL_DMA_PRIORITY_LOW. The behavior of any other value is implementation defined. See the implementation-specific DMA documentation for more details.
* @param[out] obj Pointer to a DMA object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] priority The priority of this DMA operation relative to others. The number of priority levels which are supported is hardware dependent. All implementations define a #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW. The behavior of any other value is implementation defined. See the implementation-specific DMA documentation for more details.
* @param[in] direction The direction memory is copied
* @return The status of the init request
*/
@ -157,7 +212,9 @@ cy_rslt_t cyhal_dma_start_transfer(cyhal_dma_t *obj);
*/
bool cyhal_dma_is_busy(cyhal_dma_t *obj);
/** The DMA callback handler registration
/** Register a DMA callback handler.
*
* This function will be called when one of the events enabled by \ref cyhal_dma_enable_event occurs.
*
* @param[in] obj The DMA object
* @param[in] callback The callback handler which will be invoked when an event triggers
@ -166,6 +223,8 @@ bool cyhal_dma_is_busy(cyhal_dma_t *obj);
void cyhal_dma_register_callback(cyhal_dma_t *obj, cyhal_dma_event_callback_t callback, void *callback_arg);
/** Configure DMA event enablement.
*
* When an enabled event occurs, the function specified by \ref cyhal_dma_register_callback will be called.
*
* @param[in] obj The DMA object
* @param[in] event The DMA event type

View File

@ -6,7 +6,7 @@
*
********************************************************************************
* \copyright
* Copyright 2018-2019 Cypress Semiconductor Corporation
* Copyright 2018-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -71,12 +71,12 @@ cy_rslt_t cyhal_dma_start_transfer_dmac(cyhal_dma_t *obj);
/** Configure DMAC event enablement.
*
* @param[in] obj The DMA object
* @param[in] event The DMA event type
* @param[in] intrPriority The priority for NVIC interrupt events. The priority from the most recent call will take precedence, i.e all events will have the same priority.
* @param[in] enable True to turn on interrupts, False to turn off
* @param[in] obj The DMA object
* @param[in] event The DMA event type
* @param[in] intr_priority The priority for NVIC interrupt events. The priority from the most recent call will take precedence, i.e all events will have the same priority.
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_dma_enable_event_dmac(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intrPriority, bool enable);
void cyhal_dma_enable_event_dmac(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable);
/** Checks whether a transfer is pending or running on the DMA channel
*

View File

@ -6,7 +6,7 @@
*
********************************************************************************
* \copyright
* Copyright 2018-2019 Cypress Semiconductor Corporation
* Copyright 2018-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -71,12 +71,12 @@ cy_rslt_t cyhal_dma_start_transfer_dw(cyhal_dma_t *obj);
/** Configure Datawire event enablement.
*
* @param[in] obj The DMA object
* @param[in] event The DMA event type
* @param[in] intrPriority The priority for NVIC interrupt events. The priority from the most recent call will take precedence, i.e all events will have the same priority.
* @param[in] enable True to turn on interrupts, False to turn off
* @param[in] obj The DMA object
* @param[in] event The DMA event type
* @param[in] intr_priority The priority for NVIC interrupt events. The priority from the most recent call will take precedence, i.e all events will have the same priority.
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_dma_enable_event_dw(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intrPriority, bool enable);
void cyhal_dma_enable_event_dw(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable);
/** Checks whether a transfer is pending or running on the DMA channel
*

View File

@ -6,7 +6,7 @@
*
********************************************************************************
* \copyright
* Copyright 2018-2019 Cypress Semiconductor Corporation
* Copyright 2018-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -25,24 +25,46 @@
* limitations under the License.
*******************************************************************************/
/******************************************************************************
* Provides a high level Cypress EZI2C Slave interface for interacting with
* an I2C master.
* This interface abstracts out the chip specific details. If any chip specific
* functionality is necessary, or performance is critical the low level functions
* can be used directly.
*
* Cypress EZI2C emulates a common I2C EEPROM interface that acts like dual-port
* memory between the external master and your code. Once the interface is setup,
* your code can read/write freely from the specified buffer(s).
* All I2C transactions to/from the master are handled automatically.
*******************************************************************************/
/**
* \addtogroup group_hal_ezi2c EZI2C (Inter-Integrated Circuit)
* \ingroup group_hal
* \{
* High level interface for interacting with the Cypress EZ Inter-Integrated Circuit (EZI2C).
* The EZI2C driver implements an I2C slave device that emulates a common I2C EEPROM interface between
* the external master and your application code. EZI2C Slave buffers can be set up as any variable, array,
* or structure in your code without worrying about the I2C protocol. I2C related transactions and processing
* of data from the I2C master are handled by the driver through internal interrupt routine, reducing application
* involvement to maintain the I2C buffer.
*
* \section subsection_ezi2c_features Features
* * EZI2C Slave functionality
* * Configurable standard data rates of 100/400/1000 kbps - \ref cyhal_ezi2c_data_rate_t
* * Supports one or two addresses with independent memory buffers - \ref cyhal_ezi2c_cfg_t
* * Memory buffers provide configurable read/write and read only regions - \ref cyhal_ezi2c_cfg_t
* * 8 or 16-bit sub-addressing - \ref cyhal_ezi2c_sub_addr_size_t
* * Configurable interrupt and callback assignment from EZI2C events - \ref cyhal_ezi2c_event_t
*
* \section section_ezi2c_quickstart Quick Start
* Initialize EZI2C by using \ref cyhal_ezi2c_init and selecting the <b>sda</b> and <b>scl</b> pins.
* Setup one or two memory buffers and read/write boundaries using the EZI2C configuration
* structure \ref cyhal_ezi2c_cfg_t.
* See \ref subsection_ezi2c_snippet_1
* \note The clock parameter <b>clk</b> is optional and can be set to NULL to generate and use an
* available clock resource.
*
* \section section_ezi2c_snippets Code snippets
*
* \subsection subsection_ezi2c_snippet_1 Snippet 1: EZI2C Initialization and Configuration
* The following snippet shows how to initialize and configure an EZI2C and assign the pins to the <b>sda</b> and <b>scl</b> lines.
* The <b>clk</b> need not be provided (NULL), in which case a clock resource is assigned.
*
* \snippet ezi2c.c snippet_cyhal_ezi2c_init
*
* \subsection subsection_ezi2c_snippet_2 Snippet 2: Register Callback function
* The following snippet shows how to use the \ref cyhal_ezi2c_register_callback function. The <b>callback</b> parameter
* refers to the handler which will be invoked when an event triggers.
*
* \snippet ezi2c.c snippet_cyhal_ezi2c_handler
*/
#pragma once
@ -51,20 +73,35 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name EZI2C Results
*/
/** The requested resource type is invalid */
#define CYHAL_EZI2C_RSLT_ERR_INVALID_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 0))
#define CYHAL_EZI2C_RSLT_ERR_INVALID_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 0))
/** Can not reach desired data rate */
#define CYHAL_EZI2C_RSLT_ERR_CAN_NOT_REACH_DR (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 1))
#define CYHAL_EZI2C_RSLT_ERR_CAN_NOT_REACH_DR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 1))
/** Number of addresses is not valid */
#define CYHAL_EZI2C_RSLT_ERR_NUM_ADDR_NOT_VALID (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 2))
#define CYHAL_EZI2C_RSLT_ERR_NUM_ADDR_NOT_VALID \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 2))
/** Number of addresses is not valid */
#define CYHAL_EZI2C_RSLT_ERR_CHECK_USER_CONFIG (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 3))
#define CYHAL_EZI2C_RSLT_ERR_CHECK_USER_CONFIG \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_EZI2C, 3))
/**
* \} \}
*/
/** CYHAL_EZI2C_EVENT_NONE event is deprecated and that CYHAL_EZI2C_STATUS_OK should be used instead */
#define CYHAL_EZI2C_EVENT_NONE CYHAL_EZI2C_STATUS_OK
/** Size of Sub-Address */
typedef enum
@ -85,27 +122,21 @@ typedef enum
typedef enum
{
/** Each EZI2C slave status is encoded in a separate bit, therefore multiple bits may be set to indicate the current status */
CYHAL_EZI2C_STATUS_OK = 0x0UL, /**< Operation completed successfully */
CYHAL_EZI2C_STATUS_READ1 = 0x01UL, /**< The Read transfer intended for the primary slave address is complete */
CYHAL_EZI2C_STATUS_WRITE1 = 0x02UL, /**< The Write transfer intended for the primary slave address is complete */
CYHAL_EZI2C_STATUS_READ2 = 0x04UL, /**< The Read transfer intended for the secondary slave address is complete */
CYHAL_EZI2C_STATUS_WRITE2 = 0x08UL, /**< The Write transfer intended for the secondary slave address is complete */
CYHAL_EZI2C_STATUS_BUSY = 0x10UL, /**< A transfer intended for the primary address or secondary address is in progress */
CYHAL_EZI2C_STATUS_ERR = 0x20UL /**< An error occurred during a transfer intended for the primary or secondary slave address */
CYHAL_EZI2C_STATUS_OK = 0x1UL, /**< Operation completed successfully */
CYHAL_EZI2C_STATUS_READ1 = 0x2UL, /**< The Read transfer intended for the primary slave address is complete */
CYHAL_EZI2C_STATUS_WRITE1 = 0x4UL, /**< The Write transfer intended for the primary slave address is complete */
CYHAL_EZI2C_STATUS_READ2 = 0x8UL, /**< The Read transfer intended for the secondary slave address is complete */
CYHAL_EZI2C_STATUS_WRITE2 = 0x10UL, /**< The Write transfer intended for the secondary slave address is complete */
CYHAL_EZI2C_STATUS_BUSY = 0x20UL, /**< A transfer intended for the primary address or secondary address is in progress */
CYHAL_EZI2C_STATUS_ERR = 0x40UL /**< An error occurred during a transfer intended for the primary or secondary slave address */
} cyhal_ezi2c_status_t;
/** Enum to enable/disable/report interrupt cause flags. When an event is triggered
* the status can be obtained by calling \ref cyhal_ezi2c_get_activity_status.
* \note This is a placeholder for now. It may be extended in the future.
*/
typedef enum
{
CYHAL_EZI2C_EVENT_NONE = 0, /* No event */
} cyhal_ezi2c_event_t;
/** This type is deprecated and that cyhal_ezi2c_status_t should be used instead */
typedef cyhal_ezi2c_status_t cyhal_ezi2c_event_t;
/** Handler for I2C events */
typedef void (*cyhal_ezi2c_event_callback_t)(void *callback_arg, cyhal_ezi2c_event_t event);
typedef void (*cyhal_ezi2c_event_callback_t)(void *callback_arg, cyhal_ezi2c_status_t event);
/** Initial EZI2C sub configuration */
typedef struct
@ -141,16 +172,19 @@ typedef struct
cyhal_ezi2c_sub_addr_size_t sub_address_size;
} cyhal_ezi2c_cfg_t;
/** Initialize the EZI2C (slave), and configures its specifieds pins and clock.
/** Initialize the EZI2C (slave), and configures its specified pins and clock.
* See \ref subsection_ezi2c_snippet_1
*
* @param[out] obj The I2C object
* @param[out] obj Pointer to an EZI2C object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] sda The sda pin
* @param[in] scl The scl pin
* @param[in] clk The clock to use can be shared, if NULL a new clock will be allocated
* @param[in] cfg The ezi2c configuration (refer to cyhal_ezi2c_cfg_t for details)
* @return The status of the init request
*/
cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_divider_t *clk, const cyhal_ezi2c_cfg_t *cfg);
cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk, const cyhal_ezi2c_cfg_t *cfg);
/** Deinitialize the ezi2c object
*
@ -160,8 +194,9 @@ void cyhal_ezi2c_free(cyhal_ezi2c_t *obj);
/**
* EZI2C slave get activity status
* This function returns a non-zero value if an I2C Read or Write
* This function returns a non-zero value ( \ref cyhal_ezi2c_status_t) if an I2C Read or Write
* cycle has occurred since the last time this function was called.
* See \ref subsection_ezi2c_snippet_2
*
* @param[in] obj The EZI2C object
*
@ -169,7 +204,9 @@ void cyhal_ezi2c_free(cyhal_ezi2c_t *obj);
*/
cyhal_ezi2c_status_t cyhal_ezi2c_get_activity_status(cyhal_ezi2c_t *obj);
/** The EZI2C event callback handler registration
/** Register a EZI2C event callback handler
*
* See \ref subsection_ezi2c_snippet_2
*
* @param[in] obj The EZI2C object
* @param[in] callback The callback handler which will be invoked when an event triggers
@ -177,7 +214,14 @@ cyhal_ezi2c_status_t cyhal_ezi2c_get_activity_status(cyhal_ezi2c_t *obj);
*/
void cyhal_ezi2c_register_callback(cyhal_ezi2c_t *obj, cyhal_ezi2c_event_callback_t callback, void *callback_arg);
/** Configure and Enable or Disable EZI2C Interrupt.
*
* @param[in] obj The EZI2C object
* @param[in] event The EZI2C event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_ezi2c_enable_event(cyhal_ezi2c_t *obj, cyhal_ezi2c_status_t event, uint8_t intr_priority, bool enable);
#if defined(__cplusplus)
}

View File

@ -26,31 +26,88 @@
*******************************************************************************/
/**
* \addtogroup group_hal_flash Flash
* \addtogroup group_hal_flash Flash (Flash System Routine)
* \ingroup group_hal
* \{
* High level interface for interacting with internal flash memory.
* High level interface to the internal flash memory.
*
* This driver allows data to be read from and written to flash. It also
* provides the ability to obtain information about the address and
* characteristics of the flash block(s) contained on the device.
* Flash memory provides non-volatile storage for user firmware, user configuration
* data, and bulk data storage.
*
* This driver allows data to be read from and written to flash. It also provides the
* ability to obtain information about the address and characteristics of the flash
* block(s) contained on the device. During flash write time, the device should not be
* reset (including XRES pin, software reset, and watchdog) or unexpected changes may
* be made to portions of the flash. Also, the low-voltage detect circuits should be
* configured to generate an interrupt instead of a reset.
*
* \note A Read while Write violation may occur for some devices when a flash Read
* operation is initiated in the same or neighboring flash sector where the flash
* Write, Erase, or Program operation is working. Refer the the device datasheet
* for more information. This violation may cause a HardFault exception. To avoid
* the Read while Write violation, the user must carefully split the Read and Write
* operations on flash sectors which are not neighboring, considering all cores in
* a multi-processor device. You may edit the linker script to place the code into
* neighboring sectors. For example, use sectors number 0 and 1 for code and sectors
* 2 and 3 for data storage.
*
* \section features Features
* * Flash operations are performed on a per-sector basis
* * Supports blocking or partially blocking erase, program and write
* \section code_snippet Code Snippets
* \subsection subsection_flash_use_case_1 Snippet 1: Discovering flash characteristics
* Following code snippet demonstrates how to discover flash characteristics. Refer \ref
* cyhal_flash_info_t for more information.
* \snippet flash.c snippet_cyhal_flash_get_flash_info
*
* \subsection subsection_flash_use_case_2 Snippet 2: Blocking Flash Write Operation
* Following code snippet demonstrates blocking flash write.
* It uses a constant array with a size equaling the size of one flash row. This
* array is placed at an address in flash such that it occupies one complete flash row.
* It uses blocking flash write operation which blocks the caller until the write is
* completed. It then verifies the flash data by comparing the flash data with the
* written data.
* \snippet flash.c flag_snippet_cyhal_flash_blocking_mode_flashwrite
* \note It is recommended to declare the flash array as global variable.
*
* \subsection subsection_flash_use_case_3 Snippet 3: Non-blocking Flash Write Operation using polling
* Following code snippet implements the non-blocking flash write using polling to
* complete the flash write operation. It uses a constant array with a size equaling
* the size of one flash row. This array is placed at an address in flash such that it
* occupies one complete flash row. It uses a polling method to complete the flash
* write operation. It then verifies the flash data by comparing the flash data with
* the written data.
* \snippet flash.c flag_snippet_cyhal_flash_partially_blocking_mode_polling_flashwrite
* \note It is recommended to declare the flash array as global variable.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* Defines
*******************************************************************************/
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name Flash Results
*/
/** Invalid argument */
#define CYHAL_FLASH_RSLT_ERR_ADDRESS (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_FLASH, 0))
#define CYHAL_FLASH_RSLT_ERR_ADDRESS \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_FLASH, 0))
/** Unable to support due to power state */
/**
* \} \}
*/
/** @brief Information about a single block of flash memory */
typedef struct
@ -58,7 +115,7 @@ typedef struct
uint32_t start_address; //!< Start address of the memory
uint32_t size; //!< Size of the flash memory
uint32_t sector_size; //!< Sector size of the memory
uint32_t page_size; //!< Sector size of the memory
uint32_t page_size; //!< Page size of the memory
uint8_t erase_value; //!< The flash erase value
} cyhal_flash_block_info_t;
@ -69,131 +126,150 @@ typedef struct
const cyhal_flash_block_info_t *blocks; //!< Array of the distinct flash blocks
} cyhal_flash_info_t;
/*******************************************************************************
* Functions
*******************************************************************************/
/** Initialize the flash_t object for access to flash through the HAL
/** Initialize the \ref cyhal_flash_t object for accessing flash through the HAL
*
* @param[out] obj The flash object
* @return The status of the init request
* @param[out] obj Pointer to a flash object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @return The status of the init request. Returns \ref CY_RSLT_SUCCESS on successful operation.
*/
cy_rslt_t cyhal_flash_init(cyhal_flash_t *obj);
/** Free resources associated with access to flash through the HAL
/** Free resources associated with flash object through the HAL.
*
* @param[out] obj The flash object.
*
*/
void cyhal_flash_free(cyhal_flash_t *obj);
/** Gets key flash characteristics including the start address size,
* and erase values
/** Gets flash characteristics like the start address, size, erase values etc.
* Refer \ref cyhal_flash_info_t for more information.
*
* @param[in] obj The flash object.
* @param[out] info The flash configuration info.
* @param[out] info The flash characteristic info.
*
* Refer \ref subsection_flash_use_case_1 for more information.
*/
void cyhal_flash_get_info(const cyhal_flash_t *obj, cyhal_flash_info_t *info);
/** Read data starting at defined address
/** Read data starting at a defined address.
*
* @param[in] obj The flash object.
* @param[in] address Address to begin reading from.
* @param[out] data The buffer to read data into.
* @param[in] size The number of bytes to read.
* @return The status of the read request.
* @return The status of the read request. Returns \ref CY_RSLT_SUCCESS on successful operation.
*
* Refer \ref subsection_flash_use_case_2 for more information.
*
*/
cy_rslt_t cyhal_flash_read(cyhal_flash_t *obj, uint32_t address, uint8_t *data, size_t size);
/** Erase one page starting at defined address. The address must be at page boundary. This
/** Erase one page starting at a defined address. The address must be at page boundary. This
* will block until the erase operation is complete.
*
* @see cyhal_flash_get_info() to get the flash charactoristics for legal address values and
* the total erase size.
* @see cyhal_flash_get_info() to get the flash characteristics for legal address values and
* the page erase size.
*
* @param[in] obj The flash object
* @param[in] address The page starting address
* @return The status of the erase request
* @return The status of the erase request. Returns \ref CY_RSLT_SUCCESS on successful operation.
*
* Refer \ref subsection_flash_use_case_2 for more information.
*/
cy_rslt_t cyhal_flash_erase(cyhal_flash_t *obj, uint32_t address);
/** Write one page starting at defined address. The address must be at page boundary. This
/** This function erases the page and writes the new data into the page starting at a defined address. The address must be at page boundary. This
* will block until the write operation is complete.
* This function erases the page prior to writing the new data.
*
* @see cyhal_flash_get_info() to get the flash charactoristics for legal address values and
* the total write size. The provided data buffer must be at least as large as the flash
*
* @see cyhal_flash_get_info() to get the flash characteristics for legal address values and
* the page write size. The provided data buffer must be at least as large as the flash
* page_size.
*
* @param[in] obj The flash object
* @param[in] address The page starting address
* @param[in] data The data to write to the flash
* @return The status of the write request
* @return The status of the write request. Returns \ref CY_RSLT_SUCCESS on successful operation.
*
* Refer \ref subsection_flash_use_case_2 for more information.
*/
cy_rslt_t cyhal_flash_write(cyhal_flash_t *obj, uint32_t address, const uint32_t *data);
/** Program one page starting at defined address. The address must be at page boundary. This
/** Program one page with given data starting at defined address. The address must be at page boundary. This
* will block until the write operation is complete.
* Note: This function does not erase the page prior to writing. The page must be erased
* \note This function does not erase the page prior to writing. The page must be erased
* first via a separate call to erase.
*
* @see cyhal_flash_get_info() to get the flash charactoristics for legal address values and
* the total program size. The provided data buffer must be at least as large as the flash
* @see cyhal_flash_get_info() to get the flash characteristics for legal address values and
* the total page size. The provided data buffer must be at least as large as the flash
* page_size.
*
* @param[in] obj The flash object
* @param[in] address The sector starting address
* @param[in] data The data buffer to be programmed
* @return The status of the program request
* @return The status of the program request. Returns \ref CY_RSLT_SUCCESS on successful operation.
*/
cy_rslt_t cyhal_flash_program(cyhal_flash_t *obj, uint32_t address, const uint32_t *data);
/** Starts an asynchronous erase of a single page of flash. Returns immediately and reports
* a successful start or reason for failure.
* a successful start or reason for failure. The address must be aligned on a page boundary.
*
* @see cyhal_flash_get_info() to get the flash charactoristics for legal address values and
* the total erase size.
* @see cyhal_flash_get_info() to get the flash characteristics for legal address values and
* the page erase size.
*
* @param[in] obj The Flash object being operated on
* @param[in] address The address to start erasing from
* @return The status of the start_erase request
* @return The status of the start_erase request.
*
* Refer \ref subsection_flash_use_case_3 for more information.
*/
cy_rslt_t cyhal_flash_start_erase(cyhal_flash_t *obj, uint32_t address);
/** Starts an asynchronous write to a single page of flash. Returns immediately and reports
* a successful start or reason for failure.
* a successful start or reason for failure. The address must be aligned on a page boundary.
*
* @see cyhal_flash_get_info() to get the flash charactoristics for legal address values and
* the total write size. The provided data buffer must be at least as large as the flash
* @see cyhal_flash_get_info() to get the flash characteristics for legal address values and
* the page write size. The provided data buffer must be at least as large as the flash
* page_size.
*
* @param[in] obj The Flash object being operated on
* @param[in] address The address to start writing to
* @param[in] data The data to write to flash
* @return The status of the start_write request
* @return The status of the start_write request.
*
* Refer \ref subsection_flash_use_case_3 for more information.
*/
cy_rslt_t cyhal_flash_start_write(cyhal_flash_t *obj, uint32_t address, const uint32_t* data);
/** Starts asynchronous programming of a single page of flash. Returns immediately and reports
* a successful start or reason for failure.
*
* @see cyhal_flash_get_info() to get the flash charactoristics for legal address values and
* the total program size. The provided data buffer must be at least as large as the flash
* \note Perform erase operation prior to calling this.
*
* @see cyhal_flash_get_info() to get the flash characteristics for legal address values and
* the total page size. The provided data buffer must be at least as large as the flash
* page_size.
*
* @param[in] obj The Flash object being operated on
* @param[in] address The address to start programming
* @param[in] data The data to write to flash
* @return The status of the start_program request
* @return The status of the start_program request. Returns \ref CY_RSLT_SUCCESS on successful operation.
*/
cy_rslt_t cyhal_flash_start_program(cyhal_flash_t *obj, uint32_t address, const uint32_t* data);
/** Reports a successful operation result, reason of failure or busy status
/** Reports status of the flash operation
*
* @param[in] obj The Flash object being operated on
* @return Whether the flash operation is complete
* @return true if flash operation is complete. false otherwise.
*/
bool cyhal_flash_is_operation_complete(cyhal_flash_t *obj);
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,216 @@
/***************************************************************************//**
* \file cyhal_general_types.h
*
* \brief
* Provides basic types that are used across different HAL drivers.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
/**
* \addtogroup group_hal_general_types General Types
* \ingroup group_hal_types
* \{
* This section documents the basic types that are used by multiple HAL drivers.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "cy_result.h"
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_hal_results Result Codes
* \ingroup group_hal_types
* \{
* HAL specific return codes definitions for all drivers. HAL drivers are generally
* built on top of a lower level driver. In this case the errors returned from the
* HAL could be one of the values below or a value from that lower level driver.
* See the device specific documentation for details about the other error codes.
*/
/** \cond INTERNAL */
/** Generate a result code specific to the HAL driver */
#define CYHAL_RSLT_CREATE(type, driver, code) \
(CY_RSLT_CREATE(type, CY_RSLT_MODULE_ABSTRACTION_HAL_BASE, ((uint16_t)driver | (uint16_t)code)))
/** \endcond */
/**
* Enum to specify module IDs for \ref cy_rslt_t values returned from the HAL.
*/
enum cyhal_rslt_module_chip
{
CYHAL_RSLT_MODULE_HWMGR = (0x01 << 8), //!< An error occurred in hardware management module
CYHAL_RSLT_MODULE_ADC = (0x02 << 8), //!< An error occurred in ADC module
CYHAL_RSLT_MODULE_CLOCK = (0x03 << 8), //!< An error occurred in Clock module
CYHAL_RSLT_MODULE_COMP = (0x04 << 8), //!< An error occurred in comparator module
CYHAL_RSLT_MODULE_CRC = (0x05 << 8), //!< An error occurred in crypto CRC module
CYHAL_RSLT_MODULE_DAC = (0x06 << 8), //!< An error occurred in DAC module
CYHAL_RSLT_MODULE_DMA = (0x07 << 8), //!< An error occurred in DMA module
CYHAL_RSLT_MODULE_EZI2C = (0x08 << 8), //!< An error occurred in EZI2C module
CYHAL_RSLT_MODULE_FLASH = (0x09 << 8), //!< An error occurred in flash module
CYHAL_RSLT_MODULE_GPIO = (0x0A << 8), //!< An error occurred in GPIO module
CYHAL_RSLT_MODULE_I2C = (0x0B << 8), //!< An error occurred in I2C module
CYHAL_RSLT_MODULE_I2S = (0x0C << 8), //!< An error occurred in I2S module
CYHAL_RSLT_MODULE_INTERCONNECT = (0x0D << 8), //!< An error occurred in Interconnect module
CYHAL_RSLT_MODULE_OPAMP = (0x0E << 8), //!< An error occurred in OpAmp module
CYHAL_RSLT_MODULE_PDMPCM = (0x0F << 8), //!< An error occurred in PDM/PCM module
CYHAL_RSLT_MODULE_PWM = (0x10 << 8), //!< An error occurred in PWM module
CYHAL_RSLT_MODULE_QSPI = (0x11 << 8), //!< An error occurred in QSPI module
CYHAL_RSLT_MODULE_RTC = (0x12 << 8), //!< An error occurred in RTC module
CYHAL_RSLT_MODULE_SDHC = (0x13 << 8), //!< An error occurred in SDHC module
CYHAL_RSLT_MODULE_SDIO = (0x14 << 8), //!< An error occurred in SDIO module
CYHAL_RSLT_MODULE_SPI = (0x15 << 8), //!< An error occurred in SPI module
CYHAL_RSLT_MODULE_SYSPM = (0x16 << 8), //!< An error occurred in SysPM module
CYHAL_RSLT_MODULE_SYSTEM = (0x17 << 8), //!< An error occurred in System module
CYHAL_RSLT_MODULE_TIMER = (0x18 << 8), //!< An error occurred in Timer module
CYHAL_RSLT_MODULE_TRNG = (0x19 << 8), //!< An error occurred in RNG module
CYHAL_RSLT_MODULE_UART = (0x1A << 8), //!< An error occurred in UART module
CYHAL_RSLT_MODULE_USB = (0x1B << 8), //!< An error occurred in USB module
CYHAL_RSLT_MODULE_WDT = (0x1C << 8), //!< An error occurred in WDT module
};
/**
* \} group_hal_results
*/
/** Modes that can be used for asynchronous transfers */
typedef enum {
/** Use DMA if available. Otherwise fall back to software transfer. (Default) */
CYHAL_ASYNC_DMA,
/** Always perform a software transfer */
CYHAL_ASYNC_SW,
} cyhal_async_mode_t;
/**
* \addtogroup group_hal_syspm System Power Management
* \ingroup group_hal
* \{
*/
/** Flags enum for the cpu state in a custom callback. This is used to indicate what
* states a callback should be called in. When a callback is called, only one of these
* will be set at a time.
*/
typedef enum
{
CYHAL_SYSPM_CB_CPU_SLEEP = 0x01U, /**< Flag for MCU sleep callback. */
CYHAL_SYSPM_CB_CPU_DEEPSLEEP = 0x02U, /**< Flag for MCU deep sleep callback. */
CYHAL_SYSPM_CB_SYSTEM_HIBERNATE = 0x04U, /**< Flag for Hibernate callback. */
CYHAL_SYSPM_CB_SYSTEM_NORMAL = 0x08U, /**< Flag for Normal mode callback. */
CYHAL_SYSPM_CB_SYSTEM_LOW = 0x10U, /**< Flag for Low power mode callback. */
} cyhal_syspm_callback_state_t;
/** Define for enabling all system and MCU state callbacks .*/
#define CYHAL_SYSPM_CALLBACK_STATE_ALL (CYHAL_SYSPM_CB_CPU_SLEEP\
| CYHAL_SYSPM_CB_CPU_DEEPSLEEP\
| CYHAL_SYSPM_CB_SYSTEM_HIBERNATE\
| CYHAL_SYSPM_CB_SYSTEM_NORMAL\
| CYHAL_SYSPM_CB_SYSTEM_LOW)
/** Enumeration of the transition modes in custom callback. The general sequence
* is: CHECK_READY, BEFORE_TRANSITION, AFTER_TRANSITION.
* If any callback indicates that it is not able to change state as part of
* CHECK_READY, CHECK_FAIL will be run instead of the BEFORE/AFTER_TRANSITION.
*/
typedef enum
{
CYHAL_SYSPM_CHECK_READY = 0x01U, /**< Callbacks with this mode are executed before entering into the
low power mode. The purpose of this transition state is to check
if the device is ready to enter the low power mode. The application
must not perform any actions that would prevent transition after
returning true for this mode. */
CYHAL_SYSPM_CHECK_FAIL = 0x02U, /**< Callbacks with this mode are only executed if the callback returned true
for CYHAL_SYSPM_CHECK_READY and a later callback returns false for
CYHAL_SYSPM_CHECK_READY. This mode should roll back any changes made
to avoid blocking transition made in CYHAL_SYSPM_CHECK_READY mode*/
CYHAL_SYSPM_BEFORE_TRANSITION = 0x04U, /**< Callbacks with this mode are executed after the CYHAL_SYSPM_CHECK_READY
callbacks' execution returns true. In this mode, the application must
perform the actions to be done before entering into the low power mode. */
CYHAL_SYSPM_AFTER_TRANSITION = 0x08U, /**< In this mode, the application must perform the actions to be done after
exiting the low power mode. */
} cyhal_syspm_callback_mode_t;
/** The system wide custom action power callback type.
*
* @param[in] state State the system or CPU is being transitioned into.
* @param[in] mode Callback mode.
* @param[in] callback_arg User argument passed as part of registering callback in @ref cyhal_syspm_register_callback.
* @return If mode is @ref CYHAL_SYSPM_CHECK_READY, then this indicates whether the low power mode should be allowed (true) or not (false).
Otherwise the return value is ignored.
*/
typedef bool (*cyhal_syspm_callback_t)(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
/** Power management callback data object. This is used to register a new
* callback handler for power management transitions. The specific power
* states to register for can be specified as well as any modes
*/
typedef struct cyhal_syspm_callback_data
{
/** Callback to run on power state change */
cyhal_syspm_callback_t callback;
/** Power states that should trigger calling the callback. Multiple
* \ref cyhal_syspm_callback_state_t values can be ored together. */
cyhal_syspm_callback_state_t states;
/** Modes to ignore invoking the callback for. Multiple
* \ref cyhal_syspm_callback_mode_t values can be ored together. */
cyhal_syspm_callback_mode_t ignore_modes;
/** Argument value to provide to the callback. */
void *args;
/** Pointer to the next callback strucure. This should be initialized to NULL. */
struct cyhal_syspm_callback_data *next;
} cyhal_syspm_callback_data_t;
/**
* \} group_hal_syspm_apis
*/
/**
* \addtogroup group_hal_clock
* \{
*/
/** Enum defining the different ways of specifying the acceptable clock tolerance. */
typedef enum
{
CYHAL_TOLERANCE_HZ, //!< Clock tolerance specified directly in Hertz.
CYHAL_TOLERANCE_PPM, //!< Clock tolerance specified in parts-per-million.
CYHAL_TOLERANCE_PERCENT, //!< Clock tolerance specified in a percent.
} cyhal_clock_tolerance_unit_t;
/** Structure defining a clock tolerance. */
typedef struct
{
cyhal_clock_tolerance_unit_t type; //!< The type of the clock tolerance value.
uint32_t value; //!< The tolerance value to use.
} cyhal_clock_tolerance_t;
/**
* \} group_hal_clock
*/
#if defined(__cplusplus)
}
#endif
/** \} group_hal_general_types */

View File

@ -96,7 +96,7 @@ extern "C" {
*******************************************************************************/
/** Integer representation of no connect pin (required to exist in all BSPs) */
#define CYHAL_NC_PIN_VALUE ((cyhal_gpio_t)0xFFFFFFFF)
#define CYHAL_NC_PIN_VALUE (NC)
/*******************************************************************************
* Enumerations
@ -104,10 +104,10 @@ extern "C" {
/** Pin events */
typedef enum {
CYHAL_GPIO_IRQ_NONE, /**< No interrupt */
CYHAL_GPIO_IRQ_RISE, /**< Interrupt on rising edge */
CYHAL_GPIO_IRQ_FALL, /**< Interrupt on falling edge */
CYHAL_GPIO_IRQ_BOTH, /**< Interrupt on both rising and falling edges */
CYHAL_GPIO_IRQ_NONE = 0, /**< No interrupt */
CYHAL_GPIO_IRQ_RISE = 1 << 0, /**< Interrupt on rising edge */
CYHAL_GPIO_IRQ_FALL = 1 << 1, /**< Interrupt on falling edge */
CYHAL_GPIO_IRQ_BOTH = (CYHAL_GPIO_IRQ_RISE | CYHAL_GPIO_IRQ_FALL), /**< Interrupt on both rising and falling edges */
} cyhal_gpio_event_t;
/** Pin direction */
@ -125,15 +125,15 @@ typedef enum {
* If not, the <b> drive_mode </b> of the <b> pin </b> is set to <b> CYHAL_GPIO_DRIVE_NONE</b>.
*/
typedef enum {
CYHAL_GPIO_DRIVE_NONE, /**< Digital Hi-Z */
CYHAL_GPIO_DRIVE_ANALOG, /**< Analog Hi-Z */
CYHAL_GPIO_DRIVE_PULLUP, /**< Pull-up resistor */
CYHAL_GPIO_DRIVE_PULLDOWN, /**< Pull-down resistor */
CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW, /**< Open-drain, Drives Low */
CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH, /**< Open-drain, Drives High */
CYHAL_GPIO_DRIVE_STRONG, /**< Strong output */
CYHAL_GPIO_DRIVE_PULLUPDOWN, /**< Pull-up and pull-down resistors */
CYHAL_GPIO_DRIVE_PULL_NONE, /**< No Pull-up or pull-down resistors */
CYHAL_GPIO_DRIVE_NONE, /**< Digital Hi-Z. Input only. Input init value(s): 0 or 1 */
CYHAL_GPIO_DRIVE_ANALOG, /**< Analog Hi-Z. Use only for analog purpose */
CYHAL_GPIO_DRIVE_PULLUP, /**< Pull-up resistor. Input and output. Input init value(s): 1, output value(s): 0 */
CYHAL_GPIO_DRIVE_PULLDOWN, /**< Pull-down resistor. Input and output. Input init value(s): 0, output value(s): 1 */
CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW, /**< Open-drain, Drives Low. Input and output. Input init value(s): 1, output value(s): 0 */
CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH, /**< Open-drain, Drives High. Input and output. Input init value(s): 0, output value(s): 1 */
CYHAL_GPIO_DRIVE_STRONG, /**< Strong output. Output only. Output init value(s): 0 or 1 */
CYHAL_GPIO_DRIVE_PULLUPDOWN, /**< Pull-up and pull-down resistors. Input and output. Input init value(s): 0 or 1, output value(s): 0 or 1 */
CYHAL_GPIO_DRIVE_PULL_NONE, /**< No Pull-up or pull-down resistors. Input and output. Input init value(s): 0 or 1, output value(s): 0 or 1 */
} cyhal_gpio_drive_mode_t;
/** GPIO callback function type */
@ -152,6 +152,13 @@ typedef void (*cyhal_gpio_event_callback_t)(void *callback_arg, cyhal_gpio_event
* @param[in] init_val Initial value on the pin
*
* @return The status of the init request
*
* Guidance for using gpio drive modes ( \ref cyhal_gpio_drive_mode_t for details).
* For default use drive modes:
* Input GPIO direction - \ref CYHAL_GPIO_DRIVE_NONE
* Output GPIO direction - \ref CYHAL_GPIO_DRIVE_STRONG
* Bidirectional GPIO - \ref CYHAL_GPIO_DRIVE_PULLUPDOWN
* \warning Don't use \ref CYHAL_GPIO_DRIVE_STRONG for input GPIO direction. It may cause an overcurrent issue.
*/
cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode, bool init_val);
@ -164,13 +171,13 @@ void cyhal_gpio_free(cyhal_gpio_t pin);
/** Configure the GPIO pin <br>
* See \ref subsection_gpio_snippet_3.
*
* @param[in] pin The GPIO pin
* @param[in] direction The pin direction
* @param[in] drvMode The pin drive mode
* @param[in] pin The GPIO pin
* @param[in] direction The pin direction
* @param[in] drive_mode The pin drive mode
*
* @return The status of the configure request
*/
cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drvMode);
cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode);
/** Set the output value for the pin. This only works for output & in_out pins. <br>
* See \ref subsection_gpio_snippet_2.
@ -195,6 +202,9 @@ bool cyhal_gpio_read(cyhal_gpio_t pin);
void cyhal_gpio_toggle(cyhal_gpio_t pin);
/** Register/clear a callback handler for pin events <br>
*
* This function will be called when one of the events enabled by \ref cyhal_gpio_enable_event occurs.
*
* See \ref subsection_gpio_snippet_4.
*
* @param[in] pin The pin number
@ -204,6 +214,9 @@ void cyhal_gpio_toggle(cyhal_gpio_t pin);
void cyhal_gpio_register_callback(cyhal_gpio_t pin, cyhal_gpio_event_callback_t callback, void *callback_arg);
/** Enable or Disable the specified GPIO event <br>
*
* When an enabled event occurs, the function specified by \ref cyhal_gpio_register_callback will be called.
*
* See \ref subsection_gpio_snippet_4.
*
* @param[in] pin The GPIO object

View File

@ -2,7 +2,7 @@
* \file cyhal_hw_resources.h
*
* \brief
* Provides a struct definitions for configuration resources in the PDL.
* Provides struct definitions for configuration resources in the PDL.
*
********************************************************************************
* \copyright
@ -30,6 +30,8 @@
#pragma once
#include "cy_pdl.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -41,8 +43,8 @@ typedef enum
CYHAL_RSC_ADC, /*!< Analog to digital converter */
CYHAL_RSC_BLESS, /*!< Bluetooth communications block */
CYHAL_RSC_CAN, /*!< CAN communication block */
CYHAL_RSC_CLKPATH, /*!< System clock clock path, used to drive hfclks */
CYHAL_RSC_CLOCK, /*!< Clock divider */
CYHAL_RSC_CLKPATH, /*!< Clock Path. DEPRECATED. */
CYHAL_RSC_CLOCK, /*!< Clock */
CYHAL_RSC_CRYPTO, /*!< Crypto hardware accelerator */
CYHAL_RSC_DAC, /*!< Digital to analog converter */
CYHAL_RSC_DMA, /*!< DMA controller */
@ -64,8 +66,65 @@ typedef enum
CYHAL_RSC_INVALID, /*!< Placeholder for invalid type */
} cyhal_resource_t;
/* NOTE: Any changes here must also be made in cyhal_hwmgr.c */
/** Enum for the different types of clocks that exist on the device. */
typedef enum
{
// The first four items are here for backwards compatability with old clock APIs
CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT = CY_SYSCLK_DIV_8_BIT, /*!< 8bit Peripheral Divider */
CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT = CY_SYSCLK_DIV_16_BIT, /*!< 16bit Peripheral Divider */
CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT = CY_SYSCLK_DIV_16_5_BIT, /*!< 16.5bit Peripheral Divider */
CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT = CY_SYSCLK_DIV_24_5_BIT, /*!< 24.5bit Peripheral Divider */
CYHAL_CLOCK_BLOCK_IMO, /*!< Internal Main Oscillator Input Clock */
CYHAL_CLOCK_BLOCK_ECO, /*!< External Crystal Oscillator Input Clock */
CYHAL_CLOCK_BLOCK_EXT, /*!< External Input Clock */
CYHAL_CLOCK_BLOCK_ALTHF, /*!< Alternate High Frequency Input Clock */
CYHAL_CLOCK_BLOCK_ALTLF, /*!< Alternate Low Frequency Input Clock */
CYHAL_CLOCK_BLOCK_ILO, /*!< Internal Low Speed Oscillator Input Clock */
CYHAL_CLOCK_BLOCK_PILO, /*!< Precision ILO Input Clock */
CYHAL_CLOCK_BLOCK_WCO, /*!< Watch Crystal Oscillator Input Clock */
CYHAL_CLOCK_BLOCK_MFO, /*!< Medium Frequency Oscillator Clock */
CYHAL_CLOCK_BLOCK_PATHMUX, /*!< Path selection mux for input to FLL/PLLs */
CYHAL_CLOCK_BLOCK_FLL, /*!< Frequency-Locked Loop Clock */
CYHAL_CLOCK_BLOCK_PLL, /*!< Phase-Locked Loop Clock */
CYHAL_CLOCK_BLOCK_LF, /*!< Low Frequency Clock */
CYHAL_CLOCK_BLOCK_MF, /*!< Medium Frequency Clock */
CYHAL_CLOCK_BLOCK_HF, /*!< High Frequency Clock */
CYHAL_CLOCK_BLOCK_PUMP, /*!< Analog Pump Clock */
CYHAL_CLOCK_BLOCK_BAK, /*!< Backup Power Domain Clock */
CYHAL_CLOCK_BLOCK_TIMER, /*!< Timer Clock */
CYHAL_CLOCK_BLOCK_ALT_SYS_TICK, /*!< Alternative SysTick Clock */
CYHAL_CLOCK_BLOCK_FAST, /*!< Fast Clock for CM4 */
CYHAL_CLOCK_BLOCK_PERI, /*!< Peripheral Clock */
CYHAL_CLOCK_BLOCK_SLOW, /*!< Slow Clock for CM0+ */
} cyhal_clock_block_t;
/** @brief Clock object
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases. */
typedef struct
{
//For backwards compatibility with cyhal_clock_divider_t only. Do not use going forward.
cy_en_divider_types_t div_type; /*!< Deprecated */
uint8_t div_num; /*!< Deprecated */
//End BWC items
cyhal_clock_block_t block;
uint8_t channel;
bool reserved;
} cyhal_clock_t;
/**
* @brief Represents a particular instance of a resource on the chip
* @brief Represents a particular instance of a resource on the chip.
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct
{

View File

@ -29,10 +29,51 @@
* All information within this section is platform specific and is provided for reference.
* Portable application code should depend only on the APIs and types which are documented
* in the @ref group_hal section.
*
* \section group_hal_psoc6_mapping HAL Resource Hardware Mapping
* The following table shows a mapping of each HAL driver to the lower level firmware driver
* and the corresponding hardware resource. This is intended to help understand how the HAL
* is implemented for PSoC 6 and what features the underlying hardware supports.
*
* | HAL Resource | PDL Driver(s) | PSoC 6 Hardware |
* | ---------------- | ------------------- | -------------------------------- |
* | ADC | cy_adc | SAR ADC |
* | Clock | cy_sysclk | All clocks (system & peripheral) |
* | CRC | cy_crypto_core_crc | Crypto |
* | DAC | cy_ctdac | DAC |
* | DMA | cy_dma, cy_dmac | DMA Controller |
* | EZI2C | cy_scb_ezi2c | SCB |
* | Flash | cy_flash | Flash |
* | GPIO | cy_gpio | GPIO |
* | Hardware Manager | NA | NA |
* | I2C | cy_scb_i2c | SCB |
* | I2S | cy_i2s | I2S |
* | LPTimer | cy_mcwdt | MCWDT |
* | PDM/PCM | cy_pdm_pcm | PDM-PCM |
* | PWM | cy_pwm | TCPWM |
* | QSPI | cy_smif | QSPI (SMIF) |
* | RTC | cy_rtc | RTC |
* | SDHC | cy_sd_host | SD Host |
* | SDIO | cy_sd_host, or NA | SD Host, or UDB |
* | SPI | cy_scb_spi | SCB |
* | SysPM | cy_syspm | System Power Resources |
* | System | cy_syslib | System Resources |
* | Timer | cy_tcpwm_counter | TCPWM |
* | TRNG | cy_crypto_core_trng | Crypto |
* | UART | cy_scb_uart | SCB |
* | USB Device | cy_usbfs_dev_drv | USB-FS |
* | WDT | cy_wdt | WDT |
*
* \section group_hal_psoc6_errors Device Specific Errors
* Error codes generated by the low level level PDL driver all use module IDs starting
* with \ref CY_RSLT_MODULE_DRIVERS_PDL_BASE. The exact errors are documented for each
* driver in the
* <a href="https://cypresssemiconductorco.github.io/psoc6pdl/pdl_api_reference_manual/html/index.html">
* psoc6pdl documentation</a>.
*/
/**
* \addtogroup group_hal_psoc6_hw_types PSoC6 Specific Hardware Types
* \addtogroup group_hal_psoc6_hw_types PSoC 6 Specific Hardware Types
* \{
* Aliases for types which are part of the public HAL interface but whose representations
* need to vary per HAL implementation
@ -41,6 +82,7 @@
#pragma once
#include "cy_pdl.h"
#include "cyhal_general_types.h"
#include "cyhal_hw_resources.h"
#include "cyhal_pin_package.h"
#include "cyhal_triggers.h"
@ -68,9 +110,11 @@ extern "C" {
#define CYHAL_CRC_IMPL_HEADER "cyhal_crc_impl.h" //!< Implementation specific header for CRC
#define CYHAL_DMA_IMPL_HEADER "cyhal_dma_impl.h" //!< Implementation specific header for DMA
#define CYHAL_CLOCK_IMPL_HEADER "cyhal_clock_impl.h" //!< Implementation specific header for Clocks
#define CYHAL_GPIO_IMPL_HEADER "cyhal_gpio_impl.h" //!< Implementation specific header for GPIO
#define CYHAL_PWM_IMPL_HEADER "cyhal_pwm_impl.h" //!< Implementation specific header for PWM
#define CYHAL_SYSTEM_IMPL_HEADER "cyhal_system_impl.h" //!< Implementation specific header for System
#define CYHAL_SYSPM_IMPL_HEADER "cyhal_syspm_impl.h" //!< Implementation specific header for System Power Management
#define CYHAL_TIMER_IMPL_HEADER "cyhal_timer_impl.h" //!< Implementation specific header for Timer
#define CYHAL_TRNG_IMPL_HEADER "cyhal_trng_impl.h" //!< Implementation specific header for TRNG
@ -83,38 +127,47 @@ typedef uint32_t cyhal_source_t; //!< Routable signal source
/** Callbacks for Sleep and Deepsleep APIs */
#define cyhal_system_callback_t cy_stc_syspm_callback_t
/** Available clock divider types */
typedef cy_en_divider_types_t cyhal_clock_divider_types_t;
/** Divider for CM4, CM0 and Peri clock. Supports values between [1, 256] */
typedef uint16_t cyhal_system_divider_t;
/** Enum for clock type to configure. HFCLKs are configured using different APIs and does not using this enum */
typedef enum
{
CYHAL_SYSTEM_CLOCK_CM4,
CYHAL_SYSTEM_CLOCK_CM0,
CYHAL_SYSTEM_CLOCK_PERI,
} cyhal_system_clock_t;
/** @brief Clock divider object */
typedef struct {
cyhal_clock_divider_types_t div_type;
uint8_t div_num;
} cyhal_clock_divider_t;
/** @brief Event callback data object */
typedef struct {
cy_israddress callback;
void* callback_arg;
} cyhal_event_callback_data_t;
/** @brief ADC object */
/**
* @brief Shared data between timer/counter and PWM
*
* Application code should not rely on the specific content of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct cyhal_tcpwm_common {
#ifdef CY_IP_MXTCPWM
TCPWM_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin;
cyhal_clock_t clock;
bool dedicated_clock;
uint32_t clock_hz;
cyhal_event_callback_data_t callback_data;
cyhal_gpio_t pin_compl; /* PWM Only */
uint32_t default_value; /* Timer only */
#else
void *empty
#endif
} cyhal_tcpwm_common_t;
/**
* @brief ADC object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXS40PASS_SAR
SAR_Type* base;
cyhal_resource_inst_t resource;
cyhal_clock_divider_t clock;
cyhal_clock_t clock;
bool dedicated_clock;
// channel_used is a bit field. The maximum channel count
// supported by the SAR IP is 16
@ -124,7 +177,13 @@ typedef struct {
#endif
} cyhal_adc_t;
/** @brief ADC channel object */
/**
* @brief ADC channel object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXS40PASS_SAR
cyhal_adc_t* adc;
@ -135,7 +194,13 @@ typedef struct {
#endif
} cyhal_adc_channel_t;
/** @brief CRC object */
/**
* @brief CRC object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#if defined(CY_IP_MXCRYPTO_INSTANCES) || defined(CPUSS_CRYPTO_PRESENT)
CRYPTO_Type* base;
@ -144,7 +209,13 @@ typedef struct {
#endif
} cyhal_crc_t;
/** @brief DAC object */
/**
* @brief DAC object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXS40PASS_CTDAC
CTDAC_Type* base;
@ -155,7 +226,13 @@ typedef struct {
#endif
} cyhal_dac_t;
/** @brief DMA object */
/**
* @brief DMA object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#if defined(CY_IP_M4CPUSS_DMAC) || defined(CY_IP_M4CPUSS_DMA)
cyhal_resource_inst_t resource;
@ -193,43 +270,60 @@ typedef struct {
#endif
} cyhal_dma_t;
/** @brief Flash object */
/**
* @brief Flash object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
void *empty;
} cyhal_flash_t;
/** @brief I2C object */
/**
* @brief I2C object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXSCB
CySCB_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_sda;
cyhal_gpio_t pin_scl;
cyhal_clock_divider_t clock;
bool is_shared_clock;
cy_stc_scb_i2c_context_t context;
cy_stc_scb_i2c_master_xfer_config_t rx_config;
cy_stc_scb_i2c_master_xfer_config_t tx_config;
bool is_slave;
bool async;
uint32_t address;
uint32_t irq_cause;
uint16_t pending;
uint16_t events;
cyhal_event_callback_data_t callback_data;
CySCB_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_sda;
cyhal_gpio_t pin_scl;
cyhal_clock_t clock;
bool is_shared_clock;
cy_stc_scb_i2c_context_t context;
cy_stc_scb_i2c_master_xfer_config_t rx_config;
cy_stc_scb_i2c_master_xfer_config_t tx_config;
bool is_slave;
uint32_t address;
uint32_t irq_cause;
uint16_t pending;
uint16_t events;
cyhal_event_callback_data_t callback_data;
#else
void *empty;
#endif
} cyhal_i2c_t;
/** @brief EZI2C object */
/**
* @brief EZI2C object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXSCB
CySCB_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_sda;
cyhal_gpio_t pin_scl;
cyhal_clock_divider_t clock;
cyhal_clock_t clock;
bool is_shared_clock;
cy_stc_scb_ezi2c_context_t context;
uint32_t irq_cause;
@ -239,7 +333,58 @@ typedef struct {
#endif
} cyhal_ezi2c_t;
/** @brief LPTIMER object */
/**
* @brief I2S object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXAUDIOSS
I2S_Type *base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_tx_sck;
cyhal_gpio_t pin_tx_ws;
cyhal_gpio_t pin_tx_sdo;
cyhal_gpio_t pin_rx_sck;
cyhal_gpio_t pin_rx_ws;
cyhal_gpio_t pin_rx_sdi;
cyhal_gpio_t pin_mclk;
bool is_tx_slave;
bool is_rx_slave;
uint32_t mclk_hz;
uint8_t channel_length;
uint8_t word_length;
uint32_t sample_rate_hz;
cyhal_clock_t clock;
bool is_clock_owned;
uint16_t user_enabled_events;
cyhal_event_callback_data_t callback_data;
cyhal_async_mode_t async_mode;
uint8_t async_dma_priority;
cyhal_dma_t tx_dma;
cyhal_dma_t rx_dma;
// Note: When the async DMA mode is in use, these variables will always reflect the state
// that the transfer will be in after the in-progress DMA transfer, if any, is complete
const void *async_tx_buff;
size_t async_tx_length;
void *async_rx_buff;
size_t async_rx_length;
volatile bool pm_transition_ready;
cyhal_syspm_callback_data_t pm_callback;
#else
void *empty;
#endif
} cyhal_i2s_t;
/**
* @brief LPTIMER object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXS40SRSS_MCWDT_INSTANCES
MCWDT_STRUCT_Type *base;
@ -250,23 +395,50 @@ typedef struct {
#endif
} cyhal_lptimer_t;
/** @brief PWM object */
/**
* @brief PDM-PCM object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXTCPWM
TCPWM_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin;
cyhal_gpio_t pin_compl;
cyhal_clock_divider_t clock;
uint32_t clock_hz;
bool dedicated_clock;
cyhal_event_callback_data_t callback_data;
#ifdef CY_IP_MXAUDIOSS_INSTANCES
PDM_Type *base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_data;
cyhal_gpio_t pin_clk;
/** User requested irq, see cyhal_pdm_pcm_event_t */
uint32_t irq_cause;
cyhal_event_callback_data_t callback_data;
uint8_t word_size;
cyhal_dma_t dma;
volatile bool stabilized;
volatile bool pm_transition_ready;
cyhal_syspm_callback_data_t pm_callback;
void *async_buffer;
size_t async_read_remaining;
#else
void *empty;
#endif
} cyhal_pwm_t;
} cyhal_pdm_pcm_t;
/** @brief SMIF object */
/**
* @brief PWM object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef cyhal_tcpwm_common_t cyhal_pwm_t;
/**
* @brief SMIF object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXSMIF
SMIF_Type* base;
@ -281,12 +453,20 @@ typedef struct {
cy_en_smif_data_select_t data_select;
uint32_t irq_cause;
cyhal_event_callback_data_t callback_data;
cyhal_syspm_callback_data_t pm_callback;
bool pm_transition_pending;
#else
void *empty;
#endif /* ifdef CY_IP_MXSMIF */
} cyhal_qspi_t;
/** @brief RNG object */
/**
* @brief RNG object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#if defined(CY_IP_MXCRYPTO_INSTANCES) || defined(CPUSS_CRYPTO_PRESENT)
CRYPTO_Type* base;
@ -296,7 +476,13 @@ typedef struct {
#endif
} cyhal_trng_t;
/** @brief RTC object */
/**
* @brief RTC object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXS40SRSS_RTC
cy_stc_rtc_dst_t dst;
@ -305,7 +491,13 @@ typedef struct {
#endif
} cyhal_rtc_t;
/** @brief SDHC object */
/**
* @brief SDHC object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXSDHC
SDHC_Type* base;
@ -325,109 +517,112 @@ typedef struct {
cyhal_gpio_t pin_cardEmmcReset;
uint32_t irq_cause;
cyhal_event_callback_data_t callback_data;
bool pm_transition_pending;
cyhal_syspm_callback_data_t pm_callback_data;
#else
void *empty;
#endif
} cyhal_sdhc_t;
/** @brief SDIO object */
/**
* @brief SDIO object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#if defined(CY_IP_MXSDHC)
SDHC_Type* base;
cyhal_resource_inst_t resource;
bool emmc;
cy_en_sd_host_dma_type_t dmaType;
cy_stc_sd_host_context_t context;
cyhal_gpio_t pin_clk;
cyhal_gpio_t pin_cmd;
cyhal_gpio_t pin_data0;
cyhal_gpio_t pin_data1;
cyhal_gpio_t pin_data2;
cyhal_gpio_t pin_data3;
uint32_t frequencyhal_hz;
uint16_t block_size;
uint32_t irq_cause;
cy_stc_syspm_callback_params_t pm_params;
cy_stc_syspm_callback_t pm_callback;
uint32_t events;
cyhal_event_callback_data_t callback_data;
SDHC_Type* base;
bool emmc;
cy_en_sd_host_dma_type_t dmaType;
cy_stc_sd_host_context_t context;
#elif defined(CYHAL_UDB_SDIO)
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_clk;
cyhal_gpio_t pin_cmd;
cyhal_gpio_t pin_data0;
cyhal_gpio_t pin_data1;
cyhal_gpio_t pin_data2;
cyhal_gpio_t pin_data3;
cyhal_clock_t clock;
cyhal_dma_t dma0Ch0;
cyhal_dma_t dma0Ch1;
cyhal_dma_t dma1Ch1;
cyhal_dma_t dma1Ch3;
stc_sdio_irq_cb_t* pfuCb;
#endif /* defined(CY_IP_MXSDHC) */
cyhal_clock_divider_t clock;
#if defined(CYHAL_UDB_SDIO) || defined(CY_IP_MXSDHC)
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_clk;
cyhal_gpio_t pin_cmd;
cyhal_gpio_t pin_data0;
cyhal_gpio_t pin_data1;
cyhal_gpio_t pin_data2;
cyhal_gpio_t pin_data3;
cyhal_dma_t dma0Ch0;
cyhal_dma_t dma0Ch1;
cyhal_dma_t dma1Ch1;
cyhal_dma_t dma1Ch3;
uint32_t frequencyhal_hz;
uint16_t block_size;
uint32_t irq_cause;
uint32_t frequencyhal_hz;
uint16_t block_size;
stc_sdio_irq_cb_t* pfuCb;
uint32_t irq_cause;
uint32_t events;
cyhal_event_callback_data_t callback_data;
uint32_t events;
cyhal_event_callback_data_t callback_data;
bool pm_transition_pending;
cyhal_syspm_callback_data_t pm_callback_data;
#else
void *empty;
#endif /* defined(CY_IP_MXSDHC) */
#endif /* defined(CY_IP_MXSDHC) || defined(CY_IP_MXSDHC) */
} cyhal_sdio_t;
/** @brief SPI object */
/**
* @brief SPI object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXSCB
CySCB_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_miso;
cyhal_gpio_t pin_mosi;
cyhal_gpio_t pin_sclk;
cyhal_gpio_t pin_ssel;
cyhal_clock_divider_t clock;
cy_en_scb_spi_sclk_mode_t clk_mode;
uint8_t mode;
uint8_t data_bits;
bool is_slave;
bool alloc_clock;
uint8_t oversample_value;
bool msb_first;
cy_stc_scb_spi_context_t context;
uint32_t irq_cause;
uint16_t pending;
void *rx_buffer;
uint32_t rx_buffer_size;
const void *tx_buffer;
uint32_t tx_buffer_size;
bool is_async;
cyhal_event_callback_data_t callback_data;
CySCB_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin_miso;
cyhal_gpio_t pin_mosi;
cyhal_gpio_t pin_sclk;
cyhal_gpio_t pin_ssel;
cyhal_clock_t clock;
cy_en_scb_spi_sclk_mode_t clk_mode;
uint8_t mode;
uint8_t data_bits;
bool is_slave;
bool alloc_clock;
uint8_t oversample_value;
bool msb_first;
cy_stc_scb_spi_context_t context;
uint32_t irq_cause;
uint16_t volatile pending;
uint8_t write_fill;
void *rx_buffer;
uint32_t rx_buffer_size;
const void *tx_buffer;
uint32_t tx_buffer_size;
bool is_async;
cyhal_event_callback_data_t callback_data;
#else
void *empty;
#endif
} cyhal_spi_t;
/** @brief Timer object */
typedef struct {
#ifdef CY_IP_MXTCPWM
TCPWM_Type* base;
cyhal_resource_inst_t resource;
cyhal_gpio_t pin;
cyhal_clock_divider_t clock;
bool dedicated_clock;
uint32_t clock_hz;
uint8_t direction;
bool is_continuous;
bool is_compare;
cyhal_event_callback_data_t callback_data;
#else
void *empty;
#endif
} cyhal_timer_t;
/**
* @brief Timer object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef cyhal_tcpwm_common_t cyhal_timer_t;
/** @brief UART object */
/**
* @brief UART object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXSCB
CySCB_Type* base;
@ -437,12 +632,10 @@ typedef struct {
cyhal_gpio_t pin_cts;
cyhal_gpio_t pin_rts;
bool is_user_clock;
cyhal_clock_divider_t clock;
cyhal_clock_t clock;
cy_stc_scb_uart_context_t context;
cy_stc_scb_uart_config_t config;
uint32_t irq_cause;
cy_stc_syspm_callback_params_t pm_params;
cy_stc_syspm_callback_t pm_callback;
en_hsiom_sel_t saved_tx_hsiom;
en_hsiom_sel_t saved_rts_hsiom;
cyhal_event_callback_data_t callback_data;
@ -451,17 +644,24 @@ typedef struct {
#endif
} cyhal_uart_t;
/** @brief USB Device object */
/**
* @brief USB Device object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
#ifdef CY_IP_MXUSBFS
USBFS_Type* base;
cy_stc_usbfs_dev_drv_context_t context;
cyhal_resource_inst_t resource;
cyhal_resource_inst_t pll_resource;
cyhal_clock_divider_t clock;
cyhal_clock_t clock;
bool shared_clock;
cyhal_gpio_t pin_dp;
cyhal_gpio_t pin_dm;
cyhal_syspm_callback_data_t pm_callback;
uint8_t *rd_data[CY_USBFS_DEV_DRV_NUM_EPS_MAX];
uint32_t rd_size[CY_USBFS_DEV_DRV_NUM_EPS_MAX];
#else
@ -469,11 +669,20 @@ typedef struct {
#endif
} cyhal_usb_dev_t;
/** @brief WDT object */
/**
* @brief WDT object
*
* Application code should not rely on the specific contents of this struct.
* They are considered an implementation detail which is subject to change
* between platforms and/or HAL releases.
*/
typedef struct {
uint8_t placeholder;
} cyhal_wdt_t;
/* For backwards compatability. */
#include "cyhal_deprecated.h"
#if defined(__cplusplus)
}
#endif /* __cplusplus */

View File

@ -28,14 +28,29 @@
* \addtogroup group_hal_hwmgr HWMGR (Hardware Manager)
* \ingroup group_hal
* \{
* High level interface for interacting with the Hardware Manager.
* High level interface to the Hardware Manager.
*
* This provides two related functions:
* * Allows HAL drivers (or application firmware) to mark specific hardware blocks
* as consumed, so that other firmware will not accidentally try to use the block
* for a conflicting purpose.
* * For resources which are interchangeable, such as clock dividers, provides allocation
* and reservation of an available instance (if one exists).
* \section section_hwmgr_features Features
* * Allows HAL drivers or application firmware to mark specific hardware resources
* as reserved. When this is done, other reservation requests for the same resource will be denied.
* * For resources which are interchangeable such as clock dividers, provides allocation
* and reservation of an available instance.
*
* \section section_hwmgr_quickstart Quick Start
* * \ref cyhal_hwmgr_init is used to initialize the hardware manager to keep
* track of resources being used.
* * \ref cyhal_hwmgr_reserve reserves a specified resource if available.
* * \ref cyhal_hwmgr_free frees the specified resource.
* * \ref cyhal_hwmgr_allocate can be used to allocate a free block of specified
* resource, if available.
*
*
* \section section_hwmgr_snippets Code snippets
* \subsection subsection_hwmgr_snippet_1 Snippet 1: Freeing a block used by PDL or configurators
* The following snippet shows how a specific resource used directly in PDL or the
* configurators can be freed so that it can be used by HAL.<br>
*
* \snippet hw_mgr.c snippet_cyhal_hwmgr_reserve
*/
#pragma once
@ -44,64 +59,80 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** The requested resource type is invalid */
#define CYHAL_HWMGR_RSLT_ERR_INVALID (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CHIP_HWMGR, 0))
/** The requested resource is already in use */
#define CYHAL_HWMGR_RSLT_ERR_INUSE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CHIP_HWMGR, 1))
/** No resources of the requested type are available */
#define CYHAL_HWMGR_RSLT_ERR_NONE_FREE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_CHIP_HWMGR, 2))
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name Hardware Manager Results
*/
/** The requested resource type is invalid */
#define CYHAL_HWMGR_RSLT_ERR_INVALID \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_HWMGR, 0))
/** The requested resource is already in use */
#define CYHAL_HWMGR_RSLT_ERR_INUSE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_HWMGR, 1))
/** No resources of the requested type are available */
#define CYHAL_HWMGR_RSLT_ERR_NONE_FREE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_HWMGR, 2))
/** Attempt to free a resource that was not used */
#define CYHAL_HWMGR_RSLT_WARN_UNUSED (CY_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_CHIP_HWMGR, 50))
#define CYHAL_HWMGR_RSLT_WARN_UNUSED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_HWMGR, 50))
/**
* \} \}
*/
/** Initializes the hardware manager to keep track of what resources are being used.
*
* @return The status of the init request
*
*/
cy_rslt_t cyhal_hwmgr_init();
cy_rslt_t cyhal_hwmgr_init(void);
/** Reserve the specified resource.
/** Reserve the specified resource. The exact block number and
* channel number must be specified. If this is not know, use
* \ref cyhal_hwmgr_allocate.
*
* \note This function is called by the init function of hardware blocks.
* Calling this again for the same block will result in error since the hardware
* block is already marked as consumed.
*
* @param[in] obj The resource object that should be reserved
* @return The status of the reserve request
*
* See \ref subsection_hwmgr_snippet_1
*/
cy_rslt_t cyhal_hwmgr_reserve(const cyhal_resource_inst_t* obj);
/** Free the specified resource to allow it to be used by something else.
/** Free the specified resource to allow it to be reused.
*
* @param[in,out] obj The resource object to free
*
* See \ref subsection_hwmgr_snippet_1
*/
void cyhal_hwmgr_free(const cyhal_resource_inst_t* obj);
/** Allocates a free block of the specified type if available
* This function is used when the exact block number and channel number of the
* resource is not known. This function loops through all available resource
* of the specified type and assigns the resource if available.
* This function internally calls \ref cyhal_hwmgr_reserve function and hence,
* it should not be called again.
*
* @param[in] type The type of resource to allocate.
* @param[out] obj The resource object.
* @return The status of the allocate request.
*
* @param[in] type The type of resource to allocate
* @param[out] obj The resource object that was allocated
* @return The status of the allocate request
*/
cy_rslt_t cyhal_hwmgr_allocate(cyhal_resource_t type, cyhal_resource_inst_t* obj);
/** Allocate (pick and reserve) an Clock Divider resource and provide a reference to it.
*
* @param[out] obj The resource object that was allocated
* @param[in] div The type of divider to allocate
* @param[in] accept_larger Whether a larger type can be provided if there are none of the requested size available
* @return The status of the reserve request
*/
cy_rslt_t cyhal_hwmgr_allocate_clock(cyhal_clock_divider_t* obj, cyhal_clock_divider_types_t div, bool accept_larger);
/** Free the specified Clock Divider resource and allow it be used by something else.
*
* @param[in] obj The resource object that was allocated
*/
void cyhal_hwmgr_free_clock(cyhal_clock_divider_t* obj);
#if defined(__cplusplus)
}
#endif

View File

@ -94,19 +94,38 @@ PSoC 6 MCU: I2C Slave Using Callbacks</b></a>
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name I2C Results
*/
/** The requested resource type is invalid */
#define CYHAL_I2C_RSLT_ERR_INVALID_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 0))
#define CYHAL_I2C_RSLT_ERR_INVALID_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 0))
/** Can not reach desired data rate */
#define CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 1))
#define CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 1))
/** Address size is not correct, should be 1 or two */
#define CYHAL_I2C_RSLT_ERR_INVALID_ADDRESS_SIZE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 2))
#define CYHAL_I2C_RSLT_ERR_INVALID_ADDRESS_SIZE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 2))
/** User buffer is empty (TX and RX). Should be at least TX or RX or both buffers */
#define CYHAL_I2C_RSLT_ERR_TX_RX_BUFFERS_ARE_EMPTY \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 3))
/** Previous Async operation is pending */
#define CYHAL_I2C_RSLT_ERR_PREVIOUS_ASYNCH_PENDING \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 4))
/** Failed to register I2C pm callback */
#define CYHAL_I2C_RSLT_ERR_PM_CALLBACK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2C, 5))
/**
* \} \}
*/
/** Enum to enable/disable/report interrupt cause flags. */
typedef enum
@ -147,14 +166,15 @@ typedef struct
* to be in that mode.<br>
* See \ref subsection_i2c_snippet_1
*
* @param[out] obj The I2C object
* @param[out] obj Pointer to an I2C object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] sda The sda pin
* @param[in] scl The scl pin
* @param[in] clk The clock to use can be shared, if not provided a new clock will be allocated
* @return The status of the init request
*
*/
cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_divider_t *clk);
cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk);
/** Deinitialize the i2c object
*
@ -176,7 +196,10 @@ cy_rslt_t cyhal_i2c_configure(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg);
/**
* I2C master write
* I2C master blocking write
*
* This will write `size` bytes of data from the buffer pointed to by `data`. It will not return
* until either all of the data has been written, or the timeout has elapsed.
*
* @param[in] obj The I2C object
* @param[in] dev_addr device address (7-bit)
@ -190,7 +213,10 @@ cy_rslt_t cyhal_i2c_configure(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg);
cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop);
/**
* I2C master read
* I2C master blocking read
*
* This will read `size` bytes of data into the buffer pointed to by `data`. It will not return
* until either all of the data has been read, or the timeout has elapsed.
*
* @param[in] obj The I2C object
* @param[in] dev_addr device address (7-bit)
@ -203,31 +229,47 @@ cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint
*/
cy_rslt_t cyhal_i2c_master_read(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop);
/** \cond INTERNAL */
/*******************************************************************************
* Backward compatibility function. The following code is DEPRECATED and must
* not be used in new projects.
*******************************************************************************/
cy_rslt_t cyhal_i2c_slave_config_write_buff(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size);
/*******************************************************************************
* Backward compatibility function. The following code is DEPRECATED and must
* not be used in new projects.
*******************************************************************************/
cy_rslt_t cyhal_i2c_slave_config_read_buff(cyhal_i2c_t *obj, uint8_t *data, uint16_t size);
/** \endcond */
/**
* The function configures the read buffer on an I2C Slave. This is the buffer from which the master reads data from.
* The user needs to setup a new buffer every time (i.e. call slave_send and slave_recv every time the buffer has been used up)<br>
* The function configures the write buffer on an I2C Slave. This is the buffer to which the master writes data to.
* The user needs to setup a new buffer every time (i.e. call \ref cyhal_i2c_slave_config_write_buffer and \ref cyhal_i2c_slave_config_read_buffer
* every time the buffer has been used up)<br>
* See related code example: <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-i2c-master" ><b>PSoC 6 MCU: I2C Master</b></a>
*
* @param[in] obj The I2C object
* @param[in] data I2C slave send data
* @param[in] size I2C slave send data size
*
* @return The status of the slave_config_write_buff request
* @return The status of the slave_config_write_buffer request
*/
cy_rslt_t cyhal_i2c_slave_config_write_buff(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size);
cy_rslt_t cyhal_i2c_slave_config_write_buffer(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size);
/**
* The function configures the write buffer on an I2C Slave. This is the buffer to which the master writes data to.
* The user needs to setup a new buffer every time (i.e. call slave_send and slave_recv every time the buffer has been used up)<br>
* The function configures the read buffer on an I2C Slave. This is the buffer from which the master reads data from.
* The user needs to setup a new buffer every time (i.e. call \ref cyhal_i2c_slave_config_write_buffer and \ref cyhal_i2c_slave_config_read_buffer
* every time the buffer has been used up)<br>
* See related code example: <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-i2c-master" ><b>PSoC 6 MCU: I2C Master</b></a>
*
* @param[in] obj The I2C object
* @param[out] data I2C slave receive data
* @param[in] size I2C slave receive data size
*
* @return The status of the slave_config_read_buff request
* @return The status of the slave_config_read_buffer request
*/
cy_rslt_t cyhal_i2c_slave_config_read_buff(cyhal_i2c_t *obj, uint8_t *data, uint16_t size);
cy_rslt_t cyhal_i2c_slave_config_read_buffer(cyhal_i2c_t *obj, uint8_t *data, uint16_t size);
/** Perform an I2C write using a block of data stored at the specified memory location
@ -258,7 +300,12 @@ cy_rslt_t cyhal_i2c_master_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_
cy_rslt_t cyhal_i2c_master_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, uint16_t size, uint32_t timeout);
/** Initiate a non-blocking I2C master asynchronous transfer. Supports simultaneous write and read operation.<br>
* Use callback handler to handle the events until data transfer is complete.<br>
*
* This will transfer `rx_size` bytes into the buffer pointed to by `rx`, while simultaneously transfering
* `tx_size` bytes of data from the buffer pointed to by `tx`, both in the background.
* When the requested quantity of data has been received, the @ref CYHAL_I2C_MASTER_RD_CMPLT_EVENT will be raised.
* When the requested quantity of data has been transmitted, the @ref CYHAL_I2C_MASTER_WR_CMPLT_EVENT will be raised.
* See @ref cyhal_i2c_register_callback and @ref cyhal_i2c_enable_event.
* If either of <b>tx_size</b> or <b>rx_size</b> is '0', the respective write or read operation is not performed.
* See \ref subsection_i2c_snippet_3
*
@ -284,7 +331,10 @@ cy_rslt_t cyhal_i2c_master_transfer_async(cyhal_i2c_t *obj, uint16_t address, co
*/
cy_rslt_t cyhal_i2c_abort_async(cyhal_i2c_t *obj);
/** The I2C event callback handler registration<br>
/** Register an I2C event callback handler<br>
*
* This function will be called when one of the events enabled by \ref cyhal_i2c_enable_event occurs.
*
* See \ref subsection_i2c_snippet_2
*
* @param[in] obj The I2C object
@ -295,15 +345,17 @@ cy_rslt_t cyhal_i2c_abort_async(cyhal_i2c_t *obj);
void cyhal_i2c_register_callback(cyhal_i2c_t *obj, cyhal_i2c_event_callback_t callback, void *callback_arg);
/** Configure and Enable or Disable I2C Interrupt.
*
* When an enabled event occurs, the function specified by \ref cyhal_i2c_register_callback will be called.
*
* See \ref subsection_i2c_snippet_2
*
* @param[in] obj The I2C object
* @param[in] event The I2C event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
* @param[in] obj The I2C object
* @param[in] event The I2C event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t intrPriority, bool enable);
void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t intr_priority, bool enable);
/*******************************************************************************
* Backward compatibility macro. The following code is DEPRECATED and must

View File

@ -0,0 +1,418 @@
/***************************************************************************//**
* \file cyhal_i2s.h
*
* \brief
* Provides a high level interface for interacting with the Cypress I2S.
* This interface abstracts out the chip specific details. If any chip specific
* functionality is necessary, or performance is critical the low level functions
* can be used directly.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
/**
* \addtogroup group_hal_i2s I2S (Inter-IC Sound)
* \ingroup group_hal
* \{
* High level interface for interacting with the Inter-IC Sound (I2S).
*
* The I2S protocol is a asynchronous serial interface protocol. This driver supports
* both transmit and receive modes of operation. The communication frequency, sample rate,
* word size, and channel size can all be configured.
*
* \section section_i2s_features Features
*
* * Transmit and receive functionality
* * Configurable data rates
* * Configurable channel and word size
* * Configurable interrupt and callback assignment from I2S events - \ref cyhal_i2s_event_t
*
* \section section_i2s_quickstart Quick Start
* Initialize an I2S instance using the \ref cyhal_i2s_init and provide the transmit (tx) and/or receive (rx) pins.<br>
* See \ref subsection_i2s_snippet_1 for example initialization as transmit or receive.
* \note The clock parameter (const \ref cyhal_clock_t *clk) is optional and can be set
* to NULL to generate and use an available clock resource with a default frequency.
*
* The sclk frequency is determined as `sclk = sample_rate_hz * channel_length * 2`
* (multiplying by 2 for 2 channels - left and right). The input clock must be a multiple of this sclk
* frequency; see the implementation specific documentation for the supported multipliers.
*
* It is possible to use either only TX functionality, only RX functionality, or both RX and TX functionality at the same time.
* If RX and TX are both in use, the same sample rate, channel length, word length, sclk frequency will be used for both.
*
* \section section_i2s_snippets Code Snippets
*
* \subsection subsection_i2s_snippet_1 Snippet 1: I2S Initialization and Configuration
* This snippet initializes an I2S resource for transmit or receive and assigns the pins.
*
* Initializing as I2S transmitter
* \snippet i2s.c snippet_cyhal_i2s_transmit_init
*
* Initializing as I2S receiver
* \snippet i2s.c snippet_cyhal_i2s_receive_init
*
* \subsection subsection_i2s_snippet_2 Snippet 2: I2S Transmit One-shot
* This snippet shows how to transmit data using \ref cyhal_i2s_write_async when the entire sample
* is available at once. <br>
*
* \snippet i2s.c snippet_cyhal_i2s_async_transmit_one_shot
* \subsection subsection_i2s_snippet_3 Snippet 3: I2S Transmit Streaming
* This snippet shows how to transmit data using \ref cyhal_i2s_write_async when sample data is
* being continuously loaded and transmitted (e.g. streaming over the network). <br>
*
* \snippet i2s.c snippet_cyhal_i2s_async_transmit_streaming
* \subsection subsection_i2s_snippet_4 Snippet 4: I2S Receive
* This snippet shows how to receive data using \ref cyhal_i2s_read_async. <br>
*
* \snippet i2s.c snippet_cyhal_i2s_async_receive
*
* \section subsection_i2s_moreinformation More Information
*
* <b>Code examples (Github)</b>
* * <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-i2s" ><b>
PSoC 6 MCU: Inter-IC Sound (I2S)</b></a>
* * <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-pdm-to-i2s" ><b>
PSoC 6 MCU: PDM to I2S</b></a>
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_general_types.h"
#include "cyhal_hw_types.h"
#include "cyhal_gpio.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name I2S Results
*/
/** An invalid pin location was specified */
#define CYHAL_I2S_RSLT_ERR_INVALID_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2S, 0))
/** An argument was provided */
#define CYHAL_I2S_RSLT_ERR_INVALID_ARG \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2S, 1))
/** Initialization of the I2S hardware failed*/
#define CYHAL_I2S_RSLT_ERR_INIT_FAILED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2S, 2))
/** The requested clock frequency could not be achieved */
#define CYHAL_I2S_RSLT_ERR_CLOCK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_I2S, 3))
/**
* \} \}
*/
/** I2S events */
typedef enum {
/** TX HW Buffer is not full */
CYHAL_I2S_TX_NOT_FULL = 1 << 0,
/** TX HW Buffer is half empty */
CYHAL_I2S_TX_HALF_EMPTY = 1 << 1,
/** TX HW Buffer is Empty */
CYHAL_I2S_TX_EMPTY = 1 << 2,
/** Attempt to write when TX HW Buffer is full */
CYHAL_I2S_TX_OVERFLOW = 1 << 3,
/** Interface ready to transfer data but HW TX buffer is empty */
CYHAL_I2S_TX_UNDERFLOW = 1 << 4,
/** Pending async transmit is complete (but the HW buffer may still contain unsent data) */
CYHAL_I2S_ASYNC_TX_COMPLETE = 1 << 5,
/** RX HW Buffer is not Empty */
CYHAL_I2S_RX_NOT_EMPTY = 1 << 6,
/** RX HW Buffer is half full */
CYHAL_I2S_RX_HALF_FULL = 1 << 7,
/** RX HW Buffer is FULL */
CYHAL_I2S_RX_FULL = 1 << 8,
/** Attempt to write when RX HW Buffer is full */
CYHAL_I2S_RX_OVERFLOW = 1 << 9,
/** Attempt to read when HW RX buffer is empty */
CYHAL_I2S_RX_UNDERFLOW = 1 << 10,
/** Pending async receive is complete */
CYHAL_I2S_ASYNC_RX_COMPLETE = 1 << 11,
} cyhal_i2s_event_t;
/** Pins to use for one I2S direction */
typedef struct {
cyhal_gpio_t sck; //!< Clock pin
cyhal_gpio_t ws; //!< Word select
cyhal_gpio_t data; //!< Data pin (sdo or sdi)
} cyhal_i2s_pins_t;
/** I2S Configuration */
typedef struct {
/** Configure TX to operate a slave (true) or master (false) */
bool is_tx_slave;
/** Configure RX to operate a slave (true) or master (false) **/
bool is_rx_slave;
/** Frequency, in hertz, of the master clock if it is provided by an external pin.
* If the mclk pin is not NC, this must be nonzero.
* If the mclk pin is NC, this must be zero.
*/
uint32_t mclk_hz;
/** Number of bits in each channel. See the implementation specific documentation for supported values. **/
uint8_t channel_length;
/** Number of bits in each word. Must be less than or equal to channel_length.
* If word_length < channel_length, the excess bits will be padded with 0's.
*/
uint8_t word_length;
/** Sample rate in Hz */
uint32_t sample_rate_hz;
} cyhal_i2s_config_t;
/** Handler for I2S event callbacks */
typedef void (*cyhal_i2s_event_callback_t)(void *callback_arg, cyhal_i2s_event_t event);
/** Initialize the I2S peripheral. It sets the default parameters for I2S
* peripheral, and configures its specifieds pins.
* If only one direction is to be used, then the pins for the other direction need not be specified (i.e. they may be set to NC).
* For example, if only RX is needed, tx_sck, tx_ws, and tx_sdo may all be set to NC.
* If one pin is specified for a direction, all pins for that direction must be specified.
*
* @param[out] obj Pointer to an I2S object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] tx_pins Pins for I2S transmit. If NULL, transmit functionality will be disabled.
* @param[in] rx_pins Pins for I2S receive. If NULL, receive functionality will be disabled.
* @param[in] mclk The master clock input pin, if an external clock should be used for the I2S block. Set to NC if an internal
* clock source should be used.
* @param[in] config Initial block configuration
* @param[in] clk Clock source to use for this instance. If NULL, a dedicated clock divider will be allocated for this instance.
* @return The status of the init request
*/
cy_rslt_t cyhal_i2s_init(cyhal_i2s_t *obj, const cyhal_i2s_pins_t* tx_pins, const cyhal_i2s_pins_t* rx_pins, cyhal_gpio_t mclk,
const cyhal_i2s_config_t* config, cyhal_clock_t* clk);
/** Deinitialize the i2s object
*
* @param[in,out] obj The i2s object
*/
void cyhal_i2s_free(cyhal_i2s_t *obj);
/** Set the I2S sample rate
*
* @param[in] obj The I2S object
* @param[in] sample_rate_hz Sample rate in Hz
* @return The status of the set sample rate request
*/
cy_rslt_t cyhal_i2s_set_sample_rate(cyhal_i2s_t *obj, uint32_t sample_rate_hz);
/** Starts transmitting data.
*
* @param[in] obj The I2S object
* @return The status of the start request.
*/
cy_rslt_t cyhal_i2s_start_tx(cyhal_i2s_t *obj);
/** Stops transmitting data.
*
* @param[in] obj The I2S object
* @return The status of the stop request.
*/
cy_rslt_t cyhal_i2s_stop_tx(cyhal_i2s_t *obj);
/** Starts receiving data.
*
* @param[in] obj The I2S object
* @return The status of the start request.
*/
cy_rslt_t cyhal_i2s_start_rx(cyhal_i2s_t *obj);
/** Stops receiving data.
*
* @param[in] obj The I2S object
* @return The status of the stop request.
*/
cy_rslt_t cyhal_i2s_stop_rx(cyhal_i2s_t *obj);
/** Read data synchronously
*
* This will read either `length` words or the number of words that are currently available in the
* receive buffer, whichever is less, then return. The value pointed to by `length` will be updated
* to reflect the number of words that were actually read.
*
* @param[in] obj The I2S object
* @param[out] data The buffer for receiving
* @param[in,out] length Number of words to (as configured in cyhal_i2s_config_t.word_length) read, updated with the number actually read
* @return The status of the read request
*
* @note Each word will be aligned to the next largest power of 2. For example, if the word length is 16 bits,
* each word will consume two bytes. But if the word length is 20, each word will consume 32 bytes.
* @return The status of the read request
*/
cy_rslt_t cyhal_i2s_read(cyhal_i2s_t *obj, void *data, size_t* length);
/** Send data synchronously
*
* This will write either `length` words or until the write buffer is full, whichever is less,
* then return. The value pointed to by `length` will be updated to reflect the number of words
* that were actually written.
* @note This function only queues data into the write buffer; it does not block until the
* data has all been sent out over the wire.
*
* @param[in] obj The I2S object
* @param[in] data The buffer for sending
* @param[in,out] length Number of words to write (as configured in cyhal_i2s_config_t.word_length, updated with the number actually written
* @return The status of the write request
*
* @note Each word will be aligned to the next largest power of 2. For example, if the word length is 16 bits,
* each word will consume two bytes. But if the word length is 20, each word will consume 32 bytes.
*/
cy_rslt_t cyhal_i2s_write(cyhal_i2s_t *obj, const void *data, size_t *length);
/** Checks if the specified I2S peripheral is transmitting data, including if a pending async transfer is waiting
* to write more data to the transmit buffer.
*
* @param[in] obj The I2S peripheral to check
* @return Whether the I2S is still transmitting
*/
bool cyhal_i2s_is_tx_busy(cyhal_i2s_t *obj);
/** Checks if the specified I2S peripheral has received data that has not yet been read out of the hardware buffer.
* This includes if an async read transfer is pending.
*
* @param[in] obj The I2S peripheral to check
* @return Whether the I2S is still transmitting
*/
bool cyhal_i2s_is_rx_busy(cyhal_i2s_t *obj);
/** Start I2S asynchronous read.
*
* This will transfer `rx_length` words into the buffer pointed to by `rx` in the background. When the
* requested quantity of data has been read, the @ref CYHAL_I2S_ASYNC_RX_COMPLETE event will be raised.
* See @ref cyhal_i2s_register_callback and @ref cyhal_i2s_enable_event.
*
* cyhal_i2s_set_async_mode can be used to control whether this uses DMA or a CPU-driven transfer.
*
* @note Each word will be aligned to the next largest power of 2. For example, if the word length is 16 bits,
* each word will consume two bytes. But if the word length is 20, each word will consume 32 bytes.
*
* @param[in] obj The I2S object
* @param[out] rx The receive buffer.
* @param[in] rx_length Number of words (as configured in cyhal_i2s_config_t.word_length) to read.
* @return The status of the read_async request
*/
cy_rslt_t cyhal_i2s_read_async(cyhal_i2s_t *obj, void *rx, size_t rx_length);
/** Start I2S asynchronous write.
*
* This will transfer `tx_length` words into the tx buffer in the background. When the requested
* quantity of data has been queued in the transmit buffer, the @ref CYHAL_I2S_ASYNC_TX_COMPLETE
* event will be raised. See @ref cyhal_i2s_register_callback and @ref cyhal_i2s_enable_event.
*
* cyhal_i2s_set_async_mode can be used to control whether this uses DMA or a SW (CPU-driven) transfer.
*
* @note Each word will be aligned to the next largest power of 2. For example, if the word length is 16 bits,
* each word will consume two bytes. But if the word length is 20, each word will consume 32 bytes.
*
* @param[in] obj The I2S object
* @param[in] tx The transmit buffer.
* @param[in] tx_length The number of words to transmit.
* @return The status of the transfer_async request
*/
cy_rslt_t cyhal_i2s_write_async(cyhal_i2s_t *obj, const void *tx, size_t tx_length);
/** Set the mechanism that is used to perform I2S asynchronous transfers. The default is SW.
* @warning The effect of calling this function while an async transfer is pending is undefined.
*
* @param[in] obj The I2S object
* @param[in] mode The transfer mode
* @param[in] dma_priority The priority, if DMA is used. Valid values are the same as for @ref cyhal_dma_init.
* If DMA is not selected, the only valid value is CYHAL_DMA_PRIORITY_DEFAULT, and no
guarantees are made about prioritization.
* @return The status of the set mode request
*/
cy_rslt_t cyhal_i2s_set_async_mode(cyhal_i2s_t *obj, cyhal_async_mode_t mode, uint8_t dma_priority);
/** Checks if the specified I2S peripheral is in the process of reading data from the hardware buffer into RAM.
*
* @note: This only checks whether there is an ongoing transfer (e.g. via cyhal_i2s_read_async) into RAM from the
* I2S peripheral's hardware buffer. It does not check whether unread data exists in the hardware buffer.
*
* @param[in] obj The I2S peripheral to check
* @return Whether an asynchronous read operation is still in progress
*/
bool cyhal_i2s_is_read_pending(cyhal_i2s_t *obj);
/** Checks if the specified I2S peripheral is in the process of writing data into the hardware buffer.
*
* @note: This only checks whether there is an ongoing transfer (e.g. via cyhal_i2s_transfer_async) from RAM into the
* I2S peripheral's hardware buffer. It does not check whether unwritten data exists in the hardware buffer.
*
* @param[in] obj The I2S peripheral to check
* @return Whether an asynchronous write operation is still in progress
*/
bool cyhal_i2s_is_write_pending(cyhal_i2s_t *obj);
/** Abort I2S asynchronous read
*
* This function does not perform any validation before aborting the transfer.
* Any validation which is required is the responsibility of the application.
*
* @param[in] obj The I2S object
* @return The status of the abort_async_read request
*/
cy_rslt_t cyhal_i2s_abort_read_async(cyhal_i2s_t *obj);
/** Abort I2S asynchronous write
*
* This function does not perform any validation before aborting the transfer.
* Any validation which is required is the responsibility of the application.
*
* @param[in] obj The I2S object
* @return The status of the abort_async_write request
*/
cy_rslt_t cyhal_i2s_abort_write_async(cyhal_i2s_t *obj);
/** Register an I2S callback handler
*
* This function will be called when one of the events enabled by \ref cyhal_i2s_enable_event occurs.
*
* @param[in] obj The I2S object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
* @param[in] callback_arg Generic argument that will be provided to the callback when called
*/
void cyhal_i2s_register_callback(cyhal_i2s_t *obj, cyhal_i2s_event_callback_t callback, void *callback_arg);
/** Configure I2S events.
*
* When an enabled event occurs, the function specified by \ref cyhal_i2s_register_callback will be called.
*
* @param[in] obj The I2S object
* @param[in] event The I2S event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on specified events, False to turn off
*/
void cyhal_i2s_enable_event(cyhal_i2s_t *obj, cyhal_i2s_event_t event, uint8_t intr_priority, bool enable);
#if defined(__cplusplus)
}
#endif
#ifdef CYHAL_I2S_IMPL_HEADER
#include CYHAL_I2S_IMPL_HEADER
#endif /* CYHAL_I2S_IMPL_HEADER */
/** \} group_hal_i2s */

View File

@ -29,13 +29,27 @@
* \addtogroup group_hal_interconnect INTERCONNECT (Internal digital routing)
* \ingroup group_hal
* \{
* High level interface for interacting with the digital routing.
* High level interface to the Cypress digital routing.
*
* This provides limited facilities for runtime manipulation of the on chip routing.
* \section subsection_interconnect_features Features
* Facilities for runtime manipulation of the on chip routing.
* The following types of connections are supported:
* * Connection from a peripheral to a pin. (A dedicated connection must exist
between the pin and the peripheral; see the device datasheet for more details)
* * Experimental support for connecting between two on-chip "trigger" terminals.
*
* \section subsection_interconnect_quickstart Quick Start
* * \ref cyhal_connect_pin can be used to connect a pin to a peripheral.(A dedicated connection must exist
* between the pin and the peripheral; see the device datasheet for more details)
* * \ref cyhal_disconnect_pin can be used to disconnect a pin from a peripheral.
* The drive mode will be reset to High-Z after disconnecting
*
* \section section_interconnect_snippets Code Snippets
*
* \subsection subsection_interconnect_snippet1 Snippet 1: Connecting a pin to TCPWM block
* The following code snippet demonstrates connecting a GPIO pin to an active TCPWM block on a PSoC 6 device.
* using the \ref cyhal_connect_pin. It is assumed that the TCPWM is already configured and active.<br>
* \snippet interconnect.c snippet_cyhal_interconnect_connect_pin
*/
#pragma once
@ -44,45 +58,61 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name Interconnect Results
*/
/** No connection is available */
#define CYHAL_CONNECT_RSLT_NO_CONNECTION (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_INTERCONNECT, 0))
#define CYHAL_CONNECT_RSLT_NO_CONNECTION \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_INTERCONNECT, 0))
/** The connections source and destination are already connected */
#define CYHAL_CONNECT_RSLT_ALREADY_CONNECTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_INTERCONNECT, 1))
#define CYHAL_CONNECT_RSLT_ALREADY_CONNECTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_INTERCONNECT, 1))
/** Invalid trigger connection */
#define CYHAL_CONNECT_RSLT_INVALID_TRIGGER_CONNECTION (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_INTERCONNECT, 2))
#define CYHAL_CONNECT_RSLT_INVALID_TRIGGER_CONNECTION \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_INTERCONNECT, 2))
/**
* \} \}
*/
/** Indicates that a mux output does not continue to another mux */
#define CYHAL_INTERCONNECT_MUX_NOT_CONTINUATION 0xFF
/** Connect a pin to a peripheral terminal. This will route a direct connect from the pin to the peripheral.
* Any previous direct connection from the pin will be overriden.
* @param[in] pin_connection Details about the pin and its target connection
/** Connect a pin to a peripheral terminal. This will route a direct connection from the pin to the peripheral.
* Any previous direct connection from the pin will be overriden.<br>
* See \ref subsection_interconnect_snippet1
* @param[in] pin_connection The pin and target peripheral terminal to be connected
* @return The status of the connect request
*/
cy_rslt_t cyhal_connect_pin(const cyhal_resource_pin_mapping_t *pin_connection);
/** Disconnect a peripheral from a pin. This will also reset the pin's drive mode to High-Z.
* @param[in] pin The pin to disconnect
* @param[in] pin The pin to be disconnected
* @return The status of the disconnect request
*/
cy_rslt_t cyhal_disconnect_pin(cyhal_gpio_t pin);
/** WORK IN PROGRESS. This function is not yet fully implemented.
* Connects two digital terminals on the device using any internal interconnect. As expected, a single
* source can drive multiple destinations, but a destination can only be driven by a single source.
* If the output is already connected, or the connection can not be established an error will be returned.
/**
* \warning WORK IN PROGRESS. This function is not yet fully implemented.<br>
*
* Connects two digital terminals on the device using any internal interconnect. A single
* source can drive multiple destinations, but a destination can be driven by only one source.
* If the destination is already connected, or the connection can not be established an error will be returned.
* @param[in] source The source of the signal to connect
* @param[in] dest The destination of the signal to connect
* @return The status of the connect request
*/
cy_rslt_t cyhal_connect_trigger(cyhal_source_t source, cyhal_dest_t dest);
#if defined(__cplusplus)
}
#endif

View File

@ -26,14 +26,33 @@
*******************************************************************************/
/**
* \addtogroup group_hal_lptimer LPTIMER (Low-Power Timer)
* \addtogroup group_hal_lptimer LPTimer (Low-Power Timer)
* \ingroup group_hal
* \{
* High level interface for interacting with the low-power timer (LPTIMER).
* High level interface for interacting with the low-power timer (LPTimer).
*
* This can be used to measure timing between events, or to perform
* some action the ability after a set interval. It continues to operate
* in some low power modes; see the device datasheet for details.
* LPTimer can operate in all possible low power modes. It can be used either to measure timing between events, or to perform
* some action after a specified interval of time.
* \section subsection_lptimer_features Features
* * Configurable to create a free-running timer or generate periodic interrupts.
* * Configurable to update the match value of an already configured LPTimer set up to generate an interrupt on match.
* * Used for measuring time between events in free-running mode.
*
* \section subsection_lptimer_quickstart Quick Start
*
* \ref cyhal_lptimer_init can be used for a LPTimer initialization which resets all the clocking and prescaler registers, along with disabling the compare interrupt.
*
* See \ref subsection_lptimer_snippet_2.
*
* \section subsection_lptimer_snippets Code snippets
*
* \subsection subsection_lptimer_snippet_1 Snippet 1: LPTimer initialization with Default configuration
* The following snippet initializes a LPTimer in free running mode.
* \snippet lptimer.c snippet_cyhal_lptimer_simple_init_def
*
* \subsection subsection_lptimer_snippet_2 Snippet 2: Simple LPTimer initialization with set Match value
* The following snippet initializes a LPTimer and assigns the Match value to the LPTimer.
* \snippet lptimer.c snippet_cyhal_lptimer_simple_init
*/
#pragma once
@ -47,45 +66,63 @@
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name LPTimer Results
*/
/** Failed to configure power management callback */
#define CYHAL_LPTIMER_RSLT_ERR_PM_CALLBACK (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_WDT, 0))
#define CYHAL_LPTIMER_RSLT_ERR_PM_CALLBACK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_WDT, 0))
/** LPTIMER interrupt triggers */
/**
* \} \}
*/
/** LPTimer Information */
typedef struct cyhal_lptimer_info {
uint32_t frequency_hz; /**< Operating clock frequency the LPTimer is running on. */
uint8_t min_set_delay; /**< Minimum permitted value for the delay parameter in \ref cyhal_lptimer_set_delay. */
uint32_t max_counter_value; /**< Maximum value of the counter. */
} cyhal_lptimer_info_t;
/** LPTimer interrupt triggers */
typedef enum {
CYHAL_LPTIMER_COMPARE_MATCH,
} cyhal_lptimer_event_t;
/** Handler for LPTIMER interrupts */
/** Handler for LPTimer interrupts */
typedef void (*cyhal_lptimer_event_callback_t)(void *callback_arg, cyhal_lptimer_event_t event);
/** Initialize the LPTIMER
/** Initialize the LPTimer
*
* Initialize or re-initialize the LPTIMER. This resets all the
* Initialize or re-initialize the LPTimer. This resets all the
* clocking and prescaler registers, along with disabling
* the compare interrupt. Refer to the BSP for the clock source
* for the LPTIMER.
* for the LPTimer.
*
* @param[out] obj The LPTIMER object
* @return The status of the init request
* @param[out] obj Pointer to an LPTimer object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @return The status of the init request. On success it returns \ref CY_RSLT_SUCCESS.
*/
cy_rslt_t cyhal_lptimer_init(cyhal_lptimer_t *obj);
/** Deinitialize the LPTIMER
/** Deinitialize the LPTimer
*
* Powers down the LPTIMER.
* After calling this function no other LPTIMER functions should be called except
* Powers down the LPTimer.
* After calling this function no other LPTimer functions should be called except
* cyhal_lptimer_init(). Calling any function other than init after freeing is
* undefined.
*
* @param[inout] obj The LPTIMER object
* @param[inout] obj The LPTimer object
*/
void cyhal_lptimer_free(cyhal_lptimer_t *obj);
/** Reload/Reset the Low-Power timer.
*
* @param[in] obj The LPTIMER object
* @return The status of the reload request
* @param[in] obj The LPTimer object
* @return The status of the reload request. On success it returns \ref CY_RSLT_SUCCESS.
*/
cy_rslt_t cyhal_lptimer_reload(cyhal_lptimer_t *obj);
@ -94,30 +131,31 @@ cy_rslt_t cyhal_lptimer_reload(cyhal_lptimer_t *obj);
/** Update the match/compare value
*
* Update the match value of an already configured LPTIMER set up
* Update the match value of an already configured LPTimer set up
* to generate an interrupt on match. Note that this function does not
* reinitialize the counter or the associated peripheral initialization
* sequence.
*
* @param[in] obj The LPTIMER object
* @param[in] obj The LPTimer object
* @param[in] value The tick value to match
*
* @return The status of the set_match request
* @return The status of the set_match request. On success it returns \ref CY_RSLT_SUCCESS.
*/
cy_rslt_t cyhal_lptimer_set_match(cyhal_lptimer_t *obj, uint32_t value);
/** Update the match/compare value
*
* Update the match value of an already configured LPTIMER set up
* Update the match value of an already configured LPTimer set up
* to generate an interrupt on match delay from the current counter value.
* Note that this function does not reinitialize the counter or the
* associated peripheral initialization
* sequence.
*
* @param[in] obj The LPTIMER object
* @param[in] delay The ticks to wait
* @param[in] obj The LPTimer object
* @param[in] delay The ticks to wait. The minimum permitted delay value can be
* queried using \ref cyhal_lptimer_get_info
*
* @return The status of the set_match request
* @return The status of the set_match request. On success it returns \ref CY_RSLT_SUCCESS.
*/
cy_rslt_t cyhal_lptimer_set_delay(cyhal_lptimer_t *obj, uint32_t delay);
@ -125,36 +163,49 @@ cy_rslt_t cyhal_lptimer_set_delay(cyhal_lptimer_t *obj, uint32_t delay);
*
* If no rollover has occurred, the seconds passed since cyhal_lptimer_init() or cyhal_lptimer_set_time()
* was called can be found by dividing the ticks returned by this function
* by the frequency of the source clock (refer to the BSP for the clock source).
* by the frequency of the source clock (Refer to BSP Settings section in the kit's BSP API Reference Manual for details on the clock source for LPTimer).
*
* @param[in] obj The LPTIMER object
* @param[in] obj The LPTimer object
* @return The timer's timer value in ticks
*/
uint32_t cyhal_lptimer_read(const cyhal_lptimer_t *obj);
/** The LPTIMER match event handler registration
/** Register a LPTimer match event handler
*
* @param[in] obj The LPTIMER object
* This function will be called when one of the events enabled by \ref cyhal_lptimer_enable_event occurs.
*
* @param[in] obj The LPTimer object
* @param[in] callback The callback handler which will be invoked when the interrupt triggers
* @param[in] callback_arg Generic argument that will be provided to the handler when called
*/
void cyhal_lptimer_register_callback(cyhal_lptimer_t *obj, cyhal_lptimer_event_callback_t callback, void *callback_arg);
/** Configure and Enable/Disable the LPTIMER events
/** Configure and Enable/Disable the LPTimer events
*
* @param[in] obj The LPTIMER object
* @param[in] event The LPTIMER event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] enable True to turn on event, False to turn off
* When an enabled event occurs, the function specified by \ref cyhal_lptimer_register_callback will be called.
*
* @param[in] obj The LPTimer object
* @param[in] event The LPTimer event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on event, False to turn off
*/
void cyhal_lptimer_enable_event(cyhal_lptimer_t *obj, cyhal_lptimer_event_t event, uint8_t intrPriority, bool enable);
void cyhal_lptimer_enable_event(cyhal_lptimer_t *obj, cyhal_lptimer_event_t event, uint8_t intr_priority, bool enable);
/** Manually trigger the LPTIMER interrupt.
/** Manually trigger the LPTimer interrupt.
*
* @param[in] obj The LPTIMER object
* @param[in] obj The LPTimer object
*/
void cyhal_lptimer_irq_trigger(cyhal_lptimer_t *obj);
/** Get information about the LPTimer.
*
* Provides information such as operating frequency, etc.
*
* @param[in] obj The LPTimer object.
* @param[out] info Information about the LPtimer.
*/
void cyhal_lptimer_get_info(cyhal_lptimer_t *obj, cyhal_lptimer_info_t *info);
#if defined(__cplusplus)
}
#endif
@ -163,4 +214,4 @@ void cyhal_lptimer_irq_trigger(cyhal_lptimer_t *obj);
#include CYHAL_LPTIMER_IMPL_HEADER
#endif /* CYHAL_LPTIMER_IMPL_HEADER */
/** \} group_hal_lptimer */
/** \} group_hal_lptimer */

View File

@ -1,80 +0,0 @@
/***************************************************************************//**
* \file cyhal_modules.h
*
* \brief
* Provides an enum of all HAL modules types that can be used for generating
* custom cy_rslt_t items.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
/**
* \ingroup group_result
* \{
* Enum definition for all HAL resource modules.
*/
#pragma once
#include "cy_result.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** Enum to in indicate which module an errors occurred in. */
/**
* @brief Enum to specify module IDs for @ref cy_rslt_t values returned from the HAL.
*
*/
enum cyhal_rslt_module_chip
{
CYHAL_RSLT_MODULE_CHIP_HWMGR = CY_RSLT_MODULE_ABSTRACTION_HAL_BASE, //!< An error occurred in hardware management module
CYHAL_RSLT_MODULE_ADC, //!< An error occurred in ADC module
CYHAL_RSLT_MODULE_COMP, //!< An error occurred in comparator module
CYHAL_RSLT_MODULE_CRC, //!< An error occurred in crypto CRC module
CYHAL_RSLT_MODULE_DAC, //!< An error occurred in DAC module
CYHAL_RSLT_MODULE_DMA, //!< An error occurred in DMA module
CYHAL_RSLT_MODULE_FLASH, //!< An error occurred in flash module
CYHAL_RSLT_MODULE_GPIO, //!< An error occurred in GPIO module
CYHAL_RSLT_MODULE_I2C, //!< An error occurred in I2C module
CYHAL_RSLT_MODULE_I2S, //!< An error occurred in I2S module
CYHAL_RSLT_MODULE_INTERCONNECT, //!< An error occurred in Interconnct module
CYHAL_RSLT_MODULE_OPAMP, //!< An error occurred in OpAmp module
CYHAL_RSLT_MODULE_PDMPCM, //!< An error occurred in PDM/PCM module
CYHAL_RSLT_MODULE_PWM, //!< An error occurred in PWM module
CYHAL_RSLT_MODULE_QSPI, //!< An error occurred in QSPI module
CYHAL_RSLT_MODULE_RTC, //!< An error occurred in RTC module
CYHAL_RSLT_MODULE_SDHC, //!< An error occurred in SDHC module
CYHAL_RSLT_MODULE_SDIO, //!< An error occurred in SDIO module
CYHAL_RSLT_MODULE_SPI, //!< An error occurred in SPI module
CYHAL_RSLT_MODULE_SYSTEM, //!< An error occurred in System module
CYHAL_RSLT_MODULE_TIMER, //!< An error occurred in Timer module
CYHAL_RSLT_MODULE_TRNG, //!< An error occurred in RNG module
CYHAL_RSLT_MODULE_UART, //!< An error occurred in UART module
CYHAL_RSLT_MODULE_USB, //!< An error occurred in USB module
CYHAL_RSLT_MODULE_WDT, //!< An error occurred in WDT module
CYHAL_RSLT_MODULE_EZI2C, //!< An error occurred in EZI2C module
};
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/** \} group_hal_modules */

View File

@ -0,0 +1,290 @@
/***************************************************************************//**
* \file cyhal_pdmpcm.h
*
* \brief
* Provides a high level interface for interacting with the Cypress PDM/PCM.
* This interface abstracts out the chip specific details. If any chip specific
* functionality is necessary, or performance is critical the low level functions
* can be used directly.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
/**
* \addtogroup group_hal_pdmpcm PDM/PCM (Pulse-Density Modulation to Pulse-Code Modulation Converter)
* \ingroup group_hal
* \{
* High level interface for interacting with the pulse-density modulation to
* pulse-code modulation (PDM/PCM) converter.
*
* The PDM/PCM converter is a asynchronous operation. A PDM-PCM converter is used
* to convert 1-bit digital audio streaming data to PCM data. The sample rate, word
* size, and channels can all be configured.
*
* \section section_pdmpcm_features Features
*
* * Supports FIFO buffer for Incoming Data
* * Configurable Gain Settings
* * Configurable Word Length
* * Configurable interrupt and callback assignment from PDM/PCM events - \ref cyhal_pdm_pcm_event_t
*
* \section section_pdmpcm_quickstart Quick Start
* Initialize a PDM/PCM converter instance using the \ref cyhal_pdm_pcm_init and
* provide the clock and data pins.<br>
* See \ref subsection_pdmpcm_snippet_1 for example initialization.
* \note The clock parameter (const \ref cyhal_clock_divider_t *clk) is optional and
* can be set to NULL to generate and use an available clock resource with a default
* frequency.
*
* \section section_pdmpcm_snippets Code Snippets
* \note Error checking is omitted for clarity
*
* \subsection subsection_pdmpcm_snippet_1 Snippet 1: PDM/PCM Initialization and Configuration
* This snippet initializes a PCM/PCM resource for conversion and assigns the pins.
*
* \snippet pdmpcm.c snippet_cyhal_pdmpcm_init
*
* \subsection subsection_pdmpcm_snippet_2 Snippet 2: PDM/PCM Asynchronous Receive
* This snippet shows how to receive data in the background using \ref cyhal_pdm_pcm_read_async.
* Notification of the asynchronous read completion is achieved by using \ref cyhal_pdm_pcm_register_callback
* to register a callback function and \ref cyhal_pdm_pcm_enable_event to enable callling the
* callback when an synchonous read completes.
*
* \snippet pdmpcm.c snippet_cyhal_pdmpcm_async_receive
*
* \section subsection_pdmpcm_moreinformation More Information
*
* <b>Code examples (Github)</b>
* * <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-pdm-pcm" ><b>
PSoC 6 MCU: PDM-to-PCM</b></a>
* * <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-pdm-to-i2s" ><b>
PSoC 6 MCU: PDM to I2S</b></a>
*/
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "cyhal_general_types.h"
#include "cyhal_hw_types.h"
#include "cyhal_pin_package.h"
#include "cyhal_syspm.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name PDM/PCM Results
*/
/** The pin PDM/PCM hardware cannot be initialized with the passed in pin */
#define CYHAL_PDM_PCM_RSLT_ERR_INVALID_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PDMPCM, 0))
/** A configuration parameter is invalid: sample_rate, decimation_rate, PCM word length, left/right gain.
* See the implementation specific documentation for valid range */
#define CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PDMPCM, 1))
/** An async read operation is already progres */
#define CYHAL_PDM_PCM_RSLT_ERR_ASYNC_IN_PROGRESS \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PDMPCM, 2))
/**
* \} \}
*/
/** PDM/PCM interrupt triggers */
typedef enum {
CYHAL_PDM_PCM_RX_HALF_FULL = 0x01, /**< RX hardware buffer is half full */
CYHAL_PDM_PCM_RX_NOT_EMPTY = 0x02, /**< RX hardware buffer is not empty */
CYHAL_PDM_PCM_RX_OVERFLOW = 0x04, /**< Attempt to write to a full RX hardware buffer */
CYHAL_PDM_PCM_RX_UNDERFLOW = 0x08, /**< Attempt to read from an empty buffer */
CYHAL_PDM_PCM_ASYNC_COMPLETE = 0x10, /**< Async operation completed */
} cyhal_pdm_pcm_event_t;
/** PDM/PCM channel select */
typedef enum {
CYHAL_PDM_PCM_MODE_LEFT, /**< The channel mono left */
CYHAL_PDM_PCM_MODE_RIGHT, /**< The channel mono right */
CYHAL_PDM_PCM_MODE_STEREO, /**< The channel stereo */
} cyhal_pdm_pcm_mode_t;
/** Describes the current configuration of a PDM/PCM */
typedef struct
{
uint32_t sample_rate; /**< Sample rate in Hz */
uint8_t decimation_rate; /**< PDM decimation rate */
cyhal_pdm_pcm_mode_t mode; /**< left, right, or stereo */
uint8_t word_length; /**< PCM word length in bits, see the implementation specific documentation for valid range */
int8_t left_gain; /**< PGA in 0.5 dB increment, for example a value of 5 would mean +2.5 dB. The closest fit value will be used, see the implementation specific documentation for valid ranges. This may be negative if the implementation supports it. */
int8_t right_gain; /**< PGA in 0.5 dB increment, for example a value of 5 would mean +2.5 dB. The closest fit value will be used, see the implementation specific documentation for valid ranges. This may be negative if the implementation supports it. */
} cyhal_pdm_pcm_cfg_t;
/** Handler for PDM/PCM interrupts */
typedef void (*cyhal_pdm_pcm_event_callback_t)(void *handler_arg, cyhal_pdm_pcm_event_t event);
/** Initialize the PDM/PCM peripheral
*
* Configures the pins used by PDM/PCM converter, sets a default format and frequency, and enables the peripheral
* @param[out] obj Pointer to a PDM/PCM object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] pin_data The pin to use for PDM input
* @param[in] pin_clk The pin to use for PDM clock output
* @param[in] clk_source The clock source for PDM/PCM block
* @param[in] cfg The configuration for the PDM/PCM block
* @return The status of the init request
*/
cy_rslt_t cyhal_pdm_pcm_init(cyhal_pdm_pcm_t *obj, cyhal_gpio_t pin_data, cyhal_gpio_t pin_clk,
const cyhal_clock_divider_t *clk_source, const cyhal_pdm_pcm_cfg_t *cfg);
/** Release a PDM/PCM object, behavior is undefined if an asynchronous read is in progress
*
* Return the peripheral, pins and clock owned by the PDM/PCM object to their reset state
* @param[in,out] obj The PDM/PCM object to deinitialize
*/
void cyhal_pdm_pcm_free(cyhal_pdm_pcm_t *obj);
/**
* Start the PDM/PCM operation
*
* @param[in] obj The PDM/PCM object to start
* @return the status of the start request
*/
cy_rslt_t cyhal_pdm_pcm_start(cyhal_pdm_pcm_t *obj);
/**
* Stop the PDM/PCM operation
*
* @param[in] obj The PDM/PCM object to start
* @return the status of the stop request
*/
cy_rslt_t cyhal_pdm_pcm_stop(cyhal_pdm_pcm_t *obj);
/** Updates the PDM/PCM channel gains. Each integer increment represent a 0.5 dB value.
* For example: a gain value of 5 would mean +2.5 dB.
* If the exact gain value requested is not supported, it will be rounded to the
* nearest legal value. See the implementation specific documentation for valid ranges.
*
* \note Gains may be negative if the implementation supports it.
*
* @param[in] obj The PDM/PCM object to configure
* @param[in] gain_left The gain of the left channel in units of 0.5 dB
* @param[in] gain_right The gain of the right channel in units of 0.5 dB
* @return The status of the set gain operation. An error will be returned if the value is outside of range supported by HW.
*/
cy_rslt_t cyhal_pdm_pcm_set_gain(cyhal_pdm_pcm_t *obj, int8_t gain_left, int8_t gain_right);
/** Clears the hardware buffer
*
* @param[in] obj The PDM/PCM peripheral
* @return The status of the clear request
*/
cy_rslt_t cyhal_pdm_pcm_clear(cyhal_pdm_pcm_t *obj);
/** Reads data synchronously
*
* This will read either `length` words or the number of words that are currently available in the
* receive buffer, whichever is less, then return. The value pointed to by `length` will be updated
* to reflect the number of words that were actually read.
* If there are less data in FIFO than length, length will be update with number of words read.
*
* @param[in] obj The PDM/PCM peripheral
* @param[out] data Pointer to word array where incoming data will be stored. Buffer must be aligned to word-size.
* Each word will be aligned to the next largest power of 2. For example, if the word length is 16 bits,
* each word will consume two bytes. But if the word length is 20, each word will consume 32 bits.
* Negative value will use sign-extension. -1 with 24-bit word length will have 32-bit value of 0xFFFFFFFF.
* @param[in,out] length Number of 32-bit words to read, updated with the number actually read
* @return The status of the read request
*/
cy_rslt_t cyhal_pdm_pcm_read(cyhal_pdm_pcm_t *obj, void *data, size_t *length);
/** Begin asynchronous PDM/PCM read
*
* This will transfer `length` words into the buffer pointed to by `data` in the background. When the
* requested quantity of data has been read, the @ref CYHAL_PDM_PCM_ASYNC_COMPLETE event will be raised.
* See @ref cyhal_pdm_pcm_register_callback and @ref cyhal_pdm_pcm_enable_event.
*
* cyhal_pdm_pcm_set_async_mode can be used to control whether this uses DMA or a CPU-driven transfer.
*
* @param[in] obj The PDM/PCM object
* @param[out] data Pointer to word array where incoming data will be stored. Buffer must be aligned to word-size.
* Each word will be aligned to the next largest power of 2. For example, if the word length is 16 bits,
* each word will consume two bytes. But if the word length is 20, each word will consume 32 bits.
* Negative value will use sign-extension. -1 with 24-bit word length will have 32-bit value of 0xFFFFFFFF.
* @param[in] length Number of words to read
* @return The status of the read_async request
*/
cy_rslt_t cyhal_pdm_pcm_read_async(cyhal_pdm_pcm_t *obj, void *data, size_t length);
/** Checks if an async read operation is pending
*
* @param[in] obj The PDM/PCM peripheral to check
* @return Indication of whether a PDM/PCM async operation is pending
*/
bool cyhal_pdm_pcm_is_pending(cyhal_pdm_pcm_t *obj);
/** Abort an PDM/PCM operation started by cyhal_pdm_pcm_read_async function
*
* @param[in] obj The PDM/PCM peripheral to stop
* @return The status of the abort_async request
*/
cy_rslt_t cyhal_pdm_pcm_abort_async(cyhal_pdm_pcm_t *obj);
/** Register a PDM/PCM event handler
*
* This function will be called when one of the events enabled by \ref cyhal_pdm_pcm_enable_event occurs.
*
* @param[in] obj The PDM/PCM object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
* @param[in] callback_arg Generic argument that will be provided to the callback when called
*/
void cyhal_pdm_pcm_register_callback(cyhal_pdm_pcm_t *obj, cyhal_pdm_pcm_event_callback_t callback, void *callback_arg);
/** Configure PDM/PCM event enablement.
*
* @param[in] obj The PDM/PCM object
* @param[in] event The PDM/PCM event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on events, False to turn off
*/
void cyhal_pdm_pcm_enable_event(cyhal_pdm_pcm_t *obj, cyhal_pdm_pcm_event_t event, uint8_t intr_priority, bool enable);
/** Set the mechanism that is used to perform PDM/PCM asynchronous operation. The default is SW.
*
* When an enabled event occurs, the function specified by \ref cyhal_pdm_pcm_register_callback will be called.
*
* @param[in] obj The PDM/PCM object
* @param[in] mode The transfer mode
* @param[in] dma_priority The priority, if DMA is used. Valid values are the same as for @ref cyhal_dma_init.
* If DMA is not selected, the only valid value is CYHAL_DMA_PRIORITY_DEFAULT, and no
guarantees are made about prioritization.
* @return The status of the set mode request
*/
cy_rslt_t cyhal_pdm_pcm_set_async_mode(cyhal_pdm_pcm_t *obj, cyhal_async_mode_t mode, uint8_t dma_priority);
#if defined(__cplusplus)
}
#endif
#ifdef CYHAL_PDMPCM_IMPL_HEADER
#include CYHAL_PDMPCM_IMPL_HEADER
#endif /* CYHAL_PDMPCM_IMPL_HEADER */
/** \} group_hal_pdmpcm */

View File

@ -62,10 +62,9 @@ typedef enum {
CYHAL_PORT_20 = 0x14,
} cyhal_port_t;
/** Bitfield representing the configuration of a GPIO (hsiom selection and mode).
* Use the CY_GPIO_CFG_GET_MODE and CY_GPIO_CFG_GET_HSIOM to extract the
* individual field values.
*/
/** \cond INTERNAL */
/* The items in this cond block are DEPRECATED. They are only provided for mbed usage. */
typedef uint16_t cyhal_gpio_mapping_cfg_t; // 8bit hsiom, 8bit mode
/** Extract the GPIO mode setting from a cyhal_gpio_mapping_cfg_t */
@ -73,12 +72,11 @@ typedef uint16_t cyhal_gpio_mapping_cfg_t; // 8bit hsiom, 8bit mode
/** Extract the HSIOM selection from a cyhal_gpio_mapping_cfg_t */
#define CY_GPIO_CFG_GET_HSIOM(x) ((en_hsiom_sel_t)(((x) >> 8) & 0xFF))
/** \cond INTERNAL */
#define CY_GPIO_CFG_CREATE(hsiom, mode) ((cyhal_gpio_mapping_cfg_t)(((hsiom) << 8) + (mode)))
#define CYHAL_PIN_OUT_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(hsiom, CY_GPIO_DM_STRONG_IN_OFF)
#define CYHAL_PIN_OUT_BUF_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(hsiom, CY_GPIO_DM_STRONG)
#define CYHAL_PIN_OD_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(hsiom, CY_GPIO_DM_OD_DRIVESLOW_IN_OFF)
#define CYHAL_PIN_OD_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(hsiom, CY_GPIO_DM_OD_DRIVESLOW)
#define CYHAL_PIN_IN_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(hsiom, CY_GPIO_DM_HIGHZ)
#define CYHAL_PIN_PULLUP_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(hsiom, CY_GPIO_DM_PULLUP)
#define CYHAL_PIN_ANALOG_FUNCTION(hsiom) CY_GPIO_CFG_CREATE(HSIOM_SEL_GPIO, CY_GPIO_DM_ANALOG)

View File

@ -86,29 +86,41 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name PWM Results
*/
/** Bad argument */
#define CYHAL_PWM_RSLT_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PWM, 0))
/** Failed to initialize PWM clock */
#define CYHAL_PWM_RSLT_FAILED_CLOCK_INIT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PWM, 1))
/** Failed to initialize PWM */
#define CYHAL_PWM_RSLT_FAILED_INIT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PWM, 2))
/**
* \} \}
*/
/** Initialize the PWM out peripheral and configure the pin
* This is similar to the \ref cyhal_pwm_init_adv() but uses defaults for some of the
* more advanced setup options. See \ref subsection_pwm_snippet_1.
*
* @param[out] obj The PWM object to initialize
* @param[out] obj Pointer to a PWM object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] pin The PWM pin to initialize
* @param[in] clk An optional, pre-allocated clock to use, if NULL a new clock will be allocated
* @return The status of the init request.
*/
#define cyhal_pwm_init(obj, pin, clk) (cyhal_pwm_init_adv(obj, pin, NC, CYHAL_PWM_LEFT_ALIGN, true, 0u, (bool)(pin & 1), clk))
/** Bad argument */
#define CYHAL_PWM_RSLT_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PWM, 0))
/** Failed to initialize PWM clock */
#define CYHAL_PWM_RSLT_FAILED_CLOCK_INIT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PWM, 1))
/** Failed to initialize PWM */
#define CYHAL_PWM_RSLT_FAILED_INIT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_PWM, 2))
#define cyhal_pwm_init(obj, pin, clk) (cyhal_pwm_init_adv(obj, pin, NC, (pin & 1) ? CYHAL_PWM_RIGHT_ALIGN : CYHAL_PWM_LEFT_ALIGN, true, 0u, (bool)(pin & 1), clk))
/** PWM interrupt triggers */
typedef enum {
@ -132,7 +144,8 @@ typedef void(*cyhal_pwm_event_callback_t)(void *callback_arg, cyhal_pwm_event_t
* This is similar to the \ref cyhal_pwm_init() but provides additional setup options. <br>
* See \ref subsection_pwm_snippet_3.
*
* @param[out] obj The PWM object to initialize.
* @param[out] obj Pointer to a PWM object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] pin The PWM pin to initialize.
* @param[in] compl_pin An optional, additional inverted output pin. <br>
* If supplied, this must be connected to the same PWM instance as <b>pin</b>, for
@ -149,7 +162,7 @@ typedef void(*cyhal_pwm_event_callback_t)(void *callback_arg, cyhal_pwm_event_t
*
* @note In some cases, it is possible to use a pin designated for non-inverting output as an inverting output and vice versa. Whether this is possible is dependent on the HAL implementation and operating mode. See the implementation specific documentation for details.
*/
cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t compl_pin, cyhal_pwm_alignment_t pwm_alignment, bool continuous, uint32_t dead_time_us, bool invert, const cyhal_clock_divider_t *clk);
cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t compl_pin, cyhal_pwm_alignment_t pwm_alignment, bool continuous, uint32_t dead_time_us, bool invert, const cyhal_clock_t *clk);
/** Deinitialize the PWM object
*
@ -189,7 +202,9 @@ cy_rslt_t cyhal_pwm_start(cyhal_pwm_t *obj);
*/
cy_rslt_t cyhal_pwm_stop(cyhal_pwm_t *obj);
/** The PWM interrupt handler registration
/** Register a PWM interrupt handler
*
* This function will be called when one of the events enabled by \ref cyhal_pwm_enable_event occurs.
*
* @param[in] obj The PWM object
* @param[in] callback The callback handler which will be invoked when the event occurs
@ -198,6 +213,8 @@ cy_rslt_t cyhal_pwm_stop(cyhal_pwm_t *obj);
void cyhal_pwm_register_callback(cyhal_pwm_t *obj, cyhal_pwm_event_callback_t callback, void *callback_arg);
/** Configure PWM event enablement.
*
* When an enabled event occurs, the function specified by \ref cyhal_pwm_register_callback will be called.
*
* @param[in] obj The PWM object
* @param[in] event The PWM event type

View File

@ -54,13 +54,13 @@ __STATIC_INLINE void cyhal_pwm_register_callback_internal(cyhal_pwm_t *obj, cyha
#define cyhal_pwm_register_callback(obj, callback, callback_arg) cyhal_pwm_register_callback_internal(obj, callback, callback_arg)
__STATIC_INLINE void cyhal_pwm_enable_event_internal(cyhal_pwm_t *obj, cyhal_pwm_event_t event, uint8_t intrPriority, bool enable)
__STATIC_INLINE void cyhal_pwm_enable_event_internal(cyhal_pwm_t *obj, cyhal_pwm_event_t event, uint8_t intr_priority, bool enable)
{
uint32_t converted = cyhal_pwm_convert_event(event);
cyhal_tcpwm_enable_event(obj->base, &(obj->resource), converted, intrPriority, enable);
cyhal_tcpwm_enable_event(obj->base, &(obj->resource), converted, intr_priority, enable);
}
#define cyhal_pwm_enable_event(obj, event, intrPriority, enable) cyhal_pwm_enable_event_internal(obj, event, intrPriority, enable)
#define cyhal_pwm_enable_event(obj, event, intr_priority, enable) cyhal_pwm_enable_event_internal(obj, event, intr_priority, enable)
#if defined(__cplusplus)
}

View File

@ -29,10 +29,42 @@
* \addtogroup group_hal_qspi QSPI (Quad Serial Peripheral Interface)
* \ingroup group_hal
* \{
* High level interface for interacting with the Quad Serial Peripheral Interface (QSPI) interface.
* High level interface for interacting with the Quad-SPI interface.
*
* The QSPI block supports sending commands to and receiving commands from an
* another device (often an external memory) via single, dual, quad, or octal SPI.
* QSPI is an SPI-based communication interface, often used with external memory devices.
* The QSPI driver supports sending and receiving commands to/from from another
* device via a single, dual, quad, or octal SPI interface.
*
* \section subsection_qspi_features Features
* * Standard SPI Master interface
* * Supports Single/Dual/Quad/Octal SPI memories
* * Supports Dual-Quad SPI mode
* * Execute-In-Place (XIP) from external Quad SPI Flash
* * Supports external serial memory initialization via Serial Flash Discoverable Parameters (SFDP) standard
*
* \section subsection_qspi_code_snippets Code Snippets
* \note The following snippets show commands specific to the
* <a href="https://www.cypress.com/documentation/datasheets/s25fl512s-512-mbit-64-mbyte-30v-spi-flash-memory">S25FL512S Cypress NOR Flash device</a>.
* Refer to the datasheet of the external memory device for device specific memory commands.
* \subsection subsection_qspi_snippet_1 Code Snippet 1: Initializing the cyhal_qspi_command_t structure
* The following code snip demonstrates an example for initializing the cyhal_qspi_command_t structure for
* any given flash command. The cyhal_qspi_command_t.mode_bits structure has several other components which should
* be set as per the command. Mode bits are not required for single SPI read command, hence, mode_bits.disabled
* is set to TRUE in the below example code.
* \snippet qspi.c snippet_cyhal_qspi_structure_initialisation
* \subsection subsection_qspi_snippet_2 Code Snippet 2: QSPI initialization and Reading Flash memory
* This example function demonstrates the initialization of the QSPI component and use of the cyhal_qspi_read() function
* to complete the read operation and receive the read data in a buffer.
* \snippet qspi.c snippet_cyhal_qspi_read
* \subsection subsection_qspi_snippet_3 Code Snippet 3: Erasing Flash memory
* The following code snippet demonstrates the use of cyhal_qspi_transfer() API for sending single byte instruction
* that may or may not need any address or data bytes. It also shows the usage of status register read command within
* a while loop to poll the WIP bit status.
* \snippet qspi.c snippet_cyhal_qspi_erase
* \note Flash memories need erase operation before programming.
* \subsection subsection_qspi_snippet_4 Code Snippet 4: Programming Flash memory
* This code snippet demonstrates the usage cyhal_qspi_write() API for executing program operation on flash memory.
* \snippet qspi.c snippet_cyhal_qspi_program
*/
#pragma once
@ -41,78 +73,96 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** QSPI Bus width
*
* Some parts of commands provide variable bus width
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name QSPI Results
*/
/** Bus width Error. */
#define CYHAL_QSPI_RSLT_ERR_BUS_WIDTH \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 0))
/** Pin related Error. */
#define CYHAL_QSPI_RSLT_ERR_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 1))
/** Data select Error. */
#define CYHAL_QSPI_RSLT_ERR_DATA_SEL \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 2))
/** QSPI instance related error. */
#define CYHAL_QSPI_RSLT_ERR_INSTANCE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 3))
/** Clock frequency error. */
#define CYHAL_QSPI_RSLT_ERR_FREQUENCY \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 4))
/**
* \} \}
*/
/** QSPI Bus width. Some parts of commands provide variable bus width. */
typedef enum cyhal_qspi_bus_width {
CYHAL_QSPI_CFG_BUS_SINGLE = 1,
CYHAL_QSPI_CFG_BUS_DUAL = 2,
CYHAL_QSPI_CFG_BUS_QUAD = 4,
CYHAL_QSPI_CFG_BUS_OCTAL = 8,
CYHAL_QSPI_CFG_BUS_SINGLE = 1, /**< Normal SPI Mode */
CYHAL_QSPI_CFG_BUS_DUAL = 2, /**< Dual SPI Mode */
CYHAL_QSPI_CFG_BUS_QUAD = 4, /**< Quad SPI Mode */
CYHAL_QSPI_CFG_BUS_OCTAL = 8, /**< Octal SPI Mode */
} cyhal_qspi_bus_width_t;
/** Size in bits */
/** Address size in bits */
typedef enum cyhal_qspi_size {
CYHAL_QSPI_CFG_SIZE_8 = 8,
CYHAL_QSPI_CFG_SIZE_16 = 16,
CYHAL_QSPI_CFG_SIZE_24 = 24,
CYHAL_QSPI_CFG_SIZE_32 = 32,
CYHAL_QSPI_CFG_SIZE_8 = 8, /**< 8 bits address */
CYHAL_QSPI_CFG_SIZE_16 = 16, /**< 16 bits address */
CYHAL_QSPI_CFG_SIZE_24 = 24, /**< 24 bits address */
CYHAL_QSPI_CFG_SIZE_32 = 32, /**< 32 bits address */
} cyhal_qspi_size_t;
/** QSPI interrupt triggers */
typedef enum {
CYHAL_QSPI_EVENT_NONE = 0, /**< No event >*/
CYHAL_QSPI_IRQ_TRANSMIT_DONE = 1 << 0, /**< Async transmit done. >*/
CYHAL_QSPI_IRQ_RECEIVE_DONE = 1 << 1, /**< Async receive done. >*/
CYHAL_QSPI_EVENT_NONE = 0, /**< No event */
CYHAL_QSPI_IRQ_TRANSMIT_DONE = 1 << 0, /**< Async transmit done */
CYHAL_QSPI_IRQ_RECEIVE_DONE = 1 << 1, /**< Async receive done */
} cyhal_qspi_event_t;
#define CYHAL_QSPI_RSLT_ERR_BUS_WIDTH (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 0)) /**< Bus width Error. >*/
#define CYHAL_QSPI_RSLT_ERR_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 1)) /**< Pin related Error. >*/
#define CYHAL_QSPI_RSLT_ERR_DATA_SEL (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 2)) /**< Data select Error. >*/
#define CYHAL_QSPI_RSLT_ERR_INSTANCE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 3)) /**< QSPI instance related Error. >*/
#define CYHAL_QSPI_RSLT_ERR_FREQUENCY (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 4)) /**< Clock frequency error. >*/
/** @brief QSPI command settings */
typedef struct cyhal_qspi_command {
struct {
cyhal_qspi_bus_width_t bus_width; /**< Bus width for the instruction >*/
uint8_t value; /**< Instruction value >*/
bool disabled; /**< Instruction phase skipped if disabled is set to true >*/
} instruction;
cyhal_qspi_bus_width_t bus_width; /**< Bus width for the instruction */
uint8_t value; /**< Instruction value */
bool disabled; /**< Instruction phase skipped if disabled is set to true */
} instruction; /**< Instruction structure */
struct {
cyhal_qspi_bus_width_t bus_width; /**< Bus width for the address >*/
cyhal_qspi_size_t size; /**< Address size >*/
uint32_t value; /**< Address value >*/
bool disabled; /**< Address phase skipped if disabled is set to true >*/
} address;
cyhal_qspi_bus_width_t bus_width; /**< Bus width for the address */
cyhal_qspi_size_t size; /**< Address size */
uint32_t value; /**< Address value */
bool disabled; /**< Address phase skipped if disabled is set to true */
} address; /**< Address structure */
struct {
cyhal_qspi_bus_width_t bus_width; /**< Bus width for mode bits >*/
cyhal_qspi_size_t size; /**< Mode bits size >*/
uint32_t value; /**< Mode bits value >*/
bool disabled; /**< Mode bits phase skipped if disabled is set to true >*/
} mode_bits;
uint8_t dummy_count; /**< Dummy cycles count >*/
cyhal_qspi_bus_width_t bus_width; /**< Bus width for mode bits */
cyhal_qspi_size_t size; /**< Mode bits size */
uint32_t value; /**< Mode bits value */
bool disabled; /**< Mode bits phase skipped if disabled is set to true */
} mode_bits; /**< Mode bits structure */
uint8_t dummy_count; /**< Dummy cycles count */
struct {
cyhal_qspi_bus_width_t bus_width; /**< Bus width for data >*/
} data;
cyhal_qspi_bus_width_t bus_width; /**< Bus width for data */
} data; /**< Data structure */
} cyhal_qspi_command_t;
/** Handler for QSPI callbacks */
typedef void (*cyhal_qspi_event_callback_t)(void *callback_arg, cyhal_qspi_event_t event);
/** Initialize QSPI peripheral.
*
* It should initialize QSPI pins (io0-io7, sclk and ssel), set frequency, clock polarity and phase mode.
* The clock for the peripheral should be enabled
*
* @param[out] obj QSPI object
* @param[out] obj Pointer to a QSPI object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] io0 Data pin 0
* @param[in] io1 Data pin 1
* @param[in] io2 Data pin 2
@ -153,56 +203,68 @@ cy_rslt_t cyhal_qspi_set_frequency(cyhal_qspi_t *obj, uint32_t hz);
/** Receive a command and block of data, synchronously.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[out] data RX buffer
* @param[in,out] length in - RX buffer length in bytes, out - number of bytes read
* This will read either `length` bytes or the number of bytes that are currently available in the
* receive buffer, whichever is less, then return. The value pointed to by `length` will be updated
* to reflect the number of bytes that were actually read.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[out] data RX buffer
* @param[in] length RX buffer length in bytes
* @return The status of the read request
*/
cy_rslt_t cyhal_qspi_read(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, void *data, size_t *length);
/** Receive a command and block of data in asynchronous mode. This requires __enable_irq() to have been called
* in order to work. To receive a notification when the read is complete, enable and register a callback
* using cyhal_qspi_irq_enable and cyhal_qspi_register_irq.
/** Receive a command and block of data in asynchronous mode.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[out] data RX buffer
* @param[in,out] length in - RX buffer length in bytes, out - number of bytes read
* This will transfer `length` bytes into the buffer pointed to by `data` in the background. When the
* requested quantity of data has been read, the @ref CYHAL_QSPI_IRQ_RECEIVE_DONE event will be raised.
* See @ref cyhal_qspi_register_callback and @ref cyhal_qspi_enable_event.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[out] data RX buffer
* @param[in] length RX buffer length in bytes
* @return The status of the read request
*/
cy_rslt_t cyhal_qspi_read_async(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, void *data, size_t *length);
/** Send a command and block of data, synchronously.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[in] data TX buffer
* @param[in,out] length in - TX buffer length in bytes, out - number of bytes written
* This will write either `length` bytes or until the write buffer is full, whichever is less,
* then return. The value pointed to by `length` will be updated to reflect the number of bytes
* that were actually written.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[in] data TX buffer
* @param[in] length TX buffer length in bytes
* @return The status of the write request
*/
cy_rslt_t cyhal_qspi_write(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, const void *data, size_t *length);
/** Send a command and block of data in asynchronous mode. This requires __enable_irq() to have been called
* in order to work. To receive a notification when the read is complete, enable and register a callback
* using cyhal_qspi_irq_enable and cyhal_qspi_register_irq.
/** Send a command and block of data in asynchronous mode.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[in] data TX buffer
* @param[in,out] length in - TX buffer length in bytes, out - number of bytes written
* This will transfer `length` bytes into the tx buffer in the background. When the requested
* quantity of data has been queued in the transmit buffer, the @ref CYHAL_QSPI_IRQ_TRANSMIT_DONE
* event will be raised. See @ref cyhal_qspi_register_callback and @ref cyhal_qspi_enable_event.
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[in] data TX buffer
* @param[in] length TX buffer length in bytes
* @return The status of the write request
*/
cy_rslt_t cyhal_qspi_write_async(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, const void *data, size_t *length);
/** Send a command (and optionally data) and get the response. Can be used to send/receive device specific commands
*
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[in] tx_data TX buffer
* @param[in,out] tx_size in - TX buffer length in bytes, out - bytes actually written
* @param[out] rx_data RX buffer
* @param[in,out] rx_size in - RX buffer length in bytes, out - bytes actually read
* @param[in] obj QSPI object
* @param[in] command QSPI command
* @param[in] tx_data TX buffer
* @param[in] tx_size TX buffer length in bytes
* @param[out] rx_data RX buffer
* @param[in] rx_size RX buffer length in bytes
* @return The status of the transfer request
*/
cy_rslt_t cyhal_qspi_transfer(
@ -210,9 +272,11 @@ cy_rslt_t cyhal_qspi_transfer(
size_t rx_size
);
/** The QSPI event handler registration
/** Register a QSPI event handler
*
* @param[in] obj The QSPI object
* This function will be called when one of the events enabled by \ref cyhal_qspi_enable_event occurs.
*
* @param[in] obj The QSPI object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
* @param[in] callback_arg Generic argument that will be provided to the handler when called
*/
@ -220,12 +284,15 @@ void cyhal_qspi_register_callback(cyhal_qspi_t *obj, cyhal_qspi_event_callback_t
/** Configure QSPI interrupt enablement.
*
* @param[in] obj The QSPI object
* @param[in] event The QSPI event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
* When an enabled event occurs, the function specified by \ref cyhal_qspi_register_callback will be called.
*
* @param[in] obj The QSPI object
* @param[in] event The QSPI event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_qspi_enable_event(cyhal_qspi_t *obj, cyhal_qspi_event_t event, uint8_t intrPriority, bool enable);
void cyhal_qspi_enable_event(cyhal_qspi_t *obj, cyhal_qspi_event_t event, uint8_t intr_priority, bool enable);
#if defined(__cplusplus)
}

View File

@ -34,9 +34,28 @@
* The real time clock provides tracking of the current time and date, as
* well as the ability to trigger a callback at a specific time in the future.
*
* If a suitable clock source is available, the RTC can continue timekeeping
* operations even when the device is in a low power operating mode. See the
* device datasheet for more details.
* \section section_rtc_features Features
* * Configurable interrupt and callback assignment on RTC event \ref cyhal_rtc_event_t
* * Set alarm for a specific time and date \ref cyhal_rtc_set_alarm
*
* \section section_rtc_quickstart Quick Start
*
* Initialise the RTC using \ref cyhal_rtc_init. Set the current time and date using \ref cyhal_rtc_write. <br>
* See \ref subsection_rtc_snippet_1 to initialize RTC, read and write current date and time to the RTC peripheral.
* See \ref subsection_rtc_snippet_2 to set an alarm event on a specific time and date.
*
* \section section_rtc_snippets Code snippets
* \subsection subsection_rtc_snippet_1 Snippet 1: Initialize RTC, write and read current time and date
* The following code snippet initialises the RTC using the \ref cyhal_rtc_init. The current date and time are set using \ref cyhal_rtc_write.
* The current date and time is read from the RTC using \ref cyhal_rtc_read. The time structure <b> tm </b>, contains the calendar date and time which
* are broken down into its components. This structure is declared in standard C library time.h which is included by HAL.
* \snippet rtc.c snippet_cyhal_rtc_read_write_data_time
*
* \subsection subsection_rtc_snippet_2 Snippet 2: RTC Alarm using Callbacks
* The following code snippet configures the RTC to trigger an alarm event on a specified date and time using \ref cyhal_rtc_set_alarm.
* A callback is registered to handle the alarm event using \ref cyhal_rtc_register_callback.
* \snippet rtc.c snippet_cyhal_set_alarm_callback
*/
#pragma once
@ -46,17 +65,27 @@
#include <time.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
/** RTC not initialized */
#define CY_RSLT_RTC_NOT_INITIALIZED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_RTC, 0)
/** Bad argument */
#define CY_RSLT_RTC_BAD_ARGUMENT CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_RTC, 1)
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name RTC Results
*/
/** RTC not initialized */
#define CY_RSLT_RTC_NOT_INITIALIZED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_RTC, 0))
/** Bad argument */
#define CY_RSLT_RTC_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_RTC, 1))
/**
* \} \}
*/
/** RTC interrupt triggers */
typedef enum {
CYHAL_RTC_ALARM,
@ -65,12 +94,12 @@ typedef enum {
/** @brief Defines which fields should be active for the alarm. */
typedef struct
{
uint8_t en_sec : 1; /** !< Enable match of seconds */
uint8_t en_min : 1; /** !< Enable match of minutes */
uint8_t en_hour : 1; /** !< Enable match of hours */
uint8_t en_day : 1; /** !< Enable match of day of week */
uint8_t en_date : 1; /** !< Enable match of date in month */
uint8_t en_month : 1; /** !< Enable match of month */
uint8_t en_sec : 1; /**< Enable match of seconds */
uint8_t en_min : 1; /**< Enable match of minutes */
uint8_t en_hour : 1; /**< Enable match of hours */
uint8_t en_day : 1; /**< Enable match of day of week */
uint8_t en_date : 1; /**< Enable match of date in month */
uint8_t en_month : 1; /**< Enable match of month */
} cyhal_alarm_active_t;
/** Enumeration used to configure the DST format */
@ -111,10 +140,11 @@ typedef void (*cyhal_rtc_event_callback_t)(void *callback_arg, cyhal_rtc_event_t
* before any other RTC functions are called. This does not change the state
* of the RTC. It just enables access to it.
* NOTE: Before calling this, make sure all necessary System Clocks are setup
* correctly. Generally this means making sure the RTC has access to a Crystal
* for optimal accuracy and operation in low power.
* correctly. Generally this means making sure the RTC has access to a crystal
* oscillator for optimal accuracy and operation in low power.
*
* @param[out] obj RTC object
* @param[out] obj Pointer to an RTC object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @return The status of the init request
*/
cy_rslt_t cyhal_rtc_init(cyhal_rtc_t *obj);
@ -137,7 +167,7 @@ void cyhal_rtc_free(cyhal_rtc_t *obj);
*/
bool cyhal_rtc_is_enabled(cyhal_rtc_t *obj);
/** Get the current time from the RTC peripheral
/** Get the current time and date from the RTC peripheral
*
* @param[in] obj RTC object
* @param[out] time The current time (see: https://en.cppreference.com/w/cpp/chrono/c/tm)
@ -145,7 +175,7 @@ bool cyhal_rtc_is_enabled(cyhal_rtc_t *obj);
*/
cy_rslt_t cyhal_rtc_read(cyhal_rtc_t *obj, struct tm *time);
/** Write the current time in seconds to the RTC peripheral
/** Write the specified time and date to the RTC peripheral
*
* @param[in] obj RTC object
* @param[in] time The time to be set (see: https://en.cppreference.com/w/cpp/chrono/c/tm)
@ -170,7 +200,7 @@ cy_rslt_t cyhal_rtc_set_dst(cyhal_rtc_t *obj, const cyhal_rtc_dst_t *start, cons
*/
bool cyhal_rtc_is_dst(cyhal_rtc_t *obj);
/** Set an alarm for the specified time in seconds to the RTC peripheral
/** Set an alarm for the specified time and date using the RTC peripheral
*
* @param[in] obj RTC object
* @param[in] time The alarm time to be set (see: https://en.cppreference.com/w/cpp/chrono/c/tm)
@ -179,22 +209,36 @@ bool cyhal_rtc_is_dst(cyhal_rtc_t *obj);
*/
cy_rslt_t cyhal_rtc_set_alarm(cyhal_rtc_t *obj, const struct tm *time, cyhal_alarm_active_t active);
/** The RTC event callback handler registration
/** Set an alarm at a specified number of seconds in the future
*
* @param[in] obj RTC object
* @param[in] seconds The number of seconds in the future for the alarm to be
* set to. Because alarms cannot match the year (see \ref cyhal_alarm_active_t)
* the maximum number of seconds allowed is 365d*24h*60m*60s == 31,536,000s
* @return The status of the set_alarm_by_seconds request
*/
cy_rslt_t cyhal_rtc_set_alarm_by_seconds(cyhal_rtc_t *obj, const uint32_t seconds);
/** Register a RTC event callback handler
*
* This function will be called when one of the events enabled by \ref cyhal_rtc_enable_event occurs.
*
* @param[in] obj The RTC object
* @param[in] callback The callback handler which will be invoked when the alarm fires
* @param[in] callback The callback handler which will be invoked when the alarm event fires
* @param[in] callback_arg Generic argument that will be provided to the callback when called
*/
void cyhal_rtc_register_callback(cyhal_rtc_t *obj, cyhal_rtc_event_callback_t callback, void *callback_arg);
/** Configure RTC event enablement.
*
* @param[in] obj The RTC object
* @param[in] event The RTC event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
* When an enabled event occurs, the function specified by \ref cyhal_rtc_register_callback will be called.
*
* @param[in] obj The RTC object
* @param[in] event The RTC event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_rtc_enable_event(cyhal_rtc_t *obj, cyhal_rtc_event_t event, uint8_t intrPriority, bool enable);
void cyhal_rtc_enable_event(cyhal_rtc_t *obj, cyhal_rtc_event_t event, uint8_t intr_priority, bool enable);
#if defined(__cplusplus)
}

View File

@ -45,9 +45,6 @@ extern CySCB_Type* const CYHAL_SCB_BASE_ADDRESSES[CY_IP_MXSCB_INSTANCES];
/** The interrupt number of the SCB blocks. */
extern const IRQn_Type CYHAL_SCB_IRQ_N[CY_IP_MXSCB_INSTANCES];
/** The configuration structs for the resource in use on each SCB block (e.g. cyhal_i2c_t) */
extern void *cyhal_scb_config_structs[CY_IP_MXSCB_INSTANCES];
/** Get the SCB block corresponding to an IRQn.
*
@ -60,12 +57,41 @@ uint8_t cyhal_scb_get_block_from_irqn(IRQn_Type irqn);
*
* @return A pointer to the SCB object corresponding to the currently running ISR.
*/
__STATIC_INLINE void *cyhal_scb_get_irq_obj(void)
{
IRQn_Type irqn = CYHAL_GET_CURRENT_IRQN();
uint8_t block = cyhal_scb_get_block_from_irqn(irqn);
return cyhal_scb_config_structs[block];
}
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_find_scb_map(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map, size_t count);
#define CYHAL_FIND_SCB_MAP(pin, pin_map) cyhal_find_scb_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t))
/**
* 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);
#if defined(__cplusplus)
}

View File

@ -29,10 +29,42 @@
* \addtogroup group_hal_sdhc SDHC (SD Host Controller)
* \ingroup group_hal
* \{
* High level interface for interacting with the SD Host Controller (SDHC).
* High level interface to the Secure Digital Host Controller (SDHC).
*
* The SD Host Controller allows data to be read from and written to several types
* of memory cards, including SD and eMMC (see cyhal_sdhc_card_type_t for a full list).
* The SDHC driver allows data to be read from and written to an SD Card using the SDHC block.
* The data is transferred in blocks with a block size of 512 bytes.
*
* \section subsection_sdhc_features Features
* * Supports the 4-bit interface
* * Supports Ultra High Speed (UHS-I) mode
* * Supports Default Speed (DS), High Speed (HS), SDR12, SDR25 and SDR50 speed modes
*
* \section subsection_sdhc_quickstart Quick Start
* Initialize SDHC by using \ref cyhal_sdhc_init by selecting the pins according to the target device used.
* Specify the SDHC configuration using the configuration structure (const \ref cyhal_sdhc_config_t * config). <br>
* See \ref subsection_sdhc_snippet_1
*
* \section subsection_sdhc_code_snippets Code Snippets
*
* \subsection subsection_sdhc_snippet_1 Snippet 1: SDHC Initialization and configuration
* The following snippet is used to initialize the SDHC block. SDHC object - \ref cyhal_sdhc_t,
* SDHC card configuration structure (const \ref cyhal_sdhc_config_t * config). The pins connected to the SDHC block
* needs to be provided to the \ref cyhal_sdhc_init function.
* \snippet sdhc.c snippet_cyhal_sdhc_init
*
* \subsection subsection_sdhc_snippet_2 Snippet 2: SDHC Initialization and configuration with custom card detect pin
* The following snippet is used to initialize the SDHC block with a custom card detect pin. Cy_SD_Host_IsCardConnected()
* function needs to be over-ridden depending on the card detect pin selected.
* \snippet sdhc.c snippet_cyhal_sdhc_init_custom_card_detect
*
* \subsection subsection_sdhc_snippet_3 Snippet 3: Reading a block of data from an SD Card
* The following snippet reads a block of data from the SD Card.
* \snippet sdhc.c snippet_cyhal_sdhc_read
* \subsection subsection_sdhc_snippet_4 Snippet 4: Writing a block of data to an SD Card
* The following snippet writes a block of data to the SD Card.
* \snippet sdhc.c snippet_cyhal_sdhc_write
*/
#pragma once
@ -46,8 +78,30 @@
extern "C" {
#endif
#define CYHAL_SDHC_RSLT_ERR_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDHC, 0)) /**< Pin related Error. >*/
#define CYHAL_SDHC_RSLT_ERR_UNSUPPORTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDHC, 1)) /**< Requested feature is not supported on this hardware. >*/
/*******************************************************************************
* Defines
*******************************************************************************/
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name SDHC Results
*/
/**< Pin related Error. >*/
#define CYHAL_SDHC_RSLT_ERR_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDHC, 0))
/** Requested feature is not supported on this hardware. */
#define CYHAL_SDHC_RSLT_ERR_UNSUPPORTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDHC, 1))
/**
* \} \}
*/
/*******************************************************************************
* Enumerations
*******************************************************************************/
/** Card types */
typedef enum
@ -62,30 +116,39 @@ typedef enum
/** SDHC interrupt triggers */
typedef enum {
CYHAL_SDHC_CMD_COMPLETE = 0x0001, //!> Command Complete
CYHAL_SDHC_XFER_COMPLETE = 0x0002, //!> Host read/write transfer is complete
CYHAL_SDHC_BGAP_EVENT = 0x0004, //!> This bit is set when both read/write transaction is stopped at the block gap
CYHAL_SDHC_DMA_INTERRUPT = 0x0008, //!> Host controller detects an SDMA Buffer Boundary during transfer
CYHAL_SDHC_BUF_WR_READY = 0x0010, //!> This bit is set if the Buffer Write Enable changes from 0 to 1
CYHAL_SDHC_BUF_RD_READY = 0x0020, //!> This bit is set if the Buffer Read Enable changes from 0 to 1
CYHAL_SDHC_CARD_INSERTION = 0x0040, //!> This bit is set if the Card Inserted in the Present State register changes from 0 to 1.
CYHAL_SDHC_CARD_REMOVAL = 0x0080, //!> This bit is set if the Card Inserted in the Present State register changes from 1 to 0.
CYHAL_SDHC_CARD_INTERRUPT = 0x0100, //!> The synchronized value of the DAT[1] interrupt input for SD mode
CYHAL_SDHC_INT_A = 0x0200,
CYHAL_SDHC_INT_B = 0x0400,
CYHAL_SDHC_INT_C = 0x0800,
CYHAL_SDHC_RE_TUNE_EVENT = 0x1000, //!> This bit is set if the Re-Tuning Request changes from 0 to 1
CYHAL_SDHC_FX_EVENT = 0x2000, //!> This status is set when R[14] of response register is set to 1
CYHAL_SDHC_CQE_EVENT = 0x4000, //!> This status is set if Command Queuing/Crypto event has occurred
CYHAL_SDHC_ERR_INTERRUPT = 0x8000, //!> If any of the bits in the Error Interrupt Status register are set
CYHAL_SDHC_ALL_INTERRUPTS = 0xFFFF, //!> Is used to enable/disable all interrupts
CYHAL_SDHC_CMD_COMPLETE = 0x00001, //!> Command Complete
CYHAL_SDHC_XFER_COMPLETE = 0x00002, //!> Host read/write transfer is complete
CYHAL_SDHC_BGAP_EVENT = 0x00004, //!> This bit is set when both read/write transaction is stopped at the block gap
CYHAL_SDHC_DMA_INTERRUPT = 0x00008, //!> Host controller detects an SDMA Buffer Boundary during transfer
CYHAL_SDHC_BUF_WR_READY = 0x00010, //!> This bit is set if the Buffer Write Enable changes from 0 to 1
CYHAL_SDHC_BUF_RD_READY = 0x00020, //!> This bit is set if the Buffer Read Enable changes from 0 to 1
CYHAL_SDHC_CARD_INSERTION = 0x00040, //!> This bit is set if the Card Inserted in the Present State register changes from 0 to 1.
CYHAL_SDHC_CARD_REMOVAL = 0x00080, //!> This bit is set if the Card Inserted in the Present State register changes from 1 to 0.
CYHAL_SDHC_CARD_INTERRUPT = 0x00100, //!> The synchronized value of the DAT[1] interrupt input for SD mode
CYHAL_SDHC_INT_A = 0x00200,
CYHAL_SDHC_INT_B = 0x00400,
CYHAL_SDHC_INT_C = 0x00800,
CYHAL_SDHC_RE_TUNE_EVENT = 0x01000, //!> This bit is set if the Re-Tuning Request changes from 0 to 1
CYHAL_SDHC_FX_EVENT = 0x02000, //!> This status is set when R[14] of response register is set to 1
CYHAL_SDHC_CQE_EVENT = 0x04000, //!> This status is set if Command Queuing/Crypto event has occurred
CYHAL_SDHC_ASYNC_READ_COMPLETE = 0x10000, //!> Asynchronous read operation is complete
CYHAL_SDHC_ASYNC_WRITE_COMPLETE = 0x20000, //!> Asynchronous write operation is complete
CYHAL_SDHC_ERR_INTERRUPT = 0x08000, //!> If any of the bits in the Error Interrupt Status register are set
CYHAL_SDHC_ALL_INTERRUPTS = 0x3FFFF, //!> Is used to enable/disable all interrupts
} cyhal_sdhc_event_t;
#define CYHAL_SDHC_RSLT_ERR_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDHC, 0)) /**< Pin related Error. >*/
/*******************************************************************************
* Typedefs
*******************************************************************************/
/** Handler for SDHC interrupts */
typedef void (*cyhal_sdhc_event_callback_t)(void *callback_arg, cyhal_sdhc_event_t event);
/*******************************************************************************
* Data Structures
*******************************************************************************/
/** @brief Defines configuration options for the SDHC block */
typedef struct
{
@ -95,9 +158,15 @@ typedef struct
uint8_t busWidth; //!< The desired bus width
} cyhal_sdhc_config_t;
/*******************************************************************************
* Functions
*******************************************************************************/
/** Initialize the SDHC peripheral
*
* @param[out] obj The SDHC object
* @param[out] obj Pointer to an SDHC object.
* The caller must allocate the memory for this object but the init function will
* initialize its contents.
* @param[in] config The card configuration object
* @param[out] clk The pin connected to the clk signal
* @param[in] cmd The pin connected to the command signal
@ -116,6 +185,7 @@ typedef struct
* @param[in] ledCtrl The pin connected to the ledCtrl signal
* @param[in] cardEmmcReset The pin connected to the cardEmmcReset signal
* @return The status of the init request
*
*/
cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
const cyhal_sdhc_config_t *config,
@ -143,36 +213,54 @@ cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
*/
void cyhal_sdhc_free(cyhal_sdhc_t *obj);
/** Attempts to read data over the SDHC peripheral.
/** Attempts to read data synchronously over the SDHC peripheral.
*
* This will read as many blocks as possible, up to `length` blocks, into the buffer
* pointed to by `data`, then return. The value pointed to by `length` will be
* updated to reflect the number of words that were actually read.
*
* See \ref subsection_sdhc_snippet_3
*
* @param[in] obj The SDHC object
* @param[in] address The address to read data from
* @param[out] data Pointer to the byte-array of data to read from the device
* @param[out] data Pointer to the byte-array where data read from the device should be stored
* @param[in,out] length Number of 512 byte blocks to read, updated with the number actually read
* @return The status of the read request
*/
cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length);
/** Attempts to write data over SDHC peripheral
/** Attempts to write data synchronously over SDHC peripheral
*
* This will write as many blocks as possible, up to `length` blocks, then return.
* The value pointed to by `length` will be updated to reflect the number of words
* that were actually read.
*
* See \ref subsection_sdhc_snippet_4
*
* @param[in] obj The SDHC object
* @param[in] address The address to write data to
* @param[in] data Pointer to the byte-array of data to write to the device
* @param[in,out] length Number of 512 byte blocks to write, updated with the number actually written
* @return The status of the write request
*
*/
cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length);
/** Attempts to erase a block of data over the SDHC peripheral
/** Erases a block of data over the SDHC peripheral
*
* @param[in] obj The SDHC object
* @param[in] startAddr Is the address of the first byte to erase
* @param[in] length Number of 512 byte blocks (starting at startAddr) to erase
* @param[in] obj The SDHC object
* @param[in] start_addr Is the address of the first byte to erase
* @param[in] length Number of 512 byte blocks (starting at start_addr) to erase
* @return The status of the erase request
*
*/
cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t length);
cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t start_addr, size_t length);
/** Begin the SDHC read
/** Start SDHC asynchronous read
*
* This will transfer `length` 512 byte blocks into the buffer pointed to by `data` in the background.
* When the requested quantity of data has been read, the @ref CYHAL_SDHC_ASYNC_READ_COMPLETE event will
* be raised. See @ref cyhal_sdhc_register_callback and @ref cyhal_sdhc_enable_event.
*
* @param[in] obj The SDHC object that holds the transfer information
* @param[in] address The address to read data from
@ -182,8 +270,11 @@ cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t l
*/
cy_rslt_t cyhal_sdhc_read_async(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length);
/** Begin the SDHC write
/** Start asynchronous SDHC write
*
* This will transfer `length` 512 byte blocks from the buffer pointed to by `data` in the background.
* When the requested quantity of data has been written, the @ref CYHAL_SDHC_ASYNC_WRITE_COMPLETE event
* will be raised. See @ref cyhal_sdhc_register_callback and @ref cyhal_sdhc_enable_event.
* @param[in] obj The SDHC object that holds the transfer information
* @param[in] address The address to write data to
* @param[in] data The transmit buffer
@ -206,22 +297,27 @@ bool cyhal_sdhc_is_busy(const cyhal_sdhc_t *obj);
*/
cy_rslt_t cyhal_sdhc_abort_async(const cyhal_sdhc_t *obj);
/** The SDHC callback handler registration
/** Register an SDHC callback handler
*
* This function will be called when one of the events enabled by \ref cyhal_sdhc_enable_event occurs.
*
* @param[in] obj The SDHC object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
* @param[in] callback The callback handler which will be invoked when the event fires
* @param[in] callback_arg Generic argument that will be provided to the callback when called
*/
void cyhal_sdhc_register_callback(cyhal_sdhc_t *obj, cyhal_sdhc_event_callback_t callback, void *callback_arg);
/** Configure SDHC event enablement.
*
* When an enabled event occurs, the function specified by \ref cyhal_sdhc_register_callback will be called.
*
* @param[in] obj The SDHC object
* @param[in] event The SDHC event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intrPriority, bool enable);
void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intr_priority, bool enable);
#if defined(__cplusplus)
}

View File

@ -29,14 +29,54 @@
* \addtogroup group_hal_sdio SDIO (Secure Digital Input Output)
* \ingroup group_hal
* \{
* High level interface for interacting with the Secure Digital Input Output (SDIO) interface.
*
* The Secure Digital Input Output (SDIO) protocol is an extension of the SD
* interface for general I/O functions.
* High level interface to the Secure Digital Input Output (SDIO).
*
* This driver allows commands to be sent over the SDIO bus; the supported commands
* can be found in cyhal_sdio_command_t. Bulk data transfer is also supported
* can be found in \ref cyhal_sdio_command_t. Bulk data transfer is also supported
* via cyhal_sdio_bulk_transfer().
*
* The SDIO protocol is an extension of the SD
* interface for general I/O functions. Refer to the SD Specifications Part 1 SDIO
* Specifications Version 4.10 for more information on the SDIO protocol and specifications.
*
*
* \section subsection_sdio_features Features
* * Supports 4-bit interface
* * Supports Ultra High Speed (UHS-I) mode
* * Supports Default Speed (DS), High Speed (HS), SDR12, SDR25 and SDR50 speed modes
* * Supports SDIO card interrupts in both 1-bit and 4-bit modes
* * Supports Standard capacity (SDSC), High capacity (SDHC) and Extended capacity (SDXC) memory
*
* \section subsection_sdio_quickstart Quick Start
*
* \ref cyhal_sdio_init initializes the SDIO peripheral and passes a pointer to the SDIO block through the **obj** object of type \ref cyhal_sdio_t.
*
* \section subsection_sdio_code_snippets Code Snippets
*
* \subsection subsection_sdio_use_case_1 Snippet1: Simple SDIO Initialization example
* The following snippet shows how to initialize the SDIO interface with a pre-defined configuration
*
* \snippet sdio.c snippet_cyhal_sdio_simple_init
*
* \subsection subsection_sdio_use_case_2 Snippet2: Configure Interrupt
* The following snippet shows how to configure an interrupt and handle specific events. Refer \ref cyhal_sdio_event_t for different types of events.
*
* \snippet sdio.c snippet_cyhal_sdio_interrupt_callback
*
* \subsection subsection_sdio_use_case_3 Snippet3: Sending Commands
* The following snippet shows how to send a particular command. Some steps of the card initialization have been provided for reference. Refer \ref cyhal_sdio_command_t for different commands.
*
* \snippet sdio.c snippet_cyhal_sdio_send_command
*
* \subsection subsection_sdio_use_case_4 Snippet4: Bulk Data Transfer
* The following snippet shows how to start a bulk data transfer.
*
* \snippet sdio.c snippet_cyhal_sdio_bulk_transfer
*
* \subsection subsection_sdio_use_case_5 Snippet5: Async Data Transfer
*
* The following snippet shows how to start an async data transfer.
* \snippet sdio.c snippet_cyhal_sdio_async_transfer
*/
#pragma once
@ -50,6 +90,10 @@
extern "C" {
#endif
/*******************************************************************************
* Defines
*******************************************************************************/
#define CYHAL_SDIO_RET_NO_ERRORS (0x00) /**< No error*/
#define CYHAL_SDIO_RET_NO_SP_ERRORS (0x01) /**< Non-specific error code*/
#define CYHAL_SDIO_RET_CMD_CRC_ERROR (0x02) /**< There was a CRC error on the Command/Response*/
@ -65,79 +109,94 @@ extern "C" {
#define CYHAL_SDIO_SEMA_NOT_INITED (0x400) /**< Semaphore is not initiated */
#define CYHAL_SDIO_FUNC_NOT_SUPPORTED (0x800) /**< Function is not supported */
#define CYHAL_SDIO_CANCELED (0x1000) /**< Operation canceled */
#define CYHAL_SDIO_PM_PENDING_ERROR (0x2000) /**< Transfer cannot be initiated after power mode transition allowed.*/
/* HAL return value defines */
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name SDIO Results
*/
/** Incorrect parameter value define */
#define CYHAL_SDIO_RSLT_ERR_BAD_PARAM CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
CYHAL_RSLT_MODULE_SDIO, \
CYHAL_SDIO_BAD_ARGUMENT)
#define CYHAL_SDIO_RSLT_ERR_BAD_PARAM \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDIO, CYHAL_SDIO_BAD_ARGUMENT))
/** Clock initialization error define */
#define CYHAL_SDIO_RSLT_ERR_CLOCK CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
CYHAL_RSLT_MODULE_SDIO, \
CYHAL_SDIO_CLOCK_ERROR)
#define CYHAL_SDIO_RSLT_ERR_CLOCK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDIO, CYHAL_SDIO_CLOCK_ERROR))
/** Semaphore not initiated error define */
#define CYHAL_SDIO_RSLT_ERR_SEMA_NOT_INITED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
CYHAL_RSLT_MODULE_SDIO, \
CYHAL_SDIO_SEMA_NOT_INITED)
#define CYHAL_SDIO_RSLT_ERR_SEMA_NOT_INITED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDIO, CYHAL_SDIO_SEMA_NOT_INITED))
/** Error define based on SDIO lower function return value */
#define CYHAL_SDIO_RSLT_ERR_FUNC_RET(retVal) CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
CYHAL_RSLT_MODULE_SDIO, (retVal))
#define CYHAL_SDIO_RSLT_ERR_FUNC_RET(retVal) \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDIO, ((uint16_t)retVal)))
/** Define to indicate canceled operation */
#define CYHAL_SDIO_RSLT_CANCELED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
CYHAL_RSLT_MODULE_SDIO, \
CYHAL_SDIO_CANCELED)
#define CYHAL_SDIO_RSLT_CANCELED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDIO, CYHAL_SDIO_CANCELED))
/** Transfers are not allowed after the SDIO block has allowed power mode transition. */
#define CYHAL_SDIO_RSLT_ERR_PM_PENDING \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SDIO, CYHAL_SDIO_PM_PENDING_ERROR))
/**
* \} \}
*/
/*******************************************************************************
* Enumerations
*******************************************************************************/
/** Commands that can be issued */
typedef enum
{
CYHAL_SDIO_CMD_GO_IDLE_STATE = 0, //!> Go to idle state
CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR = 3, //!> Send a relative address
CYHAL_SDIO_CMD_IO_SEND_OP_COND = 5, //!> Send an OP IO
CYHAL_SDIO_CMD_SELECT_CARD = 7, //!> Send a card select
CYHAL_SDIO_CMD_GO_INACTIVE_STATE = 15, //!> Go to inactive state
CYHAL_SDIO_CMD_IO_RW_DIRECT = 52, //!> Perform a direct read/write
CYHAL_SDIO_CMD_IO_RW_EXTENDED = 53, //!> Perform an extended read/write
CYHAL_SDIO_CMD_GO_IDLE_STATE = 0, //!< Go to idle state
CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR = 3, //!< Send a relative address
CYHAL_SDIO_CMD_IO_SEND_OP_COND = 5, //!< Send an OP IO
CYHAL_SDIO_CMD_SELECT_CARD = 7, //!< Send a card select
CYHAL_SDIO_CMD_GO_INACTIVE_STATE = 15, //!< Go to inactive state
CYHAL_SDIO_CMD_IO_RW_DIRECT = 52, //!< Perform a direct read/write
CYHAL_SDIO_CMD_IO_RW_EXTENDED = 53, //!< Perform an extended read/write
} cyhal_sdio_command_t;
/** Types of transfer that can be performed */
typedef enum
{
CYHAL_READ, //!> Read from the card
CYHAL_WRITE //!> Write to the card
CYHAL_READ, //!< Read from the card
CYHAL_WRITE //!< Write to the card
} cyhal_transfer_t;
/** Types of events that could be asserted by SDIO */
typedef enum {
/* Interrupt-based thread events */
CYHAL_SDIO_CMD_COMPLETE = 0x00001, //!> Command Complete
CYHAL_SDIO_XFER_COMPLETE = 0x00002, //!> Host read/write transfer is complete
CYHAL_SDIO_BGAP_EVENT = 0x00004, //!> This bit is set when both read/write transaction is stopped
CYHAL_SDIO_DMA_INTERRUPT = 0x00008, //!> Host controller detects an SDMA Buffer Boundary during transfer
CYHAL_SDIO_BUF_WR_READY = 0x00010, //!> This bit is set if the Buffer Write Enable changes from 0 to 1
CYHAL_SDIO_BUF_RD_READY = 0x00020, //!> This bit is set if the Buffer Read Enable changes from 0 to 1
CYHAL_SDIO_CARD_INSERTION = 0x00040, //!> This bit is set if the Card Inserted in the Present State
CYHAL_SDIO_CARD_REMOVAL = 0x00080, //!> This bit is set if the Card Inserted in the Present State
CYHAL_SDIO_CARD_INTERRUPT = 0x00100, //!> The synchronized value of the DAT[1] interrupt input for SD mode
CYHAL_SDIO_INT_A = 0x00200, //!> Reserved: set to 0
CYHAL_SDIO_INT_B = 0x00400, //!> Reserved: set to 0
CYHAL_SDIO_INT_C = 0x00800, //!> Reserved: set to 0
CYHAL_SDIO_RE_TUNE_EVENT = 0x01000, //!> Reserved: set to 0
CYHAL_SDIO_FX_EVENT = 0x02000, //!> This status is set when R[14] of response register is set to 1
CYHAL_SDIO_CQE_EVENT = 0x04000, //!> This status is set if Command Queuing/Crypto event has occurred
CYHAL_SDIO_ERR_INTERRUPT = 0x08000, //!> If any of the bits in the Error Interrupt Status register are set
CYHAL_SDIO_CMD_COMPLETE = 0x00001, //!< Command Complete
CYHAL_SDIO_XFER_COMPLETE = 0x00002, //!< Host read/write transfer is complete
CYHAL_SDIO_BGAP_EVENT = 0x00004, //!< This bit is set when both read/write transaction is stopped
CYHAL_SDIO_DMA_INTERRUPT = 0x00008, //!< Host controller detects an SDMA Buffer Boundary during transfer
CYHAL_SDIO_BUF_WR_READY = 0x00010, //!< This bit is set if the Buffer Write Enable changes from 0 to 1
CYHAL_SDIO_BUF_RD_READY = 0x00020, //!< This bit is set if the Buffer Read Enable changes from 0 to 1
CYHAL_SDIO_CARD_INSERTION = 0x00040, //!< This bit is set if the Card Inserted in the Present State
CYHAL_SDIO_CARD_REMOVAL = 0x00080, //!< This bit is set if the Card Inserted in the Present State
CYHAL_SDIO_CARD_INTERRUPT = 0x00100, //!< The synchronized value of the DAT[1] interrupt input for SD mode
CYHAL_SDIO_INT_A = 0x00200, //!< Reserved: set to 0
CYHAL_SDIO_INT_B = 0x00400, //!< Reserved: set to 0
CYHAL_SDIO_INT_C = 0x00800, //!< Reserved: set to 0
CYHAL_SDIO_RE_TUNE_EVENT = 0x01000, //!< Reserved: set to 0
CYHAL_SDIO_FX_EVENT = 0x02000, //!< This status is set when R[14] of response register is set to 1
CYHAL_SDIO_CQE_EVENT = 0x04000, //!< This status is set if Command Queuing/Crypto event has occurred
CYHAL_SDIO_ERR_INTERRUPT = 0x08000, //!< If any of the bits in the Error Interrupt Status register are set
/* Non-interrupt-based thread events */
CYHAL_SDIO_GOING_DOWN = 0x10000, //!> The interface is going away (eg: powering down for some period of time)
CYHAL_SDIO_COMING_UP = 0x20000, //!> The interface is back up (eg: came back from a low power state)
CYHAL_SDIO_GOING_DOWN = 0x10000, //!< The interface is going away (eg: powering down for some period of time)
CYHAL_SDIO_COMING_UP = 0x20000, //!< The interface is back up (eg: came back from a low power state)
CYHAL_SDIO_ALL_INTERRUPTS = 0x0E1FF, //!> Is used to enable/disable all interrupts events
CYHAL_SDIO_ALL_INTERRUPTS = 0x0E1FF, //!< Is used to enable/disable all interrupts events
} cyhal_sdio_event_t;
/*******************************************************************************
* Data Structures
*******************************************************************************/
/** @brief SDIO controller initial configuration */
typedef struct
{
@ -148,9 +207,15 @@ typedef struct
/** Callback for SDIO events */
typedef void (*cyhal_sdio_event_callback_t)(void *callback_arg, cyhal_sdio_event_t event);
/*******************************************************************************
* Data Structures
*******************************************************************************/
/** Initialize the SDIO peripheral
*
* @param[out] obj The SDIO object
* @param[out] obj Pointer to an SDIO object.
* The caller must allocate the memory for this object but the init
* function will initialize its contents.
* @param[out] clk The pin connected to the clk signal
* @param[in] cmd The pin connected to the command signal
* @param[in] data0 The pin connected to the data0 signal
@ -158,36 +223,45 @@ typedef void (*cyhal_sdio_event_callback_t)(void *callback_arg, cyhal_sdio_event
* @param[in] data2 The pin connected to the data2 signal
* @param[in] data3 The pin connected to the data3 signal
* @return The status of the init request
*
* Returns \ref CY_RSLT_SUCCESS on successful operation. Refer \ref subsection_sdio_use_case_1 for more information.
*/
cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk, cyhal_gpio_t data0, cyhal_gpio_t data1, cyhal_gpio_t data2, cyhal_gpio_t data3);
/** Release the SDIO peripheral, not currently invoked. It requires further
* resource management.
/** Release the SDIO block.
*
* @param[in,out] obj The SDIO object
*/
void cyhal_sdio_free(cyhal_sdio_t *obj);
/** Configure the SDIO block.
/** Configure the SDIO block with required parameters. Refer \ref cyhal_sdio_cfg_t for more information.
*
* @param[in,out] obj The SDIO object
* @param[in] config The SDIO configuration to apply
* @return The status of the configure request
* @return The status of the configure request.
*
* Returns \ref CY_RSLT_SUCCESS on successful operation.
*/
cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config);
/** Sends a command to the SDIO block.
/** Sends command to the SDIO device. See \ref cyhal_sdio_command_t for list of available commands.
*
* This will block until the command is completed.
*
* @param[in,out] obj The SDIO object
* @param[in] direction The direction of transfer (read/write)
* @param[in] command The SDIO command to send
* @param[in] command The command to send to the SDIO device
* @param[in] argument The argument to the command
* @param[out] response The response from the SDIO device
* @return The status of the configure request
* @return The status of the command transfer.
*
* Returns \ref CY_RSLT_SUCCESS on successful operation. Refer \ref subsection_sdio_use_case_3 for more information.
*/
cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t direction, cyhal_sdio_command_t command, uint32_t argument, uint32_t* response);
/** Performs a bulk data transfer (CMD=53) to the SDIO block.
/** Performs a bulk data transfer. Sends \ref CYHAL_SDIO_CMD_IO_RW_EXTENDED command (CMD=53) which allows writing and reading of a large number of I/O registers with a single command.
*
* This will block until the transfer is completed.
*
* @param[in,out] obj The SDIO object
* @param[in] direction The direction of transfer (read/write)
@ -201,51 +275,73 @@ cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t directio
* in the buffer will be the requested data.
* @param[in] length The number of bytes to send
* @param[out] response The response from the SDIO device
* @return The status of the configure request
* @return The status of the bulk transfer operation.
*
* Returns \ref CY_RSLT_SUCCESS on successful operation. Refer \ref subsection_sdio_use_case_4 for more information.
*/
cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument, const uint32_t* data, uint16_t length, uint32_t* response);
/** Performs a bulk asynchronus data transfer (CMD=53) to the SDIO block.
/** Performs a bulk asynchronous data transfer by issuing the \ref CYHAL_SDIO_CMD_IO_RW_EXTENDED command(CMD=53) to the SDIO block.
* After exiting this function the \ref CYHAL_SDIO_CMD_COMPLETE and \ref CYHAL_SDIO_XFER_COMPLETE events are not asserted.
*
* To complete the asynchronous transfer, call \ref cyhal_sdio_is_busy()
* until it returns false.
* The \ref CYHAL_SDIO_CMD_COMPLETE and \ref CYHAL_SDIO_XFER_COMPLETE events are enabled
* after the asynchronous transfer is complete and in the condition they were
* enabled in before the transfer operation started. Handle these events in the interrupt callback.
*
* When the transfer is complete, the \ref CYHAL_SDIO_XFER_COMPLETE event will be raised.
* See \ref cyhal_sdio_register_callback and \ref cyhal_sdio_enable_event.
*
* @param[in,out] obj The SDIO object
* @param[in] direction The direction of transfer (read/write)
* @param[in] argument The argument to the command
* @param[in] data The data to send to the SDIO device
* @param[in] length The number of bytes to send
* @return The status of the configure request
* @return The status of the async tranfer operation.
*
* Returns \ref CY_RSLT_SUCCESS on successful operation. Refer \ref subsection_sdio_use_case_5 for more information.
*/
cy_rslt_t cyhal_sdio_transfer_async(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument, const uint32_t* data, uint16_t length);
/** Checks if the specified SDIO is in use
*
* @param[in] obj The SDIO peripheral to check
* @return Indication of whether the SDIO is still transmitting
* @return true if SDIO is in use. false, otherwise.
*/
bool cyhal_sdio_is_busy(const cyhal_sdio_t *obj);
/** Abort an SDIO transfer
*
* @param[in] obj The SDIO peripheral to stop
* @return The status of the abort_async request
* @return The status of the abort_async request.
*
* Returns \ref CY_RSLT_SUCCESS on successful operation.
*/
cy_rslt_t cyhal_sdio_abort_async(const cyhal_sdio_t *obj);
/** The SDIO event callback registration
/** Register an SDIO event callback to be invoked when the event is triggered.
*
* This function will be called when one of the events enabled by \ref cyhal_sdio_enable_event occurs.
*
* @param[in] obj The SDIO object
* @param[in] callback The callback function which will be invoked when the event triggers
* @param[in] callback_arg Generic argument that will be provided to the callback when executed
*
* Refer \ref subsection_sdio_use_case_2 for more implementation.
*/
void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_event_callback_t callback, void *callback_arg);
/** Configure which SDIO events trigger callbacks.
/** Enables callbacks to be triggered for specified SDIO events. Refer \ref cyhal_sdio_event_t for all events.
*
* @param[in] obj The SDIO object
* @param[in] event The SDIO event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable Set to true to enable events, or false to disable them
*
* Refer \ref subsection_sdio_use_case_2 for more information.
*/
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intrPriority, bool enable);
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intr_priority, bool enable);
/*******************************************************************************
* Backward compatibility macro. The following code is DEPRECATED and must

View File

@ -82,6 +82,7 @@
*
* * <a href="https://github.com/cypresssemiconductorco/mtb-example-psoc6-spi-master"><b>mtb-example-psoc6-spi-master</b></a>: This example project demonstrates
* use of SPI (HAL) resource in PSoC® 6 MCU in Master mode to write data to an SPI slave.
*
*/
#pragma once
@ -90,26 +91,41 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name SPI Results
*/
/** Bad argument */
#define CYHAL_SPI_RSLT_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 0))
#define CYHAL_SPI_RSLT_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 0))
/** Failed to initialize SPI clock */
#define CYHAL_SPI_RSLT_CLOCK_ERROR (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 1))
#define CYHAL_SPI_RSLT_CLOCK_ERROR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 1))
/** Failed to Transfer SPI data */
#define CYHAL_SPI_RSLT_TRANSFER_ERROR (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 2))
#define CYHAL_SPI_RSLT_TRANSFER_ERROR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 2))
/** Provided clock is not supported by SPI */
#define CYHAL_SPI_RSLT_CLOCK_NOT_SUPPORTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 3))
#define CYHAL_SPI_RSLT_CLOCK_NOT_SUPPORTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 3))
/** Provided PIN configuration is not supported by SPI */
#define CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 5))
#define CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 5))
/** Provided PIN configuration is not supported by SPI */
#define CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 6))
#define CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 6))
/** The requested resource type is invalid */
#define CYHAL_SPI_RSLT_ERR_INVALID_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 7))
#define CYHAL_SPI_RSLT_ERR_INVALID_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 7))
/**
* \} \}
*/
/** Compatibility define for cyhal_spi_set_frequency. */
#define cyhal_spi_frequency cyhal_spi_set_frequency
@ -127,25 +143,36 @@ typedef enum {
/** Handler for SPI interrupts */
typedef void (*cyhal_spi_event_callback_t)(void *callback_arg, cyhal_spi_event_t event);
/** Flag for SPI \ref cyhal_spi_mode_t values indicating that the LSB is sent first. */
#define CYHAL_SPI_MODE_FLAG_LSB (0x01u)
/** Flag for SPI \ref cyhal_spi_mode_t values indicating that the CPHA=1. */
#define CYHAL_SPI_MODE_FLAG_CPHA (0x02u)
/** Flag for SPI \ref cyhal_spi_mode_t values indicating that the CPOL=1. */
#define CYHAL_SPI_MODE_FLAG_CPOL (0x04u)
/** Creates a \ref cyhal_spi_mode_t value given the cpol, cpha, lsb values. */
#define CYHAL_SPI_MODE(cpol, cpha, lsb) (((cpol > 0) ? CYHAL_SPI_MODE_FLAG_CPOL : 0) | \
((cpha > 0) ? CYHAL_SPI_MODE_FLAG_CPHA : 0) | \
(( lsb > 0) ? CYHAL_SPI_MODE_FLAG_LSB : 0))
/** SPI operating modes */
typedef enum
{
/** Standard motorola SPI CPOL=0, CPHA=0 with MSB first operation */
CYHAL_SPI_MODE_00_MSB,
CYHAL_SPI_MODE_00_MSB = CYHAL_SPI_MODE(0, 0, 0),
/** Standard motorola SPI CPOL=0, CPHA=0 with LSB first operation */
CYHAL_SPI_MODE_00_LSB,
CYHAL_SPI_MODE_00_LSB = CYHAL_SPI_MODE(0, 0, 1),
/** Standard motorola SPI CPOL=0, CPHA=1 with MSB first operation */
CYHAL_SPI_MODE_01_MSB,
CYHAL_SPI_MODE_01_MSB = CYHAL_SPI_MODE(0, 1, 0),
/** Standard motorola SPI CPOL=0, CPHA=1 with LSB first operation */
CYHAL_SPI_MODE_01_LSB,
CYHAL_SPI_MODE_01_LSB = CYHAL_SPI_MODE(0, 1, 1),
/** Standard motorola SPI CPOL=1, CPHA=0 with MSB first operation */
CYHAL_SPI_MODE_10_MSB,
CYHAL_SPI_MODE_10_MSB = CYHAL_SPI_MODE(1, 0, 0),
/** Standard motorola SPI CPOL=1, CPHA=0 with LSB first operation */
CYHAL_SPI_MODE_10_LSB,
CYHAL_SPI_MODE_10_LSB = CYHAL_SPI_MODE(1, 0, 1),
/** Standard motorola SPI CPOL=1, CPHA=1 with MSB first operation */
CYHAL_SPI_MODE_11_MSB,
CYHAL_SPI_MODE_11_MSB = CYHAL_SPI_MODE(1, 1, 0),
/** Standard motorola SPI CPOL=1, CPHA=1 with LSB first operation */
CYHAL_SPI_MODE_11_LSB,
CYHAL_SPI_MODE_11_LSB = CYHAL_SPI_MODE(1, 1, 1),
} cyhal_spi_mode_t;
/** @brief Initial SPI configuration. */
@ -159,7 +186,8 @@ typedef struct
/** Initialize the SPI peripheral
*
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
* @param[out] obj The SPI object to initialize
* @param[out] obj Pointer to a SPI object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] mosi The pin to use for MOSI
* @note At least MOSI or MISO pin should be non-NC
* @param[in] miso The pin to use for MISO
@ -175,7 +203,7 @@ typedef struct
* @param[in] is_slave false for master mode or true for slave mode operation
* @return The status of the init request
*/
cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, cyhal_gpio_t sclk, cyhal_gpio_t ssel, const cyhal_clock_divider_t *clk,
cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, cyhal_gpio_t sclk, cyhal_gpio_t ssel, const cyhal_clock_t *clk,
uint8_t bits, cyhal_spi_mode_t mode, bool is_slave);
/** Release a SPI object
@ -195,10 +223,11 @@ void cyhal_spi_free(cyhal_spi_t *obj);
*/
cy_rslt_t cyhal_spi_set_frequency(cyhal_spi_t *obj, uint32_t hz);
/** Get a received value out of the SPI receive buffer
/** Synchronously get a received value out of the SPI receive buffer
*
* In Master mode - transmits fill-in value and read the data from RxFifo
* In Slave mode - Blocks until a value is available
*
* @param[in] obj The SPI peripheral to read
* @param[in] value The value received
* @return The status of the read request
@ -208,10 +237,11 @@ cy_rslt_t cyhal_spi_set_frequency(cyhal_spi_t *obj, uint32_t hz);
*/
cy_rslt_t cyhal_spi_recv(cyhal_spi_t *obj, uint32_t* value);
/** Send a byte out
/** Synchronously send a byte out
*
* In Master mode transmits value to slave and read/drop a value from the RxFifo.
* In Slave mode writes a value to TxFifo
*
* @param[in] obj The SPI peripheral to use for sending
* @param[in] value The value to send
* @return The status of the write request
@ -221,11 +251,13 @@ cy_rslt_t cyhal_spi_recv(cyhal_spi_t *obj, uint32_t* value);
*/
cy_rslt_t cyhal_spi_send(cyhal_spi_t *obj, uint32_t value);
/** Write a block out and receive a value
/** Synchronously Write a block out and receive a value
*
* The total number of bytes sent and received will be the maximum of
* tx_length and rx_length. The bytes written will be padded with the
* value 0xff.
* value given by write_fill.
*
* This function will block for the duration of the transfer.
*
* @param[in] obj The SPI peripheral to use for sending
* @param[in] tx Pointer to the byte-array of data to write to the device
@ -238,7 +270,12 @@ cy_rslt_t cyhal_spi_send(cyhal_spi_t *obj, uint32_t value);
*/
cy_rslt_t cyhal_spi_transfer(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length, uint8_t write_fill);
/** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
/** Start an asynchronous SPI transfer.
*
* This will transfer `rx_length` bytes into the buffer pointed to by `rx`, while simultaneously transfering
* `tx_length` bytes of data from the buffer pointed to by `tx`, both in the background.
* When the transfer is complete, the @ref CYHAL_SPI_IRQ_DONE event will be raised.
* See @ref cyhal_spi_register_callback and @ref cyhal_spi_enable_event.
*
* @param[in] obj The SPI object that holds the transfer information
* @param[in] tx The transmit buffer
@ -264,9 +301,11 @@ bool cyhal_spi_is_busy(cyhal_spi_t *obj);
*/
cy_rslt_t cyhal_spi_abort_async(cyhal_spi_t *obj);
/** The SPI callback handler registration
/** Register a SPI callback handler
*
* @param[in] obj The SPI object
* This function will be called when one of the events enabled by \ref cyhal_spi_enable_event occurs.
*
* @param[in] obj The SPI object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
* @param[in] callback_arg Generic argument that will be provided to the callback when called
*/
@ -274,12 +313,14 @@ void cyhal_spi_register_callback(cyhal_spi_t *obj, cyhal_spi_event_callback_t ca
/** Configure SPI interrupt. This function is used for word-approach
*
* @param[in] obj The SPI object
* @param[in] event The SPI event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
* When an enabled event occurs, the function specified by \ref cyhal_spi_register_callback will be called.
*
* @param[in] obj The SPI object
* @param[in] event The SPI event type
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_spi_enable_event(cyhal_spi_t *obj, cyhal_spi_event_t event, uint8_t intrPriority, bool enable);
void cyhal_spi_enable_event(cyhal_spi_t *obj, cyhal_spi_event_t event, uint8_t intr_priority, bool enable);
/*******************************************************************************
* Backward compatibility macro. The following code is DEPRECATED and must

View File

@ -0,0 +1,386 @@
/***************************************************************************//**
* \file cyhal_syspm.h
*
* \brief
* Provides a high level interface for interacting with the Cypress power
* management configuration. This interface abstracts out the
* chip specific details. If any chip specific functionality is necessary, or
* performance is critical the low level functions can be used directly.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
/**
* \addtogroup group_hal_syspm System Power Management
* \ingroup group_hal
* \{
* Interface for changing power states and restricting when they are allowed.
*
* Power management is handled both at a system level and at a peripheral driver
* level. The system wide API (this) allows the user to interact with the product
* as a whole. Additionally, each peripheral keeps track of what its state is and
* whether it can safely move to a new state while still maintaining any current
* operations.
*
* At the System level, the APIs are intended to allow the application to specify
* exactly what is happening. It can request changes to both the MCU Power State
* as well as the System Wide Power State. There are three supported MCU Power
* States:
* * Active - This is the normal operating state of the MCU
* * Sleep - In this state the MCU is no longer running. It can be woken up again
* from an interrupt. This state is reached by calling \ref cyhal_syspm_sleep.
* * Deep Sleep - In this state the MCU is no longer running. It can only be woken
* up by select interrupts. This state is reached by calling \ref
* cyhal_syspm_deepsleep.
* <p>Additionally, there are three supported system states:
* * Normal (\ref CYHAL_SYSPM_SYSTEM_NORMAL) - This is a normal operating state
* for the device. This is exposed by \ref cyhal_syspm_set_system_state.
* * Low (\ref CYHAL_SYSPM_SYSTEM_LOW) - This is a lower power operating state
* that may be supported by the device. This state often imposes specific
* requirements on clock speeds and voltage levels. See the device specific
* documentation for any device specific requirements for this mode, or whether
* it is even supported. If the device supports this mode, it is exposed by
* \ref cyhal_syspm_set_system_state.
* * Hibernate - This is the lowest available power state. In this state most of
* the chip is powered down. It has a very limited number of wakeup sources, and
* may require the device to reboot in order to come back up. It can be accessed
* by calling \ref cyhal_syspm_hibernate.
* Any time a power state transition is requested a series of callbacks are invoked.
* This allows peripherals, or other parts of the application, to confirm they are
* not currently doing something that would not work in the requested power state.
* HAL Peripheral drivers automatically register these callbacks when they are
* initialized. The application also has the option to register a callback
* function(s) to be called on requested state transitions by callling \ref
* cyhal_syspm_register_callback. If registered, the application level callbacks
* are invoked first. This gives the application a chance stop any peripherals, if
* appropriate, to ensure the power transition can actually happen. Alternatively
* it can directly reject the transition. Each callback registered can specify
* the exact set of states ( \ref cyhal_syspm_callback_state_t ) that it should
* be called for. Each callback is invoked multiple times as part of the transition
* process as defined by \ref cyhal_syspm_callback_mode_t.
*
* At any point the code can lock the ability to enter deep sleep by calling \ref
* cyhal_syspm_lock_deepsleep. This should be done in critical blocks that need to
* continue remain active. When the critical work is complete, and the lock is no
* longer needed, it can be released by calling \ref cyhal_syspm_unlock_deepsleep.
* The lock is a counter with a max count of USHRT_MAX. It must be locked/unlocked
* an equal number of times before the device is actually able to enter deep sleep.
*
* All peripherals are expected to operate in the default Active/Normal power
* state. Some peripherals (primarily analog) can operate in lower power states as
* well. These drivers will operate in all power states that the hardware supports.
*
* When power transitions are requested each type of peripheral has a default
* behavior. Peripherals that can continue to operate in the requested power mode
* do not interfere. Peripherals that are not currently active allow the transition,
* but make sure they restore their state if needed for when the device comes back.
* Peripherals that are active and cannot continue to work in the requested power
* state will block the transition.
*
* \note The power management functionality available depends on the availability
* of the features in the hardware. For detailed information about exactly what is
* supported on each device, refer to the Device Datasheet or Technical Reference
* Manual (TRM).
* \section section_syspm_features Features
* This driver provides control over multiple different types of power management
* and when those transitions are allowed:
* * Change CPU Power State: APIs to allow changing the current CPU state into
* one of the lower power CPU states (SLEEP, DEEPSLEEP)
* * Change System Power State: An API allows for changing the system wide power
* state between one of states (NORMAL, LOW)
* - Hibernate: An API that allows to set the hibernate
* wakeup source and set the system state to Hibernate.
* * General Purpose Power State Transition Callback: APIs allow for
* registering/unregistering a callback function to be notified when various power
* state transitions happen. If registered, the application can do anything necessary
* at power transitions. It can even prevent the transition if need-be.
* * Peripheral Specific Power State Transition Callback: APIs allow for
* registering/unregistering a callback function to be called when a peripheral with
* a CUSTOM power mode strategy exists and a power mode transition is requested.
* This allows the application to customize when it is OK for the peripheral to enter
* a low power state.
* - Lock DeepSleep: APIs to prevent/allow the CPU from going to deep sleep. This
* is a convenience API rather than needing to implement a full Transition Callback
* handler.
*
* \section section_syspm_quickstart Quick Start
*
* Unlike most HAL drivers this does not require initializing an instance object. The
* APIs provided here can be called at anytime. See the snippets below for examples
* of how to use this driver.
*
* \section section_syspm_snippets Code Snippets
*
* \subsection subsection_syspm_snippet_1 Snippet 1: Simple deep sleep locking
* The following snippet shows how to use the deep sleep locking APIs to restrict
* when the device can enter deep sleep. In between the lock/unlock calls any
* attempt to change power modes will automatically be canceled.
* \snippet syspm.c snippet_cyhal_syspm_simple_locking
*
* \subsection subsection_syspm_snippet_2 Snippet 2: Calling different power state functions
* The following snippet shows the different functions that exist to change power states
* on the device and how they can each be called.
* \snippet syspm.c snippet_cyhal_syspm_power_transitions
*
* \subsection subsection_syspm_snippet_3 Snippet 3: Using callbacks for application power management
* The following snippet shows how to use the callback mechanisms to manage whether
* it is safe to enter low power modes.
* \snippet syspm.c snippet_cyhal_syspm_app_callback
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_general_types.h"
#include "cyhal_hw_types.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name SysPM Results
*/
/** Incorrect argument passed into a function. */
#define CYHAL_SYSPM_RSLT_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSPM, 0))
/** Driver was unable to be initialized. */
#define CYHAL_SYSPM_RSLT_INIT_ERROR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSPM, 1))
/** Failed to register callback */
#define CYHAL_SYSPM_RSLT_CB_REGISTER_ERROR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSPM, 2))
/** Power Management transition is pending, data cannot be transferred */
#define CYHAL_SYSPM_RSLT_ERR_PM_PENDING \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSPM, 3))
/**
* \} \}
*/
/** \cond INTERNAL */
/** Sentinel value to indicate end of callback list */
#define CYHAL_SYSPM_END_OF_LIST ((cyhal_syspm_callback_data_t*)0x789)
/** \endcond */
/** Enumeration of the system wide power modes. These modes are device specifc and
* may not be supported on all devices. Refer to the device specific documentation
* or the Data Sheet to determine what is allowed. Devices that do support these
* modes may have requirements for adjusting system settings such as clocks or
* voltage levels before transition.
*/
typedef enum
{
CYHAL_SYSPM_SYSTEM_NORMAL, /**< Normal Mode. */
CYHAL_SYSPM_SYSTEM_LOW, /**< Low Power Mode. */
} cyhal_syspm_system_state_t;
/** Flags enum for the hibernate wakeup sources.
* \note Not all wakeup sources are valid on devices. Refer to the datasheet for
* device specifics.
*/
typedef enum
{
CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW = 0x01U, /**< Wake on a low logic level for the LPComp0. */
CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH = 0x02U, /**< Wake on a high logic level for the LPComp0. */
CYHAL_SYSPM_HIBERNATE_LPCOMP1_LOW = 0x04U, /**< Wake on a low logic level for the LPComp1. */
CYHAL_SYSPM_HIBERNATE_LPCOMP1_HIGH = 0x08U, /**< Wake on a high logic level for the LPComp1. */
CYHAL_SYSPM_HIBERNATE_RTC_ALARM = 0x10U, /**< Configure the RTC alarm as wakeup source. */
CYHAL_SYSPM_HIBERNATE_WDT = 0x20U, /**< Configure the WDT interrupt as wakeup source. */
CYHAL_SYSPM_HIBERNATE_PINA_LOW = 0x40U, /**< Configure a low logic level for the first wakeup-pin.
See device datasheet for specific pin. */
CYHAL_SYSPM_HIBERNATE_PINA_HIGH = 0x80U, /**< Configure a high logic level for the first wakeup-pin.
See device datasheet for specific pin. */
CYHAL_SYSPM_HIBERNATE_PINB_LOW = 0x100U, /**< Configure a low logic level for the second wakeup-pin.
See device datasheet for specific pin. */
CYHAL_SYSPM_HIBERNATE_PINB_HIGH = 0x200U /**< Configure a high logic level for the second wakeup-pin.
See device datasheet for specific pin. */
} cyhal_syspm_hibernate_source_t;
/** Sets the system mode to hibernate.
*
* This function configures the sources to wake up the device from hibernate mode
* and then sets the system to hibernate mode.
*
* In hibernate mode, all internal supplies are off and no internal state is retained.
*
* Sources can be wakeup pins, LPComparators, Watchdog (WDT) interrupt, or a Real-Time
* clock (RTC) alarm (interrupt). Wakeup from system hibernate always results in a device
* reset and normal boot process.
*
* Wakeup pins:
*
* A wakeup is supported by pins with programmable polarity. These pins
* are typically connected to the GPIO pins or on-chip peripherals under some
* conditions. See device datasheet to check if this feature is supported and for specific
* pin connections. Setting the wakeup pin to this level will cause a wakeup from
* system hibernate mode.
*
* LPComparators:
*
* A wakeup is supported by LPComps with programmable polarity.
* Setting the LPComp to this level will cause a wakeup from system hibernate
* mode.
*
* Watchdog Timer:
*
* A wakeup is performed by a WDT interrupt.
*
* Real-time Clock:
*
* A wakeup is performed by the RTC alarm.
*
* For information about hibernate behavior, wakeup sources and their assignment in specific
* devices, refer to the appropriate device TRM.
*
* @param[in] wakeup_source
* The source to be configured as a wakeup source from the system hibernate power mode,
* see @ref cyhal_syspm_hibernate_source_t. The input parameter values can be ORed.
* For example, if you want to enable LPComp0 (active high) and WDT, call this function:
* cyhal_syspm_hibernate(CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH | CYHAL_SYSPM_HIBERNATE_WDT).
*
* @warning Do not call this function with different polarity levels for the same
* wakeup source. For example, do not call a function like this:
* cyhal_syspm_hibernate(CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW | CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH);
*
* @return Returns CY_RSLT_SUCCESS if the processor successfully entered the hibernate mode,
* otherwise error.
*/
cy_rslt_t cyhal_syspm_hibernate(cyhal_syspm_hibernate_source_t wakeup_source);
/** Set the system-wide state of the device. This is used to change the power state
* within the Active power mode. \ref cyhal_syspm_get_system_state can be used to
* get the current state.
* \note Not all devices support different states within the Active power mode. If
* the device does not support changing state, an error will be returned.
*
* @param[in] state System wide state.
*
* @return Returns CY_RSLT_SUCCESS if the processor successfully entered the requested system state,
* otherwise error.
*/
cy_rslt_t cyhal_syspm_set_system_state(cyhal_syspm_system_state_t state);
/** Gets the system-wide state of the device. States can be changed by calling
* \ref cyhal_syspm_set_system_state.
* \note Not all devices support different states within the Active power mode. If
* the device does not support changing state, this will return \ref
* CYHAL_SYSPM_SYSTEM_NORMAL.
* @return Returns the current system-wide power state of the device.
*/
cyhal_syspm_system_state_t cyhal_syspm_get_system_state();
/** Register the specified handler with the power manager to be notified of power
* state changes. This is intended for application wide decisions. Peripherals handle
* their ability to perform power transitions internally. This callback will be called
* before any of the peripheral callbacks for \ref CYHAL_SYSPM_CHECK_READY and
* \ref CYHAL_SYSPM_BEFORE_TRANSITION. This callback will be called after all peripheral
* callback for \ref CYHAL_SYSPM_CHECK_FAIL and \ref CYHAL_SYSPM_AFTER_TRANSITION.
* \note The callback will be executed from a critical section
*
* @param[in] callback_data The data for the callback to register
*/
void cyhal_syspm_register_callback(cyhal_syspm_callback_data_t *callback_data);
/** Removes the registered handler from the power manager so no future notifications are made.
*
* * @param[in] callback_data The data for the callback to unregister
*/
void cyhal_syspm_unregister_callback(cyhal_syspm_callback_data_t *callback_data);
/** Set CPU to sleep mode.
*
* @return Returns CY_RSLT_SUCCESS if the processor successfully entered the sleep mode ,
* otherwise error.
*/
cy_rslt_t cyhal_syspm_sleep(void);
/** Set CPU to deep sleep mode.
*
* @return Returns CY_RSLT_SUCCESS if the processor successfully entered the deep sleep mode,
* otherwise error.
*/
cy_rslt_t cyhal_syspm_deepsleep(void);
/** Lock deep sleep.
*
* This function prevents the CPU from going to deep sleep. The lock is implemented as a counter
* from 0 to USHRT_MAX. Each call to this function increments the counter by 1.
* \ref cyhal_syspm_unlock_deepsleep must be called an equal number of times to fully unlock.
* Deepsleep will only be allowed when the counter is equal to 0.
*/
void cyhal_syspm_lock_deepsleep(void);
/** Unlock deep sleep.
*
* This function decrements the lock counter by 1 and must be called an equal number of times as
* @ref cyhal_syspm_lock_deepsleep is called to fully unlock. Deepsleep will only be allowed
* when the counter is equal to 0.
*/
void cyhal_syspm_unlock_deepsleep(void);
/** Timed deep-sleep without system timer.
*
* Provides a way to deep-sleep for a desired number of milliseconds(ms) with the system timer disabled.
* The system timer is disabled before sleeping and a low power timer is setup to wake
* the device from deep-sleep after the desired number of ms have elapsed.
*
* @note The actual ms in the best case will be 1 ms less than the desired time to
* prevent the device from over-sleeping due to low clock accuracy.
*
* @param[in] obj Pre-Initialized LPTimer object.
* @param[in] desired_ms Desired number of ms to deep-sleep.
* @param[out] actual_ms Actual number of ms that was spent in deep-sleep.
* This value can range from 0 to desired_ms - 1
* depending on how long the device was able to deep-sleep.
* @return The status of the deep-sleep request.
*/
cy_rslt_t cyhal_syspm_tickless_deepsleep(cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms);
/** Timed sleep without system timer.
*
* Provides a way to sleep for a desired number of milliseconds(ms) with the system timer disabled.
* The system timer is disabled before sleeping and a low power timer is setup to wake
* the device from sleep after the desired number of ms have elapsed.
*
* @note The actual ms in the best case will be 1 ms less than the desired time to
* prevent the device from over-sleeping due to low clock accuracy.
*
* @param[in] obj Pre-Initialized LPTimer object.
* @param[in] desired_ms Desired number of ms to sleep.
* @param[out] actual_ms Actual number of ms that was spent in sleep.
* This value can range from 0 to desired_ms - 1
* depending on how long the device was able to sleep.
* @return The status of the sleep request.
*/
cy_rslt_t cyhal_syspm_tickless_sleep(cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms);
#if defined(__cplusplus)
}
#endif
#ifdef CYHAL_SYSPM_IMPL_HEADER
#include CYHAL_SYSPM_IMPL_HEADER
#endif /* CYHAL_SYSTEM_IMPL_HEADER */
/** \} group_hal_system */

View File

@ -0,0 +1,87 @@
/***************************************************************************//**
* \file cyhal_syspm_impl.h
*
* \brief
* Provides a PSoC Specific interface for interacting with the Cypress power
* management and system clock configuration. This interface abstracts out the
* chip specific details. If any chip specific functionality is necessary, or
* performance is critical the low level functions can be used directly.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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.
*******************************************************************************/
#pragma once
/**
* \addtogroup group_hal_psoc6_syspm System Power Management
* \ingroup group_hal_psoc6
* \{
* The PSoC 6 Power Management has the following characteristics:
* \ref CYHAL_SYSPM_SYSTEM_NORMAL equates to the Low Power mode<br>
* \ref CYHAL_SYSPM_SYSTEM_LOW equates to the Ultra Low Power mode
*
* \section group_hal_psoc6_syspm_ulp Switching the System into Ultra Low Power
* Before switching into system Ultra Low Power mode, ensure that the device meets
* the requirements below:
*
* * The core regulator voltage is set to <b>0.9 V (nominal)</b> and the
* following limitations must be meet:
* * The maximum operating frequency for all Clk_HF paths must not exceed
* <b>50* MHz</b>
* * The maximum operating frequency for peripheral and slow clock must not exceed
* <b>25* MHz</b>.
* * The total current consumption must be less than or equal to <b>20* mA</b>
* * Flash write operations are prohibited. Flash is Read-only in this mode.
*
* \note * - Numbers shown are approximate and real limit values may be
* different because they are device specific. You should refer to the device
* datasheet for exact values of maximum frequency and current in system
* ULP mode.
* \} group_hal_psoc6_syspm
*/
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \cond INTERNAL
*/
cy_rslt_t cyhal_syspm_init(void);
void cyhal_syspm_register_peripheral_callback(cyhal_syspm_callback_data_t *callback_data);
void cyhal_syspm_unregister_peripheral_callback(cyhal_syspm_callback_data_t *callback_data);
#define cyhal_syspm_sleep() Cy_SysPm_CpuEnterSleep(CY_SYSPM_WAIT_FOR_INTERRUPT)
#define cyhal_syspm_deepsleep() Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT)
#define cyhal_syspm_get_system_state() (Cy_SysPm_IsSystemUlp() ? CYHAL_SYSPM_SYSTEM_LOW : CYHAL_SYSPM_SYSTEM_NORMAL)
cy_rslt_t cyhal_syspm_tickless_sleep_deepsleep(cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms, bool deep_sleep);
#define cyhal_syspm_tickless_deepsleep(obj, desired_ms, actual_ms) cyhal_syspm_tickless_sleep_deepsleep(obj, desired_ms, actual_ms, true)
#define cyhal_syspm_tickless_sleep(obj, desired_ms, actual_ms) cyhal_syspm_tickless_sleep_deepsleep(obj, desired_ms, actual_ms, false)
/** \endcond */
#if defined(__cplusplus)
}
#endif

View File

@ -26,16 +26,42 @@
*******************************************************************************/
/**
* \addtogroup group_hal_system System (Power Management and System Clock)
* \addtogroup group_hal_system System
* \ingroup group_hal
* \{
* High level interface for interacting with the power management
* and system clock configuration.
* High level interface for interacting with reset and delays.
*
* \section section_system_features Features
* This driver provides three categories of functionality:
* * Retrieval and adjustment of system clock frequencies.
* * Control over low power operating modes.
* * The ability to disable interrupts during a critical section, and to renable them afterwards.
* * Ability to get the last reset reason.
* * Ability to delay for a period of time.
* * The ability to disable interrupts during a critical section.
*
* \section subsection_system_quickstart Quick Start
* * \ref cyhal_system_critical_section_enter and \ref
* cyhal_system_critical_section_exit are used to control the interrupts
* * \ref cyhal_system_delay_ms and \ref cyhal_system_delay_us are delay functions
* used to halt the CPU exectution for a specified period of time
* * \ref cyhal_system_get_reset_reason gets the cause of latest system reset and
* \ref cyhal_system_clear_reset_reason clears the reset cause registers
*
* \section subsection_system_codesnippet Code Snippets
* \subsection subsection_system_snippet1 Snippet 1: Critical Section
* Critical section is a portion in the code where all active interrupts are
* disabled. This is usually provided in places where the code execution must not
* be disturbed by an interrupt. An example is a firmware controlled communication
* protocol where timing of each byte must be maintained and any interrupt might
* cause loss of data. <br>
* \ref cyhal_system_critical_section_enter returns the current state of interrupts
* which denote the active interrupts in the system. This must be passed as argument
* to \ref cyhal_system_critical_section_exit while exiting the critical section.
* \snippet system.c snippet_cyhal_system_critical_section
*
* \subsection subsection_system_snippet2 Snippet 2: Reset reason
* \ref cyhal_system_get_reset_reason must be called at the beginning of the main to
* determine the reason for reset. The return parameters are present in \ref
* cyhal_reset_reason_t.
* \snippet system.c snippet_cyhal_system_reset_reason
*/
#pragma once
@ -44,34 +70,35 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name System Results
*/
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_ERROR (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 0))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_INVALID_CLK_DIVIDER (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 1))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_UNABLE_TO_SET_CLK_FREQ (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 2))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_SRC_CLK_DISABLED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 3))
/** An error occurred in System module */
#define CYHAL_SYSTEM_RSLT_NO_VALID_DIVIDER (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 4))
#define CYHAL_SYSTEM_RSLT_ERROR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SYSTEM , 0))
/**
* \} \}
*/
/** Flags enum of possible system reset causes */
typedef enum
{
CYHAL_SYSTEM_RESET_NONE = 0, /** No cause */
CYHAL_SYSTEM_RESET_WDT = 1 << 0, /** A watchdog timer (WDT) reset has occurred */
CYHAL_SYSTEM_RESET_ACTIVE_FAULT = 1 << 1, /** The fault logging system requested a reset from its Active logic. */
CYHAL_SYSTEM_RESET_DEEPSLEEP_FAULT = 1 << 2, /** The fault logging system requested a reset from its Deep-Sleep logic. */
CYHAL_SYSTEM_RESET_SOFT = 1 << 3, /** The CPU requested a system reset through it's SYSRESETREQ. */
CYHAL_SYSTEM_RESET_HIB_WAKEUP = 1 << 4, /** A reset has occurred due to a a wakeup from hibernate power mode. */
CYHAL_SYSTEM_RESET_WCO_ERR = 1 << 5, /** A reset has occurred due to a watch-crystal clock error */
CYHAL_SYSTEM_RESET_SYS_CLK_ERR = 1 << 6, /** A reset has occurred due to a system clock error */
CYHAL_SYSTEM_RESET_NONE = 0, /**< No cause */
CYHAL_SYSTEM_RESET_WDT = 1 << 0, /**< A watchdog timer (WDT) reset has occurred */
CYHAL_SYSTEM_RESET_ACTIVE_FAULT = 1 << 1, /**< The fault logging system requested a reset from its Active logic. */
CYHAL_SYSTEM_RESET_DEEPSLEEP_FAULT = 1 << 2, /**< The fault logging system requested a reset from its Deep-Sleep logic. */
CYHAL_SYSTEM_RESET_SOFT = 1 << 3, /**< The CPU requested a system reset through it's SYSRESETREQ. */
CYHAL_SYSTEM_RESET_HIB_WAKEUP = 1 << 4, /**< A reset has occurred due to a a wakeup from hibernate power mode. */
CYHAL_SYSTEM_RESET_WCO_ERR = 1 << 5, /**< A reset has occurred due to a watch-crystal clock error */
CYHAL_SYSTEM_RESET_SYS_CLK_ERR = 1 << 6, /**< A reset has occurred due to a system clock error */
} cyhal_reset_reason_t;
/** Enter a critical section
@ -81,55 +108,22 @@ typedef enum
*
* @return Returns the state before entering the critical section. This value must be provided
* to \ref cyhal_system_critical_section_exit() to properly restore the state
*
* See \ref subsection_system_snippet1 for code snippet on critical section
*/
uint32_t cyhal_system_critical_section_enter(void);
/** Exit a critical section
*
* Re-enables the interrupts if they were enabled before
* cyhal_system_critical_section_enter() was called. The argument should be the value
* returned from \ref cyhal_system_critical_section_enter().
* cyhal_system_critical_section_enter() was called. The argument should be the value
* returned from \ref cyhal_system_critical_section_enter().
*
* @param[in] oldState The state of interrupts from cyhal_system_critical_section_enter()
* @param[in] old_state The state of interrupts from cyhal_system_critical_section_enter()
*
* See \ref subsection_system_snippet1 for code snippet on critical section
*/
void cyhal_system_critical_section_exit(uint32_t oldState);
/** Send the device to sleep
*
*
* The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the
* system clock to the core is stopped until a reset or an interrupt occurs.
*
* @return Returns CY_RSLT_SUCCESS if the processor successfully entered and exited sleep,
* otherwise error
*/
cy_rslt_t cyhal_system_sleep(void);
/** Send the device to deep sleep
*
* This processor is setup ready for deep sleep, and sent to sleep using __WFI(). This mode
* has the same sleep features as sleep plus it powers down peripherals and clocks. All state
* is still maintained.
*
* @return Returns CY_RSLT_SUCCESS if the processor successfully entered and exited sleep,
* otherwise error
*/
cy_rslt_t cyhal_system_deepsleep(void);
/** Register the specified handler with the power manager to be notified when the power
* state changes.
*
* @param[in] callback The handler to notify on power transitions
* @return The status of the register_callback request
*/
cy_rslt_t cyhal_system_register_callback(cyhal_system_callback_t *callback);
/** Removes the specified handler from the power manager so no future notification are made.
*
* @param[in] callback The handler to remove from receiving notifications
* @return The status of the unregister_callback request
*/
cy_rslt_t cyhal_system_unregister_callback(cyhal_system_callback_t const *callback);
void cyhal_system_critical_section_exit(uint32_t old_state);
/**
* Requests that the current operation delays for at least the specified length of time.
@ -157,34 +151,11 @@ cy_rslt_t cyhal_system_delay_ms(uint32_t milliseconds);
*/
void cyhal_system_delay_us(uint16_t microseconds);
/** Gets the specified clock's current frequency.
*
* @param[in] clock ID of clock to configure
* @param[out] frequency_hz The frequency the clock is currently running at
* @return The status of the get_frequency request
*/
cy_rslt_t cyhal_system_clock_get_frequency(uint8_t clock, uint32_t *frequency_hz);
/** Sets the specified clock's frequency and enables it.
* This will turn on any additional clocks needed to drive this.
*
* @param[in] clock ID of clock to configure
* @param[in] frequency_hz The frequency to run the clock at
* @return The status of the set_frequency request
*/
cy_rslt_t cyhal_system_clock_set_frequency(uint8_t clock, uint32_t frequency_hz);
/** Divides the clock frequency by the divider
*
* @param[in] clock The clock to configure divider value for
* @param[in] divider The divider value to divide the frequency by
* @return The status of the set_divider request
*/
cy_rslt_t cyhal_system_clock_set_divider(cyhal_system_clock_t clock, cyhal_system_divider_t divider);
/** Gets the cause of the latest reset or resets that occured in the system.
/** Gets the cause of the latest reset or resets that occurred in the system.
*
* @return Returns an enum of flags with the cause of the last reset(s)
*
* Refer \ref subsection_system_snippet2 for code snippet on cyhal_system_get_reset_reason
*/
cyhal_reset_reason_t cyhal_system_get_reset_reason(void);

View File

@ -35,10 +35,16 @@
#define cyhal_system_critical_section_exit(x) Cy_SysLib_ExitCriticalSection(x)
#define cyhal_system_sleep() Cy_SysPm_CpuEnterSleep(CY_SYSPM_WAIT_FOR_INTERRUPT)
#define cyhal_system_deepsleep() Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT)
#define cyhal_system_delay_us(microseconds) Cy_SysLib_DelayUs(microseconds)
/*
* The power management functions below have been migrated to the System Power Management module.
* Please refer to cyhal_syspm.h or System Power Management documentation for further details.
*/
#define cyhal_system_sleep() Cy_SysPm_CpuEnterSleep(CY_SYSPM_WAIT_FOR_INTERRUPT)
#define cyhal_system_deepsleep() Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT)
cy_rslt_t cyhal_system_register_callback(cyhal_system_callback_t *callback);
cy_rslt_t cyhal_system_unregister_callback(cyhal_system_callback_t const *callback);
#endif /* CY_IP_MXS40SRSS */

View File

@ -52,12 +52,18 @@ typedef struct {
/** Contains data about all of the TCPWMs */
extern const cyhal_tcpwm_data_t CYHAL_TCPWM_DATA[CY_IP_MXTCPWM_INSTANCES];
/**
* Free a timer/counter or a PWM object's shared data
*
* @param[in] obj The timer/counter or the PWM resource
*/
void cyhal_tcpwm_free(cyhal_tcpwm_common_t *obj);
/** Initialize a timer/counter or PWM object's callback data.
*
* @param[in] resource The timer/counter or PWM resource
* @param[in,out] callback_data The callback data object belonging to the timer/counter or PWM
* @param[in,out] tcpwm The shared data struct between timer/counter and PWM
*/
void cyhal_tcpwm_init_callback_data(cyhal_resource_inst_t *resource, cyhal_event_callback_data_t *callback_data);
void cyhal_tcpwm_init_data(cyhal_tcpwm_common_t *tcpwm);
/** The TCPWM interrupt handler registration
*
@ -72,10 +78,16 @@ void cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddres
* @param[in] type The type of the timer/counter or PWM
* @param[in] resource The timer/counter or PWM resource
* @param[in] event The timer/counter or PWM event type
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on events, False to turn off
*/
void cyhal_tcpwm_enable_event(TCPWM_Type *type, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intrPriority, bool enable);
void cyhal_tcpwm_enable_event(TCPWM_Type *type, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable);
/** Returns whether power management transition should be allowed.
*
* @return true if no tcpwm is actively blocking power mode transition
*/
bool cyhal_tcpwm_pm_transition_pending(void);
/** \} group_hal_psoc6_tcpwm_common */
/** \endcond */

View File

@ -85,12 +85,33 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name Timer Results
*/
/** Bad argument. eg: null pointer */
#define CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 0))
/** Failed to initialize Timer clock */
#define CYHAL_TIMER_RSLT_ERR_CLOCK_INIT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 1))
/** Failed to initialize Timer */
#define CYHAL_TIMER_RSLT_ERR_INIT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 2))
/** Cannot change the timer frequency when a shared clock divider is in use */
#define CYHAL_TIMER_RSLT_ERR_SHARED_CLOCK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 3))
/**
* \} \}
*/
/*******************************************************************************
* Enumerations
*******************************************************************************/
@ -128,7 +149,7 @@ typedef struct
bool is_compare; //!< Is it in compare (true) or capture (false) mode
uint32_t period; //!< Timer/counter period
uint32_t compare_value; //!< Timer/counter comparison value
uint32_t value; //!< Current value of the timer/counter
uint32_t value; //!< Default value of the timer/counter. \ref cyhal_timer_reset() will also change counter to this value when called.
} cyhal_timer_cfg_t;
/*******************************************************************************
@ -138,16 +159,11 @@ typedef struct
/** Handler for timer events */
typedef void(*cyhal_timer_event_callback_t)(void *callback_arg, cyhal_timer_event_t event);
/** Bad argument. eg: null pointer */
#define CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 0))
/** Failed to initialize Timer clock */
#define CYHAL_TIMER_RSLT_ERR_CLOCK_INIT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 1))
/** Failed to initialize Timer */
#define CYHAL_TIMER_RSLT_ERR_INIT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 2))
/** Cannot change the timer frequency when a shared clock divider is in use */
#define CYHAL_TIMER_RSLT_ERR_SHARED_CLOCK (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TIMER, 3))
/*******************************************************************************
* Defines
*******************************************************************************/
/** Default timer frequency, used when an existing clock divider is not provided to init */
/** Default timer frequency, used when an existing clock divider is not provided to \ref cyhal_timer_init() */
#define CYHAL_TIMER_DEFAULT_FREQ (1000000u)
/*******************************************************************************
@ -157,13 +173,14 @@ typedef void(*cyhal_timer_event_callback_t)(void *callback_arg, cyhal_timer_even
/** Initialize the timer/counter peripheral and configure the pin. <br>
* See \ref subsection_timer_snippet_1.
*
* @param[out] obj The timer/counter object to initialize
* @param[out] obj Pointer to a timer/counter object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] pin optional - The timer/counter compare/capture pin to initialize
* @param[in] clk optional - The shared clock to use, if not provided a new clock will be allocated
* and the timer frequency will be set to CYHAL_TIMER_DEFAULT_FREQ
* @return The status of the init request
*/
cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_divider_t *clk);
cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk);
/** Deinitialize the timer/counter object
*
@ -171,7 +188,8 @@ cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clo
*/
void cyhal_timer_free(cyhal_timer_t *obj);
/** Updates the configuration of the timer/counter object <br>
/** Updates the configuration and counter value of the timer/counter object. <br>
* This function may temporary stop the timer if it is currently running.
* See \ref subsection_timer_snippet_1.
* @param[in] obj The timer/counter object
* @param[in] cfg The configuration of the timer/counter
@ -190,7 +208,11 @@ cy_rslt_t cyhal_timer_configure(cyhal_timer_t *obj, const cyhal_timer_cfg_t *cfg
*/
cy_rslt_t cyhal_timer_set_frequency(cyhal_timer_t *obj, uint32_t hz);
/** Starts the timer/counter with the pre-set configuration <br>
/** Starts the timer/counter with the pre-set configuration from \ref cyhal_timer_configure.
* This does not reset the counter. The count value will start from the value that was
* set by the last operation to modify it. See \ref cyhal_timer_configure, and \ref
* cyhal_timer_reset for how the value can be changed. If none of these functions have
* been called, it will start from 0.<br>
* See \ref subsection_timer_snippet_1.
*
* @param[in] obj The timer/counter object
@ -198,14 +220,22 @@ cy_rslt_t cyhal_timer_set_frequency(cyhal_timer_t *obj, uint32_t hz);
*/
cy_rslt_t cyhal_timer_start(cyhal_timer_t *obj);
/** Stops the timer/counter <br>
* See \ref subsection_timer_snippet_1.
/** Stops the timer/counter. Does not reset counter value. <br>
*
* @param[in] obj The timer/counter object
* @return The status of the stop request
*/
cy_rslt_t cyhal_timer_stop(cyhal_timer_t *obj);
/** Reset the timer/counter value to the default value set from \ref cyhal_timer_configure.
* If \ref cyhal_timer_configure was never called, this will reset timer/counter value to 0.
* This function may temporary stop the timer. <br>
*
* @param[in] obj The timer/counter object
* @return The status of the reset request
*/
cy_rslt_t cyhal_timer_reset(cyhal_timer_t *obj);
/** Reads the current value from the timer/counter <br>
* See \ref subsection_timer_snippet_1.
*
@ -214,7 +244,10 @@ cy_rslt_t cyhal_timer_stop(cyhal_timer_t *obj);
*/
uint32_t cyhal_timer_read(const cyhal_timer_t *obj);
/** The timer/counter callback handler registration <br>
/** Register a timer/counter callback handler<br>
*
* This function will be called when one of the events enabled by \ref cyhal_timer_enable_event occurs.
*
* See \ref subsection_timer_snippet_2.
*
* @param[in] obj The timer/counter object
@ -224,6 +257,9 @@ uint32_t cyhal_timer_read(const cyhal_timer_t *obj);
void cyhal_timer_register_callback(cyhal_timer_t *obj, cyhal_timer_event_callback_t callback, void *callback_arg);
/** Configure timer/counter event enablement <br>
*
* When an enabled event occurs, the function specified by \ref cyhal_timer_register_callback will be called.
*
* See \ref subsection_timer_snippet_2.
*
* @param[in] obj The timer/counter object

View File

@ -47,6 +47,8 @@ __STATIC_INLINE uint32_t cyhal_timer_convert_event(cyhal_timer_event_t event)
return pdl_event;
}
#define cyhal_timer_free(obj) cyhal_tcpwm_free(obj)
__STATIC_INLINE void cyhal_timer_register_callback_internal(cyhal_timer_t *obj, cyhal_timer_event_callback_t callback, void *callback_arg)
{
cyhal_tcpwm_register_callback(&(obj->resource), (cy_israddress) callback, callback_arg);
@ -54,13 +56,13 @@ __STATIC_INLINE void cyhal_timer_register_callback_internal(cyhal_timer_t *obj,
#define cyhal_timer_register_callback(obj, callback, callback_arg) cyhal_timer_register_callback_internal(obj, callback, callback_arg)
__STATIC_INLINE void cyhal_timer_enable_event_internal(cyhal_timer_t *obj, cyhal_timer_event_t event, uint8_t intrPriority, bool enable)
__STATIC_INLINE void cyhal_timer_enable_event_internal(cyhal_timer_t *obj, cyhal_timer_event_t event, uint8_t intr_priority, bool enable)
{
uint32_t converted = cyhal_timer_convert_event(event);
cyhal_tcpwm_enable_event(obj->base, &(obj->resource), converted, intrPriority, enable);
cyhal_tcpwm_enable_event(obj->base, &(obj->resource), converted, intr_priority, enable);
}
#define cyhal_timer_enable_event(obj, event, intrPriority, enable) cyhal_timer_enable_event_internal(obj, event, intrPriority, enable)
#define cyhal_timer_enable_event(obj, event, intr_priority, enable) cyhal_timer_enable_event_internal(obj, event, intr_priority, enable)
#if defined(__cplusplus)
}

View File

@ -29,9 +29,26 @@
* \addtogroup group_hal_trng TRNG (True Random Number Generator)
* \ingroup group_hal
* \{
* High level interface for interacting with the true random number generator (TRNG).
* High level interface to the True Random Number Generator (TRNG).
*
* This block uses dedicated hardware to efficiently generate truly random numbers.
* This block uses dedicated hardware to efficiently generate true random numbers.
*
* \section subsection_trng_features Features
* * Number generated is statistically random
* * Based on physical processes exhibiting random variation
* * Generated sequences of numbers cannot be duplicated by running the process again
* * Uses polynomial generators with fixed and programmable polynomials
*
* \section subsection_trng_quickstart Quick Start
*
* \ref cyhal_trng_init initializes the TRNG and passes a pointer to the **TRNG** block through the **obj** object of type \ref cyhal_trng_t.
*
* See \ref subsection_trng_use_case_1.
*
* \subsection subsection_trng_use_case_1 Simple TRNG number generation example
* The following snippet initializes a TRNG and generates a true random number.
*
* \snippet trng.c snippet_cyhal_trng_simple_init
*/
#pragma once
@ -40,23 +57,36 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name TRNG Results
*/
/** An invalid argument was passed to a function. */
#define CYHAL_TRNG_RSLT_ERR_BAD_ARGUMENT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TRNG, 0))
#define CYHAL_TRNG_RSLT_ERR_BAD_ARGUMENT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TRNG, 0))
/** Hardware error in the crypto block. This will only occur if the Ring oscillators in the TRNG generator are explicitly
* disabled during TRNG generation.
*/
#define CYHAL_TRNG_RSLT_ERR_HW (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TRNG, 1))
#define CYHAL_TRNG_RSLT_ERR_HW \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_TRNG, 1))
/**
* \} \}
*/
/** Initialize the random number generator.
*
* @param[out] obj The random number generator object
* @param[out] obj Pointer to a random number generator object. The caller must
* allocate the memory for this object but the init function will initialize its contents.
* @return The status of the init request
*
* Returns \ref CY_RSLT_SUCCESS if the operation was successful
*/
cy_rslt_t cyhal_trng_init(cyhal_trng_t *obj);
@ -70,6 +100,8 @@ void cyhal_trng_free(cyhal_trng_t *obj);
*
* @param[in] obj The random number generator object
* @return The random number generated
*
* See \ref subsection_trng_use_case_1
*/
uint32_t cyhal_trng_generate(const cyhal_trng_t *obj);

View File

@ -47,9 +47,37 @@
*
* Flow control can be configured via cyhal_uart_set_flow_control()
*
* The data frame size, STOP bits, and parity can be configured via cyhal_uart_cfg_t.
* The data frame size, STOP bits and parity can be configured via \ref cyhal_uart_cfg_t.
* The UART contains dedicated hardware buffers for transmit and receive. Optionally,
* either these can be augmented with a software buffer.
* either of these can be augmented with a software buffer.
*
* \note For applications that require printing messages on a UART terminal using printf(),
* the <a href="https://github.com/cypresssemiconductorco/retarget-io">retarget-io</a> utility library can be used directly.
*
*
* \section subsection_uart_features Features
* * Configurable UART baud rate - \ref cyhal_uart_set_baud
* * Configurable data frame size, STOP bits and parity - \ref cyhal_uart_cfg_t
* * Configurable interrupts and callback on UART events - \ref cyhal_uart_event_t
* \section subsection_uart_quickstart Quick Start
* \ref cyhal_uart_init is used for UART initialization
*
* \section subsection_uart_sample_snippets Code Snippets
*
* \subsection subsection_uart_snippet_1 Snippet 1: Initialization and Configuration
* The following snippet initializes the UART block and assigns the **tx**, **rx** pins and sets the baudrate.
*
* The snippet also shows how to use \ref cyhal_uart_write, \ref cyhal_uart_putc, \ref cyhal_uart_read API.
*
* \snippet uart.c snippet_cyhal_uart_init
*
* \subsection subsection_uart_snippet_2 Snippet 2: Interrupts on UART events
*
* In the following snippet, UART events are handled in a callback function.
* The callback function has to be registered and then the events have to be enabled.
*
* \snippet uart.c snippet_cyhal_uart_event
*
*/
#pragma once
@ -58,25 +86,47 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/****************************************************************
* Defines
*****************************************************************/
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name UART Results
*/
/** The requested resource type is invalid */
#define CYHAL_UART_RSLT_ERR_INVALID_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 0))
#define CYHAL_UART_RSLT_ERR_INVALID_PIN \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 0))
/** Failed to configure power management callback */
#define CYHAL_UART_RSLT_ERR_PM_CALLBACK (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 1))
#define CYHAL_UART_RSLT_ERR_PM_CALLBACK \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 1))
/** The getc call timed out with no received data */
#define CY_RSLT_ERR_CSP_UART_GETC_TIMEOUT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 2))
#define CY_RSLT_ERR_CSP_UART_GETC_TIMEOUT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 2))
/** The actual baud rate is greater than 10% off the requested baud rate */
#define CY_RSLT_WRN_CSP_UART_BAUD_TOLERANCE (CY_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_UART, 3))
#define CY_RSLT_WRN_CSP_UART_BAUD_TOLERANCE \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_UART, 3))
/**
* \} \}
*/
/** The baud rate to set to if no clock is specified in the init function */
#define CYHAL_UART_DEFAULT_BAUD 115200
/** The maximum allowable difference between baud requested and actual baud **/
#define CYHAL_UART_MAX_BAUD_PERCENT_DIFFERENCE 10
/****************************************************************
* Enumerations
*****************************************************************/
/** UART Parity */
typedef enum
{
@ -89,7 +139,7 @@ typedef enum
typedef enum
{
CYHAL_UART_IRQ_NONE = 0, //!< No interrupt
CYHAL_UART_IRQ_TX_TRANSMIT_IN_FIFO = 1 << 1, //!< All tx data from transmit has been moved to uart FIFO
CYHAL_UART_IRQ_TX_TRANSMIT_IN_FIFO = 1 << 1, //!< All tx data from transmit has been moved to UART FIFO
CYHAL_UART_IRQ_TX_DONE = 1 << 2, //!< All tx data has been transmitted
CYHAL_UART_IRQ_TX_ERROR = 1 << 3, //!< An error occurred in tx
CYHAL_UART_IRQ_RX_FULL = 1 << 4, //!< The rx software buffer is full, additional data are store into fifo buffer.
@ -99,43 +149,52 @@ typedef enum
CYHAL_UART_IRQ_TX_EMPTY = 1 << 8, //!< The tx hardware buffer is empty
} cyhal_uart_event_t;
/****************************************************************
* Typedef
*****************************************************************/
/** @brief Initial UART configuration */
typedef struct
{
uint32_t data_bits; //!< The number of start bits
uint32_t stop_bits; //!< The number of stop bits
uint32_t data_bits; //!< The number of data bits (generally 8 or 9)
uint32_t stop_bits; //!< The number of stop bits (generally 0 or 1)
cyhal_uart_parity_t parity; //!< The parity
uint8_t *rx_buffer; //!< The rx software buffer pointer, if NULL, no rx software buffer will be used
uint32_t rx_buffer_size; //!< The number of bytes in the rx software buffer
} cyhal_uart_cfg_t;
/** UART callback function type */
typedef void (*cyhal_uart_event_callback_t)(void *callback_arg, cyhal_uart_event_t event);
/** Initialize the uart peripheral. It sets the default parameters for uart
* peripheral, and configures its specifieds pins.
/*******************************************************************************
* Functions
*******************************************************************************/
/** Initialize the UART peripheral.
*
* @param[out] obj The uart object
* @param[out] obj Pointer to a UART object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] tx The TX pin name, if no TX pin use NC
* @param[in] rx The RX pin name, if no RX pin use NC
* @param[in] clk The clock to use can be shared, if not provided a new clock will be,
* allocated and the default baud rate set
* @param[in] cfg The uart configuration data for data bits, stop bits and parity,
* if not provided, default values of (8, 1, none) will be used
* @param[in] clk The clock to use can be shared. If not provided, a new clock will be
* allocated and the default baud rate will be set
* @param[in] cfg The UART configuration data for data bits, stop bits and parity.
* If not provided, default values of (8, 1, none) will be used
* @return The status of the init request
*/
cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, const cyhal_clock_divider_t *clk, const cyhal_uart_cfg_t *cfg);
cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, const cyhal_clock_t *clk, const cyhal_uart_cfg_t *cfg);
/** Release the uart peripheral, not currently invoked. It requires further
* resource management.
/** Release the UART peripheral.
*
* @param[in,out] obj The uart object
* @param[in,out] obj The UART object
*/
void cyhal_uart_free(cyhal_uart_t *obj);
/** Configure the baud rate
*
* @param[in,out] obj The uart object
* @param[in,out] obj The UART object
* @param[in] baudrate The baud rate to be configured
* @param[out] actualbaud The actual baud rate achieved by the HAL
* Specify NULL if you do not want this information.
@ -145,67 +204,69 @@ cy_rslt_t cyhal_uart_set_baud(cyhal_uart_t *obj, uint32_t baudrate, uint32_t *ac
/** Configure the data bits, stop bits, and parity
*
* @param[in,out] obj The uart object
* @param[in] cfg The uart configuration data for data bits, stop bits and parity.
* @param[in,out] obj The UART object
* @param[in] cfg The UART configuration data for data bits, stop bits and parity.
* rx_buffer and rx_buffer_size are ignored.
* @return The status of the configure request
*/
cy_rslt_t cyhal_uart_configure(cyhal_uart_t *obj, const cyhal_uart_cfg_t *cfg);
/** Get character. This is a blocking call, waiting for a character
/** Get a character. This is a blocking call which waits till a character is received.
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @param[out] value The value read from the serial port
* @param[in] timeout The time in ms to spend attempting to receive from serial port
* timeout = zero is wait forever
* @param[in] timeout The time in ms to spend attempting to receive from serial port.
* Zero is wait forever
* @return The status of the getc request
*/
cy_rslt_t cyhal_uart_getc(cyhal_uart_t *obj, uint8_t *value, uint32_t timeout);
/** Send a character. This is a blocking call, waiting for the peripheral to be available
* for writing
/** Send a character. This is a blocking call which waits till the character is sent out from the UART completley.
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @param[in] value The character to be sent
* @return The status of the putc request
*/
cy_rslt_t cyhal_uart_putc(cyhal_uart_t *obj, uint32_t value);
/** Check the number of bytes avaialable to read from the receive buffers
/** Check the number of bytes available to read from the receive buffers
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return The number of readable bytes
*/
uint32_t cyhal_uart_readable(cyhal_uart_t *obj);
/** Check the number of bytes than can be written to the transmit buffer
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return The number of bytes that can be written
*/
uint32_t cyhal_uart_writable(cyhal_uart_t *obj);
/** Clear the uart peripheral buffers
/** Clear the UART buffers
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return The status of the clear request
*/
cy_rslt_t cyhal_uart_clear(cyhal_uart_t *obj);
/** Configure the uart for the flow control. It sets flow control in the hardware
* if a uart peripheral supports it, otherwise software emulation is used.
/** Configure the UART for the flow control. It sets flow control in the hardware
* if a UART peripheral supports it, otherwise software emulation is used.
*
* @param[in,out] obj The uart object
* @param[in,out] obj The UART object
* @param[in] cts The TX pin name
* @param[in] rts The RX pin name
* @return The status of the init_flow_control request
*/
cy_rslt_t cyhal_uart_set_flow_control(cyhal_uart_t *obj, cyhal_gpio_t cts, cyhal_gpio_t rts);
/** Begin synchronous TX transfer. The used buffer is specified in the uart object,
* tx_buff
/** Begin synchronous TX transfer.
*
* @param[in] obj The uart object
* This will write either `length` bytes or until the write buffer is full, whichever is less,
* then return. The value pointed to by `length` will be updated to reflect the number of bytes
* that were actually written.
*
* @param[in] obj The UART object
* @param[in] tx The transmit buffer
* @param[in,out] tx_length [in] The number of bytes to transmit, [out] number actually transmitted
* @return The status of the tx request
@ -213,48 +274,58 @@ cy_rslt_t cyhal_uart_set_flow_control(cyhal_uart_t *obj, cyhal_gpio_t cts, cyhal
cy_rslt_t cyhal_uart_write(cyhal_uart_t *obj, void *tx, size_t *tx_length);
/** Begin synchronous RX transfer (enable interrupt for data collecting)
* The used buffer is specified in the uart object - rx_buff
*
* @param[in] obj The uart object
* This will read either `length` bytes or the number of bytes that are currently available in the
* receive buffer, whichever is less, then return. The value pointed to by `length` will be updated
* to reflect the number of bytes that were actually read.
*
* @param[in] obj The UART object
* @param[in] rx The receive buffer
* @param[in,out] rx_length [in] The number of bytes to receive, [out] number actually received
* @return The status of the rx request
*/
cy_rslt_t cyhal_uart_read(cyhal_uart_t *obj, void *rx, size_t *rx_length);
/** Begin asynchronous TX transfer. The transmit buffer is a user defined buffer that will be
* sent on the uart. The user must register a callback with cyhal_uart_irq_register_callback. If
* desired, TX callback events can be enabled using cyhal_uart_enable_event with the appropriate
* events.
/** Begin asynchronous TX transfer.
*
* @param[in] obj The uart object
* This will transfer `length` bytes into the buffer pointed to by `rx` in the background. When the
* requested quantity of data has been read, the @ref CYHAL_UART_IRQ_TX_TRANSMIT_IN_FIFO event will
* be raised. The transmit buffer is a user defined buffer that will be sent on the UART. The user
* must register a callback with \ref cyhal_uart_register_callback. If desired, TX callback
* events can be enabled using \ref cyhal_uart_enable_event with the appropriate events.
*
* @param[in] obj The UART object
* @param[in] tx The transmit buffer
* @param[in] length The number of bytes to transmit
* @return The status of the tx_async request
*/
cy_rslt_t cyhal_uart_write_async(cyhal_uart_t *obj, void *tx, size_t length);
/** Begin asynchronous RX transfer. Recevied data is placed in the user specified buffer.
* The user must register a callback with cyhal_uart_irq_register_callback. RX callback events
* can be enabled using cyhal_uart_enable_event with the appropriate events.
/** Begin asynchronous RX transfer.
*
* @param[in] obj The uart object
* This will transfer `length` bytes into the buffer pointed to by `rx` in the background. When the
* requested quantity of data has been read, the @ref CYHAL_UART_IRQ_RX_DONE event will be raised.
* Received data is placed in the user specified buffer. The user must register a callback with
* \ref cyhal_uart_register_callback. RX callback events can be enabled using \ref
* cyhal_uart_enable_event with the appropriate events.
*
* @param[in] obj The UART object
* @param[out] rx The user specified receive buffer
* @param[in] length The number of bytes to receive
* @return The status of the rx_async request
*/
cy_rslt_t cyhal_uart_read_async(cyhal_uart_t *obj, void *rx, size_t length);
/** Attempts to determine if the uart peripheral is already in use for TX
/** Attempts to determine if the UART peripheral is already in use for TX
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return Is the TX channel active
*/
bool cyhal_uart_is_tx_active(cyhal_uart_t *obj);
/** Attempts to determine if the uart peripheral is already in use for RX
/** Attempts to determine if the UART peripheral is already in use for RX
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return Is the RX channel active
*/
bool cyhal_uart_is_rx_active(cyhal_uart_t *obj);
@ -262,7 +333,7 @@ bool cyhal_uart_is_rx_active(cyhal_uart_t *obj);
/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
* flushes the TX hardware buffer if TX FIFO is used
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return The status of the tx_abort request
*/
cy_rslt_t cyhal_uart_write_abort(cyhal_uart_t *obj);
@ -270,27 +341,30 @@ cy_rslt_t cyhal_uart_write_abort(cyhal_uart_t *obj);
/** Abort the ongoing read transaction. It disables the enabled interrupt for RX and
* flushes the RX hardware buffer if RX FIFO is used
*
* @param[in] obj The uart object
* @param[in] obj The UART object
* @return The status of the read_abort request
*/
cy_rslt_t cyhal_uart_read_abort(cyhal_uart_t *obj);
/** The uart callback handler registration
/** Register a uart callback handler
*
* @param[in] obj The uart object
* This function will be called when one of the events enabled by \ref cyhal_uart_enable_event occurs.
*
* @param[in] obj The UART object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
* @param[in] callback_arg Generic argument that will be provided to the callback when called
*/
void cyhal_uart_register_callback(cyhal_uart_t *obj, cyhal_uart_event_callback_t callback, void *callback_arg);
/** Configure uart interrupt. This function is used for word-approach
/** Enable or disable specified UART events.
*
* @param[in] obj The uart object
* @param[in] event The uart event type, this argument supports the bitwise-or of multiple enum flag values
* @param[in] intrPriority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
* When an enabled event occurs, the function specified by \ref cyhal_uart_register_callback will be called.
*
* @param[in] obj The UART object
* @param[in] event The uart event type, this argument supports the bitwise-or of multiple enum flag values
* @param[in] intr_priority The priority for NVIC interrupt events
* @param[in] enable True to turn on interrupts, False to turn off
*/
void cyhal_uart_enable_event(cyhal_uart_t *obj, cyhal_uart_event_t event, uint8_t intrPriority, bool enable);
void cyhal_uart_enable_event(cyhal_uart_t *obj, cyhal_uart_event_t event, uint8_t intr_priority, bool enable);
#if defined(__cplusplus)
}

View File

@ -9,7 +9,7 @@
*
********************************************************************************
* \copyright
* Copyright 2019 Cypress Semiconductor Corporation
* Copyright 2019-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -29,16 +29,62 @@
* \addtogroup group_hal_usb_dev USB Device
* \ingroup group_hal
* \{
* High level interface for interacting with the USB Device interface.
* High level interface for interacting with the USB Device.
*
* This block supports one control endpoint (EP0) and one or more data endpoints
* see the device datasheet for the number of data endpoints supported.
* This block supports one control endpoint (EP0) and one or more data endpoints.
* See the device datasheet for the number of data endpoints supported.
*
* Four transfer types are supported (cyhal_usb_dev_ep_type_t):
* Four transfer types are supported (see \ref cyhal_usb_dev_ep_type_t):
* * Bulk
* * Interrupt
* * Isochronous
* * Control
*
* \section section_usb_dev_features Features
* * Complies with USB specification 2.0
* * Supports full-speed peripheral device operation with a signaling bit rate of 12 Mbps.
* * Configurable D+ AND D- pins using \ref cyhal_gpio_t
* * Configurable Interrupt and Callback assignment on USB events like SOF, Bus Reset, EP0 Setup and EP0 transaction.
* * Configurable USB device address.
* * Configurable USB Endpoints (except for Endpoint 0)
*
* \section section_usb_dev_quickstart Quick Start
* \ref cyhal_usb_dev_init can be used for initialization of USB by providing the USBDP and USBDM pins.
* See \ref subsection_usb_dev_snippet_1 for the initialization code snippet.
*
* \section section_usb_dev_snippets Code snippets
*
* \subsection subsection_usb_dev_snippet_1 Snippet 1: USB Device Initialization
* The following section initializes the USB Device and assigns the USBDM and USBDP pins using
* \ref cyhal_usb_dev_init. The clock parameter <b>clk</b> is optional and need not be provided (NULL),
* to generate and use an available clock resource with a default frequency. The device can be made
* physically visible to the USB Host by using \ref cyhal_usb_dev_connect
*
* \snippet usb_dev.c snippet_cyhal_usb_dev_init
*
*
* \subsection subsection_usb_dev_snippet_2 Snippet 2: Handling USB Event Completion
* USB events (see \ref cyhal_usb_dev_event_t) like Bus Reset, EP0 transaction, EP0 Setup can be mapped to an interrupt and assigned
* a callback function. The callback function needs to be first registered using
* \ref cyhal_usb_dev_register_event_callback. Use different callback functions to handle events individually.
*
* \snippet usb_dev.c snippet_cyhal_usb_dev_event
*
*
* \subsection subsection_usb_dev_snippet_3 Snippet 3: Custom USB Interrupt Handler
* The following section illustrates how to set up the IRQ interrupt handler for USB device. Inside the handler
* \ref cyhal_usb_dev_process_irq has been used to process the interrupts.
*
* \snippet usb_dev.c snippet_cyhal_usb_dev_irq
*
*
* \subsection subsection_usb_dev_snippet_4 Snippet 4: Adding an Endpoint and Handling its Interrupts
* The following section shows how to add endpoint to the USB device and configure the endpoint using
* \ref cyhal_usb_dev_endpoint_add. The interrupts associated with the endpoints are handled by a
* callback function registered using \ref cyhal_usb_dev_register_endpoint_callback.
* The endpoint can also be configured using <a href="https://www.cypress.com/ModusToolboxUSBConfig">ModusToolbox USB Configurator</a>
*
* \snippet usb_dev.c snippet_cyhal_usb_dev_endpoint
*/
#pragma once
@ -47,32 +93,36 @@
#include <stdbool.h>
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cyhal_modules.h"
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_hal_usb_dev_common Common
* \{
*/
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name USB Results
*/
/** The usb error */
#define CYHAL_USB_DEV_RSLT_ERR (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_USB, 0))
#define CYHAL_USB_DEV_RSLT_ERR \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_USB, 0))
/** The driver configuration is not supported by the HAL */
#define CYHAL_USB_DEV_RSLT_ERR_BAD_DRV_CFG (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_USB, 1))
#define CYHAL_USB_DEV_RSLT_ERR_BAD_DRV_CFG \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_USB, 1))
/** The configuration of USB clock failed */
#define CYHAL_USB_DEV_RSLT_ERR_CLK_CFG (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_USB, 2))
/** \} group_hal_usb_dev_common */
#define CYHAL_USB_DEV_RSLT_ERR_CLK_CFG \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_USB, 2))
/**
* \addtogroup group_hal_usb_dev_endpoint Endpoint
* \{
* APIs relating to endpoint management
*/
* \} \}
*/
/**
* \addtogroup group_hal_usb_dev_endpoint Endpoint
* \{
* APIs relating to endpoint management
*/
/** Returns true if endpoint direction is IN */
#define CYHAL_USB_DEV_IS_IN_EP(endpoint) (0U != (0x80U & (uint32_t) (endpoint)))
@ -93,10 +143,11 @@ typedef enum
/** \} group_hal_usb_dev_endpoint */
/**
* \addtogroup group_hal_usb_dev_common Common
* \{
*/
* \addtogroup group_hal_usb_dev_common Common
* \{
*/
/** Service Callback Events */
typedef enum
@ -107,23 +158,20 @@ typedef enum
CYHAL_USB_DEV_EVENT_EP0_OUT, /**< Callback hooked to endpoint 0 OUT packet interrupt */
} cyhal_usb_dev_event_t;
/**
* USB endpoint address (consists from endpoint number and direction)
*
* \ingroup group_hal_usb_dev_endpoint
*/
* USB endpoint address (consists from endpoint number and direction)
*/
typedef uint8_t cyhal_usb_dev_ep_t;
/**
* Callback handler for USB Device interrupt
*/
* Callback handler for USB Device interrupt
*/
typedef void (*cyhal_usb_dev_irq_callback_t)(void);
/**
* Callback handler for the transfer completion event for data endpoints (not applicable for endpoint 0)
*
* \ingroup group_hal_usb_dev_endpoint
*/
* Callback handler for the transfer completion event for data endpoints (not applicable for endpoint 0)
*/
typedef void (* cyhal_usb_dev_endpoint_callback_t)(cyhal_usb_dev_ep_t endpoint);
/** Callback handler for the events for USB Device */
@ -132,54 +180,72 @@ typedef void (*cyhal_usb_dev_event_callback_t)(void);
/** Callback handler for the events for USB Device */
typedef void (*cyhal_usb_dev_sof_callback_t)(uint32_t frame_number);
/**
* Initialize this USBPhy instance.
* Initialize the USB instance.
*
* @param[in,out] obj The usb device object
* @param[out] obj Pointer to a USB object. The caller must allocate the
* memory for this object but the init function will initialize its contents.
* @param[in] dp The D+ pin to initialize
* @param[in] dm The D- pin to initialize
* @param[in] clk The clock to use can be shared, if not provided a new clock will be allocated
*
* @return The status of the initialization request
*/
cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t dm, const cyhal_clock_divider_t *clk);
cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t dm, const cyhal_clock_t *clk);
/**
* Power down this USBPhy instance
* Power down the USB instance
*
* Disable interrupts and stop sending events.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*/
void cyhal_usb_dev_free(cyhal_usb_dev_t *obj);
/**
* Make the USB phy visible to the USB host
* Make the USB device visible to the USB host
*
* Enable either the D+ or D- pull-up so the host can detect
* the presence of this device.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*/
void cyhal_usb_dev_connect(cyhal_usb_dev_t *obj);
/**
* Detach the USB phy
* Detach the USB device
*
* Disable the D+ and D- pull-up and stop responding to
* USB traffic.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*/
void cyhal_usb_dev_disconnect(cyhal_usb_dev_t *obj);
/**
* Suspend the USB phy. This allows the device to enter deepsleep.
* Any data left any USB EP buffers will be lost, when device go into deepsleep.
* Call \ref cyhal_usb_dev_resume to resume USB from deepsleep.
*
* @param[in] obj The usb device object
*/
void cyhal_usb_dev_suspend(cyhal_usb_dev_t *obj);
/**
* Resume the USB phy from a suspended state. \see cyhal_usb_dev_suspend
*
* @param[in] obj The usb device object
*/
void cyhal_usb_dev_resume(cyhal_usb_dev_t *obj);
/**
* Set this device to the configured state
*
* Enable added endpoints if they are not enabled
* already.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*/
void cyhal_usb_dev_set_configured(cyhal_usb_dev_t *obj);
@ -190,14 +256,14 @@ typedef void (*cyhal_usb_dev_sof_callback_t)(uint32_t frame_number);
* is leaving the configured state. The USBPhy can disable all
* endpoints other than endpoint 0.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*/
void cyhal_usb_dev_set_unconfigured(cyhal_usb_dev_t *obj);
/**
* Configure start of frame interrupt enablement.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] enable True to turn on interrupt and start calling sof callback on every frame,
* False to turn off interrupt and stop calling sof callback.
*/
@ -206,7 +272,7 @@ typedef void (*cyhal_usb_dev_sof_callback_t)(uint32_t frame_number);
/**
* Set the USBPhy's address
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] address This device's USB address
*/
void cyhal_usb_dev_set_address(cyhal_usb_dev_t *obj, uint8_t address);
@ -214,16 +280,16 @@ typedef void (*cyhal_usb_dev_sof_callback_t)(uint32_t frame_number);
/** \} group_hal_usb_dev_common */
/**
* \addtogroup group_hal_usb_dev_ep0 EP0
* \{
* APIs relating specifically to management of endpoint zero
*/
* \addtogroup group_hal_usb_dev_ep0 EP0
* \{
* APIs relating specifically to management of endpoint zero
*/
/**
* Get wMaxPacketSize of endpoint 0.
* The endpoint 0 has dedicated buffer.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*
* @return The size allocated for endpoint 0
*/
@ -232,7 +298,7 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
/**
* Read the contents of the SETUP packet
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] buffer Buffer to fill with data
* @param[in] size Size of buffer passed in
*/
@ -241,7 +307,7 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
/**
* Start receiving a packet of up to wMaxPacketSize on endpoint 0
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] buffer Buffer to fill with the data read
* @param[in] size Size of buffer
*/
@ -250,7 +316,7 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
/**
* Read the contents of a received packet
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*
* @return Actual number of bytes that was read
*/
@ -259,7 +325,7 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
/**
* Write a packet on endpoint 0
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] buffer Buffer fill with data to send
* @param[in] size Size of data to send
*
@ -271,7 +337,7 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
* Protocol stall on endpoint 0.
* Stall all IN and OUT packets on endpoint 0 until a SETUP packet is received.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*
* @note The stall is cleared automatically when a setup packet is received
*/
@ -280,19 +346,19 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
/** \} group_hal_usb_dev_ep0 */
/**
* \addtogroup group_hal_usb_dev_endpoint
* \{
*/
* \addtogroup group_hal_usb_dev_endpoint
* \{
*/
/**
* Configure an endpoint.
*
* @param[in,out] obj The usb device object
* @param[in] alloc True to allocates buffer for the endpoint, false to skip allocation
* @param[in] enable True to enable endpoint operation, false to skip enablement
* @param[in] endpoint Endpoint to configure and enable
* @param[in] maxPacket The maximum packet size that can be sent or received
* @param[in] type The type of endpoint (does not care when enable parameter is false)
* @param[in,out] obj The USB device object
* @param[in] alloc True to allocates buffer for the endpoint, false to skip allocation
* @param[in] enable True to enable endpoint operation, false to skip enablement
* @param[in] endpoint Endpoint to configure and enable
* @param[in] max_packet The maximum packet size that can be sent or received
* @param[in] type The type of endpoint (does not care when enable parameter is false)
*
* @return The status of the endpoint add request
*
@ -302,12 +368,12 @@ uint32_t cyhal_usb_dev_ep0_get_max_packet(cyhal_usb_dev_t *obj);
* - After endpoint was enabled it must be removed with cyhal_usb_dev_endpoint_remove
* and then enabled again.
*/
cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enable ,cyhal_usb_dev_ep_t endpoint, uint32_t maxPacket, cyhal_usb_dev_ep_type_t type);
cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enable ,cyhal_usb_dev_ep_t endpoint, uint32_t max_packet, cyhal_usb_dev_ep_type_t type);
/**
* Disable an endpoint
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to disable
*
* @return The status of the endpoint remove request
@ -320,7 +386,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
* Set the HALT feature for this endpoint so that all further
* communication is aborted.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to stall
*
* @return The status of the endpoint stall request
@ -333,7 +399,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
* Clear the HALT feature on this endpoint so communication can
* resume.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to stall
*
* @return The status of the endpoint unstall request
@ -343,7 +409,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
/**
* Return the endpoint stall state
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to check stall state
*
* @return True if endpoint stalled, false otherwise.
@ -353,7 +419,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
/**
* Start a read on the given endpoint
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to start the read on
* @param[in] data Buffer to fill with data
* @param[in] size Size of the read buffer. This must be at least
@ -366,18 +432,18 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
/**
* Finish a read on the given endpoint
*
* @param[in,out] obj The usb device object
* @param[in] endpoint Endpoint to check
* @param[out] actSize Actual number of bytes that was read
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to check
* @param[out] act_size Actual number of bytes that was read
*
* @return The status of a finish read
*/
cy_rslt_t cyhal_usb_dev_endpoint_read_result(cyhal_usb_dev_t *obj, cyhal_usb_dev_ep_t endpoint, uint32_t *actSize);
cy_rslt_t cyhal_usb_dev_endpoint_read_result(cyhal_usb_dev_t *obj, cyhal_usb_dev_ep_t endpoint, uint32_t *act_size);
/**
* Start a write on the given endpoint
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to write to
* @param[in] data Buffer to write
* @param[in] size Size of data to write
@ -389,7 +455,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
/**
* Abort the current transfer if it has not yet been sent
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to abort the transfer on. It is implementation defined
* if this function has an effect on receive endpoints.
*
@ -406,13 +472,16 @@ cy_rslt_t cyhal_usb_dev_endpoint_add(cyhal_usb_dev_t *obj, bool alloc, bool enab
/** \} group_hal_usb_dev_endpoint */
/**
* \addtogroup group_hal_usb_dev_common Common
* \{
*/
* \addtogroup group_hal_usb_dev_common Common
* \{
*/
/** The USB Device callback handler registration
/** Register a USB Device callback handler
*
* @param[in,out] obj The usb device object
* This function will be called when the USB interrupt is triggered. This interrupt can be
* enabled or disabled using \ref cyhal_usb_dev_irq_enable.
*
* @param[in,out] obj The USB device object
* @param[in] callback The event handler function which will be invoked when the event fires
*
* @return The status of the register_irq_callback request
@ -422,6 +491,8 @@ cy_rslt_t cyhal_usb_dev_register_irq_callback(cyhal_usb_dev_t *obj, cyhal_usb_de
/**
* Configure USB Device event enablement.
*
* When the interrupt is enabled and triggered, the function specified by \ref cyhal_usb_dev_register_irq_callback will be called.
*
* @param[in,out] obj The usb device object
* @param[in] enable True to turn on events, False to turn off
*/
@ -430,14 +501,14 @@ void cyhal_usb_dev_irq_enable(cyhal_usb_dev_t *obj, bool enable);
/**
* Default USB Device interrupt handler.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
*/
void cyhal_usb_dev_process_irq(cyhal_usb_dev_t *obj);
/**
* The USB Device endpoint complete callback handler registration
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] endpoint Endpoint to registers handler
* @param[in] callback The callback handler which will be invoked when the endpoint comp
*
@ -448,8 +519,8 @@ void cyhal_usb_dev_register_endpoint_callback(cyhal_usb_dev_t *obj, cyhal_usb_de
/**
* The USB Device event complete callback handler registration. The events are defined by x type.
*
* @param[in,out] obj The usb device object
* @param[in] event The event that triggers the callback, see /ref cyhal_usb_dev_event_t
* @param[in,out] obj The USB device object
* @param[in] event The event that triggers the callback, see \ref cyhal_usb_dev_event_t
* @param[in] callback The callback handler which will be invoked when the interrupt fires
*/
void cyhal_usb_dev_register_event_callback(cyhal_usb_dev_t *obj, cyhal_usb_dev_event_t event, cyhal_usb_dev_event_callback_t callback);
@ -457,7 +528,7 @@ void cyhal_usb_dev_register_event_callback(cyhal_usb_dev_t *obj, cyhal_usb_dev_e
/**
* The USB Device start of frame (SOF) complete callback handler registration.
*
* @param[in,out] obj The usb device object
* @param[in,out] obj The USB device object
* @param[in] callback The callback handler which will be invoked when the interrupt fires
*/
void cyhal_usb_dev_register_sof_callback( cyhal_usb_dev_t *obj, cyhal_usb_dev_sof_callback_t callback);
@ -472,4 +543,4 @@ void cyhal_usb_dev_register_sof_callback( cyhal_usb_dev_t *obj, cyhal_usb_dev_so
#include CYHAL_USB_DEV_IMPL_HEADER
#endif /* CYHAL_USB_DEV_IMPL_HEADER */
/** \} group_hal_usb_dev */
/** \} group_hal_usb_dev */

View File

@ -39,20 +39,18 @@
extern "C" {
#endif
#define CYHAL_IRQN_OFFSET (16U) /**< Offset for implementation-defined ISR type numbers (IRQ0 = 16) */
#define CYHAL_GET_CURRENT_IRQN() ((IRQn_Type) (__get_IPSR() - CYHAL_IRQN_OFFSET)) /**< Macro to get the IRQn of the current ISR */
#define CYHAL_IRQN_OFFSET 16 /**< Offset for implementation-defined ISR type numbers (IRQ0 = 16) */
#define CYHAL_GET_CURRENT_IRQN() ((IRQn_Type) (__get_IPSR() - CYHAL_IRQN_OFFSET)) /**< Macro to get the IRQn of the current ISR */
#define CYHAL_MAP_COLUMNS (2U) /**< Number of columns in the flag map */
/**
* \addtogroup group_hal_psoc6_pin_package
* \{
*/
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0xFFFFUL)) /**< Macro to extract the pin number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((uint32_t)(pin >> 16) & 0xFFUL)) /**< Macro to extract the port number */
/** Looks up the resource block that connects to the specified pins from the provided resource pin mapping table.
* This is a convinience utility for cyhal_utils_get_resource() if the mappings is an array of known size.
* This is a convenience utility for cyhal_utils_get_resource() if the mappings is an array of known size.
*
* @param[in] pin The pin to lookup the hardware block for
* @param[in] mappings The mappings of pin to hardware block
@ -63,7 +61,7 @@ extern "C" {
/** Converts the provided gpio pin to a resource instance object
*
* @param[in] pin The pin to get a resource object for
* @return The equivilant resource instance object for the provided pin.
* @return The equivalent resource instance object for the provided pin.
*/
static inline cyhal_resource_inst_t cyhal_utils_get_gpio_resource(cyhal_gpio_t pin)
{
@ -113,7 +111,8 @@ static inline uint32_t cyhal_divider_value(uint32_t frequency, uint32_t frac_bit
return ((Cy_SysClk_ClkPeriGetFrequency() * (1 << frac_bits)) + (frequency / 2)) / frequency - 1;
}
/** Determine if two resources are the same
/** Determine if two resources are the same. If more than two instances need to be
* compared, it is better to call \ref cyhal_utils_resources_equal_all().
*
* @param[in] resource1 First resource to compare
* @param[in] resource2 Second resource to compare
@ -121,6 +120,102 @@ static inline uint32_t cyhal_divider_value(uint32_t frequency, uint32_t frac_bit
*/
bool cyhal_utils_resources_equal(const cyhal_resource_inst_t *resource1, const cyhal_resource_inst_t *resource2);
/** Determine if the set of resources are the same. This expects at least two resource
* instances to be provided. NOTE: If only two instances are provided it is better
* to use \ref cyhal_utils_resources_equal().
*
* @param[in] count The number of resources being provided to compare
* @param[in] ... Variable List of const cyhal_resource_inst_t* items to compare
* @return Boolean indicating whether resource instances are the same
*/
bool cyhal_utils_resources_equal_all(uint32_t count, ...);
/** Converts a set of flags from one representation to a equivalent set of flags
* in another representation.
* For example usage see cyhal_syspm.c or cyhal_sdhc.c
*
* @param[in] map Map of the flags from one representation to the other.
* The keys represent the source flags and the values
* represent the equivalent flags to be converted to.
* @param[in] from_column Column index of the flags to convert from in the map.
* @param[in] to_column Column index of the equivalent flags to be converted to in the map.
* @param[in] count Count of the total flags in the list.
* @param[in] source_flags Source flags to be converted.
* @return Converted flags.
*/
uint32_t cyhal_utils_convert_flags(
const uint32_t map[][CYHAL_MAP_COLUMNS],
uint8_t from_index,
uint8_t to_index,
uint32_t count,
uint32_t source_flags);
/** Converts a hal pm mode to a pdl mode
*
* @param[in] mode hal power management callback mode.
* @return Equivalent pdl syspm mode.
*/
cy_en_syspm_callback_mode_t cyhal_utils_convert_haltopdl_pm_mode(cyhal_syspm_callback_mode_t mode);
/** Converts a pdl pm mode to a hal mode
*
* @param[in] mode pdl syspm power management callback mode.
* @return Equivalent hal pm callback mode.
*/
cyhal_syspm_callback_mode_t cyhal_utils_convert_pdltohal_pm_mode(cy_en_syspm_callback_mode_t mode);
/**
* Utility method to check if the clock is using the new data format (true) or the old
* format (false).
* @param[out] clock The clock instance to check which format it is using.
* @return Indication of whether the provided clock is using the new format (true) or old (false)
*/
static inline bool cyhal_utils_is_new_clock_format(const cyhal_clock_t *clock)
{
return (((cyhal_clock_block_t)clock->div_type == clock->block) && (clock->div_num == clock->channel));
}
/** Gets the peripheral divider information from a provided clock instance. The clock can be using either
* the new or the old format for clocks.
*
* @param[in] clock The clock to get peripheral divider information from
* @param[out] div_type The divider type the clock instance represents
* @param[out] div_num The divider number the clock instance represents
*/
void cyhal_utils_get_peri_clock_details(const cyhal_clock_t *clock, cy_en_divider_types_t *div_type, uint32_t *div_num);
/**
* Allocates a clock that can drive the specified instance.
*
* @param[out] clock The clock object to initialize
* @param[in] clocked_item The destination that the allocated clock must be able to drive
* @param[in] div The divider width that is required. This is ignored if the block is hard-wired to an HFCLK output
* @param[in] accept_larger If no dividers of the specified width are available, can a wider divider be substituted.
*/
cy_rslt_t cyhal_utils_allocate_clock(cyhal_clock_t *clock, const cyhal_resource_inst_t *clocked_item, cyhal_clock_divider_types_t div, bool accept_larger);
/**
* Calculates clock tolerance in the specified units given a desired and actual frequency
*
* @param[in] type tolerance type
* @param[in] desired_hz desired clock frequency in hertz
* @param[in] actual_hz actual clock frequency in hertz
* @return the computed tolerance
*/
int32_t cyhal_utils_calculate_tolerance(cyhal_clock_tolerance_unit_t type, uint32_t desired_hz, uint32_t actual_hz);
/**
* Attempts to set the clock to the specified frequency. This is similar to cyhal_clock_set_frequency, but it will also make
* an attempt to set the frequency for HFCLK outputs, which are not supported by the public API due to their limited range
* of supported dividers (1, 2, 4, 8)
*
* @param[in] clock The clock instance to set the frequency for.
* @param[in] hz The frequency, in hertz, to set the clock to.
* @param[in] tolerance The allowed tolerance from the desired hz that is acceptable, use NULL if no
* tolerance check is required.
*/
cy_rslt_t cyhal_utils_set_clock_frequency(cyhal_clock_t* clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance);
#if defined(__cplusplus)
}
#endif

View File

@ -2,14 +2,14 @@
* \file cyhal_wdt.h
*
* \brief
* Provides a high level interface for interacting with the Cypress Watchdog Timer.
* Provides a high level interface for interacting with the Watchdog Timer.
* This interface abstracts out the chip specific details. If any chip specific
* functionality is necessary, or performance is critical the low level functions
* can be used directly.
*
********************************************************************************
* \copyright
* Copyright 2019 Cypress Semiconductor Corporation
* Copyright 2019-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,33 +30,28 @@
* \ingroup group_hal
* \{
* High level interface to the Watchdog Timer (WDT).
*
* cyhal_wdt_init() initializes the WDT and passes a pointer to the WDT block through obj.
* The timeout_ms parameter takes in the timeout in milliseconds.
* It can be used for recovering from a CPU or firmware failure.
The watchdog timer is initialized with a timeout interval. Once the WDT is started,
if cyhal_wdt_kick() must be called at least once within the timeout interval. In case
the firmware fails to do so, it is considered to be a CPU crash or firmware failure and the device
will be reset.
*
* The WDT can be used for recovering from a CPU or firmware failure.
* The WDT is initialized with a timeout interval. Once the WDT is started, \ref
* cyhal_wdt_kick must be called at least once within each timeout interval to
* reset the count. In case the firmware fails to do so, it is considered to be a
* CPU crash or firmware failure and the device will be reset.
*
*\section subsection_wdt_features Features
* WDT supports Device Reset generation if not serviced within the configured timeout interval.
*
* WDT resets the device if the WDT is not "kicked" using \ref cyhal_wdt_kick
* within the configured timeout interval.
*
* \section subsection_wdt_quickstart Quick Start
*
* \ref cyhal_wdt_init() can be used for initialization by providing the WDT object (obj) and the timeout parameter
* (timeout period in ms).
* The timeout parameter can have a minimum value of 1ms. The maximum value of the timeout
* parameter can be obtained using the cyhal_wdt_get_max_timeout_ms().
* \ref cyhal_wdt_init() is used to initialize the WDT by providing the WDT object
* (**obj**) and the timeout (**timeout_ms**) value in milliseconds.
* The timeout parameter can have a minimum value of 1ms. The maximum value of the
* timeout parameter can be obtained using the cyhal_wdt_get_max_timeout_ms().
*
* \section subsection_wdt_snippet Code Snippet
*
* \section subsection_wdt_sample_use_case Sample use case
*
* \subsection subsection_wdt_use_case Use Case: Initialization and reset functionality
* The following snippet initializes the WDT and depicts the reset functionality of WDT in case of CPU or
* firmware failure.
* \subsection subsection_wdt_snippet1 Snippet 1: Initialize the WDT and reset the
* WDT periodically The following snippet initializes the WDT and illustrates how
* to reset the WDT within the timeout interval.
* \snippet wdt.c snippet_cyhal_wdt_init_and_reset
*/
@ -69,17 +64,28 @@
extern "C" {
#endif
/** \addtogroup group_hal_results
* \{ *//**
* \{ @name WDT Results
*/
/** WDT timeout out of range */
#define CY_RSLT_WDT_INVALID_TIMEOUT (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_WDT, 0))
#define CY_RSLT_WDT_INVALID_TIMEOUT \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_WDT, 0))
/** WDT already initialized */
#define CY_RSLT_WDT_ALREADY_INITIALIZED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_WDT, 1))
#define CY_RSLT_WDT_ALREADY_INITIALIZED \
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_WDT, 1))
/**
* \} \}
*/
/** Initialize and start the WDT
*
* Initialize or re-initialize the WDT.
* \attention The specified timeout must be at least 1ms and at most the WDT's maximum timeout (see cyhal_wdt_get_max_timeout_ms()).
* \note The specified timeout must be at least 1ms and at most the WDT's maximum timeout (see cyhal_wdt_get_max_timeout_ms()).
*
* @param[out] obj The WDT object
* @param[out] obj Pointer to a WDT object. The caller must allocate the memory
* for this object but the init function will initialize its contents.
* @param[in] timeout_ms The time in milliseconds before the WDT times out (1ms - max) (see cyhal_wdt_get_max_timeout_ms())
* @return The status of the init request
*
@ -87,12 +93,11 @@ extern "C" {
*/
cy_rslt_t cyhal_wdt_init(cyhal_wdt_t *obj, uint32_t timeout_ms);
/** Deinitialize the WDT
/** Free the WDT
*
* Powers down the WDT.
* Powers down the WDT. Releases object (obj).
* After calling this function no other WDT functions should be called except
* cyhal_wdt_init(). Calling any function other than init after freeing is
* undefined.
* cyhal_wdt_init().
*
* @param[inout] obj The WDT object
*
@ -100,29 +105,25 @@ cy_rslt_t cyhal_wdt_init(cyhal_wdt_t *obj, uint32_t timeout_ms);
void cyhal_wdt_free(cyhal_wdt_t *obj);
/** Refresh the WDT
/** Resets the WDT
*
* Refreshes the WDT. This function should be called periodically to prevent the WDT from timing out.
* In the event of a timeout, the WDT resets the system.
* This function should be called periodically to prevent the WDT from timing out and resetting the device.
*
* See \ref subsection_wdt_snippet1
*
* @param[inout] obj The WDT object
*
* See \ref subsection_wdt_use_case
*/
void cyhal_wdt_kick(cyhal_wdt_t *obj);
/** Start the WDT
*
* Enables the WDT.
/** Start (enable) the WDT
*
* @param[inout] obj The WDT object
* @return The status of the start request
*/
void cyhal_wdt_start(cyhal_wdt_t *obj);
/** Stop the WDT
*
* Disables the WDT.
/** Stop (disable) the WDT
*
* @param[inout] obj The WDT object
* @return The status of the stop request
@ -138,9 +139,7 @@ void cyhal_wdt_stop(cyhal_wdt_t *obj);
*/
uint32_t cyhal_wdt_get_timeout_ms(cyhal_wdt_t *obj);
/** Gets the maximum WDT timeout
*
* Gets the maximum timeout for the WDT.
/** Gets the maximum WDT timeout in milliseconds
*
* @return The maximum timeout for the WDT
*/

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 104-M-CSP-BLE package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_104_m_csp_ble PSoC6_01 104-M-CSP-BLE
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 104-M-CSP-BLE package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 104-M-CSP-BLE package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -136,9 +142,10 @@ typedef cyhal_gpio_psoc6_01_104_m_csp_ble_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 104-M-CSP-BLE-USB package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_104_m_csp_ble_usb PSoC6_01 104-M-CSP-BLE-USB
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 104-M-CSP-BLE-USB package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 104-M-CSP-BLE-USB package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -138,9 +144,10 @@ typedef cyhal_gpio_psoc6_01_104_m_csp_ble_usb_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 116-BGA-BLE package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_116_bga_ble PSoC6_01 116-BGA-BLE
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 116-BGA-BLE package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 116-BGA-BLE package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -144,9 +150,10 @@ typedef cyhal_gpio_psoc6_01_116_bga_ble_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 116-BGA-USB package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_116_bga_usb PSoC6_01 116-BGA-USB
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 116-BGA-USB package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 116-BGA-USB package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -144,9 +150,10 @@ typedef cyhal_gpio_psoc6_01_116_bga_usb_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 124-BGA package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_124_bga PSoC6_01 124-BGA
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 124-BGA package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 124-BGA package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -172,9 +178,10 @@ typedef cyhal_gpio_psoc6_01_124_bga_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 124-BGA-SIP package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_124_bga_sip PSoC6_01 124-BGA-SIP
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 124-BGA-SIP package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 124-BGA-SIP package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -153,9 +159,10 @@ typedef cyhal_gpio_psoc6_01_124_bga_sip_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 43-SMT package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_43_smt PSoC6_01 43-SMT
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 43-SMT package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 43-SMT package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -98,9 +104,10 @@ typedef cyhal_gpio_psoc6_01_43_smt_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 68-QFN-BLE package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_68_qfn_ble PSoC6_01 68-QFN-BLE
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 68-QFN-BLE package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 68-QFN-BLE package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -104,9 +110,10 @@ typedef cyhal_gpio_psoc6_01_68_qfn_ble_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_01 device GPIO HAL header for 80-WLCSP package
*
* \note
* Generator version: 1.5.7254.21430
* Generator version: 1.5.7361.18849
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_01_80_wlcsp PSoC6_01 80-WLCSP
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_01 80-WLCSP package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 80-WLCSP package for the PSoC6_01 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -130,9 +136,10 @@ typedef cyhal_gpio_psoc6_01_80_wlcsp_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_02 device GPIO HAL header for 100-WLCSP package
*
* \note
* Generator version: 1.5.7254.21305
* Generator version: 1.5.7361.18814
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_02_100_wlcsp PSoC6_02 100-WLCSP
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_02 100-WLCSP package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 100-WLCSP package for the PSoC6_02 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -152,9 +158,10 @@ typedef cyhal_gpio_psoc6_02_100_wlcsp_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_02 device GPIO HAL header for 124-BGA package
*
* \note
* Generator version: 1.5.7254.21305
* Generator version: 1.5.7361.18814
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_02_124_bga PSoC6_02 124-BGA
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_02 124-BGA package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 124-BGA package for the PSoC6_02 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -172,9 +178,10 @@ typedef cyhal_gpio_psoc6_02_124_bga_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_02 device GPIO HAL header for 128-TQFP package
*
* \note
* Generator version: 1.5.7254.21305
* Generator version: 1.5.7361.18814
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_02_128_tqfp PSoC6_02 128-TQFP
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_02 128-TQFP package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 128-TQFP package for the PSoC6_02 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -174,9 +180,10 @@ typedef cyhal_gpio_psoc6_02_128_tqfp_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_02 device GPIO HAL header for 68-QFN package
*
* \note
* Generator version: 1.5.7254.21305
* Generator version: 1.5.7361.18814
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_02_68_qfn PSoC6_02 68-QFN
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_02 68-QFN package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 68-QFN package for the PSoC6_02 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -122,9 +128,10 @@ typedef cyhal_gpio_psoc6_02_68_qfn_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_03 device GPIO HAL header for 100-TQFP package
*
* \note
* Generator version: 1.5.7254.21421
* Generator version: 1.5.7361.18858
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_03_100_tqfp PSoC6_03 100-TQFP
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_03 100-TQFP package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 100-TQFP package for the PSoC6_03 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -133,9 +139,10 @@ typedef cyhal_gpio_psoc6_03_100_tqfp_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_03 device GPIO HAL header for 49-WLCSP package
*
* \note
* Generator version: 1.5.7254.21421
* Generator version: 1.5.7361.18858
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_03_49_wlcsp PSoC6_03 49-WLCSP
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_03 49-WLCSP package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Definitions for all of the pins that are bonded out on in the 50-WLCSP package for the PSoC6_03 series. */
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 49-WLCSP package for the PSoC6_03 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -100,9 +106,10 @@ typedef cyhal_gpio_psoc6_03_49_wlcsp_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -5,7 +5,7 @@
* PSoC6_03 device GPIO HAL header for 68-QFN package
*
* \note
* Generator version: 1.5.7254.21421
* Generator version: 1.5.7361.18858
*
********************************************************************************
* \copyright
@ -34,6 +34,7 @@
* \addtogroup group_hal_psoc6_pin_package_psoc6_03_68_qfn PSoC6_03 68-QFN
* \ingroup group_hal_psoc6_pin_package
* \{
* Pin definitions and connections specific to the PSoC6_03 68-QFN package.
*/
#if defined(__cplusplus)
@ -41,11 +42,16 @@ extern "C" {
#endif /* __cplusplus */
/** Gets a pin definition from the provided port and pin numbers */
#define CYHAL_GET_GPIO(port, pin) (((port) << 16) + (pin))
#define CYHAL_GET_GPIO(port, pin) (((port) << 3) + (pin))
/** Macro that, given a gpio, will extract the pin number */
#define CYHAL_GET_PIN(pin) ((uint8_t)(pin & 0x07))
/** Macro that, given a gpio, will extract the port number */
#define CYHAL_GET_PORT(pin) ((uint8_t)((pin >> 3) & 0x1F))
/** Definitions for all of the pins that are bonded out on in the 68-QFN package for the PSoC6_03 series. */
typedef enum {
NC = (int)0xFFFFFFFF, //!< No Connect/Invalid Pin
NC = 0xFF, //!< No Connect/Invalid Pin
P0_0 = CYHAL_GET_GPIO(CYHAL_PORT_0, 0), //!< Port 0 Pin 0
P0_1 = CYHAL_GET_GPIO(CYHAL_PORT_0, 1), //!< Port 0 Pin 1
@ -122,9 +128,10 @@ typedef cyhal_gpio_psoc6_03_68_qfn_t cyhal_gpio_t;
/** Represents an association between a pin and a resource */
typedef struct
{
cyhal_gpio_t pin; //!< The GPIO pin
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_mapping_cfg_t cfg; //!< The DriveMode and HSIOM configuration value
const cyhal_resource_inst_t *inst; //!< The associated resource instance
cyhal_gpio_t pin; //!< The GPIO pin
uint8_t drive_mode; //!< The DriveMode configuration value
en_hsiom_sel_t hsiom; //!< The HSIOM configuration value
} cyhal_resource_pin_mapping_t;
/* Pin connections */

View File

@ -31,7 +31,6 @@
#include "cyhal_analog_common.h"
#include "cyhal_gpio.h"
#include "cyhal_hwmgr.h"
#include "cyhal_interconnect.h"
#include "cyhal_utils.h"
#if defined(CY_IP_MXS40PASS_SAR_INSTANCES)
@ -177,7 +176,7 @@ static uint8_t cyhal_adc_get_pin_addr(cyhal_gpio_t gpio, bool is_vplus)
/*******************************************************************************
* ADC HAL Functions
*******************************************************************************/
cy_rslt_t cyhal_adc_init(cyhal_adc_t *obj, cyhal_gpio_t pin, const cyhal_clock_divider_t *clk)
cy_rslt_t cyhal_adc_init(cyhal_adc_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk)
{
const uint32_t DESIRED_DIVIDER = 8000000u; // 8 MHz. Required range is 1.7 - 18
@ -185,18 +184,12 @@ cy_rslt_t cyhal_adc_init(cyhal_adc_t *obj, cyhal_gpio_t pin, const cyhal_clock_d
cy_rslt_t result = CY_RSLT_SUCCESS;
if (CYHAL_NC_PIN_VALUE == pin)
result = CYHAL_ADC_RSLT_BAD_ARGUMENT;
if (CY_RSLT_SUCCESS == result)
{
memset(obj, 0, sizeof(cyhal_adc_t));
obj->base = NULL;
obj->channel_used = 0;
obj->clock.div_num = CYHAL_RSC_INVALID;
obj->resource.type = CYHAL_RSC_INVALID;
obj->dedicated_clock = false;
}
memset(obj, 0, sizeof(cyhal_adc_t));
obj->base = NULL;
obj->channel_used = 0;
obj->clock.div_num = CYHAL_RSC_INVALID;
obj->resource.type = CYHAL_RSC_INVALID;
obj->dedicated_clock = false;
const cyhal_resource_pin_mapping_t *map = CY_UTILS_GET_RESOURCE(pin, cyhal_pin_map_pass_sarmux_pads);
if (NULL == map)
@ -295,50 +288,45 @@ cy_rslt_t cyhal_adc_channel_init(cyhal_adc_channel_t *obj, cyhal_adc_t* adc, cyh
{
CY_ASSERT(obj != NULL);
CY_ASSERT(adc != NULL);
if (CYHAL_NC_PIN_VALUE == pin)
return CYHAL_ADC_RSLT_BAD_ARGUMENT;
// Check for invalid pin or pin belonging to a different SAR
const cyhal_resource_pin_mapping_t *map = CY_UTILS_GET_RESOURCE(pin, cyhal_pin_map_pass_sarmux_pads);
if (NULL == map || map->inst->block_num != adc->resource.block_num)
if (NULL == map || !cyhal_utils_resources_equal(map->inst, &(adc->resource)))
return CYHAL_ADC_RSLT_BAD_ARGUMENT;
memset(obj, 0, sizeof(cyhal_adc_channel_t));
cy_rslt_t result;
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(pin);
if (CY_RSLT_SUCCESS != (result = cyhal_hwmgr_reserve(&pinRsc)))
return result;
obj->pin = pin;
cy_rslt_t result = cyhal_utils_reserve_and_connect(pin, map);
if (CY_RSLT_SUCCESS == result)
result = cyhal_connect_pin(map);
// Find the first available channel
uint8_t chosen_channel = __CLZ(__RBIT(~adc->channel_used));
if(chosen_channel >= CY_SAR_MAX_NUM_CHANNELS) // No channels available
result = CYHAL_ADC_RSLT_NO_CHANNELS;
else
{
// Don't set the ADC until here so that free knows whether we have allocated
// the channel on the parent ADC instance (and therefore doesn't try to free it if
// something fails further up)
obj->adc = adc;
obj->channel_idx = chosen_channel;
obj->adc->channel_used |= 1U << chosen_channel;
obj->pin = pin;
// Find the first available channel
uint8_t chosen_channel = __CLZ(__RBIT(~adc->channel_used));
if (chosen_channel >= CY_SAR_MAX_NUM_CHANNELS) // No channels available
result = CYHAL_ADC_RSLT_NO_CHANNELS;
else
{
// Don't set the ADC until here so that free knows whether we have allocated
// the channel on the parent ADC instance (and therefore doesn't try to free it if
// something fails further up)
obj->adc = adc;
obj->channel_idx = chosen_channel;
obj->adc->channel_used |= 1U << chosen_channel;
}
// The current version only supports single-ended channels, so always set the vplus switch
uint32_t fw_ctrl = cyhal_adc_get_fw_switch_control(pin, true);
uint32_t mux_ctrl = cyhal_adc_get_mux_switch_control(pin);
Cy_SAR_SetAnalogSwitch(obj->adc->base, CY_SAR_MUX_SWITCH0, fw_ctrl, CY_SAR_SWITCH_CLOSE);
Cy_SAR_SetSwitchSarSeqCtrl(obj->adc->base, mux_ctrl, CY_SAR_SWITCH_SEQ_CTRL_ENABLE);
uint8_t pin_select = cyhal_adc_get_pin_addr(pin, true);
uint32_t channel_config = CYHAL_SAR_DEFAULT_CH_CONFIG | pin_select;
obj->adc->base->CHAN_CONFIG[chosen_channel] = channel_config;
}
// The current version only supports single-ended channels, so always set the vplus switch
uint32_t fw_ctrl = cyhal_adc_get_fw_switch_control(pin, true);
uint32_t mux_ctrl = cyhal_adc_get_mux_switch_control(pin);
Cy_SAR_SetAnalogSwitch(obj->adc->base, CY_SAR_MUX_SWITCH0, fw_ctrl, CY_SAR_SWITCH_CLOSE);
Cy_SAR_SetSwitchSarSeqCtrl(obj->adc->base, mux_ctrl, CY_SAR_SWITCH_SEQ_CTRL_ENABLE);
uint8_t pin_select = cyhal_adc_get_pin_addr(pin, true);
uint32_t channel_config = CYHAL_SAR_DEFAULT_CH_CONFIG | pin_select;
obj->adc->base->CHAN_CONFIG[chosen_channel] = channel_config;
return result;
}

View File

@ -34,7 +34,7 @@ extern "C"
static uint16_t cyhal_analog_ref_count = 0;
void cyhal_analog_init()
void cyhal_analog_init(void)
{
if(cyhal_analog_ref_count == 0)
{
@ -45,7 +45,7 @@ void cyhal_analog_init()
++cyhal_analog_ref_count;
}
void cyhal_analog_free()
void cyhal_analog_free(void)
{
CY_ASSERT(cyhal_analog_ref_count > 0);
--cyhal_analog_ref_count;

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,6 @@
#include "cyhal_dac.h"
#include "cyhal_gpio.h"
#include "cyhal_hwmgr.h"
#include "cyhal_interconnect.h"
#include "cyhal_utils.h"
#include "cy_pdl.h"
@ -64,7 +63,7 @@ static const cy_stc_ctdac_config_t CYHAL_CTDAC_DEFAULT_CONFIG =
.deglitchMode = CY_CTDAC_DEGLITCHMODE_UNBUFFERED,
.outputMode = CY_CTDAC_OUTPUT_VALUE,
.outputBuffer = CY_CTDAC_OUTPUT_UNBUFFERED,
.deepSleep = CY_CTDAC_DEEPSLEEP_DISABLE,
.deepSleep = CY_CTDAC_DEEPSLEEP_ENABLE,
.deglitchCycles = 0,
.value = 0,
.nextValue = 0,
@ -86,15 +85,9 @@ cy_rslt_t cyhal_dac_init(cyhal_dac_t *obj, cyhal_gpio_t pin)
cy_rslt_t result = CY_RSLT_SUCCESS;
if (CYHAL_NC_PIN_VALUE == pin)
result = CYHAL_DAC_RSLT_BAD_ARGUMENT;
if (CY_RSLT_SUCCESS == result)
{
obj->resource.type = CYHAL_RSC_INVALID;
obj->base = NULL;
obj->pin = CYHAL_NC_PIN_VALUE;
}
obj->resource.type = CYHAL_RSC_INVALID;
obj->base = NULL;
obj->pin = CYHAL_NC_PIN_VALUE;
const cyhal_resource_pin_mapping_t *map = CY_UTILS_GET_RESOURCE(pin, cyhal_pin_map_pass_ctdac_voutsw);
if (NULL == map)
@ -113,15 +106,11 @@ cy_rslt_t cyhal_dac_init(cyhal_dac_t *obj, cyhal_gpio_t pin)
obj->base = cyhal_ctdac_base[dac_inst.block_num];
// We don't need any special configuration of the pin, so just reserve it
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(pin);
if (CY_RSLT_SUCCESS == (result = cyhal_hwmgr_reserve(&pinRsc)))
result = cyhal_utils_reserve_and_connect(pin, map);
if (CY_RSLT_SUCCESS == result)
obj->pin = pin;
}
if (CY_RSLT_SUCCESS == result)
result = cyhal_connect_pin(map);
if (CY_RSLT_SUCCESS == result)
{
result = (cy_rslt_t)Cy_CTDAC_Init(obj->base, &CYHAL_CTDAC_DEFAULT_CONFIG);

View File

@ -0,0 +1,293 @@
/***************************************************************************/ /**
* \file cyhal_deprecated.c
*
* \brief
* Provides access to items that are device specific and no longer part of the
* common HAL API.
*
********************************************************************************
* \copyright
* Copyright 2018-2019 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_deprecated.h"
#include "cyhal_hwmgr.h"
#include "cyhal_clock.h"
#define HZ_PER_MHZ 1000000
uint32_t get_src_freq(cy_en_clkpath_in_sources_t source)
{
/* get the frequency of the source, i.e., the path mux input */
switch(source)
{
case CY_SYSCLK_CLKPATH_IN_IMO: /* IMO frequency is fixed at 8 MHz */
return CY_SYSCLK_IMO_FREQ;
case CY_SYSCLK_CLKPATH_IN_ILO: /* ILO, WCO and PILO frequencies are nominally 32.768 kHz */
case CY_SYSCLK_CLKPATH_IN_WCO:
case CY_SYSCLK_CLKPATH_IN_PILO:
return CY_SYSCLK_ILO_FREQ;
default:
return 0;
}
}
static uint32_t get_clkpath_freq(cy_en_clkhf_in_sources_t path, uint32_t freq, uint8_t *fll_pll_used)
{
*fll_pll_used = 0xff;
if (path == CY_SYSCLK_CLKHF_IN_CLKPATH0)
{
cy_stc_fll_manual_config_t fll_config;
Cy_SysClk_FllGetConfiguration(&fll_config);
if (fll_config.outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
{
freq *= fll_config.fllMult;
freq /= fll_config.refDiv;
freq /= (fll_config.enableOutputDiv ? 2U : 1U);
*fll_pll_used = 0;
}
}
else if((uint32_t)path <= CY_SRSS_NUM_PLL)
{
cy_stc_pll_manual_config_t pll_config;
Cy_SysClk_PllGetConfiguration(path, &pll_config);
if (pll_config.outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
{
freq *= pll_config.feedbackDiv;
freq /= pll_config.referenceDiv;
freq /= pll_config.outputDiv;
*fll_pll_used = (uint8_t)path;
}
}
return freq;
}
static cy_rslt_t try_set_hf_divider(uint8_t hf_clock, uint32_t input_freq, uint32_t target_freq)
{
bool divider_found = false;
cy_en_clkhf_dividers_t divider;
if (target_freq == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_NO_DIVIDE;
}
else if (target_freq * 2 == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_DIVIDE_BY_2;
}
else if (target_freq * 4 == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_DIVIDE_BY_4;
}
else if (target_freq * 8 == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_DIVIDE_BY_8;
}
if (divider_found)
{
Cy_SysClk_ClkHfSetDivider(hf_clock, divider);
Cy_SysClk_ClkHfEnable(hf_clock);
return CY_RSLT_SUCCESS;
}
else
{
return CYHAL_SYSTEM_RSLT_NO_VALID_DIVIDER;
}
}
static cy_rslt_t try_set_fll(uint8_t hf_clock, uint32_t target_freq)
{
Cy_SysClk_FllDisable();
Cy_SysClk_ClkHfSetSource(hf_clock, CY_SYSCLK_CLKHF_IN_CLKPATH0);
Cy_SysClk_ClkPathSetSource(0, CY_SYSCLK_CLKPATH_IN_IMO);
cy_rslt_t rslt = Cy_SysClk_FllConfigure(CY_SYSCLK_IMO_FREQ, target_freq, CY_SYSCLK_FLLPLL_OUTPUT_AUTO);
if (rslt == CY_RSLT_SUCCESS)
{
// Wait up to 1 seconds for FLL to lock
rslt = Cy_SysClk_FllEnable(1000000);
}
if (rslt == CY_RSLT_SUCCESS)
{
Cy_SysClk_ClkHfSetDivider(hf_clock, CY_SYSCLK_CLKHF_NO_DIVIDE);
SystemCoreClockUpdate();
}
return rslt;
}
static cy_rslt_t try_set_pll(uint8_t hf_clock, uint8_t pll, uint32_t target_freq)
{
Cy_SysClk_PllDisable(pll);
Cy_SysClk_ClkHfSetSource(hf_clock, (cy_en_clkhf_in_sources_t)(pll));
cy_stc_pll_config_t cfg;
cfg.inputFreq = CY_SYSCLK_IMO_FREQ;
cfg.outputFreq = target_freq;
cfg.lfMode = false;
cfg.outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO;
Cy_SysClk_ClkPathSetSource(pll, CY_SYSCLK_CLKPATH_IN_IMO);
cy_rslt_t rslt = Cy_SysClk_PllConfigure(pll, &cfg);
if (rslt == CY_RSLT_SUCCESS)
{
// Wait up to 1 seconds for PLL to lock
rslt = Cy_SysClk_PllEnable(pll, 1000000);
}
if (rslt == CY_RSLT_SUCCESS)
{
Cy_SysClk_ClkHfSetDivider(hf_clock, CY_SYSCLK_CLKHF_NO_DIVIDE);
SystemCoreClockUpdate();
}
return rslt;
}
cy_rslt_t cyhal_system_clock_get_frequency(uint8_t hf_clock, uint32_t *frequency_hz)
{
*frequency_hz = Cy_SysClk_ClkHfGetFrequency(hf_clock);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_system_clock_set_frequency(uint8_t hf_clock, uint32_t frequency_hz)
{
cy_en_clkhf_in_sources_t path = Cy_SysClk_ClkHfGetSource((uint32_t)hf_clock);
cy_en_clkpath_in_sources_t source = Cy_SysClk_ClkPathGetSource((uint32_t)path);
uint32_t src_freq = get_src_freq(source);
if (src_freq == 0)
{
return CYHAL_SYSTEM_RSLT_SRC_CLK_DISABLED;
}
uint8_t fll_pll_used;
uint32_t clkpath_freq = get_clkpath_freq(path, src_freq, &fll_pll_used);
cy_rslt_t rslt = try_set_hf_divider(hf_clock, clkpath_freq, frequency_hz);
if (rslt == CY_RSLT_SUCCESS)
{
SystemCoreClockUpdate();
return rslt;
}
bool enabled = Cy_SysClk_ClkHfIsEnabled(hf_clock);
if (enabled && fll_pll_used == 0)
{
return try_set_fll(hf_clock, frequency_hz);
}
else if (enabled && fll_pll_used <= SRSS_NUM_PLL)
{
return try_set_pll(hf_clock, fll_pll_used, frequency_hz);
}
else
{
// Cannot get the correct frequency. Try to allocate an FLL or PLL
cyhal_clock_t inst;
rslt = cyhal_clock_allocate(&inst, CYHAL_CLOCK_BLOCK_PATHMUX);
if (rslt == CY_RSLT_SUCCESS)
{
if (inst.channel < SRSS_NUM_PLL)
{
rslt = try_set_fll(hf_clock, frequency_hz);
}
else if (inst.channel <= SRSS_NUM_PLL)
{
rslt = try_set_pll(hf_clock, inst.channel, frequency_hz);
}
else
{
// No FLL or PLL available.
rslt = CYHAL_SYSTEM_RSLT_UNABLE_TO_SET_CLK_FREQ;
}
if (!enabled && rslt == CY_RSLT_SUCCESS)
{
rslt = Cy_SysClk_ClkHfEnable(hf_clock);
}
if (rslt != CY_RSLT_SUCCESS)
{
cyhal_clock_free(&inst);
}
}
}
return rslt;
}
cy_rslt_t cyhal_system_clock_set_divider(cyhal_system_clock_t clock, cyhal_system_divider_t divider)
{
if (divider < 1 || divider > 0x100)
{
return CYHAL_SYSTEM_RSLT_INVALID_CLK_DIVIDER;
}
switch(clock)
{
case CYHAL_SYSTEM_CLOCK_CM4:
{
Cy_SysClk_ClkFastSetDivider(divider - 1);
break;
}
case CYHAL_SYSTEM_CLOCK_CM0:
{
Cy_SysClk_ClkSlowSetDivider(divider - 1);
break;
}
case CYHAL_SYSTEM_CLOCK_PERI:
{
Cy_SysClk_ClkPeriSetDivider(divider - 1);
break;
}
default:
{
return CYHAL_SYSTEM_RSLT_INVALID_CLK_DIVIDER;
}
}
SystemCoreClockUpdate();
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_hwmgr_allocate_clock(cyhal_clock_divider_t* obj, cyhal_clock_divider_types_t div, bool accept_larger)
{
static uint8_t counts[] = { PERI_DIV_8_NR, PERI_DIV_16_NR, PERI_DIV_16_5_NR, PERI_DIV_24_5_NR };
cyhal_clock_divider_types_t max_div_type = (accept_larger) ? (cyhal_clock_divider_types_t)(sizeof(counts) - 1) : div;
cy_rslt_t rslt = CYHAL_HWMGR_RSLT_ERR_NONE_FREE;
for(cyhal_clock_divider_types_t current_div = div; rslt != CY_RSLT_SUCCESS && current_div <= max_div_type; ++current_div)
{
uint8_t block = (uint8_t)current_div;
uint8_t count = counts[block];
for (int i = 0; rslt != CY_RSLT_SUCCESS && i < count; i++)
{
cyhal_resource_inst_t res = { CYHAL_RSC_CLOCK, block, i };
bool reserved = (CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(&res));
if (reserved)
{
obj->div_type = current_div;
obj->div_num = i;
rslt = CY_RSLT_SUCCESS;
}
}
}
return rslt;
}
void cyhal_hwmgr_free_clock(cyhal_clock_divider_t* obj)
{
cyhal_resource_inst_t res = { CYHAL_RSC_CLOCK, obj->div_type, obj->div_num };
cyhal_hwmgr_free(&res);
}

View File

@ -9,7 +9,7 @@
*
********************************************************************************
* \copyright
* Copyright 2018-2019 Cypress Semiconductor Corporation
* Copyright 2018-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -27,9 +27,8 @@
#include "cyhal_dma_dmac.h"
#include "cyhal_dma_dw.h"
#include "cyhal_hwmgr.h"
#include "cyhal_system.h"
#include "cyhal_utils.h"
#include "cyhal_hwmgr.h"
/**
* \addtogroup group_hal_dma DMA (Direct Memory Access)
@ -179,20 +178,20 @@ void cyhal_dma_register_callback(cyhal_dma_t *obj, cyhal_dma_event_callback_t ca
cyhal_system_critical_section_exit(saved_intr_status);
}
void cyhal_dma_enable_event(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intrPriority, bool enable)
void cyhal_dma_enable_event(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable)
{
CY_ASSERT(NULL != obj);
#ifdef CY_IP_M4CPUSS_DMAC
if(obj->resource.type == CYHAL_RSC_DMA)
{
cyhal_dma_enable_event_dmac(obj, event, intrPriority, enable);
cyhal_dma_enable_event_dmac(obj, event, intr_priority, enable);
}
#endif
#ifdef CY_IP_M4CPUSS_DMA
if(obj->resource.type == CYHAL_RSC_DW)
{
cyhal_dma_enable_event_dw(obj, event, intrPriority, enable);
cyhal_dma_enable_event_dw(obj, event, intr_priority, enable);
}
#endif
}

View File

@ -6,7 +6,7 @@
*
********************************************************************************
* \copyright
* Copyright 2018-2019 Cypress Semiconductor Corporation
* Copyright 2018-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,7 +26,7 @@
#include "cyhal_dma_dmac.h"
#include "cyhal_dma_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_system.h"
#include "cyhal_syspm.h"
#include "cyhal_utils.h"
#include "cyhal_triggers.h"
@ -71,6 +71,48 @@ static const cy_stc_dmac_channel_config_t default_channel_config_dmac =
.bufferable = false,
};
static bool cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
static cyhal_syspm_callback_data_t cyhal_dma_dmac_pm_callback_args = {
.callback = &cyhal_dma_dmac_pm_callback,
.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
.next = NULL,
.args = NULL,
.ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION,
};
static bool cyhal_dma_dmac_pm_transition_pending = false;
static bool cyhal_dma_dmac_has_enabled(void)
{
for (uint8_t i = 0; i < CPUSS_DMAC_CH_NR; i++)
if (cyhal_dmac_config_structs[i])
return true;
return false;
}
static bool cyhal_dma_dmac_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
bool block_transition = false;
switch(mode)
{
case CYHAL_SYSPM_CHECK_READY:
for (uint8_t i = 0; i < CPUSS_DMAC_CH_NR && !block_transition; i++)
{
block_transition |= (cyhal_dmac_config_structs[i] != NULL) && cyhal_dma_is_busy_dmac(cyhal_dmac_config_structs[i]);
}
cyhal_dma_dmac_pm_transition_pending = !block_transition;
break;
case CYHAL_SYSPM_CHECK_FAIL:
case CYHAL_SYSPM_AFTER_TRANSITION:
cyhal_dma_dmac_pm_transition_pending = false;
break;
default:
break;
}
return cyhal_dma_dmac_pm_transition_pending;
}
/** Sets the dmac configuration struct */
static inline void cyhal_dma_set_dmac_obj(cyhal_dma_t *obj)
{
@ -96,10 +138,7 @@ static inline uint8_t cyhal_dma_get_dmac_block_from_irqn(IRQn_Type irqn)
/* Since there is only one dmac block this function always returns 0. diff
* is calculated here only to verify that this was called from a valid
* IRQn. */
CY_UNUSED uint8_t diff = irqn - cpuss_interrupts_dmac_0_IRQn;
CY_ASSERT(diff < CPUSS_DMAC_CH_NR);
CY_ASSERT(irqn >= cpuss_interrupts_dmac_0_IRQn && irqn < cpuss_interrupts_dmac_0_IRQn + (IRQn_Type)CPUSS_DMAC_CH_NR);
return 0;
}
@ -123,6 +162,7 @@ static inline IRQn_Type cyhal_dma_get_dmac_irqn(cyhal_dma_t *obj)
/** Gets the dmac base pointer from block number */
static inline DMAC_Type* cyhal_dma_get_dmac_base(uint8_t block_num)
{
CY_UNUSED_PARAMETER(block_num);
return DMAC;
}
@ -205,6 +245,11 @@ cy_rslt_t cyhal_dma_init_dmac(cyhal_dma_t *obj, uint8_t priority)
if(!CY_DMAC_IS_PRIORITY_VALID(priority))
return CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY;
if (cyhal_dma_dmac_pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t rslt = cyhal_hwmgr_allocate(CYHAL_RSC_DMA, &obj->resource);
if(rslt != CY_RSLT_SUCCESS)
return rslt;
@ -219,6 +264,11 @@ cy_rslt_t cyhal_dma_init_dmac(cyhal_dma_t *obj, uint8_t priority)
obj->callback_data.callback_arg = NULL;
obj->irq_cause = 0;
if (!cyhal_dma_dmac_has_enabled())
{
cyhal_syspm_register_peripheral_callback(&cyhal_dma_dmac_pm_callback_args);
}
cyhal_dma_set_dmac_obj(obj);
return CY_RSLT_SUCCESS;
@ -232,6 +282,13 @@ void cyhal_dma_free_dmac(cyhal_dma_t *obj)
NVIC_DisableIRQ(cyhal_dma_get_dmac_irqn(obj));
cyhal_dma_free_dmac_obj(obj);
if (!cyhal_dma_dmac_has_enabled())
{
cyhal_syspm_unregister_peripheral_callback(&cyhal_dma_dmac_pm_callback_args);
cyhal_dma_dmac_pm_transition_pending = false;
}
cyhal_hwmgr_free(&obj->resource);
}
@ -330,6 +387,9 @@ cy_rslt_t cyhal_dma_start_transfer_dmac(cyhal_dma_t *obj)
if(cyhal_dma_is_busy_dmac(obj))
return CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED;
if (cyhal_dma_dmac_pm_transition_pending)
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint32_t trigline = cyhal_dma_get_dmac_trigger_line(obj->resource.block_num, obj->resource.channel_num);
cy_en_trigmux_status_t trig_status = Cy_TrigMux_SwTrigger(trigline, CY_TRIGGER_TWO_CYCLES);
@ -341,14 +401,14 @@ cy_rslt_t cyhal_dma_start_transfer_dmac(cyhal_dma_t *obj)
return CY_RSLT_SUCCESS;
}
void cyhal_dma_enable_event_dmac(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intrPriority, bool enable)
void cyhal_dma_enable_event_dmac(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable)
{
if(enable)
obj->irq_cause |= event;
else
obj->irq_cause &= ~event;
NVIC_SetPriority(cyhal_dma_get_dmac_irqn(obj), intrPriority);
NVIC_SetPriority(cyhal_dma_get_dmac_irqn(obj), intr_priority);
}
bool cyhal_dma_is_busy_dmac(cyhal_dma_t *obj)

View File

@ -6,7 +6,7 @@
*
********************************************************************************
* \copyright
* Copyright 2018-2019 Cypress Semiconductor Corporation
* Copyright 2018-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,7 +26,7 @@
#include "cyhal_dma_dw.h"
#include "cyhal_dma_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_system.h"
#include "cyhal_syspm.h"
#include "cyhal_utils.h"
#include "cyhal_triggers.h"
@ -77,6 +77,48 @@ static const cy_stc_dma_channel_config_t default_channel_config_dw =
.bufferable = false,
};
static bool cyhal_dma_dw_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
static cyhal_syspm_callback_data_t cyhal_dma_dw_pm_callback_args = {
.callback = &cyhal_dma_dw_pm_callback,
.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
.next = NULL,
.args = NULL,
.ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION,
};
static bool cyhal_dma_dw_pm_transition_pending = false;
static bool cyhal_dma_dw_has_enabled(void)
{
for (uint8_t i = 0; i < NUM_DW_CHANNELS; i++)
if (cyhal_dw_config_structs[i])
return true;
return false;
}
static bool cyhal_dma_dw_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
bool block_transition = false;
switch(mode)
{
case CYHAL_SYSPM_CHECK_READY:
for (uint8_t i = 0; i < NUM_DW_CHANNELS && !block_transition; i++)
{
block_transition |= (cyhal_dw_config_structs[i] != NULL) && cyhal_dma_is_busy_dw(cyhal_dw_config_structs[i]);
}
cyhal_dma_dw_pm_transition_pending = !block_transition;
break;
case CYHAL_SYSPM_CHECK_FAIL:
case CYHAL_SYSPM_AFTER_TRANSITION:
cyhal_dma_dw_pm_transition_pending = false;
break;
default:
break;
}
return cyhal_dma_dw_pm_transition_pending;
}
/** Sets the dw configuration struct */
static inline void cyhal_dma_set_dw_obj(cyhal_dma_t *obj)
{
@ -99,44 +141,32 @@ static inline cyhal_dma_t* cyhal_dma_get_dw_obj(uint8_t block, uint8_t channel)
/** This should never be called from a non-dma IRQn */
static inline uint8_t cyhal_dma_get_dw_block_from_irqn(IRQn_Type irqn)
{
uint8_t diff = irqn - cpuss_interrupts_dw0_0_IRQn;
#if defined(CPUSS_DW0_CH_NR) && !defined(CPUSS_DW1_CH_NR)
CY_ASSERT(diff < CPUSS_DW0_CH_NR);
if(diff < CPUSS_DW0_CH_NR)
#ifdef CPUSS_DW0_CH_NR
if (irqn >= cpuss_interrupts_dw0_0_IRQn && irqn < cpuss_interrupts_dw0_0_IRQn + (IRQn_Type)CPUSS_DW0_CH_NR)
return 0;
#elif defined(CPUSS_DW0_CH_NR) && defined(CPUSS_DW1_CH_NR)
CY_ASSERT(diff < CPUSS_DW0_CH_NR + CPUSS_DW1_CH_NR);
if(diff < CPUSS_DW0_CH_NR)
return 0;
if(diff < CPUSS_DW0_CH_NR + CPUSS_DW1_CH_NR)
#endif
#ifdef CPUSS_DW1_CH_NR
if (irqn >= cpuss_interrupts_dw1_0_IRQn && irqn < cpuss_interrupts_dw1_0_IRQn + (IRQn_Type)CPUSS_DW1_CH_NR)
return 1;
#endif
// Should never reach here. Just silencing compiler warnings.
CY_ASSERT(false);
return 255;
return 0xFF;
}
/** Gets the dw channel number from irq number */
/** This should never be called from a non-dma IRQn */
static inline uint8_t cyhal_dma_get_dw_channel_from_irqn(IRQn_Type irqn)
{
uint8_t diff = irqn - cpuss_interrupts_dw0_0_IRQn;
#if defined(CPUSS_DW0_CH_NR) && !defined(CPUSS_DW1_CH_NR)
CY_ASSERT(diff < CPUSS_DW0_CH_NR);
if(diff < CPUSS_DW0_CH_NR)
return diff;
#elif defined(CPUSS_DW0_CH_NR) && defined(CPUSS_DW1_CH_NR)
CY_ASSERT(diff < CPUSS_DW0_CH_NR + CPUSS_DW1_CH_NR);
if(diff < CPUSS_DW0_CH_NR)
return diff;
else
return diff - CPUSS_DW0_CH_NR;
#ifdef CPUSS_DW0_CH_NR
if (irqn >= cpuss_interrupts_dw0_0_IRQn && irqn < cpuss_interrupts_dw0_0_IRQn + (IRQn_Type)CPUSS_DW0_CH_NR)
return irqn - cpuss_interrupts_dw0_0_IRQn;
#endif
#ifdef CPUSS_DW1_CH_NR
if (irqn >= cpuss_interrupts_dw1_0_IRQn && irqn < cpuss_interrupts_dw1_0_IRQn + (IRQn_Type)CPUSS_DW1_CH_NR)
return irqn - cpuss_interrupts_dw1_0_IRQn;
#endif
CY_ASSERT(false);
return 0xFF;
}
/** Gets the irqn corresponding to a particular cyhal_dma_t config struct */
@ -246,6 +276,11 @@ cy_rslt_t cyhal_dma_init_dw(cyhal_dma_t *obj, uint8_t priority)
obj->callback_data.callback_arg = NULL;
obj->irq_cause = 0;
if (!cyhal_dma_dw_has_enabled())
{
cyhal_syspm_register_peripheral_callback(&cyhal_dma_dw_pm_callback_args);
}
cyhal_dma_set_dw_obj(obj);
return CY_RSLT_SUCCESS;
@ -259,6 +294,13 @@ void cyhal_dma_free_dw(cyhal_dma_t *obj)
NVIC_DisableIRQ(cyhal_dma_get_dw_irqn(obj));
cyhal_dma_free_dw_obj(obj);
if (!cyhal_dma_dw_has_enabled())
{
cyhal_syspm_unregister_peripheral_callback(&cyhal_dma_dw_pm_callback_args);
cyhal_dma_dw_pm_transition_pending = false;
}
cyhal_hwmgr_free(&obj->resource);
}
@ -356,6 +398,9 @@ cy_rslt_t cyhal_dma_start_transfer_dw(cyhal_dma_t *obj)
if(cyhal_dma_is_busy_dw(obj))
return CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED;
if (cyhal_dma_dw_pm_transition_pending)
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint32_t trigline = cyhal_dma_get_dw_trigger_line(obj->resource.block_num, obj->resource.channel_num);
cy_en_trigmux_status_t trig_status = Cy_TrigMux_SwTrigger(trigline, CY_TRIGGER_TWO_CYCLES);
@ -367,14 +412,14 @@ cy_rslt_t cyhal_dma_start_transfer_dw(cyhal_dma_t *obj)
return CY_RSLT_SUCCESS;
}
void cyhal_dma_enable_event_dw(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intrPriority, bool enable)
void cyhal_dma_enable_event_dw(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable)
{
if(enable)
obj->irq_cause |= event;
else
obj->irq_cause &= ~event;
NVIC_SetPriority(cyhal_dma_get_dw_irqn(obj), intrPriority);
NVIC_SetPriority(cyhal_dma_get_dw_irqn(obj), intr_priority);
}
bool cyhal_dma_is_busy_dw(cyhal_dma_t *obj)

View File

@ -27,9 +27,9 @@
#include "cyhal_ezi2c.h"
#include "cyhal_scb_common.h"
#include "cyhal_gpio.h"
#include "cyhal_interconnect.h"
#include "cyhal_system_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_utils.h"
#ifdef CY_IP_MXSCB
@ -38,13 +38,23 @@ extern "C"
{
#endif
/* Peripheral clock values for different EZI2C speeds according PDL API Reference Guide */
#define SCB_PERI_CLOCK_SLAVE_STD 8000000
#define SCB_PERI_CLOCK_SLAVE_FST 12500000
#define SCB_PERI_CLOCK_SLAVE_FSTP 50000000
#define SCB_PERI_CLOCK_MASTER_STD 2000000
#define SCB_PERI_CLOCK_MASTER_FST 8500000
#define SCB_PERI_CLOCK_MASTER_FSTP 20000000
/* Defines for mapping hal status to pdl */
#define EZI2C_COUNT (6U)
#define EZI2C_IDX_HAL (0U)
#define EZI2C_IDX_PDL (1U)
static cyhal_ezi2c_status_t cyhal_convert_activity_status(uint32_t pdl_status);
/* Structure to map EZI2C (PDL) status on HAL EZI2C status */
static const uint32_t ezi2c_status_map[EZI2C_COUNT][CYHAL_MAP_COLUMNS] =
{
{ (uint32_t)CYHAL_EZI2C_STATUS_READ1, (uint32_t)CY_SCB_EZI2C_STATUS_READ1 },
{ (uint32_t)CYHAL_EZI2C_STATUS_WRITE1, (uint32_t)CY_SCB_EZI2C_STATUS_WRITE1 },
{ (uint32_t)CYHAL_EZI2C_STATUS_READ2, (uint32_t)CY_SCB_EZI2C_STATUS_READ2 },
{ (uint32_t)CYHAL_EZI2C_STATUS_WRITE2, (uint32_t)CY_SCB_EZI2C_STATUS_WRITE2 },
{ (uint32_t)CYHAL_EZI2C_STATUS_BUSY, (uint32_t)CY_SCB_EZI2C_STATUS_BUSY },
{ (uint32_t)CYHAL_EZI2C_STATUS_ERR, (uint32_t)CY_SCB_EZI2C_STATUS_ERR },
};
/* Implement ISR for EZI2C */
static void cyhal_ezi2c_irq_handler(void)
@ -52,62 +62,54 @@ static void cyhal_ezi2c_irq_handler(void)
cyhal_ezi2c_t *obj = (cyhal_ezi2c_t*) cyhal_scb_get_irq_obj();
Cy_SCB_EZI2C_Interrupt(obj->base, &(obj->context));
/* Call if registered callback here */
/* Check if callback is registered */
cyhal_ezi2c_event_callback_t callback = (cyhal_ezi2c_event_callback_t) obj->callback_data.callback;
if (callback != NULL)
{
callback(obj->callback_data.callback_arg, CYHAL_EZI2C_EVENT_NONE);
/* Check status of EZI2C and verify which events are enabled */
cyhal_ezi2c_status_t status = cyhal_ezi2c_get_activity_status(obj);
if(status & obj->irq_cause)
{
(void) (callback) (obj->callback_data.callback_arg, (cyhal_ezi2c_status_t)(status & obj->irq_cause));
}
}
}
static uint32_t cyhal_set_peri_divider(cyhal_ezi2c_t *obj, uint32_t freq)
static bool cyhal_ezi2c_pm_callback_instance(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
{
/* Return the actual data rate on success, 0 otherwise */
uint32_t peri_freq = 0;
if (freq == 0)
{
return 0;
}
if (freq <= CY_SCB_I2C_STD_DATA_RATE)
{
peri_freq = SCB_PERI_CLOCK_SLAVE_STD;
}
else if (freq <= CY_SCB_I2C_FST_DATA_RATE)
{
peri_freq = SCB_PERI_CLOCK_SLAVE_FST;
}
else if (freq <= CY_SCB_I2C_FSTP_DATA_RATE)
{
peri_freq = SCB_PERI_CLOCK_SLAVE_FSTP;
}
else
{
return 0;
}
cyhal_ezi2c_t *obj = (cyhal_ezi2c_t*)(obj_ptr);
/* Connect assigned divider to be a clock source for EZI2C */
cy_en_sysclk_status_t status = Cy_SysClk_PeriphAssignDivider((en_clk_dst_t)((uint8_t)PCLK_SCB0_CLOCK + obj->resource.block_num), obj->clock.div_type, obj->clock.div_num);
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num);
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphSetDivider (obj->clock.div_type, obj->clock.div_num, cyhal_divider_value(peri_freq, 0u));
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num);
CY_ASSERT(CY_SYSCLK_SUCCESS == status);
cy_stc_syspm_callback_params_t ezi2c_callback_params = {
.base = (void *) (obj->base),
.context = (void *) &(obj->context)
};
return Cy_SCB_I2C_SetDataRate(obj->base, freq, Cy_SysClk_PeriphGetFrequency(obj->clock.div_type, obj->clock.div_num));
bool allow = true;
switch(state)
{
case CYHAL_SYSPM_CB_CPU_DEEPSLEEP:
allow = (CY_SYSPM_SUCCESS == Cy_SCB_EZI2C_DeepSleepCallback(&ezi2c_callback_params, pdl_mode));
break;
case CYHAL_SYSPM_CB_SYSTEM_HIBERNATE:
allow = (CY_SYSPM_SUCCESS == Cy_SCB_EZI2C_HibernateCallback(&ezi2c_callback_params, pdl_mode));
break;
default:
break;
}
return allow;
}
cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_divider_t *clk, const cyhal_ezi2c_cfg_t *cfg)
cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk, const cyhal_ezi2c_cfg_t *cfg)
{
CY_ASSERT(NULL != obj);
memset(obj, 0, sizeof(cyhal_ezi2c_t));
/* Validate input configuration structure */
if ((0 == cfg->slave1_cfg.slave_address) || ((cfg->two_addresses) && (0 == cfg->slave2_cfg.slave_address)))
{
return CYHAL_EZI2C_RSLT_ERR_CHECK_USER_CONFIG;
}
CY_ASSERT(NULL != obj);
/* Populate configuration structure */
const cy_stc_scb_ezi2c_config_t ezI2cConfig =
{
@ -127,9 +129,9 @@ cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t sc
cy_rslt_t result;
/* Reserve the I2C */
const cyhal_resource_pin_mapping_t *sda_map = CY_UTILS_GET_RESOURCE(sda, cyhal_pin_map_scb_i2c_sda);
const cyhal_resource_pin_mapping_t *scl_map = CY_UTILS_GET_RESOURCE(scl, cyhal_pin_map_scb_i2c_scl);
if ((NULL == sda_map) || (NULL == scl_map) || (sda_map->inst->block_num != scl_map->inst->block_num))
const cyhal_resource_pin_mapping_t *sda_map = CYHAL_FIND_SCB_MAP(sda, cyhal_pin_map_scb_i2c_sda);
const cyhal_resource_pin_mapping_t *scl_map = CYHAL_FIND_SCB_MAP(scl, cyhal_pin_map_scb_i2c_scl);
if ((NULL == sda_map) || (NULL == scl_map) || !cyhal_utils_resources_equal(sda_map->inst, scl_map->inst))
{
return CYHAL_EZI2C_RSLT_ERR_INVALID_PIN;
}
@ -139,32 +141,17 @@ cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t sc
/* Reserve the SDA pin */
if (result == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(sda);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(sda, sda_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_sda = sda;
/* Configures the HSIOM connection to the pin */
Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(sda), CYHAL_GET_PIN(sda), CY_GPIO_CFG_GET_HSIOM(scl_map->cfg));
/* Configures the pin output buffer drive mode and input buffer enable */
Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(sda), CYHAL_GET_PIN(sda), CY_GPIO_DM_OD_DRIVESLOW);
}
}
/* Reserve the SCL pin */
if (result == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(scl);
/* Connect SCB I2C function to pins */
cy_rslt_t result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(scl, scl_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_scl = scl;
/* Configures the HSIOM connection to the pin */
Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(scl), CYHAL_GET_PIN(scl), CY_GPIO_CFG_GET_HSIOM(scl_map->cfg));
/* Configures the pin output buffer drive mode and input buffer enable */
Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(scl), CYHAL_GET_PIN(scl), CY_GPIO_DM_OD_DRIVESLOW);
}
}
if (result == CY_RSLT_SUCCESS)
@ -189,24 +176,8 @@ cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t sc
result = Cy_SCB_EZI2C_Init(obj->base, &ezI2cConfig, &(obj->context));
}
int32_t ezi2c_freq;
switch(cfg->data_rate)
{
case CYHAL_EZI2C_DATA_RATE_100KHZ:
ezi2c_freq = 100000;
break;
case CYHAL_EZI2C_DATA_RATE_400KHZ:
ezi2c_freq = 400000;
break;
case CYHAL_EZI2C_DATA_RATE_1MHZ:
ezi2c_freq = 1000000;
break;
default:
return CYHAL_EZI2C_RSLT_ERR_CHECK_USER_CONFIG;
}
/* Set data rate */
int32_t dataRate = cyhal_set_peri_divider(obj, ezi2c_freq);
uint32_t dataRate = cyhal_i2c_set_peri_divider(obj->base, obj->resource.block_num, &(obj->clock), (uint32_t)cfg->data_rate, true);
if (dataRate == 0)
{
/* Can not reach desired data rate */
@ -226,10 +197,10 @@ cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t sc
if (result == CY_RSLT_SUCCESS)
{
cyhal_scb_update_instance_data(obj->resource.block_num, (void*)obj, &cyhal_ezi2c_pm_callback_instance);
obj->callback_data.callback = NULL;
obj->callback_data.callback_arg = NULL;
obj->irq_cause = 0;
cyhal_scb_config_structs[obj->resource.block_num] = obj;
cy_stc_sysint_t irqCfg = { CYHAL_SCB_IRQ_N[obj->resource.block_num], CYHAL_ISR_PRIORITY_DEFAULT };
Cy_SysInt_Init(&irqCfg, cyhal_ezi2c_irq_handler);
@ -258,6 +229,7 @@ void cyhal_ezi2c_free(cyhal_ezi2c_t *obj)
cyhal_hwmgr_free(&(obj->resource));
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
cyhal_scb_update_instance_data(obj->resource.block_num, NULL, NULL);
}
cyhal_utils_release_if_used(&(obj->pin_sda));
@ -271,7 +243,7 @@ void cyhal_ezi2c_free(cyhal_ezi2c_t *obj)
cyhal_ezi2c_status_t cyhal_ezi2c_get_activity_status(cyhal_ezi2c_t *obj)
{
return (cyhal_ezi2c_status_t)Cy_SCB_EZI2C_GetActivity(obj->base, &(obj->context));
return cyhal_convert_activity_status(Cy_SCB_EZI2C_GetActivity(obj->base, &(obj->context)));
}
void cyhal_ezi2c_register_callback(cyhal_ezi2c_t *obj, cyhal_ezi2c_event_callback_t callback, void *callback_arg)
@ -282,6 +254,31 @@ void cyhal_ezi2c_register_callback(cyhal_ezi2c_t *obj, cyhal_ezi2c_event_callbac
cyhal_system_critical_section_exit(savedIntrStatus);
}
void cyhal_ezi2c_enable_event(cyhal_ezi2c_t *obj, cyhal_ezi2c_status_t event, uint8_t intr_priority, bool enable)
{
if (enable)
{
obj->irq_cause |= event;
}
else
{
obj->irq_cause &= ~event;
}
IRQn_Type irqn = CYHAL_SCB_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intr_priority);
}
static cyhal_ezi2c_status_t cyhal_convert_activity_status(uint32_t pdl_status)
{
cyhal_ezi2c_status_t hal_status = (cyhal_ezi2c_status_t)cyhal_utils_convert_flags(ezi2c_status_map, EZI2C_IDX_PDL, EZI2C_IDX_HAL, EZI2C_COUNT, pdl_status);
if ((hal_status & (CYHAL_EZI2C_STATUS_BUSY | CYHAL_EZI2C_STATUS_ERR)) == 0)
{
hal_status |= CYHAL_EZI2C_STATUS_OK;
}
return hal_status;
}
#if defined(__cplusplus)
}
#endif

View File

@ -26,6 +26,8 @@
#include "cyhal_hwmgr.h"
#include "cyhal_hw_types.h"
#include "cyhal_flash.h"
#include "cy_utils.h"
#include "cyhal_syspm.h"
#include <string.h>
#ifdef CY_IP_MXS40SRSS
@ -34,8 +36,11 @@
extern "C" {
#endif /* __cplusplus */
typedef cy_en_flashdrv_status_t (*flash_operation)(uint32_t rowAddr, const uint32_t* data);
static bool cyhal_flash_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
static const cyhal_flash_block_info_t FLASH_BLOCKS[2] =
{
// Main Flash
@ -57,6 +62,53 @@ static const cyhal_flash_block_info_t FLASH_BLOCKS[2] =
};
static uint8_t writeBuf[CY_FLASH_SIZEOF_ROW];
static bool pending_pm_change = false;
static uint16_t init_count = 0;
static cyhal_syspm_callback_data_t cyhal_flash_internal_pm_cb = {
.callback = cyhal_flash_pm_callback,
.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_SLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE | CYHAL_SYSPM_CB_SYSTEM_LOW),
.next = NULL,
.args = NULL,
.ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION,
};
static inline cy_rslt_t cyhal_convert_flash_status(uint32_t pdl_status)
{
if(pdl_status == CY_FLASH_DRV_OPERATION_STARTED)
{
return CY_RSLT_SUCCESS;
}
else
{
return pdl_status;
}
}
static bool cyhal_flash_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
CY_UNUSED_PARAMETER(callback_arg);
bool allow = true;
switch (mode)
{
case CYHAL_SYSPM_CHECK_READY:
if (CY_RSLT_SUCCESS == Cy_Flash_IsOperationComplete())
pending_pm_change = true;
else
allow = false;
break;
case CYHAL_SYSPM_AFTER_TRANSITION:
case CYHAL_SYSPM_CHECK_FAIL:
pending_pm_change = false;
break;
default:
/* Don't care */
break;
}
return allow;
}
static inline bool is_in_flash(uint32_t address)
{
@ -71,35 +123,48 @@ static inline bool is_in_sram(uint32_t address)
static cy_rslt_t run_flash_operation(
flash_operation operation, uint32_t address, const uint32_t* data, bool clearCache)
{
const uint32_t* buffer;
if (is_in_sram((uint32_t)data))
{
buffer = data;
}
cy_rslt_t status;
if (pending_pm_change)
status = CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
else
{
memcpy(writeBuf, (const void *)data, CY_FLASH_SIZEOF_ROW);
buffer = (const uint32_t*)writeBuf;
const uint32_t* buffer;
if (is_in_sram((uint32_t)data))
{
buffer = data;
}
else
{
memcpy(writeBuf, (const void *)data, CY_FLASH_SIZEOF_ROW);
buffer = (const uint32_t*)writeBuf;
}
status = (cy_rslt_t)cyhal_convert_flash_status((cy_rslt_t)operation(address, buffer));
if (clearCache)
{
Cy_SysLib_ClearFlashCacheAndBuffer();
}
}
cy_en_flashdrv_status_t status = operation(address, buffer);
if (clearCache)
{
Cy_SysLib_ClearFlashCacheAndBuffer();
}
return (cy_rslt_t)status;
return status;
}
cy_rslt_t cyhal_flash_init(cyhal_flash_t *obj)
{
CY_ASSERT(NULL != obj);
if(init_count == 0)
cyhal_syspm_register_peripheral_callback(&cyhal_flash_internal_pm_cb);
init_count++;
return CY_RSLT_SUCCESS;
}
void cyhal_flash_free(cyhal_flash_t *obj)
{
CY_ASSERT(NULL != obj);
CY_ASSERT(init_count > 0);
init_count--;
if(init_count == 0)
cyhal_syspm_unregister_peripheral_callback(&cyhal_flash_internal_pm_cb);
}
void cyhal_flash_get_info(const cyhal_flash_t *obj, cyhal_flash_info_t *info)
@ -126,9 +191,11 @@ cy_rslt_t cyhal_flash_erase(cyhal_flash_t *obj, uint32_t address)
CY_ASSERT(NULL != obj);
cy_rslt_t status = CYHAL_FLASH_RSLT_ERR_ADDRESS;
if (is_in_flash(address))
if (pending_pm_change)
status = CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
else if (is_in_flash(address))
{
status = Cy_Flash_EraseRow(address);
status = (cy_rslt_t)cyhal_convert_flash_status(Cy_Flash_EraseRow(address));
Cy_SysLib_ClearFlashCacheAndBuffer();
}
@ -161,9 +228,15 @@ cy_rslt_t cyhal_flash_start_erase(cyhal_flash_t *obj, uint32_t address)
{
CY_ASSERT(NULL != obj);
cy_rslt_t status = is_in_flash(address)
? Cy_Flash_StartEraseRow(address)
: CYHAL_FLASH_RSLT_ERR_ADDRESS;
cy_rslt_t status;
if (pending_pm_change)
status = CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
else
{
status = (cy_rslt_t)cyhal_convert_flash_status(is_in_flash(address)
? Cy_Flash_StartEraseRow(address)
: CYHAL_FLASH_RSLT_ERR_ADDRESS);
}
return (status);
}
@ -194,17 +267,9 @@ bool cyhal_flash_is_operation_complete(cyhal_flash_t *obj)
{
CY_ASSERT(NULL != obj);
bool complete;
cy_rslt_t status = Cy_Flash_IsOperationComplete();
if (CY_FLASH_DRV_SUCCESS == status)
{
bool complete = (CY_FLASH_DRV_SUCCESS == Cy_Flash_IsOperationComplete());
if (complete)
Cy_SysLib_ClearFlashCacheAndBuffer();
complete = true;
}
else
{
complete = false;
}
return complete;
}

View File

@ -47,7 +47,7 @@ static void *hal_gpio_callback_args[IOSS_GPIO_GPIO_PORT_NR][CY_GPIO_PINS_MAX];
* Internal Interrrupt Service Routine
*******************************************************************************/
static void ioss_irq_handler()
static void ioss_irq_handler(void)
{
IRQn_Type irqn = CYHAL_GET_CURRENT_IRQN();
uint32_t port = irqn - ioss_interrupts_gpio_0_IRQn;
@ -136,7 +136,7 @@ static uint32_t cyhal_gpio_convert_drive_mode(cyhal_gpio_drive_mode_t drive_mode
* HAL Implementation
*******************************************************************************/
cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drvMode, bool initVal)
cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode, bool init_val)
{
/* Mbed creates GPIOs for pins that are dedicated to other peripherals in some cases. */
#ifndef __MBED__
@ -148,8 +148,8 @@ cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cy
if (status == CY_RSLT_SUCCESS)
{
uint32_t pdlDrvMode = cyhal_gpio_convert_drive_mode(drvMode, direction);
Cy_GPIO_Pin_FastInit(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdlDrvMode, initVal, HSIOM_SEL_GPIO);
uint32_t pdl_drive_mode = cyhal_gpio_convert_drive_mode(drive_mode, direction);
Cy_GPIO_Pin_FastInit(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdl_drive_mode, init_val, HSIOM_SEL_GPIO);
}
return status;
@ -172,10 +172,10 @@ void cyhal_gpio_free(cyhal_gpio_t pin)
}
}
cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drvMode)
cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode)
{
uint32_t pdlDrvMode = cyhal_gpio_convert_drive_mode(drvMode, direction);
Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdlDrvMode);
uint32_t pdldrive_mode = cyhal_gpio_convert_drive_mode(drive_mode, direction);
Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdldrive_mode);
return CY_RSLT_SUCCESS;
}
@ -188,7 +188,7 @@ void cyhal_gpio_register_callback(cyhal_gpio_t pin, cyhal_gpio_event_callback_t
cyhal_system_critical_section_exit(savedIntrStatus);
}
void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t intrPriority, bool enable)
void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t intr_priority, bool enable)
{
Cy_GPIO_ClearInterrupt(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin));
Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), (uint32_t)event);
@ -198,14 +198,14 @@ void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t
IRQn_Type irqn = (IRQn_Type)(ioss_interrupts_gpio_0_IRQn + CYHAL_GET_PORT(pin));
if (NVIC_GetEnableIRQ(irqn) == 0)
{
cy_stc_sysint_t irqCfg = {irqn, intrPriority};
cy_stc_sysint_t irqCfg = {irqn, intr_priority};
Cy_SysInt_Init(&irqCfg, ioss_irq_handler);
NVIC_EnableIRQ(irqn);
}
else
{
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
}
}

View File

@ -40,7 +40,7 @@ extern "C"
#ifdef CY_IP_MXS40PASS_SAR_INSTANCES
#define CY_BLOCK_COUNT_ADC CY_IP_MXS40PASS_SAR_INSTANCES
#else
#define CY_BLOCK_COUNT_ADC 0
#define CY_BLOCK_COUNT_ADC 0
#endif
#ifdef CY_IP_MXBLESS_INSTANCES
@ -82,21 +82,56 @@ extern "C"
#define CY_CHANNEL_COUNT_CAN 0
#endif
#ifdef SRSS_NUM_CLKPATH
#define CY_BLOCK_COUNT_CLK_PATH SRSS_NUM_CLKPATH
#if SRSS_ECO_PRESENT
#define ECO_COUNT 1
#else
#define CY_BLOCK_COUNT_CLK_PATH 0
#define ECO_COUNT 0
#endif
#define CY_BLOCK_COUNT_CLOCK 4
#define CY_CHANNEL_COUNT_CLOCK (PERI_DIV_8_NR + PERI_DIV_16_NR + PERI_DIV_16_5_NR + PERI_DIV_24_5_NR)
#if SRSS_ALTHF_PRESENT
#define ALTHF_COUNT 1
#else
#define ALTHF_COUNT 0
#endif
#if SRSS_ALTLF_PRESENT
#define ALTLF_COUNT 1
#else
#define ALTLF_COUNT 0
#endif
#if SRSS_PILO_PRESENT
#define PILO_COUNT 1
#else
#define PILO_COUNT 0
#endif
#if SRSS_BACKUP_PRESENT
#define WCO_COUNT 1
#else
#define WCO_COUNT 0
#endif
#if SRSS_MFO_PRESENT
// 1 for MFO and one for MF
#define MF_COUNT 2
#else
#define MF_COUNT 0
#endif
// ECO, ALTHF, ALTLF, PILO, WCO, MFO, MF
#define EXTRA_CLOCKS 7
//12 = IMO, EXT, ILO, FLL, LF, Pump, BAK, Timer, AltSysTick, Slow, Fast, Peri
#define CY_CHANNEL_COUNT_CLOCK (12 + EXTRA_CLOCKS + 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)
#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 1
#define CY_BLOCK_COUNT_CRYPTO 1
#else
#define CY_BLOCK_COUNT_CRYPTO 0
#define CY_BLOCK_COUNT_CRYPTO 0
#endif
#ifdef CY_IP_MXS40PASS_CTDAC_INSTANCES
@ -114,18 +149,18 @@ extern "C"
#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)
#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
#define CY_BLOCK_COUNT_DW 0
#define CY_CHANNEL_COUNT_DW 0
#endif
#ifdef 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_BLOCK_COUNT_GPIO 0
#define CY_CHANNEL_COUNT_GPIO 0
#endif
@ -160,9 +195,9 @@ extern "C"
#endif
#ifdef CY_IP_MXSMIF_INSTANCES
#define CY_BLOCK_COUNT_QSPI CY_IP_MXSMIF_INSTANCES
#define CY_BLOCK_COUNT_QSPI CY_IP_MXSMIF_INSTANCES
#else
#define CY_BLOCK_COUNT_QSPI 0
#define CY_BLOCK_COUNT_QSPI 0
#endif
#ifdef CY_IP_MXS40SRSS_RTC_INSTANCES
@ -178,9 +213,9 @@ extern "C"
#endif
#ifdef CY_IP_MXSDHC_INSTANCES
#define CY_BLOCK_COUNT_SDHC CY_IP_MXSDHC_INSTANCES
#define CY_BLOCK_COUNT_SDHC CY_IP_MXSDHC_INSTANCES
#else
#define CY_BLOCK_COUNT_SDHC 0
#define CY_BLOCK_COUNT_SDHC 0
#endif
#ifdef CY_IP_MXTCPWM_INSTANCES
@ -229,9 +264,9 @@ extern "C"
#endif
#ifdef CY_IP_MXS40SRSS_MCWDT_INSTANCES
#define CY_BLOCK_COUNT_MCWDT CY_IP_MXS40SRSS_MCWDT_INSTANCES
#define CY_BLOCK_COUNT_MCWDT CY_IP_MXS40SRSS_MCWDT_INSTANCES
#else
#define CY_BLOCK_COUNT_MCWDT 0
#define CY_BLOCK_COUNT_MCWDT 0
#endif
@ -253,9 +288,7 @@ extern "C"
#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_CLK_PATH (CY_OFFSET_CAN + CY_SIZE_CAN)
#define CY_SIZE_CLK_PATH (CY_BLOCK_COUNT_CLK_PATH)
#define CY_OFFSET_CLOCK (CY_OFFSET_CLK_PATH + CY_SIZE_CLK_PATH)
#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
@ -303,12 +336,51 @@ extern "C"
* Variables
*******************************************************************************/
static const uint8_t cyhal_block_offsets_clock[4] =
#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
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
};
static const uint8_t cyhal_block_offsets_dma[] =
@ -411,16 +483,13 @@ static const uint8_t cyhal_block_offsets_tcpwm[] =
static uint8_t cyhal_used[(CY_TOTAL_ALLOCATABLE_ITEMS + 7) / 8] = {0};
/** Array of pin to resource mappings, provided by the BSP. Must be terminated with a CYHAL_RSC_INVALID entry */
extern cyhal_resource_pin_mapping_t* cyhal_resource_pin_mapping;
// Note: the ordering here needs to be parallel to that of cyhal_resource_t
static const uint16_t cyhal_resource_offsets[] =
{
CY_OFFSET_ADC,
CY_OFFSET_BLE,
CY_OFFSET_CAN,
CY_OFFSET_CLK_PATH,
CY_OFFSET_CLOCK, /* Placeholder for ClockPath which is deprecated */
CY_OFFSET_CLOCK,
CY_OFFSET_CRYPTO,
CY_OFFSET_DAC,
@ -458,14 +527,14 @@ static const uint32_t cyhal_has_channels =
* 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() __attribute__ ((deprecated));
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()
static inline void check_array_size(void)
{
uint32_t dummy = 1 / (sizeof(cyhal_resource_offsets) == (sizeof(uint16_t) * CYHAL_RSC_INVALID));
(void)dummy;
@ -537,6 +606,14 @@ static inline uint8_t cyhal_get_block_offset_length(cyhal_resource_t type)
static cy_rslt_t cyhal_get_bit_position(cyhal_resource_t type, uint8_t block, uint8_t channel, uint16_t* bitPosition)
{
/* For backwards compatability. */
if (type == CYHAL_RSC_CLKPATH)
{
channel = block;
block = CYHAL_CLOCK_BLOCK_PATHMUX;
type = CYHAL_RSC_CLOCK;
}
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
@ -616,7 +693,7 @@ static inline cy_rslt_t cyhal_clear_bit(uint8_t* used, cyhal_resource_t type, ui
* Hardware Manager API
*******************************************************************************/
cy_rslt_t cyhal_hwmgr_init()
cy_rslt_t cyhal_hwmgr_init(void)
{
return CY_RSLT_SUCCESS;
}
@ -696,39 +773,6 @@ cy_rslt_t cyhal_hwmgr_allocate(cyhal_resource_t type, cyhal_resource_inst_t* obj
return CYHAL_HWMGR_RSLT_ERR_NONE_FREE;
}
cy_rslt_t cyhal_hwmgr_allocate_clock(cyhal_clock_divider_t* obj, cyhal_clock_divider_types_t div, bool accept_larger)
{
static uint8_t counts[] = { PERI_DIV_8_NR, PERI_DIV_16_NR, PERI_DIV_16_5_NR, PERI_DIV_24_5_NR };
cyhal_clock_divider_types_t max_div_type = (accept_larger) ? (cyhal_clock_divider_types_t)(sizeof(counts) - 1) : div;
cy_rslt_t rslt = CYHAL_HWMGR_RSLT_ERR_NONE_FREE;
for(cyhal_clock_divider_types_t current_div = div; rslt != CY_RSLT_SUCCESS && current_div <= max_div_type; ++current_div)
{
uint8_t block = (uint8_t)current_div;
uint8_t count = counts[block];
for (int i = 0; rslt != CY_RSLT_SUCCESS && i < count; i++)
{
cyhal_resource_inst_t res = { CYHAL_RSC_CLOCK, block, i };
bool reserved = (CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(&res));
if (reserved)
{
obj->div_type = current_div;
obj->div_num = i;
rslt = CY_RSLT_SUCCESS;
}
}
}
return rslt;
}
void cyhal_hwmgr_free_clock(cyhal_clock_divider_t* obj)
{
cyhal_resource_inst_t res = { CYHAL_RSC_CLOCK, obj->div_type, obj->div_num };
cyhal_hwmgr_free(&res);
}
#if defined(__cplusplus)
}
#endif

View File

@ -27,9 +27,10 @@
#include "cyhal_i2c.h"
#include "cyhal_scb_common.h"
#include "cyhal_gpio.h"
#include "cyhal_interconnect.h"
#include "cyhal_system_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_system.h"
#include "cyhal_syspm.h"
#include "cyhal_utils.h"
#ifdef CY_IP_MXSCB
@ -43,19 +44,6 @@ extern "C"
#define PENDING_TX 2
#define PENDING_TX_RX 3
/* Must be between 1.55 MHz and 12.8 MHz for running i2c master at 100KHz */
#define SCB_PERI_CLOCK_SLAVE_STD 8000000
/* Must be between 7.82 MHz and 15.38 MHz for running i2c master at 400KHz */
#define SCB_PERI_CLOCK_SLAVE_FST 12500000
/* Must be between 15.84 MHz and 89.0 MHz for running i2c master at 1MHz */
#define SCB_PERI_CLOCK_SLAVE_FSTP 50000000
/* Must be between 1.55 MHz and 3.2 MHz for running i2c slave at 100KHz */
#define SCB_PERI_CLOCK_MASTER_STD 2000000
/* Must be between 7.82 MHz and 10 MHz for running i2c slave at 400KHz */
#define SCB_PERI_CLOCK_MASTER_FST 8500000
/* Must be between 14.32 MHz and 25.8 MHz for running i2c slave at 1MHz */
#define SCB_PERI_CLOCK_MASTER_FSTP 20000000
#define CYHAL_I2C_MASTER_DEFAULT_FREQ 100000
static const cy_stc_scb_i2c_config_t default_i2c_config = {
@ -80,20 +68,23 @@ static void cyhal_i2c_irq_handler(void)
Cy_SCB_I2C_Interrupt(obj->base, &(obj->context));
if (obj->async)
if (obj->pending)
{
/* This code is part of cyhal_i2c_master_transfer_async() API functionality */
/* cyhal_i2c_master_transfer_async() API uses this interrupt handler for RX Transfer */
/* cyhal_i2c_master_transfer_async() API uses this interrupt handler for RX transfer */
if (0 == (Cy_SCB_I2C_MasterGetStatus(obj->base, &obj->context) & CY_SCB_I2C_MASTER_BUSY))
{
if (obj->tx_config.bufferSize)
/* Check if TX is completed and run RX in case when TX and RX are enabled */
if (obj->pending == PENDING_TX_RX)
{
/* Start RX Transfer */
/* Start RX transfer */
obj->pending = PENDING_RX;
Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
/* Finish Async Transfer */
}
else
{
/* Finish async TX or RX separate transfer */
obj->pending = PENDING_NONE;
obj->async = false;
}
}
}
@ -110,70 +101,48 @@ static void cyhal_i2c_cb_wrapper(uint32_t event)
}
}
static uint32_t cyhal_set_peri_divider(cyhal_i2c_t *obj, uint32_t freq, bool is_slave)
static bool cyhal_i2c_pm_callback_instance(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
{
/* Return the actual data rate on success, 0 otherwise */
uint32_t peri_freq = 0;
if (freq == 0)
{
return 0;
}
if (freq <= CY_SCB_I2C_STD_DATA_RATE)
{
peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_STD : SCB_PERI_CLOCK_MASTER_STD;
}
else if (freq <= CY_SCB_I2C_FST_DATA_RATE)
{
peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_FST : SCB_PERI_CLOCK_MASTER_FST;
}
else if (freq <= CY_SCB_I2C_FSTP_DATA_RATE)
{
peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_FSTP : SCB_PERI_CLOCK_MASTER_FSTP;
}
else
{
return 0;
}
cy_en_sysclk_status_t status = Cy_SysClk_PeriphAssignDivider((en_clk_dst_t)((uint8_t)PCLK_SCB0_CLOCK + obj->resource.block_num), obj->clock.div_type, obj->clock.div_num);
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num);
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphSetDivider(obj->clock.div_type, obj->clock.div_num, cyhal_divider_value(peri_freq, 0u));
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num);
CY_ASSERT(CY_SYSCLK_SUCCESS == status);
cyhal_i2c_t *obj = (cyhal_i2c_t*)obj_ptr;
cy_stc_syspm_callback_params_t i2c_callback_params = {
.base = (void *) (obj->base),
.context = (void *) &(obj->context)
};
bool allow = true;
/* According to PDL API Reference Guide - Cy_SysClk_PeriphGetFrequency() use only for i2c master role */
if(!is_slave)
{
return Cy_SCB_I2C_SetDataRate(obj->base, freq, Cy_SysClk_PeriphGetFrequency(obj->clock.div_type, obj->clock.div_num));
}
else
{
return Cy_SCB_I2C_GetDataRate(obj->base, Cy_SysClk_PeriphGetFrequency(obj->clock.div_type, obj->clock.div_num));
}
if (CYHAL_SYSPM_CB_CPU_DEEPSLEEP == state)
allow = (CY_SYSPM_SUCCESS == Cy_SCB_I2C_DeepSleepCallback(&i2c_callback_params, pdl_mode));
else if (CYHAL_SYSPM_CB_SYSTEM_HIBERNATE == state)
allow = (CY_SYSPM_SUCCESS == Cy_SCB_I2C_HibernateCallback(&i2c_callback_params, pdl_mode));
return allow;
}
/* Start API implementing */
cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_divider_t *clk)
cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk)
{
CY_ASSERT(NULL != obj);
memset(obj, 0, sizeof(cyhal_i2c_t));
/* Explicitly marked not allocated resources as invalid to prevent freeing them. */
obj->resource.type = CYHAL_RSC_INVALID;
obj->pin_scl = CYHAL_NC_PIN_VALUE;
obj->pin_sda = CYHAL_NC_PIN_VALUE;
obj->is_shared_clock = true;
/* Initial value for async operations */
obj->pending = PENDING_NONE;
/* Reserve the I2C */
const cyhal_resource_pin_mapping_t *sda_map = CY_UTILS_GET_RESOURCE(sda, cyhal_pin_map_scb_i2c_sda);
const cyhal_resource_pin_mapping_t *scl_map = CY_UTILS_GET_RESOURCE(scl, cyhal_pin_map_scb_i2c_scl);
if ((NULL == sda_map) || (NULL == scl_map) || (sda_map->inst->block_num != scl_map->inst->block_num))
const cyhal_resource_pin_mapping_t *sda_map = CYHAL_FIND_SCB_MAP(sda, cyhal_pin_map_scb_i2c_sda);
const cyhal_resource_pin_mapping_t *scl_map = CYHAL_FIND_SCB_MAP(scl, cyhal_pin_map_scb_i2c_scl);
if ((NULL == sda_map) || (NULL == scl_map) || !cyhal_utils_resources_equal(sda_map->inst, scl_map->inst))
{
return CYHAL_I2C_RSLT_ERR_INVALID_PIN;
}
obj->resource = *(scl_map->inst);
obj->base = CYHAL_SCB_BASE_ADDRESSES[obj->resource.block_num];
cy_rslt_t result = cyhal_hwmgr_reserve(&(obj->resource));
if (result != CY_RSLT_SUCCESS)
{
@ -181,32 +150,21 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c
}
/* Reserve the SDA pin */
cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(sda);
result = cyhal_hwmgr_reserve(&pin_rsc);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_sda = sda;
result = cyhal_utils_reserve_and_connect(sda, sda_map);
if (result == CY_RSLT_SUCCESS)
obj->pin_sda = sda;
}
Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(sda), CYHAL_GET_PIN(sda), CY_GPIO_CFG_GET_HSIOM(scl_map->cfg));
Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(sda), CYHAL_GET_PIN(sda), CY_GPIO_DM_OD_DRIVESLOW);
/* Reserve the SCL pin */
if (result == CY_RSLT_SUCCESS)
{
pin_rsc = cyhal_utils_get_gpio_resource(scl);
/* Connect SCB I2C function to pins */
cy_rslt_t result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(scl, scl_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_scl = scl;
}
Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(scl), CYHAL_GET_PIN(scl), CY_GPIO_CFG_GET_HSIOM(scl_map->cfg));
Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(scl), CYHAL_GET_PIN(scl), CY_GPIO_DM_OD_DRIVESLOW);
}
obj->base = CYHAL_SCB_BASE_ADDRESSES[obj->resource.block_num];
if (result == CY_RSLT_SUCCESS)
{
obj->is_shared_clock = (clk != NULL);
@ -222,7 +180,7 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c
if (result == CY_RSLT_SUCCESS)
{
uint32_t dataRate = cyhal_set_peri_divider(obj, CYHAL_I2C_MASTER_DEFAULT_FREQ, false);
uint32_t dataRate = cyhal_i2c_set_peri_divider(obj->base, obj->resource.block_num, &(obj->clock), CYHAL_I2C_MASTER_DEFAULT_FREQ, false);
if (dataRate == 0)
{
/* Can not reach desired data rate */
@ -238,13 +196,13 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c
if (result == CY_RSLT_SUCCESS)
{
cyhal_scb_update_instance_data(obj->resource.block_num, (void*)obj, &cyhal_i2c_pm_callback_instance);
/* Enable I2C to operate */
Cy_SCB_I2C_Enable(obj->base);
obj->callback_data.callback = NULL;
obj->callback_data.callback_arg = NULL;
obj->irq_cause = CYHAL_I2C_EVENT_NONE;
cyhal_scb_config_structs[obj->resource.block_num] = obj;
cy_stc_sysint_t irqCfg = { CYHAL_SCB_IRQ_N[obj->resource.block_num], CYHAL_ISR_PRIORITY_DEFAULT };
Cy_SysInt_Init(&irqCfg, cyhal_i2c_irq_handler);
@ -262,8 +220,10 @@ void cyhal_i2c_free(cyhal_i2c_t *obj)
{
CY_ASSERT(NULL != obj);
if (CYHAL_RSC_INVALID != obj->resource.type)
{
cyhal_scb_update_instance_data(obj->resource.block_num, NULL, NULL);
IRQn_Type irqn = CYHAL_SCB_IRQ_N[obj->resource.block_num];
NVIC_DisableIRQ(irqn);
@ -299,7 +259,7 @@ cy_rslt_t cyhal_i2c_configure(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg)
}
/* Set data rate */
uint32_t dataRate = cyhal_set_peri_divider(obj, cfg->frequencyhal_hz, cfg->is_slave);
uint32_t dataRate = cyhal_i2c_set_peri_divider(obj->base, obj->resource.block_num, &(obj->clock), cfg->frequencyhal_hz, cfg->is_slave);
if (dataRate == 0)
{
/* Can not reach desired data rate */
@ -314,6 +274,9 @@ cy_rslt_t cyhal_i2c_configure(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg)
cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
cy_en_scb_i2c_status_t status = obj->context.state == CY_SCB_I2C_IDLE
? Cy_SCB_I2C_MasterSendStart(obj->base, dev_addr, CY_SCB_I2C_WRITE_XFER, timeout, &obj->context)
: Cy_SCB_I2C_MasterSendReStart(obj->base, dev_addr, CY_SCB_I2C_WRITE_XFER, timeout, &obj->context);
@ -344,6 +307,9 @@ cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint
cy_rslt_t cyhal_i2c_master_read(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
cy_en_scb_i2c_command_t ack = CY_SCB_I2C_ACK;
/* Start transaction, send dev_addr */
@ -377,16 +343,19 @@ cy_rslt_t cyhal_i2c_master_read(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *da
return status;
}
/* The following code is DEPRECATED and must not be used in new projects */
cy_rslt_t cyhal_i2c_slave_config_write_buff(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size)
{
if (obj->context.state == CY_SCB_I2C_IDLE)
{
Cy_SCB_I2C_SlaveConfigReadBuf(obj->base, (uint8_t *)data, size, &obj->context);
}
return CY_RSLT_SUCCESS;
return cyhal_i2c_slave_config_read_buffer(obj, (uint8_t *)data, size);
}
/* The following code is DEPRECATED and must not be used in new projects */
cy_rslt_t cyhal_i2c_slave_config_read_buff(cyhal_i2c_t *obj, uint8_t *data, uint16_t size)
{
return cyhal_i2c_slave_config_write_buffer(obj, (uint8_t *)data, size);
}
cy_rslt_t cyhal_i2c_slave_config_write_buffer(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size)
{
if (obj->context.state == CY_SCB_I2C_IDLE)
{
@ -395,8 +364,20 @@ cy_rslt_t cyhal_i2c_slave_config_read_buff(cyhal_i2c_t *obj, uint8_t *data, uint
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_i2c_slave_config_read_buffer(cyhal_i2c_t *obj, uint8_t *data, uint16_t size)
{
if (obj->context.state == CY_SCB_I2C_IDLE)
{
Cy_SCB_I2C_SlaveConfigReadBuf(obj->base, (uint8_t *)data, size, &obj->context);
}
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_i2c_master_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, const uint8_t *data, uint16_t size, uint32_t timeout)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint8_t mem_addr_buf[2];
if (mem_addr_size == 1)
{
@ -435,6 +416,9 @@ cy_rslt_t cyhal_i2c_master_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_
cy_rslt_t cyhal_i2c_master_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, uint16_t size, uint32_t timeout)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint8_t mem_addr_buf[2];
if (mem_addr_size == 1)
{
@ -460,6 +444,9 @@ cy_rslt_t cyhal_i2c_master_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t
cy_rslt_t cyhal_i2c_master_transfer_async(cyhal_i2c_t *obj, uint16_t address, const void *tx, size_t tx_size, void *rx, size_t rx_size)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
obj->rx_config.slaveAddress = address;
obj->tx_config.slaveAddress = address;
@ -469,31 +456,31 @@ cy_rslt_t cyhal_i2c_master_transfer_async(cyhal_i2c_t *obj, uint16_t address, co
obj->tx_config.buffer = (void *)tx;
obj->tx_config.bufferSize = tx_size;
obj->async = true;
if (tx_size)
if (!obj->pending)
{
/* Write first, then read, or write only. */
if (rx_size > 0)
/* Validate input data and do appropriate action */
if (tx_size)
{
obj->pending = PENDING_TX_RX;
obj->pending = (rx_size)
? PENDING_TX_RX
: PENDING_TX;
Cy_SCB_I2C_MasterWrite(obj->base, &obj->tx_config, &obj->context);
/* Receive covered by interrupt handler - cyhal_i2c_irq_handler() */
}
else if (rx_size)
{
obj->pending = PENDING_RX;
Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
}
else
{
obj->pending = PENDING_TX;
return CYHAL_I2C_RSLT_ERR_TX_RX_BUFFERS_ARE_EMPTY;
}
/* Transmit */
Cy_SCB_I2C_MasterWrite(obj->base, &obj->tx_config, &obj->context);
/* Receive covered by interrupt handler */
}
else if (rx_size)
else
{
/* Read transaction */
obj->pending = PENDING_RX;
Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
return CYHAL_I2C_RSLT_ERR_PREVIOUS_ASYNCH_PENDING;
}
return CY_RSLT_SUCCESS;
}
@ -569,7 +556,7 @@ void cyhal_i2c_register_callback(cyhal_i2c_t *obj, cyhal_i2c_event_callback_t ca
obj->irq_cause = CYHAL_I2C_EVENT_NONE;
}
void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t intrPriority, bool enable)
void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t intr_priority, bool enable)
{
if (enable)
{
@ -581,7 +568,7 @@ void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t i
}
IRQn_Type irqn = CYHAL_SCB_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
}
#if defined(__cplusplus)

File diff suppressed because it is too large Load Diff

View File

@ -24,9 +24,7 @@
*******************************************************************************/
#include "cyhal_interconnect.h"
#include "cyhal_hwmgr.h"
#include "cyhal_gpio_impl.h"
#include "cyhal_hwmgr.h"
#ifdef CY_IP_MXPERI
@ -39,8 +37,8 @@ cy_rslt_t cyhal_connect_pin(const cyhal_resource_pin_mapping_t *pin_connection)
{
cyhal_gpio_t pin = pin_connection->pin;
GPIO_PRT_Type *port = Cy_GPIO_PortToAddr(CYHAL_GET_PORT(pin));
en_hsiom_sel_t hsiom = CY_GPIO_CFG_GET_HSIOM(pin_connection->cfg);
uint8_t mode = CY_GPIO_CFG_GET_MODE(pin_connection->cfg);
en_hsiom_sel_t hsiom = pin_connection->hsiom;
uint8_t mode = pin_connection->drive_mode;
Cy_GPIO_Pin_FastInit(port, CYHAL_GET_PIN(pin), mode, 1, hsiom);
// Force output to enable pulls.

View File

@ -25,6 +25,14 @@
* limitations under the License.
*******************************************************************************/
/**
* \addtogroup group_hal_psoc6_lptimer LPTIMER
* \ingroup group_hal_psoc6
* \{
* The maximum number of ticks that can set to an LPTIMER is 0xFFF0FFFF. It is not recommended to use 0xFFFFFFFF because to avoid both C0 and C1 overflowing.
* \} group_hal_psoc6_lptimer
*/
#include "cmsis_compiler.h"
#include "cy_mcwdt.h"
#include "cy_syslib.h"
@ -52,12 +60,16 @@ static MCWDT_STRUCT_Type * const CYHAL_LPTIMER_BASE_ADDRESSES[] = {
#endif
};
#define CY_MCWDT_MAX_DELAY_TICKS (0xfff0ffffUL) /* ~36hours, Not set to 0xffffffff to avoid C0 and C1 both overflowing */
#define CY_MCWDT_LPTIMER_CTRL (CY_MCWDT_CTR0 | CY_MCWDT_CTR1 | CY_MCWDT_CTR2)
#define CY_MCWDT_MIN_DELAY 3 /* minimum amount of lfclk cycles of that LPTIMER can delay for. */
#define CY_MCWDT_MIN_DELAY (3U) /* minimum amount of lfclk cycles of that LPTIMER can delay for. */
#define CY_MCWDT_MAX_DELAY_TICKS (0xfff0ffffUL) /* ~36hours, Not set to 0xffffffff to avoid C0 and C1 both overflowing */
#define CY_MCWDT_MAX_COUNTER_VAL (0xffffffffUL) /* Maximum value of the counter before it rolls over */
#define CY_DEFAULT_MCWDT_PRIORITY 3
#define CY_DEFAULT_MCWDT_PRIORITY (3U)
/* For all PSoC 6 architectures the MCWDT is driven by CLK_LF that will always run at 32.768 KHz */
#define CY_MCWDT_CLK_FREQ_HZ (32768U)
static const uint16_t CY_MCWDT_RESET_TIME_US = 62;
static const uint16_t CY_MCWDT_SETMATCH_NOWAIT_TIME_US = 0;
@ -152,7 +164,7 @@ void cyhal_lptimer_free(cyhal_lptimer_t *obj)
cy_rslt_t cyhal_lptimer_reload(cyhal_lptimer_t *obj)
{
Cy_MCWDT_ResetCounters(obj->base, CY_MCWDT_CTR2, CY_MCWDT_RESET_TIME_US);
Cy_MCWDT_ResetCounters(obj->base, (CY_MCWDT_CTR0 | CY_MCWDT_CTR1 | CY_MCWDT_CTR2), 2 * CY_MCWDT_RESET_TIME_US);
return CY_RSLT_SUCCESS;
}
@ -239,14 +251,14 @@ void cyhal_lptimer_register_callback(cyhal_lptimer_t *obj, cyhal_lptimer_event_c
cyhal_system_critical_section_exit(savedIntrStatus);
}
void cyhal_lptimer_enable_event(cyhal_lptimer_t *obj, cyhal_lptimer_event_t event, uint8_t intrPriority, bool enable)
void cyhal_lptimer_enable_event(cyhal_lptimer_t *obj, cyhal_lptimer_event_t event, uint8_t intr_priority, bool enable)
{
CY_ASSERT(event == CYHAL_LPTIMER_COMPARE_MATCH);
Cy_MCWDT_ClearInterrupt(obj->base, CY_MCWDT_CTR1);
Cy_MCWDT_SetInterruptMask(obj->base, enable ? CY_MCWDT_CTR1 : 0);
IRQn_Type irqn = (IRQn_Type)(srss_interrupt_mcwdt_0_IRQn + obj->resource.block_num);
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
}
void cyhal_lptimer_irq_trigger(cyhal_lptimer_t *obj)
@ -256,8 +268,18 @@ void cyhal_lptimer_irq_trigger(cyhal_lptimer_t *obj)
NVIC_SetPendingIRQ(irqn);
}
void cyhal_lptimer_get_info(cyhal_lptimer_t *obj, cyhal_lptimer_info_t *info)
{
CY_UNUSED_PARAMETER(obj);
CY_ASSERT(info != NULL);
info->frequency_hz = CY_MCWDT_CLK_FREQ_HZ;
info->min_set_delay = CY_MCWDT_MIN_DELAY;
info->max_counter_value = CY_MCWDT_MAX_COUNTER_VAL;
}
#if defined(__cplusplus)
}
#endif
#endif /* CY_IP_MXS40SRSS_MCWDT_INSTANCES */
#endif /* CY_IP_MXS40SRSS_MCWDT_INSTANCES */

View File

@ -169,7 +169,14 @@ cy_rslt_t cyhal_connect_trigger(cyhal_source_t source, cyhal_dest_t dest)
else
{
cyhal_dest_t intraDest = cyhal_intra_trigger_source[foundSource];
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
if (CYHAL_INTERCONNECT_MUX_NOT_CONTINUATION != intraDest)
#if __clang__
#pragma clang diagnostic pop
#endif
{
// This destination can be driven by the output of another mux.
uint8_t upstreamMuxIdx = cyhal_dest_to_mux_fake[intraDest];

View File

@ -0,0 +1,792 @@
/*******************************************************************************
* File Name: cyhal_pdmpcm.c
*
* Description:
* Provides a high level interface for interacting with the Cypress I2C. This is
* a wrapper around the lower level PDL API.
*
********************************************************************************
* \copyright
* Copyright 2018-2019 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 <stdlib.h>
#include "cyhal_dma.h"
#include "cyhal_gpio.h"
#include "cyhal_hwmgr.h"
#include "cyhal_pdmpcm.h"
#include "cyhal_syspm_impl.h"
#include "cyhal_system.h"
#include "cyhal_utils.h"
#include "cy_device.h"
#include "cy_device_headers.h"
#include "cy_pdm_pcm.h"
#include "cy_utils.h"
/**
* \addtogroup group_hal_psoc6_pdmpcm PDM/PCM (Pulse Density Modulation to Pulse Code Modulation Converter)
* \ingroup group_hal_psoc6
* \{
* The PSoC 6 PDM/PCM Supports the following conversion parameters:<ul>
* <li>Mode: Mono Left, Mono Right, Stereo
* <li>Word Length: 16/18/20/24 bits</li>
* <li>Sampling Rate: up to 48kHz</li>
* <li>Left/Right Gain Amplifier: -12dB to +10.5dB in 1.5dB steps.</li>
* </ul>
* \} group_hal_psoc6_pdmpcm
*/
#ifdef CY_IP_MXAUDIOSS_INSTANCES
#if defined(__cplusplus)
extern "C"
{
#endif
#define CYHAL_PDM_PCM_EVENT_NONE ((cyhal_pdm_pcm_event_t) 0x0)
#define CLK_SOURCE_HFCLK1 (1)
#define HALF_FIFO (0x80U)
#define MIN_GAIN -24
#define MAX_GAIN 21
#define MAX_SAMPLE_RATE 48000 // 48 kHz
#define STABILIZATION_FS 46 // 35-45 PCM samples it takes for PCM to stabilize. Round to even so that same number of left and right samples are removed
static PDM_Type *const cyhal_pdm_pcm_base[] =
{
#if (CY_IP_MXAUDIOSS_INSTANCES == 1 && defined(AUDIOSS_PDM) && AUDIOSS_PDM)
PDM,
#elif (CY_IP_MXAUDIOSS_INSTANCES >= 1 && defined(AUDIOSS0_PDM) && AUDIOSS0_PDM)
PDM0,
#endif
#if (CY_IP_MXAUDIOSS_INSTANCES >= 2 && defined(AUDIOSS1_PDM) && AUDIOSS1_PDM)
PDM1,
#endif
#if (CY_IP_MXS40AUDIOSS_INSTANCES > 2)
#warning Unhandled audioss instance count
#endif
};
static cyhal_pdm_pcm_t* cyhal_pdm_pcm_config_structs[CY_IP_MXAUDIOSS_INSTANCES];
static const IRQn_Type cyhal_pdm_pcm_irq_n[] =
{
#if (CY_IP_MXAUDIOSS_INSTANCES == 1 && defined(AUDIOSS_PDM) && AUDIOSS_PDM) // Without index suffix
audioss_interrupt_pdm_IRQn,
#elif (CY_IP_MXAUDIOSS_INSTANCES >= 1 && defined(AUDIOSS0_PDM) && AUDIOSS0_PDM)
audioss_0_interrupt_pdm_IRQn,
#endif
#if (CY_IP_MXAUDIOSS_INSTANCES >= 2 && defined(AUDIOSS1_PDM) && AUDIOSS1_PDM)
audioss_1_interrupt_pdm_IRQn,
#endif
#if (CY_IP_MXS40AUDIOSS_INSTANCES > 2)
#warning Unhandled audioss instance count
#endif
};
static uint8_t cyhal_i2s_get_block_from_irqn(IRQn_Type irqn) {
switch (irqn)
{
#if (CY_CPU_CORTEX_M4)
#if (CY_IP_MXAUDIOSS_INSTANCES == 1 && defined(AUDIOSS_PDM) && AUDIOSS_PDM) // Without index suffix
case audioss_interrupt_pdm_IRQn:
return 0;
#elif (CY_IP_MXAUDIOSS_INSTANCES >= 1 && defined(AUDIOSS0_PDM) && AUDIOSS0_PDM)
case audioss_0_interrupt_pdm_IRQn:
return 0;
#endif
#if (CY_IP_MXAUDIOSS_INSTANCES >= 2 && defined(AUDIOSS1_PDM) && AUDIOSS1_PDM)
case audioss_1_interrupt_pdm_IRQn:
return 1;
#endif
#if (CY_IP_MXS40AUDIOSS_INSTANCES > 2)
#warning Unhandled audioss instance count
#endif
#endif /* (CY_CPU_CORTEX_M4) */
default:
CY_ASSERT(false); // Should never be called with a non-I2S IRQn
return 0;
}
}
static const cy_stc_pdm_pcm_config_t default_pdm_pcm_config =
{
.clkDiv = CY_PDM_PCM_CLK_DIV_BYPASS, // Configured by cyhal_pdm_pcm_init
.mclkDiv = CY_PDM_PCM_CLK_DIV_BYPASS, // Configured by cyhal_pdm_pcm_init
.ckoDiv = 3U, // Configured by cyhal_pdm_pcm_init
.ckoDelay = 0U,
.sincDecRate = 32U, // Configured by cyhal_pdm_pcm_init
.chanSelect = CY_PDM_PCM_OUT_STEREO, // Configured by cyhal_pdm_pcm_init
.chanSwapEnable = false,
.highPassFilterGain = 0U,
.highPassDisable = false,
.softMuteCycles = CY_PDM_PCM_SOFT_MUTE_CYCLES_96,
.softMuteFineGain = 1UL,
.softMuteEnable = false,
.wordLen = CY_PDM_PCM_WLEN_16_BIT, // Configured by cyhal_pdm_pcm_init
.signExtension = true,
.gainLeft = CY_PDM_PCM_BYPASS, // Configured by cyhal_pdm_pcm_init and cyhal_pdm_pcm_set_gain
.gainRight = CY_PDM_PCM_BYPASS, // Configured by cyhal_pdm_pcm_init and cyhal_pdm_pcm_set_gain
.rxFifoTriggerLevel = HALF_FIFO - 1,
.dmaTriggerEnable = false,
.interruptMask = 0UL,
};
static inline void cyhal_pdm_pcm_set_rx_fifo_level(cyhal_pdm_pcm_t *obj, uint8_t fifo_level)
{
PDM_PCM_RX_FIFO_CTL(obj->base) = _VAL2FLD(PDM_RX_FIFO_CTL_TRIGGER_LEVEL, fifo_level - 1);
Cy_PDM_PCM_ClearInterrupt(obj->base, CY_PDM_PCM_INTR_RX_TRIGGER);
}
static bool cyhal_pdm_pcm_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
cyhal_pdm_pcm_t *obj = (cyhal_pdm_pcm_t *)callback_arg;
switch (mode)
{
case CYHAL_SYSPM_CHECK_READY:
obj->pm_transition_ready = Cy_PDM_PCM_GetCurrentState(obj->base) == 0 && !cyhal_pdm_pcm_is_pending(obj);
break;
case CYHAL_SYSPM_CHECK_FAIL:
case CYHAL_SYSPM_AFTER_TRANSITION:
obj->pm_transition_ready = false;
break;
default:
break;
}
return obj->pm_transition_ready;
}
static inline void cyhal_pdm_pcm_increment_async_buffer(cyhal_pdm_pcm_t *obj, size_t increment)
{
CY_ASSERT(obj->async_read_remaining >= increment);
uint32_t saved_intr = cyhal_system_critical_section_enter();
obj->async_read_remaining -= increment;
obj->async_buffer = (obj->async_read_remaining == 0)
? NULL
: (void*)(((uint8_t*) obj->async_buffer) + increment * obj->word_size);
cyhal_system_critical_section_exit(saved_intr);
}
static inline void cyhal_pdm_pcm_try_read_async(cyhal_pdm_pcm_t *obj)
{
size_t read_remaining = obj->async_read_remaining;
cyhal_pdm_pcm_read(obj, obj->async_buffer, &read_remaining);
cyhal_pdm_pcm_increment_async_buffer(obj, read_remaining);
}
static inline cy_rslt_t cyhal_pdm_pcm_dma_start(cyhal_pdm_pcm_t *obj)
{
cy_rslt_t rslt;
size_t transfer_size = HALF_FIFO;
if (obj->async_read_remaining <= HALF_FIFO)
{
transfer_size = obj->async_read_remaining;
// Only want the user callback to be call on the last dma transfer.
cyhal_dma_enable_event(&(obj->dma), CYHAL_DMA_TRANSFER_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);
}
cyhal_dma_cfg_t dma_cfg =
{
.src_addr = (uint32_t)(&(obj->base->RX_FIFO_RD)),
.src_increment = 0,
.dst_addr = (uint32_t)obj->async_buffer,
.dst_increment = 1,
.transfer_width = 8 * obj->word_size,
.length = transfer_size,
.burst_size = 0,
.action = CYHAL_DMA_TRANSFER_BURST,
};
rslt = cyhal_dma_configure(&(obj->dma), &dma_cfg);
if (CY_RSLT_SUCCESS == rslt)
{
cyhal_pdm_pcm_increment_async_buffer(obj, transfer_size);
rslt = cyhal_dma_start_transfer(&(obj->dma));
}
return rslt;
}
static void cyhal_pdm_pcm_hw_irq_handler(void)
{
IRQn_Type irqn = CYHAL_GET_CURRENT_IRQN();
cyhal_pdm_pcm_t *obj = cyhal_pdm_pcm_config_structs[cyhal_i2s_get_block_from_irqn(irqn)];
if (obj != NULL)
{
uint32_t irq_status = Cy_PDM_PCM_GetInterruptStatus(obj->base);
Cy_PDM_PCM_ClearInterrupt(obj->base, irq_status);
cyhal_pdm_pcm_event_t event = CYHAL_PDM_PCM_EVENT_NONE;
if((CY_PDM_PCM_INTR_RX_TRIGGER & irq_status) || (CY_PDM_PCM_INTR_RX_OVERFLOW & irq_status))
{
if (obj->stabilized)
{
if (NULL != obj->async_buffer)
{
if (obj->dma.resource.type == CYHAL_RSC_INVALID)
{
if (obj->async_read_remaining > 0)
{
cyhal_pdm_pcm_try_read_async(obj);
}
if (obj->async_read_remaining == 0)
{
event |= CYHAL_PDM_PCM_ASYNC_COMPLETE;
}
}
else
{
if (obj->async_read_remaining > 0 && !cyhal_dma_is_busy(&(obj->dma)))
{
cy_rslt_t rslt = cyhal_pdm_pcm_dma_start(obj);
CY_UNUSED_PARAMETER(rslt);
CY_ASSERT(CY_RSLT_SUCCESS == rslt);
}
}
if (obj->async_read_remaining == 0)
{
obj->async_buffer = NULL;
if (!(obj->irq_cause & CYHAL_PDM_PCM_RX_HALF_FULL))
{
// Only disable the interrupt mask if the user did not explicitly enable the mask
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) & ~CY_PDM_PCM_INTR_RX_TRIGGER);
}
}
}
if (CY_PDM_PCM_INTR_RX_TRIGGER & irq_status)
{
event |= CYHAL_PDM_PCM_RX_HALF_FULL;
}
}
else
{
// The PDM/PCM block alternates between left and right in stereo.
// To preserve oddness and eveness of left and right, removes an even number of elements.
for (int i = 0; i < STABILIZATION_FS; i++)
{
PDM_PCM_RX_FIFO_RD(obj->base);
}
cyhal_pdm_pcm_set_rx_fifo_level(obj, HALF_FIFO);
if (!cyhal_pdm_pcm_is_pending(obj) && !(CYHAL_PDM_PCM_RX_HALF_FULL & obj->irq_cause))
{
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) & ~CY_PDM_PCM_INTR_RX_TRIGGER);
}
obj->stabilized = true;
}
}
if (CY_PDM_PCM_INTR_RX_NOT_EMPTY & irq_status)
{
event |= CYHAL_PDM_PCM_RX_NOT_EMPTY;
}
if (CY_PDM_PCM_INTR_RX_OVERFLOW & irq_status)
{
event |= CYHAL_PDM_PCM_RX_OVERFLOW;
}
if (CY_PDM_PCM_INTR_RX_UNDERFLOW & irq_status)
{
event |= CYHAL_PDM_PCM_RX_UNDERFLOW;
}
event &= obj->irq_cause;
if (event != CYHAL_PDM_PCM_EVENT_NONE)
{
cyhal_pdm_pcm_event_callback_t callback = (cyhal_pdm_pcm_event_callback_t) obj->callback_data.callback;
if (callback != NULL)
{
callback(obj->callback_data.callback_arg, event);
}
}
}
}
static inline bool cyhal_pdm_pcm_invalid_gain_range(int8_t gain_value)
{
return gain_value < MIN_GAIN || gain_value > MAX_GAIN;
}
static inline cy_en_pdm_pcm_gain_t scale_gain_value(int8_t gain_value)
{
// The hardware use gain rate of 1.5 dB per register increment,
// ranging from -12dB (register value 0x0) to 10.5dB (register value 0xF).
// Need to scale dB range [-24, 21] to register range [0x0, 0xF]
return (cy_en_pdm_pcm_gain_t) ((gain_value + 25) / 3);
}
static inline cy_rslt_t cyhal_pdm_pcm_set_pdl_config_struct(const cyhal_pdm_pcm_cfg_t *cfg, cy_stc_pdm_pcm_config_t *pdl_config)
{
// PDM_CKO = sample_rate * decimation_rate
if (cfg->sample_rate > MAX_SAMPLE_RATE)
{
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM;
}
uint32_t pdm_cko = cfg->sample_rate * cfg->decimation_rate;
uint32_t hf1_freq = Cy_SysClk_ClkHfGetFrequency(CLK_SOURCE_HFCLK1);
// need to use 3 clock dividers to divied hf1_freq to pdm_cko
// divider 0 and 1 have values 1 to 4, divider 2 has values 2 to 16
uint8_t best_div0 = 1, best_div1 = 1, best_div2 = 2;
uint32_t min_error = UINT32_MAX;
for (uint8_t div1 = 1; div1 <= 4; div1++)
{
// start divider 0 at divider 1 's current value
// (div0, div1) = (2,3) is equivalent to (3,2)
for (uint8_t div0 = div1; div0 <= 4; div0++)
{
uint32_t div01_freq = div0 * div1 * pdm_cko;
for (uint8_t div2 = 2; div2 <= 16; div2++)
{
uint32_t computed_hfclk1_freq = div01_freq * div2;
uint32_t error = computed_hfclk1_freq < hf1_freq ? hf1_freq - computed_hfclk1_freq : computed_hfclk1_freq - hf1_freq;
if (error < min_error)
{
best_div0 = div0;
best_div1 = div1;
best_div2 = div2;
min_error = error;
}
}
}
}
pdl_config->clkDiv = (cy_en_pdm_pcm_clk_div_t)(best_div0 - 1);
pdl_config->mclkDiv = (cy_en_pdm_pcm_clk_div_t)(best_div1 - 1);
pdl_config->ckoDiv = best_div2 - 1;
// sinc_rate = decimation_rate / 2
// decimation rate is always valid. The max value for sync rate is 0x7F
pdl_config->sincDecRate = (cfg->decimation_rate) / 2;
switch(cfg->mode)
{
case CYHAL_PDM_PCM_MODE_LEFT:
pdl_config->chanSelect = CY_PDM_PCM_OUT_CHAN_LEFT;
break;
case CYHAL_PDM_PCM_MODE_RIGHT:
pdl_config->chanSelect = CY_PDM_PCM_OUT_CHAN_RIGHT;
break;
case CYHAL_PDM_PCM_MODE_STEREO:
pdl_config->chanSelect = CY_PDM_PCM_OUT_STEREO;
break;
default:
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM;
}
switch(cfg->word_length)
{
case 16:
pdl_config->wordLen = CY_PDM_PCM_WLEN_16_BIT;
break;
case 18:
pdl_config->wordLen = CY_PDM_PCM_WLEN_18_BIT;
break;
case 20:
pdl_config->wordLen = CY_PDM_PCM_WLEN_20_BIT;
break;
case 24:
pdl_config->wordLen = CY_PDM_PCM_WLEN_24_BIT;
break;
default:
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM;
}
if (cyhal_pdm_pcm_invalid_gain_range(cfg->left_gain) || cyhal_pdm_pcm_invalid_gain_range(cfg->right_gain))
{
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM;
}
pdl_config->gainLeft = scale_gain_value(cfg->left_gain);
pdl_config->gainRight = scale_gain_value(cfg->right_gain);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_pdm_pcm_init(cyhal_pdm_pcm_t *obj, cyhal_gpio_t pin_data, cyhal_gpio_t pin_clk,
const cyhal_clock_divider_t *clk_source, const cyhal_pdm_pcm_cfg_t *cfg)
{
CY_ASSERT(NULL != obj);
memset(obj, 0, sizeof(cyhal_pdm_pcm_t));
// On PSoC6, the PDM/PCM block is always driven from HFCLK1.
CY_UNUSED_PARAMETER(clk_source);
/* Explicitly marked not allocated resources as invalid to prevent freeing them. */
obj->resource.type = CYHAL_RSC_INVALID;
obj->pin_data = CYHAL_NC_PIN_VALUE;
obj->pin_clk = CYHAL_NC_PIN_VALUE;
obj->dma.resource.type = CYHAL_RSC_INVALID;
/* Reserve the PDM-PCM */
const cyhal_resource_pin_mapping_t *data_map = CY_UTILS_GET_RESOURCE(pin_data, cyhal_pin_map_audioss_pdm_data);
const cyhal_resource_pin_mapping_t *clk_map = CY_UTILS_GET_RESOURCE(pin_clk, cyhal_pin_map_audioss_pdm_clk);
if ((NULL == data_map) || (NULL == clk_map) || !cyhal_utils_resources_equal(data_map->inst, clk_map->inst))
{
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_PIN;
}
obj->resource = *(data_map->inst);
// There is only one PDM-PCM instance on PSoC6.
CY_ASSERT(obj->resource.type == CYHAL_RSC_PDM && obj->resource.block_num == 0 && obj->resource.channel_num == 0);
obj->base = cyhal_pdm_pcm_base[obj->resource.channel_num];
cy_rslt_t result = cyhal_hwmgr_reserve(&(obj->resource));
if (result != CY_RSLT_SUCCESS)
{
return result;
}
/* Reserve the pdm in pin */
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_utils_reserve_and_connect(pin_data, data_map);
if (result == CY_RSLT_SUCCESS)
obj->pin_data = pin_data;
}
/* Reserve the clk pin */
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_utils_reserve_and_connect(pin_clk, clk_map);
if (result == CY_RSLT_SUCCESS)
obj->pin_clk = pin_clk;
}
if (result == CY_RSLT_SUCCESS)
{
cy_stc_pdm_pcm_config_t pdl_struct = default_pdm_pcm_config;
result = cyhal_pdm_pcm_set_pdl_config_struct(cfg, &pdl_struct);
if (result == CY_RSLT_SUCCESS)
{
result = (cy_rslt_t)Cy_PDM_PCM_Init(obj->base, &pdl_struct);
}
}
if (result == CY_RSLT_SUCCESS)
{
cyhal_pdm_pcm_config_structs[obj->resource.channel_num] = obj;
obj->word_size = cfg->word_length <= 16 ? 2 : 4;
obj->callback_data.callback = NULL;
obj->callback_data.callback_arg = NULL;
obj->irq_cause = CYHAL_PDM_PCM_EVENT_NONE;
obj->stabilized = false;
obj->pm_transition_ready = false;
obj->pm_callback.callback = &cyhal_pdm_pcm_pm_callback,
obj->pm_callback.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
obj->pm_callback.next = NULL;
obj->pm_callback.args = (void*)obj;
obj->pm_callback.ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION;
cyhal_syspm_register_peripheral_callback(&(obj->pm_callback));
cy_stc_sysint_t irqCfg = { cyhal_pdm_pcm_irq_n[obj->resource.channel_num], CYHAL_ISR_PRIORITY_DEFAULT };
Cy_SysInt_Init(&irqCfg, &cyhal_pdm_pcm_hw_irq_handler);
NVIC_EnableIRQ(cyhal_pdm_pcm_irq_n[obj->resource.channel_num]);
cyhal_pdm_pcm_clear(obj);
}
if (result != CY_RSLT_SUCCESS)
{
cyhal_pdm_pcm_free(obj);
}
return result;
}
void cyhal_pdm_pcm_free(cyhal_pdm_pcm_t *obj)
{
CY_ASSERT(NULL != obj);
if (CYHAL_RSC_INVALID != obj->resource.type)
{
cyhal_syspm_unregister_peripheral_callback(&(obj->pm_callback));
Cy_PDM_PCM_DeInit(obj->base);
NVIC_DisableIRQ(cyhal_pdm_pcm_irq_n[obj->resource.channel_num]);
cyhal_hwmgr_free(&(obj->resource));
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
}
cyhal_utils_release_if_used(&(obj->pin_data));
cyhal_utils_release_if_used(&(obj->pin_clk));
if (CYHAL_RSC_INVALID != obj->dma.resource.type)
{
cyhal_dma_free(&(obj->dma));
}
}
cy_rslt_t cyhal_pdm_pcm_start(cyhal_pdm_pcm_t *obj)
{
CY_ASSERT(NULL != obj);
if (obj->pm_transition_ready)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
obj->stabilized = false;
// Remove any element currently in the FIFO. This ensure the correct stabilization time delay.
Cy_PDM_PCM_ClearFifo(obj->base);
Cy_PDM_PCM_Enable(obj->base);
// After Enable is asserted, there is a transition period of about 35-45 sample cycles.
cyhal_pdm_pcm_set_rx_fifo_level(obj, STABILIZATION_FS);
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) | CY_PDM_PCM_INTR_RX_TRIGGER);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_pdm_pcm_stop(cyhal_pdm_pcm_t *obj)
{
CY_ASSERT(NULL != obj);
Cy_PDM_PCM_Disable(obj->base);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_pdm_pcm_set_gain(cyhal_pdm_pcm_t *obj, int8_t gain_left, int8_t gain_right)
{
CY_ASSERT(NULL != obj);
if (cyhal_pdm_pcm_invalid_gain_range(gain_left) || cyhal_pdm_pcm_invalid_gain_range(gain_right))
{
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM;
}
Cy_PDM_PCM_SetGain(obj->base, CY_PDM_PCM_CHAN_LEFT, scale_gain_value(gain_left));
Cy_PDM_PCM_SetGain(obj->base, CY_PDM_PCM_CHAN_RIGHT, scale_gain_value(gain_right));
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_pdm_pcm_clear(cyhal_pdm_pcm_t *obj)
{
CY_ASSERT(NULL != obj);
Cy_PDM_PCM_ClearFifo(obj->base);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_pdm_pcm_read(cyhal_pdm_pcm_t *obj, void *data, size_t *length)
{
CY_ASSERT(NULL != obj);
if (!(obj->stabilized))
{
*length = 0;
}
uint8_t fifo_count = Cy_PDM_PCM_GetNumInFifo(obj->base);
if (*length > fifo_count)
{
*length = fifo_count;
}
size_t i;
if (obj->word_size == 2)
{
uint16_t *buffer = (uint16_t *)data;
for (i = 0; i < *length; i++)
{
buffer[i] = (Cy_PDM_PCM_ReadFifo(obj->base) & 0xFFFF);
}
}
else
{
uint32_t *buffer = (uint32_t *)data;
for (i = 0; i < *length; i++)
{
buffer[i] = (Cy_PDM_PCM_ReadFifo(obj->base));
}
}
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_pdm_pcm_read_async(cyhal_pdm_pcm_t *obj, void *data, size_t length)
{
CY_ASSERT(NULL != obj);
if (obj->pm_transition_ready)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
if (cyhal_pdm_pcm_is_pending(obj))
{
return CYHAL_PDM_PCM_RSLT_ERR_ASYNC_IN_PROGRESS;
}
// Disable PDM interrupts temporarily.
NVIC_DisableIRQ(cyhal_pdm_pcm_irq_n[obj->resource.channel_num]);
obj->async_buffer = data;
obj->async_read_remaining = length;
cy_rslt_t rslt;
if (obj->stabilized)
{
if (obj->dma.resource.type == CYHAL_RSC_INVALID)
{
// read as much as we can, if there are left overs, then set interrupt flags
cyhal_pdm_pcm_try_read_async(obj);
if (0 == obj->async_read_remaining)
{
cyhal_pdm_pcm_event_callback_t callback = (cyhal_pdm_pcm_event_callback_t) obj->callback_data.callback;
if (callback != NULL)
{
obj->async_buffer = NULL;
callback(obj->callback_data.callback_arg, CYHAL_PDM_PCM_ASYNC_COMPLETE);
}
}
rslt = CY_RSLT_SUCCESS;
}
else
{
rslt = cyhal_pdm_pcm_dma_start(obj);
}
}
else
{
// The block has not stabilized
rslt = CY_RSLT_SUCCESS;
}
// Setup interrupt for FIFO half full.
if (0 != obj->async_read_remaining)
{
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) | CY_PDM_PCM_INTR_RX_TRIGGER);
}
NVIC_EnableIRQ(cyhal_pdm_pcm_irq_n[obj->resource.channel_num]);
return rslt;
}
bool cyhal_pdm_pcm_is_pending(cyhal_pdm_pcm_t *obj)
{
CY_ASSERT(NULL != obj);
return obj->async_read_remaining != 0 && obj->async_buffer != NULL;
}
cy_rslt_t cyhal_pdm_pcm_abort_async(cyhal_pdm_pcm_t *obj)
{
CY_ASSERT(NULL != obj);
uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
obj->async_read_remaining = 0;
obj->async_buffer = NULL;
// Only disable the interrupt mask if the user did not explicitly enable the mask
if (!(obj->irq_cause & CYHAL_PDM_PCM_RX_HALF_FULL))
{
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) & ~CY_PDM_PCM_INTR_RX_TRIGGER);
}
cyhal_system_critical_section_exit(savedIntrStatus);
return CY_RSLT_SUCCESS;
}
void cyhal_pdm_pcm_register_callback(cyhal_pdm_pcm_t *obj, cyhal_pdm_pcm_event_callback_t callback, void *callback_arg)
{
uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
obj->callback_data.callback = (cy_israddress) callback;
obj->callback_data.callback_arg = callback_arg;
cyhal_system_critical_section_exit(savedIntrStatus);
}
static inline uint32_t cyhal_pdm_pcm_get_pdl_event_mask(cyhal_pdm_pcm_event_t event)
{
uint32_t mask = 0;
if (event & CYHAL_PDM_PCM_RX_HALF_FULL)
{
mask |= CY_PDM_PCM_INTR_RX_TRIGGER;
}
if (event & CYHAL_PDM_PCM_RX_NOT_EMPTY)
{
mask |= CY_PDM_PCM_INTR_RX_NOT_EMPTY;
}
if (event & CYHAL_PDM_PCM_RX_OVERFLOW)
{
mask |= CY_PDM_PCM_INTR_RX_OVERFLOW;
}
if (event & CYHAL_PDM_PCM_RX_UNDERFLOW)
{
mask |= CY_PDM_PCM_INTR_RX_UNDERFLOW;
}
return mask;
}
void cyhal_pdm_pcm_enable_event(cyhal_pdm_pcm_t *obj, cyhal_pdm_pcm_event_t event, uint8_t intr_priority, bool enable)
{
uint32_t mask = cyhal_pdm_pcm_get_pdl_event_mask(event);
if (enable)
{
obj->irq_cause |= event;
Cy_PDM_PCM_ClearInterrupt(obj->base, mask);
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) | mask);
}
else
{
obj->irq_cause &= ~event;
uint32_t intr_status = cyhal_system_critical_section_enter();
if (!obj->stabilized && cyhal_pdm_pcm_is_pending(obj))
{
// The half full event is used internally by the stabilization code.
// The start() API clear the FIFO, if we have more data than the half FIFO, then PDM/PCM has stabilized.
// This half interrupt mask will automatically cleared by the stabilization code.
// Is an async operation is pending the mask will also be cleared automatically when the async operation finishes
mask &= ~CY_PDM_PCM_INTR_RX_TRIGGER;
}
Cy_PDM_PCM_SetInterruptMask(obj->base, Cy_PDM_PCM_GetInterruptMask(obj->base) & ~mask);
cyhal_system_critical_section_exit(intr_status);
}
NVIC_SetPriority(cyhal_pdm_pcm_irq_n[obj->resource.channel_num], intr_priority);
}
static void cyhal_pdm_pcm_dma_callback(void *callback_arg, cyhal_dma_event_t event)
{
cyhal_pdm_pcm_t *obj = (cyhal_pdm_pcm_t *)callback_arg;
if (obj != NULL)
{
// DMA finished trigger callback
cyhal_pdm_pcm_event_callback_t callback = (cyhal_pdm_pcm_event_callback_t) obj->callback_data.callback;
if (callback != NULL)
{
callback(obj->callback_data.callback_arg, CYHAL_PDM_PCM_ASYNC_COMPLETE);
}
}
}
cy_rslt_t cyhal_pdm_pcm_set_async_mode(cyhal_pdm_pcm_t *obj, cyhal_async_mode_t mode, uint8_t dma_priority)
{
CY_ASSERT(NULL != obj);
if (CYHAL_ASYNC_SW == mode)
{
if (CYHAL_DMA_PRIORITY_DEFAULT != dma_priority)
{
return CYHAL_PDM_PCM_RSLT_ERR_INVALID_CONFIG_PARAM;
}
if (CYHAL_RSC_INVALID != obj->dma.resource.type)
{
cyhal_dma_free(&(obj->dma));
obj->dma.resource.type = CYHAL_RSC_INVALID;
}
}
else if (CYHAL_ASYNC_DMA == mode && CYHAL_RSC_INVALID == obj->dma.resource.type)
{
cy_rslt_t rslt = cyhal_dma_init(&(obj->dma), dma_priority, CYHAL_DMA_DIRECTION_PERIPH2MEM);
if (CY_RSLT_SUCCESS != rslt)
{
return rslt;
}
cyhal_dma_register_callback(&(obj->dma), &cyhal_pdm_pcm_dma_callback, obj);
}
return CY_RSLT_SUCCESS;
}
#if defined(__cplusplus)
}
#endif
#endif /* CY_IP_MXAUDIOSS_INSTANCES */

View File

@ -43,7 +43,7 @@
#include "cyhal_pwm_impl.h"
#include "cyhal_gpio.h"
#include "cyhal_hwmgr.h"
#include "cyhal_interconnect.h"
#include "cyhal_syspm.h"
#include "cyhal_utils.h"
#ifdef CY_IP_MXTCPWM
@ -61,6 +61,7 @@ static const uint32_t US_PER_SEC = 1000000u;
_VAL2FLD(TCPWM_CNT_TR_CTRL2_OVERFLOW_MODE, CY_TCPWM_PWM_TR_CTRL2_CLEAR) | \
_VAL2FLD(TCPWM_CNT_TR_CTRL2_UNDERFLOW_MODE, CY_TCPWM_PWM_TR_CTRL2_SET))
static const cyhal_resource_pin_mapping_t* try_alloc_pwm(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map, size_t count)
{
for (uint32_t i = 0; i < count; i++)
@ -94,7 +95,7 @@ static cy_rslt_t convert_alignment(cyhal_pwm_alignment_t hal_alignment, uint32_t
}
}
cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t pin_compl, cyhal_pwm_alignment_t pwm_alignment, bool continuous, uint32_t dead_time_us, bool invert, const cyhal_clock_divider_t *clk)
cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t pin_compl, cyhal_pwm_alignment_t pwm_alignment, bool continuous, uint32_t dead_time_us, bool invert, const cyhal_clock_t *clk)
{
CY_ASSERT(NULL != obj);
@ -114,13 +115,11 @@ cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t pi
else
{
/* Explicitly marked not allocated resources as invalid to prevent freeing them. */
obj->resource.type = CYHAL_RSC_INVALID;
obj->dedicated_clock = false;
memset(obj, 0, sizeof(cyhal_pwm_t));
obj->resource = *map->inst;
obj->base = CYHAL_TCPWM_DATA[obj->resource.block_num].base;
obj->pin = CYHAL_NC_PIN_VALUE;
obj->pin_compl = CYHAL_NC_PIN_VALUE;
result = cyhal_utils_reserve_and_connect(pin, map);
if (CY_RSLT_SUCCESS == result)
{
@ -154,32 +153,30 @@ cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t pi
en_clk_dst_t pclk = (en_clk_dst_t)(CYHAL_TCPWM_DATA[obj->resource.block_num].clock_dst + obj->resource.channel_num);
if (NULL != clk)
{
obj->clock = *clk;
obj->clock_hz = source_hz / (1 + Cy_SysClk_PeriphGetDivider(clk->div_type, clk->div_num));
if (CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphAssignDivider(pclk, clk->div_type, clk->div_num))
{
result = CYHAL_PWM_RSLT_FAILED_CLOCK_INIT;
}
}
else
else if (CY_RSLT_SUCCESS == (result = cyhal_hwmgr_allocate_clock(&(obj->clock), CY_SYSCLK_DIV_16_BIT, false)))
{
if (CY_RSLT_SUCCESS == (result = cyhal_hwmgr_allocate_clock(&(obj->clock), CY_SYSCLK_DIV_16_BIT, false)))
{
obj->dedicated_clock = true;
uint32_t div = (dead_time_us > 0)
? (((uint64_t)source_hz * dead_time_us) / (US_PER_SEC * MAX_DEAD_TIME_CYCLES)) + 1
: (uint32_t)(1 << (TCPWM_MAX_WIDTH - CYHAL_TCPWM_DATA[obj->resource.block_num].max_count));
obj->dedicated_clock = true;
uint32_t div = (dead_time_us > 0)
? (((uint64_t)source_hz * dead_time_us) / (US_PER_SEC * MAX_DEAD_TIME_CYCLES)) + 1
: (uint32_t)(1 << (TCPWM_MAX_WIDTH - CYHAL_TCPWM_DATA[obj->resource.block_num].max_count));
if (0 == div ||
CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphSetDivider(obj->clock.div_type, obj->clock.div_num, div - 1) ||
CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num) ||
CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphAssignDivider(pclk, obj->clock.div_type, obj->clock.div_num))
{
result = CYHAL_PWM_RSLT_FAILED_CLOCK_INIT;
}
else
{
obj->clock_hz = source_hz / div;
}
if (0 == div ||
CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphSetDivider(obj->clock.div_type, obj->clock.div_num, div - 1) ||
CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num) ||
CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphAssignDivider(pclk, obj->clock.div_type, obj->clock.div_num))
{
result = CYHAL_PWM_RSLT_FAILED_CLOCK_INIT;
}
else
{
obj->clock_hz = source_hz / div;
}
}
}
@ -231,7 +228,7 @@ cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t pi
if (CY_RSLT_SUCCESS == result)
{
cyhal_tcpwm_init_callback_data(&(obj->resource), &(obj->callback_data));
cyhal_tcpwm_init_data(obj);
Cy_TCPWM_PWM_Enable(obj->base, obj->resource.channel_num);
}
else
@ -245,30 +242,8 @@ cy_rslt_t cyhal_pwm_init_adv(cyhal_pwm_t *obj, cyhal_gpio_t pin, cyhal_gpio_t pi
void cyhal_pwm_free(cyhal_pwm_t *obj)
{
CY_ASSERT(NULL != obj);
IRQn_Type irqn = (IRQn_Type)(CYHAL_TCPWM_DATA[obj->resource.block_num].isr_offset + obj->resource.channel_num);
NVIC_DisableIRQ(irqn);
cyhal_utils_release_if_used(&(obj->pin));
cyhal_utils_release_if_used(&(obj->pin_compl));
if (NULL != obj->base)
{
Cy_TCPWM_PWM_Disable(obj->base, obj->resource.channel_num);
cyhal_hwmgr_free(&(obj->resource));
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
}
if (obj->dedicated_clock)
{
cy_en_sysclk_status_t rslt = Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num);
CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
CY_ASSERT(CY_SYSCLK_SUCCESS == rslt);
cyhal_hwmgr_free_clock(&(obj->clock));
obj->dedicated_clock = false;
}
cyhal_tcpwm_free(obj);
}
static cy_rslt_t cyhal_pwm_set_period_and_compare(cyhal_pwm_t *obj, uint32_t period, uint32_t compare)
@ -322,6 +297,11 @@ cy_rslt_t cyhal_pwm_set_duty_cycle(cyhal_pwm_t *obj, float duty_cycle, uint32_t
cy_rslt_t cyhal_pwm_start(cyhal_pwm_t *obj)
{
CY_ASSERT(NULL != obj);
if (cyhal_tcpwm_pm_transition_pending())
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
Cy_TCPWM_PWM_Enable(obj->base, obj->resource.channel_num);
Cy_TCPWM_TriggerReloadOrIndex(obj->base, 1u << obj->resource.channel_num);
return CY_RSLT_SUCCESS;
}

View File

@ -31,6 +31,7 @@
#include "cyhal_gpio.h"
#include "cyhal_interconnect.h"
#include "cyhal_system_impl.h"
#include "cyhal_syspm.h"
#ifdef CY_IP_MXSMIF
@ -140,6 +141,32 @@ static cyhal_qspi_t *cyhal_qspi_get_irq_obj(void)
return cyhal_qspi_config_structs[block];
}
static bool cyhal_qspi_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
cyhal_qspi_t *obj = (cyhal_qspi_t *)callback_arg;
bool allow = true;
switch(mode)
{
case CYHAL_SYSPM_CHECK_READY:
allow &= obj->context.txBufferCounter == 0;
allow &= obj->context.rxBufferCounter == 0;
allow &= Cy_SMIF_GetRxFifoStatus(obj->base) == 0;
allow &= Cy_SMIF_GetTxFifoStatus(obj->base) == 0;
if (allow)
{
obj->pm_transition_pending = true;
}
break;
case CYHAL_SYSPM_AFTER_TRANSITION:
case CYHAL_SYSPM_CHECK_FAIL:
obj->pm_transition_pending = false;
break;
default:
break;
}
return allow;
}
/*******************************************************************************
* Dispatcher Interrrupt Service Routine
*******************************************************************************/
@ -156,11 +183,11 @@ static void cyhal_qspi_cb_wrapper(uint32_t event)
}
/*******************************************************************************
* (Internal) Interrrupt Service Routines
* (Internal) Interrupt Service Routines
*******************************************************************************/
/* Interrupt call, needed for SMIF Async operations */
static void cyhal_qspi_irq_handler()
static void cyhal_qspi_irq_handler(void)
{
cyhal_qspi_t *obj = cyhal_qspi_get_irq_obj();
Cy_SMIF_Interrupt(obj->base, &(obj->context));
@ -170,43 +197,20 @@ static void cyhal_qspi_irq_handler()
* (Internal) QSPI Pin Related Functions
*******************************************************************************/
#ifndef __MBED__
/* Check if pin valid as resource and reserve it */
static cy_rslt_t check_pin_and_reserve(cyhal_gpio_t pin)
static cy_rslt_t check_pin_and_reserve(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *mapping)
{
cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(pin);
return cyhal_hwmgr_reserve(&pin_rsc);
}
/* Checks what pins are provided by user and calls check_pin_and_reserve for each */
static cy_rslt_t make_pin_reservations(cyhal_qspi_t *obj)
{
cy_rslt_t result;
/* reserve the SCLK pin */
result = check_pin_and_reserve(obj->pin_sclk);
/* reserve the ssel pin */
if (result == CY_RSLT_SUCCESS)
{
result = check_pin_and_reserve(obj->pin_ssel);
}
/* reserve the io pins */
for (uint8_t i = 0; (i < MAX_DATA_PINS) && (result == CY_RSLT_SUCCESS); i++)
{
if (NC != obj->pin_ios[i])
{
result = check_pin_and_reserve(obj->pin_ios[i]);
}
}
// Mbed calls qspi_init multiple times without calling qspi_free to update the QSPI frequency/mode.
// As a result, we can't worry about resource reservation if running through mbed.
#ifndef __MBED__
cy_rslt_t result = cyhal_utils_reserve_and_connect(pin, mapping);
#else
cy_rslt_t result = cyhal_connect_pin(mapping);
#endif
return result;
}
#endif
/*******************************************************************************
* (Internal) QSPI Config Related Functions
*******************************************************************************/
@ -425,7 +429,7 @@ static const cyhal_resource_pin_mapping_t *get_slaveselect(cyhal_gpio_t ssel, cy
}
/* Based on data pins chosen, determines SMIF data select parameter */
static const cyhal_resource_pin_mapping_t *get_dataselect(cyhal_gpio_t io0, cy_en_smif_data_select_t *data_select)
static const cyhal_resource_pin_mapping_t *get_dataselect(cyhal_gpio_t io0, cy_en_smif_data_select_t *data_select, uint8_t *offset)
{
bool pin_found = false;
const cyhal_resource_pin_mapping_t *pin_mapping = CY_UTILS_GET_RESOURCE(io0, cyhal_pin_map_smif_spi_data0);
@ -433,6 +437,7 @@ static const cyhal_resource_pin_mapping_t *get_dataselect(cyhal_gpio_t io0, cy_e
{
pin_found = true;
*data_select = CY_SMIF_DATA_SEL0;
*offset = 0;
}
if (!pin_found)
{
@ -441,6 +446,7 @@ static const cyhal_resource_pin_mapping_t *get_dataselect(cyhal_gpio_t io0, cy_e
{
pin_found = true;
*data_select = CY_SMIF_DATA_SEL1;
*offset = 2;
}
}
#if DATA8_PRESENT
@ -451,6 +457,7 @@ static const cyhal_resource_pin_mapping_t *get_dataselect(cyhal_gpio_t io0, cy_e
{
pin_found = true;
*data_select = CY_SMIF_DATA_SEL2;
*offset = 4;
}
}
if (!pin_found)
@ -460,6 +467,7 @@ static const cyhal_resource_pin_mapping_t *get_dataselect(cyhal_gpio_t io0, cy_e
{
pin_found = true;
*data_select = CY_SMIF_DATA_SEL3;
*offset = 6;
}
}
#endif
@ -484,8 +492,6 @@ cy_rslt_t cyhal_qspi_init(
memset(obj, 0, sizeof(cyhal_qspi_t));
obj->resource.type = CYHAL_RSC_INVALID;
cy_en_smif_slave_select_t slave_select = CY_SMIF_SLAVE_SELECT_0;
cy_en_smif_data_select_t data_select = CY_SMIF_DATA_SEL0;
cyhal_qspi_bus_width_t max_width;
obj->pin_sclk = sclk;
@ -501,173 +507,83 @@ cy_rslt_t cyhal_qspi_init(
cy_rslt_t result = check_user_pins(obj, &max_width);
const cyhal_resource_pin_mapping_t *ssel_map = NULL;
const cyhal_resource_pin_mapping_t *io0_map = NULL;
const cyhal_resource_pin_mapping_t *io1_map = NULL;
const cyhal_resource_pin_mapping_t *io2_map = NULL;
const cyhal_resource_pin_mapping_t *io3_map = NULL;
const cyhal_resource_pin_mapping_t *io4_map = NULL;
const cyhal_resource_pin_mapping_t *io5_map = NULL;
const cyhal_resource_pin_mapping_t *io6_map = NULL;
const cyhal_resource_pin_mapping_t *io7_map = NULL;
uint8_t pin_offset = 0;
const cyhal_resource_pin_mapping_t *sclk_map = CY_UTILS_GET_RESOURCE(sclk, cyhal_pin_map_smif_spi_clk);
if (NULL == sclk_map)
const cyhal_resource_pin_mapping_t *ssel_map = get_slaveselect(ssel, &(obj->slave_select));
const cyhal_resource_pin_mapping_t *io_maps[8] = { NULL };
const size_t data_pin_map_sizes[MAX_DATA_PINS - 1] = // Must compute sizes here since we can't get them from the map pointers
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
if (CY_RSLT_SUCCESS == result)
{
ssel_map = get_slaveselect(ssel, &slave_select);
if (ssel_map == NULL)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
else
{
obj->slave_select = slave_select;
}
}
if (CY_RSLT_SUCCESS == result)
{
io0_map = get_dataselect(obj->pin_ios[0], &data_select);
if (io0_map == NULL)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
else
{
obj->data_select = data_select;
}
}
if (CY_RSLT_SUCCESS == result)
{
switch (data_select)
{
case CY_SMIF_DATA_SEL0:
if (max_width >= CYHAL_QSPI_CFG_BUS_DUAL)
{
io1_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[1], cyhal_pin_map_smif_spi_data1);
if (NULL == io1_map)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
if (max_width >= CYHAL_QSPI_CFG_BUS_QUAD)
{
io2_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[2], cyhal_pin_map_smif_spi_data2);
io3_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[3], cyhal_pin_map_smif_spi_data3);
if ((NULL == io2_map) || (NULL == io3_map))
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
sizeof(cyhal_pin_map_smif_spi_data1) / sizeof(cyhal_resource_pin_mapping_t),
sizeof(cyhal_pin_map_smif_spi_data2) / sizeof(cyhal_resource_pin_mapping_t),
sizeof(cyhal_pin_map_smif_spi_data3) / sizeof(cyhal_resource_pin_mapping_t),
#if DATA8_PRESENT
if (max_width >= CYHAL_QSPI_CFG_BUS_OCTAL)
{
io4_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[4], cyhal_pin_map_smif_spi_data4);
io5_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[5], cyhal_pin_map_smif_spi_data5);
io6_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[6], cyhal_pin_map_smif_spi_data6);
io7_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[7], cyhal_pin_map_smif_spi_data7);
if ((NULL == io4_map) || (NULL == io5_map) || (NULL == io6_map) || (NULL == io7_map))
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
sizeof(cyhal_pin_map_smif_spi_data4) / sizeof(cyhal_resource_pin_mapping_t),
sizeof(cyhal_pin_map_smif_spi_data5) / sizeof(cyhal_resource_pin_mapping_t),
sizeof(cyhal_pin_map_smif_spi_data6) / sizeof(cyhal_resource_pin_mapping_t),
sizeof(cyhal_pin_map_smif_spi_data7) / sizeof(cyhal_resource_pin_mapping_t),
#endif
break;
case CY_SMIF_DATA_SEL1:
if (max_width >= CYHAL_QSPI_CFG_BUS_DUAL)
{
io1_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[1], cyhal_pin_map_smif_spi_data3);
if (NULL == io1_map)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
break;
};
const cyhal_resource_pin_mapping_t *data_pin_maps[MAX_DATA_PINS - 1] = // Not used to get the map for data pin 0
{
cyhal_pin_map_smif_spi_data1,
cyhal_pin_map_smif_spi_data2,
cyhal_pin_map_smif_spi_data3,
#if DATA8_PRESENT
case CY_SMIF_DATA_SEL2:
if (max_width >= CYHAL_QSPI_CFG_BUS_DUAL)
{
io1_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[1], cyhal_pin_map_smif_spi_data5);
if (NULL == io1_map)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
if (max_width >= CYHAL_QSPI_CFG_BUS_QUAD)
{
io2_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[2], cyhal_pin_map_smif_spi_data6);
io3_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[3], cyhal_pin_map_smif_spi_data7);
if ((NULL == io2_map) || (NULL == io3_map))
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
break;
case CY_SMIF_DATA_SEL3:
if (max_width >= CYHAL_QSPI_CFG_BUS_DUAL)
{
io1_map = CY_UTILS_GET_RESOURCE(obj->pin_ios[1], cyhal_pin_map_smif_spi_data7);
if (NULL == io1_map)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
break;
cyhal_pin_map_smif_spi_data4,
cyhal_pin_map_smif_spi_data5,
cyhal_pin_map_smif_spi_data6,
cyhal_pin_map_smif_spi_data7,
#endif
default:
result = CYHAL_QSPI_RSLT_ERR_DATA_SEL;
}
}
/* Check that all pins are belongs to same instance */
};
if (CY_RSLT_SUCCESS == result)
{
if (sclk_map->inst->block_num != ssel_map->inst->block_num ||
sclk_map->inst->block_num != io0_map->inst->block_num)
io_maps[0] = get_dataselect(obj->pin_ios[0], &(obj->data_select), &pin_offset);
if (NULL == sclk_map || NULL == ssel_map || NULL == io_maps[0] ||
!cyhal_utils_resources_equal_all(3, sclk_map->inst, ssel_map->inst, io_maps[0]->inst))
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
}
}
if (CY_RSLT_SUCCESS == result && (max_width >= CYHAL_QSPI_CFG_BUS_DUAL))
if (CY_RSLT_SUCCESS == result)
{
if (sclk_map->inst->block_num != io1_map->inst->block_num)
/* Check that all data pins are valid and belong to same instance */
for (uint8_t i = 1; i < max_width; i++)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
io_maps[i] = cyhal_utils_get_resource(obj->pin_ios[i], data_pin_maps[i - 1 + pin_offset], data_pin_map_sizes[i - 1 + pin_offset]);
if (NULL == io_maps[i] || !cyhal_utils_resources_equal(sclk_map->inst, io_maps[i]->inst))
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
break;
}
}
}
/* Pins io2 and io3 are only available in CY_SMIF_DATA_SEL0 and CY_SMIF_DATA_SEL2 modes */
if ((CY_RSLT_SUCCESS == result) && ((data_select == CY_SMIF_DATA_SEL0) || (data_select == CY_SMIF_DATA_SEL2))
&& (max_width >= CYHAL_QSPI_CFG_BUS_QUAD))
if (CY_RSLT_SUCCESS == result)
{
if ((sclk_map->inst->block_num != io2_map->inst->block_num) ||
(sclk_map->inst->block_num != io3_map->inst->block_num))
/* reserve the SCLK pin */
result = check_pin_and_reserve(obj->pin_sclk, sclk_map);
/* reserve the ssel pin */
if (result == CY_RSLT_SUCCESS)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
result = check_pin_and_reserve(obj->pin_ssel, ssel_map);
}
}
/* Pins io4, io5, io6 and io7 are only available in CY_SMIF_DATA_SEL0 mode */
if ((CY_RSLT_SUCCESS == result) && (data_select == CY_SMIF_DATA_SEL0) && (max_width >= CYHAL_QSPI_CFG_BUS_OCTAL))
{
if ((sclk_map->inst->block_num != io4_map->inst->block_num) ||
(sclk_map->inst->block_num != io5_map->inst->block_num) ||
(sclk_map->inst->block_num != io6_map->inst->block_num) ||
(sclk_map->inst->block_num != io7_map->inst->block_num))
/* reserve the io pins */
for (uint8_t i = 0; (i < MAX_DATA_PINS) && (result == CY_RSLT_SUCCESS); i++)
{
result = CYHAL_QSPI_RSLT_ERR_PIN;
if (NC != obj->pin_ios[i])
{
result = check_pin_and_reserve(obj->pin_ios[i], io_maps[i]);
}
}
}
#ifndef __MBED__
// Mbed calls qspi_init multiple times without calling qspi_free to update the QSPI frequency/mode.
// As a result, we won't worry about resource reservation if running through mbed.
if (CY_RSLT_SUCCESS == result)
{
result = make_pin_reservations(obj);
}
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_hwmgr_reserve(sclk_map->inst);
@ -678,45 +594,6 @@ cy_rslt_t cyhal_qspi_init(
{
obj->resource = *sclk_map->inst;
obj->base = smif_base_addresses[obj->resource.block_num];
result = cyhal_connect_pin(sclk_map);
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(ssel_map);
}
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(io0_map);
}
if ((CY_RSLT_SUCCESS == result) && (max_width >= CYHAL_QSPI_CFG_BUS_DUAL))
{
result = cyhal_connect_pin(io1_map);
}
}
if ((CY_RSLT_SUCCESS == result) && ((data_select == CY_SMIF_DATA_SEL0) || (data_select == CY_SMIF_DATA_SEL2)) &&
(max_width >= CYHAL_QSPI_CFG_BUS_QUAD))
{
result = cyhal_connect_pin(io2_map);
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(io3_map);
}
}
if ((CY_RSLT_SUCCESS == result) && (data_select == CY_SMIF_DATA_SEL0) && (max_width >= CYHAL_QSPI_CFG_BUS_OCTAL))
{
result = cyhal_connect_pin(io4_map);
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(io5_map);
}
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(io6_map);
}
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(io7_map);
}
}
/* cyhal_qspi_set_frequency should be called here.
@ -731,13 +608,20 @@ cy_rslt_t cyhal_qspi_init(
if (CY_RSLT_SUCCESS == result)
{
Cy_SMIF_SetDataSelect(obj->base, slave_select, data_select);
Cy_SMIF_SetDataSelect(obj->base, obj->slave_select, obj->data_select);
Cy_SMIF_Enable(obj->base, &obj->context);
obj->callback_data.callback = NULL;
obj->callback_data.callback_arg = NULL;
obj->irq_cause = CYHAL_QSPI_EVENT_NONE;
cyhal_qspi_config_structs[obj->resource.block_num] = obj;
obj->pm_transition_pending = false;
obj->pm_callback.callback = &cyhal_qspi_pm_callback;
obj->pm_callback.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
obj->pm_callback.args = obj;
obj->pm_callback.next = NULL;
obj->pm_callback.ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION;
cyhal_syspm_register_peripheral_callback(&(obj->pm_callback));
cy_stc_sysint_t irqCfg = { CYHAL_QSPI_IRQ_N[obj->resource.block_num], CYHAL_ISR_PRIORITY_DEFAULT };
Cy_SysInt_Init(&irqCfg, cyhal_qspi_irq_handler);
@ -758,7 +642,7 @@ void cyhal_qspi_free(cyhal_qspi_t *obj)
{
IRQn_Type irqn = CYHAL_QSPI_IRQ_N[obj->resource.block_num];
NVIC_DisableIRQ(irqn);
cyhal_syspm_unregister_peripheral_callback(&(obj->pm_callback));
if (obj->base != NULL)
{
Cy_SMIF_DeInit(obj->base);
@ -787,6 +671,10 @@ cy_rslt_t cyhal_qspi_set_frequency(cyhal_qspi_t *obj, uint32_t hz)
/* no restriction on the value of length. This function splits the read into multiple chunked transfers. */
cy_rslt_t cyhal_qspi_read(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, void *data, size_t *length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t status = CY_RSLT_SUCCESS;
uint32_t chunk = 0;
size_t read_bytes = *length;
@ -833,6 +721,10 @@ cy_rslt_t cyhal_qspi_read(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command
cy_rslt_t cyhal_qspi_read_async(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, void *data, size_t *length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t status = qspi_command_transfer(obj, command, command->address.value, false);
if (CY_RSLT_SUCCESS == status)
@ -854,6 +746,10 @@ cy_rslt_t cyhal_qspi_read_async(cyhal_qspi_t *obj, const cyhal_qspi_command_t *c
/* length can be up to 65536. */
cy_rslt_t cyhal_qspi_write(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, const void *data, size_t *length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t status = qspi_command_transfer(obj, command, command->address.value, false);
if (CY_RSLT_SUCCESS == status)
@ -876,6 +772,10 @@ cy_rslt_t cyhal_qspi_write(cyhal_qspi_t *obj, const cyhal_qspi_command_t *comman
/* length can be up to 65536. */
cy_rslt_t cyhal_qspi_write_async(cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, const void *data, size_t *length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t status = qspi_command_transfer(obj, command, command->address.value, false);
if (CY_RSLT_SUCCESS == status)
@ -898,6 +798,10 @@ cy_rslt_t cyhal_qspi_transfer(
cyhal_qspi_t *obj, const cyhal_qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data,
size_t rx_size)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t status = CY_RSLT_SUCCESS;
if ((tx_data == NULL || tx_size == 0) && (rx_data == NULL || rx_size == 0))
@ -933,7 +837,7 @@ void cyhal_qspi_register_callback(cyhal_qspi_t *obj, cyhal_qspi_event_callback_t
obj->irq_cause = CYHAL_QSPI_EVENT_NONE;
}
void cyhal_qspi_enable_event(cyhal_qspi_t *obj, cyhal_qspi_event_t event, uint8_t intrPriority, bool enable)
void cyhal_qspi_enable_event(cyhal_qspi_t *obj, cyhal_qspi_event_t event, uint8_t intr_priority, bool enable)
{
if (enable)
{
@ -945,7 +849,7 @@ void cyhal_qspi_enable_event(cyhal_qspi_t *obj, cyhal_qspi_event_t event, uint8_
}
IRQn_Type irqn = CYHAL_QSPI_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
}
#if defined(__cplusplus)

View File

@ -86,7 +86,7 @@ static cyhal_rtc_event_callback_t cyhal_rtc_user_handler;
static void *cyhal_rtc_handler_arg;
/* Returns century portion of BREG register used to store century info */
static inline uint16_t get_rtc_century()
static inline uint16_t get_rtc_century(void)
{
return _FLD2VAL(CYHAL_RTC_BREG_CENTURY, CYHAL_RTC_BREG);
}
@ -99,7 +99,7 @@ static inline void set_rtc_century(uint16_t century)
}
/* Returns state portion of BREG register used to store century info */
static inline uint16_t get_rtc_state()
static inline uint16_t get_rtc_state(void)
{
return _FLD2VAL(CYHAL_RTC_BREG_STATE, CYHAL_RTC_BREG);
}
@ -117,6 +117,7 @@ static void cyhal_rtc_internal_handler(void)
Cy_RTC_Interrupt(dst, NULL != dst);
}
/* Override weak function from PDL */
void Cy_RTC_Alarm1Interrupt(void)
{
if (NULL != cyhal_rtc_user_handler)
@ -313,6 +314,36 @@ cy_rslt_t cyhal_rtc_set_alarm(cyhal_rtc_t *obj, const struct tm *time, cyhal_ala
return (cy_rslt_t)Cy_RTC_SetAlarmDateAndTime(&alarm, CY_RTC_ALARM_1);
}
cy_rslt_t cyhal_rtc_set_alarm_by_seconds(cyhal_rtc_t *obj, const uint32_t seconds)
{
CY_ASSERT(NULL != obj);
static const uint32_t SECONDS_IN_YEAR = 365*24*60*60; // 31,536,000
// Note: The hardware does not support year matching so return error if
// seconds is greater than 1 year in the future
if(seconds > SECONDS_IN_YEAR)
return CY_RSLT_RTC_BAD_ARGUMENT;
struct tm now;
uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
cyhal_rtc_read(obj, &now);
cyhal_system_critical_section_exit(savedIntrStatus);
time_t future_time_t = mktime(&now) + seconds;
struct tm* future = localtime(&future_time_t);
static const cyhal_alarm_active_t active = {
.en_sec = CY_RTC_ALARM_ENABLE,
.en_min = CY_RTC_ALARM_ENABLE,
.en_hour = CY_RTC_ALARM_ENABLE,
.en_day = CY_RTC_ALARM_ENABLE,
.en_date = CY_RTC_ALARM_ENABLE,
.en_month = CY_RTC_ALARM_ENABLE
};
return cyhal_rtc_set_alarm(obj, future, active);
}
void cyhal_rtc_register_callback(cyhal_rtc_t *obj, cyhal_rtc_event_callback_t callback, void *callback_arg)
{
CY_ASSERT(NULL != obj);

View File

@ -23,6 +23,8 @@
*******************************************************************************/
#include "cyhal_scb_common.h"
#include "cyhal_hwmgr.h"
#include "cyhal_syspm.h"
#ifdef CY_IP_MXSCB
@ -135,7 +137,10 @@ const IRQn_Type CYHAL_SCB_IRQ_N[CY_IP_MXSCB_INSTANCES] =
#endif
};
void *cyhal_scb_config_structs[CY_IP_MXSCB_INSTANCES];
/** The configuration structs for the resource in use on each SCB block */
static void *cyhal_scb_config_structs[CY_IP_MXSCB_INSTANCES];
/** The callback to use for each scb instance */
static bool (*cyhal_scb_config_pm_callback[CY_IP_MXSCB_INSTANCES]) (void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode);
uint8_t cyhal_scb_get_block_from_irqn(IRQn_Type irqn) {
switch (irqn)
@ -211,6 +216,161 @@ uint8_t cyhal_scb_get_block_from_irqn(IRQn_Type irqn) {
}
}
void *cyhal_scb_get_irq_obj(void)
{
IRQn_Type irqn = CYHAL_GET_CURRENT_IRQN();
uint8_t block = cyhal_scb_get_block_from_irqn(irqn);
return cyhal_scb_config_structs[block];
}
/* Peripheral clock values for different I2C speeds according PDL API Reference Guide */
/* Must be between 1.55 MHz and 12.8 MHz for running i2c master at 100KHz */
#define SCB_PERI_CLOCK_SLAVE_STD 8000000
/* Must be between 7.82 MHz and 15.38 MHz for running i2c master at 400KHz */
#define SCB_PERI_CLOCK_SLAVE_FST 12500000
/* Must be between 15.84 MHz and 89.0 MHz for running i2c master at 1MHz */
#define SCB_PERI_CLOCK_SLAVE_FSTP 50000000
/* Must be between 1.55 MHz and 3.2 MHz for running i2c slave at 100KHz */
#define SCB_PERI_CLOCK_MASTER_STD 2000000
/* Must be between 7.82 MHz and 10 MHz for running i2c slave at 400KHz */
#define SCB_PERI_CLOCK_MASTER_FST 8500000
/* Must be between 14.32 MHz and 25.8 MHz for running i2c slave at 1MHz */
#define SCB_PERI_CLOCK_MASTER_FSTP 20000000
uint32_t cyhal_i2c_set_peri_divider(CySCB_Type *base, uint32_t block_num, cyhal_clock_t *clock, uint32_t freq, bool is_slave)
{
/* Return the actual data rate on success, 0 otherwise */
uint32_t peri_freq = 0;
if (freq == 0)
{
return 0;
}
if (freq <= CY_SCB_I2C_STD_DATA_RATE)
{
peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_STD : SCB_PERI_CLOCK_MASTER_STD;
}
else if (freq <= CY_SCB_I2C_FST_DATA_RATE)
{
peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_FST : SCB_PERI_CLOCK_MASTER_FST;
}
else if (freq <= CY_SCB_I2C_FSTP_DATA_RATE)
{
peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_FSTP : SCB_PERI_CLOCK_MASTER_FSTP;
}
else
{
return 0;
}
cy_en_sysclk_status_t status = Cy_SysClk_PeriphAssignDivider((en_clk_dst_t)((uint8_t)PCLK_SCB0_CLOCK + block_num), clock->div_type, clock->div_num);
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphDisableDivider(clock->div_type, clock->div_num);
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphSetDivider(clock->div_type, clock->div_num, cyhal_divider_value(peri_freq, 0u));
if (status == CY_SYSCLK_SUCCESS)
status = Cy_SysClk_PeriphEnableDivider(clock->div_type, clock->div_num);
CY_ASSERT(CY_SYSCLK_SUCCESS == status);
return (is_slave)
? Cy_SCB_I2C_GetDataRate(base, Cy_SysClk_PeriphGetFrequency(clock->div_type, clock->div_num))
: Cy_SCB_I2C_SetDataRate(base, freq, Cy_SysClk_PeriphGetFrequency(clock->div_type, clock->div_num));
}
const cyhal_resource_pin_mapping_t* cyhal_find_scb_map(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map, size_t count)
{
for (size_t i = 0; i < count; i++)
{
if (pin == pin_map[i].pin && CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(pin_map[i].inst))
{
cyhal_hwmgr_free(pin_map[i].inst);
return &pin_map[i];
}
}
return NULL;
}
static bool cyhal_scb_pm_transition_pending_value = false;
bool cyhal_scb_pm_transition_pending(void)
{
return cyhal_scb_pm_transition_pending_value;
}
static bool cyhal_scb_pm_callback_index(uint8_t index, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
{
void *obj = cyhal_scb_config_structs[index];
cyhal_scb_instance_pm_callback callback = cyhal_scb_config_pm_callback[index];
return ((NULL != obj) && (callback != NULL)) ? callback(obj, state, pdl_mode) : true;
}
static bool cyhal_scb_pm_callback_common(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
CY_UNUSED_PARAMETER(callback_arg);
bool allow = true;
cy_en_syspm_callback_mode_t pdl_mode = cyhal_utils_convert_haltopdl_pm_mode(mode);
for (uint8_t instance_idx = 0; instance_idx < CY_IP_MXSCB_INSTANCES; instance_idx++)
{
allow = cyhal_scb_pm_callback_index(instance_idx, state, pdl_mode);
if (!allow && mode == CYHAL_SYSPM_CHECK_READY)
{
for (uint8_t revert_idx = 0; revert_idx < instance_idx; revert_idx++)
{
cyhal_scb_pm_callback_index(revert_idx, state, CY_SYSPM_CHECK_FAIL);
}
break;
}
}
if (mode == CYHAL_SYSPM_CHECK_FAIL || mode == CYHAL_SYSPM_AFTER_TRANSITION)
{
cyhal_scb_pm_transition_pending_value = false;
}
else if (mode == CYHAL_SYSPM_CHECK_READY && allow)
{
cyhal_scb_pm_transition_pending_value = true;
}
return allow;
}
cyhal_syspm_callback_data_t cyhal_scb_pm_callback_data =
{
.callback = &cyhal_scb_pm_callback_common,
.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
.args = NULL,
.next = NULL,
.ignore_modes = (cyhal_syspm_callback_mode_t)0,
};
void cyhal_scb_update_instance_data(uint8_t block_num, void *obj, cyhal_scb_instance_pm_callback pm_callback)
{
cyhal_scb_config_structs[block_num] = obj;
cyhal_scb_config_pm_callback[block_num] = pm_callback;
int count = 0;
for (uint8_t i = 0; i < CY_IP_MXSCB_INSTANCES; i++)
{
if (cyhal_scb_config_structs[i])
{
if (count == 1)
{
return;
}
count++;
}
}
if (count == 0)
{
CY_ASSERT(obj == NULL);
cyhal_syspm_unregister_peripheral_callback(&cyhal_scb_pm_callback_data);
}
else if (count == 1 && obj != NULL)
{
cyhal_syspm_register_peripheral_callback(&cyhal_scb_pm_callback_data);
}
}
#if defined(__cplusplus)
}
#endif

View File

@ -31,10 +31,11 @@
#include "cyhal_sdhc.h"
#include "cyhal_sdio.h"
#include "cyhal_gpio.h"
#include "cyhal_clock.h"
#include "cyhal_hwmgr.h"
#include "cyhal_utils.h"
#include "cyhal_system_impl.h"
#include "cyhal_interconnect.h"
#include "cyhal_system.h"
#include "cyhal_syspm.h"
#ifdef CY_IP_MXSDHC
@ -110,12 +111,12 @@ extern "C"
#else
#define IO_VOLT_SEL_PRESENT 0
#endif
#if (defined(SDHC_CHIP_TOP_CARD_IF_POWER_EN_PRESENT) && (SDHC_CHIP_TOP_CARD_IF_POWER_EN_PRESENT)) || \
(defined(SDHC0_CHIP_TOP_CARD_IF_POWER_EN_PRESENT) && (SDHC0_CHIP_TOP_CARD_IF_POWER_EN_PRESENT)) || \
(defined(SDHC1_CHIP_TOP_CARD_IF_POWER_EN_PRESENT) && (SDHC1_CHIP_TOP_CARD_IF_POWER_EN_PRESENT))
#define CARD_IF_POWER_EN_PRESENT 1
#if (defined(SDHC_CHIP_TOP_CARD_IF_PWR_EN_PRESENT) && (SDHC_CHIP_TOP_CARD_IF_PWR_EN_PRESENT)) || \
(defined(SDHC0_CHIP_TOP_CARD_IF_PWR_EN_PRESENT) && (SDHC0_CHIP_TOP_CARD_IF_PWR_EN_PRESENT)) || \
(defined(SDHC1_CHIP_TOP_CARD_IF_PWR_EN_PRESENT) && (SDHC1_CHIP_TOP_CARD_IF_PWR_EN_PRESENT))
#define CARD_IF_PWR_EN_PRESENT 1
#else
#define CARD_IF_POWER_EN_PRESENT 0
#define CARD_IF_PWR_EN_PRESENT 0
#endif
#if (defined(SDHC_CHIP_TOP_CARD_EMMC_RESET_PRESENT) && (SDHC_CHIP_TOP_CARD_EMMC_RESET_PRESENT)) || \
(defined(SDHC0_CHIP_TOP_CARD_EMMC_RESET_PRESENT) && (SDHC0_CHIP_TOP_CARD_EMMC_RESET_PRESENT)) || \
@ -133,15 +134,6 @@ extern "C"
#define CYHAL_SDIO_DS_CB_ORDER (0U)
#endif /* !defined(CYHAL_SDIO_DS_CB_ORDER) */
/* Defines for mapping sdhc events on interrupts */
#define SDHC_EVENTS_NUM (12U)
#define SDHC_EVENTS_MAP_NUM (2U)
#define SDHC_EVENT (0U)
#define SDHC_ISR (1U)
/* List of available SDHC instances */
static SDHC_Type * const CYHAL_SDHC_BASE_ADDRESSES[CY_IP_MXSDHC_INSTANCES] =
{
@ -204,9 +196,13 @@ static uint8_t cyhal_sd_get_block_from_irqn(IRQn_Type irqn)
static void *cyhal_sd_config_structs[CY_IP_MXSDHC_INSTANCES];
/* Defines for mapping sdhc events on interrupts */
#define SDHC_EVENTS_NUM (12U)
#define SDHC_EVENT (0U)
#define SDHC_ISR (1U)
/* Structure to map SDHC events on SDHC interrupts */
static const uint32_t eventMap[SDHC_EVENTS_NUM][SDHC_EVENTS_MAP_NUM] =
static const uint32_t eventMap[SDHC_EVENTS_NUM][CYHAL_MAP_COLUMNS] =
{
{ (uint32_t)CYHAL_SDHC_CMD_COMPLETE, (uint32_t)CY_SD_HOST_CMD_COMPLETE},
{ (uint32_t)CYHAL_SDHC_XFER_COMPLETE, (uint32_t)CY_SD_HOST_XFER_COMPLETE },
@ -224,31 +220,20 @@ static const uint32_t eventMap[SDHC_EVENTS_NUM][SDHC_EVENTS_MAP_NUM] =
static cy_rslt_t setup_pin(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pinmap, size_t count, cyhal_gpio_t *objRef)
{
cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(pin);
cy_rslt_t result = cyhal_hwmgr_reserve(&pin_rsc);
cy_rslt_t result;
const cyhal_resource_pin_mapping_t *map = cyhal_utils_get_resource(pin, pinmap, count);
if (result == CY_RSLT_SUCCESS)
if (map == NULL)
{
const cyhal_resource_pin_mapping_t *map = cyhal_utils_get_resource(pin, pinmap, count);
if (map == NULL)
{
result = CYHAL_SDHC_RSLT_ERR_PIN;
}
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_connect_pin(map);
}
result = CYHAL_SDHC_RSLT_ERR_PIN;
}
else
{
result = cyhal_utils_reserve_and_connect(pin, map);
if (result == CY_RSLT_SUCCESS)
{
*objRef = pin;
}
else
{
cyhal_hwmgr_free(&pin_rsc);
}
}
return result;
@ -260,21 +245,18 @@ static bool isTransferInProcess = false;
/* Internal functions */
static cy_en_sd_host_status_t cyhal_sd_host_polltransfercomplete(SDHC_Type *base, const uint16_t delay);
static cy_en_sd_host_status_t cyhal_sd_host_pollcmdcomplete(SDHC_Type *base);
static cy_en_sd_host_status_t cyhal_sd_host_sdcardchangeclock(SDHC_Type *base, uint32_t instance_num, uint32_t frequency);
static cy_rslt_t cyhal_sd_host_sdcardchangeclock(SDHC_Type *base, uint32_t instance_num, uint32_t frequency);
static cy_en_sd_host_bus_width_t convert_buswidth(uint8_t stopbits);
static cy_en_syspm_status_t cyhal_sdio_syspm_callback(cy_stc_syspm_callback_params_t *params,
cy_en_syspm_callback_mode_t mode);
static cyhal_sdhc_event_t get_event_from_isr(uint32_t asserted_interrupt);
static bool cyhal_sdio_syspm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
/*******************************************************************************
* Deep Sleep Callback Service Routine
*******************************************************************************/
static cy_en_syspm_status_t cyhal_sdio_syspm_callback(cy_stc_syspm_callback_params_t *params,
cy_en_syspm_callback_mode_t mode)
static bool cyhal_sdio_syspm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
cy_en_syspm_status_t retVal = CY_SYSPM_FAIL;
cyhal_sdio_t *obj = params->context;
static bool wasCheckReadyExecuted = false;
bool allow = true;
cyhal_sdio_t *obj = (cyhal_sdio_t *)callback_arg;
CY_ASSERT(obj != NULL);
cy_stc_syspm_callback_params_t pdl_params =
{
@ -282,36 +264,44 @@ static cy_en_syspm_status_t cyhal_sdio_syspm_callback(cy_stc_syspm_callback_para
.context = &(obj->context)
};
retVal = Cy_SD_Host_DeepSleepCallback(&pdl_params, mode);
/* Check if hardware is ready to go sleep using lower level callback. */
if (state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP)
{
allow = (Cy_SD_Host_DeepSleepCallback(&pdl_params, cyhal_utils_convert_haltopdl_pm_mode(mode)) == CY_SYSPM_SUCCESS);
}
if (retVal == CY_SYSPM_SUCCESS)
if (allow)
{
switch (mode)
{
case CY_SYSPM_CHECK_READY:
case CYHAL_SYSPM_CHECK_READY:
{
cyhal_sdio_event_callback_t callback = (cyhal_sdio_event_callback_t) obj->callback_data.callback;
if ((callback != NULL) && (0U != (obj->events & (uint32_t) CYHAL_SDIO_GOING_DOWN)))
allow = !cyhal_sdio_is_busy(obj);
if (allow)
{
(void)(callback)(obj->callback_data.callback_arg, CYHAL_SDIO_GOING_DOWN);
/* Call the event only if we are ready to go to sleep */
cyhal_sdio_event_callback_t callback = (cyhal_sdio_event_callback_t) obj->callback_data.callback;
if ((callback != NULL) && (0U != (obj->events & (uint32_t) CYHAL_SDIO_GOING_DOWN)))
{
(void)(callback)(obj->callback_data.callback_arg, CYHAL_SDIO_GOING_DOWN);
}
/* Set transition flag to prevent any further transaction */
obj->pm_transition_pending = true;
}
wasCheckReadyExecuted = true;
break;
}
case CY_SYSPM_BEFORE_TRANSITION:
case CYHAL_SYSPM_BEFORE_TRANSITION:
{
/* Nothing to do in this mode */
/* Nothing to do */
break;
}
case CY_SYSPM_AFTER_TRANSITION:
case CY_SYSPM_CHECK_FAIL:
case CYHAL_SYSPM_AFTER_TRANSITION:
case CYHAL_SYSPM_CHECK_FAIL:
{
/* Execute this only if check ready case was executed */
if (wasCheckReadyExecuted)
if (obj->pm_transition_pending)
{
/* Execute callback to indicate that interface is coming up */
cyhal_sdio_event_callback_t callback = (cyhal_sdio_event_callback_t) obj->callback_data.callback;
@ -320,19 +310,73 @@ static cy_en_syspm_status_t cyhal_sdio_syspm_callback(cy_stc_syspm_callback_para
(void)(callback)(obj->callback_data.callback_arg, CYHAL_SDIO_COMING_UP);
}
wasCheckReadyExecuted = false;
obj->pm_transition_pending = false;
}
break;
}
default:
CY_ASSERT(false);
break;
}
}
return retVal;
return allow;
}
static bool cyhal_sdhc_syspm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
bool allow = true;
cyhal_sdhc_t *obj = (cyhal_sdhc_t *)callback_arg;
CY_ASSERT(obj != NULL);
cy_stc_syspm_callback_params_t pdl_params =
{
.base = obj->base,
.context = &(obj->context)
};
/* Check if hardware is ready to go sleep using lower level callback. */
if (state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP)
{
allow = (Cy_SD_Host_DeepSleepCallback(&pdl_params, cyhal_utils_convert_haltopdl_pm_mode(mode)) == CY_SYSPM_SUCCESS);
}
if (allow)
{
switch (mode)
{
case CYHAL_SYSPM_CHECK_READY:
{
allow = !cyhal_sdhc_is_busy(obj);
if (allow)
{
/* Set transition flag to prevent any further transaction */
obj->pm_transition_pending = true;
}
break;
}
case CYHAL_SYSPM_BEFORE_TRANSITION:
{
/* Nothing to do */
break;
}
case CYHAL_SYSPM_AFTER_TRANSITION:
case CYHAL_SYSPM_CHECK_FAIL:
{
/* Execute this only if check ready case was executed */
obj->pm_transition_pending = false;
break;
}
default:
CY_ASSERT(false);
break;
}
}
return allow;
}
static cy_en_sd_host_bus_width_t convert_buswidth(uint8_t stopbits)
{
@ -369,15 +413,14 @@ static cy_en_sd_host_bus_width_t convert_buswidth(uint8_t stopbits)
* \return \ref cy_en_sd_host_status_t
*
*******************************************************************************/
static cy_en_sd_host_status_t cyhal_sd_host_sdcardchangeclock(SDHC_Type *base, uint32_t instance_num, uint32_t frequency)
static cy_rslt_t cyhal_sd_host_sdcardchangeclock(SDHC_Type *base, uint32_t instance_num, uint32_t frequency)
{
cy_en_sd_host_status_t ret = CY_SD_HOST_ERROR_INVALID_PARAMETER;
uint32_t clockInput = 0;
cyhal_clock_t clock;
const cyhal_resource_inst_t rsc = { CYHAL_RSC_CLOCK, CYHAL_CLOCK_BLOCK_HF, CYHAL_SDHC_HF_CLOCKS[instance_num] };
cy_rslt_t ret = cyhal_clock_get(&clock, &rsc);
uint32_t clockInput = cyhal_clock_get_frequency(&clock);
cy_rslt_t get_frequency_result =
cyhal_system_clock_get_frequency(CYHAL_SDHC_HF_CLOCKS[instance_num], &clockInput);
if ((NULL != base) && (get_frequency_result == CY_RSLT_SUCCESS) && (0U != clockInput))
if ((NULL != base) && (0U != clockInput))
{
/* Update SD Host clock divider */
uint16_t clkDiv = (uint16_t) ((clockInput / frequency) >> 1UL);
@ -501,7 +544,7 @@ static void cyhal_sdhc_irq_handler(void)
uint32_t interruptStatus = Cy_SD_Host_GetNormalInterruptStatus(blockAddr);
uint32_t userInterruptStatus = interruptStatus & obj->irq_cause;
cyhal_sdhc_event_t user_events = get_event_from_isr(userInterruptStatus);
cyhal_sdhc_event_t user_events = (cyhal_sdhc_event_t)cyhal_utils_convert_flags(eventMap, SDHC_ISR, SDHC_EVENT, SDHC_EVENTS_NUM, userInterruptStatus);
if (obj->callback_data.callback != NULL)
{
@ -525,26 +568,6 @@ static void cyhal_sdhc_irq_handler(void)
}
}
static cyhal_sdhc_event_t get_event_from_isr(uint32_t asserted_interrupt)
{
cyhal_sdhc_event_t anded_events = (cyhal_sdhc_event_t) 0U;
for (uint8_t i = 0; i < SDHC_EVENTS_NUM; i++)
{
const uint32_t *map_entry = eventMap[i];
/* Anded events should be handled in user callback function as only
* there exist the knowledge of enabled events
*/
if ((asserted_interrupt & map_entry[SDHC_ISR]) != 0)
{
anded_events |= map_entry[SDHC_EVENT];
}
}
return anded_events;
}
cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
const cyhal_sdhc_config_t *config,
cyhal_gpio_t cmd,
@ -723,15 +746,10 @@ cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
hostConfig.emmc = obj->emmc;
#if LED_CTRL_PRESENT
if (NC != ledCtrl)
{
hostConfig.enableLedControl = true;
}
else
hostConfig.enableLedControl = (NC != ledCtrl);
#else
hostConfig.enableLedControl = false;
#endif
{
hostConfig.enableLedControl = false;
}
obj->context.cardType = CY_SD_HOST_NOT_EMMC;
@ -769,9 +787,24 @@ cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
if (result == CY_RSLT_SUCCESS)
{
/* Update SD Card frequency to be 25 Mhz */
result = (cy_rslt_t) cyhal_sd_host_sdcardchangeclock(obj->base, obj->resource.block_num, CY_SD_HOST_CLK_25M);
result = cyhal_sd_host_sdcardchangeclock(obj->base, obj->resource.block_num, CY_SD_HOST_CLK_25M);
}
}
if(result == CY_RSLT_SUCCESS)
{
obj->pm_transition_pending = false;
obj->pm_callback_data.callback = &cyhal_sdhc_syspm_callback,
obj->pm_callback_data.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
obj->pm_callback_data.next = NULL;
obj->pm_callback_data.args = obj;
/* The CYHAL_SYSPM_BEFORE_TRANSITION mode cannot be ignored because the PM handler
* calls the PDL deep-sleep callback that disables the block in this mode before transitioning.
*/
obj->pm_callback_data.ignore_modes = (cyhal_syspm_callback_mode_t)0,
cyhal_syspm_register_peripheral_callback(&obj->pm_callback_data);
}
}
if (result != CY_RSLT_SUCCESS)
@ -796,6 +829,8 @@ void cyhal_sdhc_free(cyhal_sdhc_t *obj)
cyhal_hwmgr_free(&(obj->resource));
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
cyhal_syspm_unregister_peripheral_callback(&obj->pm_callback_data);
}
/* Free pins */
@ -839,6 +874,11 @@ void cyhal_sdhc_free(cyhal_sdhc_t *obj)
cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t ret = CY_RSLT_SUCCESS;
cy_en_sd_host_status_t driverRet;
cy_stc_sd_host_write_read_config_t dataConfig;
@ -893,6 +933,11 @@ cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *da
cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t ret = CY_RSLT_SUCCESS;
cy_en_sd_host_status_t driverRet;
cy_stc_sd_host_write_read_config_t dataConfig;
@ -945,8 +990,13 @@ cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint
return ret;
}
cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t length)
cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t start_addr, size_t length)
{
if (obj->pm_transition_pending)
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
cy_rslt_t ret = CY_RSLT_SUCCESS;
cy_en_sd_host_status_t driverRet;
cy_en_sd_host_erase_type_t eraseType = CY_SD_HOST_ERASE_ERASE;
@ -965,7 +1015,7 @@ cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t l
/* Disable CMD Done interrupt, will be enabled after transition is complete */
Cy_SD_Host_SetNormalInterruptMask(obj->base, (regIntrSts & (uint32_t)~(CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE)));
driverRet = Cy_SD_Host_Erase(obj->base, startAddr, (startAddr + length), eraseType, &obj->context);
driverRet = Cy_SD_Host_Erase(obj->base, start_addr, (start_addr + length), eraseType, &obj->context);
if (CY_SD_HOST_SUCCESS != driverRet)
{
@ -1048,7 +1098,15 @@ cy_rslt_t cyhal_sdhc_write_async(const cyhal_sdhc_t *obj, uint32_t address, cons
bool cyhal_sdhc_is_busy(const cyhal_sdhc_t *obj)
{
return (CY_SD_HOST_XFER_COMPLETE != (CY_SD_HOST_XFER_COMPLETE & Cy_SD_Host_GetNormalInterruptStatus(obj->base)));
/* Check DAT Line Active */
uint32_t pState = Cy_SD_Host_GetPresentState(obj->base);
if ((CY_SD_HOST_DAT_LINE_ACTIVE != (pState & CY_SD_HOST_DAT_LINE_ACTIVE)) &&
(CY_SD_HOST_CMD_CMD_INHIBIT_DAT != (pState & CY_SD_HOST_CMD_CMD_INHIBIT_DAT)))
{
return false;
}
return true;
}
cy_rslt_t cyhal_sdhc_abort_async(const cyhal_sdhc_t *obj)
@ -1074,17 +1132,17 @@ void cyhal_sdhc_register_callback(cyhal_sdhc_t *obj, cyhal_sdhc_event_callback_t
cyhal_system_critical_section_exit(savedIntrStatus);
}
void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intrPriority, bool enable)
void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intr_priority, bool enable)
{
uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptMask(obj->base);
IRQn_Type irqn = CYHAL_SDHC_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
if(enable == true)
if (enable == true)
{
/* Enable specific interrupt */
if((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS)
if ((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS)
{
for (uint8_t i = 0; i < SDHC_EVENTS_NUM; i++)
{
@ -1106,7 +1164,7 @@ void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_
/* Disable interrupt */
else
{
if((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS)
if ((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS)
{
for (uint8_t i = 0; i < SDHC_EVENTS_NUM; i++)
{
@ -1129,7 +1187,7 @@ void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_
Cy_SD_Host_SetNormalInterruptMask(obj->base, interruptMask);
}
static void cyhal_sdio_irq_handler()
static void cyhal_sdio_irq_handler(void)
{
IRQn_Type irqn = CYHAL_GET_CURRENT_IRQN();
uint8_t block = cyhal_sd_get_block_from_irqn(irqn);
@ -1242,22 +1300,19 @@ cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk,
(void) Cy_SD_Host_Init(obj->base, &hostConfig, &context);
/* Register SDIO Deep Sleep Callback */
obj->pm_params.base = obj->base;
obj->pm_params.context = obj;
obj->pm_callback.callback = &cyhal_sdio_syspm_callback;
obj->pm_callback.type = CY_SYSPM_DEEPSLEEP;
obj->pm_callback.skipMode = 0;
obj->pm_callback.callbackParams = &(obj->pm_params);
obj->pm_callback.prevItm = NULL;
obj->pm_callback.nextItm = NULL;
if (result == CY_RSLT_SUCCESS)
if (CY_RSLT_SUCCESS == result)
{
if (!Cy_SysPm_RegisterCallback(&(obj->pm_callback)))
{
result = CY_RSLT_TYPE_ERROR;
}
obj->pm_transition_pending = false;
obj->pm_callback_data.callback = &cyhal_sdio_syspm_callback,
obj->pm_callback_data.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
obj->pm_callback_data.next = NULL;
obj->pm_callback_data.args = obj;
/* The CYHAL_SYSPM_BEFORE_TRANSITION mode cannot be ignored because the PM handler
* calls the PDL deep-sleep callback that disables the block in this mode before transitioning.
*/
obj->pm_callback_data.ignore_modes = (cyhal_syspm_callback_mode_t)0;
cyhal_syspm_register_peripheral_callback(&obj->pm_callback_data);
}
if (result == CY_RSLT_SUCCESS)
@ -1316,8 +1371,8 @@ void cyhal_sdio_free(cyhal_sdio_t *obj)
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
/* Unregister SDIO Deep Sleep Callback */
(void)Cy_SysPm_UnregisterCallback(&(obj->pm_callback));
cyhal_sd_config_structs[obj->resource.block_num] = NULL;
cyhal_syspm_unregister_peripheral_callback(&obj->pm_callback_data);
}
/* Free pins */
@ -1331,7 +1386,7 @@ void cyhal_sdio_free(cyhal_sdio_t *obj)
cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
{
cy_en_sd_host_status_t result = CY_SD_HOST_ERROR_TIMEOUT;
cy_rslt_t result = (cy_rslt_t)CY_SD_HOST_ERROR_TIMEOUT;
if ((NULL == obj) || (config == NULL))
{
@ -1370,6 +1425,11 @@ cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t directio
return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
}
if (obj->pm_transition_pending)
{
return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
}
cy_rslt_t ret = CY_RSLT_SUCCESS;
cy_en_sd_host_status_t result = CY_SD_HOST_ERROR_TIMEOUT;
cy_stc_sd_host_cmd_config_t cmd;
@ -1391,7 +1451,7 @@ cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t directio
Cy_SD_Host_SetNormalInterruptMask(obj->base, (regIntrSts & (uint16_t)~CY_SD_HOST_CMD_COMPLETE));
/* Check if an error occurred on any previous transactions */
if( Cy_SD_Host_GetNormalInterruptStatus(obj->base) & CY_SD_HOST_ERR_INTERRUPT )
if ( Cy_SD_Host_GetNormalInterruptStatus(obj->base) & CY_SD_HOST_ERR_INTERRUPT )
{
/* Reset the block if there was an error. Note a full reset usually
* requires more time, but this short version is working quite well and
@ -1452,6 +1512,11 @@ cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction
return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
}
if (obj->pm_transition_pending)
{
return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
}
cy_rslt_t ret = CY_RSLT_SUCCESS;
uint32_t retry = SDIO_TRANSF_TRIES;
cy_stc_sd_host_cmd_config_t cmd;
@ -1491,7 +1556,7 @@ cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction
/* Check if an error occurred on any previous transactions or reset
* after the first unsuccessful bulk transfer try
*/
if( (Cy_SD_Host_GetNormalInterruptStatus(obj->base) & CY_SD_HOST_ERR_INTERRUPT) ||
if ( (Cy_SD_Host_GetNormalInterruptStatus(obj->base) & CY_SD_HOST_ERR_INTERRUPT) ||
(retry < SDIO_TRANSF_TRIES))
{
/* Reset the block if there was an error. Note a full reset usually
@ -1601,6 +1666,11 @@ cy_rslt_t cyhal_sdio_transfer_async(cyhal_sdio_t *obj, cyhal_transfer_t directio
return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
}
if (obj->pm_transition_pending)
{
return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
}
cy_rslt_t ret = CY_RSLT_SUCCESS;
uint32_t retry = SDIO_TRANSF_TRIES;
cy_stc_sd_host_cmd_config_t cmd;
@ -1619,7 +1689,7 @@ cy_rslt_t cyhal_sdio_transfer_async(cyhal_sdio_t *obj, cyhal_transfer_t directio
while ((CY_SD_HOST_SUCCESS != result) && (retry > 0UL))
{
/* Check if an error occurred on any previous transactions or reset after the first unsuccessful bulk transfer try */
if( (Cy_SD_Host_GetNormalInterruptStatus(obj->base) & CY_SD_HOST_ERR_INTERRUPT) ||
if ((Cy_SD_Host_GetNormalInterruptStatus(obj->base) & CY_SD_HOST_ERR_INTERRUPT) ||
(retry < SDIO_TRANSF_TRIES))
{
/* Reset the block if there was an error. Note a full reset usually
@ -1760,7 +1830,7 @@ void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_event_callback_t
cyhal_system_critical_section_exit(savedIntrStatus);
}
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, uint8_t intrPriority, bool enable)
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, uint8_t intr_priority, bool enable)
{
/* Configure interrupt-based event(s) */
if (0U != ((uint32_t) event & (uint32_t) CYHAL_SDIO_ALL_INTERRUPTS))
@ -1768,7 +1838,7 @@ void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, ui
uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptMask(obj->base);
IRQn_Type irqn = CYHAL_SDHC_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
if (enable)
{

View File

@ -2,7 +2,7 @@
* \file cyhal_spi.c
*
* \brief
* Provides a high level interface for interacting with the Cypress PWM. This is
* Provides a high level interface for interacting with the Cypress SPI. This is
* a wrapper around the lower level PDL API.
*
********************************************************************************
@ -28,9 +28,10 @@
#include "cyhal_spi.h"
#include "cyhal_scb_common.h"
#include "cyhal_gpio.h"
#include "cyhal_interconnect.h"
#include "cyhal_system_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_system.h"
#include "cyhal_syspm.h"
#ifdef CY_IP_MXSCB
@ -123,29 +124,51 @@ static void cyhal_spi_irq_handler(void)
if (0 == (Cy_SCB_SPI_GetTransferStatus(obj->base, &obj->context) & CY_SCB_SPI_TRANSFER_ACTIVE))
{
if (obj->tx_buffer)
{
/* Start TX Transfer */
obj->pending = PENDING_TX;
const uint8_t *buf = obj->tx_buffer;
obj->tx_buffer = NULL;
if (obj->tx_buffer)
{
/* Start TX Transfer */
obj->pending = PENDING_TX;
const uint8_t *buf = obj->tx_buffer;
obj->tx_buffer = NULL;
Cy_SCB_SPI_Transfer(obj->base, (uint8_t *)buf, NULL, obj->tx_buffer_size, &obj->context);
} else if (obj->rx_buffer)
{
/* Start RX Transfer */
obj->pending = PENDING_RX;
uint8_t *buf = obj->rx_buffer;
obj->rx_buffer = NULL;
Cy_SCB_SPI_Transfer(obj->base, (uint8_t *)buf, NULL, obj->tx_buffer_size, &obj->context);
}
else if (obj->rx_buffer)
{
/* Start RX Transfer */
obj->pending = PENDING_RX;
uint8_t *rx_buf = obj->rx_buffer;
uint8_t *tx_buf;
size_t trx_size = obj->rx_buffer_size;
Cy_SCB_SPI_Transfer(obj->base, NULL, buf, obj->rx_buffer_size, &obj->context);
} else
{
/* Finish Async Transfer */
obj->pending = PENDING_NONE;
obj->is_async = false;
cyhal_reset_ssel(obj);
}
if (obj->rx_buffer_size > 1)
{
trx_size -= 1; // Transfer everything left except for the last byte
uint8_t **rx_buffer_p = (uint8_t **) &obj->rx_buffer;
tx_buf = *rx_buffer_p + 1; // Start at second byte to avoid trying to transmit and receive the same byte
memset(tx_buf, obj->write_fill, trx_size);
*rx_buffer_p += trx_size; // Move to 1 byte before end
obj->rx_buffer_size = 1; // Transfer the last byte on the next interrupt
}
else
{
tx_buf = &obj->write_fill;
obj->rx_buffer = NULL;
}
Cy_SCB_SPI_Transfer(obj->base, tx_buf, rx_buf, trx_size, &obj->context);
}
else
{
/* Finish Async Transfer */
obj->pending = PENDING_NONE;
obj->is_async = false;
cyhal_reset_ssel(obj);
}
}
}
@ -153,6 +176,13 @@ static void cyhal_spi_cb_wrapper(uint32_t event)
{
cyhal_spi_t *obj = (cyhal_spi_t*) cyhal_scb_get_irq_obj();
cyhal_spi_irq_event_t anded_events = (cyhal_spi_irq_event_t) (obj->irq_cause & (uint32_t) cyhal_convert_interrupt_cause(event));
// Don't call the callback until the final transfer has put everything in the FIFO/completed
if ((anded_events & (CYHAL_SPI_IRQ_DATA_IN_FIFO | CYHAL_SPI_IRQ_DONE)) && !(obj->rx_buffer == NULL && obj->tx_buffer == NULL))
{
return;
}
if (anded_events)
{
cyhal_spi_event_callback_t callback = (cyhal_spi_event_callback_t) obj->callback_data.callback;
@ -162,18 +192,16 @@ static void cyhal_spi_cb_wrapper(uint32_t event)
static cy_en_scb_spi_sclk_mode_t cyhal_convert_mode_sclk(cyhal_spi_mode_t mode)
{
uint8_t sclk_mode = (mode & 0x6) >> 1;
uint8_t sclk_mode = (mode & (CYHAL_SPI_MODE_FLAG_CPOL | CYHAL_SPI_MODE_FLAG_CPHA));
switch (sclk_mode)
{
case 0:
return (CY_SCB_SPI_CPHA0_CPOL0);
case 1:
return (CY_SCB_SPI_CPHA1_CPOL0);
case 2:
return (CY_SCB_SPI_CPHA0_CPOL1);
case 3:
case CYHAL_SPI_MODE_FLAG_CPOL | CYHAL_SPI_MODE_FLAG_CPHA:
return (CY_SCB_SPI_CPHA1_CPOL1);
case CYHAL_SPI_MODE_FLAG_CPOL:
return (CY_SCB_SPI_CPHA0_CPOL1);
case CYHAL_SPI_MODE_FLAG_CPHA:
return (CY_SCB_SPI_CPHA1_CPOL0);
default:
return (CY_SCB_SPI_CPHA0_CPOL0);
}
@ -181,22 +209,24 @@ static cy_en_scb_spi_sclk_mode_t cyhal_convert_mode_sclk(cyhal_spi_mode_t mode)
static bool is_cyhal_mode_msb(cyhal_spi_mode_t mode)
{
switch(mode)
{
case CYHAL_SPI_MODE_00_MSB:
case CYHAL_SPI_MODE_01_MSB:
case CYHAL_SPI_MODE_10_MSB:
case CYHAL_SPI_MODE_11_MSB:
return true;
case CYHAL_SPI_MODE_00_LSB:
case CYHAL_SPI_MODE_01_LSB:
case CYHAL_SPI_MODE_10_LSB:
case CYHAL_SPI_MODE_11_LSB:
return false;
default:
CY_ASSERT(false);
return true;
}
return ((mode & CYHAL_SPI_MODE_FLAG_LSB) != CYHAL_SPI_MODE_FLAG_LSB);
}
static bool cyhal_spi_pm_callback_instance(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
{
cyhal_spi_t *obj = (cyhal_spi_t *)obj_ptr;
bool allow = true;
cy_stc_syspm_callback_params_t spi_callback_params = {
.base = (void *) (obj->base),
.context = (void *) &(obj->context)
};
if (CYHAL_SYSPM_CB_CPU_DEEPSLEEP == state)
allow = (CY_SYSPM_SUCCESS == Cy_SCB_SPI_DeepSleepCallback(&spi_callback_params, pdl_mode));
else if (CYHAL_SYSPM_CB_SYSTEM_HIBERNATE == state)
allow = (CY_SYSPM_SUCCESS == Cy_SCB_SPI_HibernateCallback(&spi_callback_params, pdl_mode));
return allow;
}
cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, cyhal_gpio_t sclk, cyhal_gpio_t ssel, const cyhal_clock_divider_t *clk,
@ -206,7 +236,6 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
memset(obj, 0, sizeof(cyhal_spi_t));
cy_rslt_t result = CY_RSLT_SUCCESS;
cyhal_resource_inst_t pin_rsc;
uint8_t ovr_sample_val = SPI_OVERSAMPLE_MIN;
// Explicitly marked not allocated resources as invalid to prevent freeing them.
@ -216,73 +245,74 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
obj->pin_sclk = CYHAL_NC_PIN_VALUE;
obj->pin_ssel = CYHAL_NC_PIN_VALUE;
if ((NC == sclk) || ((NC == mosi) && (NC == miso)))
return CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED;
obj->write_fill = (uint8_t) CY_SCB_SPI_DEFAULT_TX;
const cyhal_resource_pin_mapping_t *mosi_map = NULL;
const cyhal_resource_pin_mapping_t *miso_map = NULL;
const cyhal_resource_pin_mapping_t *sclk_map = NULL;
const cyhal_resource_pin_mapping_t *ssel_map = NULL;
/* Validate pins configuration. Mandatory pins:*/
/* Master mode: MOSI pin used, MISO unused: SCLK, SSEL are optional */
/* Master mode: MISO pin used, MOSI unused: SCLK is mandatory, MOSI, SSEL are optional */
/* Slave mode: MOSI or MISO are used: SCLK is mandatory, SSEL is optional */
// Reserve the SPI
/* Slave */
if (is_slave)
{
if (NC != mosi)
if ((NC == sclk) || ((NC == mosi) && (NC == miso)))
{
mosi_map = CY_UTILS_GET_RESOURCE(mosi, cyhal_pin_map_scb_spi_s_mosi);
return CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED;
}
if (NC != miso)
}
/* Master */
else
{
if ((NC != miso && NC == sclk) || (NC == mosi && NC == miso))
{
miso_map = CY_UTILS_GET_RESOURCE(miso, cyhal_pin_map_scb_spi_s_miso);
return CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED;
}
if (NC != ssel)
{
ssel_map = CY_UTILS_GET_RESOURCE(ssel, cyhal_pin_map_scb_spi_s_select0);
}
sclk_map = CY_UTILS_GET_RESOURCE(sclk, cyhal_pin_map_scb_spi_s_clk);
}
/* Get pin configurations */
const cyhal_resource_pin_mapping_t *mosi_map;
const cyhal_resource_pin_mapping_t *miso_map;
const cyhal_resource_pin_mapping_t *sclk_map;
const cyhal_resource_pin_mapping_t *ssel_map;
if (is_slave)
{
mosi_map = CYHAL_FIND_SCB_MAP(mosi, cyhal_pin_map_scb_spi_s_mosi);
miso_map = CYHAL_FIND_SCB_MAP(miso, cyhal_pin_map_scb_spi_s_miso);
sclk_map = CYHAL_FIND_SCB_MAP(sclk, cyhal_pin_map_scb_spi_s_clk);
ssel_map = CYHAL_FIND_SCB_MAP(ssel, cyhal_pin_map_scb_spi_s_select0);
}
else
{
if (NC != mosi)
{
mosi_map = CY_UTILS_GET_RESOURCE(mosi, cyhal_pin_map_scb_spi_m_mosi);
}
if (NC != miso)
{
miso_map = CY_UTILS_GET_RESOURCE(miso, cyhal_pin_map_scb_spi_m_miso);
}
if (NC != ssel)
{
ssel_map = CY_UTILS_GET_RESOURCE(ssel, cyhal_pin_map_scb_spi_m_select0);
}
sclk_map = CY_UTILS_GET_RESOURCE(sclk, cyhal_pin_map_scb_spi_m_clk);
mosi_map = CYHAL_FIND_SCB_MAP(mosi, cyhal_pin_map_scb_spi_m_mosi);
miso_map = CYHAL_FIND_SCB_MAP(miso, cyhal_pin_map_scb_spi_m_miso);
sclk_map = CYHAL_FIND_SCB_MAP(sclk, cyhal_pin_map_scb_spi_m_clk);
ssel_map = CYHAL_FIND_SCB_MAP(ssel, cyhal_pin_map_scb_spi_m_select0);
}
if ( ((NC != mosi) && (NULL == mosi_map))
|| ((NC != miso) && (NULL == miso_map))
|| (NULL == sclk_map)
|| ((NC != ssel) && (NULL == ssel_map))
|| ((NC != ssel) && (ssel_map->inst->block_num != sclk_map->inst->block_num))
|| ((NC != mosi) && (mosi_map->inst->block_num != sclk_map->inst->block_num))
|| ((NC != miso) && (miso_map->inst->block_num != sclk_map->inst->block_num))
)
const cyhal_resource_inst_t *spi_inst = (NC != mosi)
? mosi_map->inst
: miso_map->inst;
/* Validate pins mapping */
if (((NC != mosi) && ((NULL == mosi_map) || !cyhal_utils_resources_equal(spi_inst, mosi_map->inst))) ||
((NC != miso) && ((NULL == miso_map) || !cyhal_utils_resources_equal(spi_inst, miso_map->inst))) ||
((NC != sclk) && ((NULL == sclk_map) || !cyhal_utils_resources_equal(spi_inst, sclk_map->inst))) ||
((NC != ssel) && ((NULL == ssel_map) || !cyhal_utils_resources_equal(spi_inst, ssel_map->inst))))
{
return CYHAL_SPI_RSLT_ERR_INVALID_PIN;
}
cyhal_resource_inst_t spi_inst = *sclk_map->inst;
if (CY_RSLT_SUCCESS != (result = cyhal_hwmgr_reserve(&spi_inst)))
if (CY_RSLT_SUCCESS != (result = cyhal_hwmgr_reserve(spi_inst)))
{
return result;
}
obj->resource = spi_inst;
obj->resource = *spi_inst;
// reserve the MOSI pin
if ((result == CY_RSLT_SUCCESS) && (NC != mosi))
{
pin_rsc = cyhal_utils_get_gpio_resource(mosi);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(mosi, mosi_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_mosi = mosi;
@ -292,8 +322,7 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
// reserve the MISO pin
if ((result == CY_RSLT_SUCCESS) && (NC != miso))
{
pin_rsc = cyhal_utils_get_gpio_resource(miso);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(miso, miso_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_miso = miso;
@ -301,10 +330,9 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
}
// reserve the SCLK pin
if (result == CY_RSLT_SUCCESS)
if (result == CY_RSLT_SUCCESS && (NC != sclk))
{
pin_rsc = cyhal_utils_get_gpio_resource(sclk);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(sclk, sclk_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_sclk = sclk;
@ -314,15 +342,9 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
// reserve the SSEL pin
if ((result == CY_RSLT_SUCCESS) && (NC != ssel))
{
if (is_slave)
{
pin_rsc = cyhal_utils_get_gpio_resource(ssel);
result = cyhal_hwmgr_reserve(&pin_rsc);
}
else
{
result = cyhal_gpio_init(ssel, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, true);
}
result = (is_slave)
? cyhal_utils_reserve_and_connect(ssel, ssel_map)
: cyhal_gpio_init(ssel, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, true);
if (result == CY_RSLT_SUCCESS)
{
@ -357,35 +379,17 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
}
if (result == CY_RSLT_SUCCESS)
{
cy_en_sysclk_status_t clock_assign_result = Cy_SysClk_PeriphAssignDivider(
(en_clk_dst_t)((uint8_t)PCLK_SCB0_CLOCK + obj->resource.block_num), obj->clock.div_type, obj->clock.div_num);
result = clock_assign_result == CY_SYSCLK_SUCCESS
? CY_RSLT_SUCCESS
: CYHAL_SPI_RSLT_CLOCK_ERROR;
result = (cy_rslt_t)Cy_SysClk_PeriphAssignDivider(
(en_clk_dst_t)((uint32_t)PCLK_SCB0_CLOCK + obj->resource.block_num), obj->clock.div_type, obj->clock.div_num);
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_int_spi_frequency(obj, SPI_DEFAULT_SPEED, &ovr_sample_val);
}
}
if ((result == CY_RSLT_SUCCESS) && (NC != mosi))
{
result = cyhal_connect_pin(mosi_map);
}
if ((result == CY_RSLT_SUCCESS) && (NC != miso))
{
result = cyhal_connect_pin(miso_map);
}
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_connect_pin(sclk_map);
}
if ((result == CY_RSLT_SUCCESS) && (NC != ssel) && is_slave)
{
result = cyhal_connect_pin(ssel_map);
}
if (result == CY_RSLT_SUCCESS)
{
cyhal_scb_update_instance_data(obj->resource.block_num, (void*)obj, &cyhal_spi_pm_callback_instance);
cy_stc_scb_spi_config_t config_structure = default_spi_config;
config_structure.spiMode = is_slave == 0
? CY_SCB_SPI_MASTER
@ -405,7 +409,6 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso,
obj->callback_data.callback = NULL;
obj->callback_data.callback_arg = NULL;
obj->irq_cause = 0;
cyhal_scb_config_structs[obj->resource.block_num] = obj;
cy_stc_sysint_t irqCfg = { CYHAL_SCB_IRQ_N[obj->resource.block_num], CYHAL_ISR_PRIORITY_DEFAULT };
Cy_SysInt_Init(&irqCfg, cyhal_spi_irq_handler);
@ -424,6 +427,7 @@ void cyhal_spi_free(cyhal_spi_t *obj)
{
if (NULL != obj->base)
{
cyhal_scb_update_instance_data(obj->resource.block_num, NULL, NULL);
Cy_SCB_SPI_Disable(obj->base, NULL);
Cy_SCB_SPI_DeInit(obj->base);
obj->base = NULL;
@ -466,7 +470,7 @@ static cy_rslt_t cyhal_int_spi_frequency(cyhal_spi_t *obj, uint32_t hz, uint8_t
cy_rslt_t result = CY_RSLT_SUCCESS;
uint8_t oversample_value;
uint32_t divider_value;
uint32_t last_diff = 0xFFFFFFFF;
uint32_t last_diff = 0xFFFFFFFFU;
uint8_t last_ovrsmpl_val = 0;
uint32_t last_dvdr_val = 0;
uint32_t oversampled_freq = 0;
@ -508,11 +512,13 @@ static cy_rslt_t cyhal_int_spi_frequency(cyhal_spi_t *obj, uint32_t hz, uint8_t
}
else
{
/* Slave requires such frequency: fclk_scb = N / ((0.5 * tclk_scb) 20 nsec - tDSI,
/* Slave requires such frequency: required_frequency = N / ((0.5 * desired_period) 20 nsec - tDSI,
* N is 3 when "Enable Input Glitch Filter" is false and 4 when true.
* tDSI Is external master delay which is assumed to be 16.66 nsec */
float desired_period_us = 1 / (float)hz * 1e6;
uint32_t required_frequency = (uint32_t)(3e6 / (0.5f * desired_period_us - 36.66f / 1e3));
/* Divided by 2 desired period to avoid dividing in required_frequency formula */
float desired_period_us_divided = 5e5f * (1 / (float)hz);
uint32_t required_frequency = (uint32_t)(3e6f / (desired_period_us_divided - 36.66f / 1e3f));
if (required_frequency > Cy_SysClk_ClkPeriGetFrequency())
{
@ -525,11 +531,6 @@ static cy_rslt_t cyhal_int_spi_frequency(cyhal_spi_t *obj, uint32_t hz, uint8_t
result = Cy_SysClk_PeriphSetDivider(obj->clock.div_type, obj->clock.div_num, last_dvdr_val);
if (CY_SYSCLK_SUCCESS != result)
{
result = CYHAL_SPI_RSLT_CLOCK_ERROR;
}
if (CY_RSLT_SUCCESS == result)
{
Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num);
@ -593,15 +594,16 @@ cy_rslt_t cyhal_spi_set_frequency(cyhal_spi_t *obj, uint32_t hz)
cy_rslt_t cyhal_spi_recv(cyhal_spi_t *obj, uint32_t *value)
{
if (NULL == obj)
return CYHAL_SPI_RSLT_BAD_ARGUMENT;
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint32_t read_value = CY_SCB_SPI_RX_NO_DATA;
const uint32_t fill_in = 0x0000ffffUL; /* PDL Fill in value */
uint32_t count = 0;
if (NULL == obj)
{
return CYHAL_SPI_RSLT_BAD_ARGUMENT;
}
if ((obj->is_slave) && (CYHAL_NC_PIN_VALUE == obj->pin_mosi))
{
return CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED;
@ -616,7 +618,7 @@ cy_rslt_t cyhal_spi_recv(cyhal_spi_t *obj, uint32_t *value)
{
cyhal_set_ssel(obj);
/* Clear FIFOs */
/* Clear FIFOs */
Cy_SCB_SPI_ClearTxFifo(obj->base);
Cy_SCB_SPI_ClearRxFifo(obj->base);
@ -625,12 +627,8 @@ cy_rslt_t cyhal_spi_recv(cyhal_spi_t *obj, uint32_t *value)
count = Cy_SCB_SPI_Write(obj->base, fill_in);
}
while (Cy_SCB_SPI_IsTxComplete(obj->base) == false)
{
}
while ( Cy_SCB_SPI_GetNumInRxFifo(obj->base) == 0 )
{ /* Wait for RX FIFO not empty */ }
while (Cy_SCB_SPI_IsTxComplete(obj->base) == false) { }
while (Cy_SCB_SPI_GetNumInRxFifo(obj->base) == 0) { } /* Wait for RX FIFO not empty */
cyhal_reset_ssel(obj);
}
@ -644,14 +642,14 @@ cy_rslt_t cyhal_spi_recv(cyhal_spi_t *obj, uint32_t *value)
cy_rslt_t cyhal_spi_send(cyhal_spi_t *obj, uint32_t value)
{
uint32_t count = 0;
uint32_t rx_count = 0;
cy_rslt_t result = CY_RSLT_SUCCESS;
if (NULL == obj)
{
return CYHAL_SPI_RSLT_BAD_ARGUMENT;
}
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint32_t count = 0;
cy_rslt_t result = CY_RSLT_SUCCESS;
if ((obj->is_slave) && (CYHAL_NC_PIN_VALUE == obj->pin_miso))
{
@ -666,7 +664,8 @@ cy_rslt_t cyhal_spi_send(cyhal_spi_t *obj, uint32_t value)
if (!obj->is_slave)
{
cyhal_set_ssel(obj);
/* Clear FIFOs */
/* Clear FIFOs */
Cy_SCB_SPI_ClearTxFifo(obj->base);
Cy_SCB_SPI_ClearRxFifo(obj->base);
}
@ -678,11 +677,8 @@ cy_rslt_t cyhal_spi_send(cyhal_spi_t *obj, uint32_t value)
if (!obj->is_slave)
{
while (Cy_SCB_SPI_IsTxComplete(obj->base) == false)
{
}
while (( Cy_SCB_SPI_GetNumInRxFifo(obj->base) == rx_count ) && (rx_count != Cy_SCB_GetFifoSize(obj->base)))
{ /* Wait for RX FIFO not empty */ }
while (Cy_SCB_SPI_IsTxComplete(obj->base) == false) { }
while (Cy_SCB_SPI_GetNumInRxFifo(obj->base) == 0) { } /* Wait for RX FIFO not empty */
cyhal_reset_ssel(obj);
(void)Cy_SCB_SPI_Read(obj->base);
}
@ -694,95 +690,31 @@ cy_rslt_t cyhal_spi_send(cyhal_spi_t *obj, uint32_t value)
cy_rslt_t cyhal_spi_transfer(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length, uint8_t write_fill)
{
uint32_t remaining_rx, remaining_tx, xfr_length;
uint8_t dummy[MAX_DUMMY_SIZE];
if (NULL == obj)
{
return CYHAL_SPI_RSLT_BAD_ARGUMENT;
}
if ((CYHAL_NC_PIN_VALUE == obj->pin_mosi) || (CYHAL_NC_PIN_VALUE == obj->pin_miso))
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
obj->write_fill = write_fill;
cy_rslt_t rslt = cyhal_spi_transfer_async(obj, tx, tx_length, rx, rx_length);
if (rslt == CY_RSLT_SUCCESS)
{
return CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED;
while (obj->pending != PENDING_NONE) { } /* Wait for async transfer to complete */
}
if (!obj->is_slave)
{
cyhal_set_ssel(obj);
}
if (tx_length > rx_length)
{
xfr_length = (uint32_t) rx_length;
remaining_rx = 0;
remaining_tx = (uint32_t) (tx_length - rx_length);
if (xfr_length != 0)
{
Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context));
while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { };
}
const uint8_t *bufptr = tx + (obj->data_bits <= 8 ? xfr_length : (xfr_length * 2));
Cy_SCB_SPI_Transfer(obj->base, (uint8_t *)bufptr, NULL, remaining_tx, &(obj->context));
while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { };
}
else if (tx_length < rx_length)
{
xfr_length = (uint32_t) tx_length;
remaining_rx = (uint32_t) (rx_length - tx_length);
if (xfr_length != 0)
{
Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context));
while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { };
}
memset(dummy, write_fill, sizeof(dummy));
while (remaining_rx)
{
uint8_t *bufptr = rx + (obj->data_bits <= 8 ? xfr_length : (xfr_length * 2));
if (remaining_rx <= MAX_DUMMY_SIZE)
{
Cy_SCB_SPI_Transfer(obj->base, dummy, bufptr, remaining_rx, &(obj->context));
remaining_rx = 0;
}
else
{
Cy_SCB_SPI_Transfer(obj->base, dummy, bufptr, MAX_DUMMY_SIZE, &(obj->context));
remaining_rx -= MAX_DUMMY_SIZE;
xfr_length += MAX_DUMMY_SIZE;
}
while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { };
}
}
else if (tx_length != 0) // tx_length == rx_length
{
xfr_length = (uint32_t) tx_length;
Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context));
while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { };
}
if (!obj->is_slave)
{
cyhal_reset_ssel(obj);
}
return CY_RSLT_SUCCESS;
obj->write_fill = (uint8_t) CY_SCB_SPI_DEFAULT_TX;
return rslt;
}
cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length)
{
cy_en_scb_spi_status_t spi_status;
if (NULL == obj)
{
return CYHAL_SPI_RSLT_BAD_ARGUMENT;
}
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
cy_en_scb_spi_status_t spi_status;
if ((CYHAL_NC_PIN_VALUE == obj->pin_mosi) || (CYHAL_NC_PIN_VALUE == obj->pin_miso))
{
@ -803,7 +735,8 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t
obj->tx_buffer = tx + (obj->data_bits <= 8 ? rx_length : (rx_length * 2));
obj->tx_buffer_size = tx_length - rx_length;
spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, rx, rx_length, &obj->context);
tx_length = rx_length; // Use tx_length to store entire transfer length
}
else
{
@ -812,7 +745,7 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t
obj->rx_buffer = NULL;
obj->tx_buffer = NULL;
spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, NULL, tx_length, &obj->context);
rx = NULL;
}
}
else if (rx_length > tx_length)
@ -821,21 +754,21 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t
{
/* I) write + read, II) read only */
obj->pending = PENDING_TX_RX;
obj->tx_buffer = NULL;
obj->rx_buffer = rx + (obj->data_bits <= 8 ? tx_length : (tx_length * 2));
obj->rx_buffer_size = rx_length - tx_length;
obj->tx_buffer = NULL;
spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, rx, tx_length, &obj->context);
}
else
{
/* I) read only. */
obj->pending = PENDING_RX;
obj->rx_buffer = NULL;
obj->tx_buffer = NULL;
spi_status = Cy_SCB_SPI_Transfer(obj->base, NULL, rx, rx_length, &obj->context);
obj->rx_buffer = rx_length > 1 ? rx + 1 : NULL;
obj->rx_buffer_size = rx_length - 1;
tx = &obj->write_fill;
tx_length = 1;
}
}
else
@ -844,9 +777,8 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t
obj->pending = PENDING_TX_RX;
obj->rx_buffer = NULL;
obj->tx_buffer = NULL;
spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, rx, tx_length, &obj->context);
}
spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, rx, tx_length, &obj->context);
return spi_status == CY_SCB_SPI_SUCCESS
? CY_RSLT_SUCCESS
: CYHAL_SPI_RSLT_TRANSFER_ERROR;
@ -880,7 +812,7 @@ void cyhal_spi_register_callback(cyhal_spi_t *obj, cyhal_spi_event_callback_t ca
obj->irq_cause = 0;
}
void cyhal_spi_enable_event(cyhal_spi_t *obj, cyhal_spi_event_t event, uint8_t intrPriority, bool enable)
void cyhal_spi_enable_event(cyhal_spi_t *obj, cyhal_spi_event_t event, uint8_t intr_priority, bool enable)
{
if (enable)
{
@ -892,7 +824,7 @@ void cyhal_spi_enable_event(cyhal_spi_t *obj, cyhal_spi_event_t event, uint8_t i
}
IRQn_Type irqn = CYHAL_SCB_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
}
#if defined(__cplusplus)

View File

@ -0,0 +1,400 @@
/***************************************************************************//**
* \file cyhal_syspm.c
*
* \brief
* Provides a high level interface for interacting with the Cypress power
* management and system clock configuration. This interface abstracts out the
* chip specific details. If any chip specific functionality is necessary, or
* performance is critical the low level functions can be used directly.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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 <limits.h>
#include "cyhal_system.h"
#include "cyhal_syspm.h"
#include "cy_syspm.h"
#include "cy_utils.h"
#include "cyhal_utils.h"
#include "cyhal_lptimer.h"
/** Disable the systick */
#define cyhal_syspm_disable_systick() (SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk)
/* Enable the systick */
#define cyhal_syspm_enable_systick() (SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk)
/* Hz to KHz */
#define CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR 1000
/** The common PM callback parameters set, that are used internally for different peripherals */
static cy_stc_syspm_callback_params_t internal_cb_params_sleep = {NULL, (uint32_t *)CYHAL_SYSPM_CB_CPU_SLEEP};
static cy_stc_syspm_callback_params_t internal_cb_params_deepsleep = {NULL, (uint32_t *)CYHAL_SYSPM_CB_CPU_DEEPSLEEP};
static cy_stc_syspm_callback_params_t internal_cb_params_hibernate = {NULL, (uint32_t *)CYHAL_SYSPM_CB_SYSTEM_HIBERNATE};
static cy_stc_syspm_callback_params_t internal_cb_params_lp = {NULL, (uint32_t *)CYHAL_SYSPM_CB_SYSTEM_NORMAL};
static cy_stc_syspm_callback_params_t internal_cb_params_ulp = {NULL, (uint32_t *)CYHAL_SYSPM_CB_SYSTEM_LOW};
/* The first entry in the callback chain is always reserved for the user set
* cyhal_syspm_register_callback callback. This may be set to a sentinel value
* indicating it is the end of the list. All subsequent slots are where
* peripheral drivers are tracked. This makes it very easy to determine whether
* the user registered a callback and to make sure we run that first. */
static cyhal_syspm_callback_data_t* pm_callback_ptr = CYHAL_SYSPM_END_OF_LIST;
static cyhal_syspm_callback_data_t* peripheral_pm_callback_ptr = CYHAL_SYSPM_END_OF_LIST;
static uint16_t deep_sleep_lock = 0;
#define SYSPM_CALLBACK_ORDER (10u)
static cy_en_syspm_status_t common_cb(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
static cy_stc_syspm_callback_t internal_pm_cb_sleep =
{
.callback = common_cb,
.type = CY_SYSPM_SLEEP,
.skipMode = 0,
.callbackParams = &internal_cb_params_sleep,
.prevItm = NULL,
.nextItm = NULL,
.order = SYSPM_CALLBACK_ORDER,
};
static cy_stc_syspm_callback_t internal_pm_cb_deepsleep =
{
.callback = common_cb,
.type = CY_SYSPM_DEEPSLEEP,
.skipMode = 0,
.callbackParams = &internal_cb_params_deepsleep,
.prevItm = NULL,
.nextItm = NULL,
.order = SYSPM_CALLBACK_ORDER,
};
static cy_stc_syspm_callback_t internal_pm_cb_hibernate =
{
.callback = common_cb,
.type = CY_SYSPM_HIBERNATE,
.skipMode = 0,
.callbackParams = &internal_cb_params_hibernate,
.prevItm = NULL,
.nextItm = NULL,
.order = SYSPM_CALLBACK_ORDER,
};
static cy_stc_syspm_callback_t internal_pm_cb_lp =
{
.callback = common_cb,
.type = CY_SYSPM_LP,
.skipMode = 0,
.callbackParams = &internal_cb_params_lp,
.prevItm = NULL,
.nextItm = NULL,
.order = SYSPM_CALLBACK_ORDER,
};
static cy_stc_syspm_callback_t internal_pm_cb_ulp =
{
.callback = common_cb,
.type = CY_SYSPM_ULP,
.skipMode = 0,
.callbackParams = &internal_cb_params_ulp,
.prevItm = NULL,
.nextItm = NULL,
.order = SYSPM_CALLBACK_ORDER,
};
/* Defines for mapping hal hibernate sources to pdl */
#define HIB_SRC_COUNT (10U)
#define HIB_SRC_HAL (0U)
#define HIB_SRC_PDL (1U)
static const uint32_t hib_source_map[HIB_SRC_COUNT][CYHAL_MAP_COLUMNS] =
{
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW, (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP0_LOW },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH, (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP0_HIGH },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_LPCOMP1_LOW, (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP1_LOW },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_LPCOMP1_HIGH, (uint32_t)CY_SYSPM_HIBERNATE_LPCOMP1_HIGH },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_RTC_ALARM, (uint32_t)CY_SYSPM_HIBERNATE_RTC_ALARM },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_WDT, (uint32_t)CY_SYSPM_HIBERNATE_WDT },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_PINA_LOW, (uint32_t)CY_SYSPM_HIBERNATE_PIN0_LOW },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_PINA_HIGH, (uint32_t)CY_SYSPM_HIBERNATE_PIN0_HIGH },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_PINB_LOW, (uint32_t)CY_SYSPM_HIBERNATE_PIN1_LOW },
{ (uint32_t)CYHAL_SYSPM_HIBERNATE_PINB_HIGH, (uint32_t)CY_SYSPM_HIBERNATE_PIN1_HIGH }
};
static cyhal_syspm_callback_data_t* call_all_pm_callbacks(cyhal_syspm_callback_data_t* entry, bool* allow, cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode)
{
while(entry != CYHAL_SYSPM_END_OF_LIST)
{
if (entry->callback != NULL &&
(entry->states & state) == state &&
(entry->ignore_modes & mode) != mode)
{
*allow = entry->callback(state, mode, entry->args) || mode != CYHAL_SYSPM_CHECK_READY;
if (!(*allow))
{
// Do not increment pointer so that backtracking stop at the correct location
break;
}
}
entry = entry->next;
}
return entry;
}
static void backtrack_all_pm_callbacks(cyhal_syspm_callback_data_t* start, cyhal_syspm_callback_data_t* end, cyhal_syspm_callback_state_t state)
{
while(start != end)
{
if (start->callback != NULL &&
(start->states & state) == state &&
(start->ignore_modes & CYHAL_SYSPM_CHECK_FAIL) != CYHAL_SYSPM_CHECK_FAIL)
{
start->callback(state, CYHAL_SYSPM_CHECK_FAIL, start->args);
}
start = start->next;
}
}
static cy_en_syspm_status_t common_cb(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
{
// The PDL function that wrap around this callback enters critical section, this function does not need to enter critical section.
cyhal_syspm_callback_state_t state = (cyhal_syspm_callback_state_t)(uintptr_t)callbackParams->context;
if ((state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP) && (mode == CY_SYSPM_CHECK_READY) && (deep_sleep_lock != 0))
{
return CY_SYSPM_FAIL;
}
else
{
cyhal_syspm_callback_mode_t hal_mode = cyhal_utils_convert_pdltohal_pm_mode(mode);
bool allow = true;
cyhal_syspm_callback_data_t *first, *second;
if (hal_mode == CYHAL_SYSPM_CHECK_FAIL || hal_mode == CYHAL_SYSPM_AFTER_TRANSITION)
{
first = peripheral_pm_callback_ptr;
second = pm_callback_ptr;
}
else
{
second = peripheral_pm_callback_ptr;
first = pm_callback_ptr;
}
cyhal_syspm_callback_data_t* first_current = call_all_pm_callbacks(first, &allow, state, hal_mode);
cyhal_syspm_callback_data_t* second_current = allow
? call_all_pm_callbacks(second, &allow, state, hal_mode)
: second;
if (!allow && (CYHAL_SYSPM_CHECK_READY == hal_mode))
{
backtrack_all_pm_callbacks(second, second_current, state);
backtrack_all_pm_callbacks(first, first_current, state);
}
if (state == CYHAL_SYSPM_CB_SYSTEM_LOW && hal_mode == CYHAL_SYSPM_BEFORE_TRANSITION)
{
uint32_t hfclk_freq_mhz = Cy_SysClk_ClkHfGetFrequency(0) / 1000000;
Cy_SysLib_SetWaitStates(true, hfclk_freq_mhz);
}
if (state == CYHAL_SYSPM_CB_SYSTEM_NORMAL && hal_mode == CYHAL_SYSPM_AFTER_TRANSITION)
{
uint32_t hfclk_freq_mhz = Cy_SysClk_ClkHfGetFrequency(0) / 1000000;
Cy_SysLib_SetWaitStates(false, hfclk_freq_mhz);
}
return allow ? CY_SYSPM_SUCCESS : CY_SYSPM_FAIL;
}
}
static void cyhal_syspm_remove_callback_from_list(cyhal_syspm_callback_data_t **list, cyhal_syspm_callback_data_t *remove)
{
uint32_t intr_status = cyhal_system_critical_section_enter();
while(*list != CYHAL_SYSPM_END_OF_LIST)
{
if (*list == remove)
{
*list = remove->next;
remove->next = NULL;
break;
}
list = &((*list)->next);
}
cyhal_system_critical_section_exit(intr_status);
}
static bool cyhal_syspm_is_registered(cyhal_syspm_callback_data_t *list, cyhal_syspm_callback_data_t *callback)
{
// If callback->next is NULL it must not be registered since all registered
// next ptrs in the list must point to the next callback or be equal to
// CYHAL_SYSPM_END_OF_LIST
if(callback->next == NULL)
return false;
else
return true;
}
void cyhal_syspm_register_peripheral_callback(cyhal_syspm_callback_data_t *callback_data)
{
CY_ASSERT(callback_data != NULL);
uint32_t intr_status = cyhal_system_critical_section_enter();
if(!cyhal_syspm_is_registered(peripheral_pm_callback_ptr, callback_data))
{
callback_data->next = peripheral_pm_callback_ptr;
peripheral_pm_callback_ptr = callback_data;
}
cyhal_system_critical_section_exit(intr_status);
}
void cyhal_syspm_unregister_peripheral_callback(cyhal_syspm_callback_data_t *callback_data)
{
cyhal_syspm_remove_callback_from_list(&peripheral_pm_callback_ptr, callback_data);
}
cy_rslt_t cyhal_syspm_init(void)
{
/* Check the IO status. If current status is frozen, unfreeze the system. */
if (Cy_SysPm_GetIoFreezeStatus())
{
/* Unfreeze the system */
Cy_SysPm_IoUnfreeze();
}
cy_rslt_t rslt = CY_RSLT_SUCCESS;
if (!Cy_SysPm_RegisterCallback(&internal_pm_cb_sleep) ||
!Cy_SysPm_RegisterCallback(&internal_pm_cb_deepsleep) ||
!Cy_SysPm_RegisterCallback(&internal_pm_cb_hibernate) ||
!Cy_SysPm_RegisterCallback(&internal_pm_cb_lp) ||
!Cy_SysPm_RegisterCallback(&internal_pm_cb_ulp))
{
rslt = CYHAL_SYSPM_RSLT_INIT_ERROR;
}
return rslt;
}
cy_rslt_t cyhal_syspm_hibernate(cyhal_syspm_hibernate_source_t source)
{
Cy_SysPm_SetHibernateWakeupSource(cyhal_utils_convert_flags(hib_source_map, HIB_SRC_HAL, HIB_SRC_PDL, HIB_SRC_COUNT, (uint32_t)source));
return Cy_SysPm_SystemEnterHibernate();
}
cy_rslt_t cyhal_syspm_set_system_state(cyhal_syspm_system_state_t state)
{
cy_rslt_t rslt;
/* The wait states are changed in the common syspm handler after
* state change is allowed and all handlers are called to take into
* account any frequency change that might happen as a part of the
* power management handlers
*/
switch (state)
{
case CYHAL_SYSPM_SYSTEM_NORMAL:
rslt = Cy_SysPm_SystemEnterLp();
break;
case CYHAL_SYSPM_SYSTEM_LOW:
rslt = Cy_SysPm_SystemEnterUlp();
break;
default:
/* Should never get here */
CY_ASSERT(false);
rslt = CYHAL_SYSPM_RSLT_BAD_ARGUMENT;
break;
}
return rslt;
}
void cyhal_syspm_register_callback(cyhal_syspm_callback_data_t *callback_data)
{
CY_ASSERT(callback_data != NULL);
uint32_t intr_status = cyhal_system_critical_section_enter();
if(!cyhal_syspm_is_registered(pm_callback_ptr, callback_data))
{
callback_data->next = pm_callback_ptr;
pm_callback_ptr = callback_data;
}
cyhal_system_critical_section_exit(intr_status);
}
void cyhal_syspm_unregister_callback(cyhal_syspm_callback_data_t *callback_data)
{
cyhal_syspm_remove_callback_from_list(&pm_callback_ptr, callback_data);
}
void cyhal_syspm_lock_deepsleep(void)
{
CY_ASSERT(deep_sleep_lock != USHRT_MAX);
uint32_t intr_status = cyhal_system_critical_section_enter();
if (deep_sleep_lock < USHRT_MAX)
{
deep_sleep_lock++;
}
cyhal_system_critical_section_exit(intr_status);
}
void cyhal_syspm_unlock_deepsleep(void)
{
CY_ASSERT(deep_sleep_lock != 0U);
uint32_t intr_status = cyhal_system_critical_section_enter();
if (deep_sleep_lock > 0U)
{
deep_sleep_lock--;
}
cyhal_system_critical_section_exit(intr_status);
}
cy_rslt_t cyhal_syspm_tickless_sleep_deepsleep(cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms, bool deep_sleep)
{
CY_ASSERT(obj != NULL);
uint32_t initial_ticks;
uint32_t sleep_ticks;
cyhal_lptimer_info_t timer_info;
*actual_ms = 0;
cy_rslt_t result = CY_RSLT_SUCCESS;
if(desired_ms > 0)
{
cyhal_lptimer_get_info(obj, &timer_info);
//lp_ticks = ms * lp_rate_khz
sleep_ticks = ((desired_ms - 1) * timer_info.frequency_hz) / CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR;
initial_ticks = cyhal_lptimer_read(obj);
result = cyhal_lptimer_set_delay(obj, sleep_ticks);
if(result == CY_RSLT_SUCCESS)
{
/* Stop the timer that is generating the tick interrupt. */
cyhal_syspm_disable_systick();
cyhal_lptimer_enable_event(obj, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, true);
result = deep_sleep ? cyhal_syspm_deepsleep() : cyhal_syspm_sleep();
if(result == CY_RSLT_SUCCESS)
{
uint32_t final_ticks = cyhal_lptimer_read(obj);
uint32_t ticks = (final_ticks < initial_ticks)
? (timer_info.max_counter_value - initial_ticks) + final_ticks
: final_ticks - initial_ticks;
*actual_ms = (ticks * CYHAL_HZ_TO_KHZ_CONVERSION_FACTOR) / timer_info.frequency_hz;
}
cyhal_lptimer_enable_event(obj, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, false);
/* Restart the systick timer. */
cyhal_syspm_enable_systick();
}
}
return result;
}

View File

@ -26,7 +26,6 @@
*******************************************************************************/
#include "cyhal_system.h"
#include "cyhal_hwmgr.h"
#ifdef CY_RTOS_AWARE
#include "cyabs_rtos.h"
#endif
@ -64,247 +63,6 @@ cy_rslt_t cyhal_system_delay_ms(uint32_t milliseconds)
#endif
}
uint32_t get_src_freq(cy_en_clkpath_in_sources_t source)
{
/* get the frequency of the source, i.e., the path mux input */
switch(source)
{
case CY_SYSCLK_CLKPATH_IN_IMO: /* IMO frequency is fixed at 8 MHz */
return CY_SYSCLK_IMO_FREQ;
case CY_SYSCLK_CLKPATH_IN_ILO: /* ILO, WCO and PILO frequencies are nominally 32.768 kHz */
case CY_SYSCLK_CLKPATH_IN_WCO:
case CY_SYSCLK_CLKPATH_IN_PILO:
return CY_SYSCLK_ILO_FREQ;
default:
return 0;
}
}
static uint32_t get_clkpath_freq(cy_en_clkhf_in_sources_t path, uint32_t freq, uint8_t *fll_pll_used)
{
*fll_pll_used = 0xff;
if (path == CY_SYSCLK_CLKHF_IN_CLKPATH0)
{
cy_stc_fll_manual_config_t fll_config;
Cy_SysClk_FllGetConfiguration(&fll_config);
if (fll_config.outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
{
freq *= fll_config.fllMult;
freq /= fll_config.refDiv;
freq /= (fll_config.enableOutputDiv ? 2U : 1U);
*fll_pll_used = 0;
}
}
else if((uint32_t)path <= CY_SRSS_NUM_PLL)
{
cy_stc_pll_manual_config_t pll_config;
Cy_SysClk_PllGetConfiguration(path, &pll_config);
if (pll_config.outputMode != CY_SYSCLK_FLLPLL_OUTPUT_INPUT)
{
freq *= pll_config.feedbackDiv;
freq /= pll_config.referenceDiv;
freq /= pll_config.outputDiv;
*fll_pll_used = (uint8_t)path;
}
}
return freq;
}
static cy_rslt_t try_set_hf_divider(uint8_t clock, uint32_t input_freq, uint32_t target_freq)
{
bool divider_found = false;
cy_en_clkhf_dividers_t divider;
if (target_freq == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_NO_DIVIDE;
}
else if (target_freq * 2 == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_DIVIDE_BY_2;
}
else if (target_freq * 4 == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_DIVIDE_BY_4;
}
else if (target_freq * 8 == input_freq)
{
divider_found = true;
divider = CY_SYSCLK_CLKHF_DIVIDE_BY_8;
}
if (divider_found)
{
Cy_SysClk_ClkHfSetDivider(clock, divider);
Cy_SysClk_ClkHfEnable(clock);
return CY_RSLT_SUCCESS;
}
else
{
return CYHAL_SYSTEM_RSLT_NO_VALID_DIVIDER;
}
}
static cy_rslt_t try_set_fll(uint8_t clock, uint32_t target_freq)
{
Cy_SysClk_FllDisable();
Cy_SysClk_ClkHfSetSource(clock, CY_SYSCLK_CLKHF_IN_CLKPATH0);
Cy_SysClk_ClkPathSetSource(0, CY_SYSCLK_CLKPATH_IN_IMO);
cy_rslt_t rslt = Cy_SysClk_FllConfigure(CY_SYSCLK_IMO_FREQ, target_freq, CY_SYSCLK_FLLPLL_OUTPUT_AUTO);
if (rslt == CY_RSLT_SUCCESS)
{
// Wait up to 1 seconds for FLL to lock
rslt = Cy_SysClk_FllEnable(1000000);
}
if (rslt == CY_RSLT_SUCCESS)
{
Cy_SysClk_ClkHfSetDivider(clock, CY_SYSCLK_CLKHF_NO_DIVIDE);
SystemCoreClockUpdate();
}
return rslt;
}
static cy_rslt_t try_set_pll(uint8_t clock, uint8_t pll, uint32_t target_freq)
{
Cy_SysClk_PllDisable(pll);
Cy_SysClk_ClkHfSetSource(clock, (cy_en_clkhf_in_sources_t)(pll));
cy_stc_pll_config_t cfg;
cfg.inputFreq = CY_SYSCLK_IMO_FREQ;
cfg.outputFreq = target_freq;
cfg.lfMode = false;
cfg.outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO;
Cy_SysClk_ClkPathSetSource(pll, CY_SYSCLK_CLKPATH_IN_IMO);
cy_rslt_t rslt = Cy_SysClk_PllConfigure(pll, &cfg);
if (rslt == CY_RSLT_SUCCESS)
{
// Wait up to 1 seconds for PLL to lock
rslt = Cy_SysClk_PllEnable(pll, 1000000);
}
if (rslt == CY_RSLT_SUCCESS)
{
Cy_SysClk_ClkHfSetDivider(clock, CY_SYSCLK_CLKHF_NO_DIVIDE);
SystemCoreClockUpdate();
}
return rslt;
}
/* This should be part of the PDL */
static inline bool cyhal_sysclk_clkhfisenabled(uint32_t clkHf)
{
bool retVal = false;
if (clkHf < CY_SRSS_NUM_HFROOT)
{
retVal = _FLD2BOOL(SRSS_CLK_ROOT_SELECT_ENABLE, SRSS_CLK_ROOT_SELECT[clkHf]);
}
return (retVal);
}
cy_rslt_t cyhal_system_clock_get_frequency(uint8_t clock, uint32_t *frequency_hz)
{
*frequency_hz = Cy_SysClk_ClkHfGetFrequency(clock);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_system_clock_set_frequency(uint8_t clock, uint32_t frequency_hz)
{
cy_en_clkhf_in_sources_t path = Cy_SysClk_ClkHfGetSource((uint32_t)clock);
cy_en_clkpath_in_sources_t source = Cy_SysClk_ClkPathGetSource((uint32_t)path);
uint32_t src_freq = get_src_freq(source);
if (src_freq == 0)
{
return CYHAL_SYSTEM_RSLT_SRC_CLK_DISABLED;
}
uint8_t fll_pll_used;
uint32_t clkpath_freq = get_clkpath_freq(path, src_freq, &fll_pll_used);
cy_rslt_t rslt = try_set_hf_divider(clock, clkpath_freq, frequency_hz);
if (rslt == CY_RSLT_SUCCESS)
{
SystemCoreClockUpdate();
return rslt;
}
bool enabled = cyhal_sysclk_clkhfisenabled(clock);
if (enabled && fll_pll_used == 0)
{
return try_set_fll(clock, frequency_hz);
}
else if (enabled && fll_pll_used <= SRSS_NUM_PLL)
{
return try_set_pll(clock, fll_pll_used, frequency_hz);
}
else
{
// Cannot get the correct frequency. Try to allocate an FLL or PLL
cyhal_resource_inst_t inst;
rslt = cyhal_hwmgr_allocate(CYHAL_RSC_CLKPATH, &inst);
if (rslt == CY_RSLT_SUCCESS)
{
if (inst.block_num == 0)
{
rslt = try_set_fll(clock, frequency_hz);
}
else if (inst.block_num <= SRSS_NUM_PLL)
{
rslt = try_set_pll(clock, inst.block_num, frequency_hz);
}
else
{
// No FLL or PLL available.
rslt = CYHAL_SYSTEM_RSLT_UNABLE_TO_SET_CLK_FREQ;
}
if (!enabled && rslt == CY_RSLT_SUCCESS)
{
rslt = Cy_SysClk_ClkHfEnable(clock);
}
if (rslt != CY_RSLT_SUCCESS)
{
cyhal_hwmgr_free(&inst);
}
}
}
return rslt;
}
cy_rslt_t cyhal_system_clock_set_divider(cyhal_system_clock_t clock, cyhal_system_divider_t divider)
{
if (divider < 1 || divider > 0x100)
{
return CYHAL_SYSTEM_RSLT_INVALID_CLK_DIVIDER;
}
switch(clock)
{
case CYHAL_SYSTEM_CLOCK_CM4:
{
Cy_SysClk_ClkFastSetDivider(divider - 1);
break;
}
case CYHAL_SYSTEM_CLOCK_CM0:
{
Cy_SysClk_ClkSlowSetDivider(divider - 1);
break;
}
case CYHAL_SYSTEM_CLOCK_PERI:
{
Cy_SysClk_ClkPeriSetDivider(divider - 1);
break;
}
default:
{
return CYHAL_SYSTEM_RSLT_INVALID_CLK_DIVIDER;
}
}
SystemCoreClockUpdate();
return CY_RSLT_SUCCESS;
}
cyhal_reset_reason_t cyhal_system_get_reset_reason(void)
{
uint32_t pdl_reason = Cy_SysLib_GetResetReason();

View File

@ -22,8 +22,10 @@
* limitations under the License.
*******************************************************************************/
#include "cyhal_hwmgr.h"
#include "cyhal_utils.h"
#include "cyhal_system_impl.h"
#include "cyhal_syspm.h"
#include "cyhal_system.h"
#include "cyhal_tcpwm_common.h"
#if defined(CY_IP_MXTCPWM_INSTANCES)
@ -57,17 +59,101 @@ const cyhal_tcpwm_data_t CYHAL_TCPWM_DATA[] = {
#endif
/** Callback array for TCPWM interrupts */
static cyhal_event_callback_data_t *cyhal_tcpwm_callback_data_structs[TCPWM_CHANNELS];
static cyhal_tcpwm_common_t *cyhal_tcpwm_data_structs[TCPWM_CHANNELS];
void cyhal_tcpwm_init_callback_data(cyhal_resource_inst_t *resource, cyhal_event_callback_data_t *callback_data)
bool cyhal_tcpwm_pm_has_enabled()
{
uint8_t index = GET_ARRAY_INDEX(resource->block_num, resource->channel_num);
cyhal_tcpwm_callback_data_structs[index] = callback_data;
callback_data->callback = NULL;
callback_data->callback_arg = NULL;
for (uint8_t i = 0; i < TCPWM_CHANNELS; i++)
{
if (cyhal_tcpwm_data_structs[i])
{
return true;
}
}
return false;
}
void cyhal_tcpwm_irq_handler()
static bool cyhal_tcpwm_pm_transition_pending_value = false;
bool cyhal_tcpwm_pm_transition_pending(void)
{
return cyhal_tcpwm_pm_transition_pending_value;
}
bool cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
switch(mode)
{
case CYHAL_SYSPM_CHECK_FAIL:
{
cyhal_tcpwm_pm_transition_pending_value = false;
break;
}
case CYHAL_SYSPM_AFTER_TRANSITION:
{
for (uint8_t i = 0; i < CY_IP_MXTCPWM_INSTANCES; i++)
{
uint32_t enable_flag = 0;
TCPWM_Type* base = CYHAL_TCPWM_DATA[i].base;
for (uint8_t j = 0; j < CYHAL_TCPWM_DATA[i].num_channels; j++)
{
if (cyhal_tcpwm_data_structs[GET_ARRAY_INDEX(i, j)])
{
enable_flag |= 1u << j;
}
}
if (0 != enable_flag)
{
// This only enables the counter. This does not start the timer/counter or the pwm.
Cy_TCPWM_Enable_Multiple(base, enable_flag);
}
}
cyhal_tcpwm_pm_transition_pending_value = false;
break;
}
case CYHAL_SYSPM_CHECK_READY:
{
for (uint8_t i = 0; i < CY_IP_MXTCPWM_INSTANCES; i++)
{
for (uint8_t j = 0; j < CYHAL_TCPWM_DATA[i].num_channels; j++)
{
cyhal_tcpwm_common_t* obj = cyhal_tcpwm_data_structs[GET_ARRAY_INDEX(i, j)];
if (obj && (CY_TCPWM_PWM_STATUS_COUNTER_RUNNING & Cy_TCPWM_PWM_GetStatus(obj->base, j)))
{
return false;
}
}
}
cyhal_tcpwm_pm_transition_pending_value = true;
break;
}
default:
{
break;
}
}
return true;
}
static cyhal_syspm_callback_data_t cyhal_tcpwm_syspm_callback_data =
{
.callback = &cyhal_tcpwm_pm_callback,
.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
.next = NULL,
.args = NULL,
.ignore_modes = CYHAL_SYSPM_BEFORE_TRANSITION,
};
void cyhal_tcpwm_init_data(cyhal_tcpwm_common_t *tcpwm)
{
if (!cyhal_tcpwm_pm_has_enabled())
{
cyhal_syspm_register_peripheral_callback(&cyhal_tcpwm_syspm_callback_data);
}
cyhal_tcpwm_data_structs[GET_ARRAY_INDEX(tcpwm->resource.block_num, tcpwm->resource.channel_num)] = tcpwm;
}
void cyhal_tcpwm_irq_handler(void)
{
IRQn_Type irqn = CYHAL_GET_CURRENT_IRQN();
uint8_t block, channel = 0;
@ -84,14 +170,12 @@ void cyhal_tcpwm_irq_handler()
if (block < CY_IP_MXTCPWM_INSTANCES)
{
TCPWM_Type *blockAddr = CYHAL_TCPWM_DATA[block].base;
uint32_t index = GET_ARRAY_INDEX(block, channel);
cyhal_event_callback_data_t *callback_data = cyhal_tcpwm_callback_data_structs[index];
if (callback_data->callback != NULL)
cyhal_tcpwm_common_t *tcpwm = cyhal_tcpwm_data_structs[GET_ARRAY_INDEX(block, channel)];
if (tcpwm->callback_data.callback != NULL)
{
cyhal_tcpwm_event_callback_t callback = (cyhal_tcpwm_event_callback_t) callback_data->callback;
cyhal_tcpwm_event_callback_t callback = (cyhal_tcpwm_event_callback_t) tcpwm->callback_data.callback;
/* Call registered callbacks here */
(void) (callback) (callback_data->callback_arg, Cy_TCPWM_GetInterruptStatus(blockAddr, channel));
(void) (callback) (tcpwm->callback_data.callback_arg, Cy_TCPWM_GetInterruptStatus(blockAddr, channel));
}
Cy_TCPWM_ClearInterrupt(blockAddr, channel, CY_TCPWM_INT_ON_CC_OR_TC);
@ -106,12 +190,46 @@ void cyhal_tcpwm_irq_handler()
* TCPWM Shared HAL Functions
*******************************************************************************/
void cyhal_tcpwm_free(cyhal_tcpwm_common_t *obj)
{
CY_ASSERT(NULL != obj);
IRQn_Type irqn = (IRQn_Type)(CYHAL_TCPWM_DATA[obj->resource.block_num].isr_offset + obj->resource.channel_num);
NVIC_DisableIRQ(irqn);
cyhal_utils_release_if_used(&(obj->pin));
if (NULL != obj->base)
{
cyhal_tcpwm_data_structs[GET_ARRAY_INDEX(obj->resource.block_num, obj->resource.channel_num)] = NULL;
if (!cyhal_tcpwm_pm_has_enabled())
{
cyhal_syspm_unregister_peripheral_callback(&cyhal_tcpwm_syspm_callback_data);
}
Cy_TCPWM_PWM_Disable(obj->base, obj->resource.channel_num);
cyhal_hwmgr_free(&(obj->resource));
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
}
if (obj->dedicated_clock)
{
cy_en_sysclk_status_t rslt = Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num);
CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
CY_ASSERT(CY_SYSCLK_SUCCESS == rslt);
cyhal_hwmgr_free_clock(&(obj->clock));
obj->dedicated_clock = false;
}
}
void cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg)
{
uint8_t index = GET_ARRAY_INDEX(resource->block_num, resource->channel_num);
uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
cyhal_tcpwm_callback_data_structs[index]->callback = callback;
cyhal_tcpwm_callback_data_structs[index]->callback_arg = callback_arg;
cyhal_tcpwm_data_structs[index]->callback_data.callback = callback;
cyhal_tcpwm_data_structs[index]->callback_data.callback_arg = callback_arg;
cyhal_system_critical_section_exit(savedIntrStatus);
IRQn_Type irqn = (IRQn_Type)(CYHAL_TCPWM_DATA[resource->block_num].isr_offset + resource->channel_num);
@ -124,7 +242,7 @@ void cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddres
}
}
void cyhal_tcpwm_enable_event(TCPWM_Type *type, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intrPriority, bool enable)
void cyhal_tcpwm_enable_event(TCPWM_Type *type, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable)
{
uint32_t old_mask = Cy_TCPWM_GetInterruptMask(type, resource->channel_num);
if (enable)
@ -135,7 +253,7 @@ void cyhal_tcpwm_enable_event(TCPWM_Type *type, cyhal_resource_inst_t *resource,
Cy_TCPWM_SetInterruptMask(type, resource->channel_num, enable ? (old_mask | event) : (old_mask & ~event));
IRQn_Type irqn = (IRQn_Type) (CYHAL_TCPWM_DATA[resource->block_num].isr_offset + resource->channel_num);
NVIC_SetPriority(irqn, intrPriority);
NVIC_SetPriority(irqn, intr_priority);
}
#if defined(__cplusplus)

View File

@ -28,6 +28,7 @@
#include "cyhal_timer_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_gpio.h"
#include "cyhal_syspm.h"
#if defined(CY_IP_MXTCPWM_INSTANCES)
@ -81,7 +82,7 @@ static inline uint32_t convert_direction(cyhal_timer_direction_t direction)
* Timer HAL Functions
*******************************************************************************/
cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_divider_t *clk)
cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk)
{
CY_ASSERT(NULL != obj);
@ -89,6 +90,7 @@ cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clo
if (CYHAL_NC_PIN_VALUE != pin)
return CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT;
memset(obj, 0, sizeof(cyhal_timer_t));
cy_rslt_t result = cyhal_hwmgr_allocate(CYHAL_RSC_TCPWM, &obj->resource);
if (CY_RSLT_SUCCESS == result)
{
@ -101,7 +103,6 @@ cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clo
if (NULL != clk)
{
obj->clock = *clk;
obj->dedicated_clock = false;
obj->clock_hz = Cy_SysClk_ClkPeriGetFrequency() / (1 + Cy_SysClk_PeriphGetDivider(obj->clock.div_type, obj->clock.div_num));
if (CY_SYSCLK_SUCCESS != Cy_SysClk_PeriphAssignDivider(pclk, clk->div_type, clk->div_num))
{
@ -128,7 +129,7 @@ cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clo
if (result == CY_RSLT_SUCCESS)
{
cyhal_tcpwm_init_callback_data(&(obj->resource), &(obj->callback_data));
cyhal_tcpwm_init_data(obj);
Cy_TCPWM_SetInterruptMask(obj->base, obj->resource.channel_num, CY_TCPWM_INT_NONE);
Cy_TCPWM_Counter_Enable(obj->base, obj->resource.channel_num);
}
@ -141,67 +142,24 @@ cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clo
return result;
}
void cyhal_timer_free(cyhal_timer_t *obj)
{
CY_ASSERT(NULL != obj);
IRQn_Type irqn = (IRQn_Type)(CYHAL_TCPWM_DATA[obj->resource.block_num].isr_offset + obj->resource.channel_num);
NVIC_DisableIRQ(irqn);
if (NULL != obj->base)
{
Cy_TCPWM_Counter_Disable(obj->base, obj->resource.channel_num);
cyhal_hwmgr_free(&obj->resource);
obj->base = NULL;
obj->resource.type = CYHAL_RSC_INVALID;
if (obj->dedicated_clock)
{
cy_en_sysclk_status_t rslt = Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num);
CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
CY_ASSERT(CY_SYSCLK_SUCCESS == rslt);
cyhal_hwmgr_free_clock(&(obj->clock));
obj->dedicated_clock = false;
}
}
}
cy_rslt_t cyhal_timer_configure(cyhal_timer_t *obj, const cyhal_timer_cfg_t *cfg)
{
cy_rslt_t rslt;
if (obj->is_continuous != cfg->is_continuous ||
obj->direction != cfg->direction ||
obj->is_compare != cfg->is_compare)
{
cy_stc_tcpwm_counter_config_t config = default_config;
config.period = cfg->period;
config.compare0 = cfg->compare_value;
config.runMode = cfg->is_continuous ? CY_TCPWM_COUNTER_CONTINUOUS : CY_TCPWM_COUNTER_ONESHOT;
config.compareOrCapture = cfg->is_compare ? CY_TCPWM_COUNTER_MODE_COMPARE : CY_TCPWM_COUNTER_MODE_CAPTURE;
config.countDirection = convert_direction(cfg->direction);
// DeInit will clear the interrupt mask; save it now and restore after we re-nit
uint32_t old_mask = Cy_TCPWM_GetInterruptMask(obj->base, obj->resource.channel_num);
Cy_TCPWM_Counter_DeInit(obj->base, obj->resource.channel_num, &config);
rslt = (cy_rslt_t)Cy_TCPWM_Counter_Init(obj->base, obj->resource.channel_num, &config);
Cy_TCPWM_SetInterruptMask(obj->base, obj->resource.channel_num, old_mask);
if (CY_TCPWM_SUCCESS == rslt)
{
obj->is_continuous = cfg->is_continuous;
obj->direction = cfg->direction;
obj->is_compare = cfg->is_compare;
}
}
else
{
Cy_TCPWM_Counter_SetCounter(obj->base, obj->resource.channel_num, cfg->value);
Cy_TCPWM_Counter_SetPeriod(obj->base, obj->resource.channel_num, cfg->period);
if (cfg->is_compare)
{
Cy_TCPWM_Counter_SetCompare0(obj->base, obj->resource.channel_num, cfg->compare_value);
}
rslt = CY_RSLT_SUCCESS;
}
obj->default_value = cfg->value;
cy_stc_tcpwm_counter_config_t config = default_config;
config.period = cfg->period;
config.compare0 = cfg->compare_value;
config.runMode = cfg->is_continuous ? CY_TCPWM_COUNTER_CONTINUOUS : CY_TCPWM_COUNTER_ONESHOT;
config.compareOrCapture = cfg->is_compare ? CY_TCPWM_COUNTER_MODE_COMPARE : CY_TCPWM_COUNTER_MODE_CAPTURE;
config.countDirection = convert_direction(cfg->direction);
// DeInit will clear the interrupt mask; save it now and restore after we re-nit
uint32_t old_mask = Cy_TCPWM_GetInterruptMask(obj->base, obj->resource.channel_num);
Cy_TCPWM_Counter_DeInit(obj->base, obj->resource.channel_num, &config);
rslt = (cy_rslt_t)Cy_TCPWM_Counter_Init(obj->base, obj->resource.channel_num, &config);
Cy_TCPWM_SetInterruptMask(obj->base, obj->resource.channel_num, old_mask);
// This must be called after Cy_TCPWM_Counter_Init
cyhal_timer_reset(obj);
return rslt;
}
@ -236,7 +194,11 @@ cy_rslt_t cyhal_timer_set_frequency(cyhal_timer_t *obj, uint32_t hz)
cy_rslt_t cyhal_timer_start(cyhal_timer_t *obj)
{
CY_ASSERT(NULL != obj);
Cy_TCPWM_TriggerReloadOrIndex(obj->base, 1u << obj->resource.channel_num);
if (cyhal_tcpwm_pm_transition_pending())
{
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
}
Cy_TCPWM_TriggerStart(obj->base, 1u << obj->resource.channel_num);
return CY_RSLT_SUCCESS;
}
@ -247,6 +209,18 @@ cy_rslt_t cyhal_timer_stop(cyhal_timer_t *obj)
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_timer_reset(cyhal_timer_t *obj)
{
CY_ASSERT(NULL != obj);
bool is_running = CY_TCPWM_PWM_STATUS_COUNTER_RUNNING & Cy_TCPWM_PWM_GetStatus(obj->base, obj->resource.channel_num);
if (is_running)
Cy_TCPWM_TriggerStopOrKill(obj->base, 1u << obj->resource.channel_num);
Cy_TCPWM_Counter_SetCounter(obj->base, obj->resource.channel_num, obj->default_value);
if (is_running)
Cy_TCPWM_TriggerStart(obj->base, 1u << obj->resource.channel_num);
return CY_RSLT_SUCCESS;
}
uint32_t cyhal_timer_read(const cyhal_timer_t *obj)
{
CY_ASSERT(NULL != obj);

View File

@ -26,6 +26,7 @@
#include "cyhal_hwmgr.h"
#include "cyhal_crypto_common.h"
#include "cyhal_trng_impl.h"
#include "cy_utils.h"
#if defined(CY_IP_MXCRYPTO)

View File

@ -27,9 +27,9 @@
#include "cyhal_uart.h"
#include "cyhal_scb_common.h"
#include "cyhal_gpio.h"
#include "cyhal_interconnect.h"
#include "cyhal_system_impl.h"
#include "cyhal_hwmgr.h"
#include "cyhal_syspm.h"
#ifdef CY_IP_MXSCB
@ -95,19 +95,28 @@ static void cyhal_uart_cb_wrapper(uint32_t event)
callback(obj->callback_data.callback_arg, anded_events);
}
}
static cy_en_syspm_status_t cyhal_uart_pm_callback(cy_stc_syspm_callback_params_t *params, cy_en_syspm_callback_mode_t mode)
static bool cyhal_uart_pm_callback_instance(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
{
cyhal_uart_t *obj = params->context;
cy_stc_syspm_callback_params_t pdl_params = { .base = obj->base, .context = &(obj->context) };
cy_en_syspm_status_t rslt = Cy_SCB_UART_DeepSleepCallback(&pdl_params, mode);
GPIO_PRT_Type *txport = obj->pin_tx != NC ? CYHAL_GET_PORTADDR(obj->pin_tx) : NULL,
*rtsport = obj->pin_rts != NC ? CYHAL_GET_PORTADDR(obj->pin_rts) : NULL;
uint8_t txpin = (uint8_t)CYHAL_GET_PIN(obj->pin_tx), rtspin = (uint8_t)CYHAL_GET_PIN(obj->pin_rts);
switch (mode)
cyhal_uart_t *obj = (cyhal_uart_t*)obj_ptr;
bool allow = true;
cy_stc_syspm_callback_params_t uart_callback_params = {
.base = (void *) (obj->base),
.context = (void *) &(obj->context)
};
// The output pins need to be set to high before going to deepsleep.
// Otherwise the UART on the other side would see incoming data as '0'.
GPIO_PRT_Type *txport = obj->pin_tx != NC ? CYHAL_GET_PORTADDR(obj->pin_tx) : NULL;
GPIO_PRT_Type *rtsport = obj->pin_rts != NC ? CYHAL_GET_PORTADDR(obj->pin_rts) : NULL;
uint8_t txpin = (uint8_t)CYHAL_GET_PIN(obj->pin_tx);
uint8_t rtspin = (uint8_t)CYHAL_GET_PIN(obj->pin_rts);
cy_en_syspm_status_t ret_status = Cy_SCB_UART_DeepSleepCallback(&uart_callback_params, pdl_mode);
switch (pdl_mode)
{
case CY_SYSPM_CHECK_READY:
if (rslt == CY_SYSPM_SUCCESS)
if (CY_SYSPM_SUCCESS == ret_status)
{
if (NULL != txport)
{
@ -122,9 +131,13 @@ static cy_en_syspm_status_t cyhal_uart_pm_callback(cy_stc_syspm_callback_params_
Cy_GPIO_SetHSIOM(rtsport, rtspin, HSIOM_SEL_GPIO);
}
}
else
{
allow = false;
}
break;
case CY_SYSPM_CHECK_FAIL: // fallthrough
case CY_SYSPM_CHECK_FAIL:
case CY_SYSPM_AFTER_TRANSITION:
if (NULL != txport)
{
@ -136,12 +149,15 @@ static cy_en_syspm_status_t cyhal_uart_pm_callback(cy_stc_syspm_callback_params_
}
break;
case CY_SYSPM_BEFORE_TRANSITION:
break;
default:
CY_ASSERT(false);
break;
}
return rslt;
return allow;
}
static cy_en_scb_uart_parity_t convert_parity(cyhal_uart_parity_t parity)
{
switch (parity)
@ -175,9 +191,10 @@ static cy_en_scb_uart_stop_bits_t convert_stopbits(uint8_t stopbits)
}
}
cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, const cyhal_clock_divider_t *clk, const cyhal_uart_cfg_t *cfg)
cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, const cyhal_clock_t *clk, const cyhal_uart_cfg_t *cfg)
{
CY_ASSERT(NULL != obj);
memset(obj, 0, sizeof(cyhal_uart_t));
// Explicitly marked not allocated resources as invalid to prevent freeing them.
obj->resource.type = CYHAL_RSC_INVALID;
@ -188,12 +205,11 @@ cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, c
obj->pin_rts = CYHAL_NC_PIN_VALUE;
cy_rslt_t result = CY_RSLT_SUCCESS;
cyhal_resource_inst_t pin_rsc;
// Reserve the UART
const cyhal_resource_pin_mapping_t *tx_map = CY_UTILS_GET_RESOURCE(tx, cyhal_pin_map_scb_uart_tx);
const cyhal_resource_pin_mapping_t *rx_map = CY_UTILS_GET_RESOURCE(rx, cyhal_pin_map_scb_uart_rx);
if (NULL == tx_map || NULL == rx_map || tx_map->inst->block_num != rx_map->inst->block_num)
const cyhal_resource_pin_mapping_t *tx_map = CYHAL_FIND_SCB_MAP(tx, cyhal_pin_map_scb_uart_tx);
const cyhal_resource_pin_mapping_t *rx_map = CYHAL_FIND_SCB_MAP(rx, cyhal_pin_map_scb_uart_rx);
if (NULL == tx_map || NULL == rx_map || !cyhal_utils_resources_equal(tx_map->inst, rx_map->inst))
{
return CYHAL_UART_RSLT_ERR_INVALID_PIN;
}
@ -203,28 +219,22 @@ cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, c
return result;
obj->resource = rsc;
obj->base = CYHAL_SCB_BASE_ADDRESSES[obj->resource.block_num];
// reserve the TX pin
pin_rsc = cyhal_utils_get_gpio_resource(tx);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(tx, tx_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_tx = tx;
}
//reseve the RX pin
if (result == CY_RSLT_SUCCESS)
{
pin_rsc = cyhal_utils_get_gpio_resource(rx);
result = cyhal_hwmgr_reserve(&pin_rsc);
//reseve the RX pin
result = cyhal_utils_reserve_and_connect(rx, rx_map);
if (result == CY_RSLT_SUCCESS)
{
obj->pin_rx = rx;
}
}
obj->base = CYHAL_SCB_BASE_ADDRESSES[obj->resource.block_num];
if (result == CY_RSLT_SUCCESS)
{
if (clk == NULL)
@ -244,14 +254,6 @@ cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, c
result = (cy_rslt_t)Cy_SysClk_PeriphAssignDivider(
(en_clk_dst_t)((uint8_t)PCLK_SCB0_CLOCK + obj->resource.block_num), obj->clock.div_type, obj->clock.div_num);
}
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_connect_pin(rx_map);
}
if (result == CY_RSLT_SUCCESS)
{
result = cyhal_connect_pin(tx_map);
}
if (result == CY_RSLT_SUCCESS)
{
@ -273,26 +275,16 @@ cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, c
}
}
obj->pm_params.base = obj->base;
obj->pm_params.context = obj;
obj->pm_callback.callback = &cyhal_uart_pm_callback;
obj->pm_callback.type = CY_SYSPM_DEEPSLEEP;
obj->pm_callback.skipMode = 0;
obj->pm_callback.callbackParams = &(obj->pm_params);
obj->pm_callback.prevItm = NULL;
obj->pm_callback.nextItm = NULL;
if (!Cy_SysPm_RegisterCallback(&(obj->pm_callback)))
result = CYHAL_UART_RSLT_ERR_PM_CALLBACK;
obj->callback_data.callback = NULL;
obj->callback_data.callback_arg = NULL;
obj->irq_cause = CYHAL_UART_IRQ_NONE;
cyhal_scb_config_structs[obj->resource.block_num] = obj;
cy_stc_sysint_t irqCfg = { CYHAL_SCB_IRQ_N[obj->resource.block_num], CYHAL_ISR_PRIORITY_DEFAULT };
Cy_SysInt_Init(&irqCfg, cyhal_uart_irq_handler);
NVIC_EnableIRQ(CYHAL_SCB_IRQ_N[obj->resource.block_num]);
cyhal_scb_update_instance_data(obj->resource.block_num, (void*)obj, &cyhal_uart_pm_callback_instance);
if (obj->is_user_clock)
{
Cy_SCB_UART_Enable(obj->base);
@ -320,7 +312,8 @@ void cyhal_uart_free(cyhal_uart_t *obj)
NVIC_DisableIRQ(irqn);
cyhal_hwmgr_free(&(obj->resource));
Cy_SysPm_UnregisterCallback(&(obj->pm_callback));
cyhal_scb_update_instance_data(obj->resource.block_num, NULL, NULL);
}
cyhal_utils_release_if_used(&(obj->pin_rx));
@ -341,40 +334,25 @@ static uint32_t cyhal_uart_actual_baud(uint32_t divider, uint32_t oversample)
static uint32_t cyhal_uart_baud_perdif(uint32_t desired_baud, uint32_t actual_baud)
{
uint32_t perdif;
if(actual_baud > desired_baud)
{
perdif = ((actual_baud * 100) - (desired_baud * 100)) / desired_baud;
}
else
{
perdif = ((desired_baud * 100) - (actual_baud * 100)) / desired_baud;
}
return perdif;
return (actual_baud > desired_baud)
? ((actual_baud * 100) - (desired_baud * 100)) / desired_baud
: ((desired_baud * 100) - (actual_baud * 100)) / desired_baud;
}
static uint8_t cyhal_uart_best_oversample(uint32_t baudrate)
{
uint8_t differences[UART_OVERSAMPLE_MAX + 1];
uint8_t index;
uint32_t divider;
for(index = UART_OVERSAMPLE_MIN; index < UART_OVERSAMPLE_MAX + 1; index++)
{
divider = cyhal_divider_value(baudrate * index, 0);
differences[index] = cyhal_uart_baud_perdif(baudrate, cyhal_uart_actual_baud(divider, index));
}
uint8_t best_oversample = UART_OVERSAMPLE_MIN;
uint8_t best_difference = differences[UART_OVERSAMPLE_MIN];
uint8_t best_difference = 0xFF;
for(index = UART_OVERSAMPLE_MIN; index < UART_OVERSAMPLE_MAX + 1; index++)
for (uint8_t i = UART_OVERSAMPLE_MIN; i < UART_OVERSAMPLE_MAX + 1; i++)
{
if(differences[index] < best_difference)
uint32_t divider = cyhal_divider_value(baudrate * i, 0);
uint8_t difference = cyhal_uart_baud_perdif(baudrate, cyhal_uart_actual_baud(divider, i));
if (difference < best_difference)
{
best_difference = differences[index];
best_oversample = index;
best_difference = difference;
best_oversample = i;
}
}
@ -413,9 +391,11 @@ cy_rslt_t cyhal_uart_set_baud(cyhal_uart_t *obj, uint32_t baudrate, uint32_t *ac
calculated_baud = cyhal_uart_actual_baud(divider, oversample_value);
if(actualbaud != NULL) *actualbaud = calculated_baud;
if (actualbaud != NULL)
*actualbaud = calculated_baud;
uint32_t baud_difference = cyhal_uart_baud_perdif(baudrate, calculated_baud);
if(baud_difference > CYHAL_UART_MAX_BAUD_PERCENT_DIFFERENCE) status = CY_RSLT_WRN_CSP_UART_BAUD_TOLERANCE;
if (baud_difference > CYHAL_UART_MAX_BAUD_PERCENT_DIFFERENCE)
status = CY_RSLT_WRN_CSP_UART_BAUD_TOLERANCE;
Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num);
@ -445,6 +425,9 @@ cy_rslt_t cyhal_uart_configure(cyhal_uart_t *obj, const cyhal_uart_cfg_t *cfg)
cy_rslt_t cyhal_uart_getc(cyhal_uart_t *obj, uint8_t *value, uint32_t timeout)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint32_t read_value = Cy_SCB_UART_Get(obj->base);
uint32_t timeoutTicks = timeout;
while (read_value == CY_SCB_UART_RX_NO_DATA)
@ -469,6 +452,9 @@ cy_rslt_t cyhal_uart_getc(cyhal_uart_t *obj, uint8_t *value, uint32_t timeout)
cy_rslt_t cyhal_uart_putc(cyhal_uart_t *obj, uint32_t value)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
uint32_t count = 0;
while (count == 0)
{
@ -508,41 +494,29 @@ cy_rslt_t cyhal_uart_clear(cyhal_uart_t *obj)
cy_rslt_t cyhal_uart_set_flow_control(cyhal_uart_t *obj, cyhal_gpio_t cts, cyhal_gpio_t rts)
{
cy_rslt_t result = CY_RSLT_SUCCESS;
cyhal_resource_inst_t pin_rsc;
if (cts != obj->pin_cts)
{
if (NC == cts)
{
if(obj->pin_cts != NC)
if (obj->pin_cts != NC)
{
result = cyhal_disconnect_pin(obj->pin_cts);
if (CY_RSLT_SUCCESS == result)
{
Cy_SCB_UART_DisableCts(obj->base);
pin_rsc = cyhal_utils_get_gpio_resource(obj->pin_cts);
cyhal_hwmgr_free(&pin_rsc);
}
cyhal_utils_disconnect_and_free(obj->pin_cts);
Cy_SCB_UART_DisableCts(obj->base);
}
}
else
{
const cyhal_resource_pin_mapping_t *cts_map = CY_UTILS_GET_RESOURCE(cts, cyhal_pin_map_scb_uart_cts);
if (obj->resource.block_num != cts_map->inst->block_num ||
obj->resource.channel_num != cts_map->inst->channel_num)
if (!cyhal_utils_resources_equal(&(obj->resource), cts_map->inst))
{
return CYHAL_UART_RSLT_ERR_INVALID_PIN;
}
pin_rsc = cyhal_utils_get_gpio_resource(cts);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(cts, cts_map);
if (CY_RSLT_SUCCESS == result)
{
Cy_SCB_UART_EnableCts(obj->base);
result = cyhal_connect_pin(cts_map);
}
}
@ -552,37 +526,25 @@ cy_rslt_t cyhal_uart_set_flow_control(cyhal_uart_t *obj, cyhal_gpio_t cts, cyhal
}
obj->pin_cts = cts;
}
if (rts != obj->pin_rts)
{
if (NC == rts)
{
if(obj->pin_rts != NC)
if (obj->pin_rts != NC)
{
result = cyhal_disconnect_pin(obj->pin_rts);
if (CY_RSLT_SUCCESS == result)
{
pin_rsc = cyhal_utils_get_gpio_resource(obj->pin_rts);
cyhal_hwmgr_free(&pin_rsc);
}
cyhal_utils_disconnect_and_free(obj->pin_rts);
}
}
else
{
const cyhal_resource_pin_mapping_t *rts_map = CY_UTILS_GET_RESOURCE(rts, cyhal_pin_map_scb_uart_rts);
if (obj->resource.block_num != rts_map->inst->block_num ||
obj->resource.channel_num != rts_map->inst->channel_num)
if (!cyhal_utils_resources_equal(&(obj->resource), rts_map->inst))
{
return CYHAL_UART_RSLT_ERR_INVALID_PIN;
}
pin_rsc = cyhal_utils_get_gpio_resource(rts);
result = cyhal_hwmgr_reserve(&pin_rsc);
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(rts_map);
}
result = cyhal_utils_reserve_and_connect(rts, rts_map);
}
if (result != CY_RSLT_SUCCESS)
@ -596,35 +558,41 @@ cy_rslt_t cyhal_uart_set_flow_control(cyhal_uart_t *obj, cyhal_gpio_t cts, cyhal
cy_rslt_t cyhal_uart_write(cyhal_uart_t *obj, void *tx, size_t *tx_length)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
*tx_length = Cy_SCB_UART_PutArray(obj->base, tx, *tx_length);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_uart_read(cyhal_uart_t *obj, void *rx, size_t *rx_length)
{
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
*rx_length = Cy_SCB_UART_GetArray(obj->base, rx, *rx_length);
return CY_RSLT_SUCCESS;
}
cy_rslt_t cyhal_uart_write_async(cyhal_uart_t *obj, void *tx, size_t length)
{
cy_en_scb_uart_status_t uart_status = Cy_SCB_UART_Transmit(obj->base, tx, length, &(obj->context));
return uart_status == CY_SCB_UART_SUCCESS
? CY_RSLT_SUCCESS
: CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 0);
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
return Cy_SCB_UART_Transmit(obj->base, tx, length, &(obj->context));
}
cy_rslt_t cyhal_uart_read_async(cyhal_uart_t *obj, void *rx, size_t length)
{
cy_en_scb_uart_status_t uart_status = Cy_SCB_UART_Receive(obj->base, rx, length, &(obj->context));
return uart_status == CY_SCB_UART_SUCCESS
? CY_RSLT_SUCCESS
: CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_UART, 0);
if (cyhal_scb_pm_transition_pending())
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
return Cy_SCB_UART_Receive(obj->base, rx, length, &(obj->context));
}
bool cyhal_uart_is_tx_active(cyhal_uart_t *obj)
{
return (0UL != (obj->context.txStatus & CY_SCB_UART_TRANSMIT_ACTIVE));
return (0UL != (obj->context.txStatus & CY_SCB_UART_TRANSMIT_ACTIVE)) || !Cy_SCB_IsTxComplete(obj->base);
}
bool cyhal_uart_is_rx_active(cyhal_uart_t *obj)
@ -691,7 +659,7 @@ void cyhal_uart_register_callback(cyhal_uart_t *obj, cyhal_uart_event_callback_t
obj->irq_cause = CYHAL_UART_IRQ_NONE;
}
void cyhal_uart_enable_event(cyhal_uart_t *obj, cyhal_uart_event_t event, uint8_t intrPriority, bool enable)
void cyhal_uart_enable_event(cyhal_uart_t *obj, cyhal_uart_event_t event, uint8_t intr_priority, bool enable)
{
if (enable)
{
@ -720,7 +688,7 @@ void cyhal_uart_enable_event(cyhal_uart_t *obj, cyhal_uart_event_t event, uint8_
}
}
NVIC_SetPriority(CYHAL_SCB_IRQ_N[obj->resource.block_num], intrPriority);
NVIC_SetPriority(CYHAL_SCB_IRQ_N[obj->resource.block_num], intr_priority);
}
#if defined(__cplusplus)

View File

@ -23,6 +23,40 @@
* limitations under the License.
*******************************************************************************/
/**
* \addtogroup group_hal_psoc6_udb_sdio UDB SDIO (Secure Digital Input Output)
* \ingroup group_hal_psoc6
* \{
* The UDB based SDIO interface allows for communicating between a PSoC 6 and a
* Cypress wireless device such as the CYW4343W, CYW43438, or CYW43012. This
* library allows PSoC 6 devices that do not have a dedicated SDHC hardware block,
* but do have UDBs, to work with the
* <a href="https://github.com/cypresssemiconductorco/wifi-host-driver">Wi-Fi
* Host Driver (WHD)</a> library.
*
* \warning This library does not provide a complete SDIO implementation. It is
* only intended for use with a Cypress wireless device. Additionally, using this
* driver imposes a few system wide requirements, described below, that must be
* met to work properly.
*
* \section section_psoc6_udb_sdio_restrictions Restrictions
* The optimal configuration is to have ClkSlow & ClkPeri running at 100 MHz
* and for the SDIO to run at 25 MHz. For Cypress provided Board Support Packages
* (BSPs) that use this driver the necessary configuration is done automatically.
*
* To use this library, the following must be true:
* 1. ClkSlow & ClkPeri must both run at the same speed
* 2. ClkSlow & ClkPeri must run at 4x the desired SDIO speed
* 3. The first 8-bit peripheral clock divider must be reserved for use by this driver
* 4. The following DMA channels must be reserved for use by this driver
* * DataWire 0 channel 0
* * DataWire 0 channel 1
* * DataWire 1 channel 1
* * DataWire 1 channel 3
*
* \} group_hal_psoc6_udb_sdio
*/
#include "cyhal_hwmgr.h"
#include "cy_utils.h"
@ -39,6 +73,7 @@ extern "C"
#include "cyhal_sdio.h"
#include "cyhal_gpio.h"
#include "cyhal_interconnect.h"
#include "cyhal_syspm.h"
#define CY_HAL_SDIO_CLK_DIV_VALUE ((uint8_t) 0xFF)
@ -66,30 +101,12 @@ extern "C"
static cyhal_sdio_event_callback_t cyhal_sdio_callback = NULL;
static cyhal_sdio_t *cyhal_sdio_config_struct = NULL;
static void *cyhal_sdio_callback_args = NULL;
static bool deep_sleep_pending = false;
static bool op_pending = false;
/*******************************************************************************
* (Internal) Configuration structures for SDIO pins
*******************************************************************************/
static const cy_stc_gpio_pin_config_t pin_cmd_config =
{
.outVal = 1,
.driveMode = CY_GPIO_DM_STRONG,
.hsiom = HSIOM_SEL_DSI_DSI, /* DSI controls 'out' and 'output enable' */
.intEdge = CY_GPIO_INTR_DISABLE,
.intMask = 0UL,
.vtrip = CY_GPIO_VTRIP_CMOS,
.slewRate = CY_GPIO_SLEW_FAST,
.driveSel = CY_GPIO_DRIVE_1_2,
.vregEn = 0UL,
.ibufMode = 0UL,
.vtripSel = 0UL,
.vrefSel = 0UL,
.vohSel = 0UL,
};
static const cy_stc_gpio_pin_config_t pin_data_config =
static const cy_stc_gpio_pin_config_t pin_config =
{
.outVal = 1,
.driveMode = CY_GPIO_DM_STRONG,
@ -126,30 +143,7 @@ static const cy_stc_gpio_pin_config_t pin_clk_config =
/*******************************************************************************
* Internal functions
*******************************************************************************/
static cy_en_syspm_status_t cyhal_sdio_ds_callback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
/******************************************************************************
* Parameter structure for Deep Sleep callback function
******************************************************************************/
static cy_stc_syspm_callback_params_t cyhal_sdio_pm_callback_params =
{
NULL,
NULL
};
/******************************************************************************
* Deep Sleep callback
******************************************************************************/
static cy_stc_syspm_callback_t cyhal_sdio_pm_callback =
{
&cyhal_sdio_ds_callback,
CY_SYSPM_DEEPSLEEP,
0U,
&cyhal_sdio_pm_callback_params,
NULL,
NULL,
CYHAL_SDIO_DS_CB_ORDER
};
static bool cyhal_sdio_ds_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
/* Internal deep sleep callback, which does following:
* 1. Save/restore not retained configuration registers in the Deep Sleep
@ -158,18 +152,27 @@ static cy_stc_syspm_callback_t cyhal_sdio_pm_callback =
* 3. Execute registered callback with CYHAL_SDIO_COMING_UP event, after
* exit from Deep Sleep
* */
cy_en_syspm_status_t cyhal_sdio_ds_callback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
static bool cyhal_sdio_ds_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
cy_en_syspm_status_t retVal = SDIO_DeepSleepCallback(callbackParams, mode);
static cy_stc_syspm_callback_params_t cyhal_sdio_pm_callback_params = { NULL, NULL };
bool allow = true;
cyhal_sdio_t *obj = (cyhal_sdio_t *)callback_arg;
CY_ASSERT(obj != NULL);
if (retVal == CY_SYSPM_SUCCESS)
if(state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP)
{
allow = (SDIO_DeepSleepCallback(&cyhal_sdio_pm_callback_params, cyhal_utils_convert_haltopdl_pm_mode(mode)) == CY_SYSPM_SUCCESS);
}
if (allow)
{
switch (mode)
{
case CY_SYSPM_CHECK_READY:
case CYHAL_SYSPM_CHECK_READY:
{
/* Check if transfer is pending */
if (!op_pending)
allow = !op_pending;
if (allow)
{
/* Execute callback to indicate that interface is going down */
if ((cyhal_sdio_callback != NULL) && (0U != (cyhal_sdio_config_struct->events & (uint32_t) CYHAL_SDIO_GOING_DOWN)))
@ -178,26 +181,23 @@ cy_en_syspm_status_t cyhal_sdio_ds_callback(cy_stc_syspm_callback_params_t *call
}
/* Indicate Deep Sleep entering */
deep_sleep_pending = true;
}
else
{
retVal = CY_SYSPM_FAIL;
obj->pm_transition_pending = true;
}
break;
}
case CY_SYSPM_BEFORE_TRANSITION:
case CYHAL_SYSPM_BEFORE_TRANSITION:
{
/* Nothing to do in this mode */
/* Nothing to do */
break;
}
case CY_SYSPM_AFTER_TRANSITION:
case CY_SYSPM_CHECK_FAIL:
case CYHAL_SYSPM_AFTER_TRANSITION:
case CYHAL_SYSPM_CHECK_FAIL:
{
/* Execute this only if check ready case was executed */
if (deep_sleep_pending)
if (obj->pm_transition_pending)
{
/* Execute callback to indicate that interface is coming up */
if ((cyhal_sdio_callback != NULL) && (0U != (cyhal_sdio_config_struct->events & (uint32_t) CYHAL_SDIO_COMING_UP)))
@ -205,18 +205,18 @@ cy_en_syspm_status_t cyhal_sdio_ds_callback(cy_stc_syspm_callback_params_t *call
(void)(cyhal_sdio_callback)(cyhal_sdio_callback_args, CYHAL_SDIO_COMING_UP);
}
/* Indicate Deep Sleep exit */
deep_sleep_pending = false;
/* Indicate PM mode transition exit */
obj->pm_transition_pending = false;
}
break;
}
default:
CY_ASSERT(false);
break;
}
}
return retVal;
return allow;
}
@ -263,6 +263,19 @@ static void cyhal_free_dmas()
cyhal_hwmgr_free(&dmaRsc);
}
cy_rslt_t cyhal_sdio_configure_pin(
cyhal_gpio_t pin, cyhal_gpio_t *pin_ref, const cy_stc_gpio_pin_config_t* cfg)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(pin);
cy_rslt_t result = cyhal_hwmgr_reserve(&pinRsc);
if (result == CY_RSLT_SUCCESS)
{
*pin_ref = pin;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), cfg);
}
return result;
}
cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk, cyhal_gpio_t data0, cyhal_gpio_t data1, cyhal_gpio_t data2, cyhal_gpio_t data3)
{
CY_ASSERT(NULL != obj);
@ -342,76 +355,30 @@ cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk,
retVal = cyhal_hwmgr_reserve(&dmaRsc);
}
/* Reserve the clk pin */
/* Reserve the clk, cmd & 4 data pins */
if (retVal == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(clk);
retVal = cyhal_hwmgr_reserve(&pinRsc);
if (retVal == CY_RSLT_SUCCESS)
{
obj->pin_clk = clk;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(clk), CYHAL_GET_PIN(clk), &pin_clk_config);
}
retVal = cyhal_sdio_configure_pin(clk, &obj->pin_clk, &pin_clk_config);
}
/* Reserve the cmd pin */
if (retVal == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(cmd);
retVal = cyhal_hwmgr_reserve(&pinRsc);
if (retVal == CY_RSLT_SUCCESS)
{
obj->pin_cmd = cmd;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(cmd), CYHAL_GET_PIN(cmd), &pin_cmd_config);
}
retVal = cyhal_sdio_configure_pin(cmd, &obj->pin_cmd, &pin_config);
}
/* Reserve the data0 pin */
if (retVal == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(data0);
retVal = cyhal_hwmgr_reserve(&pinRsc);
if (retVal == CY_RSLT_SUCCESS)
{
obj->pin_data0 = data0;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(data0), CYHAL_GET_PIN(data0), &pin_data_config);
}
retVal = cyhal_sdio_configure_pin(data0, &obj->pin_data0, &pin_config);
}
/* Reserve the data1 pin */
if (retVal == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(data1);
retVal = cyhal_hwmgr_reserve(&pinRsc);
if (retVal == CY_RSLT_SUCCESS)
{
obj->pin_data1 = data1;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(data1), CYHAL_GET_PIN(data1), &pin_data_config);
}
retVal = cyhal_sdio_configure_pin(data1, &obj->pin_data1, &pin_config);
}
/* Reserve the data2 pin */
if (retVal == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(data2);
retVal = cyhal_hwmgr_reserve(&pinRsc);
if (retVal == CY_RSLT_SUCCESS)
{
obj->pin_data2 = data2;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(data2), CYHAL_GET_PIN(data2), &pin_data_config);
}
retVal = cyhal_sdio_configure_pin(data2, &obj->pin_data2, &pin_config);
}
/* Reserve the data3 pin */
if (retVal == CY_RSLT_SUCCESS)
{
cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(data3);
retVal = cyhal_hwmgr_reserve(&pinRsc);
if (retVal == CY_RSLT_SUCCESS)
{
obj->pin_data3 = data3;
Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(data3), CYHAL_GET_PIN(data3), &pin_data_config);
}
retVal = cyhal_sdio_configure_pin(data3, &obj->pin_data3, &pin_config);
}
/* Reserve UDB SDIO */
@ -457,12 +424,18 @@ cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk,
obj->events = 0u;
/* Register SDIO Deep Sleep Callback */
if (retVal == CY_RSLT_SUCCESS)
if (CY_RSLT_SUCCESS == retVal)
{
if (!Cy_SysPm_RegisterCallback(&cyhal_sdio_pm_callback))
{
retVal = CY_RSLT_TYPE_ERROR;
}
obj->pm_callback_data.callback = &cyhal_sdio_ds_callback,
obj->pm_callback_data.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
obj->pm_callback_data.next = NULL;
obj->pm_callback_data.args = obj;
/* The CYHAL_SYSPM_BEFORE_TRANSITION mode cannot be ignored because the PM handler
* calls the SDIO host driver callback that saves UDB state in this mode before transitioning.
*/
obj->pm_callback_data.ignore_modes = (cyhal_syspm_callback_mode_t)0;
cyhal_syspm_register_peripheral_callback(&obj->pm_callback_data);
}
}
}
@ -495,8 +468,7 @@ void cyhal_sdio_free(cyhal_sdio_t *obj)
cyhal_hwmgr_free(&(obj->resource));
SDIO_Free();
/* Unregister SDIO Deep Sleep Callback */
(void)Cy_SysPm_UnregisterCallback(&cyhal_sdio_pm_callback);
cyhal_syspm_unregister_peripheral_callback(&obj->pm_callback_data);
}
cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
@ -528,6 +500,11 @@ cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t directio
return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
}
if (obj->pm_transition_pending)
{
return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
}
uint32_t cmdResponse;
stc_sdio_cmd_t cmd;
en_sdio_result_t status;
@ -553,24 +530,23 @@ cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t directio
cmd.u16BlockSize = 0U; /* Not used */
/* Send command only if there is no attempts to enter into Deep Sleep */
if (!deep_sleep_pending)
status = SDIO_SendCommandAndWait(&cmd);
if (Ok != status)
{
status = SDIO_SendCommandAndWait(&cmd);
if (Ok != status)
{
retVal = CYHAL_SDIO_RSLT_ERR_FUNC_RET(status);
}
else
{
retVal = CY_RSLT_SUCCESS;
}
if (response != NULL)
{
*response = cmdResponse;
}
retVal = CYHAL_SDIO_RSLT_ERR_FUNC_RET(status);
}
else
{
retVal = CY_RSLT_SUCCESS;
}
if (response != NULL)
{
*response = cmdResponse;
}
/* Indicate finished operation */
op_pending = false;
@ -582,6 +558,11 @@ cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t directio
cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument, const uint32_t* data, uint16_t length, uint32_t* response)
{
CY_ASSERT(NULL != obj);
if (obj->pm_transition_pending)
{
return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
}
cy_rslt_t retVal = CYHAL_SDIO_RSLT_CANCELED;
/* Check other pending operations */
@ -618,24 +599,20 @@ cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction
cmd.u16BlockSize = length;
}
/* Start transfer only if there is no attempts to enter into Deep Sleep */
if (!deep_sleep_pending)
status = SDIO_SendCommandAndWait(&cmd);
if (Ok != status)
{
status = SDIO_SendCommandAndWait(&cmd);
retVal = CYHAL_SDIO_RSLT_ERR_FUNC_RET(status);
}
else
{
retVal = CY_RSLT_SUCCESS;
}
if (Ok != status)
{
retVal = CYHAL_SDIO_RSLT_ERR_FUNC_RET(status);
}
else
{
retVal = CY_RSLT_SUCCESS;
}
if (response != NULL)
{
*response = cmdResponse;
}
if (response != NULL)
{
*response = cmdResponse;
}
/* Indicate finished transfer */
@ -681,7 +658,7 @@ void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_event_callback_t
cyhal_sdio_callback_args = callback_arg;
}
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intrPriority, bool enable)
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intr_priority, bool enable)
{
/* Only CYHAL_SDIO_CARD_INTERRUPT event can be registered */
if (event == CYHAL_SDIO_CARD_INTERRUPT)
@ -725,7 +702,7 @@ void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_
cyhal_sdio_config_struct->events = obj->events;
}
NVIC_SetPriority(udb_interrupts_0_IRQn, intrPriority);
NVIC_SetPriority(udb_interrupts_0_IRQn, intr_priority);
}
#if defined(__cplusplus)

View File

@ -28,7 +28,7 @@
#include "cyhal_usb_dev.h"
#include "cyhal_gpio.h"
#include "cyhal_hwmgr.h"
#include "cyhal_interconnect.h"
#include "cyhal_syspm.h"
#include "cyhal_utils.h"
#if defined(CY_IP_MXUSBFS)
@ -105,7 +105,7 @@ static cy_rslt_t cyhal_usb_dev_reseve_pll(cyhal_resource_inst_t *rsc);
static cy_rslt_t cyhal_usb_dev_init_pll(uint32_t clock, uint32_t pll, uint32_t target_freq);
static uint32_t cyhal_usb_dev_get_pll_freq(uint32_t path);
static cy_rslt_t cyhal_usb_dev_hf_clock_setup(cyhal_usb_dev_t *obj);
static cy_rslt_t cyhal_usb_dev_peri_clock_setup(cyhal_usb_dev_t *obj, const cyhal_clock_divider_t *clk);
static cy_rslt_t cyhal_usb_dev_peri_clock_setup(cyhal_usb_dev_t *obj, const cyhal_clock_t *clk);
static cy_rslt_t cyhal_usb_dev_pin_setup(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t dm);
static void cyhal_usb_dev_free_resources(cyhal_usb_dev_t *obj);
@ -373,7 +373,7 @@ static cy_rslt_t cyhal_usb_dev_hf_clock_setup(cyhal_usb_dev_t *obj)
return result;
}
static cy_rslt_t cyhal_usb_dev_peri_clock_setup(cyhal_usb_dev_t *obj, const cyhal_clock_divider_t *clk)
static cy_rslt_t cyhal_usb_dev_peri_clock_setup(cyhal_usb_dev_t *obj, const cyhal_clock_t *clk)
{
cy_rslt_t result;
cy_en_sysclk_status_t status = CY_SYSCLK_BAD_PARAM;
@ -419,32 +419,22 @@ static cy_rslt_t cyhal_usb_dev_pin_setup(cyhal_usb_dev_t *obj, cyhal_gpio_t dp,
const cyhal_resource_pin_mapping_t *dp_map = CY_UTILS_GET_RESOURCE(dp, cyhal_pin_map_usb_usb_dp_pad);
const cyhal_resource_pin_mapping_t *dm_map = CY_UTILS_GET_RESOURCE(dm, cyhal_pin_map_usb_usb_dm_pad);
if((NULL != dp_map) && (NULL != dm_map) &&
(dp_map->inst->block_num == dm_map->inst->block_num))
if ((NULL != dp_map) && (NULL != dm_map) &&
cyhal_utils_resources_equal(dp_map->inst, dm_map->inst))
{
cyhal_resource_inst_t pin_rsc;
obj->resource = *dp_map->inst;
/* reserve DM and DP pins */
pin_rsc = cyhal_utils_get_gpio_resource(dp);
result = cyhal_hwmgr_reserve(&pin_rsc);
result = cyhal_utils_reserve_and_connect(dp, dp_map);
if (CY_RSLT_SUCCESS == result)
{
obj->pin_dp = dp;
pin_rsc = cyhal_utils_get_gpio_resource(dm);
result = cyhal_hwmgr_reserve(&pin_rsc);
}
if (CY_RSLT_SUCCESS == result)
{
obj->pin_dm = dm;
result = cyhal_connect_pin(dp_map);
}
if (CY_RSLT_SUCCESS == result)
{
result = cyhal_connect_pin(dm_map);
result = cyhal_utils_reserve_and_connect(dm, dm_map);
if (CY_RSLT_SUCCESS == result)
{
obj->pin_dm = dm;
}
}
}
@ -474,11 +464,20 @@ static void cyhal_usb_dev_free_resources(cyhal_usb_dev_t *obj)
cyhal_utils_release_if_used(&(obj->pin_dm));
}
cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t dm, const cyhal_clock_divider_t *clk)
static bool cyhal_usb_dev_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
{
cyhal_usb_dev_t *obj = (cyhal_usb_dev_t *)callback_arg;
return USBFS_DEV_LPM_POWER_CTL(obj->base) & USBFS_USBLPM_POWER_CTL_SUSPEND_Msk;
}
cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t dm, const cyhal_clock_t *clk)
{
cy_rslt_t result;
CY_ASSERT(NULL != obj);
memset(obj, 0, sizeof(cyhal_usb_dev_t));
memset(obj, 0, sizeof(cyhal_usb_dev_t));
/* Reset object into the default state to handle resource free */
obj->base = NULL;
@ -515,14 +514,7 @@ cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t
static cy_stc_usbfs_dev_drv_config_t default_cfg =
{
.mode = CY_USBFS_DEV_DRV_EP_MANAGEMENT_CPU,
.dmaConfig[0] = NULL,
.dmaConfig[1] = NULL,
.dmaConfig[2] = NULL,
.dmaConfig[3] = NULL,
.dmaConfig[4] = NULL,
.dmaConfig[5] = NULL,
.dmaConfig[6] = NULL,
.dmaConfig[7] = NULL,
.dmaConfig = { 0 },
.epBuffer = NULL,
.epBufferSize = 0U,
.intrLevelSel = CYHAL_USB_DEV_IRQ_LVL_DEFAULT,
@ -562,6 +554,13 @@ cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t
&(obj->context));
cyhal_usb_dev_sof_enable(obj, false);
obj->pm_callback.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
obj->pm_callback.callback = &cyhal_usb_dev_pm_callback;
obj->pm_callback.args = (void *)obj;
obj->pm_callback.next = NULL;
obj->pm_callback.ignore_modes = (cyhal_syspm_callback_mode_t)(CYHAL_SYSPM_CHECK_FAIL | CYHAL_SYSPM_BEFORE_TRANSITION | CYHAL_SYSPM_AFTER_TRANSITION);
cyhal_syspm_register_peripheral_callback(&(obj->pm_callback));
/* Register data endpoint handlers */
for (cb_num = 0; cb_num < CYHAL_USB_DEV_EP_EVENT_NUM; cb_num++)
{
@ -583,6 +582,7 @@ cy_rslt_t cyhal_usb_dev_init(cyhal_usb_dev_t *obj, cyhal_gpio_t dp, cyhal_gpio_t
void cyhal_usb_dev_free(cyhal_usb_dev_t *obj)
{
cyhal_syspm_unregister_peripheral_callback(&(obj->pm_callback));
cyhal_usb_dev_irq_enable(obj, false);
cyhal_usb_dev_disconnect(obj);
cyhal_usb_dev_free_resources(obj);
@ -600,6 +600,15 @@ void cyhal_usb_dev_disconnect(cyhal_usb_dev_t *obj)
Cy_USBFS_Dev_Drv_Disable(obj->base, &(obj->context));
}
void cyhal_usb_dev_suspend(cyhal_usb_dev_t *obj)
{
Cy_USBFS_Dev_Drv_Suspend(obj->base, &(obj->context));
}
void cyhal_usb_dev_resume(cyhal_usb_dev_t *obj)
{
Cy_USBFS_Dev_Drv_Resume(obj->base, &(obj->context));
}
void cyhal_usb_dev_set_configured(cyhal_usb_dev_t *obj)
{
@ -780,7 +789,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_read(cyhal_usb_dev_t *obj, cyhal_usb_dev_ep_t e
}
cy_rslt_t cyhal_usb_dev_endpoint_read_result(cyhal_usb_dev_t *obj, cyhal_usb_dev_ep_t endpoint, uint32_t *actSize)
cy_rslt_t cyhal_usb_dev_endpoint_read_result(cyhal_usb_dev_t *obj, cyhal_usb_dev_ep_t endpoint, uint32_t *act_size)
{
cy_rslt_t result = CYHAL_USB_DEV_RSLT_ERR;
uint32_t ep_num = CYHAL_USB_DEV_GET_EP_NUM(endpoint);
@ -793,7 +802,7 @@ cy_rslt_t cyhal_usb_dev_endpoint_read_result(cyhal_usb_dev_t *obj, cyhal_usb_dev
ep_num,
obj->rd_data[CYHAL_USB_DEV_GET_EP_IDX(endpoint)],
obj->rd_size[CYHAL_USB_DEV_GET_EP_IDX(endpoint)],
actSize,
act_size,
&(obj->context));
if (drvStatus == CY_USBFS_DEV_DRV_SUCCESS)

View File

@ -22,10 +22,13 @@
* limitations under the License.
*******************************************************************************/
#include <stdlib.h>
#include <stdarg.h>
#include "cyhal_utils.h"
#include "cyhal_hwmgr.h"
#include "cyhal_interconnect.h"
#include "cyhal_gpio.h"
#include "cyhal_clock.h"
#if defined(__cplusplus)
extern "C"
@ -34,11 +37,14 @@ extern "C"
const cyhal_resource_pin_mapping_t *cyhal_utils_get_resource(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t* mappings, size_t count)
{
for (uint32_t i = 0; i < count; i++)
if (NC != pin)
{
if (pin == mappings[i].pin)
for (uint32_t i = 0; i < count; i++)
{
return &mappings[i];
if (pin == mappings[i].pin)
{
return &mappings[i];
}
}
}
return NULL;
@ -84,6 +90,201 @@ bool cyhal_utils_resources_equal(const cyhal_resource_inst_t *resource1, const c
(resource1->channel_num == resource2->channel_num);
}
bool cyhal_utils_resources_equal_all(uint32_t count, ...)
{
CY_ASSERT(count >= 2);
va_list args;
bool equal = true;
const cyhal_resource_inst_t *curr;
va_start(args, count);
const cyhal_resource_inst_t *first = va_arg(args, const cyhal_resource_inst_t *);
for (uint32_t i = 1; i < count; i++)
{
curr = va_arg(args, const cyhal_resource_inst_t *);
equal &= cyhal_utils_resources_equal(first, curr);
}
va_end(args);
return equal;
}
uint32_t cyhal_utils_convert_flags(
const uint32_t map[][CYHAL_MAP_COLUMNS],
uint8_t from_index,
uint8_t to_index,
uint32_t count,
uint32_t source_flags)
{
uint32_t result_flags = 0;
for (uint8_t i = 0; i < count; i++)
{
const uint32_t *map_entry = map[i];
if ((source_flags & map_entry[from_index]) == map_entry[from_index])
{
result_flags |= map_entry[to_index];
}
}
return result_flags;
}
cy_en_syspm_callback_mode_t cyhal_utils_convert_haltopdl_pm_mode(cyhal_syspm_callback_mode_t mode)
{
switch (mode)
{
case CYHAL_SYSPM_CHECK_READY:
return CY_SYSPM_CHECK_READY;
case CYHAL_SYSPM_CHECK_FAIL:
return CY_SYSPM_CHECK_FAIL;
case CYHAL_SYSPM_BEFORE_TRANSITION:
return CY_SYSPM_BEFORE_TRANSITION;
case CYHAL_SYSPM_AFTER_TRANSITION:
return CY_SYSPM_AFTER_TRANSITION;
default:
/* Should not get here */
CY_ASSERT(false);
return CY_SYSPM_CHECK_READY;
}
}
cyhal_syspm_callback_mode_t cyhal_utils_convert_pdltohal_pm_mode(cy_en_syspm_callback_mode_t mode)
{
switch (mode)
{
case CY_SYSPM_CHECK_READY:
return CYHAL_SYSPM_CHECK_READY;
case CY_SYSPM_CHECK_FAIL:
return CYHAL_SYSPM_CHECK_FAIL;
case CY_SYSPM_BEFORE_TRANSITION:
return CYHAL_SYSPM_BEFORE_TRANSITION;
case CY_SYSPM_AFTER_TRANSITION:
return CYHAL_SYSPM_AFTER_TRANSITION;
default:
/* Should not get here */
CY_ASSERT(false);
return CYHAL_SYSPM_CHECK_READY;
}
}
void cyhal_utils_get_peri_clock_details(const cyhal_clock_t *clock, cy_en_divider_types_t *div_type, uint32_t *div_num)
{
if (cyhal_utils_is_new_clock_format(clock))
{
CY_ASSERT(clock->reserved);
*div_num = clock->channel;
*div_type = (cy_en_divider_types_t)clock->block;
}
else
{
*div_num = clock->div_num;
*div_type = (cy_en_divider_types_t)clock->div_type;
}
}
cy_rslt_t cyhal_utils_allocate_clock(cyhal_clock_t *clock, const cyhal_resource_inst_t *clocked_item, cyhal_clock_divider_types_t div, bool accept_larger)
{
CY_ASSERT(NULL != clocked_item);
cyhal_resource_inst_t clock_rsc;
switch (clocked_item->type)
{
/* High frequency clock assignments are device specific. */
#if defined(CY_DEVICE_PSOC6ABLE2)
case CYHAL_RSC_I2S:
case CYHAL_RSC_PDM:
clock_rsc = CYHAL_CLOCK_HF[1];
break;
case CYHAL_RSC_SMIF:
clock_rsc = CYHAL_CLOCK_HF[2];
break;
case CYHAL_RSC_USB:
clock_rsc = CYHAL_CLOCK_HF[3];
break;
#elif defined(CY_DEVICE_PSOC6A2M)
case CYHAL_RSC_I2S:
case CYHAL_RSC_PDM:
clock_rsc = CYHAL_CLOCK_HF[1];
break;
case CYHAL_RSC_SMIF:
clock_rsc = CYHAL_CLOCK_HF[2];
break;
case CYHAL_RSC_USB:
clock_rsc = CYHAL_CLOCK_HF[3];
break;
case CYHAL_RSC_SDHC:
clock_rsc = (clocked_item->block_num == 0)
? CYHAL_CLOCK_HF[4]
: CYHAL_CLOCK_HF[2];
break;
#elif defined(CY_DEVICE_PSOC6A512K)
case CYHAL_RSC_SMIF:
clock_rsc = CYHAL_CLOCK_HF[2];
break;
case CYHAL_RSC_USB:
clock_rsc = CYHAL_CLOCK_HF[3];
break;
case CYHAL_RSC_SDHC:
clock_rsc = CYHAL_CLOCK_HF[4];
break;
#endif
case CYHAL_RSC_CLOCK:
CY_ASSERT(false); /* Use APIs provided by the clock driver */
return CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED;
default:
return cyhal_hwmgr_allocate_clock(clock, div, accept_larger);
}
cy_rslt_t result = cyhal_clock_get(clock, &clock_rsc);
if(CY_RSLT_SUCCESS == result)
{
result = cyhal_clock_init(clock);
}
return result;
}
int32_t cyhal_utils_calculate_tolerance(cyhal_clock_tolerance_unit_t type, uint32_t desired_hz, uint32_t actual_hz)
{
switch (type)
{
case CYHAL_TOLERANCE_HZ:
return desired_hz - actual_hz;
case CYHAL_TOLERANCE_PPM:
return (int32_t)(((int64_t)(desired_hz - actual_hz)) * 1000000) / ((int32_t)desired_hz);
case CYHAL_TOLERANCE_PERCENT:
return (((int32_t)(desired_hz - actual_hz)) * 100) / ((int32_t)desired_hz);
default:
CY_ASSERT(false);
return 0;
}
}
cy_rslt_t cyhal_utils_set_clock_frequency(cyhal_clock_t* clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance)
{
const uint8_t HFCLK_DIVIDERS[] = { 1, 2, 4, 8};
uint32_t source_hz = Cy_SysClk_ClkPathGetFrequency(clock->channel);
if(clock->block == CYHAL_CLOCK_BLOCK_HF)
{
// Try each of the dividers to see if it gets us within the tolerance
for(uint8_t i = 0; i < sizeof(HFCLK_DIVIDERS)/sizeof(HFCLK_DIVIDERS[0]); ++i)
{
const uint8_t divider = HFCLK_DIVIDERS[i];
uint32_t actual_freq = source_hz / divider;
uint32_t achieved_tolerance = abs(cyhal_utils_calculate_tolerance(tolerance->type, hz, actual_freq));
if(achieved_tolerance < tolerance->value)
{
return cyhal_clock_set_divider(clock, divider);
}
}
return CYHAL_CLOCK_RSLT_ERR_FREQ;
}
else
{
// Defer to the clock driver
return cyhal_clock_set_frequency(clock, hz, tolerance);
}
}
#if defined(__cplusplus)
}
#endif

View File

@ -101,8 +101,8 @@ extern "C" {
#define CYHAL_WDT_MAX_IGNORE_BITS 12
typedef struct {
uint32_t min_period_ms; // Minimum period in milliseconds that can be represented with this many ignored bits
uint32_t round_threshold_ms; // Timeout threshold in milliseconds from which to round up to the minimum period
uint16_t min_period_ms; // Minimum period in milliseconds that can be represented with this many ignored bits
uint16_t round_threshold_ms; // Timeout threshold in milliseconds from which to round up to the minimum period
// uint32_t pre_match_cycles; // The number of clock cycles in the first two full counter cycles (before the match value matters)
} cyhal_wdt_internal_ignore_bits_data_t;

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