From 2ee400f6d1198862f460a57e15e76b59b91290b9 Mon Sep 17 00:00:00 2001 From: Rbb666 Date: Tue, 26 Jul 2022 12:52:25 +0800 Subject: [PATCH] Add RTC device --- bsp/cypress/libraries/HAL_Drivers/SConscript | 3 + bsp/cypress/libraries/HAL_Drivers/drv_rtc.c | 164 ++++++++ bsp/cypress/libraries/HAL_Drivers/drv_rtc.h | 0 bsp/cypress/libraries/HAL_Drivers/drv_uart.c | 33 +- bsp/cypress/libraries/HAL_Drivers/drv_uart.h | 2 + .../libraries/IFX_PSOC6_HAL/SConscript | 4 + .../mtb-hal-cat1/include/cyhal_rtc.h | 52 +-- .../mtb-hal-cat1/source/cyhal_rtc.c | 354 ++++-------------- bsp/cypress/psoc6-cy8cproto-4343w/README.md | 88 ++--- .../psoc6-cy8cproto-4343w/board/Kconfig | 17 + .../figures/mdk_package.png | Bin 0 -> 52129 bytes 11 files changed, 349 insertions(+), 368 deletions(-) create mode 100644 bsp/cypress/libraries/HAL_Drivers/drv_rtc.c create mode 100644 bsp/cypress/libraries/HAL_Drivers/drv_rtc.h create mode 100644 bsp/cypress/psoc6-cy8cproto-4343w/figures/mdk_package.png diff --git a/bsp/cypress/libraries/HAL_Drivers/SConscript b/bsp/cypress/libraries/HAL_Drivers/SConscript index 80ddab8b2c..33cd4e13c9 100644 --- a/bsp/cypress/libraries/HAL_Drivers/SConscript +++ b/bsp/cypress/libraries/HAL_Drivers/SConscript @@ -38,6 +38,9 @@ if GetDepend(['BSP_USING_SPI']): if GetDepend(['BSP_USING_ADC']): src += ['drv_adc.c'] +if GetDepend('BSP_USING_RTC'): + src += ['drv_rtc.c'] + if GetDepend(['RT_USING_WDT']): src += ['drv_wdt.c'] diff --git a/bsp/cypress/libraries/HAL_Drivers/drv_rtc.c b/bsp/cypress/libraries/HAL_Drivers/drv_rtc.c new file mode 100644 index 0000000000..6352d9d064 --- /dev/null +++ b/bsp/cypress/libraries/HAL_Drivers/drv_rtc.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-07-25 Rbb666 first version + */ + +#include +#include +#include +#include "drv_common.h" + +#ifdef BSP_USING_RTC + +//#define DRV_DEBUG +#define LOG_TAG "drv.rtc" +#include + +cyhal_rtc_t rtc_obj; + +static rt_rtc_dev_t ifx32_rtc_dev; + +static int get_day_of_week(int day, int month, int year) +{ + int ret; + int k = 0; + int j = 0; + if (month < CY_RTC_MARCH) + { + month += CY_RTC_MONTHS_PER_YEAR; + year--; + } + + k = (year % 100); + j = (year / 100); + ret = (day + (13 * (month + 1) / 5) + k + (k / 4) + (j / 4) + (5 * j)) % 7; + ret = ((ret + 6) % 7); + + return ret; +} + +static rt_err_t set_rtc_time_stamp(time_t time_stamp) +{ + struct tm tm = {0}; + struct tm new_time = {0}; + + gmtime_r(&time_stamp, &tm); + if (tm.tm_year < 100) + { + return -RT_ERROR; + } + + new_time.tm_sec = tm.tm_sec ; + new_time.tm_min = tm.tm_min ; + new_time.tm_hour = tm.tm_hour; + new_time.tm_mday = tm.tm_mday; + new_time.tm_mon = tm.tm_mon; + new_time.tm_year = tm.tm_year; + new_time.tm_wday = get_day_of_week(tm.tm_mday, tm.tm_mon, tm.tm_year); + + if (cyhal_rtc_write(&rtc_obj, &new_time) != RT_EOK) + { + return -RT_ERROR; + } + + LOG_D("set rtc time."); + + return RT_EOK; +} + +static rt_err_t ifx_rtc_get_timeval(struct timeval *tv) +{ + struct tm tm_new = {0}; + struct tm date_time = {0}; + + cyhal_rtc_read(&rtc_obj, &date_time); + + tm_new.tm_sec = date_time.tm_sec; + tm_new.tm_min = date_time.tm_min; + tm_new.tm_hour = date_time.tm_hour; + tm_new.tm_mday = date_time.tm_mday; + tm_new.tm_mon = date_time.tm_mon; + tm_new.tm_year = date_time.tm_year; + + tv->tv_sec = timegm(&tm_new); + + return RT_EOK; +} + +static rt_err_t _rtc_init(void) +{ + if (cyhal_rtc_init(&rtc_obj) != RT_EOK) + { + LOG_E("rtc init failed."); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t _rtc_get_secs(time_t *sec) +{ + struct timeval tv; + + ifx_rtc_get_timeval(&tv); + *(time_t *) sec = tv.tv_sec; + LOG_D("RTC: get rtc_time %d", *sec); + + return RT_EOK; +} + +static rt_err_t _rtc_set_secs(time_t *sec) +{ + rt_err_t result = RT_EOK; + + if (set_rtc_time_stamp(*sec)) + { + result = -RT_ERROR; + } + LOG_D("RTC: set rtc_time %d", *sec); + + return result; +} + +static const struct rt_rtc_ops _rtc_ops = +{ + _rtc_init, + _rtc_get_secs, + _rtc_set_secs, + RT_NULL, + RT_NULL, + ifx_rtc_get_timeval, + RT_NULL, +}; + +/** + * @brief RTC initialization function. + * + * @return RT_EOK indicates successful initialization, other value indicates failed; + */ +static int rt_hw_rtc_init(void) +{ + rt_err_t result = RT_EOK; + + ifx32_rtc_dev.ops = &_rtc_ops; + + if (rt_hw_rtc_register(&ifx32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL) != RT_EOK) + { + LOG_E("rtc init failed"); + result = RT_ERROR; + } + else + { + LOG_D("rtc init success"); + } + + return result; +} + +INIT_DEVICE_EXPORT(rt_hw_rtc_init); +#endif diff --git a/bsp/cypress/libraries/HAL_Drivers/drv_rtc.h b/bsp/cypress/libraries/HAL_Drivers/drv_rtc.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bsp/cypress/libraries/HAL_Drivers/drv_uart.c b/bsp/cypress/libraries/HAL_Drivers/drv_uart.c index 7273986864..04983ef570 100644 --- a/bsp/cypress/libraries/HAL_Drivers/drv_uart.c +++ b/bsp/cypress/libraries/HAL_Drivers/drv_uart.c @@ -67,7 +67,6 @@ static void uart_isr(struct rt_serial_device *serial) struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data; RT_ASSERT(uart != RT_NULL); -#ifdef BSP_USING_UART5 if ((uart->config->usart_x->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk) != 0) { /* Clear UART "RX fifo not empty interrupt" */ @@ -75,7 +74,6 @@ static void uart_isr(struct rt_serial_device *serial) rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); } -#endif } #ifdef BSP_USING_UART0 @@ -162,16 +160,28 @@ void uart5_isr_callback(void) */ static rt_err_t ifx_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { - struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data; - RT_ASSERT(serial != RT_NULL); + struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data; RT_ASSERT(uart != RT_NULL); cy_en_scb_uart_status_t result; + const cyhal_uart_cfg_t uart_config = + { + .data_bits = 8, + .stop_bits = 1, + .parity = CYHAL_UART_PARITY_NONE, + .rx_buffer = NULL, + .rx_buffer_size = 0 + }; + /* Initialize retarget-io to use the debug UART port */ - result = cy_retarget_io_init(uart->config->tx_pin, uart->config->rx_pin, - CY_RETARGET_IO_BAUDRATE); + result = cyhal_uart_init(uart->config->uart_obj, uart->config->tx_pin, uart->config->rx_pin, NC, NC, NULL, &uart_config); + + if (result == CY_RSLT_SUCCESS) + { + result = cyhal_uart_set_baud(uart->config->uart_obj, cfg->baud_rate, NULL); + } RT_ASSERT(result != RT_ERROR); @@ -229,10 +239,13 @@ static int ifx_uarths_getc(struct rt_serial_device *serial) { int ch; rt_uint8_t read_data; + RT_ASSERT(serial != RT_NULL); + struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data; + RT_ASSERT(uart != RT_NULL); ch = -1; - if (RT_EOK == cyhal_uart_getc(&cy_retarget_io_uart_obj, (uint8_t *)&read_data, 1)) + if (RT_EOK == cyhal_uart_getc(uart->config->uart_obj, (uint8_t *)&read_data, 1)) { ch = read_data & 0xff; } @@ -258,15 +271,17 @@ void rt_hw_uart_init(void) int index; rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct ifx_uart); - struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + struct serial_configure serial_config = RT_SERIAL_CONFIG_DEFAULT; rt_err_t result = 0; for (index = 0; index < obj_num; index++) { uart_obj[index].config = &uart_config[index]; uart_obj[index].serial.ops = &_uart_ops; - uart_obj[index].serial.config = config; + uart_obj[index].serial.config = serial_config; + uart_obj[index].config->uart_obj = rt_malloc(sizeof(cyhal_uart_t)); + RT_ASSERT(uart_obj[index].config->uart_obj != RT_NULL); /* register uart device */ result = rt_hw_serial_register(&uart_obj[index].serial, uart_obj[index].config->name, diff --git a/bsp/cypress/libraries/HAL_Drivers/drv_uart.h b/bsp/cypress/libraries/HAL_Drivers/drv_uart.h index 5a0f615e96..b7c2c15157 100644 --- a/bsp/cypress/libraries/HAL_Drivers/drv_uart.h +++ b/bsp/cypress/libraries/HAL_Drivers/drv_uart.h @@ -21,6 +21,8 @@ struct ifx_uart_config { + cyhal_uart_t *uart_obj; + const char *name; rt_uint32_t tx_pin; rt_uint32_t rx_pin; diff --git a/bsp/cypress/libraries/IFX_PSOC6_HAL/SConscript b/bsp/cypress/libraries/IFX_PSOC6_HAL/SConscript index d442f7a804..887f85b073 100644 --- a/bsp/cypress/libraries/IFX_PSOC6_HAL/SConscript +++ b/bsp/cypress/libraries/IFX_PSOC6_HAL/SConscript @@ -95,6 +95,10 @@ if GetDepend(['RT_USING_SPI']): if GetDepend(['RT_USING_I2C']): src += ['mtb-hal-cat1/source/cyhal_i2c.c'] +if GetDepend('BSP_USING_RTC'): + src += ['mtb-pdl-cat1/drivers/source/cy_rtc.c'] + src += ['mtb-hal-cat1/source/cyhal_rtc.c'] + if GetDepend(['RT_USING_WDT']): src += ['mtb-pdl-cat1/drivers/source/cy_wdt.c'] src += ['mtb-hal-cat1/source/cyhal_wdt.c'] diff --git a/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/include/cyhal_rtc.h b/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/include/cyhal_rtc.h index e778aae5dd..ae84799634 100644 --- a/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/include/cyhal_rtc.h +++ b/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/include/cyhal_rtc.h @@ -9,9 +9,7 @@ * ******************************************************************************** * \copyright -* Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or -* an affiliate of Cypress Semiconductor Corporation -* +* Copyright 2018-2021 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -72,6 +70,12 @@ extern "C" { #endif +/** \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, ((uint16_t)driver | (uint16_t)code))) +/** \endcond */ + /** \addtogroup group_hal_results_rtc RTC HAL Results * RTC specific return codes * \ingroup group_hal_results @@ -80,10 +84,10 @@ extern "C" { /** RTC not initialized */ #define CY_RSLT_RTC_NOT_INITIALIZED \ - (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_RTC, 0)) + (CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_RTC, 0)) /** Bad argument */ #define CY_RSLT_RTC_BAD_ARGUMENT \ - (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_RTC, 1)) + (CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_RTC, 1)) /** * \} @@ -145,23 +149,6 @@ typedef struct typedef void (*cyhal_rtc_event_callback_t)(void *callback_arg, cyhal_rtc_event_t event); /** Initialize the RTC peripheral - * - * Power up the RTC in preparation for access. This function must be called - * 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 - * oscillator for optimal accuracy and operation in low power. - * @note Previously set time configurations are retained. This will only reset - * the time if no prior configuration can be determined. - * - * @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); - -/** Initialize the RTC peripheral using a configurator generated configuration struct * * Power up the RTC in preparation for access. This function must be called * before any other RTC functions are called. This does not change the state @@ -174,10 +161,9 @@ cy_rslt_t cyhal_rtc_init(cyhal_rtc_t *obj); * * @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. - * @param[in] cfg Configuration structure generated by a configurator. * @return The status of the init request */ -cy_rslt_t cyhal_rtc_init_cfg(cyhal_rtc_t *obj, const cyhal_rtc_configurator_t *cfg); +cy_rslt_t cyhal_rtc_init(cyhal_rtc_t *obj); /** Deinitialize RTC * @@ -213,25 +199,7 @@ cy_rslt_t cyhal_rtc_read(cyhal_rtc_t *obj, struct tm *time); */ cy_rslt_t cyhal_rtc_write(cyhal_rtc_t *obj, const struct tm *time); -/** Write the specified time and date values to the RTC peripheral - * @param[in] obj RTC object - * @param[in] sec Second to set (0-59) - * @param[in] min Minute to set (0-59) - * @param[in] hour Hour to set (0-23) - * @param[in] day Day of month to set (1-31) - * @param[in] month Month to set (1-12) - * @param[in] year 4-digit year to set - * @return The status of the write request - */ -cy_rslt_t cyhal_rtc_write_direct(cyhal_rtc_t *obj, uint32_t sec, uint32_t min, uint32_t hour, - uint32_t day, uint32_t month, uint32_t year); - /** Set the start and end time for Day Light Savings - * - * Calling this function will allow alarms to account for daylight saving time. - * This means that the RTC will be adjusted when a daylight saving time - * transition occurs, meaning times passed to \ref cyhal_rtc_set_alarm() - * will be interpreted as being in DST/not in DST as appropriate. * * @param[in] obj RTC object * @param[in] start When Day Light Savings time should start diff --git a/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/source/cyhal_rtc.c b/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/source/cyhal_rtc.c index 5da1671ef2..d84bf19cf0 100644 --- a/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/source/cyhal_rtc.c +++ b/bsp/cypress/libraries/IFX_PSOC6_HAL/mtb-hal-cat1/source/cyhal_rtc.c @@ -2,16 +2,14 @@ * \file cyhal_rtc.c * * \brief -* Provides a high level interface for interacting with the Infineon Real-Time Clock. +* Provides a high level interface for interacting with the Cypress Real-Time Clock. * 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-2021 Cypress Semiconductor Corporation (an Infineon company) or -* an affiliate of Cypress Semiconductor Corporation -* +* Copyright 2018-2021 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,15 +29,13 @@ #include "cy_utils.h" #include "cyhal_rtc.h" #include "cyhal_system.h" -#include "cyhal_utils_psoc.h" -#include "cyhal_irq_psoc.h" /** * \addtogroup group_hal_impl_rtc RTC (Real Time Clock) * \ingroup group_hal_impl * \{ * -* Internally the CAT1 (PSoCâ„¢ 6) RTC only stores the year as a two digit BCD value +* Internally the CAT1 (PSoC 6) RTC only stores the year as a two digit BCD value * (0-99); no century information is stored. On RTC initialization the HAL must, * as a result, assume a default century. If cyhal_rtc_write has been called * with a different century than the default, its value must be stored and that @@ -60,7 +56,7 @@ * \} group_hal_impl_wdt */ -#if (CYHAL_DRIVER_AVAILABLE_RTC) +#if (defined(CY_IP_MXS40SSRSS) || defined(CY_IP_MXS40SRSS)) && SRSS_BACKUP_PRESENT #if defined(__cplusplus) extern "C" { @@ -69,66 +65,22 @@ extern "C" { #define _CYHAL_RTC_STATE_UNINITIALIZED 0 #define _CYHAL_RTC_STATE_ENABLED 1 #define _CYHAL_RTC_STATE_TIME_SET 2 -#if (defined(COMPONENT_CAT1C) && (CORE == CM0P)) -// To account for the lower __NVIC_PRIO_BITS value -#define _CYHAL_RTC_DEFAULT_PRIORITY 3 -#else #define _CYHAL_RTC_DEFAULT_PRIORITY 5 -#endif // (defined(COMPONENT_CAT1C) && (CORE == CM0P)) #define _CYHAL_RTC_INIT_CENTURY 2000 #define _CYHAL_RTC_TM_YEAR_BASE 1900 -#if defined(COMPONENT_CAT1A) || defined (COMPONENT_CAT1C) #define _CYHAL_RTC_BREG (BACKUP->BREG[SRSS_BACKUP_NUM_BREG-1]) -#elif defined(COMPONENT_CAT1B) -#if defined(SRSS_BACKUP_NUM_BREG3) && (SRSS_BACKUP_NUM_BREG3 > 0) -#define _CYHAL_RTC_BREG (BACKUP->BREG_SET3[SRSS_BACKUP_NUM_BREG3-1]) -#elif defined(SRSS_BACKUP_NUM_BREG2) && (SRSS_BACKUP_NUM_BREG2 > 0) -#define _CYHAL_RTC_BREG (BACKUP->BREG_SET2[SRSS_BACKUP_NUM_BREG2-1]) -#elif defined(SRSS_BACKUP_NUM_BREG1) && (SRSS_BACKUP_NUM_BREG1 > 0) -#define _CYHAL_RTC_BREG (BACKUP->BREG_SET1[SRSS_BACKUP_NUM_BREG1-1]) -#elif defined(SRSS_BACKUP_NUM_BREG0) && (SRSS_BACKUP_NUM_BREG0 > 0) -#define _CYHAL_RTC_BREG (BACKUP->BREG_SET0[SRSS_BACKUP_NUM_BREG0-1]) -#endif -#endif /* defined(COMPONENT_CAT1B) */ - #define _CYHAL_RTC_BREG_CENTURY_Pos 0UL #define _CYHAL_RTC_BREG_CENTURY_Msk 0x0000FFFFUL #define _CYHAL_RTC_BREG_STATE_Pos 16UL #define _CYHAL_RTC_BREG_STATE_Msk 0xFFFF0000UL -static const uint32_t _CYHAL_RTC_MAX_RETRY = 10; -static const uint32_t _CYHAL_RTC_RETRY_DELAY_MS = 1; - -// Note: Use PDL directly rather than HAL. RTOS-aware delay is not needed and actually breaks functionality. -#define _CYHAL_RTC_WAIT_ONE_MS() Cy_SysLib_Delay(_CYHAL_RTC_RETRY_DELAY_MS); - -static void _cyhal_rtc_from_pdl_time(cy_stc_rtc_config_t *pdlTime, const int year, struct tm *time) { - CY_ASSERT(NULL != pdlTime); - CY_ASSERT(NULL != time); - - // The number of days that precede each month of the year, not including Feb 29 - static const uint16_t CUMULATIVE_DAYS[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - - time->tm_sec = (int)pdlTime->sec; - time->tm_min = (int)pdlTime->min; - time->tm_hour = (int)pdlTime->hour; - time->tm_mday = (int)pdlTime->date; - time->tm_mon = (int)(pdlTime->month - 1u); - time->tm_year = (int)(year - _CYHAL_RTC_TM_YEAR_BASE); - time->tm_wday = (int)(pdlTime->dayOfWeek - 1u); - time->tm_yday = (int)CUMULATIVE_DAYS[time->tm_mon] + (int)pdlTime->date - 1 + - (((int)(pdlTime->month) >= 3 && (int)(Cy_RTC_IsLeapYear((uint32_t)year) ? 1u : 0u))); - time->tm_isdst = -1; -} - /** Wrapper around the PDL Cy_RTC_DeepSleepCallback to adapt the function signature */ static cy_en_syspm_status_t _cyhal_rtc_syspm_callback(cy_stc_syspm_callback_params_t *params, cy_en_syspm_callback_mode_t mode) { return Cy_RTC_DeepSleepCallback(params, mode); } -static bool _cyhal_rtc_dst_skip_next_alarm = false; static cy_stc_rtc_dst_t *_cyhal_rtc_dst; static cy_stc_syspm_callback_params_t _cyhal_rtc_pm_cb_params = {NULL, NULL}; static cy_stc_syspm_callback_t _cyhal_rtc_pm_cb = { @@ -185,11 +137,7 @@ static void _cyhal_rtc_isr_handler(void) /* Override weak function from PDL */ void Cy_RTC_Alarm1Interrupt(void) { - if (_cyhal_rtc_dst_skip_next_alarm) - { - _cyhal_rtc_dst_skip_next_alarm = false; - } - else if (NULL != _cyhal_rtc_user_handler) + if (NULL != _cyhal_rtc_user_handler) { (*_cyhal_rtc_user_handler)(_cyhal_rtc_handler_arg, CYHAL_RTC_ALARM); } @@ -200,15 +148,23 @@ void Cy_RTC_CenturyInterrupt(void) _cyhal_rtc_set_century(_cyhal_rtc_get_century() + 100); } -static cy_rslt_t _cyhal_rtc_init_common(const cy_stc_rtc_config_t* default_time) +cy_rslt_t cyhal_rtc_init(cyhal_rtc_t *obj) { + CY_UNUSED_PARAMETER(obj); + CY_ASSERT(NULL != obj); cy_rslt_t rslt = CY_RSLT_SUCCESS; if (_cyhal_rtc_get_state() == _CYHAL_RTC_STATE_UNINITIALIZED) { if (Cy_RTC_IsExternalResetOccurred()) { // Reset to default time - Cy_RTC_SetDateAndTime(default_time); + static const cy_stc_rtc_config_t defaultTime = { + .dayOfWeek = CY_RTC_SATURDAY, + .date = 1, + .month = 1, + .year = 0, + }; + Cy_RTC_SetDateAndTime(&defaultTime); _cyhal_rtc_set_century(_CYHAL_RTC_INIT_CENTURY); } @@ -223,65 +179,29 @@ static cy_rslt_t _cyhal_rtc_init_common(const cy_stc_rtc_config_t* default_time) } else if(_cyhal_rtc_get_state() == _CYHAL_RTC_STATE_ENABLED || _cyhal_rtc_get_state() == _CYHAL_RTC_STATE_TIME_SET) { - if (Cy_RTC_GetInterruptStatus() & CY_RTC_INTR_CENTURY) + if(Cy_RTC_GetInterruptStatus() & CY_RTC_INTR_CENTURY) Cy_RTC_CenturyInterrupt(); } Cy_RTC_ClearInterrupt(CY_RTC_INTR_CENTURY); Cy_RTC_SetInterruptMask(CY_RTC_INTR_CENTURY); - _cyhal_irq_register(srss_interrupt_backup_IRQn, _CYHAL_RTC_DEFAULT_PRIORITY, _cyhal_rtc_isr_handler); + static const cy_stc_sysint_t irqCfg = {.intrSrc = srss_interrupt_backup_IRQn, .intrPriority = _CYHAL_RTC_DEFAULT_PRIORITY}; + Cy_SysInt_Init(&irqCfg, &_cyhal_rtc_isr_handler); if (rslt == CY_RSLT_SUCCESS) { _cyhal_rtc_dst = NULL; - _cyhal_irq_enable(srss_interrupt_backup_IRQn); + NVIC_EnableIRQ(srss_interrupt_backup_IRQn); } return rslt; } -cy_rslt_t cyhal_rtc_init(cyhal_rtc_t *obj) -{ - CY_UNUSED_PARAMETER(obj); - CY_ASSERT(NULL != obj); - - static const cy_stc_rtc_config_t default_time = - { - .dayOfWeek = CY_RTC_SATURDAY, - .date = 1, - .month = 1, - .year = 0, - }; - return _cyhal_rtc_init_common(&default_time); -} - -cy_rslt_t cyhal_rtc_init_cfg(cyhal_rtc_t *obj, const cyhal_rtc_configurator_t *cfg) -{ - CY_UNUSED_PARAMETER(obj); - CY_ASSERT(NULL != obj); - - cy_rslt_t rslt = _cyhal_rtc_init_common(cfg->config); - if (NULL != cfg->dst_config) - { - _cyhal_rtc_set_state(_CYHAL_RTC_STATE_TIME_SET); - - cy_stc_rtc_config_t dateTime; - Cy_RTC_GetDateAndTime(&dateTime); - rslt = Cy_RTC_EnableDstTime(cfg->dst_config, &dateTime); - if (rslt == CY_RSLT_SUCCESS) - { - obj->dst = *(cfg->dst_config); - _cyhal_rtc_dst = &(obj->dst); - } - } - return rslt; -} - void cyhal_rtc_free(cyhal_rtc_t *obj) { CY_UNUSED_PARAMETER(obj); CY_ASSERT(NULL != obj); - _cyhal_irq_free(srss_interrupt_backup_IRQn); + NVIC_DisableIRQ(srss_interrupt_backup_IRQn); Cy_RTC_SetInterruptMask(CY_RTC_INTR_CENTURY); _cyhal_rtc_dst = NULL; @@ -298,66 +218,68 @@ cy_rslt_t cyhal_rtc_read(cyhal_rtc_t *obj, struct tm *time) { CY_UNUSED_PARAMETER(obj); CY_ASSERT(NULL != obj); + // The number of days that precede each month of the year, not including Feb 29 + static const uint16_t CUMULATIVE_DAYS[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - cy_stc_rtc_config_t dateTime = { .hrFormat = CY_RTC_24_HOURS }; + cy_stc_rtc_config_t dateTime; uint32_t savedIntrStatus = cyhal_system_critical_section_enter(); Cy_RTC_GetDateAndTime(&dateTime); - const int year = (int)(dateTime.year + _cyhal_rtc_get_century()); + int year = (int)(dateTime.year + _cyhal_rtc_get_century()); cyhal_system_critical_section_exit(savedIntrStatus); - _cyhal_rtc_from_pdl_time(&dateTime, year, time); + time->tm_sec = (int)dateTime.sec; + time->tm_min = (int)dateTime.min; + time->tm_hour = (int)dateTime.hour; + time->tm_mday = (int)dateTime.date; + time->tm_mon = (int)(dateTime.month - 1u); + time->tm_year = (int)(year - _CYHAL_RTC_TM_YEAR_BASE); + time->tm_wday = (int)(dateTime.dayOfWeek - 1u); + time->tm_yday = (int)CUMULATIVE_DAYS[time->tm_mon] + (int)dateTime.date - 1 + + (((int)(dateTime.month) >= 3 && (int)(Cy_RTC_IsLeapYear((uint32_t)year) ? 1u : 0u))); + time->tm_isdst = -1; return CY_RSLT_SUCCESS; } cy_rslt_t cyhal_rtc_write(cyhal_rtc_t *obj, const struct tm *time) -{ - CY_ASSERT(NULL != obj); - return cyhal_rtc_write_direct(obj, time->tm_sec, time->tm_min, time->tm_hour, time->tm_mday, - time->tm_mon + 1, _CYHAL_RTC_TM_YEAR_BASE + time->tm_year); -} - -cy_rslt_t cyhal_rtc_write_direct(cyhal_rtc_t *obj, uint32_t sec, uint32_t min, uint32_t hour, - uint32_t day, uint32_t month, uint32_t year) { CY_UNUSED_PARAMETER(obj); - uint32_t year2digit = year % 100; + CY_ASSERT(NULL != obj); + uint32_t year2digit = time->tm_year % 100; + cy_stc_rtc_config_t newtime = { + .sec = (uint32_t)time->tm_sec, + .min = (uint32_t)time->tm_min, + .hour = (uint32_t)time->tm_hour, + .hrFormat = CY_RTC_24_HOURS, + .dayOfWeek = (uint32_t)time->tm_wday + 1, + .date = (uint32_t)time->tm_mday, + .month = (uint32_t)(time->tm_mon + 1), + .year = year2digit + }; cy_rslt_t rslt; uint32_t retry = 0; - if (!CY_RTC_IS_SEC_VALID(sec) || !CY_RTC_IS_MIN_VALID(min) || !CY_RTC_IS_HOUR_VALID(hour) || !CY_RTC_IS_MONTH_VALID(month) || !CY_RTC_IS_YEAR_SHORT_VALID(year2digit)) - { - return CY_RSLT_RTC_BAD_ARGUMENT; - } - do - { + static const uint32_t MAX_RETRY = 10, RETRY_DELAY_MS = 1; + do { if (retry != 0) - _CYHAL_RTC_WAIT_ONE_MS(); + Cy_SysLib_Delay(RETRY_DELAY_MS); uint32_t savedIntrStatus = cyhal_system_critical_section_enter(); - rslt = Cy_RTC_SetDateAndTimeDirect(sec, min, hour, day, month, year2digit); + rslt = (cy_rslt_t)Cy_RTC_SetDateAndTime(&newtime); if (rslt == CY_RSLT_SUCCESS) - _cyhal_rtc_set_century((uint16_t)(year) - (uint16_t)(year2digit)); + _cyhal_rtc_set_century((uint16_t)(time->tm_year) - (uint16_t)(year2digit) + (uint16_t)(_CYHAL_RTC_TM_YEAR_BASE)); cyhal_system_critical_section_exit(savedIntrStatus); ++retry; - } while (rslt == CY_RTC_INVALID_STATE && retry < _CYHAL_RTC_MAX_RETRY); + } while (rslt == CY_RTC_INVALID_STATE && retry < MAX_RETRY); - retry = 0; - while (CY_RTC_BUSY == Cy_RTC_GetSyncStatus() && retry < _CYHAL_RTC_MAX_RETRY) - { - _CYHAL_RTC_WAIT_ONE_MS(); - ++retry; - } + while (CY_RTC_BUSY == Cy_RTC_GetSyncStatus()) { } if (rslt == CY_RSLT_SUCCESS) - { _cyhal_rtc_set_state(_CYHAL_RTC_STATE_TIME_SET); - } return rslt; } cy_rslt_t cyhal_rtc_set_dst(cyhal_rtc_t *obj, const cyhal_rtc_dst_t *start, const cyhal_rtc_dst_t *stop) { - CY_UNUSED_PARAMETER(obj); CY_ASSERT(NULL != obj); CY_ASSERT(NULL != start); CY_ASSERT(NULL != stop); @@ -370,18 +292,16 @@ cy_rslt_t cyhal_rtc_set_dst(cyhal_rtc_t *obj, const cyhal_rtc_dst_t *start, cons cy_rslt_t rslt = Cy_RTC_EnableDstTime(&(obj->dst), &dateTime); if (rslt == CY_RSLT_SUCCESS) _cyhal_rtc_dst = &(obj->dst); - return rslt; } bool cyhal_rtc_is_dst(cyhal_rtc_t *obj) { - CY_UNUSED_PARAMETER(obj); CY_ASSERT(NULL != obj); cy_stc_rtc_config_t dateTime; Cy_RTC_GetDateAndTime(&dateTime); - return Cy_RTC_GetDstStatus(_cyhal_rtc_dst, &dateTime); + return Cy_RTC_GetDstStatus(&(obj->dst), &dateTime); } cy_rslt_t cyhal_rtc_set_alarm(cyhal_rtc_t *obj, const struct tm *time, cyhal_alarm_active_t active) @@ -389,46 +309,22 @@ cy_rslt_t cyhal_rtc_set_alarm(cyhal_rtc_t *obj, const struct tm *time, cyhal_ala // Note: the hardware does not support year matching CY_UNUSED_PARAMETER(obj); CY_ASSERT(NULL != obj); - _cyhal_rtc_dst_skip_next_alarm = false; - cy_stc_rtc_alarm_t alarm = - { - .sec = (uint32_t)time->tm_sec, - .secEn = active.en_sec ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, - .min = (uint32_t)time->tm_min, - .minEn = active.en_min ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, - .hour = (uint32_t)time->tm_hour, - .hourEn = active.en_hour ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, - .dayOfWeek = (uint32_t)(time->tm_wday + 1), - .dayOfWeekEn = active.en_day ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, - .date = (uint32_t)time->tm_mday, - .dateEn = active.en_date ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, - .month = (uint32_t)(time->tm_mon + 1), - .monthEn = active.en_month ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, - .almEn = CY_RTC_ALARM_ENABLE + cy_stc_rtc_alarm_t alarm = { + .sec = (uint32_t)time->tm_sec, + .secEn = active.en_sec ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, + .min = (uint32_t)time->tm_min, + .minEn = active.en_min ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, + .hour = (uint32_t)time->tm_hour, + .hourEn = active.en_hour ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, + .dayOfWeek = (uint32_t)(time->tm_wday + 1), + .dayOfWeekEn = active.en_day ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, + .date = (uint32_t)time->tm_mday, + .dateEn = active.en_date ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, + .month = (uint32_t)(time->tm_mon + 1), + .monthEn = active.en_month ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE, + .almEn = CY_RTC_ALARM_ENABLE }; - - cy_rslt_t rslt; - uint32_t retry = 0; - do - { - if (retry != 0) - _CYHAL_RTC_WAIT_ONE_MS(); - rslt = (cy_rslt_t)Cy_RTC_SetAlarmDateAndTime(&alarm, CY_RTC_ALARM_1); - ++retry; - } while (rslt == CY_RTC_INVALID_STATE && retry < _CYHAL_RTC_MAX_RETRY); - - return rslt; -} - -static uint32_t _cyhal_rtc_update_field(uint32_t remaining, uint32_t* curr, uint32_t *next, uint32_t max) -{ - *curr += remaining % max; - if (*curr >= max) - { - *curr %= max; - (*next)++; - } - return remaining / max; + 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) @@ -441,113 +337,24 @@ cy_rslt_t cyhal_rtc_set_alarm_by_seconds(cyhal_rtc_t *obj, const uint32_t second if(seconds > SECONDS_IN_YEAR) return CY_RSLT_RTC_BAD_ARGUMENT; - cy_stc_rtc_config_t now; + struct tm now; uint32_t savedIntrStatus = cyhal_system_critical_section_enter(); - Cy_RTC_GetDateAndTime(&now); - const int year = (int)(now.year + _cyhal_rtc_get_century()); + cyhal_rtc_read(obj, &now); cyhal_system_critical_section_exit(savedIntrStatus); - bool nowDst = _cyhal_rtc_dst && Cy_RTC_GetDstStatus(_cyhal_rtc_dst, &now); + time_t future_time_t = mktime(&now) + seconds; + struct tm* future = localtime(&future_time_t); - uint32_t remaining = seconds; - remaining = _cyhal_rtc_update_field(remaining, &now.sec, &now.min, 60); - remaining = _cyhal_rtc_update_field(remaining, &now.min, &now.hour, 60); - remaining = _cyhal_rtc_update_field(remaining, &now.hour, &now.date, 24); - - uint32_t days; - now.date += remaining; - while (now.date > (days = Cy_RTC_DaysInMonth(now.month, year))) - { - now.date -= days; - now.month++; - if (now.month > 12) - { - now.year++; - now.month = 1; - } - } - - bool setSkipNextAlarm = false; - - // Handle crossing of daylight savings time boundaries - if (_cyhal_rtc_dst) - { - bool futureDst = Cy_RTC_GetDstStatus(_cyhal_rtc_dst, &now); - - if (nowDst && !futureDst) - { - // If the alarm time is within the hour following the end of DST, - // ignore the first alarm since the adjusted time will be before - // the DST boundary causing two alarms to occur: one before the - // boundary and one after the boundary. - if (now.hour == _cyhal_rtc_dst->stopDst.hour) - { - setSkipNextAlarm = true; - } - - if (now.hour == 0) - { - now.hour = 23; - now.date--; - - if (now.date < 1) - { - now.month--; - if (now.month < 1) - { - now.month = 12; - now.year--; - } - - now.date = Cy_RTC_DaysInMonth(now.month, year); - } - } - else - { - now.hour--; - } - } - else if (!nowDst && futureDst) - { - now.hour++; - if (now.hour >= 24) - { - now.hour = 0; - now.date++; - - if (now.date > days) - { - now.date = 1; - now.month++; - if (now.month > 12) - { - now.month = 1; - // Increment year, but alarm doesn't care - } - } - } - } - } - - struct tm future; - _cyhal_rtc_from_pdl_time(&now, year, &future); - - static const cyhal_alarm_active_t active = - { + 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_DISABLE, // We do not actually compute the day as we don't care. - .en_date = CY_RTC_ALARM_ENABLE, // The absolute time (eg: date) is what is important. + .en_day = CY_RTC_ALARM_ENABLE, + .en_date = CY_RTC_ALARM_ENABLE, .en_month = CY_RTC_ALARM_ENABLE }; - savedIntrStatus = cyhal_system_critical_section_enter(); - cy_rslt_t result = cyhal_rtc_set_alarm(obj, &future, active); - _cyhal_rtc_dst_skip_next_alarm = setSkipNextAlarm; - cyhal_system_critical_section_exit(savedIntrStatus); - - return result; + 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) @@ -567,13 +374,12 @@ void cyhal_rtc_enable_event(cyhal_rtc_t *obj, cyhal_rtc_event_t event, uint8_t i CY_ASSERT(NULL != obj); CY_ASSERT(CYHAL_RTC_ALARM == event); Cy_RTC_ClearInterrupt(CY_RTC_INTR_ALARM1 | CY_RTC_INTR_ALARM2); - uint32_t alarm2_status = (Cy_RTC_GetInterruptMask() & CY_RTC_INTR_ALARM2); - Cy_RTC_SetInterruptMask((enable ? CY_RTC_INTR_ALARM1 : 0) | CY_RTC_INTR_CENTURY | alarm2_status); - _cyhal_irq_set_priority(srss_interrupt_backup_IRQn, intr_priority); + Cy_RTC_SetInterruptMask((enable ? CY_RTC_INTR_ALARM1 : 0) | CY_RTC_INTR_CENTURY); + NVIC_SetPriority(srss_interrupt_backup_IRQn, intr_priority); } #if defined(__cplusplus) } #endif -#endif /* CYHAL_DRIVER_AVAILABLE_RTC */ +#endif /* (defined(CY_IP_MXS40SSRSS) || defined(CY_IP_MXS40SRSS)) && SRSS_BACKUP_PRESENT */ diff --git a/bsp/cypress/psoc6-cy8cproto-4343w/README.md b/bsp/cypress/psoc6-cy8cproto-4343w/README.md index bf886a7073..cce3675e03 100644 --- a/bsp/cypress/psoc6-cy8cproto-4343w/README.md +++ b/bsp/cypress/psoc6-cy8cproto-4343w/README.md @@ -1,8 +1,8 @@ -# Cypress CY8CKIT-062-BLE PSoC 6 BLE Pioneer Kit 说明 +# Cypress Psoc6-CY8CKIT-062S2-43012 说明 ## 简介 -本文档为Cypress为PSoC6 BLE Pioneer Kit开发板提供的 BSP (板级支持包) 说明。 +本文档为 `RT-Thread` 为 `PSoC6 CY8CKIT-062S2-43012`开发板提供的 BSP (板级支持包) 说明。 主要内容如下: @@ -10,89 +10,91 @@ - BSP 快速上手 - 进阶使用方法 -通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-Thread 驱动更多板载资源。 +通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 `RT-Thread` 驱动更多板载资源。 ## 开发板介绍 -CY8CKIT-062-BLE PSoC6 BLE Pioneer Kit 是赛普拉斯推出的一款32位双核CPU子系统( ARM Cortex-M4 和 ARM Cortex-M0)的开发板,具有单周期乘法的150-MHz Arm Cortex-M4F CPU (浮点和 -存储器保护单元),100-MHz Cortex M0+ CPU,带单周期乘法和MPU,可以充分发挥 PSoC6 双核芯片性能。 +`PSoC6 CY8CKIT-062S2-43012` 是赛普拉斯推出的一款32位双核CPU子系统( ARM Cortex-M4 和 ARM Cortex-M0)的开发板,具有单周期乘法的150-MHz Arm Cortex-M4F CPU (浮点和存储器保护单元),100-MHz Cortex M0+ CPU,带单周期乘法和MPU,可以充分发挥 PSoC6 双核芯片性能。 -开发板外观详细信息:https://www.cypress.com/file/390496/download +开发板外观详细信息:[CY8CPROTO-062-4343W - Infineon Technologies](https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/) +该开发板核心 **板载资源** 如下: -该开发板常用 **板载资源** 如下: - -- MCU:CY8C6347BZI-BLD53,Cortex-M4主频 150MHz,Cortex-M0主频 100MHz,1 MB 应用闪存,32 KB EEPROM 区域和32 KB 安全闪存 ,288 KB 集成SRAM - MCU手册更多详细信息请参考文档 https://www.cypress.com/file/457541/download - -- 开发环境:ModusToolbox 2.0 - PSoC® Creator™ 下载链接 https://www.cypress.com/products/modustoolbox-software-environment - +- MCU:CY8C624ABZI-S2D44,Cortex-M4主频 150MHz,Cortex-M0主频 100MHz,2MB Flash 和 1MB SRAM + MCU手册更多详细信息请参考文档 [PSoC 6 MCU: CY8C62x8, CY8C62xA Datasheet (infineon.com)](https://www.infineon.com/dgdl/Infineon-PSOC_6_MCU_CY8C62X8_CY8C62XA-DataSheet-v17_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee7d03a70b1) +- 板载资源:microSD card , 64-Mb Quad-SPI NOR flash, CYW43012 Wi-Fi + Bluetooth Combo Chip +- 开发环境:ModusToolbox 2.0/MDK V5 + PSoC® Creator™ 下载链接 [ModusToolbox™ Software - Infineon Technologies](https://www.infineon.com/cms/en/design-support/tools/sdk/modustoolbox-software/) - 开发板:CY8CKIT-062-BLE PSoC 6 BLE Pioneer Kit 开发板更多详细信息请参考文档 https://www.cypress.com/file/390496/download - ## 外设支持 -本 BSP 目前对外设的支持情况详细信息请参考文档 https://www.cypress.com/file/390496/download +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +| :----------: | :----------: | :-----------: | +| USB 转串口 | 支持 | — | +| GPIO | 支持 | — | +| UART | 支持 | UART0-5 | +| I2C | 支持 | 软件+硬件 I2C | +| RTC | 支持 | — | +| WDT | 支持 | — | +| PWM | 支持 | — | +| SPI | 支持 | — | +| HardTimer | 暂不支持 | — | +| DAC | 暂不支持 | — | +| Flash | 暂不支持 | — | +| SDIO | 暂不支持 | — | +| USB Device | 暂不支持 | — | +| USB Host | 暂不支持 | — | ## 使用说明 -使用说明分为如下两个章节: - - 快速上手 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 -- 进阶使用 - - 本章节是为需要在 RT-Thread 操作系统上使用赛普拉斯开发板资源的开发者准备的。 - ### 快速上手 -本 BSP 以 ModusToolbox 2.0开发环境(GCC),介绍如何将系统运行起来。 +本 BSP 是以 MDK V5 开发环境(编译器:ARMClang ),接下来介绍如何将系统运行起来。 #### 硬件连接 -使用Type-C数据线连接开发板到 PC. +使用数据线连接开发板到 PC。 #### 编译下载 -1, 安装ModusToolbox 2.0时请使用默认路径 - -2, 打开ModusToolbox 2.0时workspace选择工程所在目录下(例如workspace: C:\Git\rt-thread\bsp\cypress) +1、配置工程: -3, 在Project Explorer的空白处右键,点击import,General->Existing Projects into Workspace ->next,点击Browse选择 - 此BSP所在目录加载工程->Finish +首先打开 MDK ,若没有安装 `Cypress-PSoC6` 的芯片支持包会提示在线安装,根据提示安装即可。若受网络问题,可以进入 [keil](https://www.keil.com/dd2/pack) 官网下载安装包,离线安装。 -4, 下载lib:在左下角Quick Panel的Tools栏,点击library Manager-> BSPs下面勾选CY8CKIT-062-BLE (若已勾选可以不用再选) - -> Libraries里PSoC6 Base Libraries下面全部勾选core-lib,psoc6cm0p,psoc6hal,psoc6make,psoc6pdl -> 点击apply 进行下载 +![mdk_package](./figures/mdk_package.png) -5, 编译此工程 +2、 编译此工程:在安装好芯片支持包后,在 `MDK`工程中进行编译。 -6, 下载此工程 +3、下载此工程: -工程默认配置使用 SWD方式下载程序,Type-C数据线连接开发板,编译之后直接点击下载按钮即可。 +工程默认配置使用板载 `DAP-LINK` 使用 `SWD` 方式下载程序,使用数据线连接开发板,编译之后直接点击下载按钮即可。 #### 运行结果 -下载程序成功之后,系统会自动运行。打开终端工具串口小助手,复位设备后,可以看到 RT-Thread 的输出信息: +下载程序成功之后,系统会自动运行。打开终端工具串口助手,选择波特率为 115200。复位设备后,LED 将会以 500HZ 的频率闪烁,而且在终端上可以看到 `RT-Thread` 的输出信息: -注:推荐使用串口调试助手如:sscom +注:推荐使用串口调试助手如:`MobaXterm` ``` + \ | / - RT - Thread Operating System - / | \ 4.0.3 build Jan 6 2020 - 2006 - 2019 Copyright by rt-thread team -hello rt-thread -msh >hello rt-thread -hello rt-thread -``` + / | \ 4.1.1 build Jul 25 2022 18:03:35 + 2006 - 2022 Copyright by RT-Thread team +msh > +``` ## 联系人信息 维护人: -- [amyqian379](https://github.com/amyqian379) \ No newline at end of file +- [Rbb666](https://github.com/Rbb666) \ No newline at end of file diff --git a/bsp/cypress/psoc6-cy8cproto-4343w/board/Kconfig b/bsp/cypress/psoc6-cy8cproto-4343w/board/Kconfig index ff79de64be..0a88af9918 100644 --- a/bsp/cypress/psoc6-cy8cproto-4343w/board/Kconfig +++ b/bsp/cypress/psoc6-cy8cproto-4343w/board/Kconfig @@ -196,6 +196,23 @@ menu "On-chip Peripheral Drivers" endif endif + menuconfig BSP_USING_RTC + bool "Enable RTC" + select RT_USING_RTC + default n + if BSP_USING_RTC + choice + prompt "Select clock source" + default BSP_RTC_USING_LSE + + config BSP_RTC_USING_LSE + bool "RTC USING LSE" + + config BSP_RTC_USING_LSI + bool "RTC USING LSI" + endchoice + endif + config BSP_USING_WDT bool "Enable Watchdog Timer" select RT_USING_WDT diff --git a/bsp/cypress/psoc6-cy8cproto-4343w/figures/mdk_package.png b/bsp/cypress/psoc6-cy8cproto-4343w/figures/mdk_package.png new file mode 100644 index 0000000000000000000000000000000000000000..230574a87bd061c26b655ed8467a0c0ad243a40f GIT binary patch literal 52129 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 F{|C;>t~dYy literal 0 HcmV?d00001