1 /***************************************************************************//**
2 * \file cyhal_scb_common.h
3 *
4 * \brief
5 * Provides a struct definitions for configuration resources in the SCB (UART, I2C, SPI).
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26
27 /** \cond INTERNAL */
28 /**
29 * \addtogroup group_hal_impl_scb_common SCB Common Functionality
30 * \ingroup group_hal_impl
31 * \{
32 * Code shared between the SCB resources (UART, I2C, and SPI).
33 */
34
35 #pragma once
36
37 #include "cy_device.h"
38 #include "cy_pdl.h"
39 #include "cyhal_utils.h"
40 #include "cyhal_irq_impl.h"
41 #include "cyhal_peri_common.h"
42
43 #if defined(__cplusplus)
44 extern "C" {
45 #endif
46
47 #if defined(CY_IP_MXSCB_INSTANCES)
48 #define _SCB_ARRAY_SIZE (CY_IP_MXSCB_INSTANCES)
49 #elif defined(CY_IP_M0S8SCB_INSTANCES)
50 #define _SCB_ARRAY_SIZE (CY_IP_M0S8SCB_INSTANCES)
51 #elif defined(CY_IP_MXS22SCB_INSTANCES)
52 #define _SCB_ARRAY_SIZE (CY_IP_MXS22SCB_INSTANCES)
53 #endif /* CY_IP_MXSCB_INSTANCES */
54
55 /* Indicates the invalid SCB block selected */
56 #define _CYHAL_SCB_BLOCK_ID_INVALID (0xFF)
57
58 /* Return number of bytes to copy into the destination buffer */
59 #define _CYHAL_SCB_BYTES_TO_COPY(actBufSize, bufSize) \
60 (((uint32_t) (actBufSize) < (uint32_t) (bufSize)) ? \
61 ((uint32_t) (actBufSize)) : ((uint32_t) (bufSize)) )
62
63
64 /** \addtogroup group_hal_results_scb SCB HAL Results
65 * SCB specific return codes
66 * \ingroup group_hal_results
67 * \{ *//**
68
69 */
70 /** Bad argument */
71 #define CYHAL_SCB_RSLT_ERR_BAD_ARGUMENT \
72 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_SCB, 0))
73
74 /**
75 * \}
76 */
77
78 /** SCB FIFO type */
79 typedef enum
80 {
81 CYHAL_SCB_FIFO_RX, //!< Set RX FIFO level
82 CYHAL_SCB_FIFO_TX, //!< Set TX FIFO level
83 } cyhal_scb_fifo_type_t;
84
85 /** Enum of possible output signals from an SCB */
86 typedef enum
87 {
88 CYHAL_SCB_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED, //!< Output the RX FIFO signal which is triggered when the receive FIFO has more entries than the configured level.
89 CYHAL_SCB_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED, //!< Output the TX FIFO signal which is triggered when the transmit FIFO has less entries than the configured level.
90 } cyhal_scb_output_t;
91
92
93 /** The mask of available SCB blocks */
94 extern const uint32_t _CYHAL_SCB_AVAILABLE_BLOCKS_MASK;
95 /** The start address of the SCB blocks */
96 extern CySCB_Type* const _CYHAL_SCB_BASE_ADDRESSES[_SCB_ARRAY_SIZE];
97 /** The interrupt number of the SCB blocks. */
98 extern const _cyhal_system_irq_t _CYHAL_SCB_IRQ_N[_SCB_ARRAY_SIZE];
99
100
101 /** Get the SCB block corresponding to an IRQn.
102 *
103 * @param[in] irqn The IRQn to get the corresponding block from
104 * @return The corresponding SCB block
105 */
106 uint8_t cyhal_scb_get_block_from_irqn(_cyhal_system_irq_t irqn);
107
108 /** Get the index of SCB block in internal arrays corresponding to SCB instance.
109 *
110 * @param[in] scb_block_num The SCB instance number
111 * @return The corresponding index of SCB block in internal array
112 */
113 uint8_t _cyhal_scb_get_block_index(uint8_t scb_block_num);
114
115 #if defined (COMPONENT_CAT5)
116 /** Get the SCB object corresponding to the currently running ISR.
117 *
118 * @param[in] irqn The index of the irq object to retrieve
119 * @return A pointer to the SCB object corresponding to the currently running ISR.
120 */
121 void *_cyhal_scb_get_irq_obj(_cyhal_system_irq_t irqn);
122 #else
123 /** Get the SCB object corresponding to the currently running ISR.
124 *
125 * @return A pointer to the SCB object corresponding to the currently running ISR.
126 */
127 void *_cyhal_scb_get_irq_obj(void);
128 #endif
129
130 /** Sets the desired clocks & data rate to achieve the specified frequency. Configuration of clock is not changed if
131 * driver does not own it.
132 * @param[in] obj The I2C or EZI2C object to configure the peri divider for
133 * @param[in] is_i2c Whether driver to be configured is I2C or EZI2C (I2C is true)
134 * @praam[in] freq The desired frequency
135 * @param[in] is_slave Is this an I2C slave (true) or master (false)
136 * @return The achieved data rate in Hz, or 0 if there was an error.
137 */
138 uint32_t _cyhal_i2c_set_peri_divider(void *obj, bool is_i2c, uint32_t freq, bool is_slave);
139
140 /** Find an available SCB instance that matches 'pin'.
141 * @param pin Pin
142 * @param pin_map Pin mapping array
143 * @param count Number of entries in pin_map
144 * @return Pin map pointer or NULL if none found
145 */
146 const cyhal_resource_pin_mapping_t* _cyhal_scb_find_map(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map,
147 size_t count, const cyhal_resource_inst_t *block_res);
148
149 /** Find all available SCB instances that matches 'pin'.
150 * @param pin Pin
151 * @param pin_map Pin mapping array
152 * @param count Number of entries in pin_map
153 * @return Bit representation of SCB blocks, that can be wired with specified pin. 1 block - 1 bit, LSB corresponds to
154 * SCB0. Only free for reserve blocks are returned. Example, output value 0x00000006 means that certain pin can belong
155 * to next non-reserved blocks: SCB2 and SCB1.
156 */
157 uint32_t _cyhal_scb_check_pin_affiliation(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *pin_map, size_t count);
158
159 /** Sets a threshold level for a FIFO that will generate an interrupt and a
160 * trigger output. The RX FIFO interrupt and trigger will be activated when
161 * the receive FIFO has more entries than the threshold. The TX FIFO interrupt
162 * and trigger will be activated when the transmit FIFO has less entries than
163 * the threshold.
164 *
165 * @param[in] base SCB base
166 * @param[in] type FIFO type to set level for
167 * @param[in] level Level threshold to set
168 * @return The status of the level set
169 * */
170 cy_rslt_t _cyhal_scb_set_fifo_level(CySCB_Type *base, cyhal_scb_fifo_type_t type, uint16_t level);
171
172 /** Enables the specified output signal from an scb.
173 *
174 * @param[in] resource SCB resource
175 * @param[in] output Which output signal to enable
176 * @param[out] source Pointer to user-allocated source signal object which
177 * will be initialized by enable_output. source should be passed to
178 * (dis)connect_digital functions to (dis)connect the associated endpoints.
179 * @return The status of the output enable
180 * */
181 cy_rslt_t _cyhal_scb_enable_output(cyhal_resource_inst_t resource, cyhal_scb_output_t output, cyhal_source_t *source);
182
183 /** Disables the specified output signal from an scb
184 *
185 * @param[in] output Which output signal to disable
186 * @return The status of the output disable
187 * */
188 cy_rslt_t _cyhal_scb_disable_output(cyhal_scb_output_t output);
189
190 #define _CYHAL_SCB_FIND_MAP(pin, pin_map) \
191 _cyhal_scb_find_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t), NULL)
192 #define _CYHAL_SCB_FIND_MAP_BLOCK(pin, pin_map, block) \
193 _cyhal_scb_find_map(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t), block)
194 #define _CYHAL_SCB_CHECK_AFFILIATION(pin, pin_map) \
195 _cyhal_scb_check_pin_affiliation(pin, pin_map, sizeof(pin_map)/sizeof(cyhal_resource_pin_mapping_t))
196
197 /**
198 * Function pointer to determine a specific scb instance can is ready for low power transition.
199 */
200 typedef bool (*cyhal_scb_instance_pm_callback)(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode);
201
202 /** Updates data in cyhal_scb_config_structs and cyhal_scb_config_modes_t structs based on block_num proveded
203 * @param[in] block_num Index of SCB block which data to be updated
204 * @param[in] obj SCB-based driver object (cyhal_uart_t, cyhal_spi_t, cyhal_i2c_t or cyhal_ezi2c_t)
205 */
206 void _cyhal_scb_update_instance_data(uint8_t block_num, void *obj, cyhal_scb_instance_pm_callback pm_callback);
207
208 /** Whether power management transition is pending and communication should be suspended. */
209 bool _cyhal_scb_pm_transition_pending(void);
210
211 /** Finds the en_clk_dst_t clock connection index for provided SCB block number
212 *
213 * @param[in] block_num Index of SCB block
214 * @return en_clk_dst_t clock connection index
215 */
_cyhal_scb_get_clock_index(uint32_t block_num)216 static inline en_clk_dst_t _cyhal_scb_get_clock_index(uint32_t block_num)
217 {
218 en_clk_dst_t clk;
219 // PSOC6A256K does not have SCB 3
220 #if defined(CY_DEVICE_PSOC6A256K)
221 if (block_num < 3)
222 clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num);
223 else
224 clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num -1);
225 #elif defined (COMPONENT_CAT5)
226 clk = (en_clk_dst_t)(block_num);
227 #elif defined (COMPONENT_CAT1D)
228 if (block_num == 0)
229 clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK);
230 else if (block_num == 1)
231 clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB1_PCLK_CLOCK);
232 else
233 clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num - 1);
234 #else
235 clk = (en_clk_dst_t)((uint32_t)_CYHAL_SCB0_PCLK_CLOCK + block_num);
236 #endif
237 return clk;
238 }
239
240 #if defined(__cplusplus)
241 }
242 #endif
243
244 /** \} group_hal_impl_scb_common */
245 /** \endcond */
246