From dc6398a38553617cba516b1e12745f4696d88b2a Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Wed, 23 Aug 2017 08:31:07 -0500 Subject: [PATCH 01/29] Check for mbed 5 support on export --- tools/build_api.py | 23 ++++++++++++----------- tools/project.py | 13 ++++++++----- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/tools/build_api.py b/tools/build_api.py index aa5e1d7dd58..42fb000ca75 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -438,6 +438,18 @@ def scan_resources(src_paths, toolchain, dependencies_paths=None, # Set the toolchain's configuration data toolchain.set_config_data(toolchain.config.get_config_data()) + if (hasattr(toolchain.target, "release_versions") and + "5" not in toolchain.target.release_versions and + "rtos" in toolchain.config.lib_config_data): + if "Cortex-A" in toolchain.target.core: + raise NotSupportedException( + ("%s Will be supported in mbed OS 5.6. " + "To use the %s, please checkout the mbed OS 5.4 release branch. " + "See https://developer.mbed.org/platforms/Renesas-GR-PEACH/#important-notice " + "for more information") % (toolchain.target.name, toolchain.target.name)) + else: + raise NotSupportedException("Target does not support mbed OS 5") + return resources def build_project(src_paths, build_path, target, toolchain_name, @@ -519,17 +531,6 @@ def build_project(src_paths, build_path, target, toolchain_name, try: # Call unified scan_resources resources = scan_resources(src_paths, toolchain, inc_dirs=inc_dirs) - if (hasattr(toolchain.target, "release_versions") and - "5" not in toolchain.target.release_versions and - "rtos" in toolchain.config.lib_config_data): - if "Cortex-A" in toolchain.target.core: - raise NotSupportedException( - ("%s Will be supported in mbed OS 5.6. " - "To use the %s, please checkout the mbed OS 5.4 release branch. " - "See https://developer.mbed.org/platforms/Renesas-GR-PEACH/#important-notice " - "for more information") % (toolchain.target.name, toolchain.target.name)) - else: - raise NotSupportedException("Target does not support mbed OS 5") # Change linker script if specified if linker_script is not None: diff --git a/tools/project.py b/tools/project.py index 05f5c0a7d0f..ff59f5b9d40 100644 --- a/tools/project.py +++ b/tools/project.py @@ -20,6 +20,7 @@ from tools.utils import argparse_force_lowercase_type from tools.utils import argparse_force_uppercase_type from tools.utils import print_large_string +from tools.utils import NotSupportedException from tools.options import extract_profile, list_profiles, extract_mcus def setup_project(ide, target, program=None, source_dir=None, build=None, export_path=None): @@ -246,11 +247,13 @@ def main(): profile = extract_profile(parser, options, toolchain_name, fallback="debug") if options.clean: rmtree(BUILD_DIR) - export(mcu, options.ide, build=options.build, - src=options.source_dir, macros=options.macros, - project_id=options.program, zip_proj=zip_proj, - build_profile=profile, app_config=options.app_config) - + try: + export(mcu, options.ide, build=options.build, + src=options.source_dir, macros=options.macros, + project_id=options.program, zip_proj=zip_proj, + build_profile=profile, app_config=options.app_config) + except NotSupportedException as exc: + print "[ERROR] %s" % str(exc) if __name__ == "__main__": main() From bce900d8f7c530e52ed35259d01553194561e6c5 Mon Sep 17 00:00:00 2001 From: Rob Meades Date: Mon, 4 Sep 2017 14:46:59 +0100 Subject: [PATCH 02/29] Fix cellular APN_db.h lookup. --- .../generic_modem_driver/PPPCellularInterface.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp index c2c1dc9e7f8..a40eef6bdc3 100644 --- a/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp +++ b/features/netsocket/cellular/generic_modem_driver/PPPCellularInterface.cpp @@ -540,18 +540,12 @@ nsapi_error_t PPPCellularInterface::connect() nsapi_error_t retcode; bool success; bool did_init = false; + const char *apn_config = NULL; if (dev_info.ppp_connection_up) { return NSAPI_ERROR_IS_CONNECTED; } - const char *apn_config = NULL; -#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP - if (!set_credentials_api_used) { - apn_config = apnconfig(dev_info.imsi); - } -#endif - do { retry_init: @@ -586,6 +580,12 @@ nsapi_error_t PPPCellularInterface::connect() return NSAPI_ERROR_NO_CONNECTION; } +#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP + if (!apn_config) { + apn_config = apnconfig(dev_info.imsi); + } +#endif + /* Check if user want skip SIM pin checking on boot up */ if (set_sim_pin_check_request) { retcode = do_sim_pin_check(_at, _pin); @@ -611,6 +611,7 @@ nsapi_error_t PPPCellularInterface::connect() _apn = _APN_GET(apn_config); _uname = _APN_GET(apn_config); _pwd = _APN_GET(apn_config); + tr_info("Looked up APN %s.", _apn); } #endif From 58c9f4b9bd9b2f5fc55d7cc23a6e7bc15e5b4c59 Mon Sep 17 00:00:00 2001 From: bcostm Date: Thu, 24 Aug 2017 16:04:53 +0200 Subject: [PATCH 03/29] STM32 USBDevice: refactor files --- ...SBHAL_STM32F103RB.h => USBHAL_IP_DEVICE.h} | 152 +++++++++++------- ...BHAL_STM32F769NI.h => USBHAL_IP_OTGFSHS.h} | 144 +++++++++++------ .../targets/TARGET_STM/USBHAL_STM32.cpp | 19 ++- .../{USBHAL_STM_TARGET.h => USBHAL_STM32.h} | 48 +++--- .../targets/TARGET_STM/USBHAL_STM32F303ZE.h | 127 --------------- .../targets/TARGET_STM/USBHAL_STM32L053C8.h | 134 --------------- .../targets/TARGET_STM/USBHAL_STM32L072CZ.h | 131 --------------- .../targets/TARGET_STM/USBHAL_STM32L475VG.h | 145 ----------------- .../targets/TARGET_STM/USBHAL_STM32L476VG.h | 145 ----------------- .../TARGET_STM/USBHAL_STM_144_64pins.h | 132 --------------- 10 files changed, 229 insertions(+), 948 deletions(-) rename features/unsupported/USBDevice/targets/TARGET_STM/{USBHAL_STM32F103RB.h => USBHAL_IP_DEVICE.h} (51%) rename features/unsupported/USBDevice/targets/TARGET_STM/{USBHAL_STM32F769NI.h => USBHAL_IP_OTGFSHS.h} (60%) rename features/unsupported/USBDevice/targets/TARGET_STM/{USBHAL_STM_TARGET.h => USBHAL_STM32.h} (61%) delete mode 100644 features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h delete mode 100644 features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h delete mode 100644 features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h delete mode 100644 features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h delete mode 100644 features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h delete mode 100644 features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F103RB.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h similarity index 51% rename from features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F103RB.h rename to features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h index 271610b217b..d637cad067d 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F103RB.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 mbed.org, MIT License +/* Copyright (c) 2017 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without @@ -15,16 +15,29 @@ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef USBHAL_STM32F103RB -#define USBHAL_STM32F103RB +#ifndef USBHAL_IP_DEVICE_H +#define USBHAL_IP_DEVICE_H +#if defined(TARGET_NUCLEO_F303ZE) +#define USBHAL_IRQn USB_LP_CAN_RX0_IRQn + +#elif defined(TARGET_NUCLEO_F103RB) #define USBHAL_IRQn USB_LP_CAN1_RX0_IRQn +#elif defined(TARGET_DISCO_L072CZ_LRWAN1) || \ + defined(TARGET_DISCO_L053C8) +#define USBHAL_IRQn USB_IRQn + +#else +#error "USB IRQ is not configured !" +#endif + +#define NB_ENDPOINT 8 // Must be a multiple of 4 bytes -#define NB_ENDPOINT 8 -/* must be multiple of 4 bytes */ #define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) + +#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE + MAX_PACKET_SIZE_EP0 + MAX_PACKET_SIZE_EP1 + MAX_PACKET_SIZE_EP2 + MAX_PACKET_SIZE_EP3) + #if (FIFO_USB_RAM_SIZE > 0x500) #error "FIFO dimensioning incorrect" #endif @@ -32,34 +45,33 @@ typedef struct { USBHAL *inst; + void (USBHAL::*bus_reset)(void); void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); + void (USBHAL::*connect_change)(unsigned int connected); void (USBHAL::*suspend_change)(unsigned int suspended); void (USBHAL::*ep0_setup)(void); void (USBHAL::*ep0_in)(void); void (USBHAL::*ep0_out)(void); void (USBHAL::*ep0_read)(void); bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - uint8_t epComplete[8]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; + bool (USBHAL::*epCallback[(2 * NB_ENDPOINT) - 2])(void); -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),!state); -} + uint8_t epComplete[2 * NB_ENDPOINT]; + + /* Memorize dummy buffer used for reception */ + uint32_t pBufRx[MAXTRANSFER_SIZE >> 2]; + uint32_t pBufRx0[MAX_PACKET_SIZE_EP0 >> 2]; + + gpio_t usb_switch; +} USBHAL_Private_t; uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) { return 1024; } -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) + +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; @@ -68,24 +80,31 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) (obj->*func)(sofnum); } -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) { - /* init parameter */ + USBHAL_Private_t *priv = ((USBHAL_Private_t *)(hpcd->pData)); +#if defined(TARGET_NUCLEO_F103RB) + gpio_write(&(priv->usb_switch), !state); +#else + gpio_write(&(priv->usb_switch), state); +#endif +} + +USBHAL *USBHAL::instance; + +USBHAL::USBHAL(void) { USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ + hpcd.Instance = USB; - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ + memset(&hpcd.Init, 0, sizeof(hpcd.Init)); hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; + hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; hpcd.Init.Sof_enable = 1; hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ + + // Pass instance for usage inside call back HALPriv->inst = this; HALPriv->bus_reset = &USBHAL::busReset; HALPriv->suspend_change = &USBHAL::suspendStateChanged; @@ -96,7 +115,6 @@ USBHAL::USBHAL(void) HALPriv->ep0_in = &USBHAL::EP0in; HALPriv->ep0_out = &USBHAL::EP0out; HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; @@ -105,43 +123,63 @@ USBHAL::USBHAL(void) HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; instance = this; + // Configure USB pins and other clocks +#if defined(TARGET_NUCLEO_F303ZE) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); // DP + __HAL_RCC_GPIOG_CLK_ENABLE(); + gpio_init_out(&HALPriv->usb_switch, PG_6); - /* Configure USB VBUS GPIO */ - gpio_init_out(&HALPriv->usb_switch,PB_14); - gpio_mode(&HALPriv->usb_switch,OpenDrain); - /* Configure USB FS GPIOs */ - +#elif defined(TARGET_NUCLEO_F103RB) /* Configure DM DP Pins - * - USB-DP (D+ of the USB connector) <======> PA12 (Nucleo board) - * Make sure to connect a 1.5KOhm pull up to USB-DP PA12 pin - * (permanent pull-up) - - USB-DM (D- of the USB connector) <======> PA11 (Nucleo board) + - USB-DP (D+ of the USB connector) <======> PA12 (Nucleo board) + Make sure to connect a 1.5KOhm pull up to USB-DP PA12 pin (permanent pull-up) + - USB-DM (D- of the USB connector) <======> PA11 (Nucleo board) */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DP + __HAL_RCC_GPIOB_CLK_ENABLE(); + gpio_init_out(&HALPriv->usb_switch, PB_14); + gpio_mode(&HALPriv->usb_switch, OpenDrain); + +#elif defined(TARGET_DISCO_L072CZ_LRWAN1) || \ + defined(TARGET_DISCO_L053C8) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); // DP - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); +#else +#error "USB pins are not configured !" +#endif __HAL_RCC_USB_CLK_ENABLE(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + // Configure PCD and FIFOs + hpcd.pData = (void*)HALPriv; hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); - HAL_PCDEx_PMAConfig(&hpcd , 0x01 , PCD_SNG_BUF, 0x90); - HAL_PCDEx_PMAConfig(&hpcd , 0x81 , PCD_SNG_BUF, 0xb0); -#if 0 - HAL_PCDEx_PMAConfig(&hpcd , 0x2, PCD_DBL_BUF, 0x018000b0); -#else - HAL_PCDEx_PMAConfig(&hpcd , 0x2, PCD_SNG_BUF, 0x100); -#endif - HAL_PCDEx_PMAConfig(&hpcd , 0x82, PCD_SNG_BUF, 0x120); - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority( USBHAL_IRQn, 1); + // EP0 + HAL_PCDEx_PMAConfig(&hpcd, 0x00, PCD_SNG_BUF, 0x30); + HAL_PCDEx_PMAConfig(&hpcd, 0x80, PCD_SNG_BUF, 0x70); + // EP1 + HAL_PCDEx_PMAConfig(&hpcd, 0x01, PCD_SNG_BUF, 0x90); + HAL_PCDEx_PMAConfig(&hpcd, 0x81, PCD_SNG_BUF, 0xb0); + // EP2 + HAL_PCDEx_PMAConfig(&hpcd, 0x02, PCD_SNG_BUF, 0x100); + HAL_PCDEx_PMAConfig(&hpcd, 0x82, PCD_SNG_BUF, 0x120); + // EP3 + HAL_PCDEx_PMAConfig(&hpcd, 0x03, PCD_DBL_BUF, 0x018000b0); + HAL_PCDEx_PMAConfig(&hpcd, 0x83, PCD_SNG_BUF, 0xb0); + + // Configure interrupt vector + NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); + NVIC_SetPriority(USBHAL_IRQn, 1); HAL_PCD_Start(&hpcd); } -#endif +#endif // USBHAL_IP_DEVICE_H diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F769NI.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h similarity index 60% rename from features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F769NI.h rename to features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h index f2bfa7a1025..6ad7eddca2c 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F769NI.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 mbed.org, MIT License +/* Copyright (c) 2017 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without @@ -15,13 +15,21 @@ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef USBHAL_STM32F769NI_H -#define USBHAL_STM32F769NI_H +#ifndef USBHAL_IP_OTGFSHS_H +#define USBHAL_IP_OTGFSHS_H + +#if defined(TARGET_DISCO_F769NI) #define USBHAL_IRQn OTG_HS_IRQn -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 4 +#else +#define USBHAL_IRQn OTG_FS_IRQn +#endif + +#define NB_ENDPOINT 4 // Must be a multiple of 4 bytes + #define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) + +#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE + MAX_PACKET_SIZE_EP0 + MAX_PACKET_SIZE_EP1 + MAX_PACKET_SIZE_EP2 + MAX_PACKET_SIZE_EP3) + #if (FIFO_USB_RAM_SIZE > 0x500) #error "FIFO dimensioning incorrect" #endif @@ -29,30 +37,37 @@ typedef struct { USBHAL *inst; + void (USBHAL::*bus_reset)(void); void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); + void (USBHAL::*connect_change)(unsigned int connected); void (USBHAL::*suspend_change)(unsigned int suspended); void (USBHAL::*ep0_setup)(void); void (USBHAL::*ep0_in)(void); void (USBHAL::*ep0_out)(void); void (USBHAL::*ep0_read)(void); bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - uint8_t epComplete[2*NB_ENDPOINT]; -}USBHAL_Private_t; + bool (USBHAL::*epCallback[(2 * NB_ENDPOINT) - 2])(void); + + uint8_t epComplete[2 * NB_ENDPOINT]; + + /* Memorize dummy buffer used for reception */ + uint32_t pBufRx[MAXTRANSFER_SIZE >> 2]; + uint32_t pBufRx0[MAX_PACKET_SIZE_EP0 >> 2]; +} USBHAL_Private_t; uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) { uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else + if (fifo == 0) { + len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ >> 16; + } + else { len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; + } + return len * 4; } + void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); @@ -60,27 +75,31 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; void (USBHAL::*func)(int frame) = priv->sof; - /* fix me call with same frame number */ (obj->*func)(sofnum); } - -USBHAL * USBHAL::instance; +USBHAL *USBHAL::instance; USBHAL::USBHAL(void) { - /* init parameter */ USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB_OTG_HS; + memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; + +#if defined(TARGET_DISCO_F769NI) + hpcd.Instance = USB_OTG_HS; hpcd.Init.phy_itface = PCD_PHY_ULPI; hpcd.Init.Sof_enable = 0; - hpcd.Init.speed = PCD_SPEED_HIGH; - //hpcd.Init.vbus_sensing_enable = 0; - //hpcd.Init.lpm_enable = 0; - /* pass instance for usage inside call back */ +#else + hpcd.Instance = USB_OTG_FS; + hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd.Init.Sof_enable = 1; + hpcd.Init.speed = PCD_SPEED_FULL; +#endif + hpcd.Init.dev_endpoints = NB_ENDPOINT; + hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; + + // Pass instance for usage inside call back HALPriv->inst = this; HALPriv->bus_reset = &USBHAL::busReset; HALPriv->suspend_change = &USBHAL::suspendStateChanged; @@ -91,7 +110,6 @@ USBHAL::USBHAL(void) { HALPriv->ep0_in = &USBHAL::EP0in; HALPriv->ep0_out = &USBHAL::EP0out; HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; @@ -99,16 +117,43 @@ USBHAL::USBHAL(void) { HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; instance = this; - /* Enable power and clocking */ + + // Configure USB pins and other clocks + + // NUCLEO_144 boards +#if defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F412ZG) || \ + defined(TARGET_NUCLEO_F429ZI) || \ + defined(TARGET_NUCLEO_F446ZE) || \ + defined(TARGET_NUCLEO_F767ZI) || \ + defined(TARGET_NUCLEO_F746ZG) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_SOF */ + pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_VBUS */ + pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); /* OTG_FS_ID */ + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + +#elif defined(TARGET_DISCO_L475VG_IOT01A) || \ + defined(TARGET_DISCO_L476VG) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* VBUS pin */ + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddUSB(); + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + +#elif defined(TARGET_DISCO_F769NI) __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); - pin_function(PA_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // CLK pin_function(PA_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D0 - pin_function(PB_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D1 pin_function(PB_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D2 pin_function(PB_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D3 @@ -116,32 +161,41 @@ USBHAL::USBHAL(void) { pin_function(PB_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D5 pin_function(PB_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D6 pin_function(PB_13, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D7 - pin_function(PC_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // STP pin_function(PH_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // NXT pin_function(PI_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR - __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); +#else +#error "USB pins are not configured !" +#endif __HAL_RCC_SYSCFG_CLK_ENABLE(); + + // Configure PCD and FIFOs + hpcd.pData = (void*)HALPriv; hpcd.State = HAL_PCD_STATE_RESET; HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ + + /* 1.25 kbytes */ /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); + /* max value 256 (= 1K bytes ) */ + /* maximum sum is 0x140 */ + HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE / 4)); + // EP0 = Bulk/Int 64 bytes in FS + HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0 / 4) + 1); + // EP1 = Bulk/Int bytes in FS + HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1 / 4) + 1); + // EP2 + HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2 / 4)); + // EP3 = ISOchronous + HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3 / 4)); + + // Configure interrupt vector NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); NVIC_SetPriority(USBHAL_IRQn, 1); + HAL_PCD_Start(&hpcd); } -#endif +#endif // USBHAL_IP_OTGFSHS_H diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp index 36c0caf3590..a52bed139c3 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011 mbed.org, MIT License +/* Copyright (c) 2017 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without @@ -15,27 +15,30 @@ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* TARGET NOT STM does not support this HAL */ + +// This file is for STM targets only #ifndef TARGET_STM #define USBSTM_HAL_UNSUPPORTED #endif -/* F4 famlily wihtout USB_STM_HAL use another HAL*/ -#if defined(TARGET_STM) && defined(TARGET_STM32F4) && !defined(USB_STM_HAL) + +// For STM32F4 devices, this file is used only if USB_STM_HAL is defined (in targets.json) +#if defined(TARGET_STM32F4) && !defined(USB_STM_HAL) #define USBSTM_HAL_UNSUPPORTED #endif #ifndef USBSTM_HAL_UNSUPPORTED + #include "USBHAL.h" #include "pinmap.h" -/* mbed endpoint definition to hal definition */ + +/* mbed endpoint definition to hal definition */ #define EP_ADDR(ep) (((ep) >> 1)|((ep) & 1) << 7) + /* from hal definition to mbed definition */ #define ADDR_EPIN(ep) (((ep) << 1) | 1) #define ADDR_EPOUT(ep) (((ep) << 1)) -/* id to detect if rx buffer is used or not */ - -#include "USBHAL_STM_TARGET.h" +#include "USBHAL_STM32.h" /* this call at device reception completion on a Out Enpoint */ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_TARGET.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h similarity index 61% rename from features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_TARGET.h rename to features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h index b380ba85945..fb323b4934c 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_TARGET.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h @@ -15,29 +15,29 @@ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifndef USBHAL_STM32_H +#define USBHAL_STM32_H + +#if defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F412ZG) || \ + defined(TARGET_NUCLEO_F429ZI) || \ + defined(TARGET_NUCLEO_F446ZE) || \ + defined(TARGET_NUCLEO_F767ZI) || \ + defined(TARGET_NUCLEO_F746ZG) || \ + defined(TARGET_DISCO_L476VG) || \ + defined(TARGET_DISCO_L475VG_IOT01A) || \ + defined(TARGET_DISCO_F769NI) +#include "USBHAL_IP_OTGFSHS.h" + +#elif defined(TARGET_NUCLEO_F303ZE) || \ + defined(TARGET_NUCLEO_F103RB) || \ + defined(TARGET_DISCO_L072CZ_LRWAN1) || \ + defined(TARGET_DISCO_L053C8) +#include "USBHAL_IP_DEVICE.h" + +#else +#error "Target not supported !" -#if defined(TARGET_DISCO_L476VG) -#include "USBHAL_STM32L476VG.h" - -#elif defined(TARGET_DISCO_L475VG_IOT01A) -#include "USBHAL_STM32L475VG.h" - -#elif defined(TARGET_DISCO_L072CZ_LRWAN1) -#include "USBHAL_STM32L072CZ.h" - -#elif defined(TARGET_NUCLEO_F303ZE) -#include "USBHAL_STM32F303ZE.h" - -#elif defined(TARGET_NUCLEO_F103RB) -#include "USBHAL_STM32F103RB.h" - -#elif defined(TARGET_DISCO_F769NI) -#include "USBHAL_STM32F769NI.h" - -#elif defined(TARGET_DISCO_L053C8) -#include "USBHAL_STM32L053C8.h" - -#else /* default configuration */ -#include "USBHAL_STM_144_64pins.h" - #endif + +#endif // USBHAL_STM32_H diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h deleted file mode 100644 index fa49ba280a7..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32F303ZE.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef USBHAL_STM32F303ZE_H -#define USBHAL_STM32F303ZE_H -#define USBHAL_IRQn USB_LP_CAN_RX0_IRQn -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 8 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[6])(void); - uint8_t epComplete[2*NB_ENDPOINT]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - return 1024; -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state){ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),state); -} - -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - uint32_t sofnum = (hpcd->Instance->FNR) & USB_FNR_FN; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB; - /* initialized Init to zero (constructor does not zero initialized the - * area */ - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - __HAL_RCC_GPIOA_CLK_ENABLE(); - /* Configure USB DM pin. This is optional, and maintained only for user guidance. */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB)); - __HAL_RCC_GPIOG_CLK_ENABLE(); - gpio_init_out(&HALPriv->usb_switch,PG_6); - /* Enable USB Clock */ - __HAL_RCC_USB_CLK_ENABLE(); - /* Enable SYSCFG Clock */ - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); -#if 1 - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_DBL_BUF, 0x018000b0); -#else - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_SNG_BUF, 0x180); -#endif - HAL_PCDEx_PMAConfig(&hpcd , 0x83, PCD_SNG_BUF, 0xb0); - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h deleted file mode 100644 index 69b6b8196cb..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L053C8.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef USBHAL_STM32L053C8_H -#define USBHAL_STM32L053C8_H - -#define USBHAL_IRQn USB_IRQn - -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 8 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[6])(void); - uint8_t epComplete[2*NB_ENDPOINT]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - return 1024; -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),state); -} - -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - uint32_t sofnum = (hpcd->Instance->FNR) & USB_FNR_FN; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) -{ - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB; - /* initialized Init to zero (constructor does not zero initialized the - * area */ - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - /* Configure USB DM pin. This is optional, and maintained only for user guidance. */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - - /* Enable USB Clock */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Enable SYSCFG Clock */ - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); -#if 1 - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_DBL_BUF, 0x018000b0); -#else - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_SNG_BUF, 0x180); -#endif - HAL_PCDEx_PMAConfig(&hpcd , 0x83, PCD_SNG_BUF, 0xb0); - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h deleted file mode 100644 index 628701af4bb..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L072CZ.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef USBHAL_STM32L072CZ_H -#define USBHAL_STM32L072CZ_H - -#define USBHAL_IRQn USB_IRQn - -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 8 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[6])(void); - uint8_t epComplete[2*NB_ENDPOINT]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - gpio_t usb_switch; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - return 1024; -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - gpio_write(&(priv->usb_switch),state); -} - -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - uint32_t sofnum = (hpcd->Instance->FNR) & USB_FNR_FN; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) -{ - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB; - /* initialized Init to zero (constructor does not zero initialized the - * area */ - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - /* Configure USB DM pin. This is optional, and maintained only for user guidance. */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF2_USB)); - - /* Enable USB Clock */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Enable SYSCFG Clock */ - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - - /* hardcoded size of FIFO according definition*/ - HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x30); - HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x70); - HAL_PCDEx_PMAConfig(&hpcd , 0x3, PCD_DBL_BUF, 0x018000b0); - HAL_PCDEx_PMAConfig(&hpcd , 0x83, PCD_SNG_BUF, 0xb0); - - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h deleted file mode 100644 index 39a9df449c1..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L475VG.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef USBHAL_STM32L475VG -#define USBHAL_STM32L475VG - -#define USBHAL_IRQn OTG_FS_IRQn - - -#define NB_ENDPOINT 4 -/* must be multiple of 4 bytes */ -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - uint8_t epComplete[8]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else - len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; -} -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; - void (USBHAL::*func)(int frame) = priv->sof; - /* fix me call with same frame number */ - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - hpcd.Instance = USB_OTG_FS; - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - __HAL_RCC_PWR_CLK_ENABLE(); - - HAL_PWREx_EnableVddUSB(); - /* Configure USB VBUS GPIO */ - __HAL_RCC_GPIOC_CLK_ENABLE(); - - /* Configure USB FS GPIOs */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - - /* Configure DM DP Pins */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - /* Configure VBUS Pin */ - pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - - hpcd.State = HAL_PCD_STATE_RESET; - - HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ - /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); - - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority( USBHAL_IRQn, 1); - - HAL_PCD_Start(&hpcd); -} - -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h deleted file mode 100644 index b08bce8b40a..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32L476VG.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef USBHAL_STM32L476VG -#define USBHAL_STM32L476VG - -#define USBHAL_IRQn OTG_FS_IRQn - - -#define NB_ENDPOINT 4 -/* must be multiple of 4 bytes */ -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - uint8_t epComplete[8]; - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else - len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; -} -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; - void (USBHAL::*func)(int frame) = priv->sof; - /* fix me call with same frame number */ - (obj->*func)(sofnum); -} - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - hpcd.Instance = USB_OTG_FS; - /* initialized all field of init including 0 field */ - /* constructor does not fill with zero */ - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - hpcd.Init.speed = PCD_SPEED_FULL; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - - __HAL_RCC_PWR_CLK_ENABLE(); - - HAL_PWREx_EnableVddUSB(); - /* Configure USB VBUS GPIO */ - __HAL_RCC_GPIOC_CLK_ENABLE(); - - /* Configure USB FS GPIOs */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - - /* Configure DM DP Pins */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - /* Configure VBUS Pin */ - pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); - - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - - hpcd.State = HAL_PCD_STATE_RESET; - - HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ - /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); - - NVIC_SetVector(USBHAL_IRQn,(uint32_t)&_usbisr); - NVIC_SetPriority( USBHAL_IRQn, 1); - - HAL_PCD_Start(&hpcd); -} - -#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h deleted file mode 100644 index 200369d8dc2..00000000000 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (c) 2016 mbed.org, MIT License -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software -* and associated documentation files (the "Software"), to deal in the Software without -* restriction, including without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or -* substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef USBHAL_STM32_144_64 -#define USBHAL_STM32_144_64 - -#define USBHAL_IRQn OTG_FS_IRQn -/* must be multiple of 4 bytes */ -#define NB_ENDPOINT 4 -#define MAXTRANSFER_SIZE 0x200 -#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) -#if (FIFO_USB_RAM_SIZE > 0x500) -#error "FIFO dimensioning incorrect" -#endif - -typedef struct -{ - USBHAL *inst; - void (USBHAL::*bus_reset)(void); - void (USBHAL::*sof)(int frame); - void (USBHAL::*connect_change)(unsigned int connected); - void (USBHAL::*suspend_change)(unsigned int suspended); - void (USBHAL::*ep0_setup)(void); - void (USBHAL::*ep0_in)(void); - void (USBHAL::*ep0_out)(void); - void (USBHAL::*ep0_read)(void); - bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); - bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); - /* memorize dummy buffer used for reception */ - uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; - uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; - uint8_t epComplete[2*NB_ENDPOINT]; -}USBHAL_Private_t; - -uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) -{ - uint32_t len; - if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; - else - len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; - return len*4; -} -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -{ - USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); - USBHAL *obj= priv->inst; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; - void (USBHAL::*func)(int frame) = priv->sof; - (obj->*func)(sofnum); -} - - -USBHAL * USBHAL::instance; - -USBHAL::USBHAL(void) { - /* init parameter */ - USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); - hpcd.Instance = USB_OTG_FS; - memset(&hpcd.Init, 0, sizeof(hpcd.Init)); - hpcd.Init.dev_endpoints = NB_ENDPOINT; - hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; - hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd.Init.Sof_enable = 1; - - hpcd.Init.speed = PCD_SPEED_FULL; - //hpcd.Init.vbus_sensing_enable = 0; - //hpcd.Init.lpm_enable = 0; - /* pass instance for usage inside call back */ - HALPriv->inst = this; - HALPriv->bus_reset = &USBHAL::busReset; - HALPriv->suspend_change = &USBHAL::suspendStateChanged; - HALPriv->connect_change = &USBHAL::connectStateChanged; - HALPriv->sof = &USBHAL::SOF; - HALPriv->ep0_setup = &USBHAL::EP0setupCallback; - HALPriv->ep_realise = &USBHAL::realiseEndpoint; - HALPriv->ep0_in = &USBHAL::EP0in; - HALPriv->ep0_out = &USBHAL::EP0out; - HALPriv->ep0_read = &USBHAL::EP0read; - hpcd.pData = (void*)HALPriv; - HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; - HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; - HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; - HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; - HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; - HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; - instance = this; - // Enable power and clocking - /* board 144 pin all similar */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_SOF */ - pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_VBUS */ - pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); /* OTG_FS_ID */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ - - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - __HAL_RCC_SYSCFG_CLK_ENABLE(); - hpcd.State = HAL_PCD_STATE_RESET; - HAL_PCD_Init(&hpcd); - /* 1.25kbytes */ - /* min value 16 (= 16 x 4 bytes) */ - /* max value 256 (= 1K bytes ) */ - /* maximum sum is 0x140 */ - HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); - /* bulk/int 64 bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); - /* bulk/int bytes in FS */ - HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); - HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); - /* ISOchronous */ - HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); - NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); - NVIC_SetPriority(USBHAL_IRQn, 1); - HAL_PCD_Start(&hpcd); -} -#endif - From 211d2011eb94bf754e00dbb6905a48907735d837 Mon Sep 17 00:00:00 2001 From: bcostm Date: Fri, 25 Aug 2017 15:37:47 +0200 Subject: [PATCH 04/29] STM32 USBDevice: add more supported targets --- .../targets/TARGET_STM/USBHAL_IP_DEVICE.h | 12 ++--- .../targets/TARGET_STM/USBHAL_IP_OTGFSHS.h | 54 ++++++++++++++----- .../targets/TARGET_STM/USBHAL_STM32.cpp | 16 +++--- .../targets/TARGET_STM/USBHAL_STM32.h | 17 +++--- 4 files changed, 62 insertions(+), 37 deletions(-) diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h index d637cad067d..89f4dfecd04 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h @@ -132,17 +132,13 @@ USBHAL::USBHAL(void) { gpio_init_out(&HALPriv->usb_switch, PG_6); #elif defined(TARGET_NUCLEO_F103RB) - /* Configure DM DP Pins - - USB-DP (D+ of the USB connector) <======> PA12 (Nucleo board) - Make sure to connect a 1.5KOhm pull up to USB-DP PA12 pin (permanent pull-up) - - USB-DM (D- of the USB connector) <======> PA11 (Nucleo board) - */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DM - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DP __HAL_RCC_GPIOB_CLK_ENABLE(); gpio_init_out(&HALPriv->usb_switch, PB_14); gpio_mode(&HALPriv->usb_switch, OpenDrain); + // Make sure to connect a 1.5K pull-up to USB-DP PA12 pin (permanent pull-up) + __HAL_RCC_GPIOA_CLK_ENABLE(); + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DP #elif defined(TARGET_DISCO_L072CZ_LRWAN1) || \ defined(TARGET_DISCO_L053C8) diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h index 6ad7eddca2c..27e2f8acbd3 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h @@ -18,7 +18,17 @@ #ifndef USBHAL_IP_OTGFSHS_H #define USBHAL_IP_OTGFSHS_H -#if defined(TARGET_DISCO_F769NI) +//================================================================== +// This board has both USB OTG FS and HS connectors. +// Select one line only. +//================================================================== +#if defined(TARGET_DISCO_F746NG) +//#define TARGET_DISCO_F746NG_OTG_FS +#define TARGET_DISCO_F746NG_OTG_HS +#endif + +#if defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_F746NG_OTG_HS) #define USBHAL_IRQn OTG_HS_IRQn #else #define USBHAL_IRQn OTG_FS_IRQn @@ -85,7 +95,8 @@ USBHAL::USBHAL(void) { memset(&hpcd.Init, 0, sizeof(hpcd.Init)); -#if defined(TARGET_DISCO_F769NI) +#if defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_F746NG_OTG_HS) hpcd.Instance = USB_OTG_HS; hpcd.Init.phy_itface = PCD_PHY_ULPI; hpcd.Init.Sof_enable = 0; @@ -120,33 +131,45 @@ USBHAL::USBHAL(void) { // Configure USB pins and other clocks - // NUCLEO_144 boards #if defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F401RE) || \ + defined(TARGET_NUCLEO_F411RE) || \ defined(TARGET_NUCLEO_F412ZG) || \ defined(TARGET_NUCLEO_F429ZI) || \ defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ - defined(TARGET_NUCLEO_F746ZG) + defined(TARGET_NUCLEO_F746ZG) || \ + defined(TARGET_DISCO_F469NI) || \ + defined(TARGET_DISCO_F746NG_OTG_FS) __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_SOF */ - pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_VBUS */ - pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); /* OTG_FS_ID */ - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP + pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // VBUS + pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); // ID + pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // SOF + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + +#elif defined(TARGET_DISCO_F429ZI) + __HAL_RCC_GPIOB_CLK_ENABLE(); + pin_function(PB_14, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // DM + pin_function(PB_15, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // DP + pin_function(PB_13, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // VBUS + pin_function(PB_12, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF12_OTG_HS_FS)); // ID __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); #elif defined(TARGET_DISCO_L475VG_IOT01A) || \ defined(TARGET_DISCO_L476VG) __HAL_RCC_GPIOA_CLK_ENABLE(); - pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ - pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ + pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM + pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP __HAL_RCC_GPIOC_CLK_ENABLE(); - pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* VBUS pin */ + pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // VBUS __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWREx_EnableVddUSB(); __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); -#elif defined(TARGET_DISCO_F769NI) +#elif defined(TARGET_DISCO_F769NI) || \ + defined(TARGET_DISCO_F746NG_OTG_HS) __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); @@ -163,9 +186,14 @@ USBHAL::USBHAL(void) { pin_function(PB_13, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D7 pin_function(PC_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // STP pin_function(PH_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // NXT +#if defined(TARGET_DISCO_F769NI) pin_function(PI_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR +#else // TARGET_DISCO_F746NG + pin_function(PC_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR +#endif __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + #else #error "USB pins are not configured !" #endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp index a52bed139c3..6953f4a0783 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.cpp @@ -16,21 +16,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// This file is for STM targets only +/* TARGET NOT STM does not support this HAL */ #ifndef TARGET_STM #define USBSTM_HAL_UNSUPPORTED #endif -// For STM32F4 devices, this file is used only if USB_STM_HAL is defined (in targets.json) -#if defined(TARGET_STM32F4) && !defined(USB_STM_HAL) +/* STM32F4 family without USB_STM_HAL use another HAL */ +#if defined(TARGET_STM) && defined(TARGET_STM32F4) && !defined(USB_STM_HAL) #define USBSTM_HAL_UNSUPPORTED #endif #ifndef USBSTM_HAL_UNSUPPORTED - #include "USBHAL.h" #include "pinmap.h" +#include "USBHAL_STM32.h" + /* mbed endpoint definition to hal definition */ #define EP_ADDR(ep) (((ep) >> 1)|((ep) & 1) << 7) @@ -38,8 +39,6 @@ #define ADDR_EPIN(ep) (((ep) << 1) | 1) #define ADDR_EPOUT(ep) (((ep) << 1)) -#include "USBHAL_STM32.h" - /* this call at device reception completion on a Out Enpoint */ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { @@ -321,15 +320,12 @@ bool USBHAL::getEndpointStallState(uint8_t endpoint) { void USBHAL::remoteWakeup(void) { } - void USBHAL::_usbisr(void) { instance->usbisr(); } - void USBHAL::usbisr(void) { - HAL_PCD_IRQHandler(&instance->hpcd); } -#endif +#endif diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h index fb323b4934c..fc3297f8422 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h @@ -19,20 +19,25 @@ #define USBHAL_STM32_H #if defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F401RE) || \ + defined(TARGET_NUCLEO_F411RE) || \ defined(TARGET_NUCLEO_F412ZG) || \ defined(TARGET_NUCLEO_F429ZI) || \ defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ defined(TARGET_NUCLEO_F746ZG) || \ - defined(TARGET_DISCO_L476VG) || \ + defined(TARGET_DISCO_F429ZI) || \ + defined(TARGET_DISCO_F469NI) || \ + defined(TARGET_DISCO_F746NG) || \ + defined(TARGET_DISCO_F769NI) || \ defined(TARGET_DISCO_L475VG_IOT01A) || \ - defined(TARGET_DISCO_F769NI) + defined(TARGET_DISCO_L476VG) #include "USBHAL_IP_OTGFSHS.h" -#elif defined(TARGET_NUCLEO_F303ZE) || \ - defined(TARGET_NUCLEO_F103RB) || \ - defined(TARGET_DISCO_L072CZ_LRWAN1) || \ - defined(TARGET_DISCO_L053C8) +#elif defined(TARGET_NUCLEO_F103RB) || \ + defined(TARGET_NUCLEO_F303ZE) || \ + defined(TARGET_DISCO_L053C8) || \ + defined(TARGET_DISCO_L072CZ_LRWAN1) #include "USBHAL_IP_DEVICE.h" #else From 1d72b3124d0337b24f376e419aa8c9949d9fb570 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 28 Aug 2017 13:20:12 +0200 Subject: [PATCH 05/29] STM32 USBDevice: Remove disco-f429zi, clean-up nucleo-f103rb --- .../USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h | 5 +---- .../USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h | 8 -------- .../USBDevice/targets/TARGET_STM/USBHAL_STM32.h | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h index 89f4dfecd04..d7cfc5b35c1 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_DEVICE.h @@ -132,10 +132,7 @@ USBHAL::USBHAL(void) { gpio_init_out(&HALPriv->usb_switch, PG_6); #elif defined(TARGET_NUCLEO_F103RB) - __HAL_RCC_GPIOB_CLK_ENABLE(); - gpio_init_out(&HALPriv->usb_switch, PB_14); - gpio_mode(&HALPriv->usb_switch, OpenDrain); - // Make sure to connect a 1.5K pull-up to USB-DP PA12 pin (permanent pull-up) + // Make sure to connect a 1.5K resistor between USB-DP PA12 pin and +3.3V __HAL_RCC_GPIOA_CLK_ENABLE(); pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DM pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_MODE_AF_INPUT)); // DP diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h index 27e2f8acbd3..95ca27a6e16 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h @@ -149,14 +149,6 @@ USBHAL::USBHAL(void) { pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // SOF __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); -#elif defined(TARGET_DISCO_F429ZI) - __HAL_RCC_GPIOB_CLK_ENABLE(); - pin_function(PB_14, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // DM - pin_function(PB_15, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // DP - pin_function(PB_13, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // VBUS - pin_function(PB_12, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF12_OTG_HS_FS)); // ID - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); - #elif defined(TARGET_DISCO_L475VG_IOT01A) || \ defined(TARGET_DISCO_L476VG) __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h index fc3297f8422..4a631f48445 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h @@ -26,7 +26,6 @@ defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ defined(TARGET_NUCLEO_F746ZG) || \ - defined(TARGET_DISCO_F429ZI) || \ defined(TARGET_DISCO_F469NI) || \ defined(TARGET_DISCO_F746NG) || \ defined(TARGET_DISCO_F769NI) || \ From e588011394731f417233dd7a277dc35ece3d4511 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 28 Aug 2017 13:21:08 +0200 Subject: [PATCH 06/29] STM32 USBDevice: Add USB_STM_HAL macro for disco-f469ni --- targets/targets.json | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/targets.json b/targets/targets.json index 70650962d32..72cde27e67c 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1486,6 +1486,7 @@ } }, "detect_code": ["0788"], + "macros_add": ["USB_STM_HAL"], "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F469NI" From 9e3b509a99a702177243e5c643a372e0911b0453 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 28 Aug 2017 14:25:44 +0200 Subject: [PATCH 07/29] STM32 USBDevice: Add NUCLEO_F446RE target --- .../unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h | 1 + features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h | 1 + 2 files changed, 2 insertions(+) diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h index 95ca27a6e16..dc2c6090eb9 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h @@ -136,6 +136,7 @@ USBHAL::USBHAL(void) { defined(TARGET_NUCLEO_F411RE) || \ defined(TARGET_NUCLEO_F412ZG) || \ defined(TARGET_NUCLEO_F429ZI) || \ + defined(TARGET_NUCLEO_F446RE) || \ defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ defined(TARGET_NUCLEO_F746ZG) || \ diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h index 4a631f48445..4c3a5123f50 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h @@ -23,6 +23,7 @@ defined(TARGET_NUCLEO_F411RE) || \ defined(TARGET_NUCLEO_F412ZG) || \ defined(TARGET_NUCLEO_F429ZI) || \ + defined(TARGET_NUCLEO_F446RE) || \ defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ defined(TARGET_NUCLEO_F746ZG) || \ From 8f4b6e241d017287641a369a14e30c4ddac0040f Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 28 Aug 2017 14:40:36 +0200 Subject: [PATCH 08/29] STM32 USBDevice: Add DISCO_F407VG target --- .../unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h | 1 + features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h | 1 + 2 files changed, 2 insertions(+) diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h index dc2c6090eb9..e79e01be476 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_IP_OTGFSHS.h @@ -140,6 +140,7 @@ USBHAL::USBHAL(void) { defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ defined(TARGET_NUCLEO_F746ZG) || \ + defined(TARGET_DISCO_F407VG) || \ defined(TARGET_DISCO_F469NI) || \ defined(TARGET_DISCO_F746NG_OTG_FS) __HAL_RCC_GPIOA_CLK_ENABLE(); diff --git a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h index 4c3a5123f50..1ed92bad54d 100644 --- a/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h +++ b/features/unsupported/USBDevice/targets/TARGET_STM/USBHAL_STM32.h @@ -27,6 +27,7 @@ defined(TARGET_NUCLEO_F446ZE) || \ defined(TARGET_NUCLEO_F767ZI) || \ defined(TARGET_NUCLEO_F746ZG) || \ + defined(TARGET_DISCO_F407VG) || \ defined(TARGET_DISCO_F469NI) || \ defined(TARGET_DISCO_F746NG) || \ defined(TARGET_DISCO_F769NI) || \ From 52f84810a70e1b055251048c913573908eb9c036 Mon Sep 17 00:00:00 2001 From: Martin Kojtal <0xc0170@gmail.com> Date: Wed, 6 Sep 2017 08:15:20 +0100 Subject: [PATCH 09/29] mts targets: fix debug() usage Instead of using #if NDEBUG, we can directly invoke debug() function. Fixes #5013 --- .../device/system_clock.c | 5 ++--- .../TARGET_MTS_MDOT_F411RE/device/system_clock.c | 6 ++---- .../TARGET_XDOT_L151CC/device/system_clock.c | 5 ++--- .../TARGET_XDOT_L151CC/xdot_low_power.c | 13 ++++--------- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c index e80ad41e0fb..eee454211db 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/device/system_clock.c @@ -35,6 +35,7 @@ **/ #include "stm32f4xx.h" +#include "mbed_debug.h" /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ @@ -240,8 +241,6 @@ uint8_t SetSysClock_PLL_HSI(void) /******************************************************************************/ void HardFault_Handler(void) { -#if !defined(NDEBUG) || NDEBUG == 0 - printf("Hard Fault\n"); -#endif + debug("Hard Fault\n"); NVIC_SystemReset(); } diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c index cf1e3832b3d..f24a80bfdaf 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/device/system_clock.c @@ -35,7 +35,7 @@ **/ #include "stm32f4xx.h" - +#include "mbed_debug.h" /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ @@ -243,8 +243,6 @@ uint8_t SetSysClock_PLL_HSI(void) /******************************************************************************/ void HardFault_Handler(void) { -#if !defined(NDEBUG) || NDEBUG == 0 - printf("Hard Fault\n"); -#endif + debug("Hard Fault\n"); NVIC_SystemReset(); } diff --git a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c index 19d80f38705..ff6478ff9eb 100644 --- a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/device/system_clock.c @@ -37,6 +37,7 @@ #include "stm32l1xx.h" #include "stdio.h" +#include "mbed_debug.h" /*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ @@ -253,9 +254,7 @@ uint8_t SetSysClock_PLL_HSI(void) /******************************************************************************/ void HardFault_Handler(void) { -#if !defined(NDEBUG) || NDEBUG == 0 - printf("Hard Fault\n"); -#endif + debug("Hard Fault\n"); NVIC_SystemReset(); } diff --git a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c index cec303bd953..437a576ecb1 100644 --- a/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c +++ b/targets/TARGET_STM/TARGET_STM32L1/TARGET_XDOT_L151CC/xdot_low_power.c @@ -30,12 +30,7 @@ #include "xdot_low_power.h" #include "stdio.h" - -#if defined(NDEBUG) && NDEBUG == 1 -#define xdot_lp_debug(...) do {} while(0) -#else -#define xdot_lp_debug(...) printf(__VA_ARGS__) -#endif +#include "mbed_debug.h" static uint32_t portA[6]; static uint32_t portB[6]; @@ -236,7 +231,7 @@ void xdot_enter_stop_mode() { HSERCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4; HSERCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3; if (HAL_RCC_OscConfig(&HSERCC_OscInitStruct) != HAL_OK) { - xdot_lp_debug("OSC initialization failed - initiating soft reset\r\n"); + debug("OSC initialization failed - initiating soft reset\r\n"); NVIC_SystemReset(); } @@ -247,7 +242,7 @@ void xdot_enter_stop_mode() { RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 32 MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 32 MHz if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { - xdot_lp_debug("PLL initialization failed - initiating soft reset\r\n"); + debug("PLL initialization failed - initiating soft reset\r\n"); NVIC_SystemReset(); } @@ -260,7 +255,7 @@ void xdot_enter_stop_mode() { HSIRCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; HAL_StatusTypeDef ret = HAL_RCC_OscConfig(&HSIRCC_OscInitStruct); if ( ret != HAL_OK ) { - xdot_lp_debug("HSI initialization failed - ADC will not function properly\r\n"); + debug("HSI initialization failed - ADC will not function properly\r\n"); } } From f766f7d42105e19b2a6b427cf1d6a582c41a950b Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Wed, 13 Sep 2017 20:05:40 -0500 Subject: [PATCH 10/29] Release deep sleep lock in destructor of Timer class Release the deep sleep lock when running instances of the Timer class are deleted. This ensures that deep sleep locks are properly released by the Timer class. --- drivers/Timer.cpp | 9 +++++++++ drivers/Timer.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/Timer.cpp b/drivers/Timer.cpp index 12f9737ca46..8e3c406ba99 100644 --- a/drivers/Timer.cpp +++ b/drivers/Timer.cpp @@ -28,6 +28,15 @@ Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker reset(); } +Timer::~Timer() { + core_util_critical_section_enter(); + if (_running) { + sleep_manager_unlock_deep_sleep(); + } + _running = 0; + core_util_critical_section_exit(); +} + void Timer::start() { core_util_critical_section_enter(); if (!_running) { diff --git a/drivers/Timer.h b/drivers/Timer.h index e353720b966..848f8087c39 100644 --- a/drivers/Timer.h +++ b/drivers/Timer.h @@ -53,6 +53,7 @@ class Timer : private NonCopyable { public: Timer(); Timer(const ticker_data_t *data); + ~Timer(); /** Start the timer */ From 5a6aee43eb58c9ba3b1d2de7d178a3d68867a0da Mon Sep 17 00:00:00 2001 From: Martin Kojtal <0xc0170@gmail.com> Date: Fri, 22 Sep 2017 14:59:07 +0100 Subject: [PATCH 11/29] PWMOut: lock deesleep addition As PWMOut in most cases depend on high speed freq clock, it should lock deepsleep while active. --- drivers/PwmOut.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/PwmOut.h b/drivers/PwmOut.h index 1a90c3576ac..c94b8584fdd 100644 --- a/drivers/PwmOut.h +++ b/drivers/PwmOut.h @@ -21,6 +21,7 @@ #if defined (DEVICE_PWMOUT) || defined(DOXYGEN_ONLY) #include "hal/pwmout_api.h" #include "platform/mbed_critical.h" +#include "platform/mbed_sleep.h" namespace mbed { /** \addtogroup drivers */ @@ -56,12 +57,18 @@ class PwmOut { * * @param pin PwmOut pin to connect to */ - PwmOut(PinName pin) { + PwmOut(PinName pin) : _deep_sleep_locked(false) { core_util_critical_section_enter(); pwmout_init(&_pwm, pin); core_util_critical_section_exit(); } + ~PwmOut() { + core_util_critical_section_enter(); + unlock_deep_sleep(); + core_util_critical_section_exit(); + } + /** Set the ouput duty-cycle, specified as a percentage (float) * * @param value A floating-point value representing the output duty-cycle, @@ -71,6 +78,7 @@ class PwmOut { */ void write(float value) { core_util_critical_section_enter(); + lock_deep_sleep(); pwmout_write(&_pwm, value); core_util_critical_section_exit(); } @@ -177,7 +185,24 @@ class PwmOut { } protected: + /** Lock deep sleep only if it is not yet locked */ + void lock_deep_sleep() { + if (_deep_sleep_locked == false) { + sleep_manager_lock_deep_sleep(); + _deep_sleep_locked = true; + } + } + + /** Unlock deep sleep in case it is locked */ + void unlock_deep_sleep() { + if (_deep_sleep_locked == true) { + sleep_manager_unlock_deep_sleep(); + _deep_sleep_locked = false; + } + } + pwmout_t _pwm; + bool _deep_sleep_locked; }; } // namespace mbed From 593fb3a6fb0e8fcb4ea564169e177841e7f45ab6 Mon Sep 17 00:00:00 2001 From: Mahadevan Mahesh Date: Fri, 25 Aug 2017 13:33:11 -0500 Subject: [PATCH 12/29] K66F: Update to SDK 2.2 Signed-off-by: Mahadevan Mahesh --- .../{ => TARGET_K64F}/hardware_init_MK64F12.c | 0 .../{ => TARGET_K66F}/hardware_init_MK66F18.c | 2 +- .../TARGET_FRDM/fsl_clock_config.c | 553 ++++-- .../TARGET_FRDM/fsl_clock_config.h | 107 +- .../TARGET_K66F/TARGET_FRDM/fsl_phy.c | 74 +- .../TARGET_K66F/TARGET_FRDM/fsl_phy.h | 4 +- .../TARGET_K66F/device/MK66F18.h | 614 +++--- .../TARGET_K66F/device/MK66F18_features.h | 157 +- .../TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct | 13 +- .../TOOLCHAIN_ARM_STD/startup_MK66F18.S | 11 +- .../TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld | 28 +- .../TOOLCHAIN_GCC_ARM/startup_MK66F18.S | 11 +- .../device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf | 13 +- .../device/TOOLCHAIN_IAR/startup_MK66F18.S | 11 +- .../TARGET_K66F/device/fsl_device_registers.h | 10 +- .../TARGET_K66F/device/system_MK66F18.c | 15 +- .../TARGET_K66F/device/system_MK66F18.h | 14 +- .../TARGET_K66F/drivers/fsl_adc16.c | 19 +- .../TARGET_K66F/drivers/fsl_adc16.h | 76 +- .../TARGET_K66F/drivers/fsl_clock.c | 246 ++- .../TARGET_K66F/drivers/fsl_clock.h | 658 ++++--- .../TARGET_K66F/drivers/fsl_cmp.c | 16 +- .../TARGET_K66F/drivers/fsl_cmp.h | 69 +- .../TARGET_K66F/drivers/fsl_cmt.c | 37 +- .../TARGET_K66F/drivers/fsl_cmt.h | 47 +- .../TARGET_K66F/drivers/fsl_common.h | 114 +- .../TARGET_K66F/drivers/fsl_crc.c | 42 +- .../TARGET_K66F/drivers/fsl_crc.h | 66 +- .../TARGET_K66F/drivers/fsl_dac.c | 19 +- .../TARGET_K66F/drivers/fsl_dac.h | 61 +- .../TARGET_K66F/drivers/fsl_dmamux.c | 14 +- .../TARGET_K66F/drivers/fsl_dmamux.h | 68 +- .../TARGET_K66F/drivers/fsl_dspi.c | 251 +-- .../TARGET_K66F/drivers/fsl_dspi.h | 370 ++-- .../TARGET_K66F/drivers/fsl_dspi_edma.c | 600 +++--- .../TARGET_K66F/drivers/fsl_dspi_edma.h | 112 +- .../TARGET_K66F/drivers/fsl_edma.c | 603 +++++- .../TARGET_K66F/drivers/fsl_edma.h | 349 ++-- .../TARGET_K66F/drivers/fsl_enet.c | 309 +-- .../TARGET_K66F/drivers/fsl_enet.h | 275 ++- .../TARGET_K66F/drivers/fsl_ewm.c | 14 +- .../TARGET_K66F/drivers/fsl_ewm.h | 59 +- .../TARGET_K66F/drivers/fsl_flash.c | 1710 ++++++++++++----- .../TARGET_K66F/drivers/fsl_flash.h | 1029 ++++++---- .../TARGET_K66F/drivers/fsl_flexbus.c | 16 +- .../TARGET_K66F/drivers/fsl_flexbus.h | 17 +- .../TARGET_K66F/drivers/fsl_flexcan.c | 96 +- .../TARGET_K66F/drivers/fsl_flexcan.h | 96 +- .../TARGET_K66F/drivers/fsl_ftm.c | 18 +- .../TARGET_K66F/drivers/fsl_ftm.h | 155 +- .../TARGET_K66F/drivers/fsl_gpio.c | 28 +- .../TARGET_K66F/drivers/fsl_gpio.h | 194 +- .../TARGET_K66F/drivers/fsl_i2c.c | 567 ++++-- .../TARGET_K66F/drivers/fsl_i2c.h | 185 +- .../TARGET_K66F/drivers/fsl_i2c_edma.c | 138 +- .../TARGET_K66F/drivers/fsl_i2c_edma.h | 55 +- .../TARGET_K66F/drivers/fsl_llwu.c | 4 +- .../TARGET_K66F/drivers/fsl_llwu.h | 97 +- .../TARGET_K66F/drivers/fsl_lmem_cache.c | 15 +- .../TARGET_K66F/drivers/fsl_lmem_cache.h | 87 +- .../TARGET_K66F/drivers/fsl_lptmr.c | 38 +- .../TARGET_K66F/drivers/fsl_lptmr.h | 113 +- .../TARGET_K66F/drivers/fsl_lpuart.c | 436 +++-- .../TARGET_K66F/drivers/fsl_lpuart.h | 173 +- .../TARGET_K66F/drivers/fsl_lpuart_edma.c | 69 +- .../TARGET_K66F/drivers/fsl_lpuart_edma.h | 28 +- .../TARGET_K66F/drivers/fsl_mpu.c | 232 --- .../TARGET_K66F/drivers/fsl_mpu.h | 495 ----- .../TARGET_K66F/drivers/fsl_pdb.c | 16 +- .../TARGET_K66F/drivers/fsl_pdb.h | 126 +- .../TARGET_K66F/drivers/fsl_pit.c | 14 +- .../TARGET_K66F/drivers/fsl_pit.h | 39 +- .../TARGET_K66F/drivers/fsl_pmc.c | 4 +- .../TARGET_K66F/drivers/fsl_pmc.h | 124 +- .../TARGET_K66F/drivers/fsl_port.h | 161 +- .../TARGET_K66F/drivers/fsl_rcm.c | 6 +- .../TARGET_K66F/drivers/fsl_rcm.h | 35 +- .../TARGET_K66F/drivers/fsl_rnga.c | 10 +- .../TARGET_K66F/drivers/fsl_rnga.h | 7 +- .../TARGET_K66F/drivers/fsl_rtc.c | 21 +- .../TARGET_K66F/drivers/fsl_rtc.h | 55 +- .../TARGET_K66F/drivers/fsl_sai.c | 154 +- .../TARGET_K66F/drivers/fsl_sai.h | 139 +- .../TARGET_K66F/drivers/fsl_sai_edma.c | 46 +- .../TARGET_K66F/drivers/fsl_sai_edma.h | 7 +- .../TARGET_K66F/drivers/fsl_sdhc.c | 400 ++-- .../TARGET_K66F/drivers/fsl_sdhc.h | 79 +- .../TARGET_K66F/drivers/fsl_sdramc.c | 51 +- .../TARGET_K66F/drivers/fsl_sdramc.h | 30 +- .../TARGET_K66F/drivers/fsl_sim.c | 56 +- .../TARGET_K66F/drivers/fsl_sim.h | 69 +- .../TARGET_K66F/drivers/fsl_smc.c | 56 +- .../TARGET_K66F/drivers/fsl_smc.h | 113 +- .../TARGET_K66F/drivers/fsl_sysmpu.c | 249 +++ .../TARGET_K66F/drivers/fsl_sysmpu.h | 435 +++++ .../TARGET_K66F/drivers/fsl_tpm.c | 77 +- .../TARGET_K66F/drivers/fsl_tpm.h | 47 +- .../TARGET_K66F/drivers/fsl_tsi_v4.c | 81 +- .../TARGET_K66F/drivers/fsl_tsi_v4.h | 54 +- .../TARGET_K66F/drivers/fsl_uart.c | 378 +++- .../TARGET_K66F/drivers/fsl_uart.h | 138 +- .../TARGET_K66F/drivers/fsl_uart_edma.c | 68 +- .../TARGET_K66F/drivers/fsl_uart_edma.h | 46 +- .../TARGET_K66F/drivers/fsl_vref.c | 70 +- .../TARGET_K66F/drivers/fsl_vref.h | 62 +- .../TARGET_K66F/drivers/fsl_wdog.c | 4 +- .../TARGET_K66F/drivers/fsl_wdog.h | 97 +- 107 files changed, 9995 insertions(+), 5851 deletions(-) rename features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/{ => TARGET_K64F}/hardware_init_MK64F12.c (100%) rename features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/{ => TARGET_K66F}/hardware_init_MK66F18.c (98%) mode change 100644 => 100755 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c mode change 100644 => 100755 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h delete mode 100644 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c delete mode 100644 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h create mode 100755 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c create mode 100755 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK64F12.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K64F/hardware_init_MK64F12.c similarity index 100% rename from features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK64F12.c rename to features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K64F/hardware_init_MK64F12.c diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK66F18.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K66F/hardware_init_MK66F18.c similarity index 98% rename from features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK66F18.c rename to features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K66F/hardware_init_MK66F18.c index 6ff6dc2614a..222a3173ee3 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK66F18.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/TARGET_K66F/hardware_init_MK66F18.c @@ -39,7 +39,7 @@ void k66f_init_eth_hardware(void) #ifndef FEATURE_UVISOR /* Disable MPU only when uVisor is not around. */ - MPU->CESR &= ~MPU_CESR_VLD_MASK; + SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK; #endif/*FEATURE_UVISOR*/ /* Ungate the port clock */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c old mode 100644 new mode 100755 index 93d47c7f502..d053db788a1 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -28,154 +28,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "fsl_common.h" -#include "fsl_smc.h" -#include "fsl_clock_config.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -/*! @brief Clock configuration structure. */ -typedef struct _clock_config -{ - mcg_config_t mcgConfig; /*!< MCG configuration. */ - sim_clock_config_t simConfig; /*!< SIM configuration. */ - osc_config_t oscConfig; /*!< OSC configuration. */ - uint32_t coreClock; /*!< core clock frequency. */ -} clock_config_t; - -/******************************************************************************* - * Variables - ******************************************************************************/ -/* System clock frequency. */ -extern uint32_t SystemCoreClock; - -/* Configuration for enter VLPR mode. Core clock = 4MHz. */ -const clock_config_t g_defaultClockConfigVlpr = { - .mcgConfig = - { - .mcgMode = kMCG_ModeBLPI, /* Work in BLPI mode. */ - .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enable. */ - .ircs = kMCG_IrcFast, /* Select IRC4M. */ - .fcrdiv = 0U, /* FCRDIV is 0.*/ - - .frdiv = 0U, - .drs = kMCG_DrsLow, /* Low frequency range */ - .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ - .oscsel = kMCG_OscselOsc, /* Select OSC */ - - .pll0Config = - { - .enableMode = 0U, /* Don't enable PLL. */ - .prdiv = 0U, - .vdiv = 0U, - }, - .pllcs = kMCG_PllClkSelPll0, - }, - .simConfig = - { - .pllFllSel = 3U, /* PLLFLLSEL select IRC48MCLK. */ - .pllFllDiv = 0U, - .pllFllFrac = 0U, - .er32kSrc = 2U, /* ERCLK32K selection, use RTC. */ - .clkdiv1 = 0x00040000U, /* SIM_CLKDIV1. */ - }, - .oscConfig = {.freq = BOARD_XTAL0_CLK_HZ, - .capLoad = 0U, - .workMode = kOSC_ModeOscLowPower, - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, -#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) - .erclkDiv = 0U, -#endif - }}, - .coreClock = 4000000U, /* Core clock frequency */ -}; - -/* Configuration for enter RUN mode. Core clock = 120MHz. */ -const clock_config_t g_defaultClockConfigRun = { - .mcgConfig = - { - .mcgMode = kMCG_ModePEE, /* Work in PEE mode. */ - .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enable. */ - .ircs = kMCG_IrcSlow, /* Select IRC32k. */ - .fcrdiv = 0U, /* FCRDIV is 0. */ - - .frdiv = 4U, - .drs = kMCG_DrsLow, /* Low frequency range */ - .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ - .oscsel = kMCG_OscselOsc, /* Select OSC */ - - .pll0Config = - { - .enableMode = 0U, .prdiv = 0x00U, .vdiv = 0x04U, - }, - .pllcs = kMCG_PllClkSelPll0, - }, - .simConfig = - { - .pllFllSel = 1U, /* PLLFLLSEL select PLL. */ - .pllFllDiv = 0U, - .pllFllFrac = 0U, - .er32kSrc = 2U, /* ERCLK32K selection, use RTC. */ - .clkdiv1 = 0x01140000U, /* SIM_CLKDIV1. */ - }, - .oscConfig = {.freq = BOARD_XTAL0_CLK_HZ, - .capLoad = 0, - .workMode = kOSC_ModeOscLowPower, - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, -#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) - .erclkDiv = 0U, -#endif - }}, - .coreClock = 120000000U, /* Core clock frequency */ -}; - -/* Configuration for HSRUN mode. Core clock = 180MHz. */ -const clock_config_t g_defaultClockConfigHsrun = { - .mcgConfig = - { - .mcgMode = kMCG_ModePEE, /* Work in PEE mode. */ - .irclkEnableMode = kMCG_IrclkEnableInStop, /* MCGIRCLK enable. */ - .ircs = kMCG_IrcSlow, /* Select IRC32k.*/ - .fcrdiv = 0U, /* FCRDIV is 0. */ - - .frdiv = 4U, - .drs = kMCG_DrsLow, /* Low frequency range. */ - .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25%. */ - .oscsel = kMCG_OscselOsc, /* Select OSC. */ - - .pll0Config = - { - .enableMode = 0U, .prdiv = 0x00U, .vdiv = 0x0EU, - }, - .pllcs = kMCG_PllClkSelPll0, - }, - .simConfig = - { - .pllFllSel = 1U, /* PLLFLLSEL select PLL. */ - .er32kSrc = 2U, /* ERCLK32K selection, use RTC. */ - .clkdiv1 = 0x02260000U, /* SIM_CLKDIV1. */ - }, - .oscConfig = {.freq = BOARD_XTAL0_CLK_HZ, - .capLoad = 0, - .workMode = kOSC_ModeOscLowPower, - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, -#if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) - .erclkDiv = 0U, -#endif - }}, - .coreClock = 180000000U, /* Core clock frequency */ -}; - -/******************************************************************************* - * Code - ******************************************************************************/ /* * How to setup clock using clock driver functions: * @@ -204,62 +56,389 @@ const clock_config_t g_defaultClockConfigHsrun = { * 4. Call CLOCK_SetSimConfig to set the clock configuration in SIM. */ -void BOARD_BootClockVLPR(void) -{ - CLOCK_SetSimSafeDivs(); - - CLOCK_BootToBlpiMode(g_defaultClockConfigVlpr.mcgConfig.fcrdiv, g_defaultClockConfigVlpr.mcgConfig.ircs, - g_defaultClockConfigVlpr.mcgConfig.irclkEnableMode); +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!ClocksProfile +product: Clocks v1.0 +processor: MK66FN2M0xxx18 +package_id: MK66FN2M0VMD18 +mcu_data: ksdk2_0 +processor_version: 1.0.1 +board: FRDM-K66F + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ - CLOCK_SetSimConfig(&g_defaultClockConfigVlpr.simConfig); +#include "fsl_smc.h" +#include "fsl_clock_config.h" - SystemCoreClock = g_defaultClockConfigVlpr.coreClock; +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define MCG_PLL_DISABLE 0U /*!< MCGPLLCLK disabled */ +#define OSC_CAP0P 0U /*!< Oscillator 0pF capacitor load */ +#define OSC_ER_CLK_DISABLE 0U /*!< Disable external reference clock */ +#define SIM_OSC32KSEL_RTC32KCLK_CLK 2U /*!< OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ +#define SIM_PLLFLLSEL_IRC48MCLK_CLK 3U /*!< PLLFLL select: IRC48MCLK clock */ +#define SIM_PLLFLLSEL_MCGPLLCLK_CLK 1U /*!< PLLFLL select: MCGPLLCLK clock */ - SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); - SMC_SetPowerModeVlpr(SMC); - while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr) - { - } -} +/******************************************************************************* + * Variables + ******************************************************************************/ +/* System clock frequency. */ +extern uint32_t SystemCoreClock; -void BOARD_BootClockRUN(void) +/******************************************************************************* + * Code + ******************************************************************************/ +/*FUNCTION********************************************************************** + * + * Function Name : CLOCK_CONFIG_SetFllExtRefDiv + * Description : Configure FLL external reference divider (FRDIV). + * Param frdiv : The value to set FRDIV. + * + *END**************************************************************************/ +static void CLOCK_CONFIG_SetFllExtRefDiv(uint8_t frdiv) { - CLOCK_SetSimSafeDivs(); - - CLOCK_InitOsc0(&g_defaultClockConfigRun.oscConfig); - CLOCK_SetXtal0Freq(BOARD_XTAL0_CLK_HZ); - - CLOCK_BootToPeeMode(g_defaultClockConfigRun.mcgConfig.oscsel, kMCG_PllClkSelPll0, - &g_defaultClockConfigRun.mcgConfig.pll0Config); - - CLOCK_SetInternalRefClkConfig(g_defaultClockConfigRun.mcgConfig.irclkEnableMode, - g_defaultClockConfigRun.mcgConfig.ircs, g_defaultClockConfigRun.mcgConfig.fcrdiv); + MCG->C1 = ((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv)); +} - CLOCK_SetSimConfig(&g_defaultClockConfigRun.simConfig); +/******************************************************************************* + ********************* Configuration BOARD_BootClockHSRUN ********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!Configuration +name: BOARD_BootClockHSRUN +outputs: +- {id: Bus_clock.outFreq, value: 60 MHz} +- {id: Core_clock.outFreq, value: 180 MHz, locked: true, accuracy: '0.001'} +- {id: Flash_clock.outFreq, value: 180/7 MHz} +- {id: FlexBus_clock.outFreq, value: 60 MHz} +- {id: LPO_clock.outFreq, value: 1 kHz} +- {id: MCGFFCLK.outFreq, value: 375 kHz} +- {id: MCGIRCLK.outFreq, value: 32.768 kHz} +- {id: OSCERCLK.outFreq, value: 12 MHz} +- {id: OSCERCLK_UNDIV.outFreq, value: 12 MHz} +- {id: PLLFLLCLK.outFreq, value: 180 MHz} +- {id: System_clock.outFreq, value: 180 MHz} +settings: +- {id: MCGMode, value: PEE} +- {id: powerMode, value: HSRUN} +- {id: MCG.FCRDIV.scale, value: '1', locked: true} +- {id: MCG.FRDIV.scale, value: '32'} +- {id: MCG.IREFS.sel, value: MCG.FRDIV} +- {id: MCG.PLLS.sel, value: MCG.PLLCS} +- {id: MCG.VDIV.scale, value: '30'} +- {id: MCG_C1_IRCLKEN_CFG, value: Enabled} +- {id: MCG_C1_IREFSTEN_CFG, value: Enabled} +- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} +- {id: MCG_C2_RANGE0_CFG, value: Very_high} +- {id: MCG_C2_RANGE0_FRDIV_CFG, value: Very_high} +- {id: OSC_CR_ERCLKEN_CFG, value: Enabled} +- {id: OSC_CR_ERCLKEN_UNDIV_CFG, value: Enabled} +- {id: RTC_CR_CLKO_CFG, value: Disabled} +- {id: SIM.LPUARTSRCSEL.sel, value: OSC.OSCERCLK} +- {id: SIM.OSC32KSEL.sel, value: RTC.RTC32KCLK} +- {id: SIM.OUTDIV2.scale, value: '3', locked: true} +- {id: SIM.OUTDIV3.scale, value: '3', locked: true} +- {id: SIM.OUTDIV4.scale, value: '7', locked: true} +- {id: SIM.PLLFLLSEL.sel, value: MCG.MCGPLLCLK} +- {id: SIM.RMIICLKSEL.sel, value: SIM.ENET_1588_CLK_EXT} +- {id: SIM.SDHCSRCSEL.sel, value: OSC.OSCERCLK} +- {id: SIM.TPMSRCSEL.sel, value: SIM.PLLFLLDIV} +- {id: SIM.TRACECLKSEL.sel, value: SIM.TRACEDIV} +- {id: SIM.TRACEDIV.scale, value: '2'} +- {id: SIM.USBSRCSEL.sel, value: SIM.USBDIV} +- {id: USBPHY.DIV.scale, value: '40'} +- {id: USBPHY.PFD_CLK_SEL.sel, value: USBPHY.PFD_CLK_DIV2} +- {id: USBPHY.PFD_FRAC_DIV.scale, value: '24', locked: true} +sources: +- {id: OSC.OSC.outFreq, value: 12 MHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ - SystemCoreClock = g_defaultClockConfigRun.coreClock; -} +/******************************************************************************* + * Variables for BOARD_BootClockHSRUN configuration + ******************************************************************************/ +const mcg_config_t mcgConfig_BOARD_BootClockHSRUN = + { + .mcgMode = kMCG_ModePEE, /* PEE - PLL Engaged External */ + .irclkEnableMode = kMCG_IrclkEnable | kMCG_IrclkEnableInStop,/* MCGIRCLK enabled as well as in STOP mode */ + .ircs = kMCG_IrcSlow, /* Slow internal reference clock selected */ + .fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */ + .frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */ + .drs = kMCG_DrsLow, /* Low frequency range */ + .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ + .oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */ + .pll0Config = + { + .enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */ + .prdiv = 0x0U, /* PLL Reference divider: divided by 1 */ + .vdiv = 0xeU, /* VCO divider: multiplied by 30 */ + }, + .pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */ + }; +const sim_clock_config_t simConfig_BOARD_BootClockHSRUN = + { + .pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */ + .pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */ + .pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */ + .er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ + .clkdiv1 = 0x2260000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /3, OUTDIV3: /3, OUTDIV4: /7 */ + }; +const osc_config_t oscConfig_BOARD_BootClockHSRUN = + { + .freq = 12000000U, /* Oscillator frequency: 12000000Hz */ + .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ + .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ + .oscerConfig = + { + .enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */ + .erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */ + } + }; +/******************************************************************************* + * Code for BOARD_BootClockHSRUN configuration + ******************************************************************************/ void BOARD_BootClockHSRUN(void) { + /* Set HSRUN power mode */ SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); SMC_SetPowerModeHsrun(SMC); while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun) { } - + /* Set the system clock dividers in SIM to safe value. */ CLOCK_SetSimSafeDivs(); + /* Initializes OSC0 according to board configuration. */ + CLOCK_InitOsc0(&oscConfig_BOARD_BootClockHSRUN); + CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockHSRUN.freq); + /* Configure the Internal Reference clock (MCGIRCLK). */ + CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockHSRUN.irclkEnableMode, + mcgConfig_BOARD_BootClockHSRUN.ircs, + mcgConfig_BOARD_BootClockHSRUN.fcrdiv); + /* Configure FLL external reference divider (FRDIV). */ + CLOCK_CONFIG_SetFllExtRefDiv(mcgConfig_BOARD_BootClockHSRUN.frdiv); + /* Set MCG to PEE mode. */ + CLOCK_BootToPeeMode(mcgConfig_BOARD_BootClockHSRUN.oscsel, + mcgConfig_BOARD_BootClockHSRUN.pllcs, + &mcgConfig_BOARD_BootClockHSRUN.pll0Config); + /* Set the clock configuration in SIM module. */ + CLOCK_SetSimConfig(&simConfig_BOARD_BootClockHSRUN); + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKHSRUN_CORE_CLOCK; +} - CLOCK_InitOsc0(&g_defaultClockConfigHsrun.oscConfig); - CLOCK_SetXtal0Freq(BOARD_XTAL0_CLK_HZ); +/******************************************************************************* + ********************* Configuration BOARD_BootClockVLPR *********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!Configuration +name: BOARD_BootClockVLPR +outputs: +- {id: Bus_clock.outFreq, value: 4 MHz} +- {id: Core_clock.outFreq, value: 4 MHz} +- {id: Flash_clock.outFreq, value: 800 kHz} +- {id: FlexBus_clock.outFreq, value: 4 MHz} +- {id: LPO_clock.outFreq, value: 1 kHz} +- {id: MCGIRCLK.outFreq, value: 4 MHz} +- {id: System_clock.outFreq, value: 4 MHz} +settings: +- {id: MCGMode, value: BLPI} +- {id: powerMode, value: VLPR} +- {id: MCG.CLKS.sel, value: MCG.IRCS} +- {id: MCG.FCRDIV.scale, value: '1', locked: true} +- {id: MCG.FRDIV.scale, value: '32'} +- {id: MCG.IRCS.sel, value: MCG.FCRDIV} +- {id: MCG_C1_IRCLKEN_CFG, value: Enabled} +- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} +- {id: MCG_C2_RANGE0_CFG, value: Very_high} +- {id: MCG_C2_RANGE0_FRDIV_CFG, value: Very_high} +- {id: RTC_CR_CLKO_CFG, value: Disabled} +- {id: SIM.OSC32KSEL.sel, value: RTC.RTC32KCLK} +- {id: SIM.OUTDIV3.scale, value: '1'} +- {id: SIM.OUTDIV4.scale, value: '5'} +- {id: SIM.PLLFLLSEL.sel, value: IRC48M.IRC48MCLK} +sources: +- {id: OSC.OSC.outFreq, value: 12 MHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ + +/******************************************************************************* + * Variables for BOARD_BootClockVLPR configuration + ******************************************************************************/ +const mcg_config_t mcgConfig_BOARD_BootClockVLPR = + { + .mcgMode = kMCG_ModeBLPI, /* BLPI - Bypassed Low Power Internal */ + .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */ + .ircs = kMCG_IrcFast, /* Fast internal reference clock selected */ + .fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */ + .frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */ + .drs = kMCG_DrsLow, /* Low frequency range */ + .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ + .oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */ + .pll0Config = + { + .enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */ + .prdiv = 0x0U, /* PLL Reference divider: divided by 1 */ + .vdiv = 0x0U, /* VCO divider: multiplied by 16 */ + }, + .pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */ + }; +const sim_clock_config_t simConfig_BOARD_BootClockVLPR = + { + .pllFllSel = SIM_PLLFLLSEL_IRC48MCLK_CLK, /* PLLFLL select: IRC48MCLK clock */ + .pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */ + .pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */ + .er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ + .clkdiv1 = 0x40000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /1, OUTDIV3: /1, OUTDIV4: /5 */ + }; +const osc_config_t oscConfig_BOARD_BootClockVLPR = + { + .freq = 12000000U, /* Oscillator frequency: 12000000Hz */ + .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ + .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ + .oscerConfig = + { + .enableMode = OSC_ER_CLK_DISABLE, /* Disable external reference clock */ + .erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */ + } + }; - CLOCK_BootToPeeMode(g_defaultClockConfigHsrun.mcgConfig.oscsel, kMCG_PllClkSelPll0, - &g_defaultClockConfigHsrun.mcgConfig.pll0Config); +/******************************************************************************* + * Code for BOARD_BootClockVLPR configuration + ******************************************************************************/ +void BOARD_BootClockVLPR(void) +{ + /* Set the system clock dividers in SIM to safe value. */ + CLOCK_SetSimSafeDivs(); + /* Initializes OSC0 according to board configuration. */ + CLOCK_InitOsc0(&oscConfig_BOARD_BootClockVLPR); + CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockVLPR.freq); + /* Set MCG to BLPI mode. */ + CLOCK_BootToBlpiMode(mcgConfig_BOARD_BootClockVLPR.fcrdiv, + mcgConfig_BOARD_BootClockVLPR.ircs, + mcgConfig_BOARD_BootClockVLPR.irclkEnableMode); + /* Select the MCG external reference clock. */ + CLOCK_SetExternalRefClkConfig(mcgConfig_BOARD_BootClockVLPR.oscsel); + /* Set the clock configuration in SIM module. */ + CLOCK_SetSimConfig(&simConfig_BOARD_BootClockVLPR); + /* Set VLPR power mode. */ + SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); +#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) + SMC_SetPowerModeVlpr(SMC, false); +#else + SMC_SetPowerModeVlpr(SMC); +#endif + while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr) + { + } + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKVLPR_CORE_CLOCK; +} - CLOCK_SetInternalRefClkConfig(g_defaultClockConfigHsrun.mcgConfig.irclkEnableMode, - g_defaultClockConfigHsrun.mcgConfig.ircs, g_defaultClockConfigHsrun.mcgConfig.fcrdiv); +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR THE CLOCKS TOOL ***************************** +!!Configuration +name: BOARD_BootClockRUN +outputs: +- {id: Bus_clock.outFreq, value: 60 MHz} +- {id: Core_clock.outFreq, value: 120 MHz} +- {id: Flash_clock.outFreq, value: 24 MHz} +- {id: FlexBus_clock.outFreq, value: 60 MHz} +- {id: LPO_clock.outFreq, value: 1 kHz} +- {id: MCGFFCLK.outFreq, value: 375 kHz} +- {id: MCGIRCLK.outFreq, value: 32.768 kHz} +- {id: OSCERCLK.outFreq, value: 12 MHz} +- {id: OSCERCLK_UNDIV.outFreq, value: 12 MHz} +- {id: PLLFLLCLK.outFreq, value: 120 MHz} +- {id: System_clock.outFreq, value: 120 MHz} +settings: +- {id: MCGMode, value: PEE} +- {id: MCG.FCRDIV.scale, value: '1', locked: true} +- {id: MCG.FRDIV.scale, value: '32'} +- {id: MCG.IREFS.sel, value: MCG.FRDIV} +- {id: MCG.PLLS.sel, value: MCG.PLLCS} +- {id: MCG.PRDIV.scale, value: '1', locked: true} +- {id: MCG.VDIV.scale, value: '20', locked: true} +- {id: MCG_C1_IRCLKEN_CFG, value: Enabled} +- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} +- {id: MCG_C2_RANGE0_CFG, value: Very_high} +- {id: MCG_C2_RANGE0_FRDIV_CFG, value: Very_high} +- {id: OSC_CR_ERCLKEN_CFG, value: Enabled} +- {id: OSC_CR_ERCLKEN_UNDIV_CFG, value: Enabled} +- {id: RTC_CR_CLKO_CFG, value: Disabled} +- {id: SIM.OSC32KSEL.sel, value: RTC.RTC32KCLK} +- {id: SIM.OUTDIV1.scale, value: '1', locked: true} +- {id: SIM.OUTDIV2.scale, value: '2'} +- {id: SIM.OUTDIV4.scale, value: '5'} +- {id: SIM.PLLFLLSEL.sel, value: MCG.MCGPLLCLK} +sources: +- {id: OSC.OSC.outFreq, value: 12 MHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR THE CLOCKS TOOL **/ - CLOCK_SetSimConfig(&g_defaultClockConfigHsrun.simConfig); +/******************************************************************************* + * Variables for BOARD_BootClockRUN configuration + ******************************************************************************/ +const mcg_config_t mcgConfig_BOARD_BootClockRUN = + { + .mcgMode = kMCG_ModePEE, /* PEE - PLL Engaged External */ + .irclkEnableMode = kMCG_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */ + .ircs = kMCG_IrcSlow, /* Slow internal reference clock selected */ + .fcrdiv = 0x0U, /* Fast IRC divider: divided by 1 */ + .frdiv = 0x0U, /* FLL reference clock divider: divided by 32 */ + .drs = kMCG_DrsLow, /* Low frequency range */ + .dmx32 = kMCG_Dmx32Default, /* DCO has a default range of 25% */ + .oscsel = kMCG_OscselOsc, /* Selects System Oscillator (OSCCLK) */ + .pll0Config = + { + .enableMode = MCG_PLL_DISABLE, /* MCGPLLCLK disabled */ + .prdiv = 0x0U, /* PLL Reference divider: divided by 1 */ + .vdiv = 0x4U, /* VCO divider: multiplied by 20 */ + }, + .pllcs = kMCG_PllClkSelPll0, /* PLL0 output clock is selected */ + }; +const sim_clock_config_t simConfig_BOARD_BootClockRUN = + { + .pllFllSel = SIM_PLLFLLSEL_MCGPLLCLK_CLK, /* PLLFLL select: MCGPLLCLK clock */ + .pllFllDiv = 0, /* PLLFLLSEL clock divider divisor: divided by 1 */ + .pllFllFrac = 0, /* PLLFLLSEL clock divider fraction: multiplied by 1 */ + .er32kSrc = SIM_OSC32KSEL_RTC32KCLK_CLK, /* OSC32KSEL select: RTC32KCLK clock (32.768kHz) */ + .clkdiv1 = 0x1140000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV2: /2, OUTDIV3: /2, OUTDIV4: /5 */ + }; +const osc_config_t oscConfig_BOARD_BootClockRUN = + { + .freq = 12000000U, /* Oscillator frequency: 12000000Hz */ + .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ + .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ + .oscerConfig = + { + .enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */ + .erclkDiv = 0, /* Divider for OSCERCLK: divided by 1 */ + } + }; - SystemCoreClock = g_defaultClockConfigHsrun.coreClock; +/******************************************************************************* + * Code for BOARD_BootClockRUN configuration + ******************************************************************************/ +void BOARD_BootClockRUN(void) +{ + /* Set the system clock dividers in SIM to safe value. */ + CLOCK_SetSimSafeDivs(); + /* Initializes OSC0 according to board configuration. */ + CLOCK_InitOsc0(&oscConfig_BOARD_BootClockRUN); + CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockRUN.freq); + /* Configure the Internal Reference clock (MCGIRCLK). */ + CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockRUN.irclkEnableMode, + mcgConfig_BOARD_BootClockRUN.ircs, + mcgConfig_BOARD_BootClockRUN.fcrdiv); + /* Configure FLL external reference divider (FRDIV). */ + CLOCK_CONFIG_SetFllExtRefDiv(mcgConfig_BOARD_BootClockRUN.frdiv); + /* Set MCG to PEE mode. */ + CLOCK_BootToPeeMode(mcgConfig_BOARD_BootClockRUN.oscsel, + mcgConfig_BOARD_BootClockRUN.pllcs, + &mcgConfig_BOARD_BootClockRUN.pll0Config); + /* Set the clock configuration in SIM module. */ + CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN); + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; } + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h old mode 100644 new mode 100755 index 0a23dd9917f..1086faaa83b --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_clock_config.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -27,28 +27,121 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef _CLOCK_CONFIG_H_ #define _CLOCK_CONFIG_H_ +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define BOARD_XTAL0_CLK_HZ 12000000U /*!< Board xtal0 frequency in Hz */ + +/******************************************************************************* + ********************* Configuration BOARD_BootClockHSRUN ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockHSRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKHSRUN_CORE_CLOCK 180000000U /*!< Core clock frequency: 180000000Hz */ + +/*! @brief MCG set for BOARD_BootClockHSRUN configuration. + */ +extern const mcg_config_t mcgConfig_BOARD_BootClockHSRUN; +/*! @brief SIM module set for BOARD_BootClockHSRUN configuration. + */ +extern const sim_clock_config_t simConfig_BOARD_BootClockHSRUN; +/*! @brief OSC set for BOARD_BootClockHSRUN configuration. + */ +extern const osc_config_t oscConfig_BOARD_BootClockHSRUN; + +/******************************************************************************* + * API for BOARD_BootClockHSRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockHSRUN(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************* Configuration BOARD_BootClockVLPR *********************** + ******************************************************************************/ /******************************************************************************* - * DEFINITION + * Definitions for BOARD_BootClockVLPR configuration ******************************************************************************/ -#define BOARD_XTAL0_CLK_HZ 12000000U -#define BOARD_XTAL32K_CLK_HZ 32768U +#define BOARD_BOOTCLOCKVLPR_CORE_CLOCK 4000000U /*!< Core clock frequency: 4000000Hz */ + +/*! @brief MCG set for BOARD_BootClockVLPR configuration. + */ +extern const mcg_config_t mcgConfig_BOARD_BootClockVLPR; +/*! @brief SIM module set for BOARD_BootClockVLPR configuration. + */ +extern const sim_clock_config_t simConfig_BOARD_BootClockVLPR; +/*! @brief OSC set for BOARD_BootClockVLPR configuration. + */ +extern const osc_config_t oscConfig_BOARD_BootClockVLPR; /******************************************************************************* - * API + * API for BOARD_BootClockVLPR configuration ******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif /* __cplusplus*/ +/*! + * @brief This function executes configuration of clocks. + * + */ void BOARD_BootClockVLPR(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 120000000U /*!< Core clock frequency: 120000000Hz */ + +/*! @brief MCG set for BOARD_BootClockRUN configuration. + */ +extern const mcg_config_t mcgConfig_BOARD_BootClockRUN; +/*! @brief SIM module set for BOARD_BootClockRUN configuration. + */ +extern const sim_clock_config_t simConfig_BOARD_BootClockRUN; +/*! @brief OSC set for BOARD_BootClockRUN configuration. + */ +extern const osc_config_t oscConfig_BOARD_BootClockRUN; + +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ void BOARD_BootClockRUN(void); -void BOARD_BootClockHSRUN(void); #if defined(__cplusplus) } #endif /* __cplusplus*/ #endif /* _CLOCK_CONFIG_H_ */ + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c index 961a97f339f..a5bef533d5f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_phy.h" @@ -53,8 +53,10 @@ extern uint32_t ENET_GetInstance(ENET_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to enet clocks for each instance. */ extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT]; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -64,14 +66,30 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz) { uint32_t bssReg; uint32_t counter = PHY_TIMEOUT_COUNT; + uint32_t idReg = 0; status_t result = kStatus_Success; uint32_t instance = ENET_GetInstance(base); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Set SMI first. */ CLOCK_EnableClock(s_enetClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ ENET_SetSMI(base, srcClock_Hz, false); + /* Initialization after PHY stars to work. */ + while ((idReg != PHY_CONTROL_ID1) && (counter != 0)) + { + PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg); + counter --; + } + + if (!counter) + { + return kStatus_Fail; + } + /* Reset PHY. */ + counter = PHY_TIMEOUT_COUNT; result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); if (result == kStatus_Success) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h index bf3167fa69a..9353bea7989 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/fsl_phy.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h index 516ce8501e3..a2d8eec3b9c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18.h @@ -9,17 +9,17 @@ ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** IAR ANSI C/C++ Compiler for ARM +** MCUXpresso Compiler ** ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151218 +** Build: b170112 ** ** Abstract: ** CMSIS Peripheral Access Layer for MK66F18 ** -** Copyright (c) 1997 - 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright (c) 1997 - 2016 Freescale Semiconductor, Inc. +** Copyright 2016 - 2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -30,7 +30,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -45,8 +45,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) @@ -5218,7 +5218,7 @@ typedef struct { /** Array initializer of DMA peripheral base pointers */ #define DMA_BASE_PTRS { DMA0 } /** Interrupt vectors for the DMA peripheral type */ -#define DMA_CHN_IRQS { DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn, DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn } +#define DMA_CHN_IRQS { { DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn, DMA0_DMA16_IRQn, DMA1_DMA17_IRQn, DMA2_DMA18_IRQn, DMA3_DMA19_IRQn, DMA4_DMA20_IRQn, DMA5_DMA21_IRQn, DMA6_DMA22_IRQn, DMA7_DMA23_IRQn, DMA8_DMA24_IRQn, DMA9_DMA25_IRQn, DMA10_DMA26_IRQn, DMA11_DMA27_IRQn, DMA12_DMA28_IRQn, DMA13_DMA29_IRQn, DMA14_DMA30_IRQn, DMA15_DMA31_IRQn } } #define DMA_ERROR_IRQS { DMA_Error_IRQn } /*! @@ -6182,6 +6182,9 @@ typedef struct { #define ENET_Receive_IRQS { ENET_Receive_IRQn } #define ENET_Error_IRQS { ENET_Error_IRQn } #define ENET_1588_Timer_IRQS { ENET_1588_Timer_IRQn } +/* ENET Buffer Descriptor and Buffer Address Alignment. */ +#define ENET_BUFF_ALIGNMENT (16U) + /*! * @} @@ -7731,30 +7734,30 @@ typedef struct { /* GPIO - Peripheral instance base addresses */ -/** Peripheral PTA base address */ -#define PTA_BASE (0x400FF000u) -/** Peripheral PTA base pointer */ -#define PTA ((GPIO_Type *)PTA_BASE) -/** Peripheral PTB base address */ -#define PTB_BASE (0x400FF040u) -/** Peripheral PTB base pointer */ -#define PTB ((GPIO_Type *)PTB_BASE) -/** Peripheral PTC base address */ -#define PTC_BASE (0x400FF080u) -/** Peripheral PTC base pointer */ -#define PTC ((GPIO_Type *)PTC_BASE) -/** Peripheral PTD base address */ -#define PTD_BASE (0x400FF0C0u) -/** Peripheral PTD base pointer */ -#define PTD ((GPIO_Type *)PTD_BASE) -/** Peripheral PTE base address */ -#define PTE_BASE (0x400FF100u) -/** Peripheral PTE base pointer */ -#define PTE ((GPIO_Type *)PTE_BASE) +/** Peripheral GPIOA base address */ +#define GPIOA_BASE (0x400FF000u) +/** Peripheral GPIOA base pointer */ +#define GPIOA ((GPIO_Type *)GPIOA_BASE) +/** Peripheral GPIOB base address */ +#define GPIOB_BASE (0x400FF040u) +/** Peripheral GPIOB base pointer */ +#define GPIOB ((GPIO_Type *)GPIOB_BASE) +/** Peripheral GPIOC base address */ +#define GPIOC_BASE (0x400FF080u) +/** Peripheral GPIOC base pointer */ +#define GPIOC ((GPIO_Type *)GPIOC_BASE) +/** Peripheral GPIOD base address */ +#define GPIOD_BASE (0x400FF0C0u) +/** Peripheral GPIOD base pointer */ +#define GPIOD ((GPIO_Type *)GPIOD_BASE) +/** Peripheral GPIOE base address */ +#define GPIOE_BASE (0x400FF100u) +/** Peripheral GPIOE base pointer */ +#define GPIOE ((GPIO_Type *)GPIOE_BASE) /** Array initializer of GPIO peripheral base addresses */ -#define GPIO_BASE_ADDRS { PTA_BASE, PTB_BASE, PTC_BASE, PTD_BASE, PTE_BASE } +#define GPIO_BASE_ADDRS { GPIOA_BASE, GPIOB_BASE, GPIOC_BASE, GPIOD_BASE, GPIOE_BASE } /** Array initializer of GPIO peripheral base pointers */ -#define GPIO_BASE_PTRS { PTA, PTB, PTC, PTD, PTE } +#define GPIO_BASE_PTRS { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE } /*! * @} @@ -9827,252 +9830,6 @@ typedef struct { */ /* end of group MCM_Peripheral_Access_Layer */ -/* ---------------------------------------------------------------------------- - -- MPU Peripheral Access Layer - ---------------------------------------------------------------------------- */ - -/*! - * @addtogroup MPU_Peripheral_Access_Layer MPU Peripheral Access Layer - * @{ - */ - -/** MPU - Register Layout Typedef */ -typedef struct { - __IO uint32_t CESR; /**< Control/Error Status Register, offset: 0x0 */ - uint8_t RESERVED_0[12]; - struct { /* offset: 0x10, array step: 0x8 */ - __I uint32_t EAR; /**< Error Address Register, slave port n, array offset: 0x10, array step: 0x8 */ - __I uint32_t EDR; /**< Error Detail Register, slave port n, array offset: 0x14, array step: 0x8 */ - } SP[5]; - uint8_t RESERVED_1[968]; - __IO uint32_t WORD[12][4]; /**< Region Descriptor n, Word 0..Region Descriptor n, Word 3, array offset: 0x400, array step: index*0x10, index2*0x4 */ - uint8_t RESERVED_2[832]; - __IO uint32_t RGDAAC[12]; /**< Region Descriptor Alternate Access Control n, array offset: 0x800, array step: 0x4 */ -} MPU_Type; - -/* ---------------------------------------------------------------------------- - -- MPU Register Masks - ---------------------------------------------------------------------------- */ - -/*! - * @addtogroup MPU_Register_Masks MPU Register Masks - * @{ - */ - -/*! @name CESR - Control/Error Status Register */ -#define MPU_CESR_VLD_MASK (0x1U) -#define MPU_CESR_VLD_SHIFT (0U) -#define MPU_CESR_VLD(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_VLD_SHIFT)) & MPU_CESR_VLD_MASK) -#define MPU_CESR_NRGD_MASK (0xF00U) -#define MPU_CESR_NRGD_SHIFT (8U) -#define MPU_CESR_NRGD(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_NRGD_SHIFT)) & MPU_CESR_NRGD_MASK) -#define MPU_CESR_NSP_MASK (0xF000U) -#define MPU_CESR_NSP_SHIFT (12U) -#define MPU_CESR_NSP(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_NSP_SHIFT)) & MPU_CESR_NSP_MASK) -#define MPU_CESR_HRL_MASK (0xF0000U) -#define MPU_CESR_HRL_SHIFT (16U) -#define MPU_CESR_HRL(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_HRL_SHIFT)) & MPU_CESR_HRL_MASK) -#define MPU_CESR_SPERR_MASK (0xF8000000U) -#define MPU_CESR_SPERR_SHIFT (27U) -#define MPU_CESR_SPERR(x) (((uint32_t)(((uint32_t)(x)) << MPU_CESR_SPERR_SHIFT)) & MPU_CESR_SPERR_MASK) - -/*! @name EAR - Error Address Register, slave port n */ -#define MPU_EAR_EADDR_MASK (0xFFFFFFFFU) -#define MPU_EAR_EADDR_SHIFT (0U) -#define MPU_EAR_EADDR(x) (((uint32_t)(((uint32_t)(x)) << MPU_EAR_EADDR_SHIFT)) & MPU_EAR_EADDR_MASK) - -/* The count of MPU_EAR */ -#define MPU_EAR_COUNT (5U) - -/*! @name EDR - Error Detail Register, slave port n */ -#define MPU_EDR_ERW_MASK (0x1U) -#define MPU_EDR_ERW_SHIFT (0U) -#define MPU_EDR_ERW(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_ERW_SHIFT)) & MPU_EDR_ERW_MASK) -#define MPU_EDR_EATTR_MASK (0xEU) -#define MPU_EDR_EATTR_SHIFT (1U) -#define MPU_EDR_EATTR(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EATTR_SHIFT)) & MPU_EDR_EATTR_MASK) -#define MPU_EDR_EMN_MASK (0xF0U) -#define MPU_EDR_EMN_SHIFT (4U) -#define MPU_EDR_EMN(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EMN_SHIFT)) & MPU_EDR_EMN_MASK) -#define MPU_EDR_EPID_MASK (0xFF00U) -#define MPU_EDR_EPID_SHIFT (8U) -#define MPU_EDR_EPID(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EPID_SHIFT)) & MPU_EDR_EPID_MASK) -#define MPU_EDR_EACD_MASK (0xFFFF0000U) -#define MPU_EDR_EACD_SHIFT (16U) -#define MPU_EDR_EACD(x) (((uint32_t)(((uint32_t)(x)) << MPU_EDR_EACD_SHIFT)) & MPU_EDR_EACD_MASK) - -/* The count of MPU_EDR */ -#define MPU_EDR_COUNT (5U) - -/*! @name WORD - Region Descriptor n, Word 0..Region Descriptor n, Word 3 */ -#define MPU_WORD_VLD_MASK (0x1U) -#define MPU_WORD_VLD_SHIFT (0U) -#define MPU_WORD_VLD(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_VLD_SHIFT)) & MPU_WORD_VLD_MASK) -#define MPU_WORD_M0UM_MASK (0x7U) -#define MPU_WORD_M0UM_SHIFT (0U) -#define MPU_WORD_M0UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M0UM_SHIFT)) & MPU_WORD_M0UM_MASK) -#define MPU_WORD_M0SM_MASK (0x18U) -#define MPU_WORD_M0SM_SHIFT (3U) -#define MPU_WORD_M0SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M0SM_SHIFT)) & MPU_WORD_M0SM_MASK) -#define MPU_WORD_M0PE_MASK (0x20U) -#define MPU_WORD_M0PE_SHIFT (5U) -#define MPU_WORD_M0PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M0PE_SHIFT)) & MPU_WORD_M0PE_MASK) -#define MPU_WORD_ENDADDR_MASK (0xFFFFFFE0U) -#define MPU_WORD_ENDADDR_SHIFT (5U) -#define MPU_WORD_ENDADDR(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_ENDADDR_SHIFT)) & MPU_WORD_ENDADDR_MASK) -#define MPU_WORD_SRTADDR_MASK (0xFFFFFFE0U) -#define MPU_WORD_SRTADDR_SHIFT (5U) -#define MPU_WORD_SRTADDR(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_SRTADDR_SHIFT)) & MPU_WORD_SRTADDR_MASK) -#define MPU_WORD_M1UM_MASK (0x1C0U) -#define MPU_WORD_M1UM_SHIFT (6U) -#define MPU_WORD_M1UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M1UM_SHIFT)) & MPU_WORD_M1UM_MASK) -#define MPU_WORD_M1SM_MASK (0x600U) -#define MPU_WORD_M1SM_SHIFT (9U) -#define MPU_WORD_M1SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M1SM_SHIFT)) & MPU_WORD_M1SM_MASK) -#define MPU_WORD_M1PE_MASK (0x800U) -#define MPU_WORD_M1PE_SHIFT (11U) -#define MPU_WORD_M1PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M1PE_SHIFT)) & MPU_WORD_M1PE_MASK) -#define MPU_WORD_M2UM_MASK (0x7000U) -#define MPU_WORD_M2UM_SHIFT (12U) -#define MPU_WORD_M2UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M2UM_SHIFT)) & MPU_WORD_M2UM_MASK) -#define MPU_WORD_M2SM_MASK (0x18000U) -#define MPU_WORD_M2SM_SHIFT (15U) -#define MPU_WORD_M2SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M2SM_SHIFT)) & MPU_WORD_M2SM_MASK) -#define MPU_WORD_PIDMASK_MASK (0xFF0000U) -#define MPU_WORD_PIDMASK_SHIFT (16U) -#define MPU_WORD_PIDMASK(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_PIDMASK_SHIFT)) & MPU_WORD_PIDMASK_MASK) -#define MPU_WORD_M2PE_MASK (0x20000U) -#define MPU_WORD_M2PE_SHIFT (17U) -#define MPU_WORD_M2PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M2PE_SHIFT)) & MPU_WORD_M2PE_MASK) -#define MPU_WORD_M3UM_MASK (0x1C0000U) -#define MPU_WORD_M3UM_SHIFT (18U) -#define MPU_WORD_M3UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M3UM_SHIFT)) & MPU_WORD_M3UM_MASK) -#define MPU_WORD_M3SM_MASK (0x600000U) -#define MPU_WORD_M3SM_SHIFT (21U) -#define MPU_WORD_M3SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M3SM_SHIFT)) & MPU_WORD_M3SM_MASK) -#define MPU_WORD_M3PE_MASK (0x800000U) -#define MPU_WORD_M3PE_SHIFT (23U) -#define MPU_WORD_M3PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M3PE_SHIFT)) & MPU_WORD_M3PE_MASK) -#define MPU_WORD_PID_MASK (0xFF000000U) -#define MPU_WORD_PID_SHIFT (24U) -#define MPU_WORD_PID(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_PID_SHIFT)) & MPU_WORD_PID_MASK) -#define MPU_WORD_M4WE_MASK (0x1000000U) -#define MPU_WORD_M4WE_SHIFT (24U) -#define MPU_WORD_M4WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M4WE_SHIFT)) & MPU_WORD_M4WE_MASK) -#define MPU_WORD_M4RE_MASK (0x2000000U) -#define MPU_WORD_M4RE_SHIFT (25U) -#define MPU_WORD_M4RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M4RE_SHIFT)) & MPU_WORD_M4RE_MASK) -#define MPU_WORD_M5WE_MASK (0x4000000U) -#define MPU_WORD_M5WE_SHIFT (26U) -#define MPU_WORD_M5WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M5WE_SHIFT)) & MPU_WORD_M5WE_MASK) -#define MPU_WORD_M5RE_MASK (0x8000000U) -#define MPU_WORD_M5RE_SHIFT (27U) -#define MPU_WORD_M5RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M5RE_SHIFT)) & MPU_WORD_M5RE_MASK) -#define MPU_WORD_M6WE_MASK (0x10000000U) -#define MPU_WORD_M6WE_SHIFT (28U) -#define MPU_WORD_M6WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M6WE_SHIFT)) & MPU_WORD_M6WE_MASK) -#define MPU_WORD_M6RE_MASK (0x20000000U) -#define MPU_WORD_M6RE_SHIFT (29U) -#define MPU_WORD_M6RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M6RE_SHIFT)) & MPU_WORD_M6RE_MASK) -#define MPU_WORD_M7WE_MASK (0x40000000U) -#define MPU_WORD_M7WE_SHIFT (30U) -#define MPU_WORD_M7WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M7WE_SHIFT)) & MPU_WORD_M7WE_MASK) -#define MPU_WORD_M7RE_MASK (0x80000000U) -#define MPU_WORD_M7RE_SHIFT (31U) -#define MPU_WORD_M7RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_WORD_M7RE_SHIFT)) & MPU_WORD_M7RE_MASK) - -/* The count of MPU_WORD */ -#define MPU_WORD_COUNT (12U) - -/* The count of MPU_WORD */ -#define MPU_WORD_COUNT2 (4U) - -/*! @name RGDAAC - Region Descriptor Alternate Access Control n */ -#define MPU_RGDAAC_M0UM_MASK (0x7U) -#define MPU_RGDAAC_M0UM_SHIFT (0U) -#define MPU_RGDAAC_M0UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M0UM_SHIFT)) & MPU_RGDAAC_M0UM_MASK) -#define MPU_RGDAAC_M0SM_MASK (0x18U) -#define MPU_RGDAAC_M0SM_SHIFT (3U) -#define MPU_RGDAAC_M0SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M0SM_SHIFT)) & MPU_RGDAAC_M0SM_MASK) -#define MPU_RGDAAC_M0PE_MASK (0x20U) -#define MPU_RGDAAC_M0PE_SHIFT (5U) -#define MPU_RGDAAC_M0PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M0PE_SHIFT)) & MPU_RGDAAC_M0PE_MASK) -#define MPU_RGDAAC_M1UM_MASK (0x1C0U) -#define MPU_RGDAAC_M1UM_SHIFT (6U) -#define MPU_RGDAAC_M1UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M1UM_SHIFT)) & MPU_RGDAAC_M1UM_MASK) -#define MPU_RGDAAC_M1SM_MASK (0x600U) -#define MPU_RGDAAC_M1SM_SHIFT (9U) -#define MPU_RGDAAC_M1SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M1SM_SHIFT)) & MPU_RGDAAC_M1SM_MASK) -#define MPU_RGDAAC_M1PE_MASK (0x800U) -#define MPU_RGDAAC_M1PE_SHIFT (11U) -#define MPU_RGDAAC_M1PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M1PE_SHIFT)) & MPU_RGDAAC_M1PE_MASK) -#define MPU_RGDAAC_M2UM_MASK (0x7000U) -#define MPU_RGDAAC_M2UM_SHIFT (12U) -#define MPU_RGDAAC_M2UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M2UM_SHIFT)) & MPU_RGDAAC_M2UM_MASK) -#define MPU_RGDAAC_M2SM_MASK (0x18000U) -#define MPU_RGDAAC_M2SM_SHIFT (15U) -#define MPU_RGDAAC_M2SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M2SM_SHIFT)) & MPU_RGDAAC_M2SM_MASK) -#define MPU_RGDAAC_M2PE_MASK (0x20000U) -#define MPU_RGDAAC_M2PE_SHIFT (17U) -#define MPU_RGDAAC_M2PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M2PE_SHIFT)) & MPU_RGDAAC_M2PE_MASK) -#define MPU_RGDAAC_M3UM_MASK (0x1C0000U) -#define MPU_RGDAAC_M3UM_SHIFT (18U) -#define MPU_RGDAAC_M3UM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M3UM_SHIFT)) & MPU_RGDAAC_M3UM_MASK) -#define MPU_RGDAAC_M3SM_MASK (0x600000U) -#define MPU_RGDAAC_M3SM_SHIFT (21U) -#define MPU_RGDAAC_M3SM(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M3SM_SHIFT)) & MPU_RGDAAC_M3SM_MASK) -#define MPU_RGDAAC_M3PE_MASK (0x800000U) -#define MPU_RGDAAC_M3PE_SHIFT (23U) -#define MPU_RGDAAC_M3PE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M3PE_SHIFT)) & MPU_RGDAAC_M3PE_MASK) -#define MPU_RGDAAC_M4WE_MASK (0x1000000U) -#define MPU_RGDAAC_M4WE_SHIFT (24U) -#define MPU_RGDAAC_M4WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M4WE_SHIFT)) & MPU_RGDAAC_M4WE_MASK) -#define MPU_RGDAAC_M4RE_MASK (0x2000000U) -#define MPU_RGDAAC_M4RE_SHIFT (25U) -#define MPU_RGDAAC_M4RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M4RE_SHIFT)) & MPU_RGDAAC_M4RE_MASK) -#define MPU_RGDAAC_M5WE_MASK (0x4000000U) -#define MPU_RGDAAC_M5WE_SHIFT (26U) -#define MPU_RGDAAC_M5WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M5WE_SHIFT)) & MPU_RGDAAC_M5WE_MASK) -#define MPU_RGDAAC_M5RE_MASK (0x8000000U) -#define MPU_RGDAAC_M5RE_SHIFT (27U) -#define MPU_RGDAAC_M5RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M5RE_SHIFT)) & MPU_RGDAAC_M5RE_MASK) -#define MPU_RGDAAC_M6WE_MASK (0x10000000U) -#define MPU_RGDAAC_M6WE_SHIFT (28U) -#define MPU_RGDAAC_M6WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M6WE_SHIFT)) & MPU_RGDAAC_M6WE_MASK) -#define MPU_RGDAAC_M6RE_MASK (0x20000000U) -#define MPU_RGDAAC_M6RE_SHIFT (29U) -#define MPU_RGDAAC_M6RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M6RE_SHIFT)) & MPU_RGDAAC_M6RE_MASK) -#define MPU_RGDAAC_M7WE_MASK (0x40000000U) -#define MPU_RGDAAC_M7WE_SHIFT (30U) -#define MPU_RGDAAC_M7WE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M7WE_SHIFT)) & MPU_RGDAAC_M7WE_MASK) -#define MPU_RGDAAC_M7RE_MASK (0x80000000U) -#define MPU_RGDAAC_M7RE_SHIFT (31U) -#define MPU_RGDAAC_M7RE(x) (((uint32_t)(((uint32_t)(x)) << MPU_RGDAAC_M7RE_SHIFT)) & MPU_RGDAAC_M7RE_MASK) - -/* The count of MPU_RGDAAC */ -#define MPU_RGDAAC_COUNT (12U) - - -/*! - * @} - */ /* end of group MPU_Register_Masks */ - - -/* MPU - Peripheral instance base addresses */ -/** Peripheral MPU base address */ -#define MPU_BASE (0x4000D000u) -/** Peripheral MPU base pointer */ -#define MPU ((MPU_Type *)MPU_BASE) -/** Array initializer of MPU peripheral base addresses */ -#define MPU_BASE_ADDRS { MPU_BASE } -/** Array initializer of MPU peripheral base pointers */ -#define MPU_BASE_PTRS { MPU } - -/*! - * @} - */ /* end of group MPU_Peripheral_Access_Layer */ - - /* ---------------------------------------------------------------------------- -- NV Peripheral Access Layer ---------------------------------------------------------------------------- */ @@ -10590,7 +10347,7 @@ typedef struct { /** Array initializer of PIT peripheral base pointers */ #define PIT_BASE_PTRS { PIT } /** Interrupt vectors for the PIT peripheral type */ -#define PIT_IRQS { PIT0_IRQn, PIT1_IRQn, PIT2_IRQn, PIT3_IRQn } +#define PIT_IRQS { { PIT0_IRQn, PIT1_IRQn, PIT2_IRQn, PIT3_IRQn } } /*! * @} @@ -13236,6 +12993,252 @@ typedef struct { */ /* end of group SPI_Peripheral_Access_Layer */ +/* ---------------------------------------------------------------------------- + -- SYSMPU Peripheral Access Layer + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup SYSMPU_Peripheral_Access_Layer SYSMPU Peripheral Access Layer + * @{ + */ + +/** SYSMPU - Register Layout Typedef */ +typedef struct { + __IO uint32_t CESR; /**< Control/Error Status Register, offset: 0x0 */ + uint8_t RESERVED_0[12]; + struct { /* offset: 0x10, array step: 0x8 */ + __I uint32_t EAR; /**< Error Address Register, slave port n, array offset: 0x10, array step: 0x8 */ + __I uint32_t EDR; /**< Error Detail Register, slave port n, array offset: 0x14, array step: 0x8 */ + } SP[5]; + uint8_t RESERVED_1[968]; + __IO uint32_t WORD[12][4]; /**< Region Descriptor n, Word 0..Region Descriptor n, Word 3, array offset: 0x400, array step: index*0x10, index2*0x4 */ + uint8_t RESERVED_2[832]; + __IO uint32_t RGDAAC[12]; /**< Region Descriptor Alternate Access Control n, array offset: 0x800, array step: 0x4 */ +} SYSMPU_Type; + +/* ---------------------------------------------------------------------------- + -- SYSMPU Register Masks + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup SYSMPU_Register_Masks SYSMPU Register Masks + * @{ + */ + +/*! @name CESR - Control/Error Status Register */ +#define SYSMPU_CESR_VLD_MASK (0x1U) +#define SYSMPU_CESR_VLD_SHIFT (0U) +#define SYSMPU_CESR_VLD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_VLD_SHIFT)) & SYSMPU_CESR_VLD_MASK) +#define SYSMPU_CESR_NRGD_MASK (0xF00U) +#define SYSMPU_CESR_NRGD_SHIFT (8U) +#define SYSMPU_CESR_NRGD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_NRGD_SHIFT)) & SYSMPU_CESR_NRGD_MASK) +#define SYSMPU_CESR_NSP_MASK (0xF000U) +#define SYSMPU_CESR_NSP_SHIFT (12U) +#define SYSMPU_CESR_NSP(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_NSP_SHIFT)) & SYSMPU_CESR_NSP_MASK) +#define SYSMPU_CESR_HRL_MASK (0xF0000U) +#define SYSMPU_CESR_HRL_SHIFT (16U) +#define SYSMPU_CESR_HRL(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_HRL_SHIFT)) & SYSMPU_CESR_HRL_MASK) +#define SYSMPU_CESR_SPERR_MASK (0xF8000000U) +#define SYSMPU_CESR_SPERR_SHIFT (27U) +#define SYSMPU_CESR_SPERR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_CESR_SPERR_SHIFT)) & SYSMPU_CESR_SPERR_MASK) + +/*! @name EAR - Error Address Register, slave port n */ +#define SYSMPU_EAR_EADDR_MASK (0xFFFFFFFFU) +#define SYSMPU_EAR_EADDR_SHIFT (0U) +#define SYSMPU_EAR_EADDR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EAR_EADDR_SHIFT)) & SYSMPU_EAR_EADDR_MASK) + +/* The count of SYSMPU_EAR */ +#define SYSMPU_EAR_COUNT (5U) + +/*! @name EDR - Error Detail Register, slave port n */ +#define SYSMPU_EDR_ERW_MASK (0x1U) +#define SYSMPU_EDR_ERW_SHIFT (0U) +#define SYSMPU_EDR_ERW(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_ERW_SHIFT)) & SYSMPU_EDR_ERW_MASK) +#define SYSMPU_EDR_EATTR_MASK (0xEU) +#define SYSMPU_EDR_EATTR_SHIFT (1U) +#define SYSMPU_EDR_EATTR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EATTR_SHIFT)) & SYSMPU_EDR_EATTR_MASK) +#define SYSMPU_EDR_EMN_MASK (0xF0U) +#define SYSMPU_EDR_EMN_SHIFT (4U) +#define SYSMPU_EDR_EMN(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EMN_SHIFT)) & SYSMPU_EDR_EMN_MASK) +#define SYSMPU_EDR_EPID_MASK (0xFF00U) +#define SYSMPU_EDR_EPID_SHIFT (8U) +#define SYSMPU_EDR_EPID(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EPID_SHIFT)) & SYSMPU_EDR_EPID_MASK) +#define SYSMPU_EDR_EACD_MASK (0xFFFF0000U) +#define SYSMPU_EDR_EACD_SHIFT (16U) +#define SYSMPU_EDR_EACD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_EDR_EACD_SHIFT)) & SYSMPU_EDR_EACD_MASK) + +/* The count of SYSMPU_EDR */ +#define SYSMPU_EDR_COUNT (5U) + +/*! @name WORD - Region Descriptor n, Word 0..Region Descriptor n, Word 3 */ +#define SYSMPU_WORD_VLD_MASK (0x1U) +#define SYSMPU_WORD_VLD_SHIFT (0U) +#define SYSMPU_WORD_VLD(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_VLD_SHIFT)) & SYSMPU_WORD_VLD_MASK) +#define SYSMPU_WORD_M0UM_MASK (0x7U) +#define SYSMPU_WORD_M0UM_SHIFT (0U) +#define SYSMPU_WORD_M0UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M0UM_SHIFT)) & SYSMPU_WORD_M0UM_MASK) +#define SYSMPU_WORD_M0SM_MASK (0x18U) +#define SYSMPU_WORD_M0SM_SHIFT (3U) +#define SYSMPU_WORD_M0SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M0SM_SHIFT)) & SYSMPU_WORD_M0SM_MASK) +#define SYSMPU_WORD_M0PE_MASK (0x20U) +#define SYSMPU_WORD_M0PE_SHIFT (5U) +#define SYSMPU_WORD_M0PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M0PE_SHIFT)) & SYSMPU_WORD_M0PE_MASK) +#define SYSMPU_WORD_ENDADDR_MASK (0xFFFFFFE0U) +#define SYSMPU_WORD_ENDADDR_SHIFT (5U) +#define SYSMPU_WORD_ENDADDR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_ENDADDR_SHIFT)) & SYSMPU_WORD_ENDADDR_MASK) +#define SYSMPU_WORD_SRTADDR_MASK (0xFFFFFFE0U) +#define SYSMPU_WORD_SRTADDR_SHIFT (5U) +#define SYSMPU_WORD_SRTADDR(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_SRTADDR_SHIFT)) & SYSMPU_WORD_SRTADDR_MASK) +#define SYSMPU_WORD_M1UM_MASK (0x1C0U) +#define SYSMPU_WORD_M1UM_SHIFT (6U) +#define SYSMPU_WORD_M1UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M1UM_SHIFT)) & SYSMPU_WORD_M1UM_MASK) +#define SYSMPU_WORD_M1SM_MASK (0x600U) +#define SYSMPU_WORD_M1SM_SHIFT (9U) +#define SYSMPU_WORD_M1SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M1SM_SHIFT)) & SYSMPU_WORD_M1SM_MASK) +#define SYSMPU_WORD_M1PE_MASK (0x800U) +#define SYSMPU_WORD_M1PE_SHIFT (11U) +#define SYSMPU_WORD_M1PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M1PE_SHIFT)) & SYSMPU_WORD_M1PE_MASK) +#define SYSMPU_WORD_M2UM_MASK (0x7000U) +#define SYSMPU_WORD_M2UM_SHIFT (12U) +#define SYSMPU_WORD_M2UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M2UM_SHIFT)) & SYSMPU_WORD_M2UM_MASK) +#define SYSMPU_WORD_M2SM_MASK (0x18000U) +#define SYSMPU_WORD_M2SM_SHIFT (15U) +#define SYSMPU_WORD_M2SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M2SM_SHIFT)) & SYSMPU_WORD_M2SM_MASK) +#define SYSMPU_WORD_PIDMASK_MASK (0xFF0000U) +#define SYSMPU_WORD_PIDMASK_SHIFT (16U) +#define SYSMPU_WORD_PIDMASK(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_PIDMASK_SHIFT)) & SYSMPU_WORD_PIDMASK_MASK) +#define SYSMPU_WORD_M2PE_MASK (0x20000U) +#define SYSMPU_WORD_M2PE_SHIFT (17U) +#define SYSMPU_WORD_M2PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M2PE_SHIFT)) & SYSMPU_WORD_M2PE_MASK) +#define SYSMPU_WORD_M3UM_MASK (0x1C0000U) +#define SYSMPU_WORD_M3UM_SHIFT (18U) +#define SYSMPU_WORD_M3UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M3UM_SHIFT)) & SYSMPU_WORD_M3UM_MASK) +#define SYSMPU_WORD_M3SM_MASK (0x600000U) +#define SYSMPU_WORD_M3SM_SHIFT (21U) +#define SYSMPU_WORD_M3SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M3SM_SHIFT)) & SYSMPU_WORD_M3SM_MASK) +#define SYSMPU_WORD_M3PE_MASK (0x800000U) +#define SYSMPU_WORD_M3PE_SHIFT (23U) +#define SYSMPU_WORD_M3PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M3PE_SHIFT)) & SYSMPU_WORD_M3PE_MASK) +#define SYSMPU_WORD_PID_MASK (0xFF000000U) +#define SYSMPU_WORD_PID_SHIFT (24U) +#define SYSMPU_WORD_PID(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_PID_SHIFT)) & SYSMPU_WORD_PID_MASK) +#define SYSMPU_WORD_M4WE_MASK (0x1000000U) +#define SYSMPU_WORD_M4WE_SHIFT (24U) +#define SYSMPU_WORD_M4WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M4WE_SHIFT)) & SYSMPU_WORD_M4WE_MASK) +#define SYSMPU_WORD_M4RE_MASK (0x2000000U) +#define SYSMPU_WORD_M4RE_SHIFT (25U) +#define SYSMPU_WORD_M4RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M4RE_SHIFT)) & SYSMPU_WORD_M4RE_MASK) +#define SYSMPU_WORD_M5WE_MASK (0x4000000U) +#define SYSMPU_WORD_M5WE_SHIFT (26U) +#define SYSMPU_WORD_M5WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M5WE_SHIFT)) & SYSMPU_WORD_M5WE_MASK) +#define SYSMPU_WORD_M5RE_MASK (0x8000000U) +#define SYSMPU_WORD_M5RE_SHIFT (27U) +#define SYSMPU_WORD_M5RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M5RE_SHIFT)) & SYSMPU_WORD_M5RE_MASK) +#define SYSMPU_WORD_M6WE_MASK (0x10000000U) +#define SYSMPU_WORD_M6WE_SHIFT (28U) +#define SYSMPU_WORD_M6WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M6WE_SHIFT)) & SYSMPU_WORD_M6WE_MASK) +#define SYSMPU_WORD_M6RE_MASK (0x20000000U) +#define SYSMPU_WORD_M6RE_SHIFT (29U) +#define SYSMPU_WORD_M6RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M6RE_SHIFT)) & SYSMPU_WORD_M6RE_MASK) +#define SYSMPU_WORD_M7WE_MASK (0x40000000U) +#define SYSMPU_WORD_M7WE_SHIFT (30U) +#define SYSMPU_WORD_M7WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M7WE_SHIFT)) & SYSMPU_WORD_M7WE_MASK) +#define SYSMPU_WORD_M7RE_MASK (0x80000000U) +#define SYSMPU_WORD_M7RE_SHIFT (31U) +#define SYSMPU_WORD_M7RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_WORD_M7RE_SHIFT)) & SYSMPU_WORD_M7RE_MASK) + +/* The count of SYSMPU_WORD */ +#define SYSMPU_WORD_COUNT (12U) + +/* The count of SYSMPU_WORD */ +#define SYSMPU_WORD_COUNT2 (4U) + +/*! @name RGDAAC - Region Descriptor Alternate Access Control n */ +#define SYSMPU_RGDAAC_M0UM_MASK (0x7U) +#define SYSMPU_RGDAAC_M0UM_SHIFT (0U) +#define SYSMPU_RGDAAC_M0UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M0UM_SHIFT)) & SYSMPU_RGDAAC_M0UM_MASK) +#define SYSMPU_RGDAAC_M0SM_MASK (0x18U) +#define SYSMPU_RGDAAC_M0SM_SHIFT (3U) +#define SYSMPU_RGDAAC_M0SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M0SM_SHIFT)) & SYSMPU_RGDAAC_M0SM_MASK) +#define SYSMPU_RGDAAC_M0PE_MASK (0x20U) +#define SYSMPU_RGDAAC_M0PE_SHIFT (5U) +#define SYSMPU_RGDAAC_M0PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M0PE_SHIFT)) & SYSMPU_RGDAAC_M0PE_MASK) +#define SYSMPU_RGDAAC_M1UM_MASK (0x1C0U) +#define SYSMPU_RGDAAC_M1UM_SHIFT (6U) +#define SYSMPU_RGDAAC_M1UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M1UM_SHIFT)) & SYSMPU_RGDAAC_M1UM_MASK) +#define SYSMPU_RGDAAC_M1SM_MASK (0x600U) +#define SYSMPU_RGDAAC_M1SM_SHIFT (9U) +#define SYSMPU_RGDAAC_M1SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M1SM_SHIFT)) & SYSMPU_RGDAAC_M1SM_MASK) +#define SYSMPU_RGDAAC_M1PE_MASK (0x800U) +#define SYSMPU_RGDAAC_M1PE_SHIFT (11U) +#define SYSMPU_RGDAAC_M1PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M1PE_SHIFT)) & SYSMPU_RGDAAC_M1PE_MASK) +#define SYSMPU_RGDAAC_M2UM_MASK (0x7000U) +#define SYSMPU_RGDAAC_M2UM_SHIFT (12U) +#define SYSMPU_RGDAAC_M2UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M2UM_SHIFT)) & SYSMPU_RGDAAC_M2UM_MASK) +#define SYSMPU_RGDAAC_M2SM_MASK (0x18000U) +#define SYSMPU_RGDAAC_M2SM_SHIFT (15U) +#define SYSMPU_RGDAAC_M2SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M2SM_SHIFT)) & SYSMPU_RGDAAC_M2SM_MASK) +#define SYSMPU_RGDAAC_M2PE_MASK (0x20000U) +#define SYSMPU_RGDAAC_M2PE_SHIFT (17U) +#define SYSMPU_RGDAAC_M2PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M2PE_SHIFT)) & SYSMPU_RGDAAC_M2PE_MASK) +#define SYSMPU_RGDAAC_M3UM_MASK (0x1C0000U) +#define SYSMPU_RGDAAC_M3UM_SHIFT (18U) +#define SYSMPU_RGDAAC_M3UM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M3UM_SHIFT)) & SYSMPU_RGDAAC_M3UM_MASK) +#define SYSMPU_RGDAAC_M3SM_MASK (0x600000U) +#define SYSMPU_RGDAAC_M3SM_SHIFT (21U) +#define SYSMPU_RGDAAC_M3SM(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M3SM_SHIFT)) & SYSMPU_RGDAAC_M3SM_MASK) +#define SYSMPU_RGDAAC_M3PE_MASK (0x800000U) +#define SYSMPU_RGDAAC_M3PE_SHIFT (23U) +#define SYSMPU_RGDAAC_M3PE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M3PE_SHIFT)) & SYSMPU_RGDAAC_M3PE_MASK) +#define SYSMPU_RGDAAC_M4WE_MASK (0x1000000U) +#define SYSMPU_RGDAAC_M4WE_SHIFT (24U) +#define SYSMPU_RGDAAC_M4WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M4WE_SHIFT)) & SYSMPU_RGDAAC_M4WE_MASK) +#define SYSMPU_RGDAAC_M4RE_MASK (0x2000000U) +#define SYSMPU_RGDAAC_M4RE_SHIFT (25U) +#define SYSMPU_RGDAAC_M4RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M4RE_SHIFT)) & SYSMPU_RGDAAC_M4RE_MASK) +#define SYSMPU_RGDAAC_M5WE_MASK (0x4000000U) +#define SYSMPU_RGDAAC_M5WE_SHIFT (26U) +#define SYSMPU_RGDAAC_M5WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M5WE_SHIFT)) & SYSMPU_RGDAAC_M5WE_MASK) +#define SYSMPU_RGDAAC_M5RE_MASK (0x8000000U) +#define SYSMPU_RGDAAC_M5RE_SHIFT (27U) +#define SYSMPU_RGDAAC_M5RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M5RE_SHIFT)) & SYSMPU_RGDAAC_M5RE_MASK) +#define SYSMPU_RGDAAC_M6WE_MASK (0x10000000U) +#define SYSMPU_RGDAAC_M6WE_SHIFT (28U) +#define SYSMPU_RGDAAC_M6WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M6WE_SHIFT)) & SYSMPU_RGDAAC_M6WE_MASK) +#define SYSMPU_RGDAAC_M6RE_MASK (0x20000000U) +#define SYSMPU_RGDAAC_M6RE_SHIFT (29U) +#define SYSMPU_RGDAAC_M6RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M6RE_SHIFT)) & SYSMPU_RGDAAC_M6RE_MASK) +#define SYSMPU_RGDAAC_M7WE_MASK (0x40000000U) +#define SYSMPU_RGDAAC_M7WE_SHIFT (30U) +#define SYSMPU_RGDAAC_M7WE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M7WE_SHIFT)) & SYSMPU_RGDAAC_M7WE_MASK) +#define SYSMPU_RGDAAC_M7RE_MASK (0x80000000U) +#define SYSMPU_RGDAAC_M7RE_SHIFT (31U) +#define SYSMPU_RGDAAC_M7RE(x) (((uint32_t)(((uint32_t)(x)) << SYSMPU_RGDAAC_M7RE_SHIFT)) & SYSMPU_RGDAAC_M7RE_MASK) + +/* The count of SYSMPU_RGDAAC */ +#define SYSMPU_RGDAAC_COUNT (12U) + + +/*! + * @} + */ /* end of group SYSMPU_Register_Masks */ + + +/* SYSMPU - Peripheral instance base addresses */ +/** Peripheral SYSMPU base address */ +#define SYSMPU_BASE (0x4000D000u) +/** Peripheral SYSMPU base pointer */ +#define SYSMPU ((SYSMPU_Type *)SYSMPU_BASE) +/** Array initializer of SYSMPU peripheral base addresses */ +#define SYSMPU_BASE_ADDRS { SYSMPU_BASE } +/** Array initializer of SYSMPU peripheral base pointers */ +#define SYSMPU_BASE_PTRS { SYSMPU } + +/*! + * @} + */ /* end of group SYSMPU_Peripheral_Access_Layer */ + + /* ---------------------------------------------------------------------------- -- TPM Peripheral Access Layer ---------------------------------------------------------------------------- */ @@ -17249,6 +17252,43 @@ typedef struct { */ /* end of group Peripheral_access_layer */ +/* ---------------------------------------------------------------------------- + -- Macros for use with bit field definitions (xxx_SHIFT, xxx_MASK). + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup Bit_Field_Generic_Macros Macros for use with bit field definitions (xxx_SHIFT, xxx_MASK). + * @{ + */ + +#if defined(__ARMCC_VERSION) + #if (__ARMCC_VERSION >= 6010050) + #pragma clang system_header + #endif +#elif defined(__IAR_SYSTEMS_ICC__) + #pragma system_include +#endif + +/** + * @brief Mask and left-shift a bit field value for use in a register bit range. + * @param field Name of the register bit field. + * @param value Value of the bit field. + * @return Masked and shifted value. + */ +#define NXP_VAL2FLD(field, value) (((value) << (field ## _SHIFT)) & (field ## _MASK)) +/** + * @brief Mask and right-shift a register value to extract a bit field value. + * @param field Name of the register bit field. + * @param value Value of the register. + * @return Masked and shifted bit field value. + */ +#define NXP_FLD2VAL(field, value) (((value) & (field ## _MASK)) >> (field ## _SHIFT)) + +/*! + * @} + */ /* end of group Bit_Field_Generic_Macros */ + + /* ---------------------------------------------------------------------------- -- SDK Compatibility ---------------------------------------------------------------------------- */ @@ -17498,16 +17538,16 @@ typedef struct { #define DSPI2 SPI2 #define FLEXCAN0 CAN0 #define FLEXCAN1 CAN1 -#define GPIOA_BASE PTA_BASE -#define GPIOA PTA -#define GPIOB_BASE PTB_BASE -#define GPIOB PTB -#define GPIOC_BASE PTC_BASE -#define GPIOC PTC -#define GPIOD_BASE PTD_BASE -#define GPIOD PTD -#define GPIOE_BASE PTE_BASE -#define GPIOE PTE +#define PTA_BASE GPIOA_BASE +#define PTA GPIOA +#define PTB_BASE GPIOB_BASE +#define PTB GPIOB +#define PTC_BASE GPIOC_BASE +#define PTC GPIOC +#define PTD_BASE GPIOD_BASE +#define PTD GPIOD +#define PTE_BASE GPIOE_BASE +#define PTE GPIOE #define Watchdog_IRQn WDOG_EWM_IRQn #define Watchdog_IRQHandler WDOG_EWM_IRQHandler #define LPTimer_IRQn LPTMR0_IRQn diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h index 07207f3a71c..19bfac70136 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/MK66F18_features.h @@ -1,14 +1,13 @@ /* ** ################################################################### ** Version: rev. 2.9, 2015-06-08 -** Build: b151217 +** Build: b170228 ** ** Abstract: ** Chip specific module features. ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -19,7 +18,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -34,8 +33,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) @@ -212,8 +211,8 @@ #define FSL_FEATURE_SOC_MMAU_COUNT (0) /* @brief MMDVSQ availability on the SoC. */ #define FSL_FEATURE_SOC_MMDVSQ_COUNT (0) -/* @brief MPU availability on the SoC. */ -#define FSL_FEATURE_SOC_MPU_COUNT (1) +/* @brief SYSMPU availability on the SoC. */ +#define FSL_FEATURE_SOC_SYSMPU_COUNT (1) /* @brief MSCAN availability on the SoC. */ #define FSL_FEATURE_SOC_MSCAN_COUNT (0) /* @brief MSCM availability on the SoC. */ @@ -304,6 +303,8 @@ #define FSL_FEATURE_SOC_USB_COUNT (1) /* @brief USBDCD availability on the SoC. */ #define FSL_FEATURE_SOC_USBDCD_COUNT (1) +/* @brief USBHS availability on the SoC. */ +#define FSL_FEATURE_SOC_USBHS_COUNT (1) /* @brief USBHSDCD availability on the SoC. */ #define FSL_FEATURE_SOC_USBHSDCD_COUNT (1) /* @brief USBPHY availability on the SoC. */ @@ -376,6 +377,8 @@ #define FSL_FEATURE_FLEXCAN_HAS_BUF31TO0M (0) /* @brief Number of interrupt vectors. */ #define FSL_FEATURE_FLEXCAN_INTERRUPT_COUNT (6) +/* @brief Is affected by errata with ID 5641 (Module does not transmit a message that is enabled to be transmitted at a specific moment during the arbitration process). */ +#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641 (0) /* CMP module features */ @@ -437,7 +440,7 @@ #define FSL_FEATURE_DMAMUX_MODULE_CHANNEL (32) /* @brief Total number of DMA channels on all modules. */ #define FSL_FEATURE_DMAMUX_DMAMUX_CHANNELS (FSL_FEATURE_SOC_DMAMUX_COUNT * 32) -/* @brief Has the periodic trigger capability for the triggered DMA channel 0 (register bit CHCFG0[TRIG]). */ +/* @brief Has the periodic trigger capability for the triggered DMA channel (register bit CHCFG0[TRIG]). */ #define FSL_FEATURE_DMAMUX_HAS_TRIG (1) /* ENET module features */ @@ -485,6 +488,10 @@ #define FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS (1) /* @brief Has flash cache control in MCM module. */ #define FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has flash cache control in MSCM module. */ + #define FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has prefetch speculation control in flash, such as kv5x. */ + #define FSL_FEATURE_FLASH_PREFETCH_SPECULATION_CONTROL_IN_FLASH (0) /* @brief P-Flash start address. */ #define FSL_FEATURE_FLASH_PFLASH_START_ADDRESS (0x00000000) /* @brief P-Flash block count. */ @@ -499,6 +506,8 @@ #define FSL_FEATURE_FLASH_PFLASH_BLOCK_DATA_PATH_WIDTH (16) /* @brief P-Flash block swap feature. */ #define FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP (1) + /* @brief P-Flash protection region count. */ + #define FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT (32) /* @brief Has FlexNVM memory. */ #define FSL_FEATURE_FLASH_HAS_FLEX_NVM (0) /* @brief FlexNVM start address. (Valid only if FlexNVM is available.) */ @@ -551,6 +560,10 @@ #define FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD (1) /* @brief Has 0x49 Erase All Blocks Unsecure command. */ #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD (0) + /* @brief Has 0x4A Read 1s All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_READ_1S_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) + /* @brief Has 0x4B Erase All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) /* @brief Has 0x80 Program Partition command. */ #define FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD (0) /* @brief Has 0x81 Set FlexRAM Function command. */ @@ -662,6 +675,10 @@ #define FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS (1) /* @brief Has flash cache control in MCM module. */ #define FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has flash cache control in MSCM module. */ + #define FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS (0) + /* @brief Has prefetch speculation control in flash, such as kv5x. */ + #define FSL_FEATURE_FLASH_PREFETCH_SPECULATION_CONTROL_IN_FLASH (0) /* @brief P-Flash start address. */ #define FSL_FEATURE_FLASH_PFLASH_START_ADDRESS (0x00000000) /* @brief P-Flash block count. */ @@ -676,6 +693,8 @@ #define FSL_FEATURE_FLASH_PFLASH_BLOCK_DATA_PATH_WIDTH (16) /* @brief P-Flash block swap feature. */ #define FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP (1) + /* @brief P-Flash protection region count. */ + #define FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT (16) /* @brief Has FlexNVM memory. */ #define FSL_FEATURE_FLASH_HAS_FLEX_NVM (1) /* @brief FlexNVM start address. (Valid only if FlexNVM is available.) */ @@ -728,6 +747,10 @@ #define FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD (1) /* @brief Has 0x49 Erase All Blocks Unsecure command. */ #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD (0) + /* @brief Has 0x4A Read 1s All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_READ_1S_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) + /* @brief Has 0x4B Erase All Execute-only Segments command. */ + #define FSL_FEATURE_FLASH_HAS_ERASE_ALL_EXECUTE_ONLY_SEGMENTS_CMD (0) /* @brief Has 0x80 Program Partition command. */ #define FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD (1) /* @brief Has 0x81 Set FlexRAM Function command. */ @@ -830,6 +853,8 @@ ((x) == FTM3 ? (8) : (-1))))) /* @brief Has counter reset by the selected input capture event (register bits C0SC[ICRST], C1SC[ICRST], ...). */ #define FSL_FEATURE_FTM_HAS_COUNTER_RESET_BY_CAPTURE_EVENT (0) +/* @brief Has extended deadtime value. */ +#define FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE (0) /* @brief Enable pwm output for the module. */ #define FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT (0) /* @brief Has half-cycle reload for the module. */ @@ -839,6 +864,15 @@ /* @brief Has reload initialization trigger. */ #define FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER (0) +/* GPIO module features */ + +/* @brief Has fast (single cycle) access capability via a dedicated memory region. */ +#define FSL_FEATURE_GPIO_HAS_FAST_GPIO (0) +/* @brief Has port input disable register (PIDR). */ +#define FSL_FEATURE_GPIO_HAS_INPUT_DISABLE (0) +/* @brief Has dedicated interrupt vector. */ +#define FSL_FEATURE_GPIO_HAS_PORT_INTERRUPT_VECTOR (1) + /* I2C module features */ /* @brief Has System Management Bus support (registers SMB, A2, SLTL and SLTH). */ @@ -861,6 +895,8 @@ #define FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION (1) /* @brief Has double buffering support (register S2). */ #define FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING (0) +/* @brief Has double buffer enable. */ +#define FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE (0) /* SAI module features */ @@ -899,12 +935,14 @@ #define FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE (8) /* @brief Number of digital filters. */ #define FSL_FEATURE_LLWU_HAS_PIN_FILTER (4) -/* @brief Has MF5 register. */ +/* @brief Has MF register. */ #define FSL_FEATURE_LLWU_HAS_MF (1) /* @brief Has PF register. */ #define FSL_FEATURE_LLWU_HAS_PF (1) /* @brief Has possibility to enable reset in low leakage power mode and enable digital filter for RESET pin (register LLWU_RST). */ #define FSL_FEATURE_LLWU_HAS_RESET_ENABLE (0) +/* @brief Has no internal module wakeup flag register. */ +#define FSL_FEATURE_LLWU_HAS_NO_INTERNAL_MODULE_WAKEUP_FLAG_REG (0) /* @brief Has external pin 0 connected to LLWU device. */ #define FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN0 (1) /* @brief Index of port of external pin. */ @@ -1126,14 +1164,24 @@ /* @brief Has process identifier support. */ #define FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE (0) +/* @brief L1 ICACHE line size in byte. */ +#define FSL_FEATURE_L1ICACHE_LINESIZE_BYTE (16) +/* @brief L1 DCACHE line size in byte. */ +#define FSL_FEATURE_L1DCACHE_LINESIZE_BYTE (16) /* LPTMR module features */ /* @brief Has shared interrupt handler with another LPTMR module. */ #define FSL_FEATURE_LPTMR_HAS_SHARED_IRQ_HANDLER (0) +/* @brief Whether LPTMR counter is 32 bits width. */ +#define FSL_FEATURE_LPTMR_CNR_WIDTH_IS_32B (0) +/* @brief Has timer DMA request enable (register bit CSR[TDRE]). */ +#define FSL_FEATURE_LPTMR_HAS_CSR_TDRE (0) /* LPUART module features */ +/* @brief LPUART0 and LPUART1 has shared interrupt vector. */ +#define FSL_FEATURE_LPUART_HAS_SHARED_IRQ0_IRQ1 (0) /* @brief Has receive FIFO overflow detection (bit field CFIFO[RXOFE]). */ #define FSL_FEATURE_LPUART_HAS_IRQ_EXTENDED_FUNCTIONS (0) /* @brief Has low power features (can be enabled in wait mode via register bit C1[DOZEEN] or CTRL[DOZEEN] if the registers are 32-bit wide). */ @@ -1150,8 +1198,10 @@ #define FSL_FEATURE_LPUART_HAS_IR_SUPPORT (1) /* @brief 2 bits long stop bit is available. */ #define FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT (1) -/* @brief Maximal data width without parity bit. */ +/* @brief If 10-bit mode is supported. */ #define FSL_FEATURE_LPUART_HAS_10BIT_DATA_SUPPORT (1) +/* @brief If 7-bit mode is supported. */ +#define FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT (0) /* @brief Baud rate fine adjustment is available. */ #define FSL_FEATURE_LPUART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT (0) /* @brief Baud rate oversampling is available (has bit fields C4[OSR], C5[BOTHEDGE], C5[RESYNCDIS] or BAUD[OSR], BAUD[BOTHEDGE], BAUD[RESYNCDIS] if the registers are 32-bit wide). */ @@ -1184,12 +1234,14 @@ #define FSL_FEATURE_LPUART_HAS_LOCAL_OPERATION_NETWORK_SUPPORT (0) /* @brief Has 32-bit registers (BAUD, STAT, CTRL, DATA, MATCH, MODIR) instead of 8-bit (BDH, BDL, C1, S1, D, etc.). */ #define FSL_FEATURE_LPUART_HAS_32BIT_REGISTERS (1) -/* @brief Lin break detect available (has bit BDH[LBKDIE]). */ -#define FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT (0) +/* @brief Lin break detect available (has bit BAUD[LBKDIE]). */ +#define FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT (1) /* @brief UART stops in Wait mode available (has bit C1[UARTSWAI]). */ #define FSL_FEATURE_LPUART_HAS_WAIT_MODE_OPERATION (0) /* @brief Has separate DMA RX and TX requests. */ #define FSL_FEATURE_LPUART_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1) +/* @brief Has separate RX and TX interrupts. */ +#define FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ (0) /* @brief Has LPAURT_PARAM. */ #define FSL_FEATURE_LPUART_HAS_PARAM (0) /* @brief Has LPUART_VERID. */ @@ -1239,7 +1291,7 @@ #define FSL_FEATURE_MCG_USE_PLLREFSEL (0) /* @brief TBD */ #define FSL_FEATURE_MCG_USE_SYSTEM_CLOCK (0) -/* @brief Has phase-locked loop (PLL) (register C5 and bits C6[VDIV], C6[PLLS], C6[LOLIE0], S[PLLST], S[LOCK0], S[LOLS]). */ +/* @brief Has phase-locked loop (PLL) (register C5 and bits C6[VDIV], C6[PLLS], C6[LOLIE0], S[PLLST], S[LOCK0], S[LOLS0]). */ #define FSL_FEATURE_MCG_HAS_PLL (1) /* @brief Has phase-locked loop (PLL) PRDIV (register C5[PRDIV]. */ #define FSL_FEATURE_MCG_HAS_PLL_PRDIV (1) @@ -1270,29 +1322,6 @@ /* @brief Reset clock mode is BLPI. */ #define FSL_FEATURE_MCG_RESET_IS_BLPI (0) -/* MPU module features */ - -/* @brief Specifies number of descriptors available. */ -#define FSL_FEATURE_MPU_DESCRIPTOR_COUNT (12) -/* @brief Has process identifier support. */ -#define FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER (1) -/* @brief Has master 0. */ -#define FSL_FEATURE_MPU_HAS_MASTER0 (1) -/* @brief Has master 1. */ -#define FSL_FEATURE_MPU_HAS_MASTER1 (1) -/* @brief Has master 2. */ -#define FSL_FEATURE_MPU_HAS_MASTER2 (1) -/* @brief Has master 3. */ -#define FSL_FEATURE_MPU_HAS_MASTER3 (1) -/* @brief Has master 4. */ -#define FSL_FEATURE_MPU_HAS_MASTER4 (1) -/* @brief Has master 5. */ -#define FSL_FEATURE_MPU_HAS_MASTER5 (1) -/* @brief Has master 6. */ -#define FSL_FEATURE_MPU_HAS_MASTER6 (1) -/* @brief Has master 7. */ -#define FSL_FEATURE_MPU_HAS_MASTER7 (0) - /* interrupt module features */ /* @brief Lowest interrupt request number. */ @@ -1390,20 +1419,13 @@ #define FSL_FEATURE_PORT_PCR_MUX_WIDTH (3) /* @brief Has dedicated interrupt vector. */ #define FSL_FEATURE_PORT_HAS_INTERRUPT_VECTOR (1) +/* @brief Has multiple pin IRQ configuration (register GICLR and GICHR). */ +#define FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG (0) /* @brief Defines whether PCR[IRQC] bit-field has flag states. */ #define FSL_FEATURE_PORT_HAS_IRQC_FLAG (0) /* @brief Defines whether PCR[IRQC] bit-field has trigger states. */ #define FSL_FEATURE_PORT_HAS_IRQC_TRIGGER (0) -/* GPIO module features */ - -/* @brief Has fast (single cycle) access capability via a dedicated memory region. */ -#define FSL_FEATURE_GPIO_HAS_FAST_GPIO (0) -/* @brief Has port input disable register (PIDR). */ -#define FSL_FEATURE_GPIO_HAS_INPUT_DISABLE (0) -/* @brief Has dedicated interrupt vector. */ -#define FSL_FEATURE_GPIO_HAS_PORT_INTERRUPT_VECTOR (1) - /* RCM module features */ /* @brief Has Loss-of-Lock Reset support. */ @@ -1746,6 +1768,12 @@ #define FSL_FEATURE_SMC_HAS_PARAM (0) /* @brief Has SMC_VERID. */ #define FSL_FEATURE_SMC_HAS_VERID (0) +/* @brief Has stop abort flag (register bit PMCTRL[STOPA]). */ +#define FSL_FEATURE_SMC_HAS_PMCTRL_STOPA (1) +/* @brief Has tamper reset (register bit SRS[TAMPER]). */ +#define FSL_FEATURE_SMC_HAS_SRS_TAMPER (0) +/* @brief Has security violation reset (register bit SRS[SECVIO]). */ +#define FSL_FEATURE_SMC_HAS_SRS_SECVIO (0) /* DSPI module features */ @@ -1769,6 +1797,17 @@ /* @brief Has separate DMA RX and TX requests. */ #define FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1) +/* SYSMPU module features */ + +/* @brief Specifies number of descriptors available. */ +#define FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT (12) +/* @brief Has process identifier support. */ +#define FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER (1) +/* @brief Total number of MPU slave. */ +#define FSL_FEATURE_SYSMPU_SLAVE_COUNT (5) +/* @brief Total number of MPU master. */ +#define FSL_FEATURE_SYSMPU_MASTER_COUNT (7) + /* SysTick module features */ /* @brief Systick has external reference clock. */ @@ -1796,12 +1835,20 @@ #define FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER (1) /* @brief Has external trigger selection. */ #define FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION (1) -/* @brief Has TPM_COMBINE. */ +/* @brief Has TPM_COMBINE register. */ #define FSL_FEATURE_TPM_HAS_COMBINE (1) -/* @brief Has TPM_FILTER. */ +/* @brief Whether COMBINE register has effect. */ +#define FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(x) (1) +/* @brief Has TPM_POL. */ +#define FSL_FEATURE_TPM_HAS_POL (1) +/* @brief Has TPM_FILTER register. */ #define FSL_FEATURE_TPM_HAS_FILTER (1) -/* @brief Has TPM_QDCTRL. */ +/* @brief Whether FILTER register has effect. */ +#define FSL_FEATURE_TPM_FILTER_HAS_EFFECTn(x) (1) +/* @brief Has TPM_QDCTRL register. */ #define FSL_FEATURE_TPM_HAS_QDCTRL (1) +/* @brief Whether QDCTRL register has effect. */ +#define FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(x) (1) /* TSI module features */ @@ -1828,8 +1875,8 @@ #define FSL_FEATURE_UART_HAS_IR_SUPPORT (1) /* @brief 2 bits long stop bit is available. */ #define FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT (1) -/* @brief Maximal data width without parity bit. */ -#define FSL_FEATURE_UART_HAS_10BIT_DATA_SUPPORT (0) +/* @brief If 10-bit mode is supported. */ +#define FSL_FEATURE_UART_HAS_10BIT_DATA_SUPPORT (1) /* @brief Baud rate fine adjustment is available. */ #define FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT (1) /* @brief Baud rate oversampling is available (has bit fields C4[OSR], C5[BOTHEDGE], C5[RESYNCDIS] or BAUD[OSR], BAUD[BOTHEDGE], BAUD[RESYNCDIS] if the registers are 32-bit wide). */ @@ -1881,6 +1928,8 @@ /* USB module features */ +/* @brief KHCI module instance count */ +#define FSL_FEATURE_USB_KHCI_COUNT (1) /* @brief HOST mode enabled */ #define FSL_FEATURE_USB_KHCI_HOST_ENABLED (1) /* @brief OTG mode enabled */ @@ -1900,6 +1949,8 @@ /* USBHS module features */ +/* @brief EHCI module instance count */ +#define FSL_FEATURE_USBHS_EHCI_COUNT (1) /* @brief Number of endpoints supported */ #define FSL_FEATURE_USBHS_ENDPT_COUNT (8) @@ -1909,7 +1960,7 @@ #define FSL_FEATURE_VREF_HAS_CHOP_OSC (1) /* @brief Has second order curvature compensation (bit SC[ICOMPEN]) */ #define FSL_FEATURE_VREF_HAS_COMPENSATION (1) -/* @brief Describes the set of SC[MODE_LV] bitfield values */ +/* @brief If high/low buffer mode supported */ #define FSL_FEATURE_VREF_MODE_LV_TYPE (1) /* @brief Module has also low reference (registers VREFL/VREFH) */ #define FSL_FEATURE_VREF_HAS_LOW_REFERENCE (0) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct index c19ce975ff1..49d7a9ae4ac 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/MK66FN2M0xxx18.sct @@ -7,14 +7,13 @@ ** Compiler: Keil ARM C/C++ Compiler ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b160406 +** Build: b170214 ** ** Abstract: ** Linker file for the Keil ARM C/C++ Compiler ** -** Copyright (c) 2016 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -25,7 +24,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -40,8 +39,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** ################################################################### */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S index c7b44f7b247..3782b2f0a71 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_ARM_STD/startup_MK66F18.S @@ -4,12 +4,11 @@ ; * MK66F18 ; * @version: 3.0 ; * @date: 2015-3-25 -; * @build: b151210 +; * @build: b170112 ; * --------------------------------------------------------------------------------------- ; * -; * Copyright (c) 1997 - 2015 , Freescale Semiconductor, Inc. -; * All rights reserved. -; * +; * Copyright (c) 1997 - 2016, Freescale Semiconductor, Inc. +; * Copyright 2016 - 2017 NXP ; * Redistribution and use in source and binary forms, with or without modification, ; * are permitted provided that the following conditions are met: ; * @@ -20,7 +19,7 @@ ; * list of conditions and the following disclaimer in the documentation and/or ; * other materials provided with the distribution. ; * -; * o Neither the name of Freescale Semiconductor, Inc. nor the names of its +; * o Neither the name of the copyright holder nor the names of its ; * contributors may be used to endorse or promote products derived from this ; * software without specific prior written permission. ; * @@ -483,6 +482,8 @@ Reset_Handler PROC LDR R0, =0xE000ED08 LDR R1, =__Vectors STR R1, [R0] + LDR R2, [R1] + MSR MSP, R2 LDR R0, =SystemInit BLX R0 CPSIE i ; Unmask interrupts diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld index 4145ee2c690..0287cf769d4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/MK66FN2M0xxx18.ld @@ -6,14 +6,13 @@ ** Compiler: GNU C Compiler ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151217 +** Build: b170214 ** ** Abstract: ** Linker file for the GNU C Compiler ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -24,7 +23,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -39,8 +38,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** ################################################################### */ @@ -212,7 +211,6 @@ SECTIONS text_end = ORIGIN(m_text) + LENGTH(m_text); ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") - USB_RAM_GAP = DEFINED(__usb_ram_size__) ? __usb_ram_size__ : 0x800; /* Uninitialized data section */ .bss : { @@ -222,9 +220,6 @@ SECTIONS __bss_start__ = .; *(.bss) *(.bss*) - . = ALIGN(512); - USB_RAM_START = .; - . += USB_RAM_GAP; *(COMMON) . = ALIGN(4); __bss_end__ = .; @@ -248,17 +243,6 @@ SECTIONS . += STACK_SIZE; } > m_data_2 - m_usb_bdt USB_RAM_START (NOLOAD) : - { - *(m_usb_bdt) - USB_RAM_BDT_END = .; - } - - m_usb_global USB_RAM_BDT_END (NOLOAD) : - { - *(m_usb_global) - } - /* Initializes stack on the end of block */ __StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2); __StackLimit = __StackTop - STACK_SIZE; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S index 5a03e0326d8..ceb9bbf6c30 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_GCC_ARM/startup_MK66F18.S @@ -4,12 +4,11 @@ /* MK66F18 */ /* @version: 3.0 */ /* @date: 2015-3-25 */ -/* @build: b151210 */ +/* @build: b170112 */ /* ---------------------------------------------------------------------------------------*/ /* */ -/* Copyright (c) 1997 - 2015 , Freescale Semiconductor, Inc. */ -/* All rights reserved. */ -/* */ +/* Copyright (c) 1997 - 2016, Freescale Semiconductor, Inc. */ +/* Copyright 2016 - 2017 NXP */ /* Redistribution and use in source and binary forms, with or without modification, */ /* are permitted provided that the following conditions are met: */ /* */ @@ -20,7 +19,7 @@ /* list of conditions and the following disclaimer in the documentation and/or */ /* other materials provided with the distribution. */ /* */ -/* o Neither the name of Freescale Semiconductor, Inc. nor the names of its */ +/* o Neither the name of the copyright holder nor the names of its */ /* contributors may be used to endorse or promote products derived from this */ /* software without specific prior written permission. */ /* */ @@ -328,6 +327,8 @@ Reset_Handler: ldr r0, =VTOR ldr r1, =__isr_vector str r1, [r0] + ldr r2, [r1] + msr msp, r2 #ifndef __NO_SYSTEM_INIT ldr r0,=SystemInit blx r0 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf index fe0daadc6ae..6d7fb6135ea 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/MK66FN2M0xxx18.icf @@ -6,14 +6,13 @@ ** Compiler: IAR ANSI C/C++ Compiler for ARM ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151009 +** Build: b170214 ** ** Abstract: ** Linker file for the IAR ANSI C/C++ Compiler for ARM ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -24,7 +23,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -39,8 +38,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** ################################################################### */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S index 4a5928de9f2..47036fbd89f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/TOOLCHAIN_IAR/startup_MK66F18.S @@ -4,12 +4,11 @@ ; MK66F18 ; @version: 3.0 ; @date: 2015-3-25 -; @build: b151210 +; @build: b170112 ; --------------------------------------------------------------------------------------- ; -; Copyright (c) 1997 - 2015 , Freescale Semiconductor, Inc. -; All rights reserved. -; +; Copyright (c) 1997 - 2016, Freescale Semiconductor, Inc. +; Copyright 2016 - 2017 NXP ; Redistribution and use in source and binary forms, with or without modification, ; are permitted provided that the following conditions are met: ; @@ -20,7 +19,7 @@ ; list of conditions and the following disclaimer in the documentation and/or ; other materials provided with the distribution. ; -; o Neither the name of Freescale Semiconductor, Inc. nor the names of its +; o Neither the name of the copyright holder nor the names of its ; contributors may be used to endorse or promote products derived from this ; software without specific prior written permission. ; @@ -355,6 +354,8 @@ Reset_Handler LDR R0, =0xE000ED08 LDR R1, =__vector_table STR R1, [R0] + LDR R2, [R1] + MSR MSP, R2 LDR R0, =SystemInit BLX R0 CPSIE I ; Unmask interrupts diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h index f7a122fcdb6..9438c67fa13 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/fsl_device_registers.h @@ -1,7 +1,6 @@ /* - * Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc. - * All rights reserved. - * + * Copyright (c) 2014 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2017 NXP * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * @@ -12,7 +11,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -26,6 +25,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * */ #ifndef __FSL_DEVICE_REGISTERS_H__ @@ -36,7 +36,7 @@ * * The CPU macro should be declared in the project or makefile. */ -#if (defined(CPU_MK66FN2M0VLQ18) || defined(CPU_MK66FX1M0VLQ18) || defined(CPU_MK66FN2M0VMD18) || \ +#if (defined(CPU_MK66FN2M0VLQ18) || defined(CPU_MK66FN2M0VMD18) || defined(CPU_MK66FX1M0VLQ18) || \ defined(CPU_MK66FX1M0VMD18)) #define K66F18_SERIES diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c index 04996c713f3..a0a09bbc4d4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.c @@ -9,19 +9,19 @@ ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** IAR ANSI C/C++ Compiler for ARM +** MCUXpresso Compiler ** ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151216 +** Build: b170112 ** ** Abstract: ** Provides a system configuration function and a global variable that ** contains the system frequency. It configures the device and initializes ** the oscillator (PLL) that is part of the microcontroller device. ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright (c) 2016 Freescale Semiconductor, Inc. +** Copyright 2016 - 2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -32,7 +32,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -47,8 +47,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) @@ -213,7 +213,6 @@ void SystemCoreClockUpdate (void) { Divider *= 0x04U; } else if ((USBPHY->ANACTRL & USBPHY_ANACTRL_PFD_CLK_SEL_MASK) == USBPHY_ANACTRL_PFD_CLK_SEL(2)) { Divider *= 0x02U; - } else { } MCGOUTClock = (uint32_t)(480000000 / Divider); MCGOUTClock *= 18; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h index 3e8652e09a7..3bbd4bf70d6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/device/system_MK66F18.h @@ -9,19 +9,19 @@ ** Freescale C/C++ for Embedded ARM ** GNU C Compiler ** IAR ANSI C/C++ Compiler for ARM +** MCUXpresso Compiler ** ** Reference manual: K66P144M180SF5RMV2, Rev. 1, Mar 2015 ** Version: rev. 3.0, 2015-03-25 -** Build: b151216 +** Build: b170112 ** ** Abstract: ** Provides a system configuration function and a global variable that ** contains the system frequency. It configures the device and initializes ** the oscillator (PLL) that is part of the microcontroller device. ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. -** All rights reserved. -** +** Copyright (c) 2016 Freescale Semiconductor, Inc. +** Copyright 2016 - 2017 NXP ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** @@ -32,7 +32,7 @@ ** list of conditions and the following disclaimer in the documentation and/or ** other materials provided with the distribution. ** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its +** o Neither the name of the copyright holder nor the names of its ** contributors may be used to endorse or promote products derived from this ** software without specific prior written permission. ** @@ -47,8 +47,8 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2013-09-02) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c index 8f1aa77b2ea..0af6a4443e9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -46,8 +46,10 @@ static uint32_t ADC16_GetInstance(ADC_Type *base); /*! @brief Pointers to ADC16 bases for each instance. */ static ADC_Type *const s_adc16Bases[] = ADC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to ADC16 clocks for each instance. */ -const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS; +static const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -57,7 +59,7 @@ static uint32_t ADC16_GetInstance(ADC_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_ADC16_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_adc16Bases); instance++) { if (s_adc16Bases[instance] == base) { @@ -65,7 +67,7 @@ static uint32_t ADC16_GetInstance(ADC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_ADC16_COUNT); + assert(instance < ARRAY_SIZE(s_adc16Bases)); return instance; } @@ -76,8 +78,10 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config) uint32_t tmp32; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_adc16Clocks[ADC16_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* ADCx_CFG1. */ tmp32 = ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_MODE(config->resolution); @@ -126,8 +130,10 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config) void ADC16_Deinit(ADC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_adc16Clocks[ADC16_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void ADC16_GetDefaultConfig(adc16_config_t *config) @@ -149,7 +155,7 @@ void ADC16_GetDefaultConfig(adc16_config_t *config) status_t ADC16_DoAutoCalibration(ADC_Type *base) { bool bHWTrigger = false; - uint32_t tmp32; + volatile uint32_t tmp32; /* 'volatile' here is for the dummy read of ADCx_R[0] register. */ status_t status = kStatus_Success; /* The calibration would be failed when in hardwar mode. @@ -171,6 +177,7 @@ status_t ADC16_DoAutoCalibration(ADC_Type *base) break; } } + tmp32 = base->R[0]; /* Dummy read to clear COCO caused by calibration. */ /* Restore the hardware trigger setting if it was enabled before. */ if (bHWTrigger) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h index c6b5bc0d1ae..ea62c55fee6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_adc16.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -74,7 +73,7 @@ enum _adc16_status_flags * @brief Channel multiplexer mode for each channel. * * For some ADC16 channels, there are two pin selections in channel multiplexer. For example, ADC0_SE4a and ADC0_SE4b - * are the different channels but share the same channel number. + * are the different channels that share the same channel number. */ typedef enum _adc_channel_mux_mode { @@ -104,7 +103,7 @@ typedef enum _adc16_resolution kADC16_Resolution12or13Bit = 1U, /*!< Single End 12-bit or Differential Sample 13-bit. */ kADC16_Resolution10or11Bit = 2U, /*!< Single End 10-bit or Differential Sample 11-bit. */ - /* This group of enumeration is for public user. */ + /* This group of enumeration is for a public user. */ kADC16_ResolutionSE8Bit = kADC16_Resolution8or9Bit, /*!< Single End 8-bit. */ kADC16_ResolutionSE12Bit = kADC16_Resolution12or13Bit, /*!< Single End 12-bit. */ kADC16_ResolutionSE10Bit = kADC16_Resolution10or11Bit, /*!< Single End 10-bit. */ @@ -203,7 +202,7 @@ typedef enum _adc16_pga_gain #endif /* FSL_FEATURE_ADC16_HAS_PGA */ /*! - * @brief ADC16 converter configuration . + * @brief ADC16 converter configuration. */ typedef struct _adc16_config { @@ -219,7 +218,7 @@ typedef struct _adc16_config } adc16_config_t; /*! - * @brief ADC16 Hardware compare configuration. + * @brief ADC16 Hardware comparison configuration. */ typedef struct _adc16_hardware_compare_config { @@ -237,7 +236,7 @@ typedef struct _adc16_channel_config uint32_t channelNumber; /*!< Setting the conversion channel number. The available range is 0-31. See channel connection information for each chip in Reference Manual document. */ - bool enableInterruptOnConversionCompleted; /*!< Generate a interrupt request once the conversion is completed. */ + bool enableInterruptOnConversionCompleted; /*!< Generate an interrupt request once the conversion is completed. */ #if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE bool enableDifferentialConversion; /*!< Using Differential sample mode. */ #endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */ @@ -296,9 +295,9 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config); void ADC16_Deinit(ADC_Type *base); /*! - * @brief Gets an available pre-defined settings for converter's configuration. + * @brief Gets an available pre-defined settings for the converter's configuration. * - * This function initializes the converter configuration structure with an available settings. The default values are: + * This function initializes the converter configuration structure with available settings. The default values are as follows. * @code * config->referenceVoltageSource = kADC16_ReferenceVoltageSourceVref; * config->clockSource = kADC16_ClockSourceAsynchronousClock; @@ -310,7 +309,7 @@ void ADC16_Deinit(ADC_Type *base); * config->enableLowPower = false; * config->enableContinuousConversion = false; * @endcode - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void ADC16_GetDefaultConfig(adc16_config_t *config); @@ -318,15 +317,15 @@ void ADC16_GetDefaultConfig(adc16_config_t *config); /*! * @brief Automates the hardware calibration. * - * This auto calibration helps to adjust the plus/minus side gain automatically on the converter's working situation. + * This auto calibration helps to adjust the plus/minus side gain automatically. * Execute the calibration before using the converter. Note that the hardware trigger should be used - * during calibration. + * during the calibration. * * @param base ADC16 peripheral base address. * * @return Execution status. * @retval kStatus_Success Calibration is done successfully. - * @retval kStatus_Fail Calibration is failed. + * @retval kStatus_Fail Calibration has failed. */ status_t ADC16_DoAutoCalibration(ADC_Type *base); #endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */ @@ -350,16 +349,16 @@ static inline void ADC16_SetOffsetValue(ADC_Type *base, int16_t value) /* @} */ /*! - * @name Advanced Feature + * @name Advanced Features * @{ */ #if defined(FSL_FEATURE_ADC16_HAS_DMA) && FSL_FEATURE_ADC16_HAS_DMA /*! - * @brief Enables generating the DMA trigger when conversion is completed. + * @brief Enables generating the DMA trigger when the conversion is complete. * * @param base ADC16 peripheral base address. - * @param enable Switcher of DMA feature. "true" means to enable, "false" means not. + * @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled. */ static inline void ADC16_EnableDMA(ADC_Type *base, bool enable) { @@ -378,7 +377,7 @@ static inline void ADC16_EnableDMA(ADC_Type *base, bool enable) * @brief Enables the hardware trigger mode. * * @param base ADC16 peripheral base address. - * @param enable Switcher of hardware trigger feature. "true" means to enable, "false" means not. + * @param enable Switcher of the hardware trigger feature. "true" means enabled, "false" means not enabled. */ static inline void ADC16_EnableHardwareTrigger(ADC_Type *base, bool enable) { @@ -408,13 +407,12 @@ void ADC16_SetChannelMuxMode(ADC_Type *base, adc16_channel_mux_mode_t mode); /*! * @brief Configures the hardware compare mode. * - * The hardware compare mode provides a way to process the conversion result automatically by hardware. Only the result - * in - * compare range is available. To compare the range, see "adc16_hardware_compare_mode_t", or the reference - * manual document for more detailed information. + * The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the result + * in the compare range is available. To compare the range, see "adc16_hardware_compare_mode_t" or the appopriate reference + * manual for more information. * * @param base ADC16 peripheral base address. - * @param config Pointer to "adc16_hardware_compare_config_t" structure. Passing "NULL" is to disable the feature. + * @param config Pointer to the "adc16_hardware_compare_config_t" structure. Passing "NULL" disables the feature. */ void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare_config_t *config); @@ -422,21 +420,21 @@ void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare /*! * @brief Sets the hardware average mode. * - * Hardware average mode provides a way to process the conversion result automatically by hardware. The multiple - * conversion results are accumulated and averaged internally. This aids reading results. + * The hardware average mode provides a way to process the conversion result automatically by using hardware. The multiple + * conversion results are accumulated and averaged internally making them easier to read. * * @param base ADC16 peripheral base address. - * @param mode Setting hardware average mode. See "adc16_hardware_average_mode_t". + * @param mode Setting the hardware average mode. See "adc16_hardware_average_mode_t". */ void ADC16_SetHardwareAverage(ADC_Type *base, adc16_hardware_average_mode_t mode); #endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */ #if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA /*! - * @brief Configures the PGA for converter's front end. + * @brief Configures the PGA for the converter's front end. * * @param base ADC16 peripheral base address. - * @param config Pointer to "adc16_pga_config_t" structure. Passing "NULL" is to disable the feature. + * @param config Pointer to the "adc16_pga_config_t" structure. Passing "NULL" disables the feature. */ void ADC16_SetPGAConfig(ADC_Type *base, const adc16_pga_config_t *config); #endif /* FSL_FEATURE_ADC16_HAS_PGA */ @@ -468,26 +466,26 @@ void ADC16_ClearStatusFlags(ADC_Type *base, uint32_t mask); /*! * @brief Configures the conversion channel. * - * This operation triggers the conversion if in software trigger mode. When in hardware trigger mode, this API + * This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API * configures the channel while the external trigger source helps to trigger the conversion. * * Note that the "Channel Group" has a detailed description. - * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC can have more than one - * group of status and control register, one for each conversion. The channel group parameter indicates which group of - * registers are used channel group 0 is for Group A registers and channel group 1 is for Group B registers. The + * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one + * group of status and control registers, one for each conversion. The channel group parameter indicates which group of + * registers are used, for example, channel group 0 is for Group A registers and channel group 1 is for Group B registers. The * channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of - * the channel groups is actively controlling ADC conversions. Channel group 0 is used for both software and hardware - * trigger modes of operation. Channel groups 1 and greater indicate potentially multiple channel group registers for - * use only in hardware trigger mode. See the chip configuration information in the MCU reference manual about the - * number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used - * for software trigger operation and therefore writes to these channel groups do not initiate a new conversion. - * Updating channel group 0 while a different channel group is actively controlling a conversion is allowed and + * the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and hardware + * trigger modes. Channel group 1 and greater indicates multiple channel group registers for + * use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual for the + * number of SC1n registers (channel groups) specific to this device. Channel group 1 or greater are not used + * for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion. + * Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a * conversion aborts the current conversion. * * @param base ADC16 peripheral base address. * @param channelGroup Channel group index. - * @param config Pointer to "adc16_channel_config_t" structure for conversion channel. + * @param config Pointer to the "adc16_channel_config_t" structure for the conversion channel. */ void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c index bffbb4a3125..d75d97ff4f1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +13,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -28,7 +29,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* @@ -124,7 +124,6 @@ static uint32_t s_extPllFreq = 0U; /* External XTAL0 (OSC0) clock frequency. */ uint32_t g_xtal0Freq; - /* External XTAL32K clock frequency. */ uint32_t g_xtal32Freq; @@ -195,17 +194,36 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +/******************************************************************************* + * Code + ******************************************************************************/ + +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ -static void CLOCK_FllStableDelay(void); - -/******************************************************************************* - * Code - ******************************************************************************/ +void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (i--) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardness how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ static uint32_t CLOCK_GetMcgExtClkFreq(void) { @@ -342,19 +360,6 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - uint32_t CLOCK_GetOsc0ErClkUndivFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -419,6 +424,9 @@ uint32_t CLOCK_GetPllFllSelClkFreq(void) case 1U: /* PLL. */ freq = CLOCK_GetPll0Freq(); break; + case 2U: /* USB1 PFD */ + freq = CLOCK_GetExtPllFreq(); + break; case 3U: /* MCG IRC48M. */ freq = MCG_INTERNAL_IRC_48M; break; @@ -572,8 +580,31 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) } bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) +{ + /* Source and freq are not used for USB HS. */ + src = src; + freq = freq; + + SIM->SCGC3 |= SIM_SCGC3_USBHS_MASK; + + SIM->USBPHYCTL = ((SIM->USBPHYCTL & ~(SIM_USBPHYCTL_USB3VOUTTRG_MASK)) | SIM_USBPHYCTL_USB3VOUTTRG(6U) /* 3.310V */ + | SIM_USBPHYCTL_USBVREGSEL_MASK); /* VREG_IN1 */ + + USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Enable USB clock output from USB PHY PLL */ + + return true; +} + +void CLOCK_DisableUsbhs0Clock(void) +{ + USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Disable USB clock output from USB PHY PLL */ + SIM->SCGC3 &= ~SIM_SCGC3_USBHS_MASK; +} + +bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) { volatile uint32_t i; + uint32_t phyPllDiv = 0U; /* * In order to bring up the internal 480MHz USB PLL clock, should make sure: @@ -584,12 +615,28 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) assert(!(MCG->C2 & MCG_C2_IRCS_MASK)); assert(OSC0->CR & OSC_CR_ERCLKEN_MASK); + if (24000000U == freq) + { + phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U); + } + else if (16000000U == freq) + { + phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U); + } + else if (12000000U == freq) + { + phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U); + } + else + { + return false; + } + /* Source and freq are not used for USB HS. */ src = src; - freq = freq; + SIM->SCGC3 |= SIM_SCGC3_USBHSPHY_MASK; SIM->SOPT2 |= SIM_SOPT2_USBREGEN_MASK; - SIM->SCGC3 |= (SIM_SCGC3_USBHS_MASK | SIM_SCGC3_USBHSPHY_MASK); i = 500000U; while (i--) @@ -597,12 +644,66 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) __NOP(); } - SIM->USBPHYCTL = ((SIM->USBPHYCTL & ~(SIM_USBPHYCTL_USB3VOUTTRG_MASK)) | SIM_USBPHYCTL_USB3VOUTTRG(6U) /* 3.310V */ - | SIM_USBPHYCTL_USBVREGSEL_MASK); /* VREG_IN1 */ + USBPHY->TRIM_OVERRIDE_EN = 0x01U; /* Override the trim. */ + USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */ + USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_POWER_MASK; /* power up PLL */ + USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL_MASK) | phyPllDiv; + USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_BYPASS_MASK; /* Clear bypass bit */ + USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; /* Clear to 0U to run clocks */ + + /* Wait for lock. */ + while (!(USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK)) + { + } return true; } +void CLOCK_DisableUsbhs0PhyPllClock(void) +{ + USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ + USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK; /* Power down PLL */ + SIM->SOPT2 &= ~SIM_SOPT2_USBREGEN_MASK; + SIM->SCGC3 &= ~SIM_SCGC3_USBHSPHY_MASK; +} + +void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src) +{ + assert((frac <= 35U) && (frac >= 18U)); + uint32_t fracFreq = (480000U * 18U / frac) * 1000U; + + USBPHY->ANACTRL = (USBPHY->ANACTRL & ~(USBPHY_ANACTRL_PFD_FRAC_MASK | USBPHY_ANACTRL_PFD_CLK_SEL_MASK)) | + (USBPHY_ANACTRL_PFD_FRAC(frac) | USBPHY_ANACTRL_PFD_CLK_SEL(src)); + + USBPHY->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK; + while (!(USBPHY->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK)) + { + } + + if (kCLOCK_UsbPfdSrcExt == src) + { + s_extPllFreq = g_xtal0Freq; + } + else if (kCLOCK_UsbPfdSrcFracDivBy4 == src) + { + s_extPllFreq = fracFreq / 4U; + } + else if (kCLOCK_UsbPfdSrcFracDivBy2 == src) + { + s_extPllFreq = fracFreq / 2U; + } + else + { + s_extPllFreq = fracFreq; + } +} + +void CLOCK_DisableUsbhs0PfdClock(void) +{ + USBPHY->ANACTRL |= USBPHY_ANACTRL_PFD_CLKGATE_MASK; + s_extPllFreq = 0U; +} + uint32_t CLOCK_GetOutClkFreq(void) { uint32_t mcgoutclk; @@ -705,6 +806,12 @@ uint32_t CLOCK_GetPll0Freq(void) mcgpll0clk = CLOCK_GetPll0RefFreq(); + /* + * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. + * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock. + */ + assert(mcgpll0clk); + mcgpll0clk /= (FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C5_PRDIV0_VAL); mcgpll0clk *= (FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C6_VDIV0_VAL); @@ -746,16 +853,6 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ @@ -936,6 +1033,14 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config) } } +void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs) +{ + MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs); + while (pllcs != MCG_S2_PLLCST_VAL) + { + } +} + void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode) { /* Clear the previous flag, MCG_SC[LOCS0]. */ @@ -1279,7 +1384,7 @@ mcg_mode_t CLOCK_GetMode(void) return mode; } -status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; bool change_drs = false; @@ -1323,7 +1428,7 @@ status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) } /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */ - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DRST_DRS(drs)); + MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); /* Check MCG_S[CLKST] */ while (kMCG_ClkOutStatFll != MCG_S_CLKST_VAL) @@ -1372,6 +1477,17 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait and check status. */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1406,7 +1522,7 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void return kStatus_Success; } -status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { uint8_t mcg_c4; bool change_drs = false; @@ -1459,7 +1575,7 @@ status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) { } - MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DRST_DRS(drs)); + MCG->C4 = (mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)); /* Wait for FLL stable time. */ if (fllStableDelay) @@ -1514,6 +1630,17 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for Reference clock Status bit to clear */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1574,6 +1701,12 @@ status_t CLOCK_SetBlpeMode(void) status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { + /* If external PLL is used, then the config could be NULL. */ + if (kMCG_PllClkSelExtPll != pllcs) + { + assert(config); + } + /* This function is designed to change MCG to PBE mode from PEE/BLPE/FBE, but with this workflow, the source mode could be all modes except PEI/PBI. @@ -1601,13 +1734,15 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co CLOCK_EnablePll0(config); } + /* Change to PLL mode. */ + MCG->C6 |= MCG_C6_PLLS_MASK; + MCG->C11 = ((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs); while (pllcs != MCG_S2_PLLCST_VAL) { } - /* Change to PLL mode. */ - MCG->C6 |= MCG_C6_PLLS_MASK; + /* Wait for PLL mode changed. */ while (!(MCG->S & MCG_S_PLLST_MASK)) { } @@ -1682,9 +1817,9 @@ status_t CLOCK_InternalModeToFbiModeQuick(void) return kStatus_Success; } -status_t CLOCK_BootToFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)) +status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)) { - return CLOCK_SetFeiMode(drs, fllStableDelay); + return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay); } status_t CLOCK_BootToFeeMode( @@ -1721,6 +1856,17 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt))) @@ -1735,7 +1881,11 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { - assert(config); + /* If external PLL is used, then the config could be NULL. */ + if (kMCG_PllClkSelExtPll != pllcs) + { + assert(config); + } CLOCK_SetExternalRefClkConfig(oscsel); @@ -1793,7 +1943,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) if (!(MCG->S & MCG_S_IRCST_MASK)) { CLOCK_ExternalModeToFbeModeQuick(); - CLOCK_SetFeiMode(config->drs, (void (*)(void))0); + CLOCK_SetFeiMode(config->dmx32, config->drs, (void (*)(void))0); } CLOCK_SetExternalRefClkConfig(config->oscsel); @@ -1805,7 +1955,7 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */ { - CLOCK_SetFeiMode(config->drs, CLOCK_FllStableDelay); + CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); } } @@ -1821,13 +1971,13 @@ status_t CLOCK_SetMcgConfig(const mcg_config_t *config) switch (next_mode) { case kMCG_ModeFEI: - status = CLOCK_SetFeiMode(config->drs, CLOCK_FllStableDelay); + status = CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFEE: status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay); break; case kMCG_ModeFBI: - status = CLOCK_SetFbiMode(config->drs, (void (*)(void))0); + status = CLOCK_SetFbiMode(config->dmx32, config->drs, (void (*)(void))0); break; case kMCG_ModeFBE: status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, (void (*)(void))0); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h index d145692508d..3f343f5cc9f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_clock.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +13,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -31,45 +32,83 @@ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ +/*! @file */ + +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could contol the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief Clock driver version. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @name Driver version */ +/*@{*/ +/*! @brief CLOCK driver version 2.2.2. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ /*! @brief External XTAL0 (OSC0) clock frequency. * - * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal0Freq to set the value in to clock driver. For example, - * if XTAL0 is 8MHz, + * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, + * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Setup the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. + * CLOCK_InitOsc0(...); // Set up the OSC0 + * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. * @endcode * - * This is important for the multicore platforms, only one core needs to setup - * OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up the + * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq + * to get a valid clock frequency. */ extern uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * - * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal32Freq to set the value in to clock driver. + * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal32Freq to set the value in the clock driver. * - * This is important for the multicore platforms, only one core needs to setup - * the clock, all other cores need to call CLOCK_SetXtal32Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up + * the clock. All other cores need to call the CLOCK_SetXtal32Freq + * to get a valid clock frequency. */ extern uint32_t g_xtal32Freq; @@ -194,16 +233,10 @@ extern uint32_t g_xtal32Freq; kCLOCK_Sdramc0 \ } -/*! @brief Clock ip name array for MMCAU. */ -#define MMCAU_CLOCKS \ - { \ - kCLOCK_Mmcau0 \ - } - /*! @brief Clock ip name array for MPU. */ -#define MPU_CLOCKS \ - { \ - kCLOCK_Mpu0 \ +#define SYSMPU_CLOCKS \ + { \ + kCLOCK_Sysmpu0 \ } /*! @brief Clock ip name array for VREF. */ @@ -242,12 +275,6 @@ extern uint32_t g_xtal32Freq; kCLOCK_Crc0 \ } -/*! @brief Clock ip name array for LMEM. */ -#define LMEM_CLOCKS \ - { \ - kCLOCK_Lmem0 \ - } - /*! @brief Clock ip name array for I2C. */ #define I2C_CLOCKS \ { \ @@ -267,9 +294,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for CMP. */ -#define CMP_CLOCKS \ - { \ - kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2 \ +#define CMP_CLOCKS \ + { \ + kCLOCK_Cmp0, kCLOCK_Cmp1, kCLOCK_Cmp2, kCLOCK_Cmp3 \ } /*! @@ -334,9 +361,26 @@ typedef enum _clock_usb_src kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */ kCLOCK_UsbSrcUsbPfd = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(2U), /*!< Use USBPFDCLK. */ kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */ - kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U) /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U), /*!< Use USB_CLKIN. */ + kCLOCK_UsbSrcUnused = 0xFFFFFFFFU, /*!< Used when the function does not + care the clock source. */ } clock_usb_src_t; +/*! @brief Source of the USB HS PHY. */ +typedef enum _clock_usb_phy_src +{ + kCLOCK_UsbPhySrcExt = 0U, /*!< Use external crystal. */ +} clock_usb_phy_src_t; + +/*! @brief Source of the USB HS PFD clock (USB1PFDCLK) */ +typedef enum _clock_usb_pfd_src +{ + kCLOCK_UsbPfdSrcExt = 0U, /*!< Use external crystal. */ + kCLOCK_UsbPfdSrcFracDivBy4 = 1U, /*!< Use PFD_FRAC output divided by 4. */ + kCLOCK_UsbPfdSrcFracDivBy2 = 2U, /*!< Use PFD_FRAC output divided by 2. */ + kCLOCK_UsbPfdSrcFrac = 3U, /*!< Use PFD_FRAC output. */ +} clock_usb_pfd_src_t; + /*------------------------------------------------------------------------------ clock_gate_t definition: @@ -402,6 +446,7 @@ typedef enum _clock_ip_name kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Cmp2 = CLK_GATE_DEFINE(0x1034U, 19U), + kCLOCK_Cmp3 = CLK_GATE_DEFINE(0x1034U, 19U), kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U), kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U), @@ -430,7 +475,7 @@ typedef enum _clock_ip_name kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Mpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U), } clock_ip_name_t; @@ -447,7 +492,7 @@ typedef struct _sim_clock_config /*! @brief OSC work mode. */ typedef enum _osc_mode { - kOSC_ModeExt = 0U, /*!< Use external clock. */ + kOSC_ModeExt = 0U, /*!< Use an external clock. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) kOSC_ModeOscLowPower = MCG_C2_EREFS_MASK, /*!< Oscillator low power. */ #else @@ -498,8 +543,8 @@ typedef struct _oscer_config * @brief OSC Initialization Configuration Structure * * Defines the configuration data structure to initialize the OSC. - * When porting to a new board, please set the following members - * according to board setting: + * When porting to a new board, set the following members + * according to the board setting: * 1. freq: The external frequency. * 2. workMode: The OSC module mode. */ @@ -575,7 +620,7 @@ typedef enum _mcg_oscsel typedef enum _mcg_pll_clk_select { kMCG_PllClkSelPll0, /*!< PLL0 output clock is selected */ - kMCG_PllClkSelExtPll /* External PLL clock is selected */ + kMCG_PllClkSelExtPll /* The external PLL clock is selected */ } mcg_pll_clk_select_t; /*! @brief MCG clock monitor mode. */ @@ -596,8 +641,8 @@ enum _mcg_status kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Could not change clock source because - it is used currently. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + it is in use. */ }; /*! @brief MCG status flags. */ @@ -621,11 +666,11 @@ enum _mcg_irclk_enable_mode /*! @brief MCG PLL clock enable mode definition. */ enum _mcg_pll_enable_mode { - kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable indepencent of - MCG clock mode. Generally, PLL + kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable independent of the + MCG clock mode. Generally, the PLL is disabled in FLL modes - (FEI/FBI/FEE/FBE), set PLL clock - enable independent will enable + (FEI/FBI/FEE/FBE). Setting the PLL clock + enable independent, enables the PLL in the FLL modes. */ kMCG_PllEnableInStop = MCG_C5_PLLSTEN0_MASK /*!< MCGPLLCLK enable in STOP mode. */ }; @@ -652,16 +697,16 @@ typedef struct _mcg_pll_config uint8_t vdiv; /*!< VCO divider VDIV. */ } mcg_pll_config_t; -/*! @brief MCG configure structure for mode change. +/*! @brief MCG mode change configuration structure * - * When porting to a new board, please set the following members - * according to board setting: - * 1. frdiv: If FLL uses the external reference clock, please set this - * value to make sure external reference clock divided by frdiv is - * in the range 31.25kHz to 39.0625kHz. + * When porting to a new board, set the following members + * according to the board setting: + * 1. frdiv: If the FLL uses the external reference clock, set this + * value to ensure that the external reference clock divided by frdiv is + * in the 31.25 kHz to 39.0625 kHz range. * 2. The PLL reference clock divider PRDIV: PLL reference clock frequency after - * PRDIV should be in the range of FSL_FEATURE_MCG_PLL_REF_MIN to - * FSL_FEATURE_MCG_PLL_REF_MAX. + * PRDIV should be in the FSL_FEATURE_MCG_PLL_REF_MIN to + * FSL_FEATURE_MCG_PLL_REF_MAX range. */ typedef struct _mcg_config { @@ -693,26 +738,6 @@ typedef struct _mcg_config extern "C" { #endif /* __cplusplus */ -/*! - * @brief Set the XTAL0 frequency based on board setting. - * - * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal0Freq(uint32_t freq) -{ - g_xtal0Freq = freq; -} - -/*! - * @brief Set the XTAL32/RTC_CLKIN frequency based on board setting. - * - * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. - */ -static inline void CLOCK_SetXtal32Freq(uint32_t freq) -{ - g_xtal32Freq = freq; -} - /*! * @brief Enable the clock for specific IP. * @@ -839,8 +864,12 @@ static inline void CLOCK_SetRtcClkOutClock(uint32_t src) /*! @brief Enable USB HS clock. * - * @param src USB HS clock source. - * @param freq The frequency specified by src. + * This function only enables the access to USB HS prepheral, upper layer + * should first call the @ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY + * clock to use USB HS. + * + * @param src USB HS does not care about the clock source, here must be @ref kCLOCK_UsbSrcUnused. + * @param freq USB HS does not care about the clock source, so this parameter is ignored. * @retval true The clock is set successfully. * @retval false The clock source is invalid to get proper USB HS clock. */ @@ -848,13 +877,49 @@ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq); /*! @brief Disable USB HS clock. * - * Disable USB HS clock. + * Disable USB HS clock, this function should not be called after + * @ref CLOCK_DisableUsbhs0PhyPllClock. */ -static inline void CLOCK_DisableUsbhs0Clock(void) -{ - SIM->SOPT2 &= ~SIM_SOPT2_USBREGEN_MASK; - SIM->SCGC3 &= ~(SIM_SCGC3_USBHS_MASK | SIM_SCGC3_USBHSPHY_MASK); -} +void CLOCK_DisableUsbhs0Clock(void); + +/*! @brief Enable USB HS PHY PLL clock. + * + * This function enables the internal 480MHz USB PHY PLL clock. + * + * @param src USB HS PHY PLL clock source. + * @param freq The frequency specified by src. + * @retval true The clock is set successfully. + * @retval false The clock source is invalid to get proper USB HS clock. + */ +bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq); + +/*! @brief Disable USB HS PHY PLL clock. + * + * This function disables USB HS PHY PLL clock. + */ +void CLOCK_DisableUsbhs0PhyPllClock(void); + +/*! @brief Enable USB HS PFD clock. + * + * This function enables USB HS PFD clock. It should be called after function + * @ref CLOCK_EnableUsbhs0PhyPllClock. + * The PFD output clock is selected by the parameter @p src. When the @p src is + * @ref kCLOCK_UsbPfdSrcExt, then the PFD outout is from external crystal + * directly, in this case, the @p frac is not used. In other cases, the PFD_FRAC + * output clock frequency is 480MHz*18/frac, the PFD output frequency is based + * on the PFD_FRAC output. + * + * @param frac The value set to PFD_FRAC, it must be in the range of 18 to 35. + * @param src Source of the USB HS PFD clock (USB1PFDCLK). + */ +void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src); + +/*! @brief Disable USB HS PFD clock. + * + * This function disables USB HS PFD clock. It should be called before function + * @ref CLOCK_DisableUsbhs0PhyPllClock. + */ +void CLOCK_DisableUsbhs0PfdClock(void); /*! @brief Enable USB FS clock. * @@ -997,9 +1062,9 @@ static inline void CLOCK_SetSimSafeDivs(void) /*@{*/ /*! - * @brief Get the MCG output clock(MCGOUTCLK) frequency. + * @brief Gets the MCG output clock (MCGOUTCLK) frequency. * - * This function gets the MCG output clock frequency (Hz) based on current MCG + * This function gets the MCG output clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGOUTCLK. @@ -1007,40 +1072,40 @@ static inline void CLOCK_SetSimSafeDivs(void) uint32_t CLOCK_GetOutClkFreq(void); /*! - * @brief Get the MCG FLL clock(MCGFLLCLK) frequency. + * @brief Gets the MCG FLL clock (MCGFLLCLK) frequency. * - * This function gets the MCG FLL clock frequency (Hz) based on current MCG - * register value. The FLL is only enabled in FEI/FBI/FEE/FBE mode, in other - * modes, FLL is disabled in low power state. + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. * * @return The frequency of MCGFLLCLK. */ uint32_t CLOCK_GetFllFreq(void); /*! - * @brief Get the MCG internal reference clock(MCGIRCLK) frequency. + * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency. * - * This function gets the MCG internal reference clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGIRCLK. */ uint32_t CLOCK_GetInternalRefClkFreq(void); /*! - * @brief Get the MCG fixed frequency clock(MCGFFCLK) frequency. + * @brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. * - * This function gets the MCG fixed frequency clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGFFCLK. */ uint32_t CLOCK_GetFixedFreqClkFreq(void); /*! - * @brief Get the MCG PLL0 clock(MCGPLL0CLK) frequency. + * @brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. * - * This function gets the MCG PLL0 clock frequency (Hz) based on current MCG + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGPLL0CLK. @@ -1048,21 +1113,21 @@ uint32_t CLOCK_GetFixedFreqClkFreq(void); uint32_t CLOCK_GetPll0Freq(void); /*! - * @brief Get the MCG external PLL frequency. + * @brief Gets the MCG external PLL frequency. * - * This function gets the MCG external PLL frequency (Hz). + * This function gets the MCG external PLL frequency in Hz. * - * @return The frequency of MCG external PLL. + * @return The frequency of the MCG external PLL. */ uint32_t CLOCK_GetExtPllFreq(void); /*! - * @brief Set the MCG external PLL frequency. + * @brief Sets the MCG external PLL frequency. * - * This function sets the MCG external PLL frequency (Hz), the MCG external PLL - * frequency is passed in to MCG driver through this function. Please call this - * function after the external PLL frequency is changed, otherwise the APIs for - * get frequency may returns wrong value. + * This function sets the MCG external PLL frequency in Hz. The MCG external PLL + * frequency is passed to the MCG driver using this function. Call this + * function after the external PLL frequency is changed. Otherwise, the APIs, which are used to get + * the frequency, may return an incorrect value. * * @param The frequency of MCG external PLL. */ @@ -1074,12 +1139,12 @@ void CLOCK_SetExtPllFreq(uint32_t freq); /*@{*/ /*! - * @brief Enable or disable MCG low power. + * @brief Enables or disables the MCG low power. * - * Enable MCG low power will disable the PLL and FLL in bypass modes. That is, - * in FBE and PBE modes, enable low power will set MCG to BLPE mode, in FBI and - * PBI mode, enable low power will set MCG to BLPI mode. - * When disable MCG low power, the PLL or FLL will be enabled based on MCG setting. + * Enabling the MCG low power disables the PLL and FLL in bypass modes. In other words, + * in FBE and PBE modes, enabling low power sets the MCG to BLPE mode. In FBI and + * PBI modes, enabling low power sets the MCG to BLPI mode. + * When disabling the MCG low power, the PLL or FLL are enabled based on MCG settings. * * @param enable True to enable MCG low power, false to disable MCG low power. */ @@ -1096,42 +1161,56 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } /*! - * @brief Configure the Internal Reference clock (MCGIRCLK) + * @brief Configures the Internal Reference clock (MCGIRCLK). * - * This function setups the \c MCGIRCLK base on parameters. It selects the IRC - * source, if fast IRC is used, this function also sets the fast IRC divider. - * This function also sets whether enable \c MCGIRCLK in stop mode. - * Calling this function in FBI/PBI/BLPI modes may change the system clock, so - * it is not allowed to use this in these modes. + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. * * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed MCGIRCLK is used as system clock, should not configure MCGIRCLK. + * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, + * the confuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); /*! - * @brief Select the MCG external reference clock. + * @brief Selects the MCG external reference clock. * - * Select the MCG external reference clock source, it changes the MCG_C7[OSCSEL] - * and wait for the clock source stable. Should not change external reference - * clock in FEE/FBE/BLPE/PBE/PEE mdes, so don't call this function in these modes. + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. - * @retval kStatus_MCG_SourceUsed External reference clock is used, should not change. + * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the confuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); +/*! + * @brief Set the FLL external reference clock divider value. + * + * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV]. + * + * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV]. + */ +static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) +{ + MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); +} + /*! * @brief Enables the PLL0 in FLL mode. * - * This function setups the PLL0 in FLL mode, make sure the PLL reference - * clock is enabled before calling this function. This function reconfigures - * the PLL0, make sure the PLL0 is not used as a clock source while calling - * this function. The function CLOCK_CalcPllDiv can help to get the proper PLL + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL * divider values. * * @param config Pointer to the configuration structure. @@ -1141,7 +1220,7 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config); /*! * @brief Disables the PLL0 in FLL mode. * - * This function disables the PLL0 in FLL mode, it should be used together with + * This function disables the PLL0 in FLL mode. It should be used together with the * @ref CLOCK_EnablePll0. */ static inline void CLOCK_DisablePll0(void) @@ -1150,70 +1229,80 @@ static inline void CLOCK_DisablePll0(void) } /*! - * @brief Calculates the PLL divider setting for desired output frequency. + * @brief Calculates the PLL divider setting for a desired output frequency. * - * This function calculates the proper reference clock divider (\c PRDIV) and - * VCO divider (\c VDIV) to generate desired PLL output frequency. It returns the - * closest frequency PLL could generate, the corresponding \c PRDIV/VDIV are - * returned from parameters. If desired frequency is not valid, this function + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function * returns 0. * * @param refFreq PLL reference clock frequency. * @param desireFreq Desired PLL output frequency. * @param prdiv PRDIV value to generate desired PLL frequency. * @param vdiv VDIV value to generate desired PLL frequency. - * @return Closest frequency PLL could generate. + * @return Closest frequency match that the PLL was able generate. */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); +/*! + * @brief Set the PLL selection. + * + * This function sets the PLL selection between PLL0/PLL1/EXTPLL, and waits for + * change finished. + * + * @param pllcs The PLL to select. + */ +void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs); + /*@}*/ /*! @name MCG clock lock monitor functions. */ /*@{*/ /*! - * @brief Set the OSC0 clock monitor mode. + * @brief Sets the OSC0 clock monitor mode. * - * Set the OSC0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the OSC0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the RTC OSC clock monitor mode. + * @brief Sets the RTC OSC clock monitor mode. * - * Set the RTC OSC clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the RTC OSC clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the PLL0 clock monitor mode. + * @brief Sets the PLL0 clock monitor mode. * - * Set the PLL0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the PLL0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the external PLL clock monitor mode. + * @brief Sets the external PLL clock monitor mode. * - * Set the external PLL clock monitor mode, see @ref mcg_monitor_mode_t + * This function ets the external PLL clock monitor mode. See @ref mcg_monitor_mode_t * for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Get the MCG status flags. + * @brief Gets the MCG status flags. * - * This function gets the MCG clock status flags, all the status flags are + * This function gets the MCG clock status flags. All status flags are * returned as a logical OR of the enumeration @ref _mcg_status_flags_t. To - * check specific flags, compare the return value with the flags. + * check a specific flag, compare the return value with the flag. * * Example: * @code @@ -1239,8 +1328,8 @@ uint32_t CLOCK_GetStatusFlags(void); /*! * @brief Clears the MCG status flags. * - * This function clears the MCG clock lock lost status. The parameter is logical - * OR value of the flags to clear, see @ref _mcg_status_flags_t. + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See @ref _mcg_status_flags_t. * * Example: * @code @@ -1265,8 +1354,8 @@ void CLOCK_ClearStatusFlags(uint32_t mask); * @brief Configures the OSC external reference clock (OSCERCLK). * * This function configures the OSC external reference clock (OSCERCLK). - * For example, to enable the OSCERCLK in normal mode and stop mode, and also set - * the output divider to 1, as follows: + * This is an example to enable the OSCERCLK in normal and stop modes and also set + * the output divider to 1: * @code oscer_config_t config = @@ -1320,45 +1409,71 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) } /*! - * @brief Initialize OSC0. + * @brief Initializes the OSC0. * - * This function initializes OSC0 according to board configuration. + * This function initializes the OSC0 according to the board configuration. * * @param config Pointer to the OSC0 configuration structure. */ void CLOCK_InitOsc0(osc_config_t const *config); /*! - * @brief Deinitialize OSC0. + * @brief Deinitializes the OSC0. * - * This function deinitializes OSC0. + * This function deinitializes the OSC0. */ void CLOCK_DeinitOsc0(void); /* @} */ +/*! + * @name External clock frequency + * @{ + */ + +/*! + * @brief Sets the XTAL0 frequency based on board settings. + * + * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal0Freq(uint32_t freq) +{ + g_xtal0Freq = freq; +} + +/*! + * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings. + * + * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. + */ +static inline void CLOCK_SetXtal32Freq(uint32_t freq) +{ + g_xtal32Freq = freq; +} +/* @} */ + /*! * @name MCG auto-trim machine. * @{ */ /*! - * @brief Auto trim the internal reference clock. + * @brief Auto trims the internal reference clock. * - * This function trims the internal reference clock using external clock. If + * This function trims the internal reference clock by using the external clock. If * successful, it returns the kStatus_Success and the frequency after * trimming is received in the parameter @p actualFreq. If an error occurs, * the error code is returned. * - * @param extFreq External clock frequency, should be bus clock. - * @param desireFreq Frequency want to trim to. - * @param actualFreq Actual frequency after trim. + * @param extFreq External clock frequency, which should be a bus clock. + * @param desireFreq Frequency to trim to. + * @param actualFreq Actual frequency after trimming. * @param atms Trim fast or slow internal reference clock. * @retval kStatus_Success ATM success. - * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for ATM. + * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. * @retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. - * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as bus clock source. - * @retval kStatus_MCG_AtmHardwareFail Hardware fails during trim. + * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * @retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms); /* @} */ @@ -1369,260 +1484,265 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ /*! * @brief Gets the current MCG mode. * - * This function checks the MCG registers and determine current MCG mode. + * This function checks the MCG registers and determines the current MCG mode. * - * @return Current MCG mode or error code, see @ref mcg_mode_t. + * @return Current MCG mode or error code; See @ref mcg_mode_t. */ mcg_mode_t CLOCK_GetMode(void); /*! - * @brief Set MCG to FEI mode. + * @brief Sets the MCG to FEI mode. * - * This function sets MCG to FEI mode. If could not set to FEI mode directly - * from current mode, this function returns error. @ref kMCG_Dmx32Default is used in this - * mode because using kMCG_Dmx32Fine with internal reference clock source - * might damage hardware. + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. * + * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to a frequency above 32768 Hz. */ -status_t CLOCK_SetFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode. + * @brief Sets the MCG to FEE mode. * - * This function sets MCG to FEE mode. If could not set to FEE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBI mode. + * @brief Sets the MCG to FBI mode. * - * This function sets MCG to FBI mode. If could not set to FBI mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. * + * @param dmx32 DMX32 in FBI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBI mode, this parameter could be NULL. Pass in - * NULL does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. */ -status_t CLOCK_SetFbiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBE mode. + * @brief Sets the MCG to FBE mode. * - * This function sets MCG to FBE mode. If could not set to FBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FBE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBE mode, this parameter could be NULL. Pass in NULL - * does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode. + * @brief Sets the MCG to BLPI mode. * - * This function sets MCG to BLPI mode. If could not set to BLPI mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpiMode(void); /*! - * @brief Set MCG to BLPE mode. + * @brief Sets the MCG to BLPE mode. * - * This function sets MCG to BLPE mode. If could not set to BLPE mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpeMode(void); /*! - * @brief Set MCG to PBE mode. + * @brief Sets the MCG to PBE mode. * - * This function sets MCG to PBE mode. If could not set to PBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. * * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * * @note - * 1. The parameter \c pllcs selects the PLL, for some platforms, there is - * only one PLL, the parameter pllcs is kept for interface compatible. - * 2. The parameter \c config is the PLL configuration structure, on some - * platforms, could choose the external PLL directly. This means that the - * configuration structure is not necessary, pass in NULL for this case. + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to PEE mode. + * @brief Sets the MCG to PEE mode. * - * This function sets MCG to PEE mode. + * This function sets the MCG to PEE mode. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * - * @note This function only change CLKS to use PLL/FLL output. If the - * PRDIV/VDIV are different from PBE mode, please setup these - * settings in PBE mode and wait for stable then switch to PEE mode. + * @note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. */ status_t CLOCK_SetPeeMode(void); /*! - * @brief Switch MCG to FBE mode quickly from external mode. + * @brief Switches the MCG to FBE mode from the external mode. * - * This function changes MCG from external modes (PEE/PBE/BLPE/FEE) to FBE mode quickly. - * It only changes to use external clock as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEE mode to FEI mode: + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock souce and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: * * @code * CLOCK_ExternalModeToFbeModeQuick(); * CLOCK_SetFeiMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not external modes, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. */ status_t CLOCK_ExternalModeToFbeModeQuick(void); /*! - * @brief Switch MCG to FBI mode quickly from internal modes. + * @brief Switches the MCG to FBI mode from internal modes. * - * This function changes MCG from internal modes (PEI/PBI/BLPI/FEI) to FBI mode quickly. - * It only changes to use MCGIRCLK as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEI mode to FEE mode: + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: * * @code * CLOCK_InternalModeToFbiModeQuick(); * CLOCK_SetFeeMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not internal mode, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. */ status_t CLOCK_InternalModeToFbiModeQuick(void); /*! - * @brief Set MCG to FEI mode during system boot up. + * @brief Sets the MCG to FEI mode during system boot up. * - * This function sets MCG to FEI mode from reset mode, it could be used to - * set up MCG during system boot up. @ref kMCG_Dmx32Default is used in this - * mode because using kMCG_Dmx32Fine with internal reference clock source - * might damage hardware. + * This function sets the MCG to FEI mode from the reset mode. It can also be used to + * set up MCG during system boot up. * + * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. + * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed + * to frequency above 32768 Hz. */ -status_t CLOCK_BootToFeiMode(mcg_drs_t drs, void (*fllStableDelay)(void)); +status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode during system bootup. + * @brief Sets the MCG to FEE mode during system bootup. * - * This function sets MCG to FEE mode from reset mode, it could be used to - * set up MCG during system boot up. + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, OSCSEL. * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode during system boot up. + * @brief Sets the MCG to BLPI mode during system boot up. * - * This function sets MCG to BLPI mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during sytem boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. * @param ircEnableMode The MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * * @retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Set MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during sytem boot up. * - * This function sets MCG to BLPE mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during sytem boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel); /*! - * @brief Set MCG to PEE mode during system boot up. + * @brief Sets the MCG to PEE mode during system boot up. * - * This function sets MCG to PEE mode from reset mode, it could be used to - * setup MCG during system boot up. + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to some target mode. + * @brief Sets the MCG to a target mode. * - * This function sets MCG to some target mode defined by the configure - * structure, if cannot switch to target mode directly, this function will - * choose the proper path. + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. * * @param config Pointer to the target MCG mode configuration structure. - * @return Return kStatus_Success if switch successfully, otherwise return error code #_mcg_status. + * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. * - * @note If external clock is used in the target mode, please make sure it is - * enabled, for example, if the OSC0 is used, please setup OSC0 correctly before - * this funciton. + * @note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c index 09885e74211..6a5f15a75b1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t CMP_GetInstance(CMP_Type *base); ******************************************************************************/ /*! @brief Pointers to CMP bases for each instance. */ static CMP_Type *const s_cmpBases[] = CMP_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to CMP clocks for each instance. */ -const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS; +static const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t CMP_GetInstance(CMP_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_CMP_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_cmpBases); instance++) { if (s_cmpBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t CMP_GetInstance(CMP_Type *base) } } - assert(instance < FSL_FEATURE_SOC_CMP_COUNT); + assert(instance < ARRAY_SIZE(s_cmpBases)); return instance; } @@ -75,8 +77,10 @@ void CMP_Init(CMP_Type *base, const cmp_config_t *config) uint8_t tmp8; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_cmpClocks[CMP_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ CMP_Enable(base, false); /* Disable the CMP module during configuring. */ @@ -123,8 +127,10 @@ void CMP_Deinit(CMP_Type *base) /* Disable the CMP module. */ CMP_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_cmpClocks[CMP_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void CMP_GetDefaultConfig(cmp_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h index 53d84a0f2d2..5d16bf08de4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmp.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -64,8 +63,8 @@ enum _cmp_interrupt_enable */ enum _cmp_status_flags { - kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on compare output has occurred. */ - kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on compare output has occurred. */ + kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on the comparison output has occurred. */ + kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on the comparison output has occurred. */ kCMP_OutputAssertEventFlag = CMP_SCR_COUT_MASK, /*!< Return the current value of the analog comparator output. */ }; @@ -85,20 +84,20 @@ typedef enum _cmp_hysteresis_mode */ typedef enum _cmp_reference_voltage_source { - kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as resistor ladder network supply reference Vin. */ - kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as resistor ladder network supply reference Vin. */ + kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as a resistor ladder network supply reference Vin. */ + kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as a resistor ladder network supply reference Vin. */ } cmp_reference_voltage_source_t; /*! - * @brief Configure the comparator. + * @brief Configures the comparator. */ typedef struct _cmp_config { bool enableCmp; /*!< Enable the CMP module. */ cmp_hysteresis_mode_t hysteresisMode; /*!< CMP Hysteresis mode. */ - bool enableHighSpeed; /*!< Enable High Speed (HS) comparison mode. */ - bool enableInvertOutput; /*!< Enable inverted comparator output. */ - bool useUnfilteredOutput; /*!< Set compare output(COUT) to equal COUTA(true) or COUT(false). */ + bool enableHighSpeed; /*!< Enable High-speed (HS) comparison mode. */ + bool enableInvertOutput; /*!< Enable the inverted comparator output. */ + bool useUnfilteredOutput; /*!< Set the compare output(COUT) to equal COUTA(true) or COUT(false). */ bool enablePinOut; /*!< The comparator output is available on the associated pin. */ #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE bool enableTriggerMode; /*!< Enable the trigger mode. */ @@ -106,24 +105,24 @@ typedef struct _cmp_config } cmp_config_t; /*! - * @brief Configure the filter. + * @brief Configures the filter. */ typedef struct _cmp_filter_config { #if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT - bool enableSample; /*!< Using external SAMPLE as sampling clock input, or using divided bus clock. */ + bool enableSample; /*!< Using the external SAMPLE as a sampling clock input or using a divided bus clock. */ #endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */ - uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7, 0 would cause the filter disabled.*/ - uint8_t filterPeriod; /*!< Filter Sample Period. The divider to bus clock. Available range is 0-255. */ + uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7; 0 disables the filter.*/ + uint8_t filterPeriod; /*!< Filter Sample Period. The divider to the bus clock. Available range is 0-255. */ } cmp_filter_config_t; /*! - * @brief Configure the internal DAC. + * @brief Configures the internal DAC. */ typedef struct _cmp_dac_config { cmp_reference_voltage_source_t referenceVoltageSource; /*!< Supply voltage reference source. */ - uint8_t DACValue; /*!< Value for DAC Output Voltage. Available range is 0-63.*/ + uint8_t DACValue; /*!< Value for the DAC Output Voltage. Available range is 0-63.*/ } cmp_dac_config_t; #if defined(__cplusplus) @@ -142,28 +141,28 @@ extern "C" { /*! * @brief Initializes the CMP. * - * This function initializes the CMP module. The operations included are: + * This function initializes the CMP module. The operations included are as follows. * - Enabling the clock for CMP module. * - Configuring the comparator. * - Enabling the CMP module. - * Note: For some devices, multiple CMP instance share the same clock gate. In this case, to enable the clock for - * any instance enables all the CMPs. Check the chip reference manual for the clock assignment of the CMP. + * Note that for some devices, multiple CMP instances share the same clock gate. In this case, to enable the clock for + * any instance enables all CMPs. See the appropriate MCU reference manual for the clock assignment of the CMP. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void CMP_Init(CMP_Type *base, const cmp_config_t *config); /*! * @brief De-initializes the CMP module. * - * This function de-initializes the CMP module. The operations included are: + * This function de-initializes the CMP module. The operations included are as follows. * - Disabling the CMP module. * - Disabling the clock for CMP module. * * This function disables the clock for the CMP. - * Note: For some devices, multiple CMP instance shares the same clock gate. In this case, before disabling the - * clock for the CMP, ensure that all the CMP instances are not used. + * Note that for some devices, multiple CMP instances share the same clock gate. In this case, before disabling the + * clock for the CMP, ensure that all the CMP instances are not used. * * @param base CMP peripheral base address. */ @@ -173,7 +172,7 @@ void CMP_Deinit(CMP_Type *base); * @brief Enables/disables the CMP module. * * @param base CMP peripheral base address. - * @param enable Enable the module or not. + * @param enable Enables or disables the module. */ static inline void CMP_Enable(CMP_Type *base, bool enable) { @@ -190,7 +189,7 @@ static inline void CMP_Enable(CMP_Type *base, bool enable) /*! * @brief Initializes the CMP user configuration structure. * -* This function initializes the user configure structure to these default values: +* This function initializes the user configuration structure to these default values. * @code * config->enableCmp = true; * config->hysteresisMode = kCMP_HysteresisLevel0; @@ -208,7 +207,7 @@ void CMP_GetDefaultConfig(cmp_config_t *config); * @brief Sets the input channels for the comparator. * * This function sets the input channels for the comparator. - * Note that two input channels cannot be set as same in the application. When the user selects the same input + * Note that two input channels cannot be set the same way in the application. When the user selects the same input * from the analog mux to the positive and negative port, the comparator is disabled automatically. * * @param base CMP peripheral base address. @@ -229,13 +228,11 @@ void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negat * @brief Enables/disables the DMA request for rising/falling events. * * This function enables/disables the DMA request for rising/falling events. Either event triggers the generation of - * the DMA - * request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP - * if the - * DMA is disabled. + * the DMA request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP + * if the DMA is disabled. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ void CMP_EnableDMA(CMP_Type *base, bool enable); #endif /* FSL_FEATURE_CMP_HAS_DMA */ @@ -245,7 +242,7 @@ void CMP_EnableDMA(CMP_Type *base, bool enable); * @brief Enables/disables the window mode. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable) { @@ -265,7 +262,7 @@ static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable) * @brief Enables/disables the pass through mode. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable) { @@ -284,7 +281,7 @@ static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable) * @brief Configures the filter. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config); @@ -292,7 +289,7 @@ void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config); * @brief Configures the internal DAC. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. "NULL" is for disabling the feature. + * @param config Pointer to the configuration structure. "NULL" disables the feature. */ void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c index 9e8831f9983..8cf72bc7e7d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -46,8 +46,6 @@ #define CMT_CMTDIV_FOUR (4) /* CMT diver 8. */ #define CMT_CMTDIV_EIGHT (8) -/* CMT mode bit mask. */ -#define CMT_MODE_BIT_MASK (CMT_MSC_MCGEN_MASK | CMT_MSC_FSK_MASK | CMT_MSC_BASE_MASK) /******************************************************************************* * Prototypes @@ -64,14 +62,16 @@ static uint32_t CMT_GetInstance(CMT_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to cmt clocks for each instance. */ -const clock_ip_name_t s_cmtClock[FSL_FEATURE_SOC_CMT_COUNT] = CMT_CLOCKS; +static const clock_ip_name_t s_cmtClock[FSL_FEATURE_SOC_CMT_COUNT] = CMT_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to cmt bases for each instance. */ static CMT_Type *const s_cmtBases[] = CMT_BASE_PTRS; /*! @brief Pointers to cmt IRQ number for each instance. */ -const IRQn_Type s_cmtIrqs[] = CMT_IRQS; +static const IRQn_Type s_cmtIrqs[] = CMT_IRQS; /******************************************************************************* * Codes @@ -82,7 +82,7 @@ static uint32_t CMT_GetInstance(CMT_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_CMT_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_cmtBases); instance++) { if (s_cmtBases[instance] == base) { @@ -90,7 +90,7 @@ static uint32_t CMT_GetInstance(CMT_Type *base) } } - assert(instance < FSL_FEATURE_SOC_CMT_COUNT); + assert(instance < ARRAY_SIZE(s_cmtBases)); return instance; } @@ -113,8 +113,10 @@ void CMT_Init(CMT_Type *base, const cmt_config_t *config, uint32_t busClock_Hz) uint8_t divider; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate clock. */ CLOCK_EnableClock(s_cmtClock[CMT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Sets clock divider. The divider set in pps should be set to make sycClock_Hz/divder = 8MHz */ @@ -144,15 +146,17 @@ void CMT_Deinit(CMT_Type *base) CMT_DisableInterrupts(base, kCMT_EndOfCycleInterruptEnable); DisableIRQ(s_cmtIrqs[CMT_GetInstance(base)]); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the clock. */ CLOCK_DisableClock(s_cmtClock[CMT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulateConfig) { - uint8_t mscReg; + uint8_t mscReg = base->MSC; - /* Set the mode. */ + /* Judge the mode. */ if (mode != kCMT_DirectIROCtl) { assert(modulateConfig); @@ -166,13 +170,14 @@ void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulat /* Set carrier modulator. */ CMT_SetModulateMarkSpace(base, modulateConfig->markCount, modulateConfig->spaceCount); + mscReg &= ~ (CMT_MSC_FSK_MASK | CMT_MSC_BASE_MASK); + mscReg |= mode; + } + else + { + mscReg &= ~CMT_MSC_MCGEN_MASK; } - /* Set the CMT mode. */ - mscReg = base->MSC; - mscReg &= ~CMT_MODE_BIT_MASK; - mscReg |= mode; - base->MSC = mscReg; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h index df0b2c91066..3d81f8a9a4a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_cmt.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief CMT driver version 2.0.0. */ -#define FSL_CMT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief CMT driver version 2.0.1. */ +#define FSL_CMT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ /*! @@ -128,15 +127,15 @@ enum _cmt_interrupt_enable }; /*! - * @brief CMT carrier generator and modulator configure structure + * @brief CMT carrier generator and modulator configuration structure * */ typedef struct _cmt_modulate_config { - uint8_t highCount1; /*!< The high time for carrier generator first register. */ - uint8_t lowCount1; /*!< The low time for carrier generator first register. */ - uint8_t highCount2; /*!< The high time for carrier generator second register for FSK mode. */ - uint8_t lowCount2; /*!< The low time for carrier generator second register for FSK mode. */ + uint8_t highCount1; /*!< The high-time for carrier generator first register. */ + uint8_t lowCount1; /*!< The low-time for carrier generator first register. */ + uint8_t highCount2; /*!< The high-time for carrier generator second register for FSK mode. */ + uint8_t lowCount2; /*!< The low-time for carrier generator second register for FSK mode. */ uint16_t markCount; /*!< The mark time for the modulator gate. */ uint16_t spaceCount; /*!< The space time for the modulator gate. */ } cmt_modulate_config_t; @@ -164,10 +163,10 @@ extern "C" { */ /*! - * @brief Gets the CMT default configuration structure. The purpose - * of this API is to get the default configuration structure for the CMT_Init(). - * Use the initialized structure unchanged in CMT_Init(), or modify - * some fields of the structure before calling the CMT_Init(). + * @brief Gets the CMT default configuration structure. This API + * gets the default configuration structure for the CMT_Init(). + * Use the initialized structure unchanged in CMT_Init() or modify + * fields of the structure before calling the CMT_Init(). * * @param config The CMT configuration structure pointer. */ @@ -216,7 +215,7 @@ void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulat * * @param base CMT peripheral base address. * @return The CMT mode. - * kCMT_DirectIROCtl Carrier modulator is disabled, the IRO signal is directly in software control. + * kCMT_DirectIROCtl Carrier modulator is disabled; the IRO signal is directly in software control. * kCMT_TimeMode Carrier modulator is enabled in time mode. * kCMT_FSKMode Carrier modulator is enabled in FSK mode. * kCMT_BasebandMode Carrier modulator is enabled in baseband mode. @@ -235,11 +234,11 @@ uint32_t CMT_GetCMTFrequency(CMT_Type *base, uint32_t busClock_Hz); /*! * @brief Sets the primary data set for the CMT carrier generator counter. * - * This function sets the high time and low time of the primary data set for the + * This function sets the high-time and low-time of the primary data set for the * CMT carrier generator counter to control the period and the duty cycle of the * output carrier signal. - * If the CMT clock period is Tcmt, The period of the carrier generator signal equals - * (highCount + lowCount) * Tcmt. The duty cycle equals highCount / (highCount + lowCount). + * If the CMT clock period is Tcmt, the period of the carrier generator signal equals + * (highCount + lowCount) * Tcmt. The duty cycle equals to highCount / (highCount + lowCount). * * @param base CMT peripheral base address. * @param highCount The number of CMT clocks for carrier generator signal high time, @@ -261,10 +260,10 @@ static inline void CMT_SetCarrirGenerateCountOne(CMT_Type *base, uint32_t highCo /*! * @brief Sets the secondary data set for the CMT carrier generator counter. * - * This function is used for FSK mode setting the high time and low time of the secondary + * This function is used for FSK mode setting the high-time and low-time of the secondary * data set CMT carrier generator counter to control the period and the duty cycle * of the output carrier signal. - * If the CMT clock period is Tcmt, The period of the carrier generator signal equals + * If the CMT clock period is Tcmt, the period of the carrier generator signal equals * (highCount + lowCount) * Tcmt. The duty cycle equals highCount / (highCount + lowCount). * * @param base CMT peripheral base address. @@ -325,7 +324,7 @@ static inline void CMT_EnableExtendedSpace(CMT_Type *base, bool enable) } /*! - * @brief Sets IRO - infrared output signal state. + * @brief Sets the IRO (infrared output) signal state. * * Changes the states of the IRO signal when the kCMT_DirectIROMode mode is set * and the IRO signal is enabled. @@ -338,12 +337,12 @@ void CMT_SetIroState(CMT_Type *base, cmt_infrared_output_state_t state); /*! * @brief Enables the CMT interrupt. * - * This function enables the CMT interrupts according to the provided maskIf enabled. + * This function enables the CMT interrupts according to the provided mask if enabled. * The CMT only has the end of the cycle interrupt - an interrupt occurs at the end * of the modulator cycle. This interrupt provides a means for the user * to reload the new mark/space values into the CMT modulator data registers * and verify the modulator mark and space. - * For example, to enable the end of cycle, do the following: + * For example, to enable the end of cycle, do the following. * @code * CMT_EnableInterrupts(CMT, kCMT_EndOfCycleInterruptEnable); * @endcode @@ -360,7 +359,7 @@ static inline void CMT_EnableInterrupts(CMT_Type *base, uint32_t mask) * * This function disables the CMT interrupts according to the provided maskIf enabled. * The CMT only has the end of the cycle interrupt. - * For example, to disable the end of cycle, do the following: + * For example, to disable the end of cycle, do the following. * @code * CMT_DisableInterrupts(CMT, kCMT_EndOfCycleInterruptEnable); * @endcode diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h index 7061b621391..b20ec09973b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_common.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -34,8 +34,12 @@ #include #include #include -#include #include + +#if defined(__ICCARM__) +#include +#endif + #include "fsl_device_registers.h" /*! @@ -43,8 +47,6 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -56,11 +58,13 @@ #define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) /* Debug console type definition. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */ /*! @brief Status group numbers. */ enum _status_groups @@ -87,6 +91,11 @@ enum _status_groups kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */ kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */ kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */ + kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */ + kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */ + kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */ + kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */ + kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */ kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */ kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */ kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */ @@ -101,6 +110,18 @@ enum _status_groups kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */ kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */ kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */ + kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */ + kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */ + kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */ + kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/ + kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */ + kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */ + kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */ + kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */ + kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */ + kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/ + kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */ + kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */ kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */ kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */ kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */ @@ -127,6 +148,14 @@ typedef int32_t status_t; */ #include "fsl_clock.h" +/* + * Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral + */ +#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \ + (defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0))) +#include "fsl_reset.h" +#endif + /*! @name Min/max macros */ /* @{ */ #if !defined(MIN) @@ -182,11 +211,20 @@ extern "C" { */ static inline void EnableIRQ(IRQn_Type interrupt) { + if (NotAvail_IRQn == interrupt) + { + return; + } + #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0) if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX) #endif { +#if defined(__GIC_PRIO_BITS) + GIC_EnableIRQ(interrupt); +#else NVIC_EnableIRQ(interrupt); +#endif } } @@ -199,11 +237,20 @@ static inline void EnableIRQ(IRQn_Type interrupt) */ static inline void DisableIRQ(IRQn_Type interrupt) { + if (NotAvail_IRQn == interrupt) + { + return; + } + #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0) if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX) #endif { +#if defined(__GIC_PRIO_BITS) + GIC_DisableIRQ(interrupt); +#else NVIC_DisableIRQ(interrupt); +#endif } } @@ -217,11 +264,19 @@ static inline void DisableIRQ(IRQn_Type interrupt) */ static inline uint32_t DisableGlobalIRQ(void) { +#if defined(CPSR_I_Msk) + uint32_t cpsr = __get_CPSR() & CPSR_I_Msk; + + __disable_irq(); + + return cpsr; +#else uint32_t regPrimask = __get_PRIMASK(); __disable_irq(); return regPrimask; +#endif } /*! @@ -236,7 +291,11 @@ static inline uint32_t DisableGlobalIRQ(void) */ static inline void EnableGlobalIRQ(uint32_t primask) { +#if defined(CPSR_I_Msk) + __set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask); +#else __set_PRIMASK(primask); +#endif } /*! @@ -244,9 +303,42 @@ static inline void EnableGlobalIRQ(uint32_t primask) * * @param irq IRQ number * @param irqHandler IRQ handler address + * @return The old IRQ handler address */ void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler); +#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) +/*! + * @brief Enable specific interrupt for wake-up from deep-sleep mode. + * + * Enable the interrupt for wake-up from deep sleep mode. + * Some interrupts are typically used in sleep mode only and will not occur during + * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable + * those clocks (significantly increasing power consumption in the reduced power mode), + * making these wake-ups possible. + * + * @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally). + * + * @param interrupt The IRQ number. + */ +void EnableDeepSleepIRQ(IRQn_Type interrupt); + +/*! + * @brief Disable specific interrupt for wake-up from deep-sleep mode. + * + * Disable the interrupt for wake-up from deep sleep mode. + * Some interrupts are typically used in sleep mode only and will not occur during + * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable + * those clocks (significantly increasing power consumption in the reduced power mode), + * making these wake-ups possible. + * + * @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally). + * + * @param interrupt The IRQ number. + */ +void DisableDeepSleepIRQ(IRQn_Type interrupt); +#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */ + #if defined(__cplusplus) } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c index f73647e1c78..dba1db8c463 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -32,6 +32,11 @@ /******************************************************************************* * Definitions ******************************************************************************/ +/*! @internal @brief Has data register with name CRC. */ +#if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG +#define DATA CRC +#define DATALL CRCLL +#endif #if defined(CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT /* @brief Default user configuration structure for CRC-16-CCITT */ @@ -87,7 +92,7 @@ typedef struct _crc_module_config * * @param enable True or false for the selected CRC protocol Reflect In (refin) parameter. */ -static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectIn(bool enable) +static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable) { return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes); } @@ -99,7 +104,7 @@ static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectIn(bool enable * * @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter. */ -static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectOut(bool enable) +static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable) { return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone); } @@ -113,7 +118,7 @@ static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectOut(bool enabl * @param base CRC peripheral address. * @param config Pointer to protocol configuration structure. */ -static void crc_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) +static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) { uint32_t crcControl; @@ -148,18 +153,18 @@ static void crc_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *con * @param base CRC peripheral address. * @param protocolConfig Pointer to protocol configuration structure. */ -static void crc_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) +static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) { crc_module_config_t moduleConfig; /* convert protocol to CRC peripheral module configuration, prepare for final checksum */ moduleConfig.polynomial = protocolConfig->polynomial; moduleConfig.seed = protocolConfig->seed; - moduleConfig.readTranspose = crc_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); - moduleConfig.writeTranspose = crc_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); + moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); + moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); moduleConfig.complementChecksum = protocolConfig->complementChecksum; moduleConfig.crcBits = protocolConfig->crcBits; - crc_ConfigureAndStart(base, &moduleConfig); + CRC_ConfigureAndStart(base, &moduleConfig); } /*! @@ -172,7 +177,7 @@ static void crc_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolCo * @param base CRC peripheral address. * @param protocolConfig Pointer to protocol configuration structure. */ -static void crc_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) +static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) { crc_module_config_t moduleConfig; /* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */ @@ -180,25 +185,27 @@ static void crc_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protoco moduleConfig.seed = protocolConfig->seed; moduleConfig.readTranspose = kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */ - moduleConfig.writeTranspose = crc_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); + moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */ moduleConfig.crcBits = protocolConfig->crcBits; - crc_ConfigureAndStart(base, &moduleConfig); + CRC_ConfigureAndStart(base, &moduleConfig); } void CRC_Init(CRC_Type *base, const crc_config_t *config) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* ungate clock */ CLOCK_EnableClock(kCLOCK_Crc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* configure CRC module and write the seed */ if (config->crcResult == kCrcFinalChecksum) { - crc_SetProtocolConfig(base, config); + CRC_SetProtocolConfig(base, config); } else { - crc_SetRawProtocolConfig(base, config); + CRC_SetRawProtocolConfig(base, config); } } @@ -246,6 +253,11 @@ void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize) } } +uint32_t CRC_Get32bitResult(CRC_Type *base) +{ + return base->DATA; +} + uint16_t CRC_Get16bitResult(CRC_Type *base) { uint32_t retval; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h index ce0b60fbaf9..247a9bac781 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_crc.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -34,28 +34,27 @@ #include "fsl_common.h" /*! - * @addtogroup crc_driver + * @addtogroup crc * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief CRC driver version. Version 2.0.0. */ -#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief CRC driver version. Version 2.0.1. + * + * Current version: 2.0.1 + * + * Change log: + * - Version 2.0.1 + * - move DATA and DATALL macro definition from header file to source file + */ +#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ -/*! @internal @brief Has data register with name CRC. */ -#if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG -#define DATA CRC -#define DATALL CRCLL -#endif - #ifndef CRC_DRIVER_CUSTOM_DEFAULTS /*! @brief Default configuration structure filled by CRC_GetDefaultConfig(). Use CRC16-CCIT-FALSE as defeault. */ #define CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT 1 @@ -108,31 +107,33 @@ extern "C" { /*! * @brief Enables and configures the CRC peripheral module. * - * This functions enables the clock gate in the Kinetis SIM module for the CRC peripheral. - * It also configures the CRC module and starts checksum computation by writing the seed. + * This function enables the clock gate in the SIM module for the CRC peripheral. + * It also configures the CRC module and starts a checksum computation by writing the seed. * * @param base CRC peripheral address. - * @param config CRC module configuration structure + * @param config CRC module configuration structure. */ void CRC_Init(CRC_Type *base, const crc_config_t *config); /*! * @brief Disables the CRC peripheral module. * - * This functions disables the clock gate in the Kinetis SIM module for the CRC peripheral. + * This function disables the clock gate in the SIM module for the CRC peripheral. * * @param base CRC peripheral address. */ static inline void CRC_Deinit(CRC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* gate clock */ CLOCK_DisableClock(kCLOCK_Crc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! - * @brief Loads default values to CRC protocol configuration structure. + * @brief Loads default values to the CRC protocol configuration structure. * - * Loads default values to CRC protocol configuration structure. The default values are: + * Loads default values to the CRC protocol configuration structure. The default values are as follows. * @code * config->polynomial = 0x1021; * config->seed = 0xFFFF; @@ -143,14 +144,14 @@ static inline void CRC_Deinit(CRC_Type *base) * config->crcResult = kCrcFinalChecksum; * @endcode * - * @param config CRC protocol configuration structure + * @param config CRC protocol configuration structure. */ void CRC_GetDefaultConfig(crc_config_t *config); /*! * @brief Writes data to the CRC module. * - * Writes input data buffer bytes to CRC data register. + * Writes input data buffer bytes to the CRC data register. * The configured type of transpose is applied. * * @param base CRC peripheral address. @@ -160,27 +161,24 @@ void CRC_GetDefaultConfig(crc_config_t *config); void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize); /*! - * @brief Reads 32-bit checksum from the CRC module. + * @brief Reads the 32-bit checksum from the CRC module. * - * Reads CRC data register (intermediate or final checksum). - * The configured type of transpose and complement are applied. + * Reads the CRC data register (either an intermediate or the final checksum). + * The configured type of transpose and complement is applied. * * @param base CRC peripheral address. - * @return intermediate or final 32-bit checksum, after configured transpose and complement operations. + * @return An intermediate or the final 32-bit checksum, after configured transpose and complement operations. */ -static inline uint32_t CRC_Get32bitResult(CRC_Type *base) -{ - return base->DATA; -} +uint32_t CRC_Get32bitResult(CRC_Type *base); /*! - * @brief Reads 16-bit checksum from the CRC module. + * @brief Reads a 16-bit checksum from the CRC module. * - * Reads CRC data register (intermediate or final checksum). - * The configured type of transpose and complement are applied. + * Reads the CRC data register (either an intermediate or the final checksum). + * The configured type of transpose and complement is applied. * * @param base CRC peripheral address. - * @return intermediate or final 16-bit checksum, after configured transpose and complement operations. + * @return An intermediate or the final 16-bit checksum, after configured transpose and complement operations. */ uint16_t CRC_Get16bitResult(CRC_Type *base); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c index 2f83f5ee9e6..8d13d622835 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t DAC_GetInstance(DAC_Type *base); ******************************************************************************/ /*! @brief Pointers to DAC bases for each instance. */ static DAC_Type *const s_dacBases[] = DAC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to DAC clocks for each instance. */ -const clock_ip_name_t s_dacClocks[] = DAC_CLOCKS; +static const clock_ip_name_t s_dacClocks[] = DAC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t DAC_GetInstance(DAC_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DAC_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dacBases); instance++) { if (s_dacBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t DAC_GetInstance(DAC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DAC_COUNT); + assert(instance < ARRAY_SIZE(s_dacBases)); return instance; } @@ -75,8 +77,10 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config) uint8_t tmp8; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_dacClocks[DAC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ /* DACx_C0. */ @@ -91,15 +95,18 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config) } base->C0 = tmp8; - DAC_Enable(base, true); + /* DAC_Enable(base, true); */ + /* Tip: The DAC output can be enabled till then after user sets their own available data in application. */ } void DAC_Deinit(DAC_Type *base) { DAC_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_dacClocks[DAC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void DAC_GetDefaultConfig(dac_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h index 44e2d048bd9..b71febf3bc3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dac.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -46,8 +45,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DAC driver version 2.0.0. */ -#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief DAC driver version 2.0.1. */ +#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ /*! @@ -104,15 +103,15 @@ typedef enum _dac_buffer_watermark #if defined(FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD kDAC_BufferWatermark1Word = 0U, /*!< 1 word away from the upper limit. */ #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_1_WORD */ -#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD +#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_2_WORDS) && FSL_FEATURE_DAC_HAS_WATERMARK_2_WORDS kDAC_BufferWatermark2Word = 1U, /*!< 2 words away from the upper limit. */ -#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_2_WORD */ -#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD +#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_2_WORDS */ +#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_3_WORDS) && FSL_FEATURE_DAC_HAS_WATERMARK_3_WORDS kDAC_BufferWatermark3Word = 2U, /*!< 3 words away from the upper limit. */ -#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_3_WORD */ -#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD) && FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD +#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_3_WORDS */ +#if defined(FSL_FEATURE_DAC_HAS_WATERMARK_4_WORDS) && FSL_FEATURE_DAC_HAS_WATERMARK_4_WORDS kDAC_BufferWatermark4Word = 3U, /*!< 4 words away from the upper limit. */ -#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_4_WORD */ +#endif /* FSL_FEATURE_DAC_HAS_WATERMARK_4_WORDS */ } dac_buffer_watermark_t; #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */ @@ -137,7 +136,7 @@ typedef enum _dac_buffer_work_mode typedef struct _dac_config { dac_reference_voltage_source_t referenceVoltageSource; /*!< Select the DAC reference voltage source. */ - bool enableLowPowerMode; /*!< Enable the low power mode. */ + bool enableLowPowerMode; /*!< Enable the low-power mode. */ } dac_config_t; /*! @@ -150,8 +149,8 @@ typedef struct _dac_buffer_config dac_buffer_watermark_t watermark; /*!< Select the buffer's watermark. */ #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */ dac_buffer_work_mode_t workMode; /*!< Select the buffer's work mode. */ - uint8_t upperLimit; /*!< Set the upper limit for buffer index. - Normally, 0-15 is available for buffer with 16 item. */ + uint8_t upperLimit; /*!< Set the upper limit for the buffer index. + Normally, 0-15 is available for a buffer with 16 items. */ } dac_buffer_config_t; /******************************************************************************* @@ -169,7 +168,7 @@ extern "C" { /*! * @brief Initializes the DAC module. * - * This function initializes the DAC module, including: + * This function initializes the DAC module including the following operations. * - Enabling the clock for DAC module. * - Configuring the DAC converter with a user configuration. * - Enabling the DAC module. @@ -182,7 +181,7 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config); /*! * @brief De-initializes the DAC module. * - * This function de-initializes the DAC module, including: + * This function de-initializes the DAC module including the following operations. * - Disabling the DAC module. * - Disabling the clock for the DAC module. * @@ -193,7 +192,7 @@ void DAC_Deinit(DAC_Type *base); /*! * @brief Initializes the DAC user configuration structure. * - * This function initializes the user configuration structure to a default value. The default values are: + * This function initializes the user configuration structure to a default value. The default values are as follows. * @code * config->referenceVoltageSource = kDAC_ReferenceVoltageSourceVref2; * config->enableLowPowerMode = false; @@ -206,7 +205,7 @@ void DAC_GetDefaultConfig(dac_config_t *config); * @brief Enables the DAC module. * * @param base DAC peripheral base address. - * @param enable Enables the feature or not. + * @param enable Enables or disables the feature. */ static inline void DAC_Enable(DAC_Type *base, bool enable) { @@ -231,7 +230,7 @@ static inline void DAC_Enable(DAC_Type *base, bool enable) * @brief Enables the DAC buffer. * * @param base DAC peripheral base address. - * @param enable Enables the feature or not. + * @param enable Enables or disables the feature. */ static inline void DAC_EnableBuffer(DAC_Type *base, bool enable) { @@ -256,7 +255,7 @@ void DAC_SetBufferConfig(DAC_Type *base, const dac_buffer_config_t *config); /*! * @brief Initializes the DAC buffer configuration structure. * - * This function initializes the DAC buffer configuration structure to a default value. The default values are: + * This function initializes the DAC buffer configuration structure to default values. The default values are as follows. * @code * config->triggerMode = kDAC_BufferTriggerBySoftwareMode; * config->watermark = kDAC_BufferWatermark1Word; @@ -271,7 +270,7 @@ void DAC_GetDefaultBufferConfig(dac_buffer_config_t *config); * @brief Enables the DMA for DAC buffer. * * @param base DAC peripheral base address. - * @param enable Enables the feature or not. + * @param enable Enables or disables the feature. */ static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable) { @@ -289,15 +288,15 @@ static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable) * @brief Sets the value for items in the buffer. * * @param base DAC peripheral base address. - * @param index Setting index for items in the buffer. The available index should not exceed the size of the DAC buffer. - * @param value Setting value for items in the buffer. 12-bits are available. + * @param index Setting the index for items in the buffer. The available index should not exceed the size of the DAC buffer. + * @param value Setting the value for items in the buffer. 12-bits are available. */ void DAC_SetBufferValue(DAC_Type *base, uint8_t index, uint16_t value); /*! - * @brief Triggers the buffer by software and updates the read pointer of the DAC buffer. + * @brief Triggers the buffer using software and updates the read pointer of the DAC buffer. * - * This function triggers the function by software. The read pointer of the DAC buffer is updated with one step + * This function triggers the function using software. The read pointer of the DAC buffer is updated with one step * after this function is called. Changing the read pointer depends on the buffer's work mode. * * @param base DAC peripheral base address. @@ -311,12 +310,12 @@ static inline void DAC_DoSoftwareTriggerBuffer(DAC_Type *base) * @brief Gets the current read pointer of the DAC buffer. * * This function gets the current read pointer of the DAC buffer. - * The current output value depends on the item indexed by the read pointer. It is updated - * by software trigger or hardware trigger. + * The current output value depends on the item indexed by the read pointer. It is updated either + * by a software trigger or a hardware trigger. * * @param base DAC peripheral base address. * - * @return Current read pointer of DAC buffer. + * @return The current read pointer of the DAC buffer. */ static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base) { @@ -327,11 +326,11 @@ static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base) * @brief Sets the current read pointer of the DAC buffer. * * This function sets the current read pointer of the DAC buffer. - * The current output value depends on the item indexed by the read pointer. It is updated by - * software trigger or hardware trigger. After the read pointer changes, the DAC output value also changes. + * The current output value depends on the item indexed by the read pointer. It is updated either by a + * software trigger or a hardware trigger. After the read pointer changes, the DAC output value also changes. * * @param base DAC peripheral base address. - * @param index Setting index value for the pointer. + * @param index Setting an index value for the pointer. */ void DAC_SetBufferReadPointer(DAC_Type *base, uint8_t index); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c index a288b9f22fc..39ce9cfbead 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -52,8 +52,10 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base); /*! @brief Array to map DMAMUX instance number to base pointer. */ static DMAMUX_Type *const s_dmamuxBases[] = DMAMUX_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Array to map DMAMUX instance number to clock name. */ static const clock_ip_name_t s_dmamuxClockName[] = DMAMUX_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -63,7 +65,7 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DMAMUX_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dmamuxBases); instance++) { if (s_dmamuxBases[instance] == base) { @@ -71,17 +73,21 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DMAMUX_COUNT); + assert(instance < ARRAY_SIZE(s_dmamuxBases)); return instance; } void DMAMUX_Init(DMAMUX_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void DMAMUX_Deinit(DMAMUX_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h index f4294d4dfa8..071348b2c25 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dmamux.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -46,8 +45,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DMAMUX driver version 2.0.0. */ -#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief DMAMUX driver version 2.0.2. */ +#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ /******************************************************************************* @@ -59,14 +58,14 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name DMAMUX Initialize and De-initialize + * @name DMAMUX Initialization and de-initialization * @{ */ /*! - * @brief Initializes DMAMUX peripheral. + * @brief Initializes the DMAMUX peripheral. * - * This function ungate the DMAMUX clock. + * This function ungates the DMAMUX clock. * * @param base DMAMUX peripheral base address. * @@ -74,9 +73,9 @@ extern "C" { void DMAMUX_Init(DMAMUX_Type *base); /*! - * @brief Deinitializes DMAMUX peripheral. + * @brief Deinitializes the DMAMUX peripheral. * - * This function gate the DMAMUX clock. + * This function gates the DMAMUX clock. * * @param base DMAMUX peripheral base address. */ @@ -89,9 +88,9 @@ void DMAMUX_Deinit(DMAMUX_Type *base); */ /*! - * @brief Enable DMAMUX channel. + * @brief Enables the DMAMUX channel. * - * This function enable DMAMUX channel to work. + * This function enables the DMAMUX channel. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -104,11 +103,11 @@ static inline void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel) } /*! - * @brief Disable DMAMUX channel. + * @brief Disables the DMAMUX channel. * - * This function disable DMAMUX channel. + * This function disables the DMAMUX channel. * - * @note User must disable DMAMUX channel before configure it. + * @note The user must disable the DMAMUX channel before configuring it. * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. */ @@ -120,13 +119,13 @@ static inline void DMAMUX_DisableChannel(DMAMUX_Type *base, uint32_t channel) } /*! - * @brief Configure DMAMUX channel source. + * @brief Configures the DMAMUX channel source. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. - * @param source Channel source which is used to trigger DMA transfer. + * @param source Channel source, which is used to trigger the DMA transfer. */ -static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint8_t source) +static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_t source) { assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL); @@ -135,9 +134,9 @@ static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint8_t #if defined(FSL_FEATURE_DMAMUX_HAS_TRIG) && FSL_FEATURE_DMAMUX_HAS_TRIG > 0U /*! - * @brief Enable DMAMUX period trigger. + * @brief Enables the DMAMUX period trigger. * - * This function enable DMAMUX period trigger feature. + * This function enables the DMAMUX period trigger feature. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -150,9 +149,9 @@ static inline void DMAMUX_EnablePeriodTrigger(DMAMUX_Type *base, uint32_t channe } /*! - * @brief Disable DMAMUX period trigger. + * @brief Disables the DMAMUX period trigger. * - * This function disable DMAMUX period trigger. + * This function disables the DMAMUX period trigger. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -165,6 +164,31 @@ static inline void DMAMUX_DisablePeriodTrigger(DMAMUX_Type *base, uint32_t chann } #endif /* FSL_FEATURE_DMAMUX_HAS_TRIG */ +#if (defined(FSL_FEATURE_DMAMUX_HAS_A_ON) && FSL_FEATURE_DMAMUX_HAS_A_ON) +/*! + * @brief Enables the DMA channel to be always ON. + * + * This function enables the DMAMUX channel always ON feature. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + * @param enable Switcher of the always ON feature. "true" means enabled, "false" means disabled. + */ +static inline void DMAMUX_EnableAlwaysOn(DMAMUX_Type *base, uint32_t channel, bool enable) +{ + assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + if (enable) + { + base->CHCFG[channel] |= DMAMUX_CHCFG_A_ON_MASK; + } + else + { + base->CHCFG[channel] &= ~DMAMUX_CHCFG_A_ON_MASK; + } +} +#endif /* FSL_FEATURE_DMAMUX_HAS_A_ON */ + /* @} */ #if defined(__cplusplus) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c index 5654ce7aac6..d3b3f0aa5f7 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_dspi.h" @@ -65,27 +65,27 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc /*! * @brief Master fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Master finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Slave fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle); /*! * @brief Slave finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle); @@ -100,7 +100,7 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param); /*! * @brief Master prepare the transfer. * Basically it set up dspi_master_handle . - * This is not a public API as it is called from other driver functions. fsl_dspi_edma.c also call this function. + * This is not a public API. */ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -123,11 +123,13 @@ static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS; /*! @brief Pointers to dspi IRQ number for each instance. */ static IRQn_Type const s_dspiIRQ[] = SPI_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to dspi clocks for each instance. */ static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to dspi handles for each instance. */ -static void *g_dspiHandle[FSL_FEATURE_SOC_DSPI_COUNT]; +static void *g_dspiHandle[ARRAY_SIZE(s_dspiBases)]; /*! @brief Pointer to master IRQ handler for each instance. */ static dspi_master_isr_t s_dspiMasterIsr; @@ -135,6 +137,8 @@ static dspi_master_isr_t s_dspiMasterIsr; /*! @brief Pointer to slave IRQ handler for each instance. */ static dspi_slave_isr_t s_dspiSlaveIsr; +/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ +volatile uint8_t s_dummyData[ARRAY_SIZE(s_dspiBases)] = {0}; /********************************************************************************************************************** * Code *********************************************************************************************************************/ @@ -143,7 +147,7 @@ uint32_t DSPI_GetInstance(SPI_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dspiBases); instance++) { if (s_dspiBases[instance] == base) { @@ -151,16 +155,26 @@ uint32_t DSPI_GetInstance(SPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DSPI_COUNT); + assert(instance < ARRAY_SIZE(s_dspiBases)); return instance; } +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = DSPI_GetInstance(base); + s_dummyData[instance] = dummyData; +} + void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { + assert(masterConfig); + uint32_t temp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -196,11 +210,14 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { + assert(masterConfig); + masterConfig->whichCtar = kDSPI_Ctar0; masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; @@ -223,10 +240,14 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -250,11 +271,15 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { + assert(slaveConfig); + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; @@ -271,8 +296,10 @@ void DSPI_Deinit(SPI_Type *base) DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -457,6 +484,8 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { + assert(command); + command->isPcsContinuous = false; command->whichCtar = kDSPI_Ctar0; command->whichPcs = kDSPI_Pcs0; @@ -466,6 +495,8 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { + assert(command); + /* First, clear Transmit Complete Flag (TCF) */ DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); @@ -562,7 +593,7 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; uint8_t bitsPerFrame; uint32_t command; @@ -598,6 +629,7 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + commandStruct.isEndOfQueue = true; commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); @@ -626,25 +658,6 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { if (remainingSendByteCount == 1) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) - { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) { DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); @@ -702,20 +715,23 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = DSPI_ReadData(base); + rxData++; + } + else + { + DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -726,25 +742,6 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { if (remainingSendByteCount <= 2) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) - { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) { DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); @@ -825,20 +822,23 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = DSPI_ReadData(base); + + if (rxData != NULL) + { + *rxData = wordReceived; + ++rxData; + *rxData = wordReceived >> 8; + ++rxData; + } + remainingReceiveByteCount -= 2; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -849,6 +849,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { + assert(handle); + assert(transfer); + dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); @@ -864,6 +867,7 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + commandStruct.isEndOfQueue = true; commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); @@ -886,7 +890,8 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If the transfer count is zero, then return immediately.*/ if (transfer->dataSize == 0) @@ -903,13 +908,10 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha handle->state = kDSPI_Busy; DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); /* Enable the NVIC for DSPI peripheral. */ EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - DSPI_MasterTransferFillUpTxFifo(base, handle); - /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt * Since SPI is a synchronous interface, we only need to enable the RX interrupt. * The IRQ handler will get the status of RX and TX interrupt flags. @@ -917,7 +919,10 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); return kStatus_Success; } @@ -943,6 +948,8 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + /* Disable interrupt requests*/ DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); @@ -956,19 +963,20 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } + handle->state = kDSPI_Idle; + if (handle->callback) { handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; /* If bits/frame is greater than one byte */ if (handle->bitsPerFrame > 8) @@ -1081,6 +1089,8 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ @@ -1091,6 +1101,8 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ if (handle->remainingReceiveByteCount) { @@ -1212,7 +1224,8 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If receive length is zero */ if (transfer->dataSize == 0) @@ -1254,11 +1267,6 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand DSPI_FlushFifo(base, true, true); DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); - DSPI_StartTransfer(base); - - /* Prepare data to transmit */ - DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; /* Enable RX FIFO drain request, the slave only use this interrupt */ @@ -1275,6 +1283,11 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); } + DSPI_StartTransfer(base); + + /* Prepare data to transmit */ + DSPI_SlaveTransferFillUpTxFifo(base, handle); + return kStatus_Success; } @@ -1300,8 +1313,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_SLAVE_DUMMY_DATA; + uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; /* Service the transmitter, if transmit buffer provided, transmit the data, * else transmit dummy pattern @@ -1386,6 +1401,8 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + /* Disable interrupt requests */ DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); @@ -1406,16 +1423,18 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } + handle->state = kDSPI_Idle; + if (handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ @@ -1429,7 +1448,9 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - uint8_t dummyPattern = DSPI_SLAVE_DUMMY_DATA; + assert(handle); + + uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; uint32_t dataReceived; uint32_t dataSend = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h index 93da32fa2f7..abfc7707d75 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,27 +33,24 @@ #include "fsl_common.h" /*! - * @addtogroup dspi + * @addtogroup dspi_driver * @{ */ -/*! @file */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.0. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief DSPI driver version 2.2.0. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*@}*/ -/*! @name Dummy data */ -/*@{*/ -#define DSPI_MASTER_DUMMY_DATA (0x00U) /*!< Master dummy data used for tx if there is not txData. */ -#define DSPI_SLAVE_DUMMY_DATA (0x00U) /*!< Slave dummy data used for tx if there is not txData. */ -/*@}*/ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status @@ -61,7 +58,7 @@ enum _dspi_status kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ @@ -75,7 +72,7 @@ enum _dspi_flags kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ @@ -109,8 +106,9 @@ typedef enum _dspi_master_slave_mode } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -169,36 +167,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -217,20 +216,21 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ /*!< DSPI slave can only use PCS0. */ }; -/*! @brief DSPI transfer state, which is used for DSPI transactional APIs' state machine. */ +/*! @brief DSPI transfer state, which is used for DSPI transactional API state machine. */ enum _dspi_transfer_state { kDSPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver. */ @@ -238,15 +238,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -258,33 +258,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -294,23 +294,23 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; @@ -357,7 +357,7 @@ typedef struct _dspi_transfer volatile size_t dataSize; /*!< Transfer bytes. */ uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the + configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer is used for slave.*/ } dspi_transfer_t; @@ -365,38 +365,39 @@ typedef struct _dspi_transfer /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -421,18 +422,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -443,8 +444,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -452,8 +453,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -466,7 +467,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -481,22 +482,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -510,7 +511,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -536,7 +537,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -549,13 +550,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -574,15 +575,16 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -594,7 +596,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -613,13 +615,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -629,13 +631,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -714,7 +716,7 @@ static inline bool DSPI_IsMaster(SPI_Type *base) /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -723,9 +725,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -735,15 +737,15 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { @@ -755,8 +757,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { @@ -766,13 +768,13 @@ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRx /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -801,19 +803,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -821,19 +823,19 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum - * supported delay is returned. The higher level peripheral driver alerts the user of an out of range delay + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay * input. * * @param base DSPI peripheral address. @@ -853,11 +855,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -869,7 +871,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -883,14 +885,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -898,11 +900,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -915,10 +917,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -933,10 +935,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -949,24 +951,25 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total +* 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the +* desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: @@ -985,7 +988,7 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1024,6 +1027,14 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} */ @@ -1037,13 +1048,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1053,12 +1064,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1067,12 +1077,11 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -1083,19 +1092,19 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1105,7 +1114,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1115,10 +1124,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1129,12 +1138,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1145,8 +1153,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1154,10 +1162,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1167,7 +1175,7 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c index 4d9e129ff24..ef0d15174f5 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_dspi_edma.h" @@ -57,7 +57,7 @@ typedef struct _dspi_slave_edma_private_handle ***********************************************************************************************************************/ /*! * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. +* This is not a public API. */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, @@ -66,7 +66,7 @@ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, /*! * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. +* This is not a public API. */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, @@ -102,6 +102,9 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaIntermediaryToTxRegHandle) { assert(handle); + assert(edmaRxRegToRxDataHandle); + assert(edmaTxDataToIntermediaryHandle); + assert(edmaIntermediaryToTxRegHandle); /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); @@ -121,7 +124,8 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If the transfer count is zero, then return immediately.*/ if (transfer->dataSize == 0) @@ -141,9 +145,11 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand return kStatus_DSPI_Busy; } + handle->state = kDSPI_Busy; + uint32_t instance = DSPI_GetInstance(base); uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = DSPI_DUMMY_DATA; uint8_t dataAlreadyFed = 0; uint8_t dataFedMax = 2; @@ -156,9 +162,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigB; edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_MASTER_DUMMY_DATA << 8) | DSPI_MASTER_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); @@ -174,6 +178,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + commandStruct.isEndOfQueue = true; commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); @@ -193,39 +198,70 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->remainingReceiveByteCount = transfer->dataSize; handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + if (handle->bitsPerFrame > 8) { - if (transfer->dataSize > 1022) + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + { + handle->state = kDSPI_Idle; + return kStatus_InvalidArgument; + } + DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ @@ -243,22 +279,16 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (unsigned)(*(handle->txData)) << 8U; } else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { @@ -291,6 +321,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (handle->remainingSendByteCount == 1) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -315,21 +346,13 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (unsigned)(*(handle->txData)) << 8U; } else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; } handle->remainingSendByteCount = 0; base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; @@ -347,7 +370,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; } handle->remainingSendByteCount -= 2; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; @@ -404,7 +426,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); transferConfigA.srcAddr = (uint32_t)rxAddr; @@ -435,6 +457,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigA.minorLoopBytes = 2; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = transferConfigA.minorLoopBytes; + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, @@ -443,9 +469,82 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->remainingSendByteCount > 0) + /*Calculate the last data : handle->lastCommand*/ + if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || + ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) + { + if (handle->txData) + { + uint32_t bufferIndex = 0; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8) + { + bufferIndex = handle->remainingSendByteCount - 1; + } + else + { + bufferIndex = handle->remainingSendByteCount - 2; + } + } + else + { + bufferIndex = handle->remainingSendByteCount; + } + + if (handle->bitsPerFrame <= 8) + { + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + } + else + { + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | + ((uint32_t)handle->txData[bufferIndex - 1] << 8) | + handle->txData[bufferIndex - 2]; + } + } + else + { + if (handle->bitsPerFrame <= 8) + { + wordToSend = dummyData; + } + else + { + wordToSend = ((uint32_t)dummyData << 8) | dummyData; + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + } + } + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); + } + + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || + ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { if (handle->txData) { @@ -470,8 +569,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2; } else { @@ -486,8 +584,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigB.minorLoopBytes = 2; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2; } else { @@ -497,74 +594,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + } + } + else + { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); } /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) - { - uint32_t bufferIndex = 0; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - if (handle->bitsPerFrame <= 8) - { - bufferIndex = handle->remainingSendByteCount - 1; - } - else - { - bufferIndex = handle->remainingSendByteCount - 2; - } - } - else - { - bufferIndex = handle->remainingSendByteCount; - } - - if (handle->bitsPerFrame <= 8) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; - } - else - { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } - } - } - else - { - if (handle->bitsPerFrame <= 8) - { - wordToSend = dummyData; - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - } + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) { transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); transferConfigC.destAddr = (uint32_t)txAddr; @@ -580,7 +636,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { transferConfigC.srcAddr = (uint32_t)(&(handle->command)); transferConfigC.destAddr = (uint32_t)txAddr; @@ -590,18 +647,28 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigC.srcOffset = 0; transferConfigC.destOffset = 0; transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (handle->bitsPerFrame <= 8) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + } + else + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); } - EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } @@ -673,20 +740,15 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand &preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ + to prepare the next 32bits data (txData to handle->command) */ if (handle->remainingSendByteCount > 1) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } @@ -699,12 +761,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); @@ -723,37 +779,28 @@ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(edmaHandle); + assert(g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } + dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; if (dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); @@ -783,7 +830,8 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; @@ -798,6 +846,8 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToTxRegHandle) { assert(handle); + assert(edmaRxRegToRxDataHandle); + assert(edmaTxDataToTxRegHandle); /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); @@ -816,7 +866,8 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If send/receive length is zero */ if (transfer->dataSize == 0) @@ -836,7 +887,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; @@ -846,54 +897,51 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) { + handle->state = kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ handle->txData = transfer->txData; handle->rxData = transfer->rxData; handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; - - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_SLAVE_DUMMY_DATA; + uint8_t dummyData = DSPI_DUMMY_DATA; uint8_t dataAlreadyFed = 0; uint8_t dataFedMax = 2; @@ -929,16 +977,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { @@ -1025,6 +1066,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle transferConfigA.minorLoopBytes = 2; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = transferConfigA.minorLoopBytes; + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, @@ -1036,98 +1081,47 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_SLAVE_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_SLAVE_DUMMY_DATA | ((uint32_t)DSPI_SLAVE_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; - - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) - { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; - } - else - { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_SLAVE_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_SLAVE_DUMMY_DATA << 8) | DSPI_SLAVE_DUMMY_DATA; - } - } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; if (handle->bitsPerFrame <= 8) { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + handle->txBuffIfNull = DSPI_DUMMY_DATA; } else { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } + handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; } + } - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); + if (handle->bitsPerFrame <= 8) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + &transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); @@ -1195,37 +1189,28 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(edmaHandle); + assert(g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } + dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; if (dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); @@ -1254,7 +1239,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h index 326b7ee442a..23e29ce2983 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,8 +37,6 @@ * @{ */ -/*! @file */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ @@ -57,9 +55,9 @@ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -69,38 +67,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -111,33 +110,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!CR; tmpreg &= ~(DMA_CR_ERCA_MASK | DMA_CR_HOE_MASK | DMA_CR_CLM_MASK | DMA_CR_EDBG_MASK); @@ -134,8 +138,10 @@ void EDMA_Init(DMA_Type *base, const edma_config_t *config) void EDMA_Deinit(DMA_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate EDMA periphral clock */ CLOCK_DisableClock(s_edmaClockName[EDMA_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void EDMA_GetDefaultConfig(edma_config_t *config) @@ -409,46 +415,32 @@ void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask) } } -uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel) +uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel) { assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL); - uint32_t nbytes = 0; - uint32_t remainingBytes = 0; + uint32_t remainingCount = 0; if (DMA_CSR_DONE_MASK & base->TCD[channel].CSR) { - remainingBytes = 0; + remainingCount = 0; } else { - /* Calculate the nbytes */ - if (base->TCD[channel].NBYTES_MLOFFYES & (DMA_NBYTES_MLOFFYES_SMLOE_MASK | DMA_NBYTES_MLOFFYES_DMLOE_MASK)) - { - nbytes = (base->TCD[channel].NBYTES_MLOFFYES & DMA_NBYTES_MLOFFYES_NBYTES_MASK) >> - DMA_NBYTES_MLOFFYES_NBYTES_SHIFT; - } - else - { - nbytes = - (base->TCD[channel].NBYTES_MLOFFNO & DMA_NBYTES_MLOFFNO_NBYTES_MASK) >> DMA_NBYTES_MLOFFNO_NBYTES_SHIFT; - } /* Calculate the unfinished bytes */ if (base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_ELINK_MASK) { - remainingBytes = ((base->TCD[channel].CITER_ELINKYES & DMA_CITER_ELINKYES_CITER_MASK) >> - DMA_CITER_ELINKYES_CITER_SHIFT) * - nbytes; + remainingCount = + (base->TCD[channel].CITER_ELINKYES & DMA_CITER_ELINKYES_CITER_MASK) >> DMA_CITER_ELINKYES_CITER_SHIFT; } else { - remainingBytes = - ((base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_CITER_MASK) >> DMA_CITER_ELINKNO_CITER_SHIFT) * - nbytes; + remainingCount = + (base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_CITER_MASK) >> DMA_CITER_ELINKNO_CITER_SHIFT; } } - return remainingBytes; + return remainingCount; } uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel) @@ -497,14 +489,19 @@ void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel) uint32_t channelIndex; edma_tcd_t *tcdRegs; + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + handle->base = base; handle->channel = channel; /* Get the DMA instance number */ edmaInstance = EDMA_GetInstance(base); channelIndex = (edmaInstance * FSL_FEATURE_EDMA_MODULE_CHANNEL) + channel; s_EDMAHandle[channelIndex] = handle; + /* Enable NVIC interrupt */ - EnableIRQ(s_edmaIRQNumber[channelIndex]); + EnableIRQ(s_edmaIRQNumber[edmaInstance][channel]); + /* Reset TCD registers to zero. Unlike the EDMA_TcdReset(DREQ will be set), CSR will be 0. Because in order to suit EDMA busy check mechanism in @@ -558,8 +555,8 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, assert(config != NULL); assert(srcAddr != NULL); assert(destAddr != NULL); - assert(srcWidth == 1U || srcWidth == 2U || srcWidth == 4U || srcWidth == 16U || srcWidth == 32U); - assert(destWidth == 1U || destWidth == 2U || destWidth == 4U || destWidth == 16U || destWidth == 32U); + assert((srcWidth == 1U) || (srcWidth == 2U) || (srcWidth == 4U) || (srcWidth == 16U) || (srcWidth == 32U)); + assert((destWidth == 1U) || (destWidth == 2U) || (destWidth == 4U) || (destWidth == 16U) || (destWidth == 32U)); assert(transferBytes % bytesEachRequest == 0); config->destAddr = (uint32_t)destAddr; @@ -825,11 +822,11 @@ void EDMA_HandleIRQ(edma_handle_t *handle) /* Clear EDMA interrupt flag */ handle->base->CINT = handle->channel; - if (handle->tcdPool == NULL) + if ((handle->tcdPool == NULL) && (handle->callback != NULL)) { (handle->callback)(handle, handle->userData, true, 0); } - else /* Use the TCD queue. */ + else /* Use the TCD queue. Please refer to the API descriptions in the eDMA header file for detailed information. */ { uint32_t sga = handle->base->TCD[handle->channel].DLAST_SGA; uint32_t sga_index; @@ -839,19 +836,19 @@ void EDMA_HandleIRQ(edma_handle_t *handle) /* Check if transfer is already finished. */ transfer_done = ((handle->base->TCD[handle->channel].CSR & DMA_CSR_DONE_MASK) != 0); - /* Get the offset of the current transfer TCD blcoks. */ + /* Get the offset of the next transfer TCD blcoks to be loaded into the eDMA engine. */ sga -= (uint32_t)handle->tcdPool; - /* Get the index of the current transfer TCD blcoks. */ + /* Get the index of the next transfer TCD blcoks to be loaded into the eDMA engine. */ sga_index = sga / sizeof(edma_tcd_t); /* Adjust header positions. */ if (transfer_done) { - /* New header shall point to the next TCD (current one is already finished) */ + /* New header shall point to the next TCD to be loaded (current one is already finished) */ new_header = sga_index; } else { - /* New header shall point to this descriptor (not finished yet) */ + /* New header shall point to this descriptor currently loaded (not finished yet) */ new_header = sga_index ? sga_index - 1U : handle->tcdSize - 1U; } /* Calculate the number of finished TCDs */ @@ -863,7 +860,7 @@ void EDMA_HandleIRQ(edma_handle_t *handle) } else { - /* Internal error occurs. */ + /* No TCD in the memory are going to be loaded or internal error occurs. */ tcds_done = 0; } } @@ -875,9 +872,9 @@ void EDMA_HandleIRQ(edma_handle_t *handle) tcds_done += handle->tcdSize; } } - /* Advance header to the point beyond the last finished TCD block. */ + /* Advance header which points to the TCD to be loaded into the eDMA engine from memory. */ handle->header = new_header; - /* Release TCD blocks. */ + /* Release TCD blocks. tcdUsed is the TCD number which can be used/loaded in the memory pool. */ handle->tcdUsed -= tcds_done; /* Invoke callback function. */ if (handle->callback) @@ -937,12 +934,260 @@ void DMA0_37_DriverIRQHandler(void) EDMA_HandleIRQ(s_EDMAHandle[7]); } } + +#if defined(DMA1) +void DMA1_04_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA1_15_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA1_26_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA1_37_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} +#endif #endif /* 8 channels (Shared) */ +/* 16 channels (Shared): K32H844P */ +#if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 16U + +void DMA0_08_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[0]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } +} + +void DMA0_19_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[1]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } +} + +void DMA0_210_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[2]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } +} + +void DMA0_311_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[3]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } +} + +void DMA0_412_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[4]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA0_513_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[5]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA0_614_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[6]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA0_715_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[7]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} + +#if defined(DMA1) +void DMA1_08_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[16]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[24]); + } +} + +void DMA1_19_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[17]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[25]); + } +} + +void DMA1_210_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[18]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[26]); + } +} + +void DMA1_311_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[19]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[27]); + } +} + +void DMA1_412_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[20]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[28]); + } +} + +void DMA1_513_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[21]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[29]); + } +} + +void DMA1_614_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[22]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[30]); + } +} + +void DMA1_715_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[23]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[31]); + } +} +#endif +#endif /* 16 channels (Shared) */ + /* 32 channels (Shared): k80 */ #if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 32U -void DMA0_DMA16_IRQHandler(void) +void DMA0_DMA16_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) { @@ -954,7 +1199,7 @@ void DMA0_DMA16_IRQHandler(void) } } -void DMA1_DMA17_IRQHandler(void) +void DMA1_DMA17_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) { @@ -966,7 +1211,7 @@ void DMA1_DMA17_IRQHandler(void) } } -void DMA2_DMA18_IRQHandler(void) +void DMA2_DMA18_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) { @@ -978,7 +1223,7 @@ void DMA2_DMA18_IRQHandler(void) } } -void DMA3_DMA19_IRQHandler(void) +void DMA3_DMA19_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) { @@ -990,7 +1235,7 @@ void DMA3_DMA19_IRQHandler(void) } } -void DMA4_DMA20_IRQHandler(void) +void DMA4_DMA20_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) { @@ -1002,7 +1247,7 @@ void DMA4_DMA20_IRQHandler(void) } } -void DMA5_DMA21_IRQHandler(void) +void DMA5_DMA21_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) { @@ -1014,7 +1259,7 @@ void DMA5_DMA21_IRQHandler(void) } } -void DMA6_DMA22_IRQHandler(void) +void DMA6_DMA22_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) { @@ -1026,7 +1271,7 @@ void DMA6_DMA22_IRQHandler(void) } } -void DMA7_DMA23_IRQHandler(void) +void DMA7_DMA23_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) { @@ -1038,7 +1283,7 @@ void DMA7_DMA23_IRQHandler(void) } } -void DMA8_DMA24_IRQHandler(void) +void DMA8_DMA24_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) { @@ -1050,7 +1295,7 @@ void DMA8_DMA24_IRQHandler(void) } } -void DMA9_DMA25_IRQHandler(void) +void DMA9_DMA25_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) { @@ -1062,7 +1307,7 @@ void DMA9_DMA25_IRQHandler(void) } } -void DMA10_DMA26_IRQHandler(void) +void DMA10_DMA26_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) { @@ -1074,7 +1319,7 @@ void DMA10_DMA26_IRQHandler(void) } } -void DMA11_DMA27_IRQHandler(void) +void DMA11_DMA27_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) { @@ -1086,7 +1331,7 @@ void DMA11_DMA27_IRQHandler(void) } } -void DMA12_DMA28_IRQHandler(void) +void DMA12_DMA28_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) { @@ -1098,7 +1343,7 @@ void DMA12_DMA28_IRQHandler(void) } } -void DMA13_DMA29_IRQHandler(void) +void DMA13_DMA29_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) { @@ -1110,7 +1355,7 @@ void DMA13_DMA29_IRQHandler(void) } } -void DMA14_DMA30_IRQHandler(void) +void DMA14_DMA30_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) { @@ -1122,7 +1367,7 @@ void DMA14_DMA30_IRQHandler(void) } } -void DMA15_DMA31_IRQHandler(void) +void DMA15_DMA31_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) { @@ -1135,6 +1380,202 @@ void DMA15_DMA31_IRQHandler(void) } #endif /* 32 channels (Shared) */ +/* 32 channels (Shared): MCIMX7U5_M4 */ +#if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 32U + +void DMA0_0_4_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[0]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[4]); + } +} + +void DMA0_1_5_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[1]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[5]); + } +} + +void DMA0_2_6_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[2]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[6]); + } +} + +void DMA0_3_7_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[3]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[7]); + } +} + +void DMA0_8_12_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA0_9_13_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA0_10_14_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA0_11_15_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} + +void DMA0_16_20_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 16U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[16]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 20U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[20]); + } +} + +void DMA0_17_21_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 17U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[17]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 21U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[21]); + } +} + +void DMA0_18_22_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 18U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[18]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 22U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[22]); + } +} + +void DMA0_19_23_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 19U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[19]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 23U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[23]); + } +} + +void DMA0_24_28_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 24U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[24]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 28U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[28]); + } +} + +void DMA0_25_29_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 25U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[25]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 29U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[29]); + } +} + +void DMA0_26_30_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 26U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[26]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 30U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[30]); + } +} + +void DMA0_27_31_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 27U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[27]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 31U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[31]); + } +} +#endif /* 32 channels (Shared): MCIMX7U5 */ + /* 4 channels (No Shared): kv10 */ #if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL > 0 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h index ca9632e247a..a97622d7e1e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_edma.h @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_EDMA_H_ #define _FSL_EDMA_H_ @@ -34,11 +34,10 @@ #include "fsl_common.h" /*! - * @addtogroup edma_driver + * @addtogroup edma * @{ */ -/*! @file */ /******************************************************************************* * Definitions ******************************************************************************/ @@ -46,7 +45,7 @@ /*! @name Driver version */ /*@{*/ /*! @brief eDMA driver version */ -#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ +#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1. */ /*@}*/ /*! @brief Compute the offset unit from DCHPRI3 */ @@ -78,28 +77,28 @@ typedef enum _edma_modulo kEDMA_Modulo128bytes, /*!< Circular buffer size is 128 bytes. */ kEDMA_Modulo256bytes, /*!< Circular buffer size is 256 bytes. */ kEDMA_Modulo512bytes, /*!< Circular buffer size is 512 bytes. */ - kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1K bytes. */ - kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2K bytes. */ - kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4K bytes. */ - kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8K bytes. */ - kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16K bytes. */ - kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32K bytes. */ - kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64K bytes. */ - kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128K bytes. */ - kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256K bytes. */ - kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512K bytes. */ - kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1M bytes. */ - kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2M bytes. */ - kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4M bytes. */ - kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8M bytes. */ - kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16M bytes. */ - kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32M bytes. */ - kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64M bytes. */ - kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128M bytes. */ - kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256M bytes. */ - kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512M bytes. */ - kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1G bytes. */ - kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2G bytes. */ + kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1 K bytes. */ + kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2 K bytes. */ + kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4 K bytes. */ + kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8 K bytes. */ + kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16 K bytes. */ + kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32 K bytes. */ + kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64 K bytes. */ + kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128 K bytes. */ + kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256 K bytes. */ + kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512 K bytes. */ + kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1 M bytes. */ + kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2 M bytes. */ + kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4 M bytes. */ + kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8 M bytes. */ + kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16 M bytes. */ + kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32 M bytes. */ + kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64 M bytes. */ + kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128 M bytes. */ + kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256 M bytes. */ + kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512 M bytes. */ + kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1 G bytes. */ + kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2 G bytes. */ } edma_modulo_t; /*! @brief Bandwidth control */ @@ -143,7 +142,7 @@ enum _edma_error_status_flags #if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1 kEDMA_GroupPriorityErrorFlag = DMA_ES_GPE_MASK, /*!< Group priority is not unique. */ #endif - kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit will be 0, otherwise be 1 */ + kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit is 0. Otherwise, it is 1. */ }; /*! @brief eDMA interrupt source */ @@ -178,7 +177,7 @@ typedef struct _edma_config the link channel is itself. */ bool enableHaltOnError; /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set. Subsequently, all service requests are ignored until the HALT bit is cleared.*/ - bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method, or fixed priority + bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method or fixed priority arbitration is used for channel selection */ bool enableDebugMode; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of a new channel. Executing channels are allowed to complete. */ @@ -212,15 +211,15 @@ typedef struct _edma_transfer_config form the next-state value as each source read is completed. */ int16_t destOffset; /*!< Sign-extended offset applied to the current destination address to form the next-state value as each destination write is completed. */ - uint16_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/ + uint32_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/ uint32_t majorLoopCounts; /*!< Major loop iteration count. */ } edma_transfer_config_t; /*! @brief eDMA channel priority configuration */ typedef struct _edma_channel_Preemption_config { - bool enableChannelPreemption; /*!< If true: channel can be suspended by other channel with higher priority */ - bool enablePreemptAbility; /*!< If true: channel can suspend other channel with low priority */ + bool enableChannelPreemption; /*!< If true: a channel can be suspended by other channel with higher priority */ + bool enablePreemptAbility; /*!< If true: a channel can suspend other channel with low priority */ uint8_t channelPriority; /*!< Channel priority */ } edma_channel_Preemption_config_t; @@ -229,14 +228,14 @@ typedef struct _edma_minor_offset_config { bool enableSrcMinorOffset; /*!< Enable(true) or Disable(false) source minor loop offset. */ bool enableDestMinorOffset; /*!< Enable(true) or Disable(false) destination minor loop offset. */ - uint32_t minorOffset; /*!< Offset for minor loop mapping. */ + uint32_t minorOffset; /*!< Offset for a minor loop mapping. */ } edma_minor_offset_config_t; /*! * @brief eDMA TCD. * * This structure is same as TCD register which is described in reference manual, - * and is used to configure scatter/gather feature as a next hardware TCD. + * and is used to configure the scatter/gather feature as a next hardware TCD. */ typedef struct _edma_tcd { @@ -256,20 +255,21 @@ typedef struct _edma_tcd /*! @brief Callback for eDMA */ struct _edma_handle; -/*! @brief Define Callback function for eDMA. */ +/*! @brief Define callback function for eDMA. */ typedef void (*edma_callback)(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds); /*! @brief eDMA transfer handle structure */ typedef struct _edma_handle { - edma_callback callback; /*!< Callback function for major count exhausted. */ - void *userData; /*!< Callback function parameter. */ - DMA_Type *base; /*!< eDMA peripheral base address. */ - edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */ - uint8_t channel; /*!< eDMA channel number. */ - volatile int8_t header; /*!< The first TCD index. */ - volatile int8_t tail; /*!< The last TCD index. */ - volatile int8_t tcdUsed; /*!< The number of used TCD slots. */ + edma_callback callback; /*!< Callback function for major count exhausted. */ + void *userData; /*!< Callback function parameter. */ + DMA_Type *base; /*!< eDMA peripheral base address. */ + edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */ + uint8_t channel; /*!< eDMA channel number. */ + volatile int8_t header; /*!< The first TCD index. Should point to the next TCD to be loaded into the eDMA engine. */ + volatile int8_t tail; /*!< The last TCD index. Should point to the next TCD to be stored into the memory pool. */ + volatile int8_t tcdUsed; /*!< The number of used TCD slots. Should reflect the number of TCDs can be used/loaded in + the memory. */ volatile int8_t tcdSize; /*!< The total number of TCD slots in the queue. */ uint8_t flags; /*!< The status of the current channel. */ } edma_handle_t; @@ -282,24 +282,24 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name eDMA initialization and De-initialization + * @name eDMA initialization and de-initialization * @{ */ /*! - * @brief Initializes eDMA peripheral. + * @brief Initializes the eDMA peripheral. * - * This function ungates the eDMA clock and configure eDMA peripheral according + * This function ungates the eDMA clock and configures the eDMA peripheral according * to the configuration structure. * * @param base eDMA peripheral base address. - * @param config Pointer to configuration structure, see "edma_config_t". - * @note This function enable the minor loop map feature. + * @param config A pointer to the configuration structure, see "edma_config_t". + * @note This function enables the minor loop map feature. */ void EDMA_Init(DMA_Type *base, const edma_config_t *config); /*! - * @brief Deinitializes eDMA peripheral. + * @brief Deinitializes the eDMA peripheral. * * This function gates the eDMA clock. * @@ -310,8 +310,8 @@ void EDMA_Deinit(DMA_Type *base); /*! * @brief Gets the eDMA default configuration structure. * - * This function sets the configuration structure to a default value. - * The default configuration is set to the following value: + * This function sets the configuration structure to default values. + * The default configuration is set to the following values. * @code * config.enableContinuousLinkMode = false; * config.enableHaltOnError = true; @@ -319,7 +319,7 @@ void EDMA_Deinit(DMA_Type *base); * config.enableDebugMode = false; * @endcode * - * @param config Pointer to eDMA configuration structure. + * @param config A pointer to the eDMA configuration structure. */ void EDMA_GetDefaultConfig(edma_config_t *config); @@ -330,22 +330,22 @@ void EDMA_GetDefaultConfig(edma_config_t *config); */ /*! - * @brief Sets all TCD registers to a default value. + * @brief Sets all TCD registers to default values. * - * This function sets TCD registers for this channel to default value. + * This function sets TCD registers for this channel to default values. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @note This function must not be called while the channel transfer is on-going, - * or it will case unpredicated results. - * @note This function will enable auto stop request feature. + * @note This function must not be called while the channel transfer is ongoing + * or it causes unpredictable results. + * @note This function enables the auto stop request feature. */ void EDMA_ResetChannel(DMA_Type *base, uint32_t channel); /*! * @brief Configures the eDMA transfer attribute. * - * This function configure the transfer attribute, including source address, destination address, + * This function configures the transfer attribute, including source address, destination address, * transfer size, address offset, and so on. It also configures the scatter gather feature if the * user supplies the TCD address. * Example: @@ -361,11 +361,11 @@ void EDMA_ResetChannel(DMA_Type *base, uint32_t channel); * @param base eDMA peripheral base address. * @param channel eDMA channel number. * @param config Pointer to eDMA transfer configuration structure. - * @param nextTcd Point to TCD structure. It can be NULL if user + * @param nextTcd Point to TCD structure. It can be NULL if users * do not want to enable scatter/gather feature. - * @note If nextTcd is not NULL, it means scatter gather feature will be enabled. - * And DREQ bit will be cleared in the previous transfer configuration which - * will be set in eDMA_ResetChannel. + * @note If nextTcd is not NULL, it means scatter gather feature is enabled + * and DREQ bit is cleared in the previous transfer configuration, which + * is set in the eDMA_ResetChannel. */ void EDMA_SetTransferConfig(DMA_Type *base, uint32_t channel, @@ -375,12 +375,12 @@ void EDMA_SetTransferConfig(DMA_Type *base, /*! * @brief Configures the eDMA minor offset feature. * - * Minor offset means signed-extended value added to source address or destination + * The minor offset means that the signed-extended value is added to the source address or destination * address after each minor loop. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param config Pointer to Minor offset configuration structure. + * @param config A pointer to the minor offset configuration structure. */ void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config); @@ -391,7 +391,7 @@ void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_mino * * @param base eDMA peripheral base address. * @param channel eDMA channel number - * @param config Pointer to channel preemption configuration structure. + * @param config A pointer to the channel preemption configuration structure. */ static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base, uint32_t channel, @@ -408,30 +408,31 @@ static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base, /*! * @brief Sets the channel link for the eDMA transfer. * - * This function configures minor link or major link mode. The minor link means that the channel link is - * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is exhausted. + * This function configures either the minor link or the major link mode. The minor link means that the channel link is + * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is + * exhausted. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param type Channel link type, it can be one of: + * @param type A channel link type, which can be one of the following: * @arg kEDMA_LinkNone * @arg kEDMA_MinorLink * @arg kEDMA_MajorLink * @param linkedChannel The linked channel number. - * @note User should ensure that DONE flag is cleared before call this interface, or the configuration will be invalid. + * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid. */ void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel); /*! * @brief Sets the bandwidth for the eDMA transfer. * - * In general, because the eDMA processes the minor loop, it continuously generates read/write sequences + * Because the eDMA processes the minor loop, it continuously generates read/write sequences * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of * each read/write access to control the bus request bandwidth seen by the crossbar switch. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param bandWidth Bandwidth setting, it can be one of: + * @param bandWidth A bandwidth setting, which can be one of the following: * @arg kEDMABandwidthStallNone * @arg kEDMABandwidthStall4Cycle * @arg kEDMABandwidthStall8Cycle @@ -439,7 +440,7 @@ void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_typ void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth); /*! - * @brief Sets the source modulo and destination modulo for eDMA transfer. + * @brief Sets the source modulo and the destination modulo for the eDMA transfer. * * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF) * calculation is performed or the original register value. It provides the ability to implement a circular data @@ -447,8 +448,8 @@ void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWi * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param srcModulo Source modulo value. - * @param destModulo Destination modulo value. + * @param srcModulo A source modulo value. + * @param destModulo A destination modulo value. */ void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo); @@ -458,7 +459,7 @@ void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, e * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param enable The command for enable(ture) or disable(false). + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable) { @@ -475,7 +476,7 @@ static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, boo * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param enable The command for enable (true) or disable (false). + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable) { @@ -489,7 +490,7 @@ static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of interrupt source to be set. User need to use + * @param mask The mask of interrupt source to be set. Users need to use * the defined edma_interrupt_enable_t type. */ void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -499,7 +500,7 @@ void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mas * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of interrupt source to be set. Use + * @param mask The mask of the interrupt source to be set. Use * the defined edma_interrupt_enable_t type. */ void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -516,15 +517,15 @@ void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t ma * This function sets all fields for this TCD structure to default value. * * @param tcd Pointer to the TCD structure. - * @note This function will enable auto stop request feature. + * @note This function enables the auto stop request feature. */ void EDMA_TcdReset(edma_tcd_t *tcd); /*! * @brief Configures the eDMA TCD transfer attribute. * - * TCD is a transfer control descriptor. The content of the TCD is the same as hardware TCD registers. - * STCD is used in scatter-gather mode. + * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers. + * The STCD is used in the scatter-gather mode. * This function configures the TCD transfer attribute, including source address, destination address, * transfer size, address offset, and so on. It also configures the scatter gather feature if the * user supplies the next TCD address. @@ -540,33 +541,34 @@ void EDMA_TcdReset(edma_tcd_t *tcd); * * @param tcd Pointer to the TCD structure. * @param config Pointer to eDMA transfer configuration structure. - * @param nextTcd Pointer to the next TCD structure. It can be NULL if user + * @param nextTcd Pointer to the next TCD structure. It can be NULL if users * do not want to enable scatter/gather feature. - * @note TCD address should be 32 bytes aligned, or it will cause eDMA error. - * @note If nextTcd is not NULL, it means scatter gather feature will be enabled. - * And DREQ bit will be cleared in the previous transfer configuration which - * will be set in EDMA_TcdReset. + * @note TCD address should be 32 bytes aligned or it causes an eDMA error. + * @note If the nextTcd is not NULL, the scatter gather feature is enabled + * and DREQ bit is cleared in the previous transfer configuration, which + * is set in the EDMA_TcdReset. */ void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd); /*! * @brief Configures the eDMA TCD minor offset feature. * - * Minor offset is a signed-extended value added to the source address or destination + * A minor offset is a signed-extended value added to the source address or a destination * address after each minor loop. * - * @param tcd Point to the TCD structure. - * @param config Pointer to Minor offset configuration structure. + * @param tcd A point to the TCD structure. + * @param config A pointer to the minor offset configuration structure. */ void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config); /*! - * @brief Sets the channel link for eDMA TCD. + * @brief Sets the channel link for the eDMA TCD. * * This function configures either a minor link or a major link. The minor link means the channel link is - * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is exhausted. + * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is + * exhausted. * - * @note User should ensure that DONE flag is cleared before call this interface, or the configuration will be invalid. + * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid. * @param tcd Point to the TCD structure. * @param type Channel link type, it can be one of: * @arg kEDMA_LinkNone @@ -579,11 +581,11 @@ void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint /*! * @brief Sets the bandwidth for the eDMA TCD. * - * In general, because the eDMA processes the minor loop, it continuously generates read/write sequences - * until the minor count is exhausted. Bandwidth forces the eDMA to stall after the completion of + * Because the eDMA processes the minor loop, it continuously generates read/write sequences + * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of * each read/write access to control the bus request bandwidth seen by the crossbar switch. - * @param tcd Point to the TCD structure. - * @param bandWidth Bandwidth setting, it can be one of: + * @param tcd A pointer to the TCD structure. + * @param bandWidth A bandwidth setting, which can be one of the following: * @arg kEDMABandwidthStallNone * @arg kEDMABandwidthStall4Cycle * @arg kEDMABandwidthStall8Cycle @@ -597,15 +599,15 @@ static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWi } /*! - * @brief Sets the source modulo and destination modulo for eDMA TCD. + * @brief Sets the source modulo and the destination modulo for the eDMA TCD. * * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF) * calculation is performed or the original register value. It provides the ability to implement a circular data * queue easily. * - * @param tcd Point to the TCD structure. - * @param srcModulo Source modulo value. - * @param destModulo Destination modulo value. + * @param tcd A pointer to the TCD structure. + * @param srcModulo A source modulo value. + * @param destModulo A destination modulo value. */ void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo); @@ -614,8 +616,8 @@ void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t d * * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request. * - * @param tcd Point to the TCD structure. - * @param enable The command for enable(ture) or disable(false). + * @param tcd A pointer to the TCD structure. + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable) { @@ -629,7 +631,7 @@ static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable) * @brief Enables the interrupt source for the eDMA TCD. * * @param tcd Point to the TCD structure. - * @param mask The mask of interrupt source to be set. User need to use + * @param mask The mask of interrupt source to be set. Users need to use * the defined edma_interrupt_enable_t type. */ void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask); @@ -638,7 +640,7 @@ void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask); * @brief Disables the interrupt source for the eDMA TCD. * * @param tcd Point to the TCD structure. - * @param mask The mask of interrupt source to be set. User need to use + * @param mask The mask of interrupt source to be set. Users need to use * the defined edma_interrupt_enable_t type. */ void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask); @@ -680,7 +682,7 @@ static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel) } /*! - * @brief Starts the eDMA transfer by software trigger. + * @brief Starts the eDMA transfer by using the software trigger. * * This function starts a minor loop transfer. * @@ -701,25 +703,34 @@ static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel) */ /*! - * @brief Gets the Remaining bytes from the eDMA current channel TCD. + * @brief Gets the remaining major loop count from the eDMA current channel TCD. * * This function checks the TCD (Task Control Descriptor) status for a specified - * eDMA channel and returns the the number of bytes that have not finished. + * eDMA channel and returns the the number of major loop count that has not finished. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @return Bytes have not been transferred yet for the current TCD. - * @note This function can only be used to get unfinished bytes of transfer without - * the next TCD, or it might be inaccuracy. - */ -uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel); + * @return Major loop count which has not been transferred yet for the current TCD. + * @note 1. This function can only be used to get unfinished major loop count of transfer without + * the next TCD, or it might be inaccuracy. + * 2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while + * the channel is running. + * Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO + * register is needed while the eDMA IP does not support getting it while a channel is active. + * In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine + * is working with while a channel is running. + * Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example + * copied before enabling the channel) is needed. The formula to calculate it is shown below: + * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured) + */ +uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel); /*! * @brief Gets the eDMA channel error status flags. * * @param base eDMA peripheral base address. - * @return The mask of error status flags. User need to use the - * _edma_error_status_flags type to decode the return variables. + * @return The mask of error status flags. Users need to use the +* _edma_error_status_flags type to decode the return variables. */ static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base) { @@ -731,7 +742,7 @@ static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base) * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @return The mask of channel status flags. User need to use the + * @return The mask of channel status flags. Users need to use the * _edma_channel_status_flags type to decode the return variables. */ uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel); @@ -741,7 +752,7 @@ uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel); * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of channel status to be cleared. User need to use + * @param mask The mask of channel status to be cleared. Users need to use * the defined _edma_channel_status_flags type. */ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -754,8 +765,8 @@ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mas /*! * @brief Creates the eDMA handle. * - * This function is called if using transaction API for eDMA. This function - * initializes the internal state of eDMA handle. + * This function is called if using the transactional API for eDMA. This function + * initializes the internal state of the eDMA handle. * * @param handle eDMA handle pointer. The eDMA handle stores callback function and * parameters. @@ -765,12 +776,12 @@ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mas void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel); /*! - * @brief Installs the TCDs memory pool into eDMA handle. + * @brief Installs the TCDs memory pool into the eDMA handle. * * This function is called after the EDMA_CreateHandle to use scatter/gather feature. * * @param handle eDMA handle pointer. - * @param tcdPool Memory pool to store TCDs. It must be 32 bytes aligned. + * @param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned. * @param tcdSize The number of TCD slots. */ void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize); @@ -778,12 +789,12 @@ void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t /*! * @brief Installs a callback function for the eDMA transfer. * - * This callback is called in eDMA IRQ handler. Use the callback to do something after + * This callback is called in the eDMA IRQ handler. Use the callback to do something after * the current major loop transfer completes. * * @param handle eDMA handle pointer. * @param callback eDMA callback function pointer. - * @param userData Parameter for callback function. + * @param userData A parameter for the callback function. */ void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData); @@ -801,8 +812,8 @@ void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userD * @param transferBytes eDMA transfer bytes to be transferred. * @param type eDMA transfer type. * @note The data address and the data width must be consistent. For example, if the SRC - * is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in - * source address error(SAE). + * is 4 bytes, the source address must be 4 bytes aligned, or it results in + * source address error (SAE). */ void EDMA_PrepareTransfer(edma_transfer_config_t *config, void *srcAddr, @@ -817,7 +828,7 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, * @brief Submits the eDMA transfer request. * * This function submits the eDMA transfer request according to the transfer configuration structure. - * If the user submits the transfer request repeatedly, this function packs an unprocessed request as + * If submitting the transfer request repeatedly, this function packs an unprocessed request as * a TCD and enables scatter/gather feature to process it in the next time. * * @param handle eDMA handle pointer. @@ -829,9 +840,9 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config); /*! - * @brief eDMA start transfer. + * @brief eDMA starts transfer. * - * This function enables the channel request. User can call this function after submitting the transfer request + * This function enables the channel request. Users can call this function after submitting the transfer request * or before submitting the transfer request. * * @param handle eDMA handle pointer. @@ -839,9 +850,9 @@ status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t void EDMA_StartTransfer(edma_handle_t *handle); /*! - * @brief eDMA stop transfer. + * @brief eDMA stops transfer. * - * This function disables the channel request to pause the transfer. User can call EDMA_StartTransfer() + * This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer() * again to resume the transfer. * * @param handle eDMA handle pointer. @@ -849,21 +860,41 @@ void EDMA_StartTransfer(edma_handle_t *handle); void EDMA_StopTransfer(edma_handle_t *handle); /*! - * @brief eDMA abort transfer. + * @brief eDMA aborts transfer. * * This function disables the channel request and clear transfer status bits. - * User can submit another transfer after calling this API. + * Users can submit another transfer after calling this API. * * @param handle DMA handle pointer. */ void EDMA_AbortTransfer(edma_handle_t *handle); /*! - * @brief eDMA IRQ handler for current major loop transfer complete. + * @brief eDMA IRQ handler for the current major loop transfer completion. * - * This function clears the channel major interrupt flag and call + * This function clears the channel major interrupt flag and calls * the callback function if it is not NULL. * + * Note: + * For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed. + * These include the final address adjustments and reloading of the BITER field into the CITER. + * Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from + * memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled). + * + * For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine. + * As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index + * in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be + * (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have + * been loaded into the eDMA engine at this point already.). + * + * For the last two continuous ISRs in a scatter/gather process, they both load the last TCD (The last ISR does not + * load a new TCD) from the memory pool to the eDMA engine when major loop completes. + * Therefore, ensure that the header and tcdUsed updated are identical for them. + * tcdUsed are both 0 in this case as no TCD to be loaded. + * + * See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for + * further details. + * * @param handle eDMA handle pointer. */ void EDMA_HandleIRQ(edma_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c index fe6077fba8f..674f525025d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_enet.h" @@ -90,10 +90,8 @@ #define ENET_IPV6VERSION 0x0006U /*! @brief Ethernet mac address length. */ #define ENET_FRAME_MACLEN 6U -/*! @brief Ethernet Frame header length. */ -#define ENET_FRAME_HEADERLEN 14U /*! @brief Ethernet VLAN header length. */ -#define ENET_FRAME_VLAN_HEADERLEN 18U +#define ENET_FRAME_VLAN_TAGLEN 4U /*! @brief MDC frequency. */ #define ENET_MDC_FREQUENCY 2500000U /*! @brief NanoSecond in one second. */ @@ -238,8 +236,10 @@ static status_t ENET_StoreRxFrameTime(ENET_Type *base, enet_handle_t *handle, en /*! @brief Pointers to enet handles for each instance. */ static enet_handle_t *s_ENETHandle[FSL_FEATURE_SOC_ENET_COUNT] = {NULL}; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to enet clocks for each instance. */ const clock_ip_name_t s_enetClock[] = ENET_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to enet transmit IRQ number for each instance. */ static const IRQn_Type s_enetTxIrqId[] = ENET_Transmit_IRQS; @@ -259,6 +259,7 @@ static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS; static enet_isr_t s_enetTxIsr; static enet_isr_t s_enetRxIsr; static enet_isr_t s_enetErrIsr; +static enet_isr_t s_enetTsIsr; /******************************************************************************* * Code ******************************************************************************/ @@ -268,7 +269,7 @@ uint32_t ENET_GetInstance(ENET_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_ENET_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_enetBases); instance++) { if (s_enetBases[instance] == base) { @@ -276,7 +277,7 @@ uint32_t ENET_GetInstance(ENET_Type *base) } } - assert(instance < FSL_FEATURE_SOC_ENET_COUNT); + assert(instance < ARRAY_SIZE(s_enetBases)); return instance; } @@ -314,10 +315,11 @@ void ENET_Init(ENET_Type *base, assert(bufferConfig->rxBufferAlign); assert(macAddr); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) uint32_t instance = ENET_GetInstance(base); - /* Ungate ENET clock. */ CLOCK_EnableClock(s_enetClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset ENET module. */ ENET_Reset(base); @@ -346,8 +348,10 @@ void ENET_Deinit(ENET_Type *base) /* Disable ENET. */ base->ECR &= ~ENET_ECR_ETHEREN_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disables the clock source. */ CLOCK_DisableClock(s_enetClock[ENET_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void ENET_SetCallback(enet_handle_t *handle, enet_callback_t callback, void *userData) @@ -407,7 +411,13 @@ static void ENET_SetMacController(ENET_Type *base, uint32_t tcr = 0; uint32_t ecr = 0; uint32_t macSpecialConfig = config->macSpecialConfig; - uint32_t instance = ENET_GetInstance(base); + uint32_t maxFrameLen = config->rxMaxFrameLen; + + /* Maximum frame length check. */ + if ((macSpecialConfig & kENET_ControlVLANTagEnable) && (maxFrameLen <= ENET_FRAME_MAX_FRAMELEN)) + { + maxFrameLen = (ENET_FRAME_MAX_FRAMELEN + ENET_FRAME_VLAN_TAGLEN); + } /* Configures MAC receive controller with user configure structure. */ rcr = ENET_RCR_NLC(!!(macSpecialConfig & kENET_ControlRxPayloadCheckEnable)) | @@ -417,16 +427,16 @@ static void ENET_SetMacController(ENET_Type *base, ENET_RCR_BC_REJ(!!(macSpecialConfig & kENET_ControlRxBroadCastRejectEnable)) | ENET_RCR_PROM(!!(macSpecialConfig & kENET_ControlPromiscuousEnable)) | ENET_RCR_MII_MODE(1) | ENET_RCR_RMII_MODE(config->miiMode) | ENET_RCR_RMII_10T(!config->miiSpeed) | - ENET_RCR_MAX_FL(config->rxMaxFrameLen) | ENET_RCR_CRCFWD(1); + ENET_RCR_MAX_FL(maxFrameLen) | ENET_RCR_CRCFWD(1); /* Receive setting for half duplex. */ if (config->miiDuplex == kENET_MiiHalfDuplex) { - rcr |= ENET_RCR_DRT(1); + rcr |= ENET_RCR_DRT_MASK; } /* Sets internal loop only for MII mode. */ if ((config->macSpecialConfig & kENET_ControlMIILoopEnable) && (config->miiMode == kENET_MiiMode)) { - rcr |= ENET_RCR_LOOP(1); + rcr |= ENET_RCR_LOOP_MASK; rcr &= ~ENET_RCR_DRT_MASK; } base->RCR = rcr; @@ -446,7 +456,7 @@ static void ENET_SetMacController(ENET_Type *base, uint32_t reemReg; base->OPD = config->pauseDuration; reemReg = ENET_RSEM_RX_SECTION_EMPTY(config->rxFifoEmptyThreshold); -#if FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD +#if defined (FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD) && FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD reemReg |= ENET_RSEM_STAT_SECTION_EMPTY(config->rxFifoStatEmptyThreshold); #endif /* FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD */ base->RSEM = reemReg; @@ -492,7 +502,22 @@ static void ENET_SetMacController(ENET_Type *base, ENET_SetSMI(base, srcClock_Hz, !!(config->macSpecialConfig & kENET_ControlSMIPreambleDisable)); } - /* Enables Ethernet interrupt and NVIC. */ +/* Enables Ethernet interrupt and NVIC. */ +#if defined(FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE + if (config->intCoalesceCfg) + { + uint32_t intMask = (ENET_EIMR_TXB_MASK | ENET_EIMR_RXB_MASK); + + /* Clear all buffer interrupts. */ + base->EIMR &= ~intMask; + + /* Set the interrupt coalescence. */ + base->TXIC = ENET_TXIC_ICFT(config->intCoalesceCfg->txCoalesceFrameCount[0]) | + config->intCoalesceCfg->txCoalesceTimeCount[0] | ENET_TXIC_ICCS_MASK | ENET_TXIC_ICEN_MASK; + base->RXIC = ENET_RXIC_ICFT(config->intCoalesceCfg->rxCoalesceFrameCount[0]) | + config->intCoalesceCfg->rxCoalesceTimeCount[0] | ENET_RXIC_ICCS_MASK | ENET_RXIC_ICEN_MASK; + } +#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */ ENET_EnableInterrupts(base, config->interrupt); /* ENET control register setting. */ @@ -545,7 +570,6 @@ static void ENET_SetTxBufferDescriptors(volatile enet_tx_bd_struct_t *txBdStartA /* Increase the index. */ curBuffDescrip++; } - } static void ENET_SetRxBufferDescriptors(volatile enet_rx_bd_struct_t *rxBdStartAlign, @@ -688,6 +712,46 @@ void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_ base->MMFR = mmfr; } +#if defined(FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO +void ENET_StartExtC45SMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data) +{ + uint32_t mmfr = 0; + + /* Parse the address from the input register. */ + uint16_t devAddr = (phyReg >> ENET_MMFR_TA_SHIFT) & 0x1FU; + uint16_t regAddr = (uint16_t)(phyReg & 0xFFFFU); + + /* Address write firstly. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiAddrWrite_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2) | ENET_MMFR_DATA(regAddr); + base->MMFR = mmfr; + + /* Build MII write command. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiWriteFrame_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2) | ENET_MMFR_DATA(data); + base->MMFR = mmfr; +} + +void ENET_StartExtC45SMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg) +{ + uint32_t mmfr = 0; + + /* Parse the address from the input register. */ + uint16_t devAddr = (phyReg >> ENET_MMFR_TA_SHIFT) & 0x1FU; + uint16_t regAddr = (uint16_t)(phyReg & 0xFFFFU); + + /* Address write firstly. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiAddrWrite_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2) | ENET_MMFR_DATA(regAddr); + base->MMFR = mmfr; + + /* Build MII read command. */ + mmfr = ENET_MMFR_ST(0) | ENET_MMFR_OP(kENET_MiiReadFrame_C45) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(devAddr) | + ENET_MMFR_TA(2); + base->MMFR = mmfr; +} +#endif /* FSL_FEATURE_ENET_HAS_EXTEND_MDIO */ + void ENET_GetRxErrBeforeReadFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic) { assert(handle); @@ -769,13 +833,15 @@ status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length) assert(handle->rxBdCurrent); assert(length); + /* Reset the length to zero. */ + *length = 0; + uint16_t validLastMask = ENET_BUFFDESCRIPTOR_RX_LAST_MASK | ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; /* Check the current buffer descriptor's empty flag. if empty means there is no frame received. */ if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) { - *length = 0; return kStatus_ENET_RxFrameEmpty; } @@ -791,7 +857,6 @@ status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length) #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ ) { - *length = 0; return kStatus_ENET_RxFrameError; } /* FCS is removed by MAC. */ @@ -821,8 +886,9 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u uint32_t len = 0; uint32_t offset = 0; + uint16_t control; bool isLastBuff = false; - volatile enet_rx_bd_struct_t *curBuffDescrip; + volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; status_t result = kStatus_Success; /* For data-NULL input, only update the buffer descriptor. */ @@ -830,37 +896,24 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u { do { - /* Get the current buffer descriptor. */ - curBuffDescrip = handle->rxBdCurrent; - /* Increase current buffer descriptor to the next one. */ - if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) - { - handle->rxBdCurrent = handle->rxBdBase; - } - else - { - handle->rxBdCurrent++; - } + /* Update the control flag. */ + control = handle->rxBdCurrent->control; + /* Updates the receive buffer descriptors. */ + ENET_UpdateReadBuffers(base, handle); - /* The last buffer descriptor of a frame. */ - if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) + /* Find the last buffer descriptor for the frame. */ + if (control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) { - /* Find the last buffer descriptor for the frame*/ break; } - } while (handle->rxBdCurrent != handle->rxBdDirty); - /* Update all receive buffer descriptors for the whole frame. */ - ENET_UpdateReadBuffers(base, handle); + } while (handle->rxBdCurrent != curBuffDescrip); return result; } else { - /* Frame read from the MAC to user buffer and update the buffer descriptors. - Process the frame, a frame on several receive buffers are considered . */ - /* Get the current buffer descriptor. */ - curBuffDescrip = handle->rxBdCurrent; +/* A frame on one buffer or several receive buffers are both considered. */ #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE enet_ptp_time_data_t ptpTimestamp; bool isPtpEventMessage = false; @@ -871,16 +924,6 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u while (!isLastBuff) { - /* Increase current buffer descriptor to the next one. */ - if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) - { - handle->rxBdCurrent = handle->rxBdBase; - } - else - { - handle->rxBdCurrent++; - } - /* The last buffer descriptor of a frame. */ if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) { @@ -900,28 +943,39 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u result = ENET_StoreRxFrameTime(base, handle, &ptpTimestamp); } #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + + /* Updates the receive buffer descriptors. */ ENET_UpdateReadBuffers(base, handle); return result; } + else + { + /* Updates the receive buffer descriptors. */ + ENET_UpdateReadBuffers(base, handle); + } } else { - /* Store the fragments of a frame on several buffer descriptors. */ + /* Store a frame on several buffer descriptors. */ isLastBuff = false; - memcpy(data + offset, curBuffDescrip->buffer, handle->rxBuffSizeAlign); - offset += handle->rxBuffSizeAlign; + /* Length check. */ if (offset >= length) { break; } + + memcpy(data + offset, curBuffDescrip->buffer, handle->rxBuffSizeAlign); + offset += handle->rxBuffSizeAlign; + + /* Updates the receive buffer descriptors. */ + ENET_UpdateReadBuffers(base, handle); } /* Get the current buffer descriptor. */ curBuffDescrip = handle->rxBdCurrent; } - /* All error happens will break the while loop and arrive here to update receive buffers. */ - ENET_UpdateReadBuffers(base, handle); } + return kStatus_ENET_RxFrameFail; } @@ -929,26 +983,23 @@ static void ENET_UpdateReadBuffers(ENET_Type *base, enet_handle_t *handle) { assert(handle); - do - { - /* Clears status. */ - handle->rxBdDirty->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; - /* Sets the receive buffer descriptor with the empty flag. */ - handle->rxBdDirty->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; - /* Increases the buffer descriptor to the next one. */ - if (handle->rxBdDirty->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) - { - handle->rxBdDirty = handle->rxBdBase; - } - else - { - handle->rxBdDirty++; - } + /* Clears status. */ + handle->rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; + /* Sets the receive buffer descriptor with the empty flag. */ + handle->rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; - /* Actives the receive buffer descriptor. */ - base->RDAR = ENET_RDAR_RDAR_MASK; + /* Increase current buffer descriptor to the next one. */ + if (handle->rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) + { + handle->rxBdCurrent = handle->rxBdBase; + } + else + { + handle->rxBdCurrent++; + } - } while (handle->rxBdDirty != handle->rxBdCurrent); + /* Actives the receive buffer descriptor. */ + base->RDAR = ENET_RDAR_RDAR_MASK; } status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length) @@ -956,7 +1007,7 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u assert(handle); assert(handle->txBdCurrent); assert(data); - assert(length <= (ENET_FRAME_MAX_VALNFRAMELEN - 4)); + assert(length <= ENET_FRAME_MAX_FRAMELEN); volatile enet_tx_bd_struct_t *curBuffDescrip = handle->txBdCurrent; uint32_t len = 0; @@ -985,6 +1036,11 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u { curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; } + else + { + curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ curBuffDescrip->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); @@ -1013,6 +1069,10 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u { curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; } + else + { + curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ /* Increase the buffer descriptor address. */ @@ -1034,6 +1094,7 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u curBuffDescrip->length = handle->txBuffSizeAlign; len += handle->txBuffSizeAlign; /* Sets the control flag. */ + curBuffDescrip->control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; /* Active the transmit buffer descriptor*/ base->TDAR = ENET_TDAR_TDAR_MASK; @@ -1054,7 +1115,7 @@ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u } while (!(curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)); - return kStatus_ENET_TxFrameFail; + return kStatus_ENET_TxFrameBusy; } } @@ -1216,7 +1277,7 @@ static bool ENET_Ptp1588ParseFrame(uint8_t *data, enet_ptp_time_data_t *ptpTsDat /* Check for VLAN frame. */ if (*(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET) == ENET_HTONS(ENET_8021QVLAN)) { - buffer += (ENET_FRAME_VLAN_HEADERLEN - ENET_FRAME_HEADERLEN); + buffer += ENET_FRAME_VLAN_TAGLEN; } ptpType = *(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET); @@ -1299,7 +1360,8 @@ void ENET_Ptp1588Configure(ENET_Type *base, enet_handle_t *handle, enet_ptp_conf /* Enables the time stamp interrupt for the master clock on a device. */ ENET_EnableInterrupts(base, kENET_TsTimerInterrupt); - /* Enables the transmit interrupt to store the transmit frame time-stamp. */ + /* Enables only frame interrupt for transmit side to store the transmit + frame time-stamp when the whole frame is transmitted out. */ ENET_EnableInterrupts(base, kENET_TxFrameInterrupt); ENET_DisableInterrupts(base, kENET_TxBufferInterrupt); @@ -1318,6 +1380,7 @@ void ENET_Ptp1588Configure(ENET_Type *base, enet_handle_t *handle, enet_ptp_conf /* Set the IRQ handler when the interrupt is enabled. */ s_enetTxIsr = ENET_TransmitIRQHandler; + s_enetTsIsr = ENET_Ptp1588TimerIRQHandler; EnableIRQ(s_enetTsIrqId[instance]); EnableIRQ(s_enetTxIrqId[instance]); } @@ -1624,8 +1687,8 @@ void ENET_TransmitIRQHandler(ENET_Type *base, enet_handle_t *handle) #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE if (base->EIR & kENET_TxFrameInterrupt) { - /* Store the transmit timestamp from the buffer descriptor should be done here. */ - ENET_StoreTxFrameTime(base, handle); + /* Store the transmit timestamp from the buffer descriptor should be done here. */ + ENET_StoreTxFrameTime(base, handle); } #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ @@ -1665,7 +1728,7 @@ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle) uint32_t errMask = kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_EBusERInterrupt | kENET_PayloadRxInterrupt | kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt | kENET_UnderrunInterrupt; - /* Check if the PTP time stamp interrupt happen. */ + /* Check if the error interrupt happen. */ if (kENET_WakeupInterrupt & base->EIR) { /* Clear the wakeup interrupt. */ @@ -1680,7 +1743,7 @@ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle) } else { - /* Clear the time stamp interrupt. */ + /* Clear the error interrupt event status. */ errMask &= base->EIR; base->EIR = errMask; /* Callback function. */ @@ -1721,13 +1784,34 @@ void ENET_Ptp1588TimerIRQHandler(ENET_Type *base, enet_handle_t *handle) } } } +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ -void ENET_1588_Timer_IRQHandler(void) +void ENET_CommonFrame0IRQHandler(ENET_Type *base) { - ENET_Ptp1588TimerIRQHandler(ENET, s_ENETHandle[0]); + uint32_t event = base->EIR; + uint32_t instance = ENET_GetInstance(base); + + if (event & ENET_TX_INTERRUPT) + { + s_enetTxIsr(base, s_ENETHandle[instance]); + } + + if (event & ENET_RX_INTERRUPT) + { + s_enetRxIsr(base, s_ENETHandle[instance]); + } + + if (event & ENET_TS_INTERRUPT) + { + s_enetTsIsr(base, s_ENETHandle[instance]); + } + if (event & ENET_ERR_INTERRUPT) + { + s_enetErrIsr(base, s_ENETHandle[instance]); + } } -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ +#if defined(ENET) void ENET_Transmit_IRQHandler(void) { s_enetTxIsr(ENET, s_ENETHandle[0]); @@ -1742,3 +1826,10 @@ void ENET_Error_IRQHandler(void) { s_enetErrIsr(ENET, s_ENETHandle[0]); } + +void ENET_1588_Timer_IRQHandler(void) +{ + s_enetTsIsr(ENET, s_ENETHandle[0]); +} +#endif + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h index f35da473cd8..211a01138b4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_enet.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -46,7 +45,7 @@ /*! @name Driver version */ /*@{*/ /*! @brief Defines the driver version. */ -#define FSL_ENET_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ +#define FSL_ENET_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1. */ /*@}*/ /*! @name Control and status region bit masks of the receive buffer descriptor. */ @@ -124,18 +123,18 @@ #endif #define ENET_TX_INTERRUPT (kENET_TxFrameInterrupt | kENET_TxBufferInterrupt) #define ENET_RX_INTERRUPT (kENET_RxFrameInterrupt | kENET_RxBufferInterrupt) +#define ENET_TS_INTERRUPT (kENET_TsTimerInterrupt | kENET_TsAvailInterrupt) #define ENET_ERR_INTERRUPT (kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_EBusERInterrupt | \ kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt | kENET_UnderrunInterrupt | kENET_PayloadRxInterrupt) + /*! @name Defines the maximum Ethernet frame size. */ /*@{*/ -#define ENET_FRAME_MAX_FRAMELEN 1518U /*!< Maximum Ethernet frame size. */ -#define ENET_FRAME_MAX_VALNFRAMELEN 1522U /*!< Maximum VLAN frame size. */ +#define ENET_FRAME_MAX_FRAMELEN 1518U /*!< Default maximum Ethernet frame size. */ /*@}*/ #define ENET_FIFO_MIN_RX_FULL 5U /*!< ENET minimum receive FIFO full. */ #define ENET_RX_MIN_BUFFERSIZE 256U /*!< ENET minimum buffer size. */ -#define ENET_BUFF_ALIGNMENT 16U /*!< Ethernet buffer alignment. */ /*! @brief Defines the PHY address scope for the ENET. */ #define ENET_PHY_MAXADDRESS (ENET_MMFR_PA_MASK >> ENET_MMFR_PA_SHIFT) @@ -191,6 +190,15 @@ typedef enum _enet_mii_read kENET_MiiReadNoCompliant = 3U /*!< Read frame operation, but not MII-compliant. */ } enet_mii_read_t; +#if defined (FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO +/*! @brief Define the MII opcode for extended MDIO_CLAUSES_45 Frame. */ +typedef enum _enet_mii_extend_opcode { + kENET_MiiAddrWrite_C45 = 0U, /*!< Address Write operation. */ + kENET_MiiWriteFrame_C45 = 1U, /*!< Write frame operation for a valid MII management frame. */ + kENET_MiiReadFrame_C45 = 3U /*!< Read frame operation for a valid MII management frame. */ +} enet_mii_extend_opcode; +#endif /* FSL_FEATURE_ENET_HAS_EXTEND_MDIO */ + /*! @brief Defines a special configuration for ENET MAC controller. * * These control flags are provided for special user requirements. @@ -237,12 +245,9 @@ typedef enum _enet_interrupt_enable kENET_RetryLimitInterrupt = ENET_EIR_RL_MASK, /*!< Collision Retry Limit interrupt source */ kENET_UnderrunInterrupt = ENET_EIR_UN_MASK, /*!< Transmit FIFO underrun interrupt source */ kENET_PayloadRxInterrupt = ENET_EIR_PLR_MASK, /*!< Payload Receive interrupt source */ - kENET_WakeupInterrupt = ENET_EIR_WAKEUP_MASK /*!< WAKEUP interrupt source */ -#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - , + kENET_WakeupInterrupt = ENET_EIR_WAKEUP_MASK, /*!< WAKEUP interrupt source */ kENET_TsAvailInterrupt = ENET_EIR_TS_AVAIL_MASK, /*!< TS AVAIL interrupt source for PTP */ kENET_TsTimerInterrupt = ENET_EIR_TS_TIMER_MASK /*!< TS WRAP interrupt source for PTP */ -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_interrupt_enable_t; /*! @brief Defines the common interrupt event for callback use. */ @@ -252,10 +257,8 @@ typedef enum _enet_event kENET_TxEvent, /*!< Transmit event. */ kENET_ErrEvent, /*!< Error event: BABR/BABT/EBERR/LC/RL/UN/PLR . */ kENET_WakeUpEvent, /*!< Wake up from sleep mode event. */ -#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE kENET_TimeStampEvent, /*!< Time stamp event. */ kENET_TimeStampAvailEvent /*!< Time stamp available event.*/ -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_event_t; /*! @brief Defines the transmit accelerator configuration. */ @@ -380,15 +383,20 @@ typedef struct _enet_data_error_stats #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_data_error_stats_t; -/*! @brief Defines the receive buffer descriptor configure structure. +/*! @brief Defines the receive buffer descriptor configuration structure. * - * Note: For the internal DMA requirements, the buffers have a corresponding alignment requirement: - * 1. The aligned receive and transmit buffer size must be evenly divisible by 16. + * Note that for the internal DMA requirements, the buffers have a corresponding alignment requirements. + * 1. The aligned receive and transmit buffer size must be evenly divisible by ENET_BUFF_ALIGNMENT. + * when the data buffers are in cacheable region when cache is enabled, all those size should be + * aligned to the maximum value of "ENET_BUFF_ALIGNMENT" and the cache line size. * 2. The aligned transmit and receive buffer descriptor start address must be at - * least 64 bit aligned. However, it's recommended to be evenly divisible by 16. - * 3. The aligned transmit and receive buffer start address must be evenly divisible by 16. + * least 64 bit aligned. However, it's recommended to be evenly divisible by ENET_BUFF_ALIGNMENT. + * buffer descriptors should be put in non-cacheable region when cache is enabled. + * 3. The aligned transmit and receive data buffer start address must be evenly divisible by ENET_BUFF_ALIGNMENT. * Receive buffers should be continuous with the total size equal to "rxBdNumber * rxBuffSizeAlign". * Transmit buffers should be continuous with the total size equal to "txBdNumber * txBuffSizeAlign". + * when the data buffers are in cacheable region when cache is enabled, all those size should be + * aligned to the maximum value of "ENET_BUFF_ALIGNMENT" and the cache line size. */ typedef struct _enet_buffer_config { @@ -429,7 +437,7 @@ typedef struct _enet_ptp_time_data_ring enet_ptp_time_data_t *ptpTsData; /*!< PTP message data structure. */ } enet_ptp_time_data_ring_t; -/*! @brief Defines the ENET PTP configure structure. */ +/*! @brief Defines the ENET PTP configuration structure. */ typedef struct _enet_ptp_config { uint8_t ptpTsRxBuffNum; /*!< Receive 1588 timestamp buffer number*/ @@ -441,19 +449,28 @@ typedef struct _enet_ptp_config } enet_ptp_config_t; #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ - +#if defined (FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE +/*! @brief Defines the interrupt coalescing configure structure. */ +typedef struct _enet_intcoalesce_config +{ + uint8_t txCoalesceFrameCount[FSL_FEATURE_ENET_QUEUE]; /*!< Transmit interrupt coalescing frame count threshold. */ + uint16_t txCoalesceTimeCount[FSL_FEATURE_ENET_QUEUE]; /*!< Transmit interrupt coalescing timer count threshold. */ + uint8_t rxCoalesceFrameCount[FSL_FEATURE_ENET_QUEUE]; /*!< Receive interrupt coalescing frame count threshold. */ + uint16_t rxCoalesceTimeCount[FSL_FEATURE_ENET_QUEUE]; /*!< Receive interrupt coalescing timer count threshold. */ +} enet_intcoalesce_config_t; +#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */ /*! @brief Defines the basic configuration structure for the ENET device. * * Note: - * 1. macSpecialConfig is used for a special control configuration, A logical OR of + * 1. macSpecialConfig is used for a special control configuration, a logical OR of * "enet_special_control_flag_t". For a special configuration for MAC, * set this parameter to 0. - * 2. txWatermark is used for a cut-through operation. It is in steps of 64 bytes: + * 2. txWatermark is used for a cut-through operation. It is in steps of 64 bytes. * 0/1 - 64 bytes written to TX FIFO before transmission of a frame begins. * 2 - 128 bytes written to TX FIFO .... * 3 - 192 bytes written to TX FIFO .... - * The maximum of txWatermark is 0x2F - 4032 bytes written to TX FIFO .... + * The maximum of txWatermark is 0x2F - 4032 bytes written to TX FIFO. * txWatermark allows minimizing the transmit latency to set the txWatermark to 0 or 1 * or for larger bus access latency 3 or larger due to contention for the system bus. * 3. rxFifoFullThreshold is similar to the txWatermark for cut-through operation in RX. @@ -485,7 +502,7 @@ typedef struct _enet_config uint16_t pauseDuration; /*!< For flow control enabled case: Pause duration. */ uint8_t rxFifoEmptyThreshold; /*!< For flow control enabled case: when RX FIFO level reaches this value, it makes MAC generate XOFF pause frame. */ -#if FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD +#if defined (FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD) && FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD uint8_t rxFifoStatEmptyThreshold; /*!< For flow control enabled case: number of frames in the receive FIFO, independent of size, that can be accept. If the limit is reached, reception continues and a pause frame is triggered. */ @@ -494,6 +511,10 @@ typedef struct _enet_config the MAC receive ready status. */ uint8_t txFifoWatermark; /*!< For store and forward disable case, the data required in TX FIFO before a frame transmit start. */ +#if defined (FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE + enet_intcoalesce_config_t *intCoalesceCfg; /* If the interrupt coalsecence is not required in the ring n(0,1,2), please set + to NULL. */ +#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */ } enet_config_t; /* Forward declaration of the handle typedef. */ @@ -507,7 +528,6 @@ struct _enet_handle { volatile enet_rx_bd_struct_t *rxBdBase; /*!< Receive buffer descriptor base address pointer. */ volatile enet_rx_bd_struct_t *rxBdCurrent; /*!< The current available receive buffer descriptor pointer. */ - volatile enet_rx_bd_struct_t *rxBdDirty; /*!< The dirty receive buffer descriptor needed to be updated from. */ volatile enet_tx_bd_struct_t *txBdBase; /*!< Transmit buffer descriptor base address pointer. */ volatile enet_tx_bd_struct_t *txBdCurrent; /*!< The current available transmit buffer descriptor pointer. */ volatile enet_tx_bd_struct_t *txBdDirty; /*!< The dirty transmit buffer descriptor needed to be updated from. */ @@ -533,7 +553,7 @@ extern "C" { #endif /*! - * @name Initialization and De-initialization + * @name Initialization and de-initialization * @{ */ @@ -541,10 +561,10 @@ extern "C" { * @brief Gets the ENET default configuration structure. * * The purpose of this API is to get the default ENET MAC controller - * configure structure for ENET_Init(). User may use the initialized - * structure unchanged in ENET_Init(), or modify some fields of the + * configuration structure for ENET_Init(). Users may use the initialized + * structure unchanged in ENET_Init() or modify fields of the * structure before calling ENET_Init(). - * Example: + * This is an example. @code enet_config_t config; ENET_GetDefaultConfig(&config); @@ -560,18 +580,18 @@ void ENET_GetDefaultConfig(enet_config_t *config); * * @param base ENET peripheral base address. * @param handle ENET handler pointer. - * @param config ENET mac configuration structure pointer. + * @param config ENET Mac configuration structure pointer. * The "enet_config_t" type mac configuration return from ENET_GetDefaultConfig * can be used directly. It is also possible to verify the Mac configuration using other methods. * @param bufferConfig ENET buffer configuration structure pointer. * The buffer configuration should be prepared for ENET Initialization. - * @param macAddr ENET mac address of Ethernet device. This MAC address should be + * @param macAddr ENET mac address of the Ethernet device. This Mac address should be * provided. * @param srcClock_Hz The internal module clock source for MII clock. * - * @note ENET has two buffer descriptors: legacy buffer descriptors and - * enhanced 1588 buffer descriptors. The legacy descriptor is used by default. To - * use 1588 feature, use the enhanced 1588 buffer descriptor + * @note ENET has two buffer descriptors legacy buffer descriptors and + * enhanced IEEE 1588 buffer descriptors. The legacy descriptor is used by default. To + * use the IEEE 1588 feature, use the enhanced IEEE 1588 buffer descriptor * by defining "ENET_ENHANCEDBUFFERDESCRIPTOR_MODE" and calling ENET_Ptp1588Configure() * to configure the 1588 feature and related buffers after calling ENET_Init(). */ @@ -593,8 +613,8 @@ void ENET_Deinit(ENET_Type *base); /*! * @brief Resets the ENET module. * - * This function restores the ENET module to reset state. - * Note that this function sets all registers to + * This function restores the ENET module to the reset state. + * Note that this function sets all registers to the * reset state. As a result, the ENET module can't work after calling this function. * * @param base ENET peripheral base address. @@ -621,7 +641,7 @@ static inline void ENET_Reset(ENET_Type *base) void ENET_SetMII(ENET_Type *base, enet_mii_speed_t speed, enet_mii_duplex_t duplex); /*! - * @brief Sets the ENET SMI(serial management interface)- MII management interface. + * @brief Sets the ENET SMI (serial management interface) - MII management interface. * * @param base ENET peripheral base address. * @param srcClock_Hz This is the ENET module clock frequency. Normally it's the system clock. See clock distribution. @@ -634,7 +654,7 @@ void ENET_SetSMI(ENET_Type *base, uint32_t srcClock_Hz, bool isPreambleDisabled) /*! * @brief Gets the ENET SMI- MII management interface configuration. * - * This API is used to get the SMI configuration to check if the MII management + * This API is used to get the SMI configuration to check whether the MII management * interface has been set. * * @param base ENET peripheral base address. @@ -646,7 +666,7 @@ static inline bool ENET_GetSMI(ENET_Type *base) } /*! - * @brief Reads data from the PHY register through SMI interface. + * @brief Reads data from the PHY register through an SMI interface. * * @param base ENET peripheral base address. * @return The data read from PHY @@ -667,7 +687,7 @@ static inline uint32_t ENET_ReadSMIData(ENET_Type *base) void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_read_t operation); /*! - * @brief Starts a SMI write command. + * @brief Starts an SMI write command. * * @param base ENET peripheral base address. * @param phyAddr The PHY address. @@ -677,6 +697,31 @@ void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_ */ void ENET_StartSMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_write_t operation, uint32_t data); +#if defined (FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO +/*! + * @brief Starts the extended IEEE802.3 Clause 45 MDIO format SMI read command. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param phyReg The PHY register. For MDIO IEEE802.3 Clause 45, + * the phyReg is a 21-bits combination of the devaddr (5 bits device address) + * and the regAddr (16 bits phy register): phyReg = (devaddr << 16) | regAddr. + */ +void ENET_StartExtC45SMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg); + +/*! + * @brief Starts the extended IEEE802.3 Clause 45 MDIO format SMI write command. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param phyReg The PHY register. For MDIO IEEE802.3 Clause 45, + * the phyReg is a 21-bits combination of the devaddr (5 bits device address) + * and the regAddr (16 bits phy register): phyReg = (devaddr << 16) | regAddr. + * @param data The data written to PHY. + */ +void ENET_StartExtC45SMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data); +#endif /* FSL_FEATURE_ENET_HAS_EXTEND_MDIO */ + /* @} */ /*! @@ -721,7 +766,7 @@ void ENET_LeaveMulticastGroup(ENET_Type *base, uint8_t *address); /* @} */ /*! - * @name Other basic operation + * @name Other basic operations * @{ */ @@ -762,13 +807,13 @@ static inline void ENET_EnableSleepMode(ENET_Type *base, bool enable) } /*! - * @brief Gets ENET transmit and receive accelerator functions from MAC controller. + * @brief Gets ENET transmit and receive accelerator functions from the MAC controller. * * @param base ENET peripheral base address. * @param txAccelOption The transmit accelerator option. The "enet_tx_accelerator_t" is - * recommended to be used to as the mask to get the exact the accelerator option. + * recommended as the mask to get the exact the accelerator option. * @param rxAccelOption The receive accelerator option. The "enet_rx_accelerator_t" is - * recommended to be used to as the mask to get the exact the accelerator option. + * recommended as the mask to get the exact the accelerator option. */ static inline void ENET_GetAccelFunction(ENET_Type *base, uint32_t *txAccelOption, uint32_t *rxAccelOption) { @@ -782,7 +827,7 @@ static inline void ENET_GetAccelFunction(ENET_Type *base, uint32_t *txAccelOptio /* @} */ /*! - * @name Interrupts. + * @name Interrupts * @{ */ @@ -791,7 +836,7 @@ static inline void ENET_GetAccelFunction(ENET_Type *base, uint32_t *txAccelOptio * * This function enables the ENET interrupt according to the provided mask. The mask * is a logical OR of enumeration members. See @ref enet_interrupt_enable_t. - * For example, to enable the TX frame interrupt and RX frame interrupt, do this: + * For example, to enable the TX frame interrupt and RX frame interrupt, do the following. * @code * ENET_EnableInterrupts(ENET, kENET_TxFrameInterrupt | kENET_RxFrameInterrupt); * @endcode @@ -810,7 +855,7 @@ static inline void ENET_EnableInterrupts(ENET_Type *base, uint32_t mask) * * This function disables the ENET interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref enet_interrupt_enable_t. - * For example, to disable the TX frame interrupt and RX frame interrupt, do this: + * For example, to disable the TX frame interrupt and RX frame interrupt, do the following. * @code * ENET_DisableInterrupts(ENET, kENET_TxFrameInterrupt | kENET_RxFrameInterrupt); * @endcode @@ -841,7 +886,7 @@ static inline uint32_t ENET_GetInterruptStatus(ENET_Type *base) * * This function clears enabled ENET interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See the @ref enet_interrupt_enable_t. - * For example, to clear the TX frame interrupt and RX frame interrupt, do this: + * For example, to clear the TX frame interrupt and RX frame interrupt, do the following. * @code * ENET_ClearInterruptStatus(ENET, kENET_TxFrameInterrupt | kENET_RxFrameInterrupt); * @endcode @@ -863,8 +908,8 @@ static inline void ENET_ClearInterruptStatus(ENET_Type *base, uint32_t mask) */ /*! - * @brief Set the callback function. - * This API is provided for application callback required case when ENET + * @brief Sets the callback function. + * This API is provided for the application callback required case when ENET * interrupt is enabled. This API should be called after calling ENET_Init. * * @param handle ENET handler pointer. Should be provided by application. @@ -879,7 +924,7 @@ void ENET_SetCallback(enet_handle_t *handle, enet_callback_t callback, void *use * This API must be called after the ENET_GetRxFrameSize and before the ENET_ReadFrame(). * If the ENET_GetRxFrameSize returns kStatus_ENET_RxFrameError, * the ENET_GetRxErrBeforeReadFrame can be used to get the exact error statistics. - * For example: + * This is an example. * @code * status = ENET_GetRxFrameSize(&g_handle, &length); * if (status == kStatus_ENET_RxFrameError) @@ -911,29 +956,54 @@ void ENET_GetRxErrBeforeReadFrame(enet_handle_t *handle, enet_data_error_stats_t */ status_t ENET_GetTxErrAfterSendFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic); #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ - /*! - * @brief Gets the size of the read frame. - * This function reads a received frame size from the ENET buffer descriptors. - * @note The FCS of the frame is removed by MAC controller and the size is the length without the FCS. - * After calling ENET_GetRxFrameSize, ENET_ReadFrame() should be called to update the - * receive buffers If the result is not "kStatus_ENET_RxFrameEmpty". - * - * @param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init. - * @param length The length of the valid frame received. - * @retval kStatus_ENET_RxFrameEmpty No frame received. Should not call ENET_ReadFrame to read frame. - * @retval kStatus_ENET_RxFrameError Data error happens. ENET_ReadFrame should be called with NULL data - * and NULL length to update the receive buffers. - * @retval kStatus_Success Receive a frame Successfully then the ENET_ReadFrame - * should be called with the right data buffer and the captured data length input. - */ +/*! +* @brief Gets the size of the read frame. +* This function gets a received frame size from the ENET buffer descriptors. +* @note The FCS of the frame is automatically removed by Mac and the size is the length without the FCS. +* After calling ENET_GetRxFrameSize, ENET_ReadFrame() should be called to update the +* receive buffers If the result is not "kStatus_ENET_RxFrameEmpty". +* +* @param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init. +* @param length The length of the valid frame received. +* @retval kStatus_ENET_RxFrameEmpty No frame received. Should not call ENET_ReadFrame to read frame. +* @retval kStatus_ENET_RxFrameError Data error happens. ENET_ReadFrame should be called with NULL data +* and NULL length to update the receive buffers. +* @retval kStatus_Success Receive a frame Successfully then the ENET_ReadFrame +* should be called with the right data buffer and the captured data length input. +*/ status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length); /*! * @brief Reads a frame from the ENET device. * This function reads a frame (both the data and the length) from the ENET buffer descriptors. * The ENET_GetRxFrameSize should be used to get the size of the prepared data buffer. - * @note The FCS of the frame is removed by MAC controller and is not delivered to the application. - * + * This is an example. + * @code + * uint32_t length; + * enet_handle_t g_handle; + * //Get the received frame size firstly. + * status = ENET_GetRxFrameSize(&g_handle, &length); + * if (length != 0) + * { + * //Allocate memory here with the size of "length" + * uint8_t *data = memory allocate interface; + * if (!data) + * { + * ENET_ReadFrame(ENET, &g_handle, NULL, 0); + * //Add the console warning log. + * } + * else + * { + * status = ENET_ReadFrame(ENET, &g_handle, data, length); + * //Call stack input API to deliver the data to stack + * } + * } + * else if (status == kStatus_ENET_RxFrameError) + * { + * //Update the received buffer when a error frame is received. + * ENET_ReadFrame(ENET, &g_handle, NULL, 0); + * } + * @endcode * @param base ENET peripheral base address. * @param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init. * @param data The data buffer provided by user to store the frame which memory size should be at least "length". @@ -952,8 +1022,10 @@ status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, u * @param data The data buffer provided by user to be send. * @param length The length of the data to be send. * @retval kStatus_Success Send frame succeed. - * @retval kStatus_ENET_TxFrameBusy Transmit buffer descriptor is busy under transmit. - * @retval kStatus_ENET_TxFrameFail Transmit frame fail. + * @retval kStatus_ENET_TxFrameBusy Transmit buffer descriptor is busy under transmission. + * The transmit busy happens when the data send rate is over the MAC capacity. + * The waiting mechanism is recommended to be added after each call return with + * kStatus_ENET_TxFrameBusy. */ status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length); @@ -981,6 +1053,14 @@ void ENET_ReceiveIRQHandler(ENET_Type *base, enet_handle_t *handle); */ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle); +/*! + * @brief the common IRQ handler for the tx/rx/error etc irq handler. + * + * This is used for the combined tx/rx/error interrupt for single ring (ring 0). + * + * @param base ENET peripheral base address. + */ +void ENET_CommonFrame0IRQHandler(ENET_Type *base); /* @} */ #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE @@ -990,7 +1070,7 @@ void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle); */ /*! - * @brief Configures the ENET PTP 1588 feature with the basic configuration. + * @brief Configures the ENET PTP IEEE 1588 feature with the basic configuration. * The function sets the clock for PTP 1588 timer and enables * time stamp interrupts and transmit interrupts for PTP 1588 features. * This API should be called when the 1588 feature is enabled @@ -1044,7 +1124,7 @@ static inline void ENET_Ptp1588StopTimer(ENET_Type *base) void ENET_Ptp1588AdjustTimer(ENET_Type *base, uint32_t corrIncrease, uint32_t corrPeriod); /*! - * @brief Sets ENET PTP 1588 timer channel mode. + * @brief Sets the ENET PTP 1588 timer channel mode. * * @param base ENET peripheral base address. * @param channel The ENET PTP timer channel number. @@ -1064,8 +1144,55 @@ static inline void ENET_Ptp1588SetChannelMode(ENET_Type *base, base->CHANNEL[channel].TCSR = tcrReg; } +#if defined(FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL) && FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL +/*! + * @brief Sets ENET PTP 1588 timer channel mode pulse width. + * + * For the input "mode" in ENET_Ptp1588SetChannelMode, the kENET_PtpChannelPulseLowonCompare + * kENET_PtpChannelPulseHighonCompare only support the pulse width for one 1588 clock. + * this function is extended for control the pulse width from 1 to 32 1588 clock cycles. + * so call this function if you need to set the timer channel mode for + * kENET_PtpChannelPulseLowonCompare or kENET_PtpChannelPulseHighonCompare + * with pulse width more than one 1588 clock, + * + * @param base ENET peripheral base address. + * @param channel The ENET PTP timer channel number. + * @param isOutputLow True --- timer channel is configured for output compare + * pulse output low. + * false --- timer channel is configured for output compare + * pulse output high. + * @param pulseWidth The pulse width control value, range from 0 ~ 31. + * 0 --- pulse width is one 1588 clock cycle. + * 31 --- pulse width is thirty two 1588 clock cycles. + * @param intEnable Enables or disables the interrupt. + */ +static inline void ENET_Ptp1588SetChannelOutputPulseWidth(ENET_Type *base, + enet_ptp_timer_channel_t channel, + bool isOutputLow, + uint8_t pulseWidth, + bool intEnable) +{ + uint32_t tcrReg; + + tcrReg = ENET_TCSR_TIE(intEnable) | ENET_TCSR_TPWC(pulseWidth); + + if (isOutputLow) + { + tcrReg |= ENET_TCSR_TMODE(kENET_PtpChannelPulseLowonCompare); + } + else + { + tcrReg |= ENET_TCSR_TMODE(kENET_PtpChannelPulseHighonCompare); + } + + /* Disable channel mode first. */ + base->CHANNEL[channel].TCSR = 0; + base->CHANNEL[channel].TCSR = tcrReg; +} +#endif /* FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL */ + /*! - * @brief Sets ENET PTP 1588 timer channel comparison value. + * @brief Sets the ENET PTP 1588 timer channel comparison value. * * @param base ENET peripheral base address. * @param channel The PTP timer channel, see "enet_ptp_timer_channel_t". diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c index 1a71a07e582..f22eff941e9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -40,7 +40,12 @@ void EWM_Init(EWM_Type *base, const ewm_config_t *config) uint32_t value = 0U; +#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \ + (defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE)) +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Ewm0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +#endif value = EWM_CTRL_EWMEN(config->enableEwm) | EWM_CTRL_ASSIN(config->setInputAssertLogic) | EWM_CTRL_INEN(config->enableEwmInput) | EWM_CTRL_INTEN(config->enableInterrupt); #if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER @@ -59,7 +64,12 @@ void EWM_Init(EWM_Type *base, const ewm_config_t *config) void EWM_Deinit(EWM_Type *base) { EWM_DisableInterrupts(base, kEWM_InterruptEnable); +#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \ + (defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE)) +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(kCLOCK_Ewm0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +#endif /* FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE */ } void EWM_GetDefaultConfig(ewm_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h index a5c45b3fe76..aa32ed3c713 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ewm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup ewm_driver + * @addtogroup ewm * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -49,14 +48,14 @@ #define FSL_EWM_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ -/*! @brief Describes ewm clock source. */ +/*! @brief Describes EWM clock source. */ #if defined(FSL_FEATURE_EWM_HAS_CLOCK_SELECT) && FSL_FEATURE_EWM_HAS_CLOCK_SELECT typedef enum _ewm_lpo_clock_source { - kEWM_LpoClockSource0 = 0U, /*!< ewm clock sourced from lpo_clk[0]*/ - kEWM_LpoClockSource1 = 1U, /*!< ewm clock sourced from lpo_clk[1]*/ - kEWM_LpoClockSource2 = 2U, /*!< ewm clock sourced from lpo_clk[2]*/ - kEWM_LpoClockSource3 = 3U, /*!< ewm clock sourced from lpo_clk[3]*/ + kEWM_LpoClockSource0 = 0U, /*!< EWM clock sourced from lpo_clk[0]*/ + kEWM_LpoClockSource1 = 1U, /*!< EWM clock sourced from lpo_clk[1]*/ + kEWM_LpoClockSource2 = 2U, /*!< EWM clock sourced from lpo_clk[2]*/ + kEWM_LpoClockSource3 = 3U, /*!< EWM clock sourced from lpo_clk[3]*/ } ewm_lpo_clock_source_t; #endif /* FSL_FEATURE_EWM_HAS_CLOCK_SELECT */ @@ -77,18 +76,18 @@ typedef struct _ewm_config #if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER uint8_t prescaler; /*!< Clock prescaler value */ #endif /* FSL_FEATURE_EWM_HAS_PRESCALER */ - uint8_t compareLowValue; /*!< Compare low register value */ - uint8_t compareHighValue; /*!< Compare high register value */ + uint8_t compareLowValue; /*!< Compare low-register value */ + uint8_t compareHighValue; /*!< Compare high-register value */ } ewm_config_t; /*! - * @brief EWM interrupt configuration structure, default settings all disabled. + * @brief EWM interrupt configuration structure with default settings all disabled. * - * This structure contains the settings for all of the EWM interrupt configurations. + * This structure contains the settings for all of EWM interrupt configurations. */ enum _ewm_interrupt_enable_t { - kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable EWM to generate an interrupt*/ + kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable the EWM to generate an interrupt*/ }; /*! @@ -98,7 +97,7 @@ enum _ewm_interrupt_enable_t */ enum _ewm_status_flags_t { - kEWM_RunningFlag = EWM_CTRL_EWMEN_MASK, /*!< Running flag, set when ewm is enabled*/ + kEWM_RunningFlag = EWM_CTRL_EWMEN_MASK, /*!< Running flag, set when EWM is enabled*/ }; /******************************************************************************* @@ -110,7 +109,7 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name EWM Initialization and De-initialization + * @name EWM initialization and de-initialization * @{ */ @@ -119,10 +118,10 @@ extern "C" { * * This function is used to initialize the EWM. After calling, the EWM * runs immediately according to the configuration. - * Note that except for interrupt enable control bit, other control bits and registers are write once after a + * Note that, except for the interrupt enable control bit, other control bits and registers are write once after a * CPU reset. Modifying them more than once generates a bus transfer error. * - * Example: + * This is an example. * @code * ewm_config_t config; * EWM_GetDefaultConfig(&config); @@ -131,7 +130,7 @@ extern "C" { * @endcode * * @param base EWM peripheral base address - * @param config The configuration of EWM + * @param config The configuration of the EWM */ void EWM_Init(EWM_Type *base, const ewm_config_t *config); @@ -147,8 +146,8 @@ void EWM_Deinit(EWM_Type *base); /*! * @brief Initializes the EWM configuration structure. * - * This function initializes the EWM configure structure to default values. The default - * values are: + * This function initializes the EWM configuration structure to default values. The default + * values are as follows. * @code * ewmConfig->enableEwm = true; * ewmConfig->enableEwmInput = false; @@ -160,7 +159,7 @@ void EWM_Deinit(EWM_Type *base); * ewmConfig->compareHighValue = 0xFEU; * @endcode * - * @param config Pointer to EWM configuration structure. + * @param config Pointer to the EWM configuration structure. * @see ewm_config_t */ void EWM_GetDefaultConfig(ewm_config_t *config); @@ -179,7 +178,7 @@ void EWM_GetDefaultConfig(ewm_config_t *config); * * @param base EWM peripheral base address * @param mask The interrupts to enable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined * @arg kEWM_InterruptEnable */ static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask) @@ -194,7 +193,7 @@ static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask) * * @param base EWM peripheral base address * @param mask The interrupts to disable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined * @arg kEWM_InterruptEnable */ static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask) @@ -203,19 +202,19 @@ static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask) } /*! - * @brief Gets EWM all status flags. + * @brief Gets all status flags. * * This function gets all status flags. * - * Example for getting Running Flag: + * This is an example for getting the running flag. * @code * uint32_t status; * status = EWM_GetStatusFlags(ewm_base) & kEWM_RunningFlag; * @endcode * @param base EWM peripheral base address * @return State of the status flag: asserted (true) or not-asserted (false).@see _ewm_status_flags_t - * - true: related status flag has been set. - * - false: related status flag is not set. + * - True: a related status flag has been set. + * - False: a related status flag is not set. */ static inline uint32_t EWM_GetStatusFlags(EWM_Type *base) { @@ -223,9 +222,9 @@ static inline uint32_t EWM_GetStatusFlags(EWM_Type *base) } /*! - * @brief Service EWM. + * @brief Services the EWM. * - * This function reset EWM counter to zero. + * This function resets the EWM counter to zero. * * @param base EWM peripheral base address */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c index 2add4e96352..f63e6c98145 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,6 +38,7 @@ * @name Misc utility defines * @{ */ +/*! @brief Alignment utility. */ #ifndef ALIGN_DOWN #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a)))) #endif @@ -45,18 +46,74 @@ #define ALIGN_UP(x, a) (-((int32_t)((uint32_t)(-((int32_t)(x))) & (uint32_t)(-((int32_t)(a)))))) #endif -#define BYTES_JOIN_TO_WORD_1_3(x, y) ((((uint32_t)(x)&0xFFU) << 24) | ((uint32_t)(y)&0xFFFFFFU)) -#define BYTES_JOIN_TO_WORD_2_2(x, y) ((((uint32_t)(x)&0xFFFFU) << 16) | ((uint32_t)(y)&0xFFFFU)) -#define BYTES_JOIN_TO_WORD_3_1(x, y) ((((uint32_t)(x)&0xFFFFFFU) << 8) | ((uint32_t)(y)&0xFFU)) -#define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFU) << 16) | ((uint32_t)(z)&0xFFFFU)) -#define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFFFU) << 8) | ((uint32_t)(z)&0xFFU)) -#define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) \ - ((((uint32_t)(x)&0xFFFFU) << 16) | (((uint32_t)(y)&0xFFU) << 8) | ((uint32_t)(z)&0xFFU)) -#define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFU) << 16) | (((uint32_t)(z)&0xFFU) << 8) | \ - ((uint32_t)(w)&0xFFU)) +/*! @brief Join bytes to word utility. */ +#define B1P4(b) (((uint32_t)(b)&0xFFU) << 24) +#define B1P3(b) (((uint32_t)(b)&0xFFU) << 16) +#define B1P2(b) (((uint32_t)(b)&0xFFU) << 8) +#define B1P1(b) ((uint32_t)(b)&0xFFU) +#define B2P3(b) (((uint32_t)(b)&0xFFFFU) << 16) +#define B2P2(b) (((uint32_t)(b)&0xFFFFU) << 8) +#define B2P1(b) ((uint32_t)(b)&0xFFFFU) +#define B3P2(b) (((uint32_t)(b)&0xFFFFFFU) << 8) +#define B3P1(b) ((uint32_t)(b)&0xFFFFFFU) +#define BYTES_JOIN_TO_WORD_1_3(x, y) (B1P4(x) | B3P1(y)) +#define BYTES_JOIN_TO_WORD_2_2(x, y) (B2P3(x) | B2P1(y)) +#define BYTES_JOIN_TO_WORD_3_1(x, y) (B3P2(x) | B1P1(y)) +#define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) (B1P4(x) | B1P3(y) | B2P1(z)) +#define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) (B1P4(x) | B2P2(y) | B1P1(z)) +#define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) (B2P3(x) | B1P2(y) | B1P1(z)) +#define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) (B1P4(x) | B1P3(y) | B1P2(z) | B1P1(w)) +/*@}*/ + +/*! + * @name Secondary flash configuration + * @{ + */ +/*! @brief Indicates whether the secondary flash has its own protection register in flash module. */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FPROTS_PROTS_MASK) +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (1) +#else +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (0) +#endif + +/*! @brief Indicates whether the secondary flash has its own Execute-Only access register in flash module. */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FACSSS_SGSIZE_S_MASK) +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (1) +#else +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (0) +#endif +/*@}*/ + +/*! + * @name Flash cache ands speculation control defines + * @{ + */ +#if defined(MCM_PLACR_CFCC_MASK) || defined(MCM_CPCR2_CCBC_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0) +#endif +#if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0) +#endif +#if defined(MCM_PLACR_DFCS_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0) +#endif +#if defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR_OCMC1_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (0) +#endif +#if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \ + defined(FMC_PFB01CR_S_B_INV_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0) +#endif /*@}*/ /*! @brief Data flash IFR map Field*/ @@ -121,6 +178,7 @@ #define FTFx_ERASE_BLOCK 0x08U /*!< ERSBLK*/ #define FTFx_ERASE_SECTOR 0x09U /*!< ERSSCR*/ #define FTFx_PROGRAM_SECTION 0x0BU /*!< PGMSEC*/ +#define FTFx_GENERATE_CRC 0x0CU /*!< CRCGEN*/ #define FTFx_VERIFY_ALL_BLOCK 0x40U /*!< RD1ALL*/ #define FTFx_READ_ONCE 0x41U /*!< RDONCE or RDINDEX*/ #define FTFx_PROGRAM_ONCE 0x43U /*!< PGMONCE or PGMINDEX*/ @@ -192,19 +250,56 @@ /*@}*/ /*! - * @brief Enumeration for access segment property. + * @name Common flash register access info defines + * @{ */ -enum _flash_access_segment_property -{ - kFLASH_accessSegmentBase = 256UL, -}; +#define FTFx_FCCOB3_REG (FTFx->FCCOB3) +#define FTFx_FCCOB5_REG (FTFx->FCCOB5) +#define FTFx_FCCOB6_REG (FTFx->FCCOB6) +#define FTFx_FCCOB7_REG (FTFx->FCCOB7) + +#if defined(FTFA_FPROTH0_PROT_MASK) || defined(FTFE_FPROTH0_PROT_MASK) || defined(FTFL_FPROTH0_PROT_MASK) +#define FTFx_FPROT_HIGH_REG (FTFx->FPROTH3) +#define FTFx_FPROTH3_REG (FTFx->FPROTH3) +#define FTFx_FPROTH2_REG (FTFx->FPROTH2) +#define FTFx_FPROTH1_REG (FTFx->FPROTH1) +#define FTFx_FPROTH0_REG (FTFx->FPROTH0) +#endif + +#if defined(FTFA_FPROTL0_PROT_MASK) || defined(FTFE_FPROTL0_PROT_MASK) || defined(FTFL_FPROTL0_PROT_MASK) +#define FTFx_FPROT_LOW_REG (FTFx->FPROTL3) +#define FTFx_FPROTL3_REG (FTFx->FPROTL3) +#define FTFx_FPROTL2_REG (FTFx->FPROTL2) +#define FTFx_FPROTL1_REG (FTFx->FPROTL1) +#define FTFx_FPROTL0_REG (FTFx->FPROTL0) +#elif defined(FTFA_FPROT0_PROT_MASK) || defined(FTFE_FPROT0_PROT_MASK) || defined(FTFL_FPROT0_PROT_MASK) +#define FTFx_FPROT_LOW_REG (FTFx->FPROT3) +#define FTFx_FPROTL3_REG (FTFx->FPROT3) +#define FTFx_FPROTL2_REG (FTFx->FPROT2) +#define FTFx_FPROTL1_REG (FTFx->FPROT1) +#define FTFx_FPROTL0_REG (FTFx->FPROT0) +#endif + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER +#define FTFx_FPROTSH_REG (FTFx->FPROTSH) +#define FTFx_FPROTSL_REG (FTFx->FPROTSL) +#endif + +#define FTFx_XACCH3_REG (FTFx->XACCH3) +#define FTFx_XACCL3_REG (FTFx->XACCL3) + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER +#define FTFx_XACCSH_REG (FTFx->XACCSH) +#define FTFx_XACCSL_REG (FTFx->XACCSL) +#endif +/*@}*/ /*! - * @brief Enumeration for acceleration ram property. + * @brief Enumeration for access segment property. */ -enum _flash_acceleration_ram_property +enum _flash_access_segment_property { - kFLASH_accelerationRamSize = 0x400U + kFLASH_AccessSegmentBase = 256UL, }; /*! @@ -212,25 +307,78 @@ enum _flash_acceleration_ram_property */ enum _flash_config_area_range { - kFLASH_configAreaStart = 0x400U, - kFLASH_configAreaEnd = 0x40FU + kFLASH_ConfigAreaStart = 0x400U, + kFLASH_ConfigAreaEnd = 0x40FU }; -/*! @brief program Flash block base address*/ -#define PFLASH_BLOCK_BASE 0x00U - -/*! @brief Total flash region count*/ -#define FSL_FEATURE_FTFx_REGION_COUNT (32U) - /*! * @name Flash register access type defines * @{ */ -#if FLASH_DRIVER_IS_FLASH_RESIDENT -#define FTFx_REG_ACCESS_TYPE volatile uint8_t * +#define FTFx_REG8_ACCESS_TYPE volatile uint8_t * #define FTFx_REG32_ACCESS_TYPE volatile uint32_t * -#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ - /*@}*/ +/*@}*/ + +/*! + * @brief MCM cache register access info defines. + */ +#if defined(MCM_PLACR_CFCC_MASK) +#define MCM_CACHE_CLEAR_MASK MCM_PLACR_CFCC_MASK +#define MCM_CACHE_CLEAR_SHIFT MCM_PLACR_CFCC_SHIFT +#if defined(MCM) +#define MCM0_CACHE_REG MCM->PLACR +#elif defined(MCM0) +#define MCM0_CACHE_REG MCM0->PLACR +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->PLACR +#endif +#elif defined(MCM_CPCR2_CCBC_MASK) +#define MCM_CACHE_CLEAR_MASK MCM_CPCR2_CCBC_MASK +#define MCM_CACHE_CLEAR_SHIFT MCM_CPCR2_CCBC_SHIFT +#if defined(MCM) +#define MCM0_CACHE_REG MCM->CPCR2 +#elif defined(MCM0) +#define MCM0_CACHE_REG MCM0->CPCR2 +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->CPCR2 +#endif +#endif + +/*! + * @brief MSCM cache register access info defines. + */ +#if defined(MSCM_OCMDR_OCM1_MASK) +#define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCM1_MASK +#define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCM1_SHIFT +#define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCM1(x) +#elif defined(MSCM_OCMDR_OCMC1_MASK) +#define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCMC1_MASK +#define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCMC1_SHIFT +#define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCMC1(x) +#endif + +/*! + * @brief MSCM prefetch speculation defines. + */ +#define MSCM_OCMDR_OCMC1_DFDS_MASK (0x10U) +#define MSCM_OCMDR_OCMC1_DFCS_MASK (0x20U) + +#define MSCM_OCMDR_OCMC1_DFDS_SHIFT (4U) +#define MSCM_OCMDR_OCMC1_DFCS_SHIFT (5U) + +/*! + * @brief Flash size encoding rule. + */ +#define FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2 (0x00U) +#define FLASH_MEMORY_SIZE_ENCODING_RULE_K3 (0x01U) + +#if defined(K32W042S1M2_M0P_SERIES) || defined(K32W042S1M2_M4_SERIES) +#define FLASH_MEMORY_SIZE_ENCODING_RULE (FLASH_MEMORY_SIZE_ENCODING_RULE_K3) +#else +#define FLASH_MEMORY_SIZE_ENCODING_RULE (FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2) +#endif /******************************************************************************* * Prototypes @@ -238,9 +386,9 @@ enum _flash_config_area_range #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief Copy flash_run_command() to RAM*/ -static void copy_flash_run_command(uint8_t *flashRunCommand); +static void copy_flash_run_command(uint32_t *flashRunCommand); /*! @brief Copy flash_cache_clear_command() to RAM*/ -static void copy_flash_cache_clear_command(uint8_t *flashCacheClearCommand); +static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation); /*! @brief Check whether flash execute-in-ram functions are ready*/ static status_t flash_check_execute_in_ram_function_info(flash_config_t *config); #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ @@ -251,6 +399,9 @@ static status_t flash_command_sequence(flash_config_t *config); /*! @brief Perform the cache clear to the flash*/ void flash_cache_clear(flash_config_t *config); +/*! @brief Process the cache to the flash*/ +static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process); + /*! @brief Validates the range and alignment of the given address range.*/ static status_t flash_check_range(flash_config_t *config, uint32_t startAddress, @@ -291,44 +442,131 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option); #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ +/*! @brief Gets the flash protection information (region size, region count).*/ +static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info); + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/ +static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info); +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(flash_config_t *config); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(void); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM +/*! @brief Sets the prefetch speculation buffer to the flash by MSCM.*/ +void mscm_flash_prefetch_speculation_enable(bool enable); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC +/*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ +void fmc_flash_prefetch_speculation_clear(void); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ + /******************************************************************************* * Variables ******************************************************************************/ /*! @brief Access to FTFx->FCCOB */ -#if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFA->FCCOB3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFE->FCCOB3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFL->FCCOB3; -#else -#error "Unknown flash controller" +volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFx_FCCOB3_REG; +/*! @brief Access to FTFx->FPROT */ +volatile uint32_t *const kFPROTL = (volatile uint32_t *)&FTFx_FPROT_LOW_REG; +#if defined(FTFx_FPROT_HIGH_REG) +volatile uint32_t *const kFPROTH = (volatile uint32_t *)&FTFx_FPROT_HIGH_REG; #endif -/*! @brief Access to FTFx->FPROT */ -#if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFA->FPROT3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFE->FPROT3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFL->FPROT3; -#else -#error "Unknown flash controller" +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER +volatile uint8_t *const kFPROTSL = (volatile uint8_t *)&FTFx_FPROTSL_REG; +volatile uint8_t *const kFPROTSH = (volatile uint8_t *)&FTFx_FPROTSH_REG; #endif #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief A function pointer used to point to relocated flash_run_command() */ -static void (*callFlashRunCommand)(FTFx_REG_ACCESS_TYPE ftfx_fstat); -/*! @brief A function pointer used to point to relocated flash_cache_clear_command() */ -static void (*callFlashCacheClearCommand)(FTFx_REG32_ACCESS_TYPE ftfx_reg); +static void (*callFlashRunCommand)(FTFx_REG8_ACCESS_TYPE ftfx_fstat); +/*! @brief A function pointer used to point to relocated flash_common_bit_operation() */ +static void (*callFlashCommonBitOperation)(FTFx_REG32_ACCESS_TYPE base, + uint32_t bitMask, + uint32_t bitShift, + uint32_t bitValue); + +/*! + * @brief Position independent code of flash_run_command() + * + * Note1: The prototype of C function is shown as below: + * @code + * void flash_run_command(FTFx_REG8_ACCESS_TYPE ftfx_fstat) + * { + * // clear CCIF bit + * *ftfx_fstat = FTFx_FSTAT_CCIF_MASK; + * + * // Check CCIF bit of the flash status register, wait till it is set. + * // IP team indicates that this loop will always complete. + * while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK)) + * { + * } + * } + * @endcode + * Note2: The binary code is generated by IAR 7.70.1 + */ +const static uint16_t s_flashRunCommandFunctionCode[] = { + 0x2180, /* MOVS R1, #128 ; 0x80 */ + 0x7001, /* STRB R1, [R0] */ + /* @4: */ + 0x7802, /* LDRB R2, [R0] */ + 0x420a, /* TST R2, R1 */ + 0xd0fc, /* BEQ.N @4 */ + 0x4770 /* BX LR */ +}; + +/*! + * @brief Position independent code of flash_common_bit_operation() + * + * Note1: The prototype of C function is shown as below: + * @code + * void flash_common_bit_operation(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t + * bitValue) + * { + * if (bitMask) + * { + * uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift)) & bitMask); + * *base = (*base & (~bitMask)) | value; + * } + * + * __ISB(); + * __DSB(); + * } + * @endcode + * Note2: The binary code is generated by IAR 7.70.1 + */ +const static uint16_t s_flashCommonBitOperationFunctionCode[] = { + 0xb510, /* PUSH {R4, LR} */ + 0x2900, /* CMP R1, #0 */ + 0xd005, /* BEQ.N @12 */ + 0x6804, /* LDR R4, [R0] */ + 0x438c, /* BICS R4, R4, R1 */ + 0x4093, /* LSLS R3, R3, R2 */ + 0x4019, /* ANDS R1, R1, R3 */ + 0x4321, /* ORRS R1, R1, R4 */ + 0x6001, /* STR R1, [R0] */ + /* @12: */ + 0xf3bf, 0x8f6f, /* ISB */ + 0xf3bf, 0x8f4f, /* DSB */ + 0xbd10 /* POP {R4, PC} */ +}; #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED) /*! @brief A static buffer used to hold flash_run_command() */ -static uint8_t s_flashRunCommand[kFLASH_executeInRamFunctionMaxSize]; -/*! @brief A static buffer used to hold flash_cache_clear_command() */ -static uint8_t s_flashCacheClearCommand[kFLASH_executeInRamFunctionMaxSize]; +static uint32_t s_flashRunCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; +/*! @brief A static buffer used to hold flash_common_bit_operation() */ +static uint32_t s_flashCommonBitOperation[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; /*! @brief Flash execute-in-ram function information */ static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo; #endif @@ -351,6 +589,7 @@ static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo; * flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; * @endcode */ +#if (FLASH_MEMORY_SIZE_ENCODING_RULE == FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2) const uint16_t kPFlashDensities[] = { 8, /* 0x0 - 8192, 8KB */ 16, /* 0x1 - 16384, 16KB */ @@ -369,6 +608,26 @@ const uint16_t kPFlashDensities[] = { 1536, /* 0xe - 1572864, 1.5MB */ /* 2048, 0xf - 2097152, 2MB */ }; +#elif(FLASH_MEMORY_SIZE_ENCODING_RULE == FLASH_MEMORY_SIZE_ENCODING_RULE_K3) +const uint16_t kPFlashDensities[] = { + 0, /* 0x0 - undefined */ + 0, /* 0x1 - undefined */ + 0, /* 0x2 - undefined */ + 0, /* 0x3 - undefined */ + 0, /* 0x4 - undefined */ + 0, /* 0x5 - undefined */ + 0, /* 0x6 - undefined */ + 0, /* 0x7 - undefined */ + 0, /* 0x8 - undefined */ + 0, /* 0x9 - undefined */ + 256, /* 0xa - 262144, 256KB */ + 0, /* 0xb - undefined */ + 1024, /* 0xc - 1048576, 1MB */ + 0, /* 0xd - undefined */ + 0, /* 0xe - undefined */ + 0, /* 0xf - undefined */ +}; +#endif /******************************************************************************* * Code @@ -376,39 +635,86 @@ const uint16_t kPFlashDensities[] = { status_t FLASH_Init(flash_config_t *config) { - uint32_t flashDensity; - if (config == NULL) { return kStatus_FLASH_InvalidArgument; } - /* calculate the flash density from SIM_FCFG1.PFSIZE */ - uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; - /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed. - * We just use the pre-defined flash size in feature file here to support pre-production parts */ - if (pfsize == 0xf) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - flashDensity = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE; +/* calculate the flash density from SIM_FCFG1.PFSIZE */ +#if defined(SIM_FCFG1_CORE1_PFSIZE_MASK) + uint32_t flashDensity; + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE1_PFSIZE_MASK) >> SIM_FCFG1_CORE1_PFSIZE_SHIFT; + if (pfsize == 0xf) + { + flashDensity = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + } + config->PFlashTotalSize = flashDensity; +#else + /* Unused code to solve MISRA-C issue*/ + config->PFlashBlockBase = kPFlashDensities[0]; + config->PFlashTotalSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; +#endif + config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS; + config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT; + config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE; } else +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ { - flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; - } + uint32_t flashDensity; + +/* calculate the flash density from SIM_FCFG1.PFSIZE */ +#if defined(SIM_FCFG1_CORE0_PFSIZE_MASK) + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE0_PFSIZE_MASK) >> SIM_FCFG1_CORE0_PFSIZE_SHIFT; +#elif defined(SIM_FCFG1_PFSIZE_MASK) + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; +#else +#error "Unknown flash size" +#endif + /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed. + * We just use the pre-defined flash size in feature file here to support pre-production parts */ + if (pfsize == 0xf) + { + flashDensity = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + } - /* fill out a few of the structure members */ - config->PFlashBlockBase = PFLASH_BLOCK_BASE; - config->PFlashTotalSize = flashDensity; - config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; - config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; + /* fill out a few of the structure members */ + config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; + config->PFlashTotalSize = flashDensity; + config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; + config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; + } + { #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL - config->PFlashAccessSegmentSize = kFLASH_accessSegmentBase << FTFx->FACSS; - config->PFlashAccessSegmentCount = FTFx->FACSN; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSSS; + config->PFlashAccessSegmentCount = FTFx->FACSNS; + } + else +#endif + { + config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSS; + config->PFlashAccessSegmentCount = FTFx->FACSN; + } #else - config->PFlashAccessSegmentSize = 0; - config->PFlashAccessSegmentCount = 0; + config->PFlashAccessSegmentSize = 0; + config->PFlashAccessSegmentCount = 0; #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + } config->PFlashCallback = NULL; @@ -418,7 +724,7 @@ status_t FLASH_Init(flash_config_t *config) { s_flashExecuteInRamFunctionInfo.activeFunctionCount = 0; s_flashExecuteInRamFunctionInfo.flashRunCommand = s_flashRunCommand; - s_flashExecuteInRamFunctionInfo.flashCacheClearCommand = s_flashCacheClearCommand; + s_flashExecuteInRamFunctionInfo.flashCommonBitOperation = s_flashCommonBitOperation; config->flashExecuteInRamFunctionInfo = &s_flashExecuteInRamFunctionInfo.activeFunctionCount; FLASH_PrepareExecuteInRamFunctions(config); } @@ -467,8 +773,8 @@ status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config) flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo; copy_flash_run_command(flashExecuteInRamFunctionInfo->flashRunCommand); - copy_flash_cache_clear_command(flashExecuteInRamFunctionInfo->flashCacheClearCommand); - flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_executeInRamFunctionTotalNum; + copy_flash_common_bit_operation(flashExecuteInRamFunctionInfo->flashCommonBitOperation); + flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_ExecuteInRamFunctionTotalNum; return kStatus_FLASH_Success; } @@ -493,6 +799,8 @@ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -513,22 +821,29 @@ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key) { uint32_t sectorSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; uint32_t endAddress; /* storing end address */ uint32_t numberOfSectors; /* number of sectors calculated by endAddress */ status_t returnCode; - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectorCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment); + if (returnCode) + { + return returnCode; + } + + /* Validate the user key */ + returnCode = flash_check_user_key(key); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; - sectorSize = flashInfo.activeSectorSize; + start = flashOperationInfo.convertedAddress; + sectorSize = flashOperationInfo.activeSectorSize; /* calculating Flash end address */ endAddress = start + lengthInBytes - 1; @@ -541,6 +856,8 @@ status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBy endAddress = numberOfSectors * sectorSize - 1; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* the start address will increment to the next sector address * until it reaches the endAdddress */ while (start <= endAddress) @@ -548,13 +865,6 @@ status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBy /* preparing passing parameter to erase a flash block */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_SECTOR, start); - /* Validate the user key */ - returnCode = flash_check_user_key(key); - if (returnCode) - { - return returnCode; - } - /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -601,6 +911,8 @@ status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -639,6 +951,8 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -650,33 +964,35 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if (src == NULL) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.blockWriteUnitSize); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.blockWriteUnitSize); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; + start = flashOperationInfo.convertedAddress; + + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); while (lengthInBytes > 0) { /* preparing passing parameter to program the flash block */ kFCCOBx[1] = *src++; - if (4 == flashInfo.blockWriteUnitSize) + if (4 == flashOperationInfo.blockWriteUnitSize) { kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_LONGWORD, start); } - else if (8 == flashInfo.blockWriteUnitSize) + else if (8 == flashOperationInfo.blockWriteUnitSize) { kFCCOBx[2] = *src++; kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_PHRASE, start); @@ -702,10 +1018,10 @@ status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, ui else { /* update start address for next iteration */ - start += flashInfo.blockWriteUnitSize; + start += flashOperationInfo.blockWriteUnitSize; /* update lengthInBytes for next iteration */ - lengthInBytes -= flashInfo.blockWriteUnitSize; + lengthInBytes -= flashOperationInfo.blockWriteUnitSize; } } @@ -742,6 +1058,8 @@ status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src } #endif /* FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT */ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -755,7 +1073,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * { status_t returnCode; uint32_t sectorSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD bool needSwitchFlexRamMode = false; #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ @@ -765,17 +1083,17 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectionCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; - sectorSize = flashInfo.activeSectorSize; + start = flashOperationInfo.convertedAddress; + sectorSize = flashOperationInfo.activeSectorSize; #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD /* Switch function of FlexRAM if needed */ @@ -783,7 +1101,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * { needSwitchFlexRamMode = true; - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableAsRam); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableAsRam); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_SetFlexramAsRamError; @@ -791,6 +1109,8 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * } #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + while (lengthInBytes > 0) { /* Make sure the write operation doesn't span two sectors */ @@ -819,9 +1139,9 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * uint32_t programSizeOfCurrentPass; uint32_t numberOfPhases; - if (lengthTobeProgrammedOfCurrentSector > kFLASH_accelerationRamSize) + if (lengthTobeProgrammedOfCurrentSector > kFLASH_AccelerationRamSize) { - programSizeOfCurrentPass = kFLASH_accelerationRamSize; + programSizeOfCurrentPass = kFLASH_AccelerationRamSize; } else { @@ -833,7 +1153,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * /* Set start address of the data to be programmed */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_SECTION, start + currentOffset); /* Set program size in terms of FEATURE_FLASH_SECTION_CMD_ADDRESS_ALIGMENT */ - numberOfPhases = programSizeOfCurrentPass / flashInfo.sectionCmdAddressAligment; + numberOfPhases = programSizeOfCurrentPass / flashOperationInfo.sectionCmdAddressAligment; kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_2(numberOfPhases, 0xFFFFU); @@ -867,7 +1187,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * /* Restore function of FlexRAM if needed. */ if (needSwitchFlexRamMode) { - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableForEeprom); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableForEeprom); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_RecoverFlexramAsEepromError; @@ -904,7 +1224,7 @@ status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, { needSwitchFlexRamMode = true; - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableForEeprom); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableForEeprom); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_SetFlexramAsEepromError; @@ -950,7 +1270,7 @@ status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, /* Switch function of FlexRAM if needed */ if (needSwitchFlexRamMode) { - returnCode = FLASH_SetFlexramFunction(config, kFLASH_flexramFunctionOptionAvailableAsRam); + returnCode = FLASH_SetFlexramFunction(config, kFLASH_FlexramFunctionOptionAvailableAsRam); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_RecoverFlexramAsRamError; @@ -966,17 +1286,18 @@ status_t FLASH_ReadResource( flash_config_t *config, uint32_t start, uint32_t *dst, uint32_t lengthInBytes, flash_read_resource_option_t option) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if ((config == NULL) || (dst == NULL)) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_resource_range(start, lengthInBytes, flashInfo.resourceCmdAddressAligment, option); + returnCode = + flash_check_resource_range(start, lengthInBytes, flashOperationInfo.resourceCmdAddressAligment, option); if (returnCode != kStatus_FLASH_Success) { return returnCode; @@ -986,11 +1307,11 @@ status_t FLASH_ReadResource( { /* preparing passing parameter */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_READ_RESOURCE, start); - if (flashInfo.resourceCmdAddressAligment == 4) + if (flashOperationInfo.resourceCmdAddressAligment == 4) { kFCCOBx[2] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU); } - else if (flashInfo.resourceCmdAddressAligment == 8) + else if (flashOperationInfo.resourceCmdAddressAligment == 8) { kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU); } @@ -1008,14 +1329,14 @@ status_t FLASH_ReadResource( /* fetch data */ *dst++ = kFCCOBx[1]; - if (flashInfo.resourceCmdAddressAligment == 8) + if (flashOperationInfo.resourceCmdAddressAligment == 8) { *dst++ = kFCCOBx[2]; } /* update start address for next iteration */ - start += flashInfo.resourceCmdAddressAligment; + start += flashOperationInfo.resourceCmdAddressAligment; /* update lengthInBytes for next iteration */ - lengthInBytes -= flashInfo.resourceCmdAddressAligment; + lengthInBytes -= flashOperationInfo.resourceCmdAddressAligment; } return (returnCode); @@ -1075,7 +1396,7 @@ status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t * if (FLASH_SECURITY_STATE_UNSECURED == (registerValue & FTFx_FSEC_SEC_MASK)) { /* Flash in unsecured state */ - *state = kFLASH_securityStateNotSecure; + *state = kFLASH_SecurityStateNotSecure; } else { @@ -1084,12 +1405,12 @@ status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t * if (FLASH_SECURITY_STATE_KEYEN == (registerValue & FTFx_FSEC_KEYEN_MASK)) { /* Backdoor key security enabled */ - *state = kFLASH_securityStateBackdoorEnabled; + *state = kFLASH_SecurityStateBackdoorEnabled; } else { /* Backdoor key security disabled */ - *state = kFLASH_securityStateBackdoorDisabled; + *state = kFLASH_SecurityStateBackdoorDisabled; } } @@ -1146,22 +1467,22 @@ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t leng { /* Check arguments. */ uint32_t blockSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; uint32_t nextBlockStartAddress; uint32_t remainingBytes; status_t returnCode; - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectionCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment); if (returnCode) { return returnCode; } - flash_get_matched_operation_info(config, start, &flashInfo); - start = flashInfo.convertedAddress; - blockSize = flashInfo.activeBlockSize; + flash_get_matched_operation_info(config, start, &flashOperationInfo); + start = flashOperationInfo.convertedAddress; + blockSize = flashOperationInfo.activeBlockSize; nextBlockStartAddress = ALIGN_UP(start, blockSize); if (nextBlockStartAddress == start) @@ -1180,7 +1501,7 @@ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t leng verifyLength = remainingBytes; } - numberOfPhrases = verifyLength / flashInfo.sectionCmdAddressAligment; + numberOfPhrases = verifyLength / flashOperationInfo.sectionCmdAddressAligment; /* Fill in verify section command parameters. */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_VERIFY_SECTION, start); @@ -1210,22 +1531,22 @@ status_t FLASH_VerifyProgram(flash_config_t *config, uint32_t *failedData) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if (expectedData == NULL) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.checkCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.checkCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; + start = flashOperationInfo.convertedAddress; while (lengthInBytes) { @@ -1251,9 +1572,9 @@ status_t FLASH_VerifyProgram(flash_config_t *config, break; } - lengthInBytes -= flashInfo.checkCmdAddressAligment; - expectedData += flashInfo.checkCmdAddressAligment / sizeof(*expectedData); - start += flashInfo.checkCmdAddressAligment; + lengthInBytes -= flashOperationInfo.checkCmdAddressAligment; + expectedData += flashOperationInfo.checkCmdAddressAligment / sizeof(*expectedData); + start += flashOperationInfo.checkCmdAddressAligment; } return (returnCode); @@ -1279,19 +1600,21 @@ status_t FLASH_IsProtected(flash_config_t *config, flash_protection_state_t *protection_state) { uint32_t endAddress; /* end address for protection check */ - uint32_t protectionRegionSize; /* size of flash protection region */ uint32_t regionCheckedCounter; /* increments each time the flash address was checked for * protection status */ uint32_t regionCounter; /* incrementing variable used to increment through the flash * protection regions */ uint32_t protectStatusCounter; /* increments each time a flash region was detected as protected */ - uint8_t flashRegionProtectStatus[FSL_FEATURE_FTFx_REGION_COUNT]; /* array of the protection status for each + uint8_t flashRegionProtectStatus[FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT]; /* array of the protection + * status for each * protection region */ - uint32_t flashRegionAddress[FSL_FEATURE_FTFx_REGION_COUNT + 1]; /* array of the start addresses for each flash - * protection region. Note this is REGION_COUNT+1 - * due to requiring the next start address after - * the end of flash for loop-check purposes below */ + uint32_t flashRegionAddress[FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT + + 1]; /* array of the start addresses for each flash + * protection region. Note this is REGION_COUNT+1 + * due to requiring the next start address after + * the end of flash for loop-check purposes below */ + flash_protection_config_t flashProtectionInfo; /* flash protection information */ status_t returnCode; if (protection_state == NULL) @@ -1306,28 +1629,24 @@ status_t FLASH_IsProtected(flash_config_t *config, return returnCode; } - /* calculating Flash end address */ - endAddress = start + lengthInBytes; - - /* Calculate the size of the flash protection region - * If the flash density is > 32KB, then protection region is 1/32 of total flash density - * Else if flash density is < 32KB, then flash protection region is set to 1KB */ - if (config->PFlashTotalSize > 32 * 1024) - { - protectionRegionSize = (config->PFlashTotalSize) / FSL_FEATURE_FTFx_REGION_COUNT; - } - else + /* Get necessary flash protection information. */ + returnCode = flash_get_protection_info(config, &flashProtectionInfo); + if (returnCode) { - protectionRegionSize = 1024; + return returnCode; } + /* calculating Flash end address */ + endAddress = start + lengthInBytes; + /* populate the flashRegionAddress array with the start address of each flash region */ regionCounter = 0; /* make sure regionCounter is initialized to 0 first */ /* populate up to 33rd element of array, this is the next address after end of flash array */ - while (regionCounter <= FSL_FEATURE_FTFx_REGION_COUNT) + while (regionCounter <= flashProtectionInfo.regionCount) { - flashRegionAddress[regionCounter] = config->PFlashBlockBase + protectionRegionSize * regionCounter; + flashRegionAddress[regionCounter] = + flashProtectionInfo.regionBase + flashProtectionInfo.regionSize * regionCounter; regionCounter++; } @@ -1341,24 +1660,80 @@ status_t FLASH_IsProtected(flash_config_t *config, * regionCounter is used to determine which FPROT[3:0] register to check for protection status * Note: FPROT=1 means NOT protected, FPROT=0 means protected */ regionCounter = 0; /* make sure regionCounter is initialized to 0 first */ - while (regionCounter < FSL_FEATURE_FTFx_REGION_COUNT) + while (regionCounter < flashProtectionInfo.regionCount) { - if (regionCounter < 8) - { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT3) >> regionCounter) & (0x01u); - } - else if ((regionCounter >= 8) && (regionCounter < 16)) - { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT2) >> (regionCounter - 8)) & (0x01u); - } - else if ((regionCounter >= 16) && (regionCounter < 24)) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT1) >> (regionCounter - 16)) & (0x01u); + if (regionCounter < 8) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSL_REG >> regionCounter) & (0x01u); + } + else if ((regionCounter >= 8) && (regionCounter < 16)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSH_REG >> (regionCounter - 8)) & (0x01u); + } + else + { + break; + } } else +#endif { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT0) >> (regionCounter - 24)) & (0x01u); + /* Note: So far protection region count may be 16/20/24/32/64 */ + if (regionCounter < 8) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL3_REG >> regionCounter) & (0x01u); + } + else if ((regionCounter >= 8) && (regionCounter < 16)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL2_REG >> (regionCounter - 8)) & (0x01u); + } +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT > 16) +#if (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 20) + else if ((regionCounter >= 16) && (regionCounter < 20)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u); + } +#else + else if ((regionCounter >= 16) && (regionCounter < 24)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u); + } +#endif /* (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 20) */ +#endif +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT > 24) + else if ((regionCounter >= 24) && (regionCounter < 32)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL0_REG >> (regionCounter - 24)) & (0x01u); + } +#endif +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && \ + (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 64) + else if (regionCounter < 40) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH3_REG >> (regionCounter - 32)) & (0x01u); + } + else if (regionCounter < 48) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH2_REG >> (regionCounter - 40)) & (0x01u); + } + else if (regionCounter < 56) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH1_REG >> (regionCounter - 48)) & (0x01u); + } + else if (regionCounter < 64) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH0_REG >> (regionCounter - 56)) & (0x01u); + } +#endif + else + { + break; + } } + regionCounter++; } @@ -1386,7 +1761,7 @@ status_t FLASH_IsProtected(flash_config_t *config, /* increment protectStatusCounter to indicate this region is protected */ protectStatusCounter++; } - start += protectionRegionSize; /* increment to an address within the next region */ + start += flashProtectionInfo.regionSize; /* increment to an address within the next region */ } regionCounter++; /* increment regionCounter to check for the next flash protection region */ } @@ -1394,18 +1769,18 @@ status_t FLASH_IsProtected(flash_config_t *config, /* if protectStatusCounter == 0, then no region of the desired flash region is protected */ if (protectStatusCounter == 0) { - *protection_state = kFLASH_protectionStateUnprotected; + *protection_state = kFLASH_ProtectionStateUnprotected; } /* if protectStatusCounter == regionCheckedCounter, then each region checked was protected */ else if (protectStatusCounter == regionCheckedCounter) { - *protection_state = kFLASH_protectionStateProtected; + *protection_state = kFLASH_ProtectionStateProtected; } /* if protectStatusCounter != regionCheckedCounter, then protection status is mixed * In other words, some regions are protected while others are unprotected */ else { - *protection_state = kFLASH_protectionStateMixed; + *protection_state = kFLASH_ProtectionStateMixed; } return (returnCode); @@ -1416,6 +1791,9 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t lengthInBytes, flash_execute_only_access_state_t *access_state) { +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + flash_access_config_t flashAccessInfo; /* flash Execute-Only information */ +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ status_t returnCode; if (access_state == NULL) @@ -1431,6 +1809,13 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, } #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + /* Get necessary flash Execute-Only information. */ + returnCode = flash_get_access_info(config, &flashAccessInfo); + if (returnCode) + { + return returnCode; + } + { uint32_t executeOnlySegmentCounter = 0; @@ -1438,31 +1823,56 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t endAddress = start + lengthInBytes; /* Aligning start address and end address */ - uint32_t alignedStartAddress = ALIGN_DOWN(start, config->PFlashAccessSegmentSize); - uint32_t alignedEndAddress = ALIGN_UP(endAddress, config->PFlashAccessSegmentSize); + uint32_t alignedStartAddress = ALIGN_DOWN(start, flashAccessInfo.SegmentSize); + uint32_t alignedEndAddress = ALIGN_UP(endAddress, flashAccessInfo.SegmentSize); uint32_t segmentIndex = 0; uint32_t maxSupportedExecuteOnlySegmentCount = - (alignedEndAddress - alignedStartAddress) / config->PFlashAccessSegmentSize; + (alignedEndAddress - alignedStartAddress) / flashAccessInfo.SegmentSize; while (start < endAddress) { uint32_t xacc; - segmentIndex = start / config->PFlashAccessSegmentSize; + segmentIndex = (start - flashAccessInfo.SegmentBase) / flashAccessInfo.SegmentSize; - if (segmentIndex < 32) - { - xacc = *(const volatile uint32_t *)&FTFx->XACCL3; - } - else if (segmentIndex < config->PFlashAccessSegmentCount) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - xacc = *(const volatile uint32_t *)&FTFx->XACCH3; - segmentIndex -= 32; + /* For secondary flash, The two XACCS registers allow up to 16 restricted segments of equal memory size. + */ + if (segmentIndex < 8) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSL_REG; + } + else if (segmentIndex < flashAccessInfo.SegmentCount) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSH_REG; + segmentIndex -= 8; + } + else + { + break; + } } else +#endif { - break; + /* For primary flash, The eight XACC registers allow up to 64 restricted segments of equal memory size. + */ + if (segmentIndex < 32) + { + xacc = *(const volatile uint32_t *)&FTFx_XACCL3_REG; + } + else if (segmentIndex < flashAccessInfo.SegmentCount) + { + xacc = *(const volatile uint32_t *)&FTFx_XACCH3_REG; + segmentIndex -= 32; + } + else + { + break; + } } /* Determine if this address range is in a execute-only protection flash segment. */ @@ -1471,24 +1881,24 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, executeOnlySegmentCounter++; } - start += config->PFlashAccessSegmentSize; + start += flashAccessInfo.SegmentSize; } if (executeOnlySegmentCounter < 1u) { - *access_state = kFLASH_accessStateUnLimited; + *access_state = kFLASH_AccessStateUnLimited; } else if (executeOnlySegmentCounter < maxSupportedExecuteOnlySegmentCount) { - *access_state = kFLASH_accessStateMixed; + *access_state = kFLASH_AccessStateMixed; } else { - *access_state = kFLASH_accessStateExecuteOnly; + *access_state = kFLASH_AccessStateExecuteOnly; } } #else - *access_state = kFLASH_accessStateUnLimited; + *access_state = kFLASH_AccessStateUnLimited; #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ return (returnCode); @@ -1503,27 +1913,27 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro switch (whichProperty) { - case kFLASH_propertyPflashSectorSize: + case kFLASH_PropertyPflashSectorSize: *value = config->PFlashSectorSize; break; - case kFLASH_propertyPflashTotalSize: + case kFLASH_PropertyPflashTotalSize: *value = config->PFlashTotalSize; break; - case kFLASH_propertyPflashBlockSize: + case kFLASH_PropertyPflashBlockSize: *value = config->PFlashTotalSize / FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; break; - case kFLASH_propertyPflashBlockCount: - *value = config->PFlashBlockCount; + case kFLASH_PropertyPflashBlockCount: + *value = (uint32_t)config->PFlashBlockCount; break; - case kFLASH_propertyPflashBlockBaseAddr: + case kFLASH_PropertyPflashBlockBaseAddr: *value = config->PFlashBlockBase; break; - case kFLASH_propertyPflashFacSupport: + case kFLASH_PropertyPflashFacSupport: #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) *value = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL; #else @@ -1531,31 +1941,39 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ break; - case kFLASH_propertyPflashAccessSegmentSize: + case kFLASH_PropertyPflashAccessSegmentSize: *value = config->PFlashAccessSegmentSize; break; - case kFLASH_propertyPflashAccessSegmentCount: + case kFLASH_PropertyPflashAccessSegmentCount: *value = config->PFlashAccessSegmentCount; break; + case kFLASH_PropertyFlexRamBlockBaseAddr: + *value = config->FlexRAMBlockBase; + break; + + case kFLASH_PropertyFlexRamTotalSize: + *value = config->FlexRAMTotalSize; + break; + #if FLASH_SSD_IS_FLEXNVM_ENABLED - case kFLASH_propertyDflashSectorSize: + case kFLASH_PropertyDflashSectorSize: *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE; break; - case kFLASH_propertyDflashTotalSize: + case kFLASH_PropertyDflashTotalSize: *value = config->DFlashTotalSize; break; - case kFLASH_propertyDflashBlockSize: + case kFLASH_PropertyDflashBlockSize: *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SIZE; break; - case kFLASH_propertyDflashBlockCount: + case kFLASH_PropertyDflashBlockCount: *value = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT; break; - case kFLASH_propertyDflashBlockBaseAddr: + case kFLASH_PropertyDflashBlockBaseAddr: *value = config->DFlashBlockBase; break; - case kFLASH_propertyEepromTotalSize: + case kFLASH_PropertyEepromTotalSize: *value = config->EEpromTotalSize; break; #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ @@ -1567,6 +1985,65 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro return kStatus_FLASH_Success; } +status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value) +{ + status_t status = kStatus_FLASH_Success; + + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + switch (whichProperty) + { +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + case kFLASH_PropertyFlashMemoryIndex: + if ((value != (uint32_t)kFLASH_MemoryIndexPrimaryFlash) && + (value != (uint32_t)kFLASH_MemoryIndexSecondaryFlash)) + { + return kStatus_FLASH_InvalidPropertyValue; + } + config->FlashMemoryIndex = (uint8_t)value; + break; +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ + + case kFLASH_PropertyFlashCacheControllerIndex: + if ((value != (uint32_t)kFLASH_CacheControllerIndexForCore0) && + (value != (uint32_t)kFLASH_CacheControllerIndexForCore1)) + { + return kStatus_FLASH_InvalidPropertyValue; + } + config->FlashCacheControllerIndex = (uint8_t)value; + break; + + case kFLASH_PropertyPflashSectorSize: + case kFLASH_PropertyPflashTotalSize: + case kFLASH_PropertyPflashBlockSize: + case kFLASH_PropertyPflashBlockCount: + case kFLASH_PropertyPflashBlockBaseAddr: + case kFLASH_PropertyPflashFacSupport: + case kFLASH_PropertyPflashAccessSegmentSize: + case kFLASH_PropertyPflashAccessSegmentCount: + case kFLASH_PropertyFlexRamBlockBaseAddr: + case kFLASH_PropertyFlexRamTotalSize: +#if FLASH_SSD_IS_FLEXNVM_ENABLED + case kFLASH_PropertyDflashSectorSize: + case kFLASH_PropertyDflashTotalSize: + case kFLASH_PropertyDflashBlockSize: + case kFLASH_PropertyDflashBlockCount: + case kFLASH_PropertyDflashBlockBaseAddr: + case kFLASH_PropertyEepromTotalSize: +#endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ + status = kStatus_FLASH_ReadOnlyProperty; + break; + default: /* catch inputs that are not recognized */ + status = kStatus_FLASH_UnknownProperty; + break; + } + + return status; +} + #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD status_t FLASH_SetFlexramFunction(flash_config_t *config, flash_flexram_function_option_t option) { @@ -1611,7 +2088,7 @@ status_t FLASH_SwapControl(flash_config_t *config, /* Make sure address provided is in the lower half of Program flash but not in the Flash Configuration Field */ if ((address >= (config->PFlashTotalSize / 2)) || - ((address >= kFLASH_configAreaStart) && (address <= kFLASH_configAreaEnd))) + ((address >= kFLASH_ConfigAreaStart) && (address <= kFLASH_ConfigAreaEnd))) { return kStatus_FLASH_SwapIndicatorAddressError; } @@ -1628,9 +2105,9 @@ status_t FLASH_SwapControl(flash_config_t *config, returnCode = flash_command_sequence(config); - returnInfo->flashSwapState = (flash_swap_state_t)FTFx->FCCOB5; - returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx->FCCOB6; - returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx->FCCOB7; + returnInfo->flashSwapState = (flash_swap_state_t)FTFx_FCCOB5_REG; + returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB6_REG; + returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB7_REG; return returnCode; } @@ -1646,23 +2123,23 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio do { - returnCode = FLASH_SwapControl(config, address, kFLASH_swapControlOptionReportStatus, &returnInfo); + returnCode = FLASH_SwapControl(config, address, kFLASH_SwapControlOptionReportStatus, &returnInfo); if (returnCode != kStatus_FLASH_Success) { return returnCode; } - if (kFLASH_swapFunctionOptionDisable == option) + if (kFLASH_SwapFunctionOptionDisable == option) { - if (returnInfo.flashSwapState == kFLASH_swapStateDisabled) + if (returnInfo.flashSwapState == kFLASH_SwapStateDisabled) { return kStatus_FLASH_Success; } - else if (returnInfo.flashSwapState == kFLASH_swapStateUninitialized) + else if (returnInfo.flashSwapState == kFLASH_SwapStateUninitialized) { /* The swap system changed to the DISABLED state with Program flash block 0 * located at relative flash address 0x0_0000 */ - returnCode = FLASH_SwapControl(config, address, kFLASH_swapControlOptionDisableSystem, &returnInfo); + returnCode = FLASH_SwapControl(config, address, kFLASH_SwapControlOptionDisableSystem, &returnInfo); } else { @@ -1679,12 +2156,12 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio * Complete. */ switch (returnInfo.flashSwapState) { - case kFLASH_swapStateUninitialized: + case kFLASH_SwapStateUninitialized: /* If current swap mode is Uninitialized, Initialize Swap to Initialized/READY state. */ returnCode = - FLASH_SwapControl(config, address, kFLASH_swapControlOptionIntializeSystem, &returnInfo); + FLASH_SwapControl(config, address, kFLASH_SwapControlOptionIntializeSystem, &returnInfo); break; - case kFLASH_swapStateReady: + case kFLASH_SwapStateReady: /* Validate whether the address provided to the swap system is matched to * swap indicator address in the IFR */ returnCode = flash_validate_swap_indicator_address(config, address); @@ -1692,23 +2169,23 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio { /* If current swap mode is Initialized/Ready, Initialize Swap to UPDATE state. */ returnCode = - FLASH_SwapControl(config, address, kFLASH_swapControlOptionSetInUpdateState, &returnInfo); + FLASH_SwapControl(config, address, kFLASH_SwapControlOptionSetInUpdateState, &returnInfo); } break; - case kFLASH_swapStateUpdate: + case kFLASH_SwapStateUpdate: /* If current swap mode is Update, Erase indicator sector in non active block * to proceed swap system to update-erased state */ returnCode = FLASH_Erase(config, address + (config->PFlashTotalSize >> 1), - FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT, kFLASH_apiEraseKey); + FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT, kFLASH_ApiEraseKey); break; - case kFLASH_swapStateUpdateErased: + case kFLASH_SwapStateUpdateErased: /* If current swap mode is Update or Update-Erased, progress Swap to COMPLETE State */ returnCode = - FLASH_SwapControl(config, address, kFLASH_swapControlOptionSetInCompleteState, &returnInfo); + FLASH_SwapControl(config, address, kFLASH_SwapControlOptionSetInCompleteState, &returnInfo); break; - case kFLASH_swapStateComplete: + case kFLASH_SwapStateComplete: break; - case kFLASH_swapStateDisabled: + case kFLASH_SwapStateDisabled: /* When swap system is in disabled state, We need to clear swap system back to uninitialized * by issuing EraseAllBlocks command */ returnCode = kStatus_FLASH_SwapSystemNotInUninitialized; @@ -1722,7 +2199,7 @@ status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_functio { break; } - } while (!((kFLASH_swapStateComplete == returnInfo.flashSwapState) && (kFLASH_swapFunctionOptionEnable == option))); + } while (!((kFLASH_SwapStateComplete == returnInfo.flashSwapState) && (kFLASH_SwapFunctionOptionEnable == option))); return returnCode; } @@ -1750,6 +2227,8 @@ status_t FLASH_ProgramPartition(flash_config_t *config, kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_2_1(FTFx_PROGRAM_PARTITION, 0xFFFFU, option); kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_1_2(eepromDataSizeCode, flexnvmPartitionCode, 0xFFFFU); + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -1766,31 +2245,70 @@ status_t FLASH_ProgramPartition(flash_config_t *config, } #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD */ -status_t FLASH_PflashSetProtection(flash_config_t *config, uint32_t protectStatus) +status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus) { if (config == NULL) { return kStatus_FLASH_InvalidArgument; } - *kFPROT = protectStatus; - - if (protectStatus != *kFPROT) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - return kStatus_FLASH_CommandFailure; - } + *kFPROTSL = protectStatus->valueLow32b.prots16b.protsl; + if (protectStatus->valueLow32b.prots16b.protsl != *kFPROTSL) + { + return kStatus_FLASH_CommandFailure; + } + + *kFPROTSH = protectStatus->valueLow32b.prots16b.protsh; + if (protectStatus->valueLow32b.prots16b.protsh != *kFPROTSH) + { + return kStatus_FLASH_CommandFailure; + } + } + else +#endif + { + *kFPROTL = protectStatus->valueLow32b.protl32b; + if (protectStatus->valueLow32b.protl32b != *kFPROTL) + { + return kStatus_FLASH_CommandFailure; + } + +#if defined(FTFx_FPROT_HIGH_REG) + *kFPROTH = protectStatus->valueHigh32b.proth32b; + if (protectStatus->valueHigh32b.proth32b != *kFPROTH) + { + return kStatus_FLASH_CommandFailure; + } +#endif + } return kStatus_FLASH_Success; } -status_t FLASH_PflashGetProtection(flash_config_t *config, uint32_t *protectStatus) +status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus) { if ((config == NULL) || (protectStatus == NULL)) { return kStatus_FLASH_InvalidArgument; } - *protectStatus = *kFPROT; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + protectStatus->valueLow32b.prots16b.protsl = *kFPROTSL; + protectStatus->valueLow32b.prots16b.protsh = *kFPROTSH; + } + else +#endif + { + protectStatus->valueLow32b.protl32b = *kFPROTL; +#if defined(FTFx_FPROT_HIGH_REG) + protectStatus->valueHigh32b.proth32b = *kFPROTH; +#endif + } return kStatus_FLASH_Success; } @@ -1881,70 +2399,215 @@ status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatu } #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ -#if FLASH_DRIVER_IS_FLASH_RESIDENT -/*! - * @brief Run flash command - * - * This function should be copied to RAM for execution to make sure that code works - * properly even flash cache is disabled. - * It is for flash-resident bootloader only, not technically required for ROM or - * flashloader (RAM-resident bootloader). - */ -void flash_run_command(FTFx_REG_ACCESS_TYPE ftfx_fstat) +status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus) { - /* clear CCIF bit */ - *ftfx_fstat = FTFx_FSTAT_CCIF_MASK; +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + FTFx_REG32_ACCESS_TYPE regBase; +#if defined(MCM) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM->PLACR; +#elif defined(MCM0) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR; +#endif + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable) + { + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + return kStatus_FLASH_InvalidSpeculationOption; + } + else + { + *regBase |= MCM_PLACR_DFCS_MASK; + } + } + else + { + *regBase &= ~MCM_PLACR_DFCS_MASK; + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= MCM_PLACR_EFDS_MASK; + } + else + { + *regBase &= ~MCM_PLACR_EFDS_MASK; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + FTFx_REG32_ACCESS_TYPE regBase; + uint32_t b0dpeMask, b0ipeMask; +#if defined(FMC_PFB01CR_B0DPE_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + b0dpeMask = FMC_PFB01CR_B0DPE_MASK; + b0ipeMask = FMC_PFB01CR_B0IPE_MASK; +#elif defined(FMC_PFB0CR_B0DPE_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + b0dpeMask = FMC_PFB0CR_B0DPE_MASK; + b0ipeMask = FMC_PFB0CR_B0IPE_MASK; +#endif + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= b0ipeMask; + } + else + { + *regBase &= ~b0ipeMask; + } + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= b0dpeMask; + } + else + { + *regBase &= ~b0dpeMask; + } - /* Check CCIF bit of the flash status register, wait till it is set. - * IP team indicates that this loop will always complete. */ - while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK)) +/* Invalidate Prefetch Speculation Buffer */ +#if defined(FMC_PFB01CR_S_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK; +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK; +#elif defined(FMC_PFB0CR_S_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK; +#endif + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM { + FTFx_REG32_ACCESS_TYPE regBase; + uint32_t flashSpeculationMask, dataPrefetchMask; + regBase = (FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0]; + flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK; + dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK; + + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable) + { + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + return kStatus_FLASH_InvalidSpeculationOption; + } + else + { + *regBase |= flashSpeculationMask; + } + } + else + { + *regBase &= ~flashSpeculationMask; + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase &= ~dataPrefetchMask; + } + else + { + *regBase |= dataPrefetchMask; + } + } } -} +#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ -/*! - * @brief Be used for determining the size of flash_run_command() - * - * This function must be defined that lexically follows flash_run_command(), - * so we can determine the size of flash_run_command() at runtime and not worry - * about toolchain or code generation differences. - */ -void flash_run_command_end(void) -{ + return kStatus_FLASH_Success; } -/*! - * @brief Copy flash_run_command() to RAM - * - * This function copys the memory between flash_run_command() and flash_run_command_end() - * into the buffer which is also means that copying flash_run_command() to RAM. - */ -static void copy_flash_run_command(uint8_t *flashRunCommand) +status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus) { - /* Calculate the valid length of flash_run_command() memory. - * Set max size(64 bytes) as default function size, in case some compiler allocates - * flash_run_command_end ahead of flash_run_command. */ - uint32_t funcLength = kFLASH_executeInRamFunctionMaxSize; - uint32_t flash_run_command_start_addr = (uint32_t)flash_run_command & (~1U); - uint32_t flash_run_command_end_addr = (uint32_t)flash_run_command_end & (~1U); - if (flash_run_command_end_addr > flash_run_command_start_addr) - { - funcLength = flash_run_command_end_addr - flash_run_command_start_addr; + memset(speculationStatus, 0, sizeof(flash_prefetch_speculation_status_t)); - assert(funcLength <= kFLASH_executeInRamFunctionMaxSize); + /* Assuming that all speculation options are enabled. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionEnable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionEnable; - /* In case some compiler allocates other function in the middle of flash_run_command - * and flash_run_command_end. */ - if (funcLength > kFLASH_executeInRamFunctionMaxSize) +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + uint32_t value; +#if defined(MCM) + value = MCM->PLACR; +#elif defined(MCM0) + value = MCM0->PLACR; +#endif + if (value & MCM_PLACR_DFCS_MASK) { - funcLength = kFLASH_executeInRamFunctionMaxSize; + /* Speculation buffer is off. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + else + { + /* Speculation buffer is on for instruction. */ + if (!(value & MCM_PLACR_EFDS_MASK)) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + uint32_t value; + uint32_t b0dpeMask, b0ipeMask; +#if defined(FMC_PFB01CR_B0DPE_MASK) + value = FMC->PFB01CR; + b0dpeMask = FMC_PFB01CR_B0DPE_MASK; + b0ipeMask = FMC_PFB01CR_B0IPE_MASK; +#elif defined(FMC_PFB0CR_B0DPE_MASK) + value = FMC->PFB0CR; + b0dpeMask = FMC_PFB0CR_B0DPE_MASK; + b0ipeMask = FMC_PFB0CR_B0IPE_MASK; +#endif + if (!(value & b0dpeMask)) + { + /* Do not prefetch in response to data references. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + if (!(value & b0ipeMask)) + { + /* Do not prefetch in response to instruction fetches. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + { + uint32_t value; + uint32_t flashSpeculationMask, dataPrefetchMask; + value = MSCM->OCMDR[0]; + flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK; + dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK; + + if (value & flashSpeculationMask) + { + /* Speculation buffer is off. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + else + { + /* Speculation buffer is on for instruction. */ + if (value & dataPrefetchMask) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } } } +#endif + + return kStatus_FLASH_Success; +} + +#if FLASH_DRIVER_IS_FLASH_RESIDENT +/*! + * @brief Copy PIC of flash_run_command() to RAM + */ +static void copy_flash_run_command(uint32_t *flashRunCommand) +{ + assert(sizeof(s_flashRunCommandFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4)); /* Since the value of ARM function pointer is always odd, but the real start address - * of function memory should be even, that's why -1 and +1 operation exist. */ - memcpy((void *)flashRunCommand, (void *)flash_run_command_start_addr, funcLength); - callFlashRunCommand = (void (*)(FTFx_REG_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1); + * of function memory should be even, that's why +1 operation exist. */ + memcpy((void *)flashRunCommand, (void *)s_flashRunCommandFunctionCode, sizeof(s_flashRunCommandFunctionCode)); + callFlashRunCommand = (void (*)(FTFx_REG8_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1); } #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ @@ -1973,7 +2636,7 @@ static status_t flash_command_sequence(flash_config_t *config) /* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using * pre-processed MICRO sentences or operating global variable in flash_run_comamnd() * to make sure that flash_run_command() will be compiled into position-independent code (PIC). */ - callFlashRunCommand((FTFx_REG_ACCESS_TYPE)(&FTFx->FSTAT)); + callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); #else /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; @@ -2015,100 +2678,173 @@ static status_t flash_command_sequence(flash_config_t *config) #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! - * @brief Run flash cache clear command + * @brief Copy PIC of flash_common_bit_operation() to RAM * - * This function should be copied to RAM for execution to make sure that code works - * properly even flash cache is disabled. - * It is for flash-resident bootloader only, not technically required for ROM or - * flashloader (RAM-resident bootloader). */ -void flash_cache_clear_command(FTFx_REG32_ACCESS_TYPE ftfx_reg) +static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation) { -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS - *ftfx_reg |= MCM_PLACR_CFCC_MASK; -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - *ftfx_reg = (*ftfx_reg & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); -#else - *ftfx_reg = (*ftfx_reg & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); + assert(sizeof(s_flashCommonBitOperationFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4)); + + /* Since the value of ARM function pointer is always odd, but the real start address + * of function memory should be even, that's why +1 operation exist. */ + memcpy((void *)flashCommonBitOperation, (void *)s_flashCommonBitOperationFunctionCode, + sizeof(s_flashCommonBitOperationFunctionCode)); + callFlashCommonBitOperation = (void (*)(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, + uint32_t bitValue))((uint32_t)flashCommonBitOperation + 1); + /* Workround for some devices which doesn't need this function */ + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)0, 0, 0, 0); +} +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(flash_config_t *config) +{ + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG; + +#if defined(MCM0) && defined(MCM1) + if (config->FlashCacheControllerIndex == (uint8_t)kFLASH_CacheControllerIndexForCore1) + { + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG; + } #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - *ftfx_reg |= MSCM_OCMDR_OCMC1(2); - *ftfx_reg |= MSCM_OCMDR_OCMC1(1); -#else -/* #error "Unknown flash cache controller" */ -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ - /* Memory barriers for good measure. - * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + +#if FLASH_DRIVER_IS_FLASH_RESIDENT + callFlashCommonBitOperation(regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U); +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ + *regBase |= MCM_CACHE_CLEAR_MASK; + + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ __ISB(); __DSB(); +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ -/*! - * @brief Be used for determining the size of flash_cache_clear_command() - * - * This function must be defined that lexically follows flash_cache_clear_command(), - * so we can determine the size of flash_cache_clear_command() at runtime and not worry - * about toolchain or code generation differences. - */ -void flash_cache_clear_command_end(void) +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(void) { +#if FLASH_DRIVER_IS_FLASH_RESIDENT + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0; +#if defined(FMC_PFB01CR_CINV_WAY_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_CINV_WAY_MASK, FMC_PFB01CR_CINV_WAY_SHIFT, 0xFU); +#else + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_CINV_WAY_MASK, FMC_PFB0CR_CINV_WAY_SHIFT, 0xFU); +#endif +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ +#if defined(FMC_PFB01CR_CINV_WAY_MASK) + FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); +#else + FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); +#endif + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ -/*! - * @brief Copy flash_cache_clear_command() to RAM - * - * This function copys the memory between flash_cache_clear_command() and flash_cache_clear_command_end() - * into the buffer which is also means that copying flash_cache_clear_command() to RAM. - */ -static void copy_flash_cache_clear_command(uint8_t *flashCacheClearCommand) +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM +/*! @brief Performs the prefetch speculation buffer clear to the flash by MSCM.*/ +void mscm_flash_prefetch_speculation_enable(bool enable) { - /* Calculate the valid length of flash_cache_clear_command() memory. - * Set max size(64 bytes) as default function size, in case some compiler allocates - * flash_cache_clear_command_end ahead of flash_cache_clear_command. */ - uint32_t funcLength = kFLASH_executeInRamFunctionMaxSize; - uint32_t flash_cache_clear_command_start_addr = (uint32_t)flash_cache_clear_command & (~1U); - uint32_t flash_cache_clear_command_end_addr = (uint32_t)flash_cache_clear_command_end & (~1U); - if (flash_cache_clear_command_end_addr > flash_cache_clear_command_start_addr) + uint8_t setValue; + if (enable) { - funcLength = flash_cache_clear_command_end_addr - flash_cache_clear_command_start_addr; + setValue = 0x0U; + } + else + { + setValue = 0x3U; + } - assert(funcLength <= kFLASH_executeInRamFunctionMaxSize); +/* The OCMDR[0] is always used to prefetch main Pflash*/ +/* For device with FlexNVM support, the OCMDR[1] is used to prefetch Dflash. + * For device with secondary flash support, the OCMDR[1] is used to prefetch secondary Pflash. */ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0], MSCM_SPECULATION_DISABLE_MASK, + MSCM_SPECULATION_DISABLE_SHIFT, setValue); +#if FLASH_SSD_IS_FLEXNVM_ENABLED || BL_HAS_SECONDARY_INTERNAL_FLASH + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[1], MSCM_SPECULATION_DISABLE_MASK, + MSCM_SPECULATION_DISABLE_SHIFT, setValue); +#endif +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ + MSCM->OCMDR[0] |= MSCM_SPECULATION_DISABLE(setValue); - /* In case some compiler allocates other function in the middle of flash_cache_clear_command - * and flash_cache_clear_command_end. */ - if (funcLength > kFLASH_executeInRamFunctionMaxSize) - { - funcLength = kFLASH_executeInRamFunctionMaxSize; - } - } + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#if FLASH_SSD_IS_FLEXNVM_ENABLED || BL_HAS_SECONDARY_INTERNAL_FLASH + MSCM->OCMDR[1] |= MSCM_SPECULATION_DISABLE(setValue); - /* Since the value of ARM function pointer is always odd, but the real start address - * of function memory should be even, that's why -1 and +1 operation exist. */ - memcpy((void *)flashCacheClearCommand, (void *)flash_cache_clear_command_start_addr, funcLength); - callFlashCacheClearCommand = (void (*)(FTFx_REG32_ACCESS_TYPE ftfx_reg))((uint32_t)flashCacheClearCommand + 1); + /* Each cahce clear instaruction should be followed by below code*/ + __ISB(); + __DSB(); +#endif + +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC +/*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ +void fmc_flash_prefetch_speculation_clear(void) +{ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0; +#if defined(FMC_PFB01CR_S_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_INV_MASK, FMC_PFB01CR_S_INV_SHIFT, 1U); +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_B_INV_MASK, FMC_PFB01CR_S_B_INV_SHIFT, 1U); +#elif defined(FMC_PFB0CR_S_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_INV_MASK, FMC_PFB0CR_S_INV_SHIFT, 1U); +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_B_INV_MASK, FMC_PFB0CR_S_B_INV_SHIFT, 1U); +#endif +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ +#if defined(FMC_PFB01CR_S_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK; +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK; +#elif defined(FMC_PFB0CR_S_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK; +#endif + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ /*! * @brief Flash Cache Clear * - * This function is used to perform the cache clear to the flash. + * This function is used to perform the cache and prefetch speculation clear to the flash. */ -#if (defined(__GNUC__)) -/* #pragma GCC push_options */ -/* #pragma GCC optimize("O0") */ -void __attribute__((optimize("O0"))) flash_cache_clear(flash_config_t *config) -#else -#if (defined(__ICCARM__)) -#pragma optimize = none -#endif -#if (defined(__CC_ARM)) -#pragma push -#pragma O0 -#endif void flash_cache_clear(flash_config_t *config) -#endif +{ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPost); +} + +/*! + * @brief Flash Cache Clear Process + * + * This function is used to perform the cache and prefetch speculation clear process to the flash. + */ +static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process) { #if FLASH_DRIVER_IS_FLASH_RESIDENT status_t returnCode = flash_check_execute_in_ram_function_info(config); @@ -2116,66 +2852,33 @@ void flash_cache_clear(flash_config_t *config) { return; } +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ -/* We pass the ftfx register address as a parameter to flash_cache_clear_comamnd() instead of using - * pre-processed MACROs or a global variable in flash_cache_clear_comamnd() - * to make sure that flash_cache_clear_command() will be compiled into position-independent code (PIC). */ -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -#if defined(MCM) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM->PLACR); + /* We pass the ftfx register address as a parameter to flash_common_bit_operation() instead of using + * pre-processed MACROs or a global variable in flash_common_bit_operation() + * to make sure that flash_common_bit_operation() will be compiled into position-independent code (PIC). */ + if (process == kFLASH_CacheClearProcessPost) + { +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM + mcm_flash_cache_clear(config); #endif -#if defined(MCM0) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR); +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC + fmc_flash_cache_clear(); #endif -#if defined(MCM1) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM1->PLACR); +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(true); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR); -#else - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR); +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + fmc_flash_prefetch_speculation_clear(); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0]); -#else - /* #error "Unknown flash cache controller" */ - /* meaningless code, just a workaround to solve warning*/ - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)0); -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ - -#else - -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -#if defined(MCM) - MCM->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#if defined(MCM0) - MCM0->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#if defined(MCM1) - MCM1->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); -#else - FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); + } + if (process == kFLASH_CacheClearProcessPre) + { +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(false); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(2); - MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(1); -#else -/* #error "Unknown flash cache controller" */ -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ -#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ + } } -#if (defined(__CC_ARM)) -#pragma pop -#endif -#if (defined(__GNUC__)) -/* #pragma GCC pop_options */ -#endif #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief Check whether flash execute-in-ram functions are ready */ @@ -2191,7 +2894,7 @@ static status_t flash_check_execute_in_ram_function_info(flash_config_t *config) flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo; if ((config->flashExecuteInRamFunctionInfo) && - (kFLASH_executeInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount)) + (kFLASH_ExecuteInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount)) { return kStatus_FLASH_Success; } @@ -2217,21 +2920,19 @@ static status_t flash_check_range(flash_config_t *config, return kStatus_FLASH_AlignmentError; } -/* check for valid range of the target addresses */ -#if !FLASH_SSD_IS_FLEXNVM_ENABLED - if ((startAddress < config->PFlashBlockBase) || - ((startAddress + lengthInBytes) > (config->PFlashBlockBase + config->PFlashTotalSize))) -#else - if (!(((startAddress >= config->PFlashBlockBase) && - ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize))) || - ((startAddress >= config->DFlashBlockBase) && - ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))))) + /* check for valid range of the target addresses */ + if ( +#if FLASH_SSD_IS_FLEXNVM_ENABLED + ((startAddress >= config->DFlashBlockBase) && + ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))) || #endif + ((startAddress >= config->PFlashBlockBase) && + ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize)))) { - return kStatus_FLASH_AddressError; + return kStatus_FLASH_Success; } - return kStatus_FLASH_Success; + return kStatus_FLASH_AddressError; } /*! @brief Gets the right address, sector and block size of current flash type which is indicated by address.*/ @@ -2250,6 +2951,8 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, #if FLASH_SSD_IS_FLEXNVM_ENABLED if ((address >= config->DFlashBlockBase) && (address <= (config->DFlashBlockBase + config->DFlashTotalSize))) { + /* When required by the command, address bit 23 selects between program flash memory + * (=0) and data flash memory (=1).*/ info->convertedAddress = address - config->DFlashBlockBase + 0x800000U; info->activeSectorSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE; info->activeBlockSize = config->DFlashTotalSize / FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT; @@ -2263,11 +2966,25 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, else #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ { - info->convertedAddress = address; + info->convertedAddress = address - config->PFlashBlockBase; info->activeSectorSize = config->PFlashSectorSize; info->activeBlockSize = config->PFlashTotalSize / config->PFlashBlockCount; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { +#if FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER || FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + /* When required by the command, address bit 23 selects between main flash memory + * (=0) and secondary flash memory (=1).*/ + info->convertedAddress += 0x800000U; +#endif + info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE; + } + else +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ + { + info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE; + } - info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE; info->sectorCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT; info->sectionCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; info->resourceCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_RESOURCE_CMD_ADDRESS_ALIGMENT; @@ -2281,7 +2998,7 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, static status_t flash_check_user_key(uint32_t key) { /* Validate the user key */ - if (key != kFLASH_apiEraseKey) + if (key != kFLASH_ApiEraseKey) { return kStatus_FLASH_EraseKeyError; } @@ -2307,13 +3024,17 @@ static status_t flash_update_flexnvm_memory_partition_status(flash_config_t *con return kStatus_FLASH_InvalidArgument; } +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD /* Get FlexNVM memory partition info from data flash IFR */ returnCode = FLASH_ReadResource(config, DFLASH_IFR_READRESOURCE_START_ADDRESS, (uint32_t *)&dataIFRReadOut, - sizeof(dataIFRReadOut), kFLASH_resourceOptionFlashIfr); + sizeof(dataIFRReadOut), kFLASH_ResourceOptionFlashIfr); if (returnCode != kStatus_FLASH_Success) { return kStatus_FLASH_PartitionStatusUpdateFailure; } +#else +#error "Cannot get FlexNVM memory partition info" +#endif /* Fill out partitioned EEPROM size */ dataIFRReadOut.EEPROMDataSetSize &= 0x0FU; @@ -2515,27 +3236,27 @@ static status_t flash_check_resource_range(uint32_t start, status = kStatus_FLASH_Success; maxReadbleAddress = start + lengthInBytes - 1; - if (option == kFLASH_resourceOptionVersionId) + if (option == kFLASH_ResourceOptionVersionId) { - if ((start != kFLASH_resourceRangeVersionIdStart) || - ((start + lengthInBytes - 1) != kFLASH_resourceRangeVersionIdEnd)) + if ((start != kFLASH_ResourceRangeVersionIdStart) || + ((start + lengthInBytes - 1) != kFLASH_ResourceRangeVersionIdEnd)) { status = kStatus_FLASH_InvalidArgument; } } - else if (option == kFLASH_resourceOptionFlashIfr) + else if (option == kFLASH_ResourceOptionFlashIfr) { - if (maxReadbleAddress < kFLASH_resourceRangePflashIfrSizeInBytes) + if (maxReadbleAddress < kFLASH_ResourceRangePflashIfrSizeInBytes) { } #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP - else if ((start >= kFLASH_resourceRangePflashSwapIfrStart) && - (maxReadbleAddress <= kFLASH_resourceRangePflashSwapIfrEnd)) + else if ((start >= kFLASH_ResourceRangePflashSwapIfrStart) && + (maxReadbleAddress <= kFLASH_ResourceRangePflashSwapIfrEnd)) { } #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */ - else if ((start >= kFLASH_resourceRangeDflashIfrStart) && - (maxReadbleAddress <= kFLASH_resourceRangeDflashIfrEnd)) + else if ((start >= kFLASH_ResourceRangeDflashIfrStart) && + (maxReadbleAddress <= kFLASH_ResourceRangeDflashIfrEnd)) { } else @@ -2556,9 +3277,9 @@ static status_t flash_check_resource_range(uint32_t start, /*! @brief Validates the gived swap control option.*/ static status_t flash_check_swap_control_option(flash_swap_control_option_t option) { - if ((option == kFLASH_swapControlOptionIntializeSystem) || (option == kFLASH_swapControlOptionSetInUpdateState) || - (option == kFLASH_swapControlOptionSetInCompleteState) || (option == kFLASH_swapControlOptionReportStatus) || - (option == kFLASH_swapControlOptionDisableSystem)) + if ((option == kFLASH_SwapControlOptionIntializeSystem) || (option == kFLASH_SwapControlOptionSetInUpdateState) || + (option == kFLASH_SwapControlOptionSetInCompleteState) || (option == kFLASH_SwapControlOptionReportStatus) || + (option == kFLASH_SwapControlOptionDisableSystem)) { return kStatus_FLASH_Success; } @@ -2571,21 +3292,48 @@ static status_t flash_check_swap_control_option(flash_swap_control_option_t opti /*! @brief Validates the gived address to see if it is equal to swap indicator address in pflash swap IFR.*/ static status_t flash_validate_swap_indicator_address(flash_config_t *config, uint32_t address) { - flash_swap_ifr_field_config_t flashSwapIfrField; + flash_swap_ifr_field_data_t flashSwapIfrFieldData; uint32_t swapIndicatorAddress; status_t returnCode; - returnCode = FLASH_ReadResource(config, kFLASH_resourceRangePflashSwapIfrStart, (uint32_t *)&flashSwapIfrField, - sizeof(flash_swap_ifr_field_config_t), kFLASH_resourceOptionFlashIfr); +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD + returnCode = + FLASH_ReadResource(config, kFLASH_ResourceRangePflashSwapIfrStart, flashSwapIfrFieldData.flashSwapIfrData, + sizeof(flashSwapIfrFieldData.flashSwapIfrData), kFLASH_ResourceOptionFlashIfr); + if (returnCode != kStatus_FLASH_Success) { return returnCode; } +#else + { + /* From RM, the actual info are stored in FCCOB6,7 */ + uint32_t returnValue[2]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapAddr, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress = (uint16_t)returnValue[0]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapEnable, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapEnableWord = (uint16_t)returnValue[0]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapDisable, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapDisableWord = (uint16_t)returnValue[0]; + } +#endif - /* The high 2 byte value of Swap Indicator Address is stored in Program Flash Swap IFR Field, - * the low 4 bit value of Swap Indicator Address is always 4'b0000 */ - swapIndicatorAddress = - (uint32_t)flashSwapIfrField.swapIndicatorAddress * FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT; + /* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field, + * the low severval bit value of Swap Indicator Address is always 1'b0 */ + swapIndicatorAddress = (uint32_t)flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress * + FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT; if (address != swapIndicatorAddress) { return kStatus_FLASH_SwapIndicatorAddressError; @@ -2599,8 +3347,8 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui /*! @brief Validates the gived flexram function option.*/ static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option) { - if ((option != kFLASH_flexramFunctionOptionAvailableAsRam) && - (option != kFLASH_flexramFunctionOptionAvailableForEeprom)) + if ((option != kFLASH_FlexramFunctionOptionAvailableAsRam) && + (option != kFLASH_FlexramFunctionOptionAvailableForEeprom)) { return kStatus_FLASH_InvalidArgument; } @@ -2608,3 +3356,77 @@ static inline status_t flasn_check_flexram_function_option_range(flash_flexram_f return kStatus_FLASH_Success; } #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +/*! @brief Gets the flash protection information (region size, region count).*/ +static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info) +{ + uint32_t pflashTotalSize; + + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + /* Clean up info Structure*/ + memset(info, 0, sizeof(flash_protection_config_t)); + +/* Note: KW40 has a secondary flash, but it doesn't have independent protection register*/ +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER) + pflashTotalSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE + + FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; + info->regionBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; +#else + pflashTotalSize = config->PFlashTotalSize; + info->regionBase = config->PFlashBlockBase; +#endif + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + info->regionCount = FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT; + } + else +#endif + { + info->regionCount = FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT; + } + + /* Calculate the size of the flash protection region + * If the flash density is > 32KB, then protection region is 1/32 of total flash density + * Else if flash density is < 32KB, then flash protection region is set to 1KB */ + if (pflashTotalSize > info->regionCount * 1024) + { + info->regionSize = (pflashTotalSize) / info->regionCount; + } + else + { + info->regionSize = 1024; + } + + return kStatus_FLASH_Success; +} + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/ +static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info) +{ + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + /* Clean up info Structure*/ + memset(info, 0, sizeof(flash_access_config_t)); + +/* Note: KW40 has a secondary flash, but it doesn't have independent access register*/ +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER) + info->SegmentBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; +#else + info->SegmentBase = config->PFlashBlockBase; +#endif + info->SegmentSize = config->PFlashAccessSegmentSize; + info->SegmentCount = config->PFlashAccessSegmentCount; + + return kStatus_FLASH_Success; +} +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h index 63463e03cb4..e143cb3e1f6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flash.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -53,21 +53,21 @@ * @name Flash version * @{ */ -/*! @brief Construct the version number for drivers. */ +/*! @brief Constructs the version number for drivers. */ #if !defined(MAKE_VERSION) #define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) #endif -/*! @brief FLASH driver version for SDK*/ -#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @brief Flash driver version for SDK*/ +#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(2, 3, 1)) /*!< Version 2.3.1. */ -/*! @brief FLASH driver version for ROM*/ +/*! @brief Flash driver version for ROM*/ enum _flash_driver_version_constants { - kFLASH_driverVersionName = 'F', /*!< Flash driver version name.*/ - kFLASH_driverVersionMajor = 2, /*!< Major flash driver version.*/ - kFLASH_driverVersionMinor = 1, /*!< Minor flash driver version.*/ - kFLASH_driverVersionBugfix = 0 /*!< Bugfix for flash driver version.*/ + kFLASH_DriverVersionName = 'F', /*!< Flash driver version name.*/ + kFLASH_DriverVersionMajor = 2, /*!< Major flash driver version.*/ + kFLASH_DriverVersionMinor = 3, /*!< Minor flash driver version.*/ + kFLASH_DriverVersionBugfix = 1 /*!< Bugfix for flash driver version.*/ }; /*@}*/ @@ -75,29 +75,41 @@ enum _flash_driver_version_constants * @name Flash configuration * @{ */ -/*! @brief Whether to support FlexNVM in flash driver */ +/*! @brief Indicates whether to support FlexNVM in the Flash driver */ #if !defined(FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT) -#define FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT 1 /*!< Enable FlexNVM support by default. */ +#define FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT 1 /*!< Enables the FlexNVM support by default. */ #endif -/*! @brief Whether the FlexNVM is enabled in flash driver */ +/*! @brief Indicates whether the FlexNVM is enabled in the Flash driver */ #define FLASH_SSD_IS_FLEXNVM_ENABLED (FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT && FSL_FEATURE_FLASH_HAS_FLEX_NVM) +/*! @brief Indicates whether to support Secondary flash in the Flash driver */ +#if !defined(FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT) +#define FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT 1 /*!< Enables the secondary flash support by default. */ +#endif + +/*! @brief Indicates whether the secondary flash is supported in the Flash driver */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) || defined(FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS) +#define FLASH_SSD_IS_SECONDARY_FLASH_ENABLED (FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT) +#else +#define FLASH_SSD_IS_SECONDARY_FLASH_ENABLED (0) +#endif + /*! @brief Flash driver location. */ #if !defined(FLASH_DRIVER_IS_FLASH_RESIDENT) #if (!defined(BL_TARGET_ROM) && !defined(BL_TARGET_RAM)) -#define FLASH_DRIVER_IS_FLASH_RESIDENT 1 /*!< Used for flash resident application. */ +#define FLASH_DRIVER_IS_FLASH_RESIDENT 1 /*!< Used for the flash resident application. */ #else -#define FLASH_DRIVER_IS_FLASH_RESIDENT 0 /*!< Used for non-flash resident application. */ +#define FLASH_DRIVER_IS_FLASH_RESIDENT 0 /*!< Used for the non-flash resident application. */ #endif #endif /*! @brief Flash Driver Export option */ #if !defined(FLASH_DRIVER_IS_EXPORTED) #if (defined(BL_TARGET_ROM) || defined(BL_TARGET_FLASH)) -#define FLASH_DRIVER_IS_EXPORTED 1 /*!< Used for ROM bootloader. */ +#define FLASH_DRIVER_IS_EXPORTED 1 /*!< Used for the ROM bootloader. */ #else -#define FLASH_DRIVER_IS_EXPORTED 0 /*!< Used for SDK application. */ +#define FLASH_DRIVER_IS_EXPORTED 0 /*!< Used for the MCUXpresso SDK application. */ #endif #endif /*@}*/ @@ -118,7 +130,7 @@ enum _flash_driver_version_constants #define kStatusGroupFlashDriver 1 #endif -/*! @brief Construct a status code value from a group and code number. */ +/*! @brief Constructs a status code value from a group and a code number. */ #if !defined(MAKE_STATUS) #define MAKE_STATUS(group, code) ((((group)*100) + (code))) #endif @@ -128,37 +140,43 @@ enum _flash_driver_version_constants */ enum _flash_status { - kStatus_FLASH_Success = MAKE_STATUS(kStatusGroupGeneric, 0), /*!< Api is executed successfully*/ + kStatus_FLASH_Success = MAKE_STATUS(kStatusGroupGeneric, 0), /*!< API is executed successfully*/ kStatus_FLASH_InvalidArgument = MAKE_STATUS(kStatusGroupGeneric, 4), /*!< Invalid argument*/ kStatus_FLASH_SizeError = MAKE_STATUS(kStatusGroupFlashDriver, 0), /*!< Error size*/ kStatus_FLASH_AlignmentError = - MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with specified baseline*/ + MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with the specified baseline*/ kStatus_FLASH_AddressError = MAKE_STATUS(kStatusGroupFlashDriver, 2), /*!< Address is out of range */ kStatus_FLASH_AccessError = - MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bounds addresses */ + MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bound addresses */ kStatus_FLASH_ProtectionViolation = MAKE_STATUS( kStatusGroupFlashDriver, 4), /*!< The program/erase operation is requested to execute on protected areas */ kStatus_FLASH_CommandFailure = MAKE_STATUS(kStatusGroupFlashDriver, 5), /*!< Run-time error during command execution. */ - kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/ - kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7), /*!< Api erase key is invalid.*/ - kStatus_FLASH_RegionExecuteOnly = MAKE_STATUS(kStatusGroupFlashDriver, 8), /*!< Current region is execute only.*/ + kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/ + kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7), /*!< API erase key is invalid.*/ + kStatus_FLASH_RegionExecuteOnly = + MAKE_STATUS(kStatusGroupFlashDriver, 8), /*!< The current region is execute-only.*/ kStatus_FLASH_ExecuteInRamFunctionNotReady = - MAKE_STATUS(kStatusGroupFlashDriver, 9), /*!< Execute-in-ram function is not available.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 9), /*!< Execute-in-RAM function is not available.*/ kStatus_FLASH_PartitionStatusUpdateFailure = MAKE_STATUS(kStatusGroupFlashDriver, 10), /*!< Failed to update partition status.*/ kStatus_FLASH_SetFlexramAsEepromError = - MAKE_STATUS(kStatusGroupFlashDriver, 11), /*!< Failed to set flexram as eeprom.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 11), /*!< Failed to set FlexRAM as EEPROM.*/ kStatus_FLASH_RecoverFlexramAsRamError = - MAKE_STATUS(kStatusGroupFlashDriver, 12), /*!< Failed to recover flexram as ram.*/ - kStatus_FLASH_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFlashDriver, 13), /*!< Failed to set flexram as ram.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 12), /*!< Failed to recover FlexRAM as RAM.*/ + kStatus_FLASH_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFlashDriver, 13), /*!< Failed to set FlexRAM as RAM.*/ kStatus_FLASH_RecoverFlexramAsEepromError = - MAKE_STATUS(kStatusGroupFlashDriver, 14), /*!< Failed to recover flexram as eeprom.*/ - kStatus_FLASH_CommandNotSupported = MAKE_STATUS(kStatusGroupFlashDriver, 15), /*!< Flash api is not supported.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 14), /*!< Failed to recover FlexRAM as EEPROM.*/ + kStatus_FLASH_CommandNotSupported = MAKE_STATUS(kStatusGroupFlashDriver, 15), /*!< Flash API is not supported.*/ kStatus_FLASH_SwapSystemNotInUninitialized = - MAKE_STATUS(kStatusGroupFlashDriver, 16), /*!< Swap system is not in uninitialzed state.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 16), /*!< Swap system is not in an uninitialzed state.*/ kStatus_FLASH_SwapIndicatorAddressError = - MAKE_STATUS(kStatusGroupFlashDriver, 17), /*!< Swap indicator address is invalid.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 17), /*!< The swap indicator address is invalid.*/ + kStatus_FLASH_ReadOnlyProperty = MAKE_STATUS(kStatusGroupFlashDriver, 18), /*!< The flash property is read-only.*/ + kStatus_FLASH_InvalidPropertyValue = + MAKE_STATUS(kStatusGroupFlashDriver, 19), /*!< The flash property value is out of range.*/ + kStatus_FLASH_InvalidSpeculationOption = + MAKE_STATUS(kStatusGroupFlashDriver, 20), /*!< The option of flash prefetch speculation is invalid.*/ }; /*@}*/ @@ -166,13 +184,13 @@ enum _flash_status * @name Flash API key * @{ */ -/*! @brief Construct the four char code for flash driver API key. */ +/*! @brief Constructs the four character code for the Flash driver API key. */ #if !defined(FOUR_CHAR_CODE) #define FOUR_CHAR_CODE(a, b, c, d) (((d) << 24) | ((c) << 16) | ((b) << 8) | ((a))) #endif /*! - * @brief Enumeration for flash driver API keys. + * @brief Enumeration for Flash driver API keys. * * @note The resulting value is built with a byte order such that the string * being readable in expected order when viewed in a hex editor, if the value @@ -180,7 +198,7 @@ enum _flash_status */ enum _flash_driver_api_keys { - kFLASH_apiEraseKey = FOUR_CHAR_CODE('k', 'f', 'e', 'k') /*!< Key value used to validate all flash erase APIs.*/ + kFLASH_ApiEraseKey = FOUR_CHAR_CODE('k', 'f', 'e', 'k') /*!< Key value used to validate all flash erase APIs.*/ }; /*@}*/ @@ -189,10 +207,10 @@ enum _flash_driver_api_keys */ typedef enum _flash_margin_value { - kFLASH_marginValueNormal, /*!< Use the 'normal' read level for 1s.*/ - kFLASH_marginValueUser, /*!< Apply the 'User' margin to the normal read-1 level.*/ - kFLASH_marginValueFactory, /*!< Apply the 'Factory' margin to the normal read-1 level.*/ - kFLASH_marginValueInvalid /*!< Not real margin level, Used to determine the range of valid margin level. */ + kFLASH_MarginValueNormal, /*!< Use the 'normal' read level for 1s.*/ + kFLASH_MarginValueUser, /*!< Apply the 'User' margin to the normal read-1 level.*/ + kFLASH_MarginValueFactory, /*!< Apply the 'Factory' margin to the normal read-1 level.*/ + kFLASH_MarginValueInvalid /*!< Not real margin level, Used to determine the range of valid margin level. */ } flash_margin_value_t; /*! @@ -200,9 +218,9 @@ typedef enum _flash_margin_value */ typedef enum _flash_security_state { - kFLASH_securityStateNotSecure, /*!< Flash is not secure.*/ - kFLASH_securityStateBackdoorEnabled, /*!< Flash backdoor is enabled.*/ - kFLASH_securityStateBackdoorDisabled /*!< Flash backdoor is disabled.*/ + kFLASH_SecurityStateNotSecure, /*!< Flash is not secure.*/ + kFLASH_SecurityStateBackdoorEnabled, /*!< Flash backdoor is enabled.*/ + kFLASH_SecurityStateBackdoorDisabled /*!< Flash backdoor is disabled.*/ } flash_security_state_t; /*! @@ -210,9 +228,9 @@ typedef enum _flash_security_state */ typedef enum _flash_protection_state { - kFLASH_protectionStateUnprotected, /*!< Flash region is not protected.*/ - kFLASH_protectionStateProtected, /*!< Flash region is protected.*/ - kFLASH_protectionStateMixed /*!< Flash is mixed with protected and unprotected region.*/ + kFLASH_ProtectionStateUnprotected, /*!< Flash region is not protected.*/ + kFLASH_ProtectionStateProtected, /*!< Flash region is protected.*/ + kFLASH_ProtectionStateMixed /*!< Flash is mixed with protected and unprotected region.*/ } flash_protection_state_t; /*! @@ -220,9 +238,9 @@ typedef enum _flash_protection_state */ typedef enum _flash_execute_only_access_state { - kFLASH_accessStateUnLimited, /*!< Flash region is unLimited.*/ - kFLASH_accessStateExecuteOnly, /*!< Flash region is execute only.*/ - kFLASH_accessStateMixed /*!< Flash is mixed with unLimited and execute only region.*/ + kFLASH_AccessStateUnLimited, /*!< Flash region is unlimited.*/ + kFLASH_AccessStateExecuteOnly, /*!< Flash region is execute only.*/ + kFLASH_AccessStateMixed /*!< Flash is mixed with unlimited and execute only region.*/ } flash_execute_only_access_state_t; /*! @@ -230,41 +248,43 @@ typedef enum _flash_execute_only_access_state */ typedef enum _flash_property_tag { - kFLASH_propertyPflashSectorSize = 0x00U, /*!< Pflash sector size property.*/ - kFLASH_propertyPflashTotalSize = 0x01U, /*!< Pflash total size property.*/ - kFLASH_propertyPflashBlockSize = 0x02U, /*!< Pflash block size property.*/ - kFLASH_propertyPflashBlockCount = 0x03U, /*!< Pflash block count property.*/ - kFLASH_propertyPflashBlockBaseAddr = 0x04U, /*!< Pflash block base address property.*/ - kFLASH_propertyPflashFacSupport = 0x05U, /*!< Pflash fac support property.*/ - kFLASH_propertyPflashAccessSegmentSize = 0x06U, /*!< Pflash access segment size property.*/ - kFLASH_propertyPflashAccessSegmentCount = 0x07U, /*!< Pflash access segment count property.*/ - kFLASH_propertyFlexRamBlockBaseAddr = 0x08U, /*!< FlexRam block base address property.*/ - kFLASH_propertyFlexRamTotalSize = 0x09U, /*!< FlexRam total size property.*/ - kFLASH_propertyDflashSectorSize = 0x10U, /*!< Dflash sector size property.*/ - kFLASH_propertyDflashTotalSize = 0x11U, /*!< Dflash total size property.*/ - kFLASH_propertyDflashBlockSize = 0x12U, /*!< Dflash block count property.*/ - kFLASH_propertyDflashBlockCount = 0x13U, /*!< Dflash block base address property.*/ - kFLASH_propertyDflashBlockBaseAddr = 0x14U, /*!< Eeprom total size property.*/ - kFLASH_propertyEepromTotalSize = 0x15U + kFLASH_PropertyPflashSectorSize = 0x00U, /*!< Pflash sector size property.*/ + kFLASH_PropertyPflashTotalSize = 0x01U, /*!< Pflash total size property.*/ + kFLASH_PropertyPflashBlockSize = 0x02U, /*!< Pflash block size property.*/ + kFLASH_PropertyPflashBlockCount = 0x03U, /*!< Pflash block count property.*/ + kFLASH_PropertyPflashBlockBaseAddr = 0x04U, /*!< Pflash block base address property.*/ + kFLASH_PropertyPflashFacSupport = 0x05U, /*!< Pflash fac support property.*/ + kFLASH_PropertyPflashAccessSegmentSize = 0x06U, /*!< Pflash access segment size property.*/ + kFLASH_PropertyPflashAccessSegmentCount = 0x07U, /*!< Pflash access segment count property.*/ + kFLASH_PropertyFlexRamBlockBaseAddr = 0x08U, /*!< FlexRam block base address property.*/ + kFLASH_PropertyFlexRamTotalSize = 0x09U, /*!< FlexRam total size property.*/ + kFLASH_PropertyDflashSectorSize = 0x10U, /*!< Dflash sector size property.*/ + kFLASH_PropertyDflashTotalSize = 0x11U, /*!< Dflash total size property.*/ + kFLASH_PropertyDflashBlockSize = 0x12U, /*!< Dflash block size property.*/ + kFLASH_PropertyDflashBlockCount = 0x13U, /*!< Dflash block count property.*/ + kFLASH_PropertyDflashBlockBaseAddr = 0x14U, /*!< Dflash block base address property.*/ + kFLASH_PropertyEepromTotalSize = 0x15U, /*!< EEPROM total size property.*/ + kFLASH_PropertyFlashMemoryIndex = 0x20U, /*!< Flash memory index property.*/ + kFLASH_PropertyFlashCacheControllerIndex = 0x21U /*!< Flash cache controller index property.*/ } flash_property_tag_t; /*! - * @brief Constants for execute-in-ram flash function. + * @brief Constants for execute-in-RAM flash function. */ enum _flash_execute_in_ram_function_constants { - kFLASH_executeInRamFunctionMaxSize = 64U, /*!< Max size of execute-in-ram function.*/ - kFLASH_executeInRamFunctionTotalNum = 2U /*!< Total number of execute-in-ram functions.*/ + kFLASH_ExecuteInRamFunctionMaxSizeInWords = 16U, /*!< The maximum size of execute-in-RAM function.*/ + kFLASH_ExecuteInRamFunctionTotalNum = 2U /*!< Total number of execute-in-RAM functions.*/ }; /*! - * @brief Flash execute-in-ram function information. + * @brief Flash execute-in-RAM function information. */ typedef struct _flash_execute_in_ram_function_config { - uint32_t activeFunctionCount; /*!< Number of available execute-in-ram functions.*/ - uint8_t *flashRunCommand; /*!< execute-in-ram function: flash_run_command.*/ - uint8_t *flashCacheClearCommand; /*!< execute-in-ram function: flash_cache_clear_command.*/ + uint32_t activeFunctionCount; /*!< Number of available execute-in-RAM functions.*/ + uint32_t *flashRunCommand; /*!< Execute-in-RAM function: flash_run_command.*/ + uint32_t *flashCommonBitOperation; /*!< Execute-in-RAM function: flash_common_bit_operation.*/ } flash_execute_in_ram_function_config_t; /*! @@ -272,9 +292,9 @@ typedef struct _flash_execute_in_ram_function_config */ typedef enum _flash_read_resource_option { - kFLASH_resourceOptionFlashIfr = + kFLASH_ResourceOptionFlashIfr = 0x00U, /*!< Select code for Program flash 0 IFR, Program flash swap 0 IFR, Data flash 0 IFR */ - kFLASH_resourceOptionVersionId = 0x01U /*!< Select code for Version ID*/ + kFLASH_ResourceOptionVersionId = 0x01U /*!< Select code for the version ID*/ } flash_read_resource_option_t; /*! @@ -283,124 +303,262 @@ typedef enum _flash_read_resource_option enum _flash_read_resource_range { #if (FSL_FEATURE_FLASH_IS_FTFE == 1) - kFLASH_resourceRangePflashIfrSizeInBytes = 1024U, /*!< Pflash IFR size in byte.*/ - kFLASH_resourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ - kFLASH_resourceRangeVersionIdStart = 0x08U, /*!< Version ID IFR start address.*/ - kFLASH_resourceRangeVersionIdEnd = 0x0FU, /*!< Version ID IFR end address.*/ -#else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */ - kFLASH_resourceRangePflashIfrSizeInBytes = 256U, /*!< Pflash IFR size in byte.*/ - kFLASH_resourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ - kFLASH_resourceRangeVersionIdStart = 0x00U, /*!< Version ID IFR start address.*/ - kFLASH_resourceRangeVersionIdEnd = 0x07U, /*!< Version ID IFR end address.*/ + kFLASH_ResourceRangePflashIfrSizeInBytes = 1024U, /*!< Pflash IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdStart = 0x08U, /*!< Version ID IFR start address.*/ + kFLASH_ResourceRangeVersionIdEnd = 0x0FU, /*!< Version ID IFR end address.*/ + kFLASH_ResourceRangePflashSwapIfrStart = 0x40000U, /*!< Pflash swap IFR start address.*/ + kFLASH_ResourceRangePflashSwapIfrEnd = + (kFLASH_ResourceRangePflashSwapIfrStart + 0x3FFU), /*!< Pflash swap IFR end address.*/ +#else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */ + kFLASH_ResourceRangePflashIfrSizeInBytes = 256U, /*!< Pflash IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdSizeInBytes = 8U, /*!< Version ID IFR size in byte.*/ + kFLASH_ResourceRangeVersionIdStart = 0x00U, /*!< Version ID IFR start address.*/ + kFLASH_ResourceRangeVersionIdEnd = 0x07U, /*!< Version ID IFR end address.*/ +#if 0x20000U == (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) + kFLASH_ResourceRangePflashSwapIfrStart = 0x8000U, /*!< Pflash swap IFR start address.*/ +#elif 0x40000U == (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) + kFLASH_ResourceRangePflashSwapIfrStart = 0x10000U, /*!< Pflash swap IFR start address.*/ +#elif 0x80000U == (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) + kFLASH_ResourceRangePflashSwapIfrStart = 0x20000U, /*!< Pflash swap IFR start address.*/ +#else + kFLASH_ResourceRangePflashSwapIfrStart = 0, #endif - kFLASH_resourceRangePflashSwapIfrStart = 0x40000U, /*!< Pflash swap IFR start address.*/ - kFLASH_resourceRangePflashSwapIfrEnd = 0x403FFU, /*!< Pflash swap IFR end address.*/ - kFLASH_resourceRangeDflashIfrStart = 0x800000U, /*!< Dflash IFR start address.*/ - kFLASH_resourceRangeDflashIfrEnd = 0x8003FFU, /*!< Dflash IFR end address.*/ + kFLASH_ResourceRangePflashSwapIfrEnd = + (kFLASH_ResourceRangePflashSwapIfrStart + 0xFFU), /*!< Pflash swap IFR end address.*/ +#endif + kFLASH_ResourceRangeDflashIfrStart = 0x800000U, /*!< Dflash IFR start address.*/ + kFLASH_ResourceRangeDflashIfrEnd = 0x8003FFU, /*!< Dflash IFR end address.*/ +}; + +/*! + * @brief Enumeration for the index of read/program once record + */ +enum _k3_flash_read_once_index +{ + kFLASH_RecordIndexSwapAddr = 0xA1U, /*!< Index of Swap indicator address.*/ + kFLASH_RecordIndexSwapEnable = 0xA2U, /*!< Index of Swap system enable.*/ + kFLASH_RecordIndexSwapDisable = 0xA3U, /*!< Index of Swap system disable.*/ }; /*! - * @brief Enumeration for the two possilbe options of set flexram function command. + * @brief Enumeration for the two possilbe options of set FlexRAM function command. */ typedef enum _flash_flexram_function_option { - kFLASH_flexramFunctionOptionAvailableAsRam = 0xFFU, /*!< Option used to make FlexRAM available as RAM */ - kFLASH_flexramFunctionOptionAvailableForEeprom = 0x00U /*!< Option used to make FlexRAM available for EEPROM */ + kFLASH_FlexramFunctionOptionAvailableAsRam = 0xFFU, /*!< An option used to make FlexRAM available as RAM */ + kFLASH_FlexramFunctionOptionAvailableForEeprom = 0x00U /*!< An option used to make FlexRAM available for EEPROM */ } flash_flexram_function_option_t; +/*! + * @brief Enumeration for acceleration RAM property. + */ +enum _flash_acceleration_ram_property +{ + kFLASH_AccelerationRamSize = 0x400U +}; + /*! * @brief Enumeration for the possible options of Swap function */ typedef enum _flash_swap_function_option { - kFLASH_swapFunctionOptionEnable = 0x00U, /*!< Option used to enable Swap function */ - kFLASH_swapFunctionOptionDisable = 0x01U /*!< Option used to Disable Swap function */ + kFLASH_SwapFunctionOptionEnable = 0x00U, /*!< An option used to enable the Swap function */ + kFLASH_SwapFunctionOptionDisable = 0x01U /*!< An option used to disable the Swap function */ } flash_swap_function_option_t; /*! - * @brief Enumeration for the possible options of Swap Control commands + * @brief Enumeration for the possible options of Swap control commands */ typedef enum _flash_swap_control_option { - kFLASH_swapControlOptionIntializeSystem = 0x01U, /*!< Option used to Intialize Swap System */ - kFLASH_swapControlOptionSetInUpdateState = 0x02U, /*!< Option used to Set Swap in Update State */ - kFLASH_swapControlOptionSetInCompleteState = 0x04U, /*!< Option used to Set Swap in Complete State */ - kFLASH_swapControlOptionReportStatus = 0x08U, /*!< Option used to Report Swap Status */ - kFLASH_swapControlOptionDisableSystem = 0x10U /*!< Option used to Disable Swap Status */ + kFLASH_SwapControlOptionIntializeSystem = 0x01U, /*!< An option used to initialize the Swap system */ + kFLASH_SwapControlOptionSetInUpdateState = 0x02U, /*!< An option used to set the Swap in an update state */ + kFLASH_SwapControlOptionSetInCompleteState = 0x04U, /*!< An option used to set the Swap in a complete state */ + kFLASH_SwapControlOptionReportStatus = 0x08U, /*!< An option used to report the Swap status */ + kFLASH_SwapControlOptionDisableSystem = 0x10U /*!< An option used to disable the Swap status */ } flash_swap_control_option_t; /*! - * @brief Enumeration for the possible flash swap status. + * @brief Enumeration for the possible flash Swap status. */ typedef enum _flash_swap_state { - kFLASH_swapStateUninitialized = 0x00U, /*!< Flash swap system is in uninitialized state.*/ - kFLASH_swapStateReady = 0x01U, /*!< Flash swap system is in ready state.*/ - kFLASH_swapStateUpdate = 0x02U, /*!< Flash swap system is in update state.*/ - kFLASH_swapStateUpdateErased = 0x03U, /*!< Flash swap system is in updateErased state.*/ - kFLASH_swapStateComplete = 0x04U, /*!< Flash swap system is in complete state.*/ - kFLASH_swapStateDisabled = 0x05U /*!< Flash swap system is in disabled state.*/ + kFLASH_SwapStateUninitialized = 0x00U, /*!< Flash Swap system is in an uninitialized state.*/ + kFLASH_SwapStateReady = 0x01U, /*!< Flash Swap system is in a ready state.*/ + kFLASH_SwapStateUpdate = 0x02U, /*!< Flash Swap system is in an update state.*/ + kFLASH_SwapStateUpdateErased = 0x03U, /*!< Flash Swap system is in an updateErased state.*/ + kFLASH_SwapStateComplete = 0x04U, /*!< Flash Swap system is in a complete state.*/ + kFLASH_SwapStateDisabled = 0x05U /*!< Flash Swap system is in a disabled state.*/ } flash_swap_state_t; /*! - * @breif Enumeration for the possible flash swap block status + * @breif Enumeration for the possible flash Swap block status */ typedef enum _flash_swap_block_status { - kFLASH_swapBlockStatusLowerHalfProgramBlocksAtZero = + kFLASH_SwapBlockStatusLowerHalfProgramBlocksAtZero = 0x00U, /*!< Swap block status is that lower half program block at zero.*/ - kFLASH_swapBlockStatusUpperHalfProgramBlocksAtZero = + kFLASH_SwapBlockStatusUpperHalfProgramBlocksAtZero = 0x01U, /*!< Swap block status is that upper half program block at zero.*/ } flash_swap_block_status_t; /*! - * @brief Flash Swap information. + * @brief Flash Swap information */ typedef struct _flash_swap_state_config { - flash_swap_state_t flashSwapState; /*!< Current swap system status.*/ - flash_swap_block_status_t currentSwapBlockStatus; /*!< Current swap block status.*/ - flash_swap_block_status_t nextSwapBlockStatus; /*!< Next swap block status.*/ + flash_swap_state_t flashSwapState; /*!chip = 0; fbConfig->writeProtect = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c index 15e1f55f437..f58f3f55f05 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -165,8 +165,6 @@ static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_ /******************************************************************************* * Variables ******************************************************************************/ -/* Array of FlexCAN handle. */ -static flexcan_handle_t *s_flexcanHandle[FSL_FEATURE_SOC_FLEXCAN_COUNT]; /* Array of FlexCAN peripheral base address. */ static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS; @@ -179,8 +177,17 @@ static const IRQn_Type s_flexcanErrorIRQ[] = CAN_Error_IRQS; static const IRQn_Type s_flexcanBusOffIRQ[] = CAN_Bus_Off_IRQS; static const IRQn_Type s_flexcanMbIRQ[] = CAN_ORed_Message_buffer_IRQS; +/* Array of FlexCAN handle. */ +static flexcan_handle_t *s_flexcanHandle[ARRAY_SIZE(s_flexcanBases)]; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of FlexCAN clock name. */ static const clock_ip_name_t s_flexcanClock[] = FLEXCAN_CLOCKS; +#if defined(FLEXCAN_PERIPH_CLOCKS) +/* Array of FlexCAN serial clock name. */ +static const clock_ip_name_t s_flexcanPeriphClock[] = FLEXCAN_PERIPH_CLOCKS; +#endif /* FLEXCAN_PERIPH_CLOCKS */ +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* FlexCAN ISR for transactional APIs. */ static flexcan_isr_t s_flexcanIsr; @@ -194,7 +201,7 @@ uint32_t FLEXCAN_GetInstance(CAN_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_FLEXCAN_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_flexcanBases); instance++) { if (s_flexcanBases[instance] == base) { @@ -202,7 +209,7 @@ uint32_t FLEXCAN_GetInstance(CAN_Type *base) } } - assert(instance < FSL_FEATURE_SOC_FLEXCAN_COUNT); + assert(instance < ARRAY_SIZE(s_flexcanBases)); return instance; } @@ -314,9 +321,13 @@ static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx) else { if (base->IMASK2 & ((uint32_t)(1 << (mbIdx - 32)))) + { return true; + } else + { return false; + } } #endif } @@ -420,14 +431,25 @@ static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz) { uint32_t mcrTemp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance; +#endif /* Assertion. */ assert(config); assert((config->maxMbNum > 0) && (config->maxMbNum <= FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + instance = FLEXCAN_GetInstance(base); /* Enable FlexCAN clock. */ - CLOCK_EnableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); - + CLOCK_EnableClock(s_flexcanClock[instance]); +#if defined(FLEXCAN_PERIPH_CLOCKS) + /* Enable FlexCAN serial clock. */ + CLOCK_EnableClock(s_flexcanPeriphClock[instance]); +#endif /* FLEXCAN_PERIPH_CLOCKS */ +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE /* Disable FlexCAN Module. */ FLEXCAN_Enable(base, false); @@ -436,6 +458,7 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc */ base->CTRL1 = (kFLEXCAN_ClkSrcOsc == config->clkSrc) ? base->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK : base->CTRL1 | CAN_CTRL1_CLKSRC_MASK; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ /* Enable FlexCAN Module for configuartion. */ FLEXCAN_Enable(base, true); @@ -472,14 +495,24 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc void FLEXCAN_Deinit(CAN_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance; +#endif /* Reset all Register Contents. */ FLEXCAN_Reset(base); /* Disable FlexCAN module. */ FLEXCAN_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + instance = FLEXCAN_GetInstance(base); +#if defined(FLEXCAN_PERIPH_CLOCKS) + /* Disable FlexCAN serial clock. */ + CLOCK_DisableClock(s_flexcanPeriphClock[instance]); +#endif /* FLEXCAN_PERIPH_CLOCKS */ /* Disable FlexCAN clock. */ - CLOCK_DisableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); + CLOCK_DisableClock(s_flexcanClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) @@ -488,7 +521,9 @@ void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) assert(config); /* Initialize FlexCAN Module config struct with default value. */ +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE config->clkSrc = kFLEXCAN_ClkSrcOsc; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ config->baudRate = 125000U; config->maxMbNum = 16; config->enableLoopBack = false; @@ -1293,13 +1328,13 @@ void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle) (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); #else - while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || - (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | - kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); + while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || + (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | + kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); #endif } -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 0) +#if defined(CAN0) void CAN0_DriverIRQHandler(void) { assert(s_flexcanHandle[0]); @@ -1308,7 +1343,7 @@ void CAN0_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 1) +#if defined(CAN1) void CAN1_DriverIRQHandler(void) { assert(s_flexcanHandle[1]); @@ -1317,7 +1352,7 @@ void CAN1_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 2) +#if defined(CAN2) void CAN2_DriverIRQHandler(void) { assert(s_flexcanHandle[2]); @@ -1326,7 +1361,7 @@ void CAN2_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 3) +#if defined(CAN3) void CAN3_DriverIRQHandler(void) { assert(s_flexcanHandle[3]); @@ -1335,7 +1370,7 @@ void CAN3_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 4) +#if defined(CAN4) void CAN4_DriverIRQHandler(void) { assert(s_flexcanHandle[4]); @@ -1343,3 +1378,30 @@ void CAN4_DriverIRQHandler(void) s_flexcanIsr(CAN4, s_flexcanHandle[4]); } #endif + +#if defined(DMA_CAN0) +void DMA_FLEXCAN0_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]); + + s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]); +} +#endif + +#if defined(DMA_CAN1) +void DMA_FLEXCAN1_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]); + + s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]); +} +#endif + +#if defined(DMA_CAN2) +void DMA_FLEXCAN2_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]); + + s_flexcanIsr(DMA_CAN2, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]); +} +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h index 13c28f357d4..118badf58fb 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_flexcan.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,15 +37,14 @@ * @{ */ - /****************************************************************************** * Definitions *****************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief FlexCAN driver version 2.1.0. */ -#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief FlexCAN driver version 2.2.0. */ +#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*@}*/ /*! @brief FlexCAN Frame ID helper macro. */ @@ -69,19 +68,18 @@ (FLEXCAN_ID_STD(id) << 1)) /*!< Standard Rx FIFO Mask helper macro Type A helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_HIGH(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ - (FLEXCAN_ID_STD(id) << 16)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ + (((uint32_t)(id) & 0x7FF) << 19)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_LOW(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 15) | (uint32_t)((uint32_t)(ide) << 14)) | \ - FLEXCAN_ID_STD(id)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ + (((uint32_t)(id) & 0x7FF) << 3)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_HIGH(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ -#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. \ - */ + (((uint32_t)(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ + (((uint32_t)(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_LOW(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ + (((uint32_t)(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_LOW(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ + (((uint32_t)(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ #define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_A(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ (FLEXCAN_ID_EXT(id) << 1)) /*!< Extend Rx FIFO Mask helper macro Type A helper macro. */ @@ -157,7 +155,7 @@ enum _flexcan_status kStatus_FLEXCAN_RxFifoBusy = MAKE_STATUS(kStatusGroup_FLEXCAN, 6), /*!< Rx Message FIFO is Busy. */ kStatus_FLEXCAN_RxFifoIdle = MAKE_STATUS(kStatusGroup_FLEXCAN, 7), /*!< Rx Message FIFO is Idle. */ kStatus_FLEXCAN_RxFifoOverflow = MAKE_STATUS(kStatusGroup_FLEXCAN, 8), /*!< Rx Message FIFO is overflowed. */ - kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 0), /*!< Rx Message FIFO is almost overflowed. */ + kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 9), /*!< Rx Message FIFO is almost overflowed. */ kStatus_FLEXCAN_ErrorStatus = MAKE_STATUS(kStatusGroup_FLEXCAN, 10), /*!< FlexCAN Module Error and Status. */ kStatus_FLEXCAN_UnHandled = MAKE_STATUS(kStatusGroup_FLEXCAN, 11), /*!< UnHadled Interrupt asserted. */ }; @@ -176,12 +174,14 @@ typedef enum _flexcan_frame_type kFLEXCAN_FrameTypeRemote = 0x1U, /*!< Remote frame type attribute. */ } flexcan_frame_type_t; +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE /*! @brief FlexCAN clock source. */ typedef enum _flexcan_clock_source { kFLEXCAN_ClkSrcOsc = 0x0U, /*!< FlexCAN Protocol Engine clock from Oscillator. */ kFLEXCAN_ClkSrcPeri = 0x1U, /*!< FlexCAN Protocol Engine clock from Peripheral Clock. */ } flexcan_clock_source_t; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ /*! @brief FlexCAN Rx Fifo Filter type. */ typedef enum _flexcan_rx_fifo_filter_type @@ -195,7 +195,7 @@ typedef enum _flexcan_rx_fifo_filter_type } flexcan_rx_fifo_filter_type_t; /*! - * @brief FlexCAN Rx FIFO priority + * @brief FlexCAN Rx FIFO priority. * * The matching process starts from the Rx MB(or Rx FIFO) with higher priority. * If no MB(or Rx FIFO filter) is satisfied, the matching process goes on with @@ -326,7 +326,9 @@ typedef struct _flexcan_frame typedef struct _flexcan_config { uint32_t baudRate; /*!< FlexCAN baud rate in bps. */ +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE flexcan_clock_source_t clkSrc; /*!< Clock source for FlexCAN Protocol Engine. */ +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ uint8_t maxMbNum; /*!< The maximum number of Message Buffers used by user. */ bool enableLoopBack; /*!< Enable or Disable Loop Back Self Test Mode. */ bool enableSelfWakeup; /*!< Enable or Disable Self Wakeup Mode. */ @@ -366,7 +368,7 @@ typedef struct _flexcan_rx_mb_config /*! @brief FlexCAN Rx FIFO configuration structure. */ typedef struct _flexcan_rx_fifo_config { - uint32_t *idFilterTable; /*!< Pointer to FlexCAN Rx FIFO identifier filter table. */ + uint32_t *idFilterTable; /*!< Pointer to the FlexCAN Rx FIFO identifier filter table. */ uint8_t idFilterNum; /*!< The quantity of filter elements. */ flexcan_rx_fifo_filter_type_t idFilterType; /*!< The FlexCAN Rx FIFO Filter type. */ flexcan_rx_fifo_priority_t priority; /*!< The FlexCAN Rx FIFO receive priority. */ @@ -431,7 +433,7 @@ extern "C" { * * This function initializes the FlexCAN module with user-defined settings. * This example shows how to set up the flexcan_config_t parameters and how - * to call the FLEXCAN_Init function by passing in these parameters: + * to call the FLEXCAN_Init function by passing in these parameters. * @code * flexcan_config_t flexcanConfig; * flexcanConfig.clkSrc = kFLEXCAN_ClkSrcOsc; @@ -445,7 +447,7 @@ extern "C" { * @endcode * * @param base FlexCAN peripheral base address. - * @param config Pointer to user-defined configuration structure. + * @param config Pointer to the user-defined configuration structure. * @param sourceClock_Hz FlexCAN Protocol Engine clock source frequency in Hz. */ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz); @@ -453,18 +455,18 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc /*! * @brief De-initializes a FlexCAN instance. * - * This function disable the FlexCAN module clock and set all register value - * to reset value. + * This function disables the FlexCAN module clock and sets all register values + * to the reset value. * * @param base FlexCAN peripheral base address. */ void FLEXCAN_Deinit(CAN_Type *base); /*! - * @brief Get the default configuration structure. + * @brief Gets the default configuration structure. * - * This function initializes the FlexCAN configuration structure to default value. The default - * value are: + * This function initializes the FlexCAN configuration structure to default values. The default + * values are as follows. * flexcanConfig->clkSrc = KFLEXCAN_ClkSrcOsc; * flexcanConfig->baudRate = 125000U; * flexcanConfig->maxMbNum = 16; @@ -473,7 +475,7 @@ void FLEXCAN_Deinit(CAN_Type *base); * flexcanConfig->enableIndividMask = false; * flexcanConfig->enableDoze = false; * - * @param config Pointer to FlexCAN configuration structure. + * @param config Pointer to the FlexCAN configuration structure. */ void FLEXCAN_GetDefaultConfig(flexcan_config_t *config); @@ -503,7 +505,7 @@ void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *conf /*! * @brief Sets the FlexCAN receive message buffer global mask. * - * This function sets the global mask for FlexCAN message buffer in a matching process. + * This function sets the global mask for the FlexCAN message buffer in a matching process. * The configuration is only effective when the Rx individual mask is disabled in the FLEXCAN_Init(). * * @param base FlexCAN peripheral base address. @@ -524,12 +526,12 @@ void FLEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask); /*! * @brief Sets the FlexCAN receive individual mask. * - * This function sets the individual mask for FlexCAN matching process. - * The configuration is only effective when the Rx individual mask is enabled in FLEXCAN_Init(). - * If Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. - * If Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to - * the Rx Filter with same index. What calls for special attention is that only the first 32 - * individual masks can be used as Rx FIFO filter mask. + * This function sets the individual mask for the FlexCAN matching process. + * The configuration is only effective when the Rx individual mask is enabled in the FLEXCAN_Init(). + * If the Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. + * If the Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to + * the Rx Filter with the same index. Note that only the first 32 + * individual masks can be used as the Rx FIFO filter mask. * * @param base FlexCAN peripheral base address. * @param maskIdx The Index of individual Mask. @@ -545,7 +547,7 @@ void FLEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask) * * @param base FlexCAN peripheral base address. * @param mbIdx The Message Buffer index. - * @param enable Enable/Disable Tx Message Buffer. + * @param enable Enable/disable Tx Message Buffer. * - true: Enable Tx Message Buffer. * - false: Disable Tx Message Buffer. */ @@ -559,8 +561,8 @@ void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable); * * @param base FlexCAN peripheral base address. * @param mbIdx The Message Buffer index. - * @param config Pointer to FlexCAN Message Buffer configuration structure. - * @param enable Enable/Disable Rx Message Buffer. + * @param config Pointer to the FlexCAN Message Buffer configuration structure. + * @param enable Enable/disable Rx Message Buffer. * - true: Enable Rx Message Buffer. * - false: Disable Rx Message Buffer. */ @@ -572,8 +574,8 @@ void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_co * This function configures the Rx FIFO with given Rx FIFO configuration. * * @param base FlexCAN peripheral base address. - * @param config Pointer to FlexCAN Rx FIFO configuration structure. - * @param enable Enable/Disable Rx FIFO. + * @param config Pointer to the FlexCAN Rx FIFO configuration structure. + * @param enable Enable/disable Rx FIFO. * - true: Enable Rx FIFO. * - false: Disable Rx FIFO. */ @@ -676,7 +678,7 @@ static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFF); + base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFFU); base->IFLAG2 = (uint32_t)(mask >> 32); #else base->IFLAG1 = mask; @@ -691,9 +693,9 @@ static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) */ /*! - * @brief Enables FlexCAN interrupts according to provided mask. + * @brief Enables FlexCAN interrupts according to the provided mask. * - * This function enables the FlexCAN interrupts according to provided mask. The mask + * This function enables the FlexCAN interrupts according to the provided mask. The mask * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. * * @param base FlexCAN peripheral base address. @@ -712,9 +714,9 @@ static inline void FLEXCAN_EnableInterrupts(CAN_Type *base, uint32_t mask) } /*! - * @brief Disables FlexCAN interrupts according to provided mask. + * @brief Disables FlexCAN interrupts according to the provided mask. * - * This function disables the FlexCAN interrupts according to provided mask. The mask + * This function disables the FlexCAN interrupts according to the provided mask. The mask * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. * * @param base FlexCAN peripheral base address. @@ -735,7 +737,7 @@ static inline void FLEXCAN_DisableInterrupts(CAN_Type *base, uint32_t mask) /*! * @brief Enables FlexCAN Message Buffer interrupts. * - * This function enables the interrupts of given Message Buffers + * This function enables the interrupts of given Message Buffers. * * @param base FlexCAN peripheral base address. * @param mask The ORed FlexCAN Message Buffer mask. @@ -747,7 +749,7 @@ static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFF); + base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFFU); base->IMASK2 |= (uint32_t)(mask >> 32); #else base->IMASK1 |= mask; @@ -757,7 +759,7 @@ static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) /*! * @brief Disables FlexCAN Message Buffer interrupts. * - * This function disables the interrupts of given Message Buffers + * This function disables the interrupts of given Message Buffers. * * @param base FlexCAN peripheral base address. * @param mask The ORed FlexCAN Message Buffer mask. @@ -769,7 +771,7 @@ static inline void FLEXCAN_DisableMbInterrupts(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFF)); + base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFFU)); base->IMASK2 &= ~((uint32_t)(mask >> 32)); #else base->IMASK1 &= ~mask; @@ -846,7 +848,7 @@ static inline void FLEXCAN_Enable(CAN_Type *base, bool enable) } /*! - * @brief Writes a FlexCAN Message to Transmit Message Buffer. + * @brief Writes a FlexCAN Message to the Transmit Message Buffer. * * This function writes a CAN Message to the specified Transmit Message Buffer * and changes the Message Buffer state to start CAN Message transmit. After @@ -938,7 +940,7 @@ status_t FLEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *rx /*! * @brief Initializes the FlexCAN handle. * - * This function initializes the FlexCAN handle which can be used for other FlexCAN + * This function initializes the FlexCAN handle, which can be used for other FlexCAN * transactional APIs. Usually, for a specified FlexCAN instance, * call this API once to get the initialized handle. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c index 85dc2194254..9cca44b0e41 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -72,8 +72,10 @@ static void FTM_SetReloadPoints(FTM_Type *base, uint32_t reloadPoints); /*! @brief Pointers to FTM bases for each instance. */ static FTM_Type *const s_ftmBases[] = FTM_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to FTM clocks for each instance. */ static const clock_ip_name_t s_ftmClocks[] = FTM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -228,8 +230,10 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) return kStatus_Fail; } +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate the FTM clock*/ CLOCK_EnableClock(s_ftmClocks[FTM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure the fault mode, enable FTM mode and disable write protection */ base->MODE = FTM_MODE_FAULTM(config->faultMode) | FTM_MODE_FTMEN_MASK | FTM_MODE_WPDIS_MASK; @@ -266,7 +270,13 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) #endif /* FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER */ /* FTM deadtime insertion control */ - base->DEADTIME = (FTM_DEADTIME_DTPS(config->deadTimePrescale) | FTM_DEADTIME_DTVAL(config->deadTimeValue)); + base->DEADTIME = (0u | +#if defined(FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) && (FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) + /* Has extended deadtime value register) */ + FTM_DEADTIME_DTVALEX(config->deadTimeValue >> 6) | +#endif /* FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE */ + FTM_DEADTIME_DTPS(config->deadTimePrescale) | + FTM_DEADTIME_DTVAL(config->deadTimeValue)); /* FTM fault filter value */ reg = base->FLTCTRL; @@ -282,8 +292,10 @@ void FTM_Deinit(FTM_Type *base) /* Set clock source to none to disable counter */ base->SC &= ~(FTM_SC_CLKS_MASK); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the FTM clock */ CLOCK_DisableClock(s_ftmClocks[FTM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void FTM_GetDefaultConfig(ftm_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h index 2fb1c08e49c..8db81a633ac 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_ftm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -#define FSL_FTM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */ -/*@}*/ +#define FSL_FTM_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2 */ + /*@}*/ /*! * @brief List of FTM channels @@ -162,7 +161,7 @@ typedef struct _ftm_phase_param typedef struct _ftm_fault_param { bool enableFaultInput; /*!< True: Fault input is enabled; false: Fault input is disabled */ - bool faultLevel; /*!< True: Fault polarity is active low i.e., '0' indicates a fault; + bool faultLevel; /*!< True: Fault polarity is active low; in other words, '0' indicates a fault; False: Fault polarity is active high */ bool useFaultFilter; /*!< True: Use the filtered fault signal; False: Use the direct path from fault input */ @@ -310,6 +309,17 @@ typedef enum _ftm_status_flags kFTM_ReloadFlag = (1U << 11) /*!< Reload Flag; Available only on certain SoC's */ } ftm_status_flags_t; +/*! + * @brief List of FTM Quad Decoder flags. + */ +enum _ftm_quad_decoder_flags +{ + kFTM_QuadDecoderCountingIncreaseFlag = FTM_QDCTRL_QUADIR_MASK, /*!< Counting direction is increasing (FTM counter + increment), or the direction is decreasing. */ + kFTM_QuadDecoderCountingOverflowOnTopFlag = FTM_QDCTRL_TOFDIR_MASK, /*!< Indicates if the TOF bit was set on the top + or the bottom of counting. */ +}; + /*! * @brief FTM configuration structure * @@ -333,7 +343,9 @@ typedef struct _ftm_config ftm_fault_mode_t faultMode; /*!< FTM fault control mode */ uint8_t faultFilterValue; /*!< Fault input filter value */ ftm_deadtime_prescale_t deadTimePrescale; /*!< The dead time prescalar value */ - uint8_t deadTimeValue; /*!< The dead time value */ + uint32_t deadTimeValue; /*!< The dead time value + deadTimeValue's available range is 0-1023 when register has DTVALEX, + otherwise its available range is 0-63. */ uint32_t extTriggers; /*!< External triggers to enable. Multiple trigger sources can be enabled by providing an OR'ed list of options available in enumeration ::ftm_external_trigger_t. */ @@ -359,7 +371,7 @@ extern "C" { /*! * @brief Ungates the FTM clock and configures the peripheral for basic operation. * - * @note This API should be called at the beginning of the application using the FTM driver. + * @note This API should be called at the beginning of the application which is using the FTM driver. * * @param base FTM peripheral base address * @param config Pointer to the user configuration structure. @@ -508,19 +520,6 @@ void FTM_SetupDualEdgeCapture(FTM_Type *base, /*! @}*/ -/*! - * @brief Configures the parameters and activates the quadrature decoder mode. - * - * @param base FTM peripheral base address - * @param phaseAParams Phase A configuration parameters - * @param phaseBParams Phase B configuration parameters - * @param quadMode Selects encoding mode used in quadrature decoder mode - */ -void FTM_SetupQuadDecode(FTM_Type *base, - const ftm_phase_params_t *phaseAParams, - const ftm_phase_params_t *phaseBParams, - ftm_quad_decode_mode_t quadMode); - /*! * @brief Sets up the working of the FTM fault protection. * @@ -593,6 +592,48 @@ void FTM_ClearStatusFlags(FTM_Type *base, uint32_t mask); /*! @}*/ +/*! + * @name Read and write the timer period + * @{ + */ + +/*! + * @brief Sets the timer period in units of ticks. + * + * Timers counts from 0 until it equals the count value set here. The count value is written to + * the MOD register. + * + * @note + * 1. This API allows the user to use the FTM module as a timer. Do not mix usage + * of this API with FTM's PWM setup API's. + * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks. + * + * @param base FTM peripheral base address + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. + */ +static inline void FTM_SetTimerPeriod(FTM_Type *base, uint32_t ticks) +{ + base->MOD = ticks; +} + +/*! + * @brief Reads the current timer counting value. + * + * This function returns the real-time timer counting value in a range from 0 to a + * timer period. + * + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. + * + * @param base FTM peripheral base address + * + * @return The current counter value in ticks + */ +static inline uint32_t FTM_GetCurrentTimerCount(FTM_Type *base) +{ + return (uint32_t)((base->CNT & FTM_CNT_COUNT_MASK) >> FTM_CNT_COUNT_SHIFT); +} + +/*! @}*/ /*! * @name Timer Start and Stop * @{ @@ -711,7 +752,7 @@ static inline void FTM_SetOutputMask(FTM_Type *base, ftm_chnl_t chnlNumber, bool #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) /*! - * @brief Allows user to enable an output on an FTM channel. + * @brief Allows users to enable an output on an FTM channel. * * To enable the PWM channel output call this function with val=true. For input mode, * call this function with val=false. @@ -816,6 +857,76 @@ static inline void FTM_SetInvertEnable(FTM_Type *base, ftm_chnl_t chnlPairNumber /*! @}*/ +/*! + * @name Quad Decoder + * @{ + */ + +/*! + * @brief Configures the parameters and activates the quadrature decoder mode. + * + * @param base FTM peripheral base address + * @param phaseAParams Phase A configuration parameters + * @param phaseBParams Phase B configuration parameters + * @param quadMode Selects encoding mode used in quadrature decoder mode + */ +void FTM_SetupQuadDecode(FTM_Type *base, + const ftm_phase_params_t *phaseAParams, + const ftm_phase_params_t *phaseBParams, + ftm_quad_decode_mode_t quadMode); + +/*! + * @brief Gets the FTM Quad Decoder flags. + * + * @param base FTM peripheral base address. + * @return Flag mask of FTM Quad Decoder, see #_ftm_quad_decoder_flags. + */ +static inline uint32_t FTM_GetQuadDecoderFlags(FTM_Type *base) +{ + return base->QDCTRL & (FTM_QDCTRL_QUADIR_MASK | FTM_QDCTRL_TOFDIR_MASK); +} + +/*! + * @brief Sets the modulo values for Quad Decoder. + * + * The modulo values configure the minimum and maximum values that the Quad decoder counter can reach. After the counter goes + * over, the counter value goes to the other side and decrease/increase again. + * + * @param base FTM peripheral base address. + * @param startValue The low limit value for Quad Decoder counter. + * @param overValue The high limit value for Quad Decoder counter. + */ +static inline void FTM_SetQuadDecoderModuloValue(FTM_Type *base, uint32_t startValue, uint32_t overValue) +{ + base->CNTIN = startValue; + base->MOD = overValue; +} + +/*! + * @brief Gets the current Quad Decoder counter value. + * + * @param base FTM peripheral base address. + * @return Current quad Decoder counter value. + */ +static inline uint32_t FTM_GetQuadDecoderCounterValue(FTM_Type *base) +{ + return base->CNT; +} + +/*! + * @brief Clears the current Quad Decoder counter value. + * + * The counter is set as the initial value. + * + * @param base FTM peripheral base address. + */ +static inline void FTM_ClearQuadDecoderCounterValue(FTM_Type *base) +{ + base->CNT = base->CNTIN; +} + +/*! @}*/ + /*! * @brief Enables or disables the FTM software trigger for PWM synchronization. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c index 8fc068f2d6a..b40ee3ac11c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -57,7 +57,7 @@ static uint32_t GPIO_GetInstance(GPIO_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_GPIO_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++) { if (s_gpioBases[instance] == base) { @@ -65,7 +65,7 @@ static uint32_t GPIO_GetInstance(GPIO_Type *base) } } - assert(instance < FSL_FEATURE_SOC_GPIO_COUNT); + assert(instance < ARRAY_SIZE(s_gpioBases)); return instance; } @@ -103,6 +103,14 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask) portBase->ISFR = mask; } +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute) +{ + base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) | + ((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT); +} +#endif + #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT /******************************************************************************* @@ -130,7 +138,7 @@ static uint32_t FGPIO_GetInstance(FGPIO_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_FGPIO_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_fgpioBases); instance++) { if (s_fgpioBases[instance] == base) { @@ -138,7 +146,7 @@ static uint32_t FGPIO_GetInstance(FGPIO_Type *base) } } - assert(instance < FSL_FEATURE_SOC_FGPIO_COUNT); + assert(instance < ARRAY_SIZE(s_fgpioBases)); return instance; } @@ -176,4 +184,12 @@ void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask) portBase->ISFR = mask; } +#if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER +void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute) +{ + base->GACR = (attribute << FGPIO_GACR_ACB0_SHIFT) | (attribute << FGPIO_GACR_ACB1_SHIFT) | + (attribute << FGPIO_GACR_ACB2_SHIFT) | (attribute << FGPIO_GACR_ACB3_SHIFT); +} +#endif + #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h index 6eaaaa08744..410e2b8ee46 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_gpio.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -38,38 +38,60 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief GPIO driver version 2.1.0. */ -#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief GPIO driver version 2.1.1. */ +#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*@}*/ -/*! @brief GPIO direction definition*/ +/*! @brief GPIO direction definition */ typedef enum _gpio_pin_direction { kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/ kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/ } gpio_pin_direction_t; +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! @brief GPIO checker attribute */ +typedef enum _gpio_checker_attribute +{ + kGPIO_UsernonsecureRWUsersecureRWPrivilegedsecureRW = + 0x00U, /*!< User nonsecure:Read+Write; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureRUsersecureRWPrivilegedsecureRW = + 0x01U, /*!< User nonsecure:Read; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureRWPrivilegedsecureRW = + 0x02U, /*!< User nonsecure:None; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureRUsersecureRPrivilegedsecureRW = + 0x03U, /*!< User nonsecure:Read; User Secure:Read; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureRPrivilegedsecureRW = + 0x04U, /*!< User nonsecure:None; User Secure:Read; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureRW = + 0x05U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureR = + 0x06U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureN = + 0x07U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:None */ + kGPIO_IgnoreAttributeCheck = 0x10U, /*!< Ignores the attribute check */ +} gpio_checker_attribute_t; +#endif + /*! * @brief The GPIO pin configuration structure. * - * Every pin can only be configured as either output pin or input pin at a time. - * If configured as a input pin, then leave the outputConfig unused - * Note : In some cases, the corresponding port property should be configured in advance - * with the PORT_SetPinConfig() + * Each pin can only be configured as either an output pin or an input pin at a time. + * If configured as an input pin, leave the outputConfig unused. + * Note that in some use cases, the corresponding port property should be configured in advance + * with the PORT_SetPinConfig(). */ typedef struct _gpio_pin_config { - gpio_pin_direction_t pinDirection; /*!< gpio direction, input or output */ - /* Output configurations, please ignore if configured as a input one */ - uint8_t outputLogic; /*!< Set default output logic, no use in input */ + gpio_pin_direction_t pinDirection; /*!< GPIO direction, input or output */ + /* Output configurations; ignore if configured as an input pin */ + uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */ } gpio_pin_config_t; /*! @} */ @@ -93,10 +115,10 @@ extern "C" { /*! * @brief Initializes a GPIO pin used by the board. * - * To initialize the GPIO, define a pin configuration, either input or output, in the user file. + * To initialize the GPIO, define a pin configuration, as either input or output, in the user file. * Then, call the GPIO_PinInit() function. * - * This is an example to define an input pin or output pin configuration: + * This is an example to define an input pin or an output pin configuration. * @code * // Define a digital input pin configuration, * gpio_pin_config_t config = @@ -112,7 +134,7 @@ extern "C" { * } * @endcode * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param pin GPIO port pin number * @param config GPIO pin configuration pointer */ @@ -126,29 +148,29 @@ void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config /*! * @brief Sets the output level of the multiple GPIO pins to the logic 1 or 0. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin GPIO pin's number + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param pin GPIO pin number * @param output GPIO pin output logic level. - * - 0: corresponding pin output low logic level. - * - 1: corresponding pin output high logic level. + * - 0: corresponding pin output low-logic level. + * - 1: corresponding pin output high-logic level. */ static inline void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output) { if (output == 0U) { - base->PCOR = 1 << pin; + base->PCOR = 1U << pin; } else { - base->PSOR = 1 << pin; + base->PSOR = 1U << pin; } } /*! * @brief Sets the output level of the multiple GPIO pins to the logic 1. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask) { @@ -158,8 +180,8 @@ static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask) /*! * @brief Sets the output level of the multiple GPIO pins to the logic 0. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask) { @@ -167,10 +189,10 @@ static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask) } /*! - * @brief Reverses current output logic of the multiple GPIO pins. + * @brief Reverses the current output logic of the multiple GPIO pins. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask) { @@ -182,13 +204,13 @@ static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask) /*@{*/ /*! - * @brief Reads the current input value of the whole GPIO port. + * @brief Reads the current input value of the GPIO port. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin GPIO pin's number + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param pin GPIO pin number * @retval GPIO port input value - * - 0: corresponding pin input low logic level. - * - 1: corresponding pin input high logic level. + * - 0: corresponding pin input low-logic level. + * - 1: corresponding pin input high-logic level. */ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) { @@ -200,7 +222,7 @@ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) /*@{*/ /*! - * @brief Reads whole GPIO port interrupt status flag. + * @brief Reads the GPIO port interrupt status flag. * * If a pin is configured to generate the DMA request, the corresponding flag * is cleared automatically at the completion of the requested DMA transfer. @@ -208,20 +230,34 @@ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) * If configured for a level sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @retval Current GPIO port interrupt status flag, for example, 0x00010001 means the + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @retval The current GPIO port interrupt status flag, for example, 0x00010001 means the * pin 0 and 17 have the interrupt. */ uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base); /*! - * @brief Clears multiple GPIO pins' interrupt status flag. + * @brief Clears multiple GPIO pin interrupt status flags. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask GPIO pins' numbers macro + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro */ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! + * @brief The GPIO module supports a device-specific number of data ports, organized as 32-bit + * words. Each 32-bit data port includes a GACR register, which defines the byte-level + * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data + * bytes in the GACR follow a standard little endian + * data convention. + * + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro + */ +void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute); +#endif + /*@}*/ /*! @} */ @@ -231,10 +267,10 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); */ /* - * Introduce the FGPIO feature. + * Introduces the FGPIO feature. * - * The FGPIO features are only support on some of Kinetis chips. The FGPIO registers are aliased to the IOPORT - * interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and will therefore + * The FGPIO features are only support on some Kinetis MCUs. The FGPIO registers are aliased to the IOPORT + * interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and * complete in a single cycle. This aliased Fast GPIO memory map is called FGPIO. */ @@ -246,10 +282,10 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); /*! * @brief Initializes a FGPIO pin used by the board. * - * To initialize the FGPIO driver, define a pin configuration, either input or output, in the user file. + * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file. * Then, call the FGPIO_PinInit() function. * - * This is an example to define an input pin or output pin configuration: + * This is an example to define an input pin or an output pin configuration: * @code * // Define a digital input pin configuration, * gpio_pin_config_t config = @@ -265,7 +301,7 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); * } * @endcode * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param pin FGPIO port pin number * @param config FGPIO pin configuration pointer */ @@ -279,11 +315,11 @@ void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *conf /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin FGPIO pin's number + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param pin FGPIO pin number * @param output FGPIOpin output logic level. - * - 0: corresponding pin output low logic level. - * - 1: corresponding pin output high logic level. + * - 0: corresponding pin output low-logic level. + * - 1: corresponding pin output high-logic level. */ static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t output) { @@ -300,8 +336,8 @@ static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 1. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask) { @@ -311,8 +347,8 @@ static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask) /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 0. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask) { @@ -320,10 +356,10 @@ static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask) } /*! - * @brief Reverses current output logic of the multiple FGPIO pins. + * @brief Reverses the current output logic of the multiple FGPIO pins. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask) { @@ -335,13 +371,13 @@ static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask) /*@{*/ /*! - * @brief Reads the current input value of the whole FGPIO port. + * @brief Reads the current input value of the FGPIO port. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param pin FGPIO pin's number + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param pin FGPIO pin number * @retval FGPIO port input value - * - 0: corresponding pin input low logic level. - * - 1: corresponding pin input high logic level. + * - 0: corresponding pin input low-logic level. + * - 1: corresponding pin input high-logic level. */ static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin) { @@ -353,28 +389,42 @@ static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin) /*@{*/ /*! - * @brief Reads the whole FGPIO port interrupt status flag. + * @brief Reads the FGPIO port interrupt status flag. * - * If a pin is configured to generate the DMA request, the corresponding flag + * If a pin is configured to generate the DMA request, the corresponding flag * is cleared automatically at the completion of the requested DMA transfer. * Otherwise, the flag remains set until a logic one is written to that flag. - * If configured for a level sensitive interrupt that remains asserted, the flag + * If configured for a level-sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @retval Current FGPIO port interrupt status flags, for example, 0x00010001 means the + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the * pin 0 and 17 have the interrupt. */ uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base); /*! - * @brief Clears the multiple FGPIO pins' interrupt status flag. + * @brief Clears the multiple FGPIO pin interrupt status flag. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @param mask FGPIO pins' numbers macro + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro */ void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask); +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! + * @brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit + * words. Each 32-bit data port includes a GACR register, which defines the byte-level + * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data + * bytes in the GACR follow a standard little endian + * data convention. + * + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro + */ +void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute); +#endif + /*@}*/ #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c index e77a3832399..6c9770af256 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -75,6 +75,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle); */ uint32_t I2C_GetInstance(I2C_Type *base); +/*! +* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the +* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop +* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided, +* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT +* value, then the related SDA hold time, SCL start and SCL stop hold time is used. +* +* @param base I2C peripheral base address. +* @param sourceClock_Hz I2C functional clock frequency in Hertz. +* @param sclStopHoldTime_ns SCL stop hold time in ns. +*/ +static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz); + /*! * @brief Set up master transfer, send slave address and decide the initial * transfer state. @@ -125,20 +138,22 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle); static void *s_i2cHandle[FSL_FEATURE_SOC_I2C_COUNT] = {NULL}; /*! @brief SCL clock divider used to calculate baudrate. */ -const uint16_t s_i2cDividerTable[] = {20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, - 48, 56, 68, 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, - 112, 128, 144, 160, 192, 240, 160, 192, 224, 256, 288, 320, 384, - 480, 320, 384, 448, 512, 576, 640, 768, 960, 640, 768, 896, 1024, - 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840}; +static const uint16_t s_i2cDividerTable[] = { + 20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68, + 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240, + 160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960, + 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840}; /*! @brief Pointers to i2c bases for each instance. */ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS; /*! @brief Pointers to i2c IRQ number for each instance. */ -const IRQn_Type s_i2cIrqs[] = I2C_IRQS; +static const IRQn_Type s_i2cIrqs[] = I2C_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to i2c clocks for each instance. */ -const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS; +static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointer to master IRQ handler for each instance. */ static i2c_isr_t s_i2cMasterIsr; @@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++) { if (s_i2cBases[instance] == base) { @@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base) } } - assert(instance < FSL_FEATURE_SOC_I2C_COUNT); + assert(instance < ARRAY_SIZE(s_i2cBases)); return instance; } +static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz) +{ + uint32_t multiplier; + uint32_t computedSclHoldTime; + uint32_t absError; + uint32_t bestError = UINT32_MAX; + uint32_t bestMult = 0u; + uint32_t bestIcr = 0u; + uint8_t mult; + uint8_t i; + + /* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register, + * and ranges from 0-2. It selects the multiplier factor for the divider. */ + /* SDA hold time = bus period (s) * mul * SDA hold value. */ + /* SCL start hold time = bus period (s) * mul * SCL start hold value. */ + /* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */ + + for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) + { + multiplier = 1u << mult; + + /* Scan table to find best match. */ + for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i) + { + /* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */ + computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz; + absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) : + (computedSclHoldTime - sclStopHoldTime_ns); + + if (absError < bestError) + { + bestMult = mult; + bestIcr = i; + bestError = absError; + + /* If the error is 0, then we can stop searching because we won't find a better match. */ + if (absError == 0) + { + break; + } + } + } + } + + /* Set frequency register based on best settings. */ + base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr); +} + static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer) { status_t result = kStatus_Success; i2c_direction_t direction = xfer->direction; - uint16_t timeout = UINT16_MAX; /* Initialize the handle transfer information. */ handle->transfer = *xfer; @@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t /* Initial transfer state. */ if (handle->transfer.subaddressSize > 0) { - handle->state = kSendCommandState; if (xfer->direction == kI2C_Read) { direction = kI2C_Write; } } - else - { - handle->state = kCheckAddressState; - } - /* Wait until the data register is ready for transmit. */ - while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) - { - } - - /* Failed to start the transfer. */ - if (timeout == 0) - { - return kStatus_I2C_Timeout; - } + handle->state = kCheckAddressState; /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); @@ -265,34 +313,41 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han result = kStatus_Success; } - if (result) - { - return result; - } - /* Handle Check address state to check the slave address is Acked in slave probe application. */ if (handle->state == kCheckAddressState) { if (statusFlags & kI2C_ReceiveNakFlag) { - return kStatus_I2C_Nak; + result = kStatus_I2C_Addr_Nak; } else { - if (handle->transfer.direction == kI2C_Write) + if (handle->transfer.subaddressSize > 0) { - /* Next state, send data. */ - handle->state = kSendDataState; + handle->state = kSendCommandState; } else { - /* Next state, receive data begin. */ - handle->state = kReceiveDataBeginState; + if (handle->transfer.direction == kI2C_Write) + { + /* Next state, send data. */ + handle->state = kSendDataState; + } + else + { + /* Next state, receive data begin. */ + handle->state = kReceiveDataBeginState; + } } } } + if (result) + { + return result; + } + /* Run state machine. */ switch (handle->state) { @@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han { result = I2C_MasterStop(base); } + else + { + base->C1 |= I2C_C1_TX_MASK; + } } /* Send NAK at the last receive byte. */ @@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle) { s_i2cSlaveIsr(base, handle); } + __DSB(); } void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz) @@ -415,12 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Temporary register for filter read. */ uint8_t fltReg; -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - uint8_t c2Reg; +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + uint8_t s2Reg; #endif - +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable I2C clock. */ CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Reset the module. */ + base->A1 = 0; + base->F = 0; + base->C1 = 0; + base->S = 0xFFU; + base->C2 = 0; +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + base->FLT = 0x50U; +#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT + base->FLT = 0x40U; +#endif + base->RA = 0; /* Disable I2C prior to configuring it. */ base->C1 &= ~(I2C_C1_IICEN_MASK); @@ -431,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Configure baud rate. */ I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz); -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - /* Configure high drive feature. */ - c2Reg = base->C2; - c2Reg &= ~(I2C_C2_HDRS_MASK); - c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive); - base->C2 = c2Reg; -#endif - /* Read out the FLT register. */ fltReg = base->FLT; @@ -455,6 +521,12 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Write the register value back to the filter register. */ base->FLT = fltReg; +/* Enable/Disable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + s2Reg = base->S2 & (~I2C_S2_DFEN_MASK); + base->S2 = s2Reg | I2C_S2_DFEN(masterConfig->enableDoubleBuffering); +#endif + /* Enable the I2C peripheral based on the configuration. */ base->C1 = I2C_C1_IICEN(masterConfig->enableMaster); } @@ -464,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base) /* Disable I2C module. */ I2C_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable I2C clock. */ CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) @@ -475,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) /* Default baud rate at 100kbps. */ masterConfig->baudRate_Bps = 100000U; -/* Default pin high drive is disabled. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - masterConfig->enableHighDrive = false; -#endif - /* Default stop hold enable is disabled. */ #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF masterConfig->enableStopHold = false; @@ -488,12 +557,21 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) /* Default glitch filter value is no filter. */ masterConfig->glitchFilterWidth = 0U; +/* Default enable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + masterConfig->enableDoubleBuffering = true; +#endif + /* Enable the I2C peripheral. */ masterConfig->enableMaster = true; } void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask) { +#ifdef I2C_HAS_STOP_DETECT + uint8_t fltReg; +#endif + if (mask & kI2C_GlobalInterruptEnable) { base->C1 |= I2C_C1_IICIE_MASK; @@ -502,14 +580,28 @@ void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask) #if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT if (mask & kI2C_StopDetectInterruptEnable) { - base->FLT |= I2C_FLT_STOPIE_MASK; + fltReg = base->FLT; + + /* Keep STOPF flag. */ + fltReg &= ~I2C_FLT_STOPF_MASK; + + /* Stop detect enable. */ + fltReg |= I2C_FLT_STOPIE_MASK; + base->FLT = fltReg; } #endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT if (mask & kI2C_StartStopDetectInterruptEnable) { - base->FLT |= I2C_FLT_SSIE_MASK; + fltReg = base->FLT; + + /* Keep STARTF and STOPF flags. */ + fltReg &= ~(I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK); + + /* Start and stop detect enable. */ + fltReg |= I2C_FLT_SSIE_MASK; + base->FLT = fltReg; } #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ } @@ -524,14 +616,14 @@ void I2C_DisableInterrupts(I2C_Type *base, uint32_t mask) #if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT if (mask & kI2C_StopDetectInterruptEnable) { - base->FLT &= ~I2C_FLT_STOPIE_MASK; + base->FLT &= ~(I2C_FLT_STOPIE_MASK | I2C_FLT_STOPF_MASK); } #endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT if (mask & kI2C_StartStopDetectInterruptEnable) { - base->FLT &= ~I2C_FLT_SSIE_MASK; + base->FLT &= ~(I2C_FLT_SSIE_MASK | I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK); } #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ } @@ -623,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_ base->F = savedMult & (~I2C_F_MULT_MASK); /* We are already in a transfer, so send a repeated start. */ - base->C1 |= I2C_C1_RSTA_MASK; + base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK; /* Restore the multiplier factor. */ base->F = savedMult; @@ -690,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base) return statusFlags; } -status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize) +status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags) { status_t result = kStatus_Success; uint8_t statusFlags = 0; @@ -728,7 +820,7 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t result = kStatus_I2C_ArbitrationLost; } - if (statusFlags & kI2C_ReceiveNakFlag) + if ((statusFlags & kI2C_ReceiveNakFlag) && txSize) { base->S = kI2C_ReceiveNakFlag; result = kStatus_I2C_Nak; @@ -741,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t } } + if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) + { + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; + + /* Send stop. */ + result = I2C_MasterStop(base); + } + return result; } -status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) +status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags) { status_t result = kStatus_Success; volatile uint8_t dummy = 0; @@ -786,8 +887,16 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) /* Single byte use case. */ if (rxSize == 0) { - /* Read the final byte. */ - result = I2C_MasterStop(base); + if (!(flags & kI2C_TransferNoStopFlag)) + { + /* Issue STOP command before reading last byte. */ + result = I2C_MasterStop(base); + } + else + { + /* Change direction to Tx to avoid extra clocks. */ + base->C1 |= I2C_C1_TX_MASK; + } } if (rxSize == 1) @@ -840,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) return result; } + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + /* Return if error. */ + if (result) + { + if (result == kStatus_I2C_Nak) + { + result = kStatus_I2C_Addr_Nak; + + I2C_MasterStop(base); + } + + return result; + } + /* Send subaddress. */ if (xfer->subaddressSize) { do { + /* Clear interrupt pending flag. */ + base->S = kI2C_IntPendingFlag; + + xfer->subaddressSize--; + base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); + /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } - /* Clear interrupt pending flag. */ - base->S = kI2C_IntPendingFlag; - /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -866,21 +998,27 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) return result; } - xfer->subaddressSize--; - base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); - } while ((xfer->subaddressSize > 0) && (result == kStatus_Success)); if (xfer->direction == kI2C_Read) { + /* Clear pending flag. */ + base->S = kI2C_IntPendingFlag; + + /* Send repeated start and slave address. */ + result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); + + /* Return if error. */ + if (result) + { + return result; + } + /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } - /* Clear pending flag. */ - base->S = kI2C_IntPendingFlag; - /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -888,62 +1026,27 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) { if (result == kStatus_I2C_Nak) { + result = kStatus_I2C_Addr_Nak; + I2C_MasterStop(base); } return result; } - - /* Send repeated start and slave address. */ - result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); - - /* Return if error. */ - if (result) - { - return result; - } - } - } - - /* Wait until address + command transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } - - /* Check if there's transfer error. */ - result = I2C_CheckAndClearError(base, base->S); - - /* Return if error. */ - if (result) - { - if (result == kStatus_I2C_Nak) - { - I2C_MasterStop(base); } - - return result; } /* Transmit data. */ if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0)) { /* Send Data. */ - result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize); - - if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) - { - /* Clear the IICIF flag. */ - base->S = kI2C_IntPendingFlag; - - /* Send stop. */ - result = I2C_MasterStop(base); - } + result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags); } /* Receive Data. */ if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0)) { - result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize); + result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags); } return result; @@ -1006,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle) { assert(handle); + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + /* Disable interrupt. */ I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable); /* Reset the state to idle. */ handle->state = kIdleState; + + /* Send STOP signal. */ + if (handle->transfer.direction == kI2C_Read) + { + base->C1 |= I2C_C1_TXAK_MASK; + while (!(base->S & kI2C_IntPendingFlag)) + { + } + base->S = kI2C_IntPendingFlag; + + base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + dummy = base->D; + } + else + { + while (!(base->S & kI2C_IntPendingFlag)) + { + } + base->S = kI2C_IntPendingFlag; + base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + } } status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count) @@ -1044,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) if (isDone || result) { /* Send stop command if transfer done or received Nak. */ - if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak)) + if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) || + (result == kStatus_I2C_Addr_Nak)) { /* Ensure stop command is a need. */ if ((base->C1 & I2C_C1_MST_MASK)) @@ -1070,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } -void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) +void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz) { assert(slaveConfig); uint8_t tmpReg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Reset the module. */ + base->A1 = 0; + base->F = 0; + base->C1 = 0; + base->S = 0xFFU; + base->C2 = 0; +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + base->FLT = 0x50U; +#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT + base->FLT = 0x40U; +#endif + base->RA = 0; /* Configure addressing mode. */ switch (slaveConfig->addressingMode) @@ -1101,15 +1246,20 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) tmpReg &= ~I2C_C1_WUEN_MASK; base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave); - /* Configure general call & baud rate control & high drive feature. */ + /* Configure general call & baud rate control. */ tmpReg = base->C2; tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK); tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall); -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - tmpReg &= ~I2C_C2_HDRS_MASK; - tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive); -#endif base->C2 = tmpReg; + +/* Enable/Disable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + tmpReg = base->S2 & (~I2C_S2_DFEN_MASK); + base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering); +#endif + + /* Set hold time. */ + I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz); } void I2C_SlaveDeinit(I2C_Type *base) @@ -1117,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base) /* Disable I2C module. */ I2C_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable I2C clock. */ CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) @@ -1134,48 +1286,106 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) /* Slave address match waking up MCU from low power mode is disabled. */ slaveConfig->enableWakeUp = false; -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - /* Default pin high drive is disabled. */ - slaveConfig->enableHighDrive = false; -#endif - /* Independent slave mode baud rate at maximum frequency is disabled. */ slaveConfig->enableBaudRateCtl = false; +/* Default enable double buffering. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + slaveConfig->enableDoubleBuffering = true; +#endif + + /* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */ + slaveConfig->sclStopHoldTime_ns = 4000; + /* Enable the I2C peripheral. */ slaveConfig->enableSlave = true; } status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize) { - return I2C_MasterWriteBlocking(base, txBuff, txSize); + status_t result = kStatus_Success; + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + /* Check start flag. */ + while (!(base->FLT & I2C_FLT_STARTF_MASK)) + { + } + /* Clear STARTF flag. */ + base->FLT |= I2C_FLT_STARTF_MASK; + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; +#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ + + /* Wait for address match flag. */ + while (!(base->S & kI2C_AddressMatchFlag)) + { + } + + /* Read dummy to release bus. */ + dummy = base->D; + + result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag); + + /* Switch to receive mode. */ + base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + + /* Read dummy to release bus. */ + dummy = base->D; + + return result; } void I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) { + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + +/* Wait until address match. */ +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + /* Check start flag. */ + while (!(base->FLT & I2C_FLT_STARTF_MASK)) + { + } + /* Clear STARTF flag. */ + base->FLT |= I2C_FLT_STARTF_MASK; /* Clear the IICIF flag. */ base->S = kI2C_IntPendingFlag; +#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ - /* Wait until the data register is ready for receive. */ - while (!(base->S & kI2C_TransferCompleteFlag)) + /* Wait for address match and int pending flag. */ + while (!(base->S & kI2C_AddressMatchFlag)) + { + } + while (!(base->S & kI2C_IntPendingFlag)) { } + /* Read dummy to release bus. */ + dummy = base->D; + + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; + /* Setup the I2C peripheral to receive data. */ base->C1 &= ~(I2C_C1_TX_MASK); while (rxSize--) { + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } /* Clear the IICIF flag. */ base->S = kI2C_IntPendingFlag; /* Read from the data register. */ *rxBuff++ = base->D; - - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } } } @@ -1226,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle handle->isBusy = true; /* Set up event mask. tx and rx are always enabled. */ - handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent; + handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent; /* Clear all flags. */ I2C_SlaveClearStatusFlags(base, kClearFlags); @@ -1315,7 +1525,10 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } - return; + if (!(status & kI2C_AddressMatchFlag)) + { + return; + } } #endif /* I2C_HAS_STOP_DETECT */ @@ -1328,7 +1541,7 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Clear the interrupt flag. */ base->S = kI2C_IntPendingFlag; - xfer->event = kI2C_SlaveRepeatedStartEvent; + xfer->event = kI2C_SlaveStartEvent; if ((handle->eventMask & xfer->event) && (handle->callback)) { @@ -1385,31 +1598,12 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) handle->isBusy = true; xfer->event = kI2C_SlaveAddressMatchEvent; - if ((handle->eventMask & xfer->event) && (handle->callback)) - { - handle->callback(base, xfer, handle->userData); - } - /* Slave transmit, master reading from slave. */ if (status & kI2C_TransferDirectionFlag) { /* Change direction to send data. */ base->C1 |= I2C_C1_TX_MASK; - /* If we're out of data, invoke callback to get more. */ - if ((!xfer->data) || (!xfer->dataSize)) - { - xfer->event = kI2C_SlaveTransmitEvent; - - if (handle->callback) - { - handle->callback(base, xfer, handle->userData); - } - - /* Clear the transferred count now that we have a new buffer. */ - xfer->transferredCount = 0; - } - doTransmit = true; } else @@ -1417,22 +1611,18 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Slave receive, master writing to slave. */ base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); - /* If we're out of data, invoke callback to get more. */ - if ((!xfer->data) || (!xfer->dataSize)) - { - xfer->event = kI2C_SlaveReceiveEvent; - - if (handle->callback) - { - handle->callback(base, xfer, handle->userData); - } + /* Read dummy to release the bus. */ + dummy = base->D; - /* Clear the transferred count now that we have a new buffer. */ - xfer->transferredCount = 0; + if (dummy == 0) + { + xfer->event = kI2C_SlaveGenaralcallEvent; } + } - /* Read dummy to release the bus. */ - dummy = base->D; + if ((handle->eventMask & xfer->event) && (handle->callback)) + { + handle->callback(base, xfer, handle->userData); } } /* Check transfer complete flag. */ @@ -1445,6 +1635,20 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } else { + /* If we're out of data, invoke callback to get more. */ + if ((!xfer->data) || (!xfer->dataSize)) + { + xfer->event = kI2C_SlaveReceiveEvent; + + if (handle->callback) + { + handle->callback(base, xfer, handle->userData); + } + + /* Clear the transferred count now that we have a new buffer. */ + xfer->transferredCount = 0; + } + /* Slave receive, master writing to slave. */ uint8_t data = base->D; @@ -1480,6 +1684,20 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Send data if there is the need. */ if (doTransmit) { + /* If we're out of data, invoke callback to get more. */ + if ((!xfer->data) || (!xfer->dataSize)) + { + xfer->event = kI2C_SlaveTransmitEvent; + + if (handle->callback) + { + handle->callback(base, xfer, handle->userData); + } + + /* Clear the transferred count now that we have a new buffer. */ + xfer->transferredCount = 0; + } + if (handle->transfer.dataSize) { /* Send data. */ @@ -1510,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } +#if defined(I2C0) void I2C0_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]); } +#endif -#if (FSL_FEATURE_SOC_I2C_COUNT > 1) +#if defined(I2C1) void I2C1_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]); } -#endif /* I2C COUNT > 1 */ +#endif -#if (FSL_FEATURE_SOC_I2C_COUNT > 2) +#if defined(I2C2) void I2C2_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]); } -#endif /* I2C COUNT > 2 */ -#if (FSL_FEATURE_SOC_I2C_COUNT > 3) +#endif + +#if defined(I2C3) void I2C3_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]); } -#endif /* I2C COUNT > 3 */ +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h index 41a9afbdd54..d55fd1d8ea3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,16 +37,14 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief I2C driver version 2.0.0. */ -#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief I2C driver version 2.0.3. */ +#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ #if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \ @@ -62,6 +60,7 @@ enum _i2c_status kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */ kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */ kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */ + kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */ }; /*! @@ -109,11 +108,11 @@ enum _i2c_interrupt_enable #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ }; -/*! @brief Direction of master and slave transfers. */ +/*! @brief The direction of master and slave transfers. */ typedef enum _i2c_direction { - kI2C_Write = 0x0U, /*!< Master transmit to slave. */ - kI2C_Read = 0x1U, /*!< Master receive from slave. */ + kI2C_Write = 0x0U, /*!< Master transmits to the slave. */ + kI2C_Read = 0x1U, /*!< Master receives from the slave. */ } i2c_direction_t; /*! @brief Addressing mode. */ @@ -126,17 +125,17 @@ typedef enum _i2c_slave_address_mode /*! @brief I2C transfer control flag. */ enum _i2c_master_transfer_flags { - kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */ - kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */ - kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */ - kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */ + kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */ + kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */ + kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */ + kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */ }; /*! * @brief Set of events sent to the callback for nonblocking slave transfers. * * These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together - * events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable. + * events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable. * Then, when the slave callback is invoked, it is passed the current event through its @a transfer * parameter. * @@ -145,33 +144,35 @@ enum _i2c_master_transfer_flags typedef enum _i2c_slave_transfer_event { kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */ - kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit + kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit (slave-transmitter role). */ - kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received + kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received data (slave-receiver role). */ - kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */ + kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT - kI2C_SlaveRepeatedStartEvent = 0x10U, /*!< A repeated start was detected. */ + kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */ #endif - kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */ + kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */ + kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */ - /*! Bit mask of all available events. */ + /*! A bit mask of all available events. */ kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT - kI2C_SlaveRepeatedStartEvent | + kI2C_SlaveStartEvent | #endif - kI2C_SlaveCompletionEvent, + kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent, } i2c_slave_transfer_event_t; /*! @brief I2C master user configuration. */ typedef struct _i2c_master_config { bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */ -#endif #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF bool enableStopHold; /*!< Controls the stop hold enable. */ +#endif +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that + enabling the double buffer disables the clock stretch. */ #endif uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */ uint8_t glitchFilterWidth; /*!< Controls the width of the glitch. */ @@ -181,15 +182,20 @@ typedef struct _i2c_master_config typedef struct _i2c_slave_config { bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */ - bool enableGeneralCall; /*!< Enable general call addressing mode. */ - bool enableWakeUp; /*!< Enables/disables waking up MCU from low power mode. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */ + bool enableGeneralCall; /*!< Enables the general call addressing mode. */ + bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */ +#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE + bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that + enabling the double buffer disables the clock stretch. */ #endif bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */ - uint16_t slaveAddress; /*!< Slave address configuration. */ - uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */ - i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */ + uint16_t slaveAddress; /*!< A slave address configuration. */ + uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */ + i2c_slave_address_mode_t + addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */ + uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C + data) while SCL is high (stop condition), SDA hold time and SCL start hold time + are also configured according to the SCL stop hold time. */ } i2c_slave_config_t; /*! @brief I2C master handle typedef. */ @@ -207,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t; /*! @brief I2C master transfer structure. */ typedef struct _i2c_master_transfer { - uint32_t flags; /*!< Transfer flag which controls the transfer. */ + uint32_t flags; /*!< A transfer flag which controls the transfer. */ uint8_t slaveAddress; /*!< 7-bit slave address. */ - i2c_direction_t direction; /*!< Transfer direction, read or write. */ - uint32_t subaddress; /*!< Sub address. Transferred MSB first. */ - uint8_t subaddressSize; /*!< Size of command buffer. */ - uint8_t *volatile data; /*!< Transfer buffer. */ - volatile size_t dataSize; /*!< Transfer size. */ + i2c_direction_t direction; /*!< A transfer direction, read or write. */ + uint32_t subaddress; /*!< A sub address. Transferred MSB first. */ + uint8_t subaddressSize; /*!< A size of the command buffer. */ + uint8_t *volatile data; /*!< A transfer buffer. */ + volatile size_t dataSize; /*!< A transfer size. */ } i2c_master_transfer_t; /*! @brief I2C master handle structure. */ @@ -221,20 +227,21 @@ struct _i2c_master_handle { i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */ size_t transferSize; /*!< Total bytes to be transferred. */ - uint8_t state; /*!< Transfer state maintained during transfer. */ - i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */ - void *userData; /*!< Callback parameter passed to callback function. */ + uint8_t state; /*!< A transfer state maintained during transfer. */ + i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */ + void *userData; /*!< A callback parameter passed to the callback function. */ }; /*! @brief I2C slave transfer structure. */ typedef struct _i2c_slave_transfer { - i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */ - uint8_t *volatile data; /*!< Transfer buffer. */ - volatile size_t dataSize; /*!< Transfer size. */ + i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */ + uint8_t *volatile data; /*!< A transfer buffer. */ + volatile size_t dataSize; /*!< A transfer size. */ status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for #kI2C_SlaveCompletionEvent. */ - size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */ + size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated + start. */ } i2c_slave_transfer_t; /*! @brief I2C slave transfer callback typedef. */ @@ -243,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer /*! @brief I2C slave handle structure. */ struct _i2c_slave_handle { - bool isBusy; /*!< Whether transfer is busy. */ + volatile bool isBusy; /*!< Indicates whether a transfer is busy. */ i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */ - uint32_t eventMask; /*!< Mask of enabled events. */ - i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */ - void *userData; /*!< Callback parameter passed to callback. */ + uint32_t eventMask; /*!< A mask of enabled events. */ + i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */ + void *userData; /*!< A callback parameter passed to the callback. */ }; /******************************************************************************* @@ -267,12 +274,12 @@ extern "C" { * @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock * and configure the I2C with master configuration. * - * @note This API should be called at the beginning of the application to use - * the I2C driver, or any operation to the I2C module could cause hard fault - * because clock is not enabled. The configuration structure can be filled by user - * from scratch, or be set with default values by I2C_MasterGetDefaultConfig(). + * @note This API should be called at the beginning of the application. + * Otherwise, any operation to the I2C module can cause a hard fault + * because the clock is not enabled. The configuration structure can be custom filled + * or it can be set with default values by using the I2C_MasterGetDefaultConfig(). * After calling this API, the master is ready to transfer. - * Example: + * This is an example. * @code * i2c_master_config_t config = { * .enableMaster = true, @@ -285,20 +292,20 @@ extern "C" { * @endcode * * @param base I2C base pointer - * @param masterConfig pointer to master configuration structure + * @param masterConfig A pointer to the master configuration structure * @param srcClock_Hz I2C peripheral clock frequency in Hz */ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz); /*! * @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock - * and initializes the I2C with slave configuration. + * and initialize the I2C with the slave configuration. * - * @note This API should be called at the beginning of the application to use - * the I2C driver, or any operation to the I2C module can cause a hard fault + * @note This API should be called at the beginning of the application. + * Otherwise, any operation to the I2C module can cause a hard fault * because the clock is not enabled. The configuration structure can partly be set - * with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user. - * Example + * with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user. + * This is an example. * @code * i2c_slave_config_t config = { * .enableSlave = true, @@ -307,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin * .slaveAddress = 0x1DU, * .enableWakeUp = false, * .enablehighDrive = false, - * .enableBaudRateCtl = false + * .enableBaudRateCtl = false, + * .sclStopHoldTime_ns = 4000 * }; - * I2C_SlaveInit(I2C0, &config); + * I2C_SlaveInit(I2C0, &config, 12000000U); * @endcode * * @param base I2C base pointer - * @param slaveConfig pointer to slave configuration structure + * @param slaveConfig A pointer to the slave configuration structure + * @param srcClock_Hz I2C peripheral clock frequency in Hz */ -void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig); +void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz); /*! * @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock. @@ -335,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base); * @brief Sets the I2C master configuration structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure(). - * Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of - * the structure before calling I2C_MasterConfigure(). - * Example: + * Use the initialized structure unchanged in the I2C_MasterConfigure() or modify + * the structure before calling the I2C_MasterConfigure(). + * This is an example. * @code * i2c_master_config_t config; * I2C_MasterGetDefaultConfig(&config); * @endcode - * @param masterConfig Pointer to the master configuration structure. + * @param masterConfig A pointer to the master configuration structure. */ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig); /*! * @brief Sets the I2C slave configuration structure to default values. * - * The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure(). + * The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure(). * Modify fields of the structure before calling the I2C_SlaveConfigure(). - * Example: + * This is an example. * @code * i2c_slave_config_t config; * I2C_SlaveGetDefaultConfig(&config); * @endcode - * @param slaveConfig Pointer to the slave configuration structure. + * @param slaveConfig A pointer to the slave configuration structure. */ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig); @@ -364,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig); * @brief Enables or disabless the I2C peripheral operation. * * @param base I2C base pointer - * @param enable pass true to enable module, false to disable module + * @param enable Pass true to enable and false to disable the module. */ static inline void I2C_Enable(I2C_Type *base, bool enable) { @@ -389,7 +398,7 @@ static inline void I2C_Enable(I2C_Type *base, bool enable) * @brief Gets the I2C status flags. * * @param base I2C base pointer - * @return status flag, use status flag to AND #_i2c_flags could get the related status. + * @return status flag, use status flag to AND #_i2c_flags to get the related status. */ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base); @@ -397,7 +406,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base); * @brief Gets the I2C status flags. * * @param base I2C base pointer - * @return status flag, use status flag to AND #_i2c_flags could get the related status. + * @return status flag, use status flag to AND #_i2c_flags to get the related status. */ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base) { @@ -407,11 +416,11 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base) /*! * @brief Clears the I2C status flag state. * - * The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag + * The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag. * * @param base I2C base pointer * @param statusMask The status flag mask, defined in type i2c_status_flag_t. - * The parameter could be any combination of the following values: + * The parameter can be any combination of the following values: * @arg kI2C_StartDetectFlag (if available) * @arg kI2C_StopDetectFlag (if available) * @arg kI2C_ArbitrationLostFlag @@ -442,11 +451,11 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas /*! * @brief Clears the I2C status flag state. * - * The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag + * The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag * * @param base I2C base pointer * @param statusMask The status flag mask, defined in type i2c_status_flag_t. - * The parameter could be any combination of the following values: + * The parameter can be any combination of the following values: * @arg kI2C_StartDetectFlag (if available) * @arg kI2C_StopDetectFlag (if available) * @arg kI2C_ArbitrationLostFlag @@ -574,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base); status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction); /*! - * @brief Performs a polling send transaction on the I2C bus without a STOP signal. + * @brief Performs a polling send transaction on the I2C bus. * * @param base The I2C peripheral base pointer. * @param txBuff The pointer to the data to be transferred. * @param txSize The length in bytes of the data to be transferred. + * @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag +* to issue a stop and kI2C_TransferNoStop to not send a stop. * @retval kStatus_Success Successfully complete the data transmission. * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer. */ -status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize); +status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags); /*! - * @brief Performs a polling receive transaction on the I2C bus with a STOP signal. + * @brief Performs a polling receive transaction on the I2C bus. * * @note The I2C_MasterReadBlocking function stops the bus before reading the final byte. * Without stopping the bus prior for the final read, the bus issues another read, resulting @@ -595,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t * @param base I2C peripheral base pointer. * @param rxBuff The pointer to the data to store the received data. * @param rxSize The length in bytes of the data to be received. + * @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag +* to issue a stop and kI2C_TransferNoStop to not send a stop. * @retval kStatus_Success Successfully complete the data transmission. * @retval kStatus_I2C_Timeout Send stop signal failed, timeout. */ -status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize); +status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags); /*! * @brief Performs a polling send transaction on the I2C bus. @@ -650,7 +663,7 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) * @param base I2C base pointer. * @param handle pointer to i2c_master_handle_t structure to store the transfer state. * @param callback pointer to user callback function. - * @param userData user paramater passed to the callback function. + * @param userData user parameter passed to the callback function. */ void I2C_MasterTransferCreateHandle(I2C_Type *base, i2c_master_handle_t *handle, @@ -660,15 +673,15 @@ void I2C_MasterTransferCreateHandle(I2C_Type *base, /*! * @brief Performs a master interrupt non-blocking transfer on the I2C bus. * - * @note Calling the API will return immediately after transfer initiates, user needs + * @note Calling the API returns immediately after transfer initiates. The user needs * to call I2C_MasterGetTransferCount to poll the transfer status to check whether - * the transfer is finished, if the return status is not kStatus_I2C_Busy, the transfer + * the transfer is finished. If the return status is not kStatus_I2C_Busy, the transfer * is finished. * * @param base I2C base pointer. * @param handle pointer to i2c_master_handle_t structure which stores the transfer state. * @param xfer pointer to i2c_master_transfer_t structure. - * @retval kStatus_Success Sucessully start the data transmission. + * @retval kStatus_Success Successfully start the data transmission. * @retval kStatus_I2C_Busy Previous transmission still not finished. * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c index c8f7c20629f..28a415e075a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData result = I2C_MasterStop(i2cPrivateHandle->base); } } + else + { + if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read) + { + /* Change to send NAK at the last byte. */ + i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK; + + /* Wait the last data to be received. */ + while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) + { + } + + /* Change direction to send. */ + i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK; + + /* Read the last data byte. */ + *(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) = + i2cPrivateHandle->base->D; + } + } i2cPrivateHandle->handle->state = kIdleState; @@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, assert(xfer); status_t result = kStatus_Success; - uint16_t timeout = UINT16_MAX; if (handle->state != kIdleState) { @@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, handle->state = kTransferDataState; - /* Wait until ready to complete. */ - while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) - { - } - - /* Failed to start the transfer. */ - if (timeout == 0) - { - return kStatus_I2C_Timeout; - } /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); @@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction); } - /* Send subaddress. */ - if (handle->transfer.subaddressSize) + if (result) { - do + return result; + } + + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + /* Return if error. */ + if (result) + { + if (result == kStatus_I2C_Nak) { - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) + result = kStatus_I2C_Addr_Nak; + + if (I2C_MasterStop(base) != kStatus_Success) { + result = kStatus_I2C_Timeout; } + if (handle->completionCallback) + { + (handle->completionCallback)(base, handle, result, handle->userData); + } + } + + return result; + } + + /* Send subaddress. */ + if (handle->transfer.subaddressSize) + { + do + { /* Clear interrupt pending flag. */ base->S = kI2C_IntPendingFlag; handle->transfer.subaddressSize--; base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)); + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } + /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, if (handle->transfer.direction == kI2C_Read) { - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } - /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; /* Send repeated start and slave address. */ result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read); - } - } - if (result) - { - return result; - } + if (result) + { + return result; + } - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + if (result) + { + return result; + } + } } /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; - - /* Check if there's transfer error. */ - result = I2C_CheckAndClearError(base, base->S); } return result; @@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_ { transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base); transfer_config.destAddr = (uint32_t)(handle->transfer.data); - - /* Send stop if kI2C_TransferNoStop flag is not asserted. */ - if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) - { - transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1); - } - else - { - transfer_config.majorLoopCounts = handle->transfer.dataSize; - } - + transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1); transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes; transfer_config.srcOffset = 0; transfer_config.destTransferSize = kEDMA_TransferSize1Bytes; @@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_ transfer_config.minorLoopBytes = 1; } + /* Store the initially configured eDMA minor byte transfer count into the I2C handle */ + handle->nbytes = transfer_config.minorLoopBytes; + EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config); EDMA_StartTransfer(handle->dmaHandle); } @@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle if (handle->transfer.direction == kI2C_Read) { /* Change direction for receive. */ - base->C1 &= ~I2C_C1_TX_MASK; + base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); /* Read dummy to release the bus. */ dummy = base->D; @@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle { result = I2C_MasterStop(base); } + else + { + /* Change direction to send. */ + base->C1 |= I2C_C1_TX_MASK; + } /* Read the last byte of data. */ if (handle->transfer.direction == kI2C_Read) @@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t if (kIdleState != handle->state) { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } else { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h index 234876d451c..40cb648ea99 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_i2c_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,31 +39,30 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ -/*! @brief I2C master edma handle typedef. */ +/*! @brief I2C master eDMA handle typedef. */ typedef struct _i2c_master_edma_handle i2c_master_edma_handle_t; -/*! @brief I2C master edma transfer callback typedef. */ +/*! @brief I2C master eDMA transfer callback typedef. */ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base, i2c_master_edma_handle_t *handle, status_t status, void *userData); -/*! @brief I2C master edma transfer structure. */ +/*! @brief I2C master eDMA transfer structure. */ struct _i2c_master_edma_handle { - i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */ + i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */ size_t transferSize; /*!< Total bytes to be transferred. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint8_t state; /*!< I2C master transfer status. */ edma_handle_t *dmaHandle; /*!< The eDMA handler used. */ i2c_master_edma_transfer_callback_t - completionCallback; /*!< Callback function called after edma transfer finished. */ - void *userData; /*!< Callback parameter passed to callback function. */ + completionCallback; /*!< A callback function called after the eDMA transfer is finished. */ + void *userData; /*!< A callback parameter passed to the callback function. */ }; /******************************************************************************* @@ -75,18 +74,18 @@ extern "C" { #endif /*_cplusplus. */ /*! - * @name I2C Block EDMA Transfer Operation + * @name I2C Block eDMA Transfer Operation * @{ */ /*! - * @brief Init the I2C handle which is used in transcational functions. + * @brief Initializes the I2C handle which is used in transcational functions. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param callback pointer to user callback function. - * @param userData user param passed to the callback function. - * @param edmaHandle EDMA handle pointer. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param callback A pointer to the user callback function. + * @param userData A user parameter passed to the callback function. + * @param edmaHandle eDMA handle pointer. */ void I2C_MasterCreateEDMAHandle(I2C_Type *base, i2c_master_edma_handle_t *handle, @@ -95,33 +94,33 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base, edma_handle_t *edmaHandle); /*! - * @brief Performs a master edma non-blocking transfer on the I2C bus. + * @brief Performs a master eDMA non-blocking transfer on the I2C bus. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param xfer pointer to transfer structure of i2c_master_transfer_t. - * @retval kStatus_Success Sucessully complete the data transmission. - * @retval kStatus_I2C_Busy Previous transmission still not finished. - * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param xfer A pointer to the transfer structure of i2c_master_transfer_t. + * @retval kStatus_Success Sucessfully completed the data transmission. + * @retval kStatus_I2C_Busy A previous transmission is still not finished. + * @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout. * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. - * @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer. + * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer. */ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer); /*! - * @brief Get master transfer status during a edma non-blocking transfer. + * @brief Gets a master transfer status during the eDMA non-blocking transfer. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param count A number of bytes transferred by the non-blocking transaction. */ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count); /*! - * @brief Abort a master edma non-blocking transfer in a early time. + * @brief Aborts a master eDMA non-blocking transfer early. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. + * @param handle A pointer to the i2c_master_edma_handle_t structure. */ void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c index c27b91e9f04..74b1001a88a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h index 7c11572e806..d5a0037bb58 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_llwu.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,7 +35,6 @@ /*! @addtogroup llwu */ /*! @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -52,9 +51,9 @@ */ typedef enum _llwu_external_pin_mode { - kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as wakeup input. */ - kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with rising edge detection. */ - kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with falling edge detection.*/ + kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as a wakeup input. */ + kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with the rising edge detection. */ + kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with the falling edge detection.*/ kLLWU_ExternalPinAnyEdge = 3U /*!< Pin enabled with any change detection. */ } llwu_external_pin_mode_t; @@ -75,9 +74,9 @@ typedef enum _llwu_pin_filter_mode */ typedef struct _llwu_version_id { - uint16_t feature; /*!< Feature Specification Number. */ - uint8_t minor; /*!< Minor version number. */ - uint8_t major; /*!< Major version number. */ + uint16_t feature; /*!< A feature specification number. */ + uint8_t minor; /*!< The minor version number. */ + uint8_t major; /*!< The major version number. */ } llwu_version_id_t; #endif /* FSL_FEATURE_LLWU_HAS_VERID */ @@ -87,20 +86,20 @@ typedef struct _llwu_version_id */ typedef struct _llwu_param { - uint8_t filters; /*!< Number of pin filter. */ - uint8_t dmas; /*!< Number of wakeup DMA. */ - uint8_t modules; /*!< Number of wakeup module. */ - uint8_t pins; /*!< Number of wake up pin. */ + uint8_t filters; /*!< A number of the pin filter. */ + uint8_t dmas; /*!< A number of the wakeup DMA. */ + uint8_t modules; /*!< A number of the wakeup module. */ + uint8_t pins; /*!< A number of the wake up pin. */ } llwu_param_t; #endif /* FSL_FEATURE_LLWU_HAS_PARAM */ #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER) /*! - * @brief External input pin filter control structure + * @brief An external input pin filter control structure */ typedef struct _llwu_external_pin_filter_mode { - uint32_t pinIndex; /*!< Pin number */ + uint32_t pinIndex; /*!< A pin number */ llwu_pin_filter_mode_t filterMode; /*!< Filter mode */ } llwu_external_pin_filter_mode_t; #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */ @@ -122,11 +121,11 @@ extern "C" { /*! * @brief Gets the LLWU version ID. * - * This function gets the LLWU version ID, including major version number, - * minor version number, and feature specification number. + * This function gets the LLWU version ID, including the major version number, + * the minor version number, and the feature specification number. * * @param base LLWU peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId A pointer to the version ID structure. */ static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *versionId) { @@ -138,11 +137,11 @@ static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *version /*! * @brief Gets the LLWU parameter. * - * This function gets the LLWU parameter, including wakeup pin number, module - * number, DMA number, and pin filter number. + * This function gets the LLWU parameter, including a wakeup pin number, a module + * number, a DMA number, and a pin filter number. * * @param base LLWU peripheral base address. - * @param param Pointer to LLWU param structure. + * @param param A pointer to the LLWU parameter structure. */ static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param) { @@ -158,8 +157,8 @@ static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param) * as a wake up source. * * @param base LLWU peripheral base address. - * @param pinIndex pin index which to be enabled as external wakeup source, start from 1. - * @param pinMode pin configuration mode defined in llwu_external_pin_modes_t + * @param pinIndex A pin index to be enabled as an external wakeup source starting from 1. + * @param pinMode A pin configuration mode defined in the llwu_external_pin_modes_t. */ void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode); @@ -167,11 +166,11 @@ void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_exte * @brief Gets the external wakeup source flag. * * This function checks the external pin flag to detect whether the MCU is - * woke up by the specific pin. + * woken up by the specific pin. * * @param base LLWU peripheral base address. - * @param pinIndex pin index, start from 1. - * @return true if the specific pin is wake up source. + * @param pinIndex A pin index, which starts from 1. + * @return True if the specific pin is a wakeup source. */ bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); @@ -181,7 +180,7 @@ bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); * This function clears the external wakeup source flag for a specific pin. * * @param base LLWU peripheral base address. - * @param pinIndex pin index, start from 1. + * @param pinIndex A pin index, which starts from 1. */ void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */ @@ -194,8 +193,8 @@ void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); * as a wake up source. * * @param base LLWU peripheral base address. - * @param moduleIndex module index which to be enabled as internal wakeup source, start from 1. - * @param enable enable or disable setting + * @param moduleIndex A module index to be enabled as an internal wakeup source starting from 1. + * @param enable An enable or a disable setting */ static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable) { @@ -213,31 +212,31 @@ static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint * @brief Gets the external wakeup source flag. * * This function checks the external pin flag to detect whether the system is - * woke up by the specific pin. + * woken up by the specific pin. * * @param base LLWU peripheral base address. - * @param moduleIndex module index, start from 1. - * @return true if the specific pin is wake up source. + * @param moduleIndex A module index, which starts from 1. + * @return True if the specific pin is a wake up source. */ static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t moduleIndex) { +#if (defined(FSL_FEATURE_LLWU_HAS_MF) && FSL_FEATURE_LLWU_HAS_MF) #if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32)) return (bool)(base->MF & (1U << moduleIndex)); #else -#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16)) -#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF) return (bool)(base->MF5 & (1U << moduleIndex)); +#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */ #else +#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16)) return (bool)(base->F5 & (1U << moduleIndex)); -#endif /* FSL_FEATURE_LLWU_HAS_PF */ #else #if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF) return (bool)(base->PF3 & (1U << moduleIndex)); #else return (bool)(base->F3 & (1U << moduleIndex)); -#endif +#endif /* FSL_FEATURE_LLWU_HAS_PF */ #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */ -#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */ +#endif /* FSL_FEATURE_LLWU_HAS_MF */ } #endif /* FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE */ @@ -248,8 +247,8 @@ static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t mo * This function enables/disables the internal DMA that is used as a wake up source. * * @param base LLWU peripheral base address. - * @param moduleIndex Internal module index which used as DMA request source, start from 1. - * @param enable Enable or disable DMA request source + * @param moduleIndex An internal module index which is used as a DMA request source, starting from 1. + * @param enable Enable or disable the DMA request source */ static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable) { @@ -271,8 +270,8 @@ static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uin * This function sets the pin filter configuration. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index which used to enable/disable the digital filter, start from 1. - * @param filterMode filter mode configuration + * @param filterIndex A pin filter index used to enable/disable the digital filter, starting from 1. + * @param filterMode A filter mode configuration */ void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode); @@ -282,18 +281,18 @@ void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_ * This function gets the pin filter flag. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index, start from 1. - * @return true if the flag is a source of existing a low-leakage power mode. + * @param filterIndex A pin filter index, which starts from 1. + * @return True if the flag is a source of the existing low-leakage power mode. */ bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); /*! - * @brief Clear the pin filter configuration. + * @brief Clears the pin filter configuration. * - * This function clear the pin filter flag. + * This function clears the pin filter flag. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index which to be clear the flag, start from 1. + * @param filterIndex A pin filter index to clear the flag, starting from 1. */ void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); @@ -303,10 +302,10 @@ void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); /*! * @brief Sets the reset pin mode. * - * This function sets how the reset pin is used as a low leakage mode exit source. + * This function determines how the reset pin is used as a low leakage mode exit source. * - * @param pinEnable Enable reset pin filter - * @param pinFilterEnable Specify whether pin filter is enabled in Low-Leakage power mode. + * @param pinEnable Enable reset the pin filter + * @param pinFilterEnable Specify whether the pin filter is enabled in Low-Leakage power mode. */ void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode); #endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c index fb6f06c3ac2..bff12af5655 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,7 +48,7 @@ void LMEM_EnableCodeCache(LMEM_Type *base, bool enable) LMEM_CodeCacheInvalidateAll(base); /* Now enable the cache. */ - base->PCCCR |= LMEM_PCCCR_ENCACHE_MASK | LMEM_PCCCR_ENWRBUF_MASK; + base->PCCCR |= LMEM_PCCCR_ENCACHE_MASK; } else { @@ -56,7 +56,7 @@ void LMEM_EnableCodeCache(LMEM_Type *base, bool enable) LMEM_CodeCachePushAll(base); /* Now disable the cache. */ - base->PCCCR &= ~(LMEM_PCCCR_ENCACHE_MASK | LMEM_PCCCR_ENWRBUF_MASK); + base->PCCCR &= ~LMEM_PCCCR_ENCACHE_MASK; } } @@ -236,7 +236,7 @@ void LMEM_CodeCacheClearMultiLines(LMEM_Type *base, uint32_t address, uint32_t l } } } - +#if (!defined(FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE)) || !FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, lmem_cache_mode_t cacheMode) { uint32_t mode = base->PCCRMR; @@ -255,6 +255,7 @@ status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, return kStatus_Success; } } +#endif /* FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE */ #if FSL_FEATURE_LMEM_HAS_SYSTEMBUS_CACHE void LMEM_EnableSystemCache(LMEM_Type *base, bool enable) @@ -265,7 +266,7 @@ void LMEM_EnableSystemCache(LMEM_Type *base, bool enable) LMEM_SystemCacheInvalidateAll(base); /* Now enable the cache. */ - base->PSCCR |= LMEM_PSCCR_ENCACHE_MASK | LMEM_PSCCR_ENWRBUF_MASK; + base->PSCCR |= LMEM_PSCCR_ENCACHE_MASK ; } else { @@ -273,7 +274,7 @@ void LMEM_EnableSystemCache(LMEM_Type *base, bool enable) LMEM_SystemCachePushAll(base); /* Now disable the cache. */ - base->PSCCR &= ~(LMEM_PSCCR_ENCACHE_MASK | LMEM_PSCCR_ENWRBUF_MASK); + base->PSCCR &= ~LMEM_PSCCR_ENCACHE_MASK; } } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h index 9e69feb4130..8df4cea3d3d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lmem_cache.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief LMEM controller driver version 2.0.0. */ -#define FSL_LMEM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief LMEM controller driver version 2.1.0. */ +#define FSL_LMEM_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*@}*/ #define LMEM_CACHE_LINE_SIZE (0x10U) /*!< Cache line is 16-bytes. */ @@ -55,9 +54,9 @@ /*! @brief LMEM cache mode options. */ typedef enum _lmem_cache_mode { - kLMEM_NonCacheable = 0x0U, /*!< CACHE mode: non-cacheable. */ - kLMEM_CacheWriteThrough = 0x2U, /*!< CACHE mode: write-through. */ - kLMEM_CacheWriteBack = 0x3U /*!< CACHE mode: write-back. */ + kLMEM_NonCacheable = 0x0U, /*!< Cache mode: non-cacheable. */ + kLMEM_CacheWriteThrough = 0x2U, /*!< Cache mode: write-through. */ + kLMEM_CacheWriteBack = 0x3U /*!< Cache mode: write-back. */ } lmem_cache_mode_t; /*! @brief LMEM cache regions. */ @@ -106,7 +105,7 @@ extern "C" { /*! * @brief Enables/disables the processor code bus cache. * This function enables/disables the cache. The function first invalidates the entire cache - * and then enables/disable both the cache and write buffers. + * and then enables/disables both the cache and write buffers. * * @param base LMEM peripheral base address. * @param enable The enable or disable flag. @@ -115,6 +114,26 @@ extern "C" { */ void LMEM_EnableCodeCache(LMEM_Type *base, bool enable); +/*! + * @brief Enables/disables the processor code bus write buffer. + * + * @param base LMEM peripheral base address. + * @param enable The enable or disable flag. + * true - enable the code bus write buffer. + * false - disable the code bus write buffer. + */ +static inline void LMEM_EnableCodeWriteBuffer(LMEM_Type *base, bool enable) +{ + if (enable) + { + base->PCCCR |= LMEM_PCCCR_ENWRBUF_MASK; + } + else + { + base->PCCCR &= ~LMEM_PCCCR_ENWRBUF_MASK; + } +} + /*! * @brief Invalidates the processor code bus cache. * This function invalidates the cache both ways, which means that @@ -163,10 +182,10 @@ void LMEM_CodeCacheInvalidateLine(LMEM_Type *base, uint32_t address); * This function invalidates multiple lines in the cache * based on the physical address and length in bytes passed in by the * user. If the function detects that the length meets or exceeds half the - * cache. Then the function performs an entire cache invalidate function, which is + * cache, the function performs an entire cache invalidate function, which is * more efficient than invalidating the cache line-by-line. - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Invalidate - Unconditionally clear valid and modified bits of a cache entry. * * @param base LMEM peripheral base address. @@ -197,8 +216,8 @@ void LMEM_CodeCachePushLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an cache push function, which is * more efficient than pushing the modified lines in the cache line-by-line. - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Push - Push a cache entry if it is valid and modified, then clear the modified bit. If * the entry is not valid or not modified, leave as is. This action does not clear the valid * bit. A cache push is synonymous with a cache flush. @@ -230,8 +249,8 @@ void LMEM_CodeCacheClearLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half the total amount of * cache, the function performs a cache clear function which is * more efficient than clearing the lines in the cache line-by-line. - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Clear - Push a cache entry if it is valid and modified, then clear the valid and * modify bits. If entry not valid or not modified, clear the valid bit. * @@ -242,6 +261,7 @@ void LMEM_CodeCacheClearLine(LMEM_Type *base, uint32_t address); */ void LMEM_CodeCacheClearMultiLines(LMEM_Type *base, uint32_t address, uint32_t length); +#if (!defined(FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE)) || !FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE /*! * @brief Demotes the cache mode of a region in processor code bus cache. * This function allows the user to demote the cache mode of a region within the device's @@ -264,6 +284,7 @@ void LMEM_CodeCacheClearMultiLines(LMEM_Type *base, uint32_t address, uint32_t l * kStatus_Fail The cache demote operation is failure. */ status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, lmem_cache_mode_t cacheMode); +#endif /* FSL_FEATURE_LMEM_SUPPORT_ICACHE_DEMOTE_REMOVE */ /*@}*/ @@ -285,6 +306,26 @@ status_t LMEM_CodeCacheDemoteRegion(LMEM_Type *base, lmem_cache_region_t region, */ void LMEM_EnableSystemCache(LMEM_Type *base, bool enable); +/*! + * @brief Enables/disables the processor system bus write buffer. + * + * @param base LMEM peripheral base address. + * @param enable The enable or disable flag. + * true - enable the system bus write buffer. + * false - disable the system bus write buffer. + */ +static inline void LMEM_EnableSystemWriteBuffer(LMEM_Type *base, bool enable) +{ + if (enable) + { + base->PSCCR |= LMEM_PSCCR_ENWRBUF_MASK; + } + else + { + base->PSCCR &= ~LMEM_PSCCR_ENWRBUF_MASK; + } +} + /*! * @brief Invalidates the processor system bus cache. * This function invalidates the entire cache both ways. @@ -320,7 +361,7 @@ void LMEM_SystemCacheClearAll(LMEM_Type *base); * @brief Invalidates a specific line in the processor system bus cache. * This function invalidates a specific line in the cache * based on the physical address passed in by the user. - * Invalidate - Unconditionally clear valid and modify bits of a cache entry + * Invalidate - Unconditionally clears valid and modify bits of a cache entry. * * @param base LMEM peripheral base address. Should be 16-byte aligned address. * If not, it is changed to the 16-byte aligned memory address. @@ -335,8 +376,8 @@ void LMEM_SystemCacheInvalidateLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an entire cache invalidate function (which is * more efficient than invalidating the cache line-by-line). - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Invalidate - Unconditionally clear valid and modify bits of a cache entry * * @param base LMEM peripheral base address. @@ -367,8 +408,8 @@ void LMEM_SystemCachePushLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an entire cache push function (which is * more efficient than pushing the modified lines in the cache line-by-line). - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Push - Push a cache entry if it is valid and modified, then clear the modify bit. If * the entry is not valid or not modified, leave as is. This action does not clear the valid * bit. A cache push is synonymous with a cache flush. @@ -400,8 +441,8 @@ void LMEM_SystemCacheClearLine(LMEM_Type *base, uint32_t address); * user. If the function detects that the length meets or exceeds half of the * cache, the function performs an entire cache clear function (which is * more efficient than clearing the lines in the cache line-by-line). - * The need to check half the total amount of cache is due to the fact that the cache consists of - * two ways and that line commands based on the physical address searches both ways. + * Because the cache consists of two ways and line commands based on the physical address searches both ways, + * check half the total amount of cache. * Clear - Push a cache entry if it is valid and modified, then clear the valid and * modify bits. If the entry is not valid or not modified, clear the valid bit. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c index b3dcc89d55d..67b3b9785cf 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,9 +48,17 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base); /*! @brief Pointers to LPTMR bases for each instance. */ static LPTMR_Type *const s_lptmrBases[] = LPTMR_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to LPTMR clocks for each instance. */ static const clock_ip_name_t s_lptmrClocks[] = LPTMR_CLOCKS; +#if defined(LPTMR_PERIPH_CLOCKS) +/* Array of LPTMR functional clock name. */ +static const clock_ip_name_t s_lptmrPeriphClocks[] = LPTMR_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + /******************************************************************************* * Code ******************************************************************************/ @@ -59,7 +67,7 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_LPTMR_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_lptmrBases); instance++) { if (s_lptmrBases[instance] == base) { @@ -67,7 +75,7 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base) } } - assert(instance < FSL_FEATURE_SOC_LPTMR_COUNT); + assert(instance < ARRAY_SIZE(s_lptmrBases)); return instance; } @@ -76,8 +84,17 @@ void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPTMR_GetInstance(base); + /* Ungate the LPTMR clock*/ - CLOCK_EnableClock(s_lptmrClocks[LPTMR_GetInstance(base)]); + CLOCK_EnableClock(s_lptmrClocks[instance]); +#if defined(LPTMR_PERIPH_CLOCKS) + CLOCK_EnableClock(s_lptmrPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure the timers operation mode and input pin setup */ base->CSR = (LPTMR_CSR_TMS(config->timerMode) | LPTMR_CSR_TFC(config->enableFreeRunning) | @@ -92,8 +109,17 @@ void LPTMR_Deinit(LPTMR_Type *base) { /* Disable the LPTMR and reset the internal logic */ base->CSR &= ~LPTMR_CSR_TEN_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPTMR_GetInstance(base); + /* Gate the LPTMR clock*/ - CLOCK_DisableClock(s_lptmrClocks[LPTMR_GetInstance(base)]); + CLOCK_DisableClock(s_lptmrClocks[instance]); +#if defined(LPTMR_PERIPH_CLOCKS) + CLOCK_DisableClock(s_lptmrPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void LPTMR_GetDefaultConfig(lptmr_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h index fd3cb1ed242..6cc909b3148 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lptmr.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,22 +33,20 @@ #include "fsl_common.h" /*! - * @addtogroup lptmr_driver + * @addtogroup lptmr * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */ +#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1 */ /*@}*/ -/*! @brief LPTMR pin selection, used in pulse counter mode.*/ +/*! @brief LPTMR pin selection used in pulse counter mode.*/ typedef enum _lptmr_pin_select { kLPTMR_PinSelectInput_0 = 0x0U, /*!< Pulse counter input 0 is selected */ @@ -57,7 +55,7 @@ typedef enum _lptmr_pin_select kLPTMR_PinSelectInput_3 = 0x3U /*!< Pulse counter input 3 is selected */ } lptmr_pin_select_t; -/*! @brief LPTMR pin polarity, used in pulse counter mode.*/ +/*! @brief LPTMR pin polarity used in pulse counter mode.*/ typedef enum _lptmr_pin_polarity { kLPTMR_PinPolarityActiveHigh = 0x0U, /*!< Pulse Counter input source is active-high */ @@ -104,13 +102,13 @@ typedef enum _lptmr_prescaler_clock_select kLPTMR_PrescalerClock_3 = 0x3U, /*!< Prescaler/glitch filter clock 3 selected. */ } lptmr_prescaler_clock_select_t; -/*! @brief List of LPTMR interrupts */ +/*! @brief List of the LPTMR interrupts */ typedef enum _lptmr_interrupt_enable { kLPTMR_TimerInterruptEnable = LPTMR_CSR_TIE_MASK, /*!< Timer interrupt enable */ } lptmr_interrupt_enable_t; -/*! @brief List of LPTMR status flags */ +/*! @brief List of the LPTMR status flags */ typedef enum _lptmr_status_flags { kLPTMR_TimerCompareFlag = LPTMR_CSR_TCF_MASK, /*!< Timer compare flag */ @@ -121,18 +119,18 @@ typedef enum _lptmr_status_flags * * This structure holds the configuration settings for the LPTMR peripheral. To initialize this * structure to reasonable defaults, call the LPTMR_GetDefaultConfig() function and pass a - * pointer to your config structure instance. + * pointer to your configuration structure instance. * - * The config struct can be made const so it resides in flash + * The configuration struct can be made constant so it resides in flash. */ typedef struct _lptmr_config { lptmr_timer_mode_t timerMode; /*!< Time counter mode or pulse counter mode */ lptmr_pin_select_t pinSelect; /*!< LPTMR pulse input pin select; used only in pulse counter mode */ lptmr_pin_polarity_t pinPolarity; /*!< LPTMR pulse input pin polarity; used only in pulse counter mode */ - bool enableFreeRunning; /*!< true: enable free running, counter is reset on overflow - false: counter is reset when the compare flag is set */ - bool bypassPrescaler; /*!< true: bypass prescaler; false: use clock from prescaler */ + bool enableFreeRunning; /*!< True: enable free running, counter is reset on overflow + False: counter is reset when the compare flag is set */ + bool bypassPrescaler; /*!< True: bypass prescaler; false: use clock from prescaler */ lptmr_prescaler_clock_select_t prescalerClockSource; /*!< LPTMR clock source */ lptmr_prescaler_glitch_value_t value; /*!< Prescaler or glitch filter value */ } lptmr_config_t; @@ -151,26 +149,26 @@ extern "C" { */ /*! - * @brief Ungate the LPTMR clock and configures the peripheral for basic operation. + * @brief Ungates the LPTMR clock and configures the peripheral for a basic operation. * * @note This API should be called at the beginning of the application using the LPTMR driver. * * @param base LPTMR peripheral base address - * @param config Pointer to user's LPTMR config structure. + * @param config A pointer to the LPTMR configuration structure. */ void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config); /*! - * @brief Gate the LPTMR clock + * @brief Gates the LPTMR clock. * * @param base LPTMR peripheral base address */ void LPTMR_Deinit(LPTMR_Type *base); /*! - * @brief Fill in the LPTMR config struct with the default settings + * @brief Fills in the LPTMR configuration structure with default settings. * - * The default values are: + * The default values are as follows. * @code * config->timerMode = kLPTMR_TimerModeTimeCounter; * config->pinSelect = kLPTMR_PinSelectInput_0; @@ -180,7 +178,7 @@ void LPTMR_Deinit(LPTMR_Type *base); * config->prescalerClockSource = kLPTMR_PrescalerClock_1; * config->value = kLPTMR_Prescale_Glitch_0; * @endcode - * @param config Pointer to user's LPTMR config structure. + * @param config A pointer to the LPTMR configuration structure. */ void LPTMR_GetDefaultConfig(lptmr_config_t *config); @@ -200,7 +198,12 @@ void LPTMR_GetDefaultConfig(lptmr_config_t *config); */ static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask) { - base->CSR |= mask; + uint32_t reg = base->CSR; + + /* Clear the TCF bit so that we don't clear this w1c bit when writing back */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg |= mask; + base->CSR = reg; } /*! @@ -208,11 +211,16 @@ static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask) * * @param base LPTMR peripheral base address * @param mask The interrupts to disable. This is a logical OR of members of the - * enumeration ::lptmr_interrupt_enable_t + * enumeration ::lptmr_interrupt_enable_t. */ static inline void LPTMR_DisableInterrupts(LPTMR_Type *base, uint32_t mask) { - base->CSR &= ~mask; + uint32_t reg = base->CSR; + + /* Clear the TCF bit so that we don't clear this w1c bit when writing back */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg &= ~mask; + base->CSR = reg; } /*! @@ -236,7 +244,7 @@ static inline uint32_t LPTMR_GetEnabledInterrupts(LPTMR_Type *base) */ /*! - * @brief Gets the LPTMR status flags + * @brief Gets the LPTMR status flags. * * @param base LPTMR peripheral base address * @@ -249,11 +257,11 @@ static inline uint32_t LPTMR_GetStatusFlags(LPTMR_Type *base) } /*! - * @brief Clears the LPTMR status flags + * @brief Clears the LPTMR status flags. * * @param base LPTMR peripheral base address * @param mask The status flags to clear. This is a logical OR of members of the - * enumeration ::lptmr_status_flags_t + * enumeration ::lptmr_status_flags_t. */ static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask) { @@ -263,47 +271,48 @@ static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask) /*! @}*/ /*! - * @name Read and Write the timer period + * @name Read and write the timer period * @{ */ /*! * @brief Sets the timer period in units of count. * - * Timers counts from 0 till it equals the count value set here. The count value is written to + * Timers counts from 0 until it equals the count value set here. The count value is written to * the CMR register. * * @note * 1. The TCF flag is set with the CNR equals the count provided here and then increments. - * 2. User can call the utility macros provided in fsl_common.h to convert to ticks + * 2. Call the utility macros provided in the fsl_common.h to convert to ticks. * * @param base LPTMR peripheral base address - * @param ticks Timer period in units of ticks + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. */ -static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint16_t ticks) +static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint32_t ticks) { - base->CMR = ticks; + assert(ticks > 0); + base->CMR = ticks - 1; } /*! * @brief Reads the current timer counting value. * - * This function returns the real-time timer counting value, in a range from 0 to a + * This function returns the real-time timer counting value in a range from 0 to a * timer period. * - * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. * * @param base LPTMR peripheral base address * - * @return Current counter value in ticks + * @return The current counter value in ticks */ -static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) +static inline uint32_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) { - /* Must first write any value to the CNR. This will synchronize and register the current value + /* Must first write any value to the CNR. This synchronizes and registers the current value * of the CNR into a temporary register which can then be read */ base->CNR = 0U; - return (uint16_t)base->CNR; + return (uint32_t)((base->CNR & LPTMR_CNR_COUNTER_MASK) >> LPTMR_CNR_COUNTER_SHIFT); } /*! @}*/ @@ -314,30 +323,40 @@ static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) */ /*! - * @brief Starts the timer counting. + * @brief Starts the timer. * * After calling this function, the timer counts up to the CMR register value. - * Each time the timer reaches CMR value and then increments, it generates a - * trigger pulse and sets the timeout interrupt flag. An interrupt will also be + * Each time the timer reaches the CMR value and then increments, it generates a + * trigger pulse and sets the timeout interrupt flag. An interrupt is also * triggered if the timer interrupt is enabled. * * @param base LPTMR peripheral base address */ static inline void LPTMR_StartTimer(LPTMR_Type *base) { - base->CSR |= LPTMR_CSR_TEN_MASK; + uint32_t reg = base->CSR; + + /* Clear the TCF bit to avoid clearing the w1c bit when writing back. */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg |= LPTMR_CSR_TEN_MASK; + base->CSR = reg; } /*! - * @brief Stops the timer counting. + * @brief Stops the timer. * - * This function stops the timer counting and resets the timer's counter register + * This function stops the timer and resets the timer's counter register. * * @param base LPTMR peripheral base address */ static inline void LPTMR_StopTimer(LPTMR_Type *base) { - base->CSR &= ~LPTMR_CSR_TEN_MASK; + uint32_t reg = base->CSR; + + /* Clear the TCF bit to avoid clearing the w1c bit when writing back. */ + reg &= ~(LPTMR_CSR_TCF_MASK); + reg &= ~LPTMR_CSR_TEN_MASK; + base->CSR = reg; } /*! @}*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c index b1b015f6f49..9a83b5698d2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -109,9 +109,23 @@ static lpuart_handle_t *s_lpuartHandle[FSL_FEATURE_SOC_LPUART_COUNT]; /* Array of LPUART peripheral base address. */ static LPUART_Type *const s_lpuartBases[] = LPUART_BASE_PTRS; /* Array of LPUART IRQ number. */ +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +static const IRQn_Type s_lpuartRxIRQ[] = LPUART_RX_IRQS; +static const IRQn_Type s_lpuartTxIRQ[] = LPUART_TX_IRQS; +#else static const IRQn_Type s_lpuartIRQ[] = LPUART_RX_TX_IRQS; +#endif +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of LPUART clock name. */ static const clock_ip_name_t s_lpuartClock[] = LPUART_CLOCKS; + +#if defined(LPUART_PERIPH_CLOCKS) +/* Array of LPUART functional clock name. */ +static const clock_ip_name_t s_lpuartPeriphClocks[] = LPUART_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + /* LPUART ISR for transactional APIs. */ static lpuart_isr_t s_lpuartIsr; @@ -123,7 +137,7 @@ uint32_t LPUART_GetInstance(LPUART_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_LPUART_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_lpuartBases); instance++) { if (s_lpuartBases[instance] == base) { @@ -131,13 +145,15 @@ uint32_t LPUART_GetInstance(LPUART_Type *base) } } - assert(instance < FSL_FEATURE_SOC_LPUART_COUNT); + assert(instance < ARRAY_SIZE(s_lpuartBases)); return instance; } static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + size_t size; if (handle->rxRingBufferTail > handle->rxRingBufferHead) @@ -154,6 +170,8 @@ static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_han static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + bool full; if (LPUART_TransferGetRxRingBufferLength(base, handle) == (handle->rxRingBufferSize - 1U)) @@ -169,6 +187,8 @@ static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length) { + assert(data); + size_t i; /* The Non Blocking write data API assume user have ensured there is enough space in @@ -181,33 +201,48 @@ static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length) { + assert(data); + size_t i; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); +#endif /* The Non Blocking read data API assume user have ensured there is enough space in peripheral to write. */ for (i = 0; i < length; i++) { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (isSevenDataBits) + { + data[i] = (base->DATA & 0x7F); + } + else + { + data[i] = base->DATA; + } +#else data[i] = base->DATA; +#endif } } -void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz) +status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz) { assert(config); + assert(config->baudRate_Bps); #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->txFifoWatermark); assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->rxFifoWatermark); #endif + uint32_t temp; uint16_t sbr, sbrTemp; uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff; - /* Enable lpuart clock */ - CLOCK_EnableClock(s_lpuartClock[LPUART_GetInstance(base)]); - - /* Disable LPUART TX RX before setting. */ - base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); - /* This LPUART instantiation uses a slightly different baud rate calculation * The idea is to use the best OSR (over-sampling rate) possible * Note, OSR is typically hard-set to 16 in other LPUART instantiations @@ -248,34 +283,75 @@ void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcC /* Check to see if actual baud rate is within 3% of desired baud rate * based on the best calculate OSR value */ - if (baudDiff < ((config->baudRate_Bps / 100) * 3)) + if (baudDiff > ((config->baudRate_Bps / 100) * 3)) { - temp = base->BAUD; + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_LPUART_BaudrateNotSupport; + } - /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. - * If so, then "BOTHEDGE" sampling must be turned on */ - if ((osr > 3) && (osr < 8)) - { - temp |= LPUART_BAUD_BOTHEDGE_MASK; - } +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPUART_GetInstance(base); - /* program the osr value (bit value is one less than actual value) */ - temp &= ~LPUART_BAUD_OSR_MASK; - temp |= LPUART_BAUD_OSR(osr - 1); + /* Enable lpuart clock */ + CLOCK_EnableClock(s_lpuartClock[instance]); +#if defined(LPUART_PERIPH_CLOCKS) + CLOCK_EnableClock(s_lpuartPeriphClocks[instance]); +#endif - /* write the sbr value to the BAUD registers */ - temp &= ~LPUART_BAUD_SBR_MASK; - base->BAUD = temp | LPUART_BAUD_SBR(sbr); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL + /*Reset all internal logic and registers, except the Global Register */ + LPUART_SoftwareReset(base); +#else + /* Disable LPUART TX RX before setting. */ + base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); +#endif + + temp = base->BAUD; + + /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. + * If so, then "BOTHEDGE" sampling must be turned on */ + if ((osr > 3) && (osr < 8)) + { + temp |= LPUART_BAUD_BOTHEDGE_MASK; } + /* program the osr value (bit value is one less than actual value) */ + temp &= ~LPUART_BAUD_OSR_MASK; + temp |= LPUART_BAUD_OSR(osr - 1); + + /* write the sbr value to the BAUD registers */ + temp &= ~LPUART_BAUD_SBR_MASK; + base->BAUD = temp | LPUART_BAUD_SBR(sbr); + /* Set bit count and parity mode. */ base->BAUD &= ~LPUART_BAUD_M10_MASK; temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK); - if (kLPUART_ParityDisabled != config->parityMode) + temp |= (uint8_t)config->parityMode; + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (kLPUART_SevenDataBits == config->dataBitsCount) + { + if (kLPUART_ParityDisabled != config->parityMode) + { + temp &= ~LPUART_CTRL_M7_MASK; /* Seven data bits and one parity bit */ + } + else + { + temp |= LPUART_CTRL_M7_MASK; + } + } + else +#endif { - temp |= (LPUART_CTRL_M_MASK | (uint8_t)config->parityMode); + if (kLPUART_ParityDisabled != config->parityMode) + { + temp |= LPUART_CTRL_M_MASK; /* Eight data bits and one parity bit */ + } } base->CTRL = temp; @@ -298,17 +374,27 @@ void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcC #endif /* Clear all status flags */ - temp = (LPUART_STAT_LBKDIF_MASK | LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT - temp |= LPUART_STAT_IDLE_MASK; + temp |= LPUART_STAT_LBKDIF_MASK; #endif #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK); #endif + /* Set data bits order. */ + if (config->isMsb) + { + temp |= LPUART_STAT_MSBF_MASK; + } + else + { + temp &= ~LPUART_STAT_MSBF_MASK; + } + base->STAT |= temp; /* Enable TX/RX base on configure structure. */ @@ -324,6 +410,8 @@ void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcC } base->CTRL = temp; + + return kStatus_Success; } void LPUART_Deinit(LPUART_Type *base) { @@ -341,11 +429,11 @@ void LPUART_Deinit(LPUART_Type *base) } /* Clear all status flags */ - temp = (LPUART_STAT_LBKDIF_MASK | LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + temp = (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT - temp |= LPUART_STAT_IDLE_MASK; + temp |= LPUART_STAT_LBKDIF_MASK; #endif #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING @@ -357,15 +445,27 @@ void LPUART_Deinit(LPUART_Type *base) /* Disable the module. */ base->CTRL = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance = LPUART_GetInstance(base); + /* Disable lpuart clock */ - CLOCK_DisableClock(s_lpuartClock[LPUART_GetInstance(base)]); + CLOCK_DisableClock(s_lpuartClock[instance]); + +#if defined(LPUART_PERIPH_CLOCKS) + CLOCK_DisableClock(s_lpuartPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void LPUART_GetDefaultConfig(lpuart_config_t *config) { assert(config); + config->baudRate_Bps = 115200U; config->parityMode = kLPUART_ParityDisabled; + config->dataBitsCount = kLPUART_EightDataBits; + config->isMsb = false; #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT config->stopBitCount = kLPUART_OneStopBit; #endif @@ -377,18 +477,14 @@ void LPUART_GetDefaultConfig(lpuart_config_t *config) config->enableRx = false; } -void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) +status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) { + assert(baudRate_Bps); + uint32_t temp, oldCtrl; uint16_t sbr, sbrTemp; uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff; - /* Store CTRL before disable Tx and Rx */ - oldCtrl = base->CTRL; - - /* Disable LPUART TX RX before setting. */ - base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); - /* This LPUART instantiation uses a slightly different baud rate calculation * The idea is to use the best OSR (over-sampling rate) possible * Note, OSR is typically hard-set to 16 in other LPUART instantiations @@ -431,6 +527,12 @@ void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcCl * based on the best calculate OSR value */ if (baudDiff < ((baudRate_Bps / 100) * 3)) { + /* Store CTRL before disable Tx and Rx */ + oldCtrl = base->CTRL; + + /* Disable LPUART TX RX before setting. */ + base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK); + temp = base->BAUD; /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling. @@ -447,17 +549,25 @@ void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcCl /* write the sbr value to the BAUD registers */ temp &= ~LPUART_BAUD_SBR_MASK; base->BAUD = temp | LPUART_BAUD_SBR(sbr); - } - /* Restore CTRL. */ - base->CTRL = oldCtrl; + /* Restore CTRL. */ + base->CTRL = oldCtrl; + + return kStatus_Success; + } + else + { + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_LPUART_BaudrateNotSupport; + } } void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask) { base->BAUD |= ((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)); #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO - base->FIFO |= ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); + base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) | + ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); #endif mask &= 0xFFFFFF00U; base->CTRL |= mask; @@ -467,7 +577,8 @@ void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask) { base->BAUD &= ~((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)); #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO - base->FIFO &= ~((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); + base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) & + ~((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)); #endif mask &= 0xFFFFFF00U; base->CTRL &= ~mask; @@ -503,24 +614,24 @@ status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask) status_t status; #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO temp = (uint32_t)base->FIFO; - temp &= (uint32_t)(~(kLPUART_TxFifoOverflowFlag | kLPUART_RxFifoUnderflowFlag)); - temp |= mask & (kLPUART_TxFifoOverflowFlag | kLPUART_RxFifoUnderflowFlag); + temp &= (uint32_t)(~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)); + temp |= (mask << 16) & (LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK); base->FIFO = temp; #endif temp = (uint32_t)base->STAT; #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT - temp &= (uint32_t)(~(kLPUART_LinBreakFlag)); - temp |= mask & kLPUART_LinBreakFlag; + temp &= (uint32_t)(~(LPUART_STAT_LBKDIF_MASK)); + temp |= mask & LPUART_STAT_LBKDIF_MASK; #endif - temp &= (uint32_t)(~(kLPUART_RxActiveEdgeFlag | kLPUART_IdleLineFlag | kLPUART_RxOverrunFlag | - kLPUART_NoiseErrorFlag | kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag)); - temp |= mask & (kLPUART_RxActiveEdgeFlag | kLPUART_IdleLineFlag | kLPUART_RxOverrunFlag | kLPUART_NoiseErrorFlag | - kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag); + temp &= (uint32_t)(~(LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK)); + temp |= mask & (LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_IDLE_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK | + LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK); #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING - temp &= (uint32_t)(~(kLPUART_DataMatch2Flag | kLPUART_DataMatch2Flag)); - temp |= mask & (kLPUART_DataMatch2Flag | kLPUART_DataMatch2Flag); + temp &= (uint32_t)(~(LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK)); + temp |= mask & (LPUART_STAT_MA2F_MASK | LPUART_STAT_MA1F_MASK); #endif - base->STAT |= temp; + base->STAT = temp; /* If some flags still pending. */ if (mask & LPUART_GetStatusFlags(base)) { @@ -540,6 +651,8 @@ status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask) void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length) { + assert(data); + /* This API can only ensure that the data is written into the data buffer but can't ensure all data in the data buffer are sent into the transmit shift buffer. */ while (length--) @@ -553,7 +666,15 @@ void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length) status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length) { + assert(data); + uint32_t statusFlag; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); +#endif while (length--) { @@ -589,7 +710,18 @@ status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length) return kStatus_LPUART_ParityError; } } +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (isSevenDataBits) + { + *(data++) = (base->DATA & 0x7F); + } + else + { + *(data++) = base->DATA; + } +#else *(data++) = base->DATA; +#endif } return kStatus_Success; @@ -603,6 +735,12 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, assert(handle); uint32_t instance; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); +#endif /* Zero the handle. */ memset(handle, 0, sizeof(lpuart_handle_t)); @@ -615,6 +753,11 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, handle->callback = callback; handle->userData = userData; +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + /* Initial seven data bits flag */ + handle->isSevenDataBits = isSevenDataBits; +#endif + #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO /* Note: Take care of the RX FIFO, RX interrupt request only assert when received bytes @@ -624,7 +767,7 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, 5 bytes are received. the last byte will be saved in FIFO but not trigger RX interrupt because the water mark is 2. */ - base->WATER &= (~LPUART_WATER_RXWATER_SHIFT); + base->WATER &= (~LPUART_WATER_RXWATER_MASK); #endif /* Get instance from peripheral base address. */ @@ -635,8 +778,13 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, s_lpuartIsr = LPUART_TransferHandleIRQ; - /* Enable interrupt in NVIC. */ +/* Enable interrupt in NVIC. */ +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ + EnableIRQ(s_lpuartRxIRQ[instance]); + EnableIRQ(s_lpuartTxIRQ[instance]); +#else EnableIRQ(s_lpuartIRQ[instance]); +#endif } void LPUART_TransferStartRingBuffer(LPUART_Type *base, @@ -645,18 +793,16 @@ void LPUART_TransferStartRingBuffer(LPUART_Type *base, size_t ringBufferSize) { assert(handle); + assert(ringBuffer); /* Setup the ring buffer address */ - if (ringBuffer) - { - handle->rxRingBuffer = ringBuffer; - handle->rxRingBufferSize = ringBufferSize; - handle->rxRingBufferHead = 0U; - handle->rxRingBufferTail = 0U; + handle->rxRingBuffer = ringBuffer; + handle->rxRingBufferSize = ringBufferSize; + handle->rxRingBufferHead = 0U; + handle->rxRingBufferTail = 0U; - /* Enable the interrupt to accept the data when user need the ring buffer. */ - LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); - } + /* Enable the interrupt to accept the data when user need the ring buffer. */ + LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable); } void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle) @@ -676,13 +822,12 @@ void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle) status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer) { - status_t status; + assert(handle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } + status_t status; /* Return error if current TX busy. */ if (kLPUART_TxBusy == handle->txState) @@ -707,6 +852,8 @@ status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *hand void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + LPUART_DisableInterrupts(base, kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_TransmissionCompleteInterruptEnable); handle->txDataSize = 0; @@ -715,16 +862,14 @@ void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle) status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kLPUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - *count = handle->txDataSizeAll - handle->txDataSize; return kStatus_Success; @@ -735,6 +880,11 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, lpuart_transfer_t *xfer, size_t *receivedBytes) { + assert(handle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); + uint32_t i; status_t status; /* How many bytes to copy from ring buffer to user memory. */ @@ -743,13 +893,6 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, size_t bytesToReceive; /* How many bytes currently have received. */ size_t bytesCurrentReceived; - uint32_t regPrimask = 0U; - - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } /* How to get data: 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize @@ -773,8 +916,8 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, /* If RX ring buffer is used. */ if (handle->rxRingBuffer) { - /* Disable IRQ, protect ring buffer. */ - regPrimask = DisableGlobalIRQ(); + /* Disable LPUART RX IRQ, protect ring buffer. */ + LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable); /* How many bytes in RX ring buffer currently. */ bytesToCopy = LPUART_TransferGetRxRingBufferLength(base, handle); @@ -811,8 +954,8 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, handle->rxDataSizeAll = bytesToReceive; handle->rxState = kLPUART_RxBusy; } - /* Enable IRQ if previously enabled. */ - EnableGlobalIRQ(regPrimask); + /* Enable LPUART RX IRQ if previously enabled. */ + LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable); /* Call user callback since all data are received. */ if (0 == bytesToReceive) @@ -849,6 +992,8 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */ if (!handle->rxRingBuffer) { @@ -862,16 +1007,14 @@ void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle) status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kLPUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - *count = handle->rxDataSizeAll - handle->rxDataSize; return kStatus_Success; @@ -879,19 +1022,17 @@ status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *hand void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) { + assert(handle); + uint8_t count; uint8_t tempCount; - volatile uint8_t dummy; - - assert(handle); /* If RX overrun. */ if (LPUART_STAT_OR_MASK & base->STAT) { - /* Read base->DATA, otherwise the RX does not work. */ - dummy = base->DATA; - /* Avoid optimization */ - dummy++; + /* Clear overrun flag, otherwise the RX does not work. */ + base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK); + /* Trigger callback. */ if (handle->callback) { @@ -964,8 +1105,19 @@ void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) } } - /* Read data. */ +/* Read data. */ +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (handle->isSevenDataBits) + { + handle->rxRingBuffer[handle->rxRingBufferHead] = (base->DATA & 0x7F); + } + else + { + handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA; + } +#else handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA; +#endif /* Increase handle->rxRingBufferHead. */ if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize) @@ -1033,71 +1185,113 @@ void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle) void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle) { - /* TODO: To be implemented. */ + /* To be implemented by User. */ } #if defined(LPUART0) -void LPUART0_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART0_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); +} +void LPUART0_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART0, s_lpuartHandle[0]); } -void LPUART0_RX_TX_DriverIRQHandler(void) +#else +void LPUART0_DriverIRQHandler(void) { - LPUART0_DriverIRQHandler(); + s_lpuartIsr(LPUART0, s_lpuartHandle[0]); } #endif +#endif #if defined(LPUART1) -void LPUART1_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART1_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); +} +void LPUART1_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART1, s_lpuartHandle[1]); } -void LPUART1_RX_TX_DriverIRQHandler(void) +#else +void LPUART1_DriverIRQHandler(void) { - LPUART1_DriverIRQHandler(); + s_lpuartIsr(LPUART1, s_lpuartHandle[1]); } #endif +#endif #if defined(LPUART2) -void LPUART2_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART2_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); +} +void LPUART2_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART2, s_lpuartHandle[2]); } -void LPUART2_RX_TX_DriverIRQHandler(void) +#else +void LPUART2_DriverIRQHandler(void) { - LPUART2_DriverIRQHandler(); + s_lpuartIsr(LPUART2, s_lpuartHandle[2]); } #endif +#endif #if defined(LPUART3) -void LPUART3_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART3_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); +} +void LPUART3_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART3, s_lpuartHandle[3]); } -void LPUART3_RX_TX_DriverIRQHandler(void) +#else +void LPUART3_DriverIRQHandler(void) { - LPUART3_DriverIRQHandler(); + s_lpuartIsr(LPUART3, s_lpuartHandle[3]); } #endif +#endif #if defined(LPUART4) -void LPUART4_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART4_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); +} +void LPUART4_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART4, s_lpuartHandle[4]); } -void LPUART4_RX_TX_DriverIRQHandler(void) +#else +void LPUART4_DriverIRQHandler(void) { - LPUART4_DriverIRQHandler(); + s_lpuartIsr(LPUART4, s_lpuartHandle[4]); } #endif +#endif #if defined(LPUART5) -void LPUART5_DriverIRQHandler(void) +#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ +void LPUART5_TX_DriverIRQHandler(void) +{ + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); +} +void LPUART5_RX_DriverIRQHandler(void) { s_lpuartIsr(LPUART5, s_lpuartHandle[5]); } -void LPUART5_RX_TX_DriverIRQHandler(void) +#else +void LPUART5_DriverIRQHandler(void) { - LPUART5_DriverIRQHandler(); + s_lpuartIsr(LPUART5, s_lpuartHandle[5]); } #endif +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h index a357400b56a..0c60f82d88f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,36 +37,35 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief LPUART driver version 2.1.0. */ -#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief LPUART driver version 2.2.3. */ +#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 2, 3)) /*@}*/ /*! @brief Error codes for the LPUART driver. */ enum _lpuart_status { - kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */ - kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */ - kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */ - kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */ - kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */ - kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */ - kStatus_LPUART_FlagCannotClearManually = - MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */ - kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */ + kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */ + kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */ + kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */ + kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */ + kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */ + kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */ + kStatus_LPUART_FlagCannotClearManually = MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */ + kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */ kStatus_LPUART_RxRingBufferOverrun = MAKE_STATUS(kStatusGroup_LPUART, 8), /*!< LPUART RX software ring buffer overrun. */ kStatus_LPUART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_LPUART, 9), /*!< LPUART RX receiver overrun. */ kStatus_LPUART_NoiseError = MAKE_STATUS(kStatusGroup_LPUART, 10), /*!< LPUART noise error. */ kStatus_LPUART_FramingError = MAKE_STATUS(kStatusGroup_LPUART, 11), /*!< LPUART framing error. */ kStatus_LPUART_ParityError = MAKE_STATUS(kStatusGroup_LPUART, 12), /*!< LPUART parity error. */ + kStatus_LPUART_BaudrateNotSupport = + MAKE_STATUS(kStatusGroup_LPUART, 13), /*!< Baudrate is not support in current clock source */ }; /*! @brief LPUART parity mode. */ @@ -77,6 +76,15 @@ typedef enum _lpuart_parity_mode kLPUART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */ } lpuart_parity_mode_t; +/*! @brief LPUART data bits count. */ +typedef enum _lpuart_data_bits +{ + kLPUART_EightDataBits = 0x0U, /*!< Eight data bit */ +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + kLPUART_SevenDataBits = 0x1U, /*!< Seven data bit */ +#endif +} lpuart_data_bits_t; + /*! @brief LPUART stop bit count. */ typedef enum _lpuart_stop_bit_count { @@ -158,11 +166,13 @@ enum _lpuart_flags #endif }; -/*! @brief LPUART configure structure. */ +/*! @brief LPUART configuration structure. */ typedef struct _lpuart_config { - uint32_t baudRate_Bps; /*!< LPUART baud rate */ - lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */ + uint32_t baudRate_Bps; /*!< LPUART baud rate */ + lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */ + lpuart_data_bits_t dataBitsCount; /*!< Data bits count, eight (default), seven */ + bool isMsb; /*!< Data bits order, LSB (default), MSB */ #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */ #endif @@ -206,7 +216,11 @@ struct _lpuart_handle void *userData; /*!< LPUART callback function parameter.*/ volatile uint8_t txState; /*!< TX transfer state. */ - volatile uint8_t rxState; /*!< RX transfer state */ + volatile uint8_t rxState; /*!< RX transfer state. */ + +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + bool isSevenDataBits; /*!< Seven data bits flag. */ +#endif }; /******************************************************************************* @@ -217,32 +231,59 @@ struct _lpuart_handle extern "C" { #endif /* _cplusplus */ +#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL + +/*! + * @name Software Reset + * @{ + */ + +/*! + * @brief Resets the LPUART using software. + * + * This function resets all internal logic and registers except the Global Register. + * Remains set until cleared by software. + * + * @param base LPUART peripheral base address. + */ +static inline void LPUART_SoftwareReset(LPUART_Type *base) +{ + base->GLOBAL |= LPUART_GLOBAL_RST_MASK; + base->GLOBAL &= ~LPUART_GLOBAL_RST_MASK; +} +/* @} */ +#endif /*FSL_FEATURE_LPUART_HAS_GLOBAL*/ + /*! * @name Initialization and deinitialization * @{ */ /*! -* @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock. -* -* This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function -* to configure the configuration structure and get the default configuration. -* The example below shows how to use this API to configure the LPUART. -* @code -* lpuart_config_t lpuartConfig; -* lpuartConfig.baudRate_Bps = 115200U; -* lpuartConfig.parityMode = kLPUART_ParityDisabled; -* lpuartConfig.stopBitCount = kLPUART_OneStopBit; -* lpuartConfig.txFifoWatermark = 0; -* lpuartConfig.rxFifoWatermark = 1; -* LPUART_Init(LPUART1, &lpuartConfig, 20000000U); -* @endcode -* -* @param base LPUART peripheral base address. -* @param config Pointer to a user-defined configuration structure. -* @param srcClock_Hz LPUART clock source frequency in HZ. -*/ -void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz); + * @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock. + * + * This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function + * to configure the configuration structure and get the default configuration. + * The example below shows how to use this API to configure the LPUART. + * @code + * lpuart_config_t lpuartConfig; + * lpuartConfig.baudRate_Bps = 115200U; + * lpuartConfig.parityMode = kLPUART_ParityDisabled; + * lpuartConfig.dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig.isMsb = false; + * lpuartConfig.stopBitCount = kLPUART_OneStopBit; + * lpuartConfig.txFifoWatermark = 0; + * lpuartConfig.rxFifoWatermark = 1; + * LPUART_Init(LPUART1, &lpuartConfig, 20000000U); + * @endcode + * + * @param base LPUART peripheral base address. + * @param config Pointer to a user-defined configuration structure. + * @param srcClock_Hz LPUART clock source frequency in HZ. + * @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source. + * @retval kStatus_Success LPUART initialize succeed + */ +status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz); /*! * @brief Deinitializes a LPUART instance. @@ -260,6 +301,8 @@ void LPUART_Deinit(LPUART_Type *base); * values are: * lpuartConfig->baudRate_Bps = 115200U; * lpuartConfig->parityMode = kLPUART_ParityDisabled; + * lpuartConfig->dataBitsCount = kLPUART_EightDataBits; + * lpuartConfig->isMsb = false; * lpuartConfig->stopBitCount = kLPUART_OneStopBit; * lpuartConfig->txFifoWatermark = 0; * lpuartConfig->rxFifoWatermark = 1; @@ -282,8 +325,10 @@ void LPUART_GetDefaultConfig(lpuart_config_t *config); * @param base LPUART peripheral base address. * @param baudRate_Bps LPUART baudrate to be set. * @param srcClock_Hz LPUART clock source frequency in HZ. + * @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source. + * @retval kStatus_Success Set baudrate succeeded. */ -void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); +status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); /* @} */ @@ -512,24 +557,40 @@ static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data) } /*! - * @brief Reads the RX register. + * @brief Reads the receiver register. * - * This function reads data from the TX register directly. The upper layer must - * ensure that the RX register is full or that the TX FIFO has data before calling this function. + * This function reads data from the receiver register directly. The upper layer must + * ensure that the receiver register is full or that the RX FIFO has data before calling this function. * * @param base LPUART peripheral base address. * @return Data read from data register. */ static inline uint8_t LPUART_ReadByte(LPUART_Type *base) { +#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + uint32_t ctrl = base->CTRL; + bool isSevenDataBits = + ((ctrl & LPUART_CTRL_M7_MASK) || + ((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK))); + + if (isSevenDataBits) + { + return (base->DATA & 0x7F); + } + else + { + return base->DATA; + } +#else return base->DATA; +#endif } /*! - * @brief Writes to transmitter register using a blocking method. + * @brief Writes to the transmitter register using a blocking method. * * This function polls the transmitter register, waits for the register to be empty or for TX FIFO to have - * room and then writes data to the transmitter buffer. + * room, and writes data to the transmitter buffer. * * @note This function does not check whether all data has been sent out to the bus. * Before disabling the transmitter, check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is @@ -542,10 +603,10 @@ static inline uint8_t LPUART_ReadByte(LPUART_Type *base) void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length); /*! -* @brief Reads the RX data register using a blocking method. +* @brief Reads the receiver data register using a blocking method. * - * This function polls the RX register, waits for the RX register full or RX FIFO - * has data then reads data from the TX register. + * This function polls the receiver register, waits for the receiver register full or receiver FIFO + * has data, and reads data from the TX register. * * @param base LPUART peripheral base address. * @param data Start address of the buffer to store the received data. @@ -601,7 +662,7 @@ void LPUART_TransferCreateHandle(LPUART_Type *base, * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. - * @param xfer LPUART transfer structure, refer to #lpuart_transfer_t. + * @param xfer LPUART transfer structure, see #lpuart_transfer_t. * @retval kStatus_Success Successfully start the data transmission. * @retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register. * @retval kStatus_InvalidArgument Invalid argument. @@ -631,7 +692,7 @@ void LPUART_TransferStartRingBuffer(LPUART_Type *base, size_t ringBufferSize); /*! - * @brief Abort the background transfer and uninstall the ring buffer. + * @brief Aborts the background transfer and uninstalls the ring buffer. * * This function aborts the background transfer and uninstalls the ring buffer. * @@ -644,7 +705,7 @@ void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle); * @brief Aborts the interrupt-driven data transmit. * * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out - * how many bytes are still not sent out. + * how many bytes are not sent out. * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. @@ -652,10 +713,10 @@ void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle); void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to LPUART TX register. + * @brief Gets the number of bytes that have been written to the LPUART transmitter register. * * This function gets the number of bytes that have been written to LPUART TX - * register by interrupt method. + * register by an interrupt method. * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. @@ -686,7 +747,7 @@ status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. - * @param xfer LPUART transfer structure, refer to #uart_transfer_t. + * @param xfer LPUART transfer structure, see #uart_transfer_t. * @param receivedBytes Bytes received from the ring buffer directly. * @retval kStatus_Success Successfully queue the transfer into the transmit queue. * @retval kStatus_LPUART_RxBusy Previous receive request is not finished. @@ -709,7 +770,7 @@ status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base, void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of bytes that have been received. * * This function gets the number of bytes that have been received. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c index b4242f62625..24da4831477 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -98,6 +98,8 @@ extern uint32_t LPUART_GetInstance(LPUART_Type *base); static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param; /* Avoid the warning for unused variables. */ @@ -118,6 +120,8 @@ static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool tra static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param; /* Avoid warning for unused parameters. */ @@ -138,11 +142,11 @@ static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool } void LPUART_TransferCreateHandleEDMA(LPUART_Type *base, - lpuart_edma_handle_t *handle, - lpuart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle) + lpuart_edma_handle_t *handle, + lpuart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle) { assert(handle); @@ -189,19 +193,18 @@ void LPUART_TransferCreateHandleEDMA(LPUART_Type *base, EDMA_SetCallback(handle->rxEdmaHandle, LPUART_ReceiveEDMACallback, &s_edmaPrivateHandle[instance]); } } + status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer) { + assert(handle); assert(handle->txEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous TX not finished. */ if (kLPUART_TxBusy == handle->txState) { @@ -216,6 +219,9 @@ status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the LPUART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -231,17 +237,15 @@ status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer) { + assert(handle); assert(handle->rxEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous RX not finished. */ if (kLPUART_RxBusy == handle->rxState) { @@ -256,6 +260,9 @@ status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpu EDMA_PrepareTransfer(&xferConfig, (void *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the LPUART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -271,6 +278,7 @@ status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpu void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle) { + assert(handle); assert(handle->txEdmaHandle); /* Disable LPUART TX EDMA. */ @@ -284,6 +292,7 @@ void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handl void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle) { + assert(handle); assert(handle->rxEdmaHandle); /* Disable LPUART RX EDMA. */ @@ -297,38 +306,36 @@ void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *ha status_t LPUART_TransferGetReceiveCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->rxEdmaHandle); + assert(count); if (kLPUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->txEdmaHandle); + assert(count); if (kLPUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h index 35e922e1251..79565c688d6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_lpuart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,8 +39,6 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -67,6 +65,8 @@ struct _lpuart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -94,11 +94,11 @@ extern "C" { * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. */ void LPUART_TransferCreateHandleEDMA(LPUART_Type *base, - lpuart_edma_handle_t *handle, - lpuart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + lpuart_edma_handle_t *handle, + lpuart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -123,7 +123,7 @@ status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart * * @param base LPUART peripheral base address. * @param handle Pointer to lpuart_edma_handle_t structure. - * @param xfer LPUART eDMA transfer structure, refer to #lpuart_transfer_t. + * @param xfer LPUART eDMA transfer structure, see #lpuart_transfer_t. * @retval kStatus_Success if succeed, others fail. * @retval kStatus_LPUART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. @@ -151,9 +151,9 @@ void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handl void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to LPUART TX register. + * @brief Gets the number of bytes written to the LPUART TX register. * - * This function gets the number of bytes that have been written to LPUART TX + * This function gets the number of bytes written to the LPUART TX * register by DMA. * * @param base LPUART peripheral base address. @@ -166,9 +166,9 @@ void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *ha status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base LPUART peripheral base address. * @param handle LPUART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c deleted file mode 100644 index 926eff9641f..00000000000 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fsl_mpu.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/* Defines the register numbers of the region descriptor configure. */ -#define MPU_REGIONDESCRIPTOR_WROD_REGNUM (4U) - -/******************************************************************************* - * Variables - ******************************************************************************/ - -const clock_ip_name_t g_mpuClock[FSL_FEATURE_SOC_MPU_COUNT] = MPU_CLOCKS; - -/******************************************************************************* - * Codes - ******************************************************************************/ - -void MPU_Init(MPU_Type *base, const mpu_config_t *config) -{ - assert(config); - uint8_t count; - - /* Un-gate MPU clock */ - CLOCK_EnableClock(g_mpuClock[0]); - - /* Initializes the regions. */ - for (count = 1; count < FSL_FEATURE_MPU_DESCRIPTOR_COUNT; count++) - { - base->WORD[count][3] = 0; /* VLD/VID+PID. */ - base->WORD[count][0] = 0; /* Start address. */ - base->WORD[count][1] = 0; /* End address. */ - base->WORD[count][2] = 0; /* Access rights. */ - base->RGDAAC[count] = 0; /* Alternate access rights. */ - } - - /* MPU configure. */ - while (config) - { - MPU_SetRegionConfig(base, &(config->regionConfig)); - config = config->next; - } - /* Enable MPU. */ - MPU_Enable(base, true); -} - -void MPU_Deinit(MPU_Type *base) -{ - /* Disable MPU. */ - MPU_Enable(base, false); - - /* Gate the clock. */ - CLOCK_DisableClock(g_mpuClock[0]); -} - -void MPU_GetHardwareInfo(MPU_Type *base, mpu_hardware_info_t *hardwareInform) -{ - assert(hardwareInform); - - uint32_t cesReg = base->CESR; - - hardwareInform->hardwareRevisionLevel = (cesReg & MPU_CESR_HRL_MASK) >> MPU_CESR_HRL_SHIFT; - hardwareInform->slavePortsNumbers = (cesReg & MPU_CESR_NSP_MASK) >> MPU_CESR_NSP_SHIFT; - hardwareInform->regionsNumbers = (mpu_region_total_num_t)((cesReg & MPU_CESR_NRGD_MASK) >> MPU_CESR_NRGD_SHIFT); -} - -void MPU_SetRegionConfig(MPU_Type *base, const mpu_region_config_t *regionConfig) -{ - assert(regionConfig); - - uint32_t wordReg = 0; - uint8_t count; - uint8_t number = regionConfig->regionNum; - - /* The start and end address of the region descriptor. */ - base->WORD[number][0] = regionConfig->startAddress; - base->WORD[number][1] = regionConfig->endAddress; - - /* The region descriptor access rights control. */ - for (count = 0; count < MPU_REGIONDESCRIPTOR_WROD_REGNUM; count++) - { - wordReg |= MPU_WORD_LOW_MASTER(count, (((uint32_t)regionConfig->accessRights1[count].superAccessRights << 3U) | - (uint8_t)regionConfig->accessRights1[count].userAccessRights)) | - MPU_WORD_HIGH_MASTER(count, ((uint32_t)regionConfig->accessRights2[count].readEnable << 1U | - (uint8_t)regionConfig->accessRights2[count].writeEnable)); - -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - wordReg |= MPU_WORD_MASTER_PE(count, regionConfig->accessRights1[count].processIdentifierEnable); -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ - } - - /* Set region descriptor access rights. */ - base->WORD[number][2] = wordReg; - - wordReg = MPU_WORD_VLD(1); -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - wordReg |= MPU_WORD_PID(regionConfig->processIdentifier) | MPU_WORD_PIDMASK(regionConfig->processIdMask); -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ - - base->WORD[number][3] = wordReg; -} - -void MPU_SetRegionAddr(MPU_Type *base, mpu_region_num_t regionNum, uint32_t startAddr, uint32_t endAddr) -{ - base->WORD[regionNum][0] = startAddr; - base->WORD[regionNum][1] = endAddr; -} - -void MPU_SetRegionLowMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_low_masters_access_rights_t *accessRights) -{ - assert(accessRights); -#if FSL_FEATURE_MPU_HAS_MASTER4 - assert(masterNum < kMPU_Master4); -#endif - uint32_t mask = MPU_WORD_LOW_MASTER_MASK(masterNum); - uint32_t right = base->RGDAAC[regionNum]; - -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - mask |= MPU_LOW_MASTER_PE_MASK(masterNum); -#endif - - /* Build rights control value. */ - right &= ~mask; - right |= MPU_WORD_LOW_MASTER(masterNum, - ((uint32_t)(accessRights->superAccessRights << 3U) | accessRights->userAccessRights)); -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - right |= MPU_WORD_MASTER_PE(masterNum, accessRights->processIdentifierEnable); -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ - - /* Set low master region access rights. */ - base->RGDAAC[regionNum] = right; -} - -void MPU_SetRegionHighMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_high_masters_access_rights_t *accessRights) -{ - assert(accessRights); -#if FSL_FEATURE_MPU_HAS_MASTER3 - assert(masterNum > kMPU_Master3); -#endif - uint32_t mask = MPU_WORD_HIGH_MASTER_MASK(masterNum); - uint32_t right = base->RGDAAC[regionNum]; - - /* Build rights control value. */ - right &= ~mask; - right |= MPU_WORD_HIGH_MASTER((masterNum - (uint8_t)kMPU_RegionNum04), - (((uint32_t)accessRights->readEnable << 1U) | accessRights->writeEnable)); - /* Set low master region access rights. */ - base->RGDAAC[regionNum] = right; -} - -bool MPU_GetSlavePortErrorStatus(MPU_Type *base, mpu_slave_t slaveNum) -{ - uint8_t sperr; - - sperr = ((base->CESR & MPU_CESR_SPERR_MASK) >> MPU_CESR_SPERR_SHIFT) & (0x1U << slaveNum); - - return (sperr != 0) ? true : false; -} - -void MPU_GetDetailErrorAccessInfo(MPU_Type *base, mpu_slave_t slaveNum, mpu_access_err_info_t *errInform) -{ - assert(errInform); - - uint16_t value; - - /* Error address. */ - errInform->address = base->SP[slaveNum].EAR; - - /* Error detail information. */ - value = (base->SP[slaveNum].EDR & MPU_EDR_EACD_MASK) >> MPU_EDR_EACD_SHIFT; - if (!value) - { - errInform->accessControl = kMPU_NoRegionHit; - } - else if (!(value & (uint16_t)(value - 1))) - { - errInform->accessControl = kMPU_NoneOverlappRegion; - } - else - { - errInform->accessControl = kMPU_OverlappRegion; - } - - value = base->SP[slaveNum].EDR; - errInform->master = (mpu_master_t)((value & MPU_EDR_EMN_MASK) >> MPU_EDR_EMN_SHIFT); - errInform->attributes = (mpu_err_attributes_t)((value & MPU_EDR_EATTR_MASK) >> MPU_EDR_EATTR_SHIFT); - errInform->accessType = (mpu_err_access_type_t)((value & MPU_EDR_ERW_MASK) >> MPU_EDR_ERW_SHIFT); -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - errInform->processorIdentification = (uint8_t)((value & MPU_EDR_EPID_MASK) >> MPU_EDR_EPID_SHIFT); -#endif - - /*!< Clears error slave port bit. */ - value = (base->CESR & ~MPU_CESR_SPERR_MASK) | (0x1U << slaveNum); - base->CESR = value; -} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h deleted file mode 100644 index acdcfd1be38..00000000000 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_mpu.h +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _FSL_MPU_H_ -#define _FSL_MPU_H_ - -#include "fsl_common.h" - -/*! - * @addtogroup mpu - * @{ - */ - -/*! @file */ - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/*! @name Driver version */ -/*@{*/ -/*! @brief MPU driver version 2.0.0. */ -#define FSL_MPU_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) -/*@}*/ - -/*! @brief MPU low master bit shift. */ -#define MPU_WORD_LOW_MASTER_SHIFT(n) (n * 6) - -/*! @brief MPU low master bit mask. */ -#define MPU_WORD_LOW_MASTER_MASK(n) (0x1Fu << MPU_WORD_LOW_MASTER_SHIFT(n)) - -/*! @brief MPU low master bit width. */ -#define MPU_WORD_LOW_MASTER_WIDTH 5 - -/*! @brief MPU low master priority setting. */ -#define MPU_WORD_LOW_MASTER(n, x) \ - (((uint32_t)(((uint32_t)(x)) << MPU_WORD_LOW_MASTER_SHIFT(n))) & MPU_WORD_LOW_MASTER_MASK(n)) - -/*! @brief MPU low master process enable bit shift. */ -#define MPU_LOW_MASTER_PE_SHIFT(n) (n * 6 + 5) - -/*! @brief MPU low master process enable bit mask. */ -#define MPU_LOW_MASTER_PE_MASK(n) (0x1u << MPU_LOW_MASTER_PE_SHIFT(n)) - -/*! @brief MPU low master process enable width. */ -#define MPU_WORD_MASTER_PE_WIDTH 1 - -/*! @brief MPU low master process enable setting. */ -#define MPU_WORD_MASTER_PE(n, x) \ - (((uint32_t)(((uint32_t)(x)) << MPU_LOW_MASTER_PE_SHIFT(n))) & MPU_LOW_MASTER_PE_MASK(n)) - -/*! @brief MPU high master bit shift. */ -#define MPU_WORD_HIGH_MASTER_SHIFT(n) (n * 2 + 24) - -/*! @brief MPU high master bit mask. */ -#define MPU_WORD_HIGH_MASTER_MASK(n) (0x03u << MPU_WORD_HIGH_MASTER_SHIFT(n)) - -/*! @brief MPU high master bit width. */ -#define MPU_WORD_HIGH_MASTER_WIDTH 2 - -/*! @brief MPU high master priority setting. */ -#define MPU_WORD_HIGH_MASTER(n, x) \ - (((uint32_t)(((uint32_t)(x)) << MPU_WORD_HIGH_MASTER_SHIFT(n))) & MPU_WORD_HIGH_MASTER_MASK(n)) - -/*! @brief MPU region number. */ -typedef enum _mpu_region_num -{ -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 0U - kMPU_RegionNum00 = 0U, /*!< MPU region number 0. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 1U - kMPU_RegionNum01 = 1U, /*!< MPU region number 1. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 2U - kMPU_RegionNum02 = 2U, /*!< MPU region number 2. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 3U - kMPU_RegionNum03 = 3U, /*!< MPU region number 3. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 4U - kMPU_RegionNum04 = 4U, /*!< MPU region number 4. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 5U - kMPU_RegionNum05 = 5U, /*!< MPU region number 5. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 6U - kMPU_RegionNum06 = 6U, /*!< MPU region number 6. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 7U - kMPU_RegionNum07 = 7U, /*!< MPU region number 7. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 8U - kMPU_RegionNum08 = 8U, /*!< MPU region number 8. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 9U - kMPU_RegionNum09 = 9U, /*!< MPU region number 9. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 10U - kMPU_RegionNum10 = 10U, /*!< MPU region number 10. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 11U - kMPU_RegionNum11 = 11U, /*!< MPU region number 11. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 12U - kMPU_RegionNum12 = 12U, /*!< MPU region number 12. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 13U - kMPU_RegionNum13 = 13U, /*!< MPU region number 13. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 14U - kMPU_RegionNum14 = 14U, /*!< MPU region number 14. */ -#endif -#if FSL_FEATURE_MPU_DESCRIPTOR_COUNT > 15U - kMPU_RegionNum15 = 15U, /*!< MPU region number 15. */ -#endif -} mpu_region_num_t; - -/*! @brief MPU master number. */ -typedef enum _mpu_master -{ -#if FSL_FEATURE_MPU_HAS_MASTER0 - kMPU_Master0 = 0U, /*!< MPU master core. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER1 - kMPU_Master1 = 1U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER2 - kMPU_Master2 = 2U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER3 - kMPU_Master3 = 3U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER4 - kMPU_Master4 = 4U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER5 - kMPU_Master5 = 5U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER6 - kMPU_Master6 = 6U, /*!< MPU master defined in SoC. */ -#endif -#if FSL_FEATURE_MPU_HAS_MASTER7 - kMPU_Master7 = 7U /*!< MPU master defined in SoC. */ -#endif -} mpu_master_t; - -/*! @brief Describes the number of MPU regions. */ -typedef enum _mpu_region_total_num -{ - kMPU_8Regions = 0x0U, /*!< MPU supports 8 regions. */ - kMPU_12Regions = 0x1U, /*!< MPU supports 12 regions. */ - kMPU_16Regions = 0x2U /*!< MPU supports 16 regions. */ -} mpu_region_total_num_t; - -/*! @brief MPU slave port number. */ -typedef enum _mpu_slave -{ - kMPU_Slave0 = 4U, /*!< MPU slave port 0. */ - kMPU_Slave1 = 3U, /*!< MPU slave port 1. */ - kMPU_Slave2 = 2U, /*!< MPU slave port 2. */ - kMPU_Slave3 = 1U, /*!< MPU slave port 3. */ - kMPU_Slave4 = 0U /*!< MPU slave port 4. */ -} mpu_slave_t; - -/*! @brief MPU error access control detail. */ -typedef enum _mpu_err_access_control -{ - kMPU_NoRegionHit = 0U, /*!< No region hit error. */ - kMPU_NoneOverlappRegion = 1U, /*!< Access single region error. */ - kMPU_OverlappRegion = 2U /*!< Access overlapping region error. */ -} mpu_err_access_control_t; - -/*! @brief MPU error access type. */ -typedef enum _mpu_err_access_type -{ - kMPU_ErrTypeRead = 0U, /*!< MPU error access type --- read. */ - kMPU_ErrTypeWrite = 1U /*!< MPU error access type --- write. */ -} mpu_err_access_type_t; - -/*! @brief MPU access error attributes.*/ -typedef enum _mpu_err_attributes -{ - kMPU_InstructionAccessInUserMode = 0U, /*!< Access instruction error in user mode. */ - kMPU_DataAccessInUserMode = 1U, /*!< Access data error in user mode. */ - kMPU_InstructionAccessInSupervisorMode = 2U, /*!< Access instruction error in supervisor mode. */ - kMPU_DataAccessInSupervisorMode = 3U /*!< Access data error in supervisor mode. */ -} mpu_err_attributes_t; - -/*! @brief MPU access rights in supervisor mode for master port 0 ~ port 3. */ -typedef enum _mpu_supervisor_access_rights -{ - kMPU_SupervisorReadWriteExecute = 0U, /*!< Read write and execute operations are allowed in supervisor mode. */ - kMPU_SupervisorReadExecute = 1U, /*!< Read and execute operations are allowed in supervisor mode. */ - kMPU_SupervisorReadWrite = 2U, /*!< Read write operations are allowed in supervisor mode. */ - kMPU_SupervisorEqualToUsermode = 3U /*!< Access permission equal to user mode. */ -} mpu_supervisor_access_rights_t; - -/*! @brief MPU access rights in user mode for master port 0 ~ port 3. */ -typedef enum _mpu_user_access_rights -{ - kMPU_UserNoAccessRights = 0U, /*!< No access allowed in user mode. */ - kMPU_UserExecute = 1U, /*!< Execute operation is allowed in user mode. */ - kMPU_UserWrite = 2U, /*!< Write operation is allowed in user mode. */ - kMPU_UserWriteExecute = 3U, /*!< Write and execute operations are allowed in user mode. */ - kMPU_UserRead = 4U, /*!< Read is allowed in user mode. */ - kMPU_UserReadExecute = 5U, /*!< Read and execute operations are allowed in user mode. */ - kMPU_UserReadWrite = 6U, /*!< Read and write operations are allowed in user mode. */ - kMPU_UserReadWriteExecute = 7U /*!< Read write and execute operations are allowed in user mode. */ -} mpu_user_access_rights_t; - -/*! @brief MPU hardware basic information. */ -typedef struct _mpu_hardware_info -{ - uint8_t hardwareRevisionLevel; /*!< Specifies the MPU's hardware and definition reversion level. */ - uint8_t slavePortsNumbers; /*!< Specifies the number of slave ports connected to MPU. */ - mpu_region_total_num_t regionsNumbers; /*!< Indicates the number of region descriptors implemented. */ -} mpu_hardware_info_t; - -/*! @brief MPU detail error access information. */ -typedef struct _mpu_access_err_info -{ - mpu_master_t master; /*!< Access error master. */ - mpu_err_attributes_t attributes; /*!< Access error attributes. */ - mpu_err_access_type_t accessType; /*!< Access error type. */ - mpu_err_access_control_t accessControl; /*!< Access error control. */ - uint32_t address; /*!< Access error address. */ -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - uint8_t processorIdentification; /*!< Access error processor identification. */ -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ -} mpu_access_err_info_t; - -/*! @brief MPU access rights for low master master port 0 ~ port 3. */ -typedef struct _mpu_low_masters_access_rights -{ - mpu_supervisor_access_rights_t superAccessRights; /*!< Master access rights in supervisor mode. */ - mpu_user_access_rights_t userAccessRights; /*!< Master access rights in user mode. */ -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - bool processIdentifierEnable; /*!< Enables or disables process identifier. */ -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ -} mpu_low_masters_access_rights_t; - -/*! @brief MPU access rights mode for high master port 4 ~ port 7. */ -typedef struct _mpu_high_masters_access_rights -{ - bool writeEnable; /*!< Enables or disables write permission. */ - bool readEnable; /*!< Enables or disables read permission. */ -} mpu_high_masters_access_rights_t; - -/*! - * @brief MPU region configuration structure. - * - * This structure is used to configure the regionNum region. - * The accessRights1[0] ~ accessRights1[3] are used to configure the four low master - * numbers: master 0 ~ master 3. The accessRights2[0] ~ accessRights2[3] are - * used to configure the four high master numbers: master 4 ~ master 7. - * The master port assignment is the chip configuration. Normally, the core is the - * master 0, debugger is the master 1. - * Note: MPU assigns a priority scheme where the debugger is treated as the highest - * priority master followed by the core and then all the remaining masters. - * MPU protection does not allow writes from the core to affect the "regionNum 0" start - * and end address nor the permissions associated with the debugger. It can only write - * the permission fields associated with the other masters. This protection guarantee - * the debugger always has access to the entire address space and those rights can't - * be changed by the core or any other bus master. Prepare - * the region configuration when regionNum is kMPU_RegionNum00. - */ -typedef struct _mpu_region_config -{ - mpu_region_num_t regionNum; /*!< MPU region number. */ - uint32_t startAddress; /*!< Memory region start address. Note: bit0 ~ bit4 always be marked as 0 by MPU. The actual - start address is 0-modulo-32 byte address. */ - uint32_t endAddress; /*!< Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by MPU. The actual end - address is 31-modulo-32 byte address. */ - mpu_low_masters_access_rights_t accessRights1[4]; /*!< Low masters access permission. */ - mpu_high_masters_access_rights_t accessRights2[4]; /*!< High masters access permission. */ -#if FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER - uint8_t processIdentifier; /*!< Process identifier used when "processIdentifierEnable" set with true. */ - uint8_t - processIdMask; /*!< Process identifier mask. The setting bit will ignore the same bit in process identifier. */ -#endif /* FSL_FEATURE_MPU_HAS_PROCESS_IDENTIFIER */ -} mpu_region_config_t; - -/*! - * @brief The configuration structure for the MPU initialization. - * - * This structure is used when calling the MPU_Init function. - */ -typedef struct _mpu_config -{ - mpu_region_config_t regionConfig; /*!< region access permission. */ - struct _mpu_config *next; /*!< pointer to the next structure. */ -} mpu_config_t; - -/******************************************************************************* - * API - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* _cplusplus */ - -/*! - * @name Initialization and deinitialization - * @{ - */ - -/*! - * @brief Initializes the MPU with the user configuration structure. - * - * This function configures the MPU module with the user-defined configuration. - * - * @param base MPU peripheral base address. - * @param config The pointer to the configuration structure. - */ -void MPU_Init(MPU_Type *base, const mpu_config_t *config); - -/*! - * @brief Deinitializes the MPU regions. - * - * @param base MPU peripheral base address. - */ -void MPU_Deinit(MPU_Type *base); - -/* @}*/ - -/*! - * @name Basic Control Operations - * @{ - */ - -/*! - * @brief Enables/disables the MPU globally. - * - * Call this API to enable or disable the MPU module. - * - * @param base MPU peripheral base address. - * @param enable True enable MPU, false disable MPU. - */ -static inline void MPU_Enable(MPU_Type *base, bool enable) -{ - if (enable) - { - /* Enable the MPU globally. */ - base->CESR |= MPU_CESR_VLD_MASK; - } - else - { /* Disable the MPU globally. */ - base->CESR &= ~MPU_CESR_VLD_MASK; - } -} - -/*! - * @brief Enables/disables the MPU for a special region. - * - * When MPU is enabled, call this API to disable an unused region - * of an enabled MPU. Call this API to minimize the power dissipation. - * - * @param base MPU peripheral base address. - * @param number MPU region number. - * @param enable True enable the special region MPU, false disable the special region MPU. - */ -static inline void MPU_RegionEnable(MPU_Type *base, mpu_region_num_t number, bool enable) -{ - if (enable) - { - /* Enable the #number region MPU. */ - base->WORD[number][3] |= MPU_WORD_VLD_MASK; - } - else - { /* Disable the #number region MPU. */ - base->WORD[number][3] &= ~MPU_WORD_VLD_MASK; - } -} - -/*! - * @brief Gets the MPU basic hardware information. - * - * @param base MPU peripheral base address. - * @param hardwareInform The pointer to the MPU hardware information structure. See "mpu_hardware_info_t". - */ -void MPU_GetHardwareInfo(MPU_Type *base, mpu_hardware_info_t *hardwareInform); - -/*! - * @brief Sets the MPU region. - * - * Note: Due to the MPU protection, the kMPU_RegionNum00 does not allow writes from the - * core to affect the start and end address nor the permissions associated with - * the debugger. It can only write the permission fields associated - * with the other masters. - * - * @param base MPU peripheral base address. - * @param regionConfig The pointer to the MPU user configuration structure. See "mpu_region_config_t". - */ -void MPU_SetRegionConfig(MPU_Type *base, const mpu_region_config_t *regionConfig); - -/*! - * @brief Sets the region start and end address. - * - * Memory region start address. Note: bit0 ~ bit4 is always marked as 0 by MPU. - * The actual start address by MPU is 0-modulo-32 byte address. - * Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by MPU. - * The actual end address used by MPU is 31-modulo-32 byte address. - * Note: Due to the MPU protection, the startAddr and endAddr can't be - * changed by the core when regionNum is "kMPU_RegionNum00". - * - * @param base MPU peripheral base address. - * @param regionNum MPU region number. - * @param startAddr Region start address. - * @param endAddr Region end address. - */ -void MPU_SetRegionAddr(MPU_Type *base, mpu_region_num_t regionNum, uint32_t startAddr, uint32_t endAddr); - -/*! - * @brief Sets the MPU region access rights for low master port 0 ~ port 3. - * This can be used to change the region access rights for any master port for any region. - * - * @param base MPU peripheral base address. - * @param regionNum MPU region number. - * @param masterNum MPU master number. Should range from kMPU_Master0 ~ kMPU_Master3. - * @param accessRights The pointer to the MPU access rights configuration. See "mpu_low_masters_access_rights_t". - */ -void MPU_SetRegionLowMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_low_masters_access_rights_t *accessRights); - -/*! - * @brief Sets the MPU region access rights for high master port 4 ~ port 7. - * This can be used to change the region access rights for any master port for any region. - * - * @param base MPU peripheral base address. - * @param regionNum MPU region number. - * @param masterNum MPU master number. Should range from kMPU_Master4 ~ kMPU_Master7. - * @param accessRights The pointer to the MPU access rights configuration. See "mpu_high_masters_access_rights_t". - */ -void MPU_SetRegionHighMasterAccessRights(MPU_Type *base, - mpu_region_num_t regionNum, - mpu_master_t masterNum, - const mpu_high_masters_access_rights_t *accessRights); - -/*! - * @brief Gets the numbers of slave ports where errors occur. - * - * @param base MPU peripheral base address. - * @param slaveNum MPU slave port number. - * @return The slave ports error status. - * true - error happens in this slave port. - * false - error didn't happen in this slave port. - */ -bool MPU_GetSlavePortErrorStatus(MPU_Type *base, mpu_slave_t slaveNum); - -/*! - * @brief Gets the MPU detailed error access information. - * - * @param base MPU peripheral base address. - * @param slaveNum MPU slave port number. - * @param errInform The pointer to the MPU access error information. See "mpu_access_err_info_t". - */ -void MPU_GetDetailErrorAccessInfo(MPU_Type *base, mpu_slave_t slaveNum, mpu_access_err_info_t *errInform); - -/* @} */ - -#if defined(__cplusplus) -} -#endif - -/*! @}*/ - -#endif /* _FSL_MPU_H_ */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c index b5c9b88ec6c..1fc4a9a486a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t PDB_GetInstance(PDB_Type *base); ******************************************************************************/ /*! @brief Pointers to PDB bases for each instance. */ static PDB_Type *const s_pdbBases[] = PDB_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to PDB clocks for each instance. */ -const clock_ip_name_t s_pdbClocks[] = PDB_CLOCKS; +static const clock_ip_name_t s_pdbClocks[] = PDB_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t PDB_GetInstance(PDB_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_PDB_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_pdbBases); instance++) { if (s_pdbBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t PDB_GetInstance(PDB_Type *base) } } - assert(instance < FSL_FEATURE_SOC_PDB_COUNT); + assert(instance < ARRAY_SIZE(s_pdbBases)); return instance; } @@ -75,8 +77,10 @@ void PDB_Init(PDB_Type *base, const pdb_config_t *config) uint32_t tmp32; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_pdbClocks[PDB_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ /* PDBx_SC. */ @@ -98,8 +102,10 @@ void PDB_Deinit(PDB_Type *base) { PDB_Enable(base, false); /* Disable the PDB module. */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_pdbClocks[PDB_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void PDB_GetDefaultConfig(pdb_config_t *config) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h index 1f05b61b26b..3dec9463462 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pdb.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -67,32 +66,32 @@ enum _pdb_status_flags enum _pdb_adc_pretrigger_flags { /* PDB PreTrigger channel match flags. */ - kPDB_ADCPreTriggerChannel0Flag = PDB_S_CF(1U << 0), /*!< Pre-Trigger 0 flag. */ - kPDB_ADCPreTriggerChannel1Flag = PDB_S_CF(1U << 1), /*!< Pre-Trigger 1 flag. */ -#if (PDB_DLY_COUNT > 2) - kPDB_ADCPreTriggerChannel2Flag = PDB_S_CF(1U << 2), /*!< Pre-Trigger 2 flag. */ - kPDB_ADCPreTriggerChannel3Flag = PDB_S_CF(1U << 3), /*!< Pre-Trigger 3 flag. */ -#endif /* PDB_DLY_COUNT > 2 */ -#if (PDB_DLY_COUNT > 4) - kPDB_ADCPreTriggerChannel4Flag = PDB_S_CF(1U << 4), /*!< Pre-Trigger 4 flag. */ - kPDB_ADCPreTriggerChannel5Flag = PDB_S_CF(1U << 5), /*!< Pre-Trigger 5 flag. */ - kPDB_ADCPreTriggerChannel6Flag = PDB_S_CF(1U << 6), /*!< Pre-Trigger 6 flag. */ - kPDB_ADCPreTriggerChannel7Flag = PDB_S_CF(1U << 7), /*!< Pre-Trigger 7 flag. */ -#endif /* PDB_DLY_COUNT > 4 */ + kPDB_ADCPreTriggerChannel0Flag = PDB_S_CF(1U << 0), /*!< Pre-trigger 0 flag. */ + kPDB_ADCPreTriggerChannel1Flag = PDB_S_CF(1U << 1), /*!< Pre-trigger 1 flag. */ +#if (PDB_DLY_COUNT2 > 2) + kPDB_ADCPreTriggerChannel2Flag = PDB_S_CF(1U << 2), /*!< Pre-trigger 2 flag. */ + kPDB_ADCPreTriggerChannel3Flag = PDB_S_CF(1U << 3), /*!< Pre-trigger 3 flag. */ +#endif /* PDB_DLY_COUNT2 > 2 */ +#if (PDB_DLY_COUNT2 > 4) + kPDB_ADCPreTriggerChannel4Flag = PDB_S_CF(1U << 4), /*!< Pre-trigger 4 flag. */ + kPDB_ADCPreTriggerChannel5Flag = PDB_S_CF(1U << 5), /*!< Pre-trigger 5 flag. */ + kPDB_ADCPreTriggerChannel6Flag = PDB_S_CF(1U << 6), /*!< Pre-trigger 6 flag. */ + kPDB_ADCPreTriggerChannel7Flag = PDB_S_CF(1U << 7), /*!< Pre-trigger 7 flag. */ +#endif /* PDB_DLY_COUNT2 > 4 */ /* PDB PreTrigger channel error flags. */ - kPDB_ADCPreTriggerChannel0ErrorFlag = PDB_S_ERR(1U << 0), /*!< Pre-Trigger 0 Error. */ - kPDB_ADCPreTriggerChannel1ErrorFlag = PDB_S_ERR(1U << 1), /*!< Pre-Trigger 1 Error. */ -#if (PDB_DLY_COUNT > 2) - kPDB_ADCPreTriggerChannel2ErrorFlag = PDB_S_ERR(1U << 2), /*!< Pre-Trigger 2 Error. */ - kPDB_ADCPreTriggerChannel3ErrorFlag = PDB_S_ERR(1U << 3), /*!< Pre-Trigger 3 Error. */ -#endif /* PDB_DLY_COUNT > 2 */ -#if (PDB_DLY_COUNT > 4) - kPDB_ADCPreTriggerChannel4ErrorFlag = PDB_S_ERR(1U << 4), /*!< Pre-Trigger 4 Error. */ - kPDB_ADCPreTriggerChannel5ErrorFlag = PDB_S_ERR(1U << 5), /*!< Pre-Trigger 5 Error. */ - kPDB_ADCPreTriggerChannel6ErrorFlag = PDB_S_ERR(1U << 6), /*!< Pre-Trigger 6 Error. */ - kPDB_ADCPreTriggerChannel7ErrorFlag = PDB_S_ERR(1U << 7), /*!< Pre-Trigger 7 Error. */ -#endif /* PDB_DLY_COUNT > 4 */ + kPDB_ADCPreTriggerChannel0ErrorFlag = PDB_S_ERR(1U << 0), /*!< Pre-trigger 0 Error. */ + kPDB_ADCPreTriggerChannel1ErrorFlag = PDB_S_ERR(1U << 1), /*!< Pre-trigger 1 Error. */ +#if (PDB_DLY_COUNT2 > 2) + kPDB_ADCPreTriggerChannel2ErrorFlag = PDB_S_ERR(1U << 2), /*!< Pre-trigger 2 Error. */ + kPDB_ADCPreTriggerChannel3ErrorFlag = PDB_S_ERR(1U << 3), /*!< Pre-trigger 3 Error. */ +#endif /* PDB_DLY_COUNT2 > 2 */ +#if (PDB_DLY_COUNT2 > 4) + kPDB_ADCPreTriggerChannel4ErrorFlag = PDB_S_ERR(1U << 4), /*!< Pre-trigger 4 Error. */ + kPDB_ADCPreTriggerChannel5ErrorFlag = PDB_S_ERR(1U << 5), /*!< Pre-trigger 5 Error. */ + kPDB_ADCPreTriggerChannel6ErrorFlag = PDB_S_ERR(1U << 6), /*!< Pre-trigger 6 Error. */ + kPDB_ADCPreTriggerChannel7ErrorFlag = PDB_S_ERR(1U << 7), /*!< Pre-trigger 7 Error. */ +#endif /* PDB_DLY_COUNT2 > 4 */ }; /*! @@ -108,7 +107,7 @@ enum _pdb_interrupt_enable * @brief PDB load value mode. * * Selects the mode to load the internal values after doing the load operation (write 1 to PDBx_SC[LDOK]). - * These values are for: + * These values are for the following operations. * - PDB counter (PDBx_MOD, PDBx_IDLY) * - ADC trigger (PDBx_CHnDLYm) * - DAC trigger (PDBx_DACINTx) @@ -158,7 +157,7 @@ typedef enum _pdb_divider_multiplication_factor * @brief Trigger input source * * Selects the trigger input source for the PDB. The trigger input source can be internal or external (EXTRG pin), or - * the software trigger. Refer to chip configuration details for the actual PDB input trigger connections. + * the software trigger. See chip configuration details for the actual PDB input trigger connections. */ typedef enum _pdb_trigger_input_source { @@ -177,7 +176,7 @@ typedef enum _pdb_trigger_input_source kPDB_TriggerInput12 = 12U, /*!< Trigger-In 12. */ kPDB_TriggerInput13 = 13U, /*!< Trigger-In 13. */ kPDB_TriggerInput14 = 14U, /*!< Trigger-In 14. */ - kPDB_TriggerSoftware = 15U, /*!< Trigger-In 15. */ + kPDB_TriggerSoftware = 15U, /*!< Trigger-In 15, software trigger. */ } pdb_trigger_input_source_t; /*! @@ -193,15 +192,15 @@ typedef struct _pdb_config } pdb_config_t; /*! - * @brief PDB ADC Pre-Trigger configuration. + * @brief PDB ADC Pre-trigger configuration. */ typedef struct _pdb_adc_pretrigger_config { - uint32_t enablePreTriggerMask; /*!< PDB Channel Pre-Trigger Enable. */ - uint32_t enableOutputMask; /*!< PDB Channel Pre-Trigger Output Select. + uint32_t enablePreTriggerMask; /*!< PDB Channel Pre-trigger Enable. */ + uint32_t enableOutputMask; /*!< PDB Channel Pre-trigger Output Select. PDB channel's corresponding pre-trigger asserts when the counter reaches the channel delay register. */ - uint32_t enableBackToBackOperationMask; /*!< PDB Channel Pre-Trigger Back-to-Back Operation Enable. + uint32_t enableBackToBackOperationMask; /*!< PDB Channel pre-trigger Back-to-Back Operation Enable. Back-to-back operation enables the ADC conversions complete to trigger the next PDB channel pre-trigger and trigger output, so that the ADC conversions can be triggered on next set of configuration and results @@ -230,29 +229,29 @@ extern "C" { */ /*! - * @brief Initializes the PDB module. + * @brief Initializes the PDB module. * - * This function is to make the initialization for PDB module. The operations includes are: + * This function initializes the PDB module. The operations included are as follows. * - Enable the clock for PDB instance. * - Configure the PDB module. * - Enable the PDB module. * * @param base PDB peripheral base address. - * @param config Pointer to configuration structure. See "pdb_config_t". + * @param config Pointer to the configuration structure. See "pdb_config_t". */ void PDB_Init(PDB_Type *base, const pdb_config_t *config); /*! - * @brief De-initializes the PDB module. + * @brief De-initializes the PDB module. * * @param base PDB peripheral base address. */ void PDB_Deinit(PDB_Type *base); /*! - * @brief Initializes the PDB user configure structure. + * @brief Initializes the PDB user configuration structure. * - * This function initializes the user configure structure to default value. the default value are: + * This function initializes the user configuration structure to a default value. The default values are as follows. * @code * config->loadValueMode = kPDB_LoadValueImmediately; * config->prescalerDivider = kPDB_PrescalerDivider1; @@ -302,7 +301,7 @@ static inline void PDB_DoSoftwareTrigger(PDB_Type *base) /*! * @brief Loads the counter values. * - * This function is to load the counter values from their internal buffer. + * This function loads the counter values from the internal buffer. * See "pdb_load_value_mode_t" about PDB's load mode. * * @param base PDB peripheral base address. @@ -382,7 +381,7 @@ static inline void PDB_ClearStatusFlags(PDB_Type *base, uint32_t mask) } /*! - * @brief Specifies the period of the counter. + * @brief Specifies the counter period. * * @param base PDB peripheral base address. * @param value Setting value for the modulus. 16-bit is available. @@ -405,7 +404,7 @@ static inline uint32_t PDB_GetCounterValue(PDB_Type *base) } /*! - * @brief Sets the value for PDB counter delay event. + * @brief Sets the value for the PDB counter delay event. * * @param base PDB peripheral base address. * @param value Setting value for PDB counter delay event. 16-bit is available. @@ -417,16 +416,16 @@ static inline void PDB_SetCounterDelayValue(PDB_Type *base, uint32_t value) /* @} */ /*! - * @name ADC Pre-Trigger + * @name ADC Pre-trigger * @{ */ /*! - * @brief Configures the ADC PreTrigger in PDB module. + * @brief Configures the ADC pre-trigger in the PDB module. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. - * @param config Pointer to configuration structure. See "pdb_adc_pretrigger_config_t". + * @param config Pointer to the configuration structure. See "pdb_adc_pretrigger_config_t". */ static inline void PDB_SetADCPreTriggerConfig(PDB_Type *base, uint32_t channel, pdb_adc_pretrigger_config_t *config) { @@ -434,30 +433,31 @@ static inline void PDB_SetADCPreTriggerConfig(PDB_Type *base, uint32_t channel, assert(NULL != config); base->CH[channel].C1 = PDB_C1_BB(config->enableBackToBackOperationMask) | PDB_C1_TOS(config->enableOutputMask) | - PDB_C1_EN(config->enableOutputMask); + PDB_C1_EN(config->enablePreTriggerMask); } /*! - * @brief Sets the value for ADC Pre-Trigger delay event. + * @brief Sets the value for the ADC pre-trigger delay event. * - * This function is to set the value for ADC Pre-Trigger delay event. IT Specifies the delay value for the channel's - * corresponding pre-trigger. The pre-trigger asserts when the PDB counter is equal to the setting value here. + * This function sets the value for ADC pre-trigger delay event. It specifies the delay value for the channel's + * corresponding pre-trigger. The pre-trigger asserts when the PDB counter is equal to the set value. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. * @param preChannel Channel group index for ADC instance. - * @param value Setting value for ADC Pre-Trigger delay event. 16-bit is available. + * @param value Setting value for ADC pre-trigger delay event. 16-bit is available. */ static inline void PDB_SetADCPreTriggerDelayValue(PDB_Type *base, uint32_t channel, uint32_t preChannel, uint32_t value) { assert(channel < PDB_C1_COUNT); - assert(preChannel < PDB_DLY_COUNT); + assert(preChannel < PDB_DLY_COUNT2); + /* xx_COUNT2 is actually the count for pre-triggers in header file. xx_COUNT is used for the count of channels. */ base->CH[channel].DLY[preChannel] = PDB_DLY_DLY(value); } /*! - * @brief Gets the ADC Pre-Trigger's status flags. + * @brief Gets the ADC pre-trigger's status flags. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. @@ -472,7 +472,7 @@ static inline uint32_t PDB_GetADCPreTriggerStatusFlags(PDB_Type *base, uint32_t } /*! - * @brief Clears the ADC Pre-Trigger's status flags. + * @brief Clears the ADC pre-trigger status flags. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. @@ -494,19 +494,19 @@ static inline void PDB_ClearADCPreTriggerStatusFlags(PDB_Type *base, uint32_t ch */ /*! - * @brief Configures the DAC trigger in PDB module. + * @brief Configures the DAC trigger in the PDB module. * * @param base PDB peripheral base address. * @param channel Channel index for DAC instance. - * @param config Pointer to configuration structure. See "pdb_dac_trigger_config_t". + * @param config Pointer to the configuration structure. See "pdb_dac_trigger_config_t". */ void PDB_SetDACTriggerConfig(PDB_Type *base, uint32_t channel, pdb_dac_trigger_config_t *config); /*! * @brief Sets the value for the DAC interval event. * - * This fucntion is to set the value for DAC interval event. DAC interval trigger would trigger the DAC module to update - * buffer when the DAC interval counter is equal to the setting value here. + * This fucntion sets the value for DAC interval event. DAC interval trigger triggers the DAC module to update + * the buffer when the DAC interval counter is equal to the set value. * * @param base PDB peripheral base address. * @param channel Channel index for DAC instance. @@ -532,7 +532,7 @@ static inline void PDB_SetDACTriggerIntervalValue(PDB_Type *base, uint32_t chann * * @param base PDB peripheral base address. * @param channelMask Channel mask value for multiple pulse out trigger channel. - * @param enable Enable the feature or not. + * @param enable Whether the feature is enabled or not. */ static inline void PDB_EnablePulseOutTrigger(PDB_Type *base, uint32_t channelMask, bool enable) { @@ -547,11 +547,11 @@ static inline void PDB_EnablePulseOutTrigger(PDB_Type *base, uint32_t channelMas } /*! - * @brief Sets event values for pulse out trigger. + * @brief Sets event values for the pulse out trigger. * - * This function is used to set event values for pulse output trigger. - * These pulse output trigger delay values specify the delay for the PDB Pulse-Out. Pulse-Out goes high when the PDB - * counter is equal to the pulse output high value (value1). Pulse-Out goes low when the PDB counter is equal to the + * This function is used to set event values for the pulse output trigger. + * These pulse output trigger delay values specify the delay for the PDB Pulse-out. Pulse-out goes high when the PDB + * counter is equal to the pulse output high value (value1). Pulse-out goes low when the PDB counter is equal to the * pulse output low value (value2). * * @param base PDB peripheral base address. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c index 1f2fdfe8b45..e5c3c4e013d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,8 +48,10 @@ static uint32_t PIT_GetInstance(PIT_Type *base); /*! @brief Pointers to PIT bases for each instance. */ static PIT_Type *const s_pitBases[] = PIT_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to PIT clocks for each instance. */ static const clock_ip_name_t s_pitClocks[] = PIT_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -59,7 +61,7 @@ static uint32_t PIT_GetInstance(PIT_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_PIT_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_pitBases); instance++) { if (s_pitBases[instance] == base) { @@ -67,7 +69,7 @@ static uint32_t PIT_GetInstance(PIT_Type *base) } } - assert(instance < FSL_FEATURE_SOC_PIT_COUNT); + assert(instance < ARRAY_SIZE(s_pitBases)); return instance; } @@ -76,8 +78,10 @@ void PIT_Init(PIT_Type *base, const pit_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate the PIT clock*/ CLOCK_EnableClock(s_pitClocks[PIT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Enable PIT timers */ base->MCR &= ~PIT_MCR_MDIS_MASK; @@ -98,8 +102,10 @@ void PIT_Deinit(PIT_Type *base) /* Disable PIT timers */ base->MCR |= PIT_MCR_MDIS_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the PIT clock*/ CLOCK_DisableClock(s_pitClocks[PIT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } #if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && FSL_FEATURE_PIT_HAS_LIFETIME_TIMER diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h index 61606e7e8bd..99c30e1e4bc 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pit.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup pit_driver + * @addtogroup pit * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -73,13 +72,13 @@ typedef enum _pit_status_flags } pit_status_flags_t; /*! - * @brief PIT config structure + * @brief PIT configuration structure * * This structure holds the configuration settings for the PIT peripheral. To initialize this * structure to reasonable defaults, call the PIT_GetDefaultConfig() function and pass a * pointer to your config structure instance. * - * The config struct can be made const so it resides in flash + * The configuration structure can be made constant so it resides in flash. */ typedef struct _pit_config { @@ -100,30 +99,30 @@ extern "C" { */ /*! - * @brief Ungates the PIT clock, enables the PIT module and configures the peripheral for basic operation. + * @brief Ungates the PIT clock, enables the PIT module, and configures the peripheral for basic operations. * * @note This API should be called at the beginning of the application using the PIT driver. * * @param base PIT peripheral base address - * @param config Pointer to user's PIT config structure + * @param config Pointer to the user's PIT config structure */ void PIT_Init(PIT_Type *base, const pit_config_t *config); /*! - * @brief Gate the PIT clock and disable the PIT module + * @brief Gates the PIT clock and disables the PIT module. * * @param base PIT peripheral base address */ void PIT_Deinit(PIT_Type *base); /*! - * @brief Fill in the PIT config struct with the default settings + * @brief Fills in the PIT configuration structure with the default settings. * - * The default values are: + * The default values are as follows. * @code * config->enableRunInDebug = false; * @endcode - * @param config Pointer to user's PIT config structure. + * @param config Pointer to the onfiguration structure. */ static inline void PIT_GetDefaultConfig(pit_config_t *config) { @@ -140,9 +139,9 @@ static inline void PIT_GetDefaultConfig(pit_config_t *config) * * When a timer has a chain mode enabled, it only counts after the previous * timer has expired. If the timer n-1 has counted down to 0, counter n - * decrements the value by one. Each timer is 32-bits, this allows the developers + * decrements the value by one. Each timer is 32-bits, which allows the developers * to chain timers together and form a longer timer (64-bits and larger). The first timer - * (timer 0) cannot be chained to any other timer. + * (timer 0) can't be chained to any other timer. * * @param base PIT peripheral base address * @param channel Timer channel number which is chained with the previous timer @@ -219,7 +218,7 @@ static inline uint32_t PIT_GetEnabledInterrupts(PIT_Type *base, pit_chnl_t chann */ /*! - * @brief Gets the PIT status flags + * @brief Gets the PIT status flags. * * @param base PIT peripheral base address * @param channel Timer channel number @@ -256,11 +255,11 @@ static inline void PIT_ClearStatusFlags(PIT_Type *base, pit_chnl_t channel, uint * @brief Sets the timer period in units of count. * * Timers begin counting from the value set by this function until it reaches 0, - * then it will generate an interrupt and load this regiter value again. - * Writing a new value to this register will not restart the timer; instead the value - * will be loaded after the timer expires. + * then it generates an interrupt and load this register value again. + * Writing a new value to this register does not restart the timer. Instead, the value + * is loaded after the timer expires. * - * @note User can call the utility macros provided in fsl_common.h to convert to ticks + * @note Users can call the utility macros provided in fsl_common.h to convert to ticks. * * @param base PIT peripheral base address * @param channel Timer channel number @@ -277,7 +276,7 @@ static inline void PIT_SetTimerPeriod(PIT_Type *base, pit_chnl_t channel, uint32 * This function returns the real-time timer counting value, in a range from 0 to a * timer period. * - * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec + * @note Users can call the utility macros provided in fsl_common.h to convert ticks to usec or msec. * * @param base PIT peripheral base address * @param channel Timer channel number diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c index 82d7b7ace13..bcdd5cb8231 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h index c60c19c01e9..99fc149fc22 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_pmc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,7 +35,6 @@ /*! @addtogroup pmc */ /*! @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -49,36 +48,36 @@ #if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV) /*! - * @brief Low-Voltage Detect Voltage Select + * @brief Low-voltage Detect Voltage Select */ typedef enum _pmc_low_volt_detect_volt_select { - kPMC_LowVoltDetectLowTrip = 0U, /*!< Low trip point selected (VLVD = VLVDL )*/ - kPMC_LowVoltDetectHighTrip = 1U /*!< High trip point selected (VLVD = VLVDH )*/ + kPMC_LowVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VLVD = VLVDL )*/ + kPMC_LowVoltDetectHighTrip = 1U /*!< High-trip point selected (VLVD = VLVDH )*/ } pmc_low_volt_detect_volt_select_t; #endif #if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV) /*! - * @brief Low-Voltage Warning Voltage Select + * @brief Low-voltage Warning Voltage Select */ typedef enum _pmc_low_volt_warning_volt_select { - kPMC_LowVoltWarningLowTrip = 0U, /*!< Low trip point selected (VLVW = VLVW1)*/ + kPMC_LowVoltWarningLowTrip = 0U, /*!< Low-trip point selected (VLVW = VLVW1)*/ kPMC_LowVoltWarningMid1Trip = 1U, /*!< Mid 1 trip point selected (VLVW = VLVW2)*/ kPMC_LowVoltWarningMid2Trip = 2U, /*!< Mid 2 trip point selected (VLVW = VLVW3)*/ - kPMC_LowVoltWarningHighTrip = 3U /*!< High trip point selected (VLVW = VLVW4)*/ + kPMC_LowVoltWarningHighTrip = 3U /*!< High-trip point selected (VLVW = VLVW4)*/ } pmc_low_volt_warning_volt_select_t; #endif #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief High-Voltage Detect Voltage Select + * @brief High-voltage Detect Voltage Select */ typedef enum _pmc_high_volt_detect_volt_select { - kPMC_HighVoltDetectLowTrip = 0U, /*!< Low trip point selected (VHVD = VHVDL )*/ - kPMC_HighVoltDetectHighTrip = 1U /*!< High trip point selected (VHVD = VHVDH )*/ + kPMC_HighVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VHVD = VHVDL )*/ + kPMC_HighVoltDetectHighTrip = 1U /*!< High-trip point selected (VHVD = VHVDH )*/ } pmc_high_volt_detect_volt_select_t; #endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */ @@ -88,8 +87,8 @@ typedef enum _pmc_high_volt_detect_volt_select */ typedef enum _pmc_bandgap_buffer_drive_select { - kPMC_BandgapBufferDriveLow = 0U, /*!< Low drive. */ - kPMC_BandgapBufferDriveHigh = 1U /*!< High drive. */ + kPMC_BandgapBufferDriveLow = 0U, /*!< Low-drive. */ + kPMC_BandgapBufferDriveHigh = 1U /*!< High-drive. */ } pmc_bandgap_buffer_drive_select_t; #endif /* FSL_FEATURE_PMC_HAS_BGBDS */ @@ -126,37 +125,37 @@ typedef struct _pmc_param #endif /* FSL_FEATURE_PMC_HAS_PARAM */ /*! - * @brief Low-Voltage Detect Configuration Structure + * @brief Low-voltage Detect Configuration Structure */ typedef struct _pmc_low_volt_detect_config { - bool enableInt; /*!< Enable interrupt when low voltage detect*/ - bool enableReset; /*!< Enable system reset when low voltage detect*/ + bool enableInt; /*!< Enable interrupt when Low-voltage detect*/ + bool enableReset; /*!< Enable system reset when Low-voltage detect*/ #if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV) - pmc_low_volt_detect_volt_select_t voltSelect; /*!< Low voltage detect trip point voltage selection*/ + pmc_low_volt_detect_volt_select_t voltSelect; /*!< Low-voltage detect trip point voltage selection*/ #endif } pmc_low_volt_detect_config_t; /*! - * @brief Low-Voltage Warning Configuration Structure + * @brief Low-voltage Warning Configuration Structure */ typedef struct _pmc_low_volt_warning_config { - bool enableInt; /*!< Enable interrupt when low voltage warning*/ + bool enableInt; /*!< Enable interrupt when low-voltage warning*/ #if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV) - pmc_low_volt_warning_volt_select_t voltSelect; /*!< Low voltage warning trip point voltage selection*/ + pmc_low_volt_warning_volt_select_t voltSelect; /*!< Low-voltage warning trip point voltage selection*/ #endif } pmc_low_volt_warning_config_t; #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief High-Voltage Detect Configuration Structure + * @brief High-voltage Detect Configuration Structure */ typedef struct _pmc_high_volt_detect_config { - bool enableInt; /*!< Enable interrupt when high voltage detect*/ - bool enableReset; /*!< Enable system reset when high voltage detect*/ - pmc_high_volt_detect_volt_select_t voltSelect; /*!< High voltage detect trip point voltage selection*/ + bool enableInt; /*!< Enable interrupt when high-voltage detect*/ + bool enableReset; /*!< Enable system reset when high-voltage detect*/ + pmc_high_volt_detect_volt_select_t voltSelect; /*!< High-voltage detect trip point voltage selection*/ } pmc_high_volt_detect_config_t; #endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */ @@ -172,7 +171,7 @@ typedef struct _pmc_bandgap_buffer_config bool enable; /*!< Enable bandgap buffer. */ #endif #if (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) - bool enableInLowPowerMode; /*!< Enable bandgap buffer in low power mode. */ + bool enableInLowPowerMode; /*!< Enable bandgap buffer in low-power mode. */ #endif /* FSL_FEATURE_PMC_HAS_BGEN */ #if (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS) pmc_bandgap_buffer_drive_select_t drive; /*!< Bandgap buffer drive select. */ @@ -196,7 +195,7 @@ extern "C" { * @brief Gets the PMC version ID. * * This function gets the PMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and a feature specification number. * * @param base PMC peripheral base address. * @param versionId Pointer to version ID structure. @@ -211,7 +210,7 @@ static inline void PMC_GetVersionId(PMC_Type *base, pmc_version_id_t *versionId) /*! * @brief Gets the PMC parameter. * - * This function gets the PMC parameter, including VLPO enable and HVD enable. + * This function gets the PMC parameter including the VLPO enable and the HVD enable. * * @param base PMC peripheral base address. * @param param Pointer to PMC param structure. @@ -220,26 +219,25 @@ void PMC_GetParam(PMC_Type *base, pmc_param_t *param); #endif /*! - * @brief Configure the low voltage detect setting. + * @brief Configures the low-voltage detect setting. * - * This function configures the low voltage detect setting, including the trip - * point voltage setting, enable interrupt or not, enable system reset or not. + * This function configures the low-voltage detect setting, including the trip + * point voltage setting, enables or disables the interrupt, enables or disables the system reset. * * @param base PMC peripheral base address. - * @param config Low-Voltage detect configuration structure. + * @param config Low-voltage detect configuration structure. */ void PMC_ConfigureLowVoltDetect(PMC_Type *base, const pmc_low_volt_detect_config_t *config); /*! - * @brief Get Low-Voltage Detect Flag status + * @brief Gets the Low-voltage Detect Flag status. * - * This function reads the current LVDF status. If it returns 1, a low - * voltage event is detected. + * This function reads the current LVDF status. If it returns 1, a low-voltage event is detected. * * @param base PMC peripheral base address. - * @return Current low voltage detect flag - * - true: Low-Voltage detected - * - false: Low-Voltage not detected + * @return Current low-voltage detect flag + * - true: Low-voltage detected + * - false: Low-voltage not detected */ static inline bool PMC_GetLowVoltDetectFlag(PMC_Type *base) { @@ -247,9 +245,9 @@ static inline bool PMC_GetLowVoltDetectFlag(PMC_Type *base) } /*! - * @brief Acknowledge to clear the Low-Voltage Detect flag + * @brief Acknowledges clearing the Low-voltage Detect flag. * - * This function acknowledges the low voltage detection errors (write 1 to + * This function acknowledges the low-voltage detection errors (write 1 to * clear LVDF). * * @param base PMC peripheral base address. @@ -260,18 +258,18 @@ static inline void PMC_ClearLowVoltDetectFlag(PMC_Type *base) } /*! - * @brief Configure the low voltage warning setting. + * @brief Configures the low-voltage warning setting. * - * This function configures the low voltage warning setting, including the trip - * point voltage setting and enable interrupt or not. + * This function configures the low-voltage warning setting, including the trip + * point voltage setting and enabling or disabling the interrupt. * * @param base PMC peripheral base address. - * @param config Low-Voltage warning configuration structure. + * @param config Low-voltage warning configuration structure. */ void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_config_t *config); /*! - * @brief Get Low-Voltage Warning Flag status + * @brief Gets the Low-voltage Warning Flag status. * * This function polls the current LVWF status. When 1 is returned, it * indicates a low-voltage warning event. LVWF is set when V Supply transitions @@ -279,8 +277,8 @@ void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_conf * * @param base PMC peripheral base address. * @return Current LVWF status - * - true: Low-Voltage Warning Flag is set. - * - false: the Low-Voltage Warning does not happen. + * - true: Low-voltage Warning Flag is set. + * - false: the Low-voltage Warning does not happen. */ static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base) { @@ -288,7 +286,7 @@ static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base) } /*! - * @brief Acknowledge to Low-Voltage Warning flag + * @brief Acknowledges the Low-voltage Warning flag. * * This function acknowledges the low voltage warning errors (write 1 to * clear LVWF). @@ -302,26 +300,26 @@ static inline void PMC_ClearLowVoltWarningFlag(PMC_Type *base) #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief Configure the high voltage detect setting. + * @brief Configures the high-voltage detect setting. * - * This function configures the high voltage detect setting, including the trip - * point voltage setting, enable interrupt or not, enable system reset or not. + * This function configures the high-voltage detect setting, including the trip + * point voltage setting, enabling or disabling the interrupt, enabling or disabling the system reset. * * @param base PMC peripheral base address. - * @param config High-Voltage detect configuration structure. + * @param config High-voltage detect configuration structure. */ void PMC_ConfigureHighVoltDetect(PMC_Type *base, const pmc_high_volt_detect_config_t *config); /*! - * @brief Get High-Voltage Detect Flag status + * @brief Gets the High-voltage Detect Flag status. * * This function reads the current HVDF status. If it returns 1, a low * voltage event is detected. * * @param base PMC peripheral base address. - * @return Current high voltage detect flag - * - true: High-Voltage detected - * - false: High-Voltage not detected + * @return Current high-voltage detect flag + * - true: High-voltage detected + * - false: High-voltage not detected */ static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base) { @@ -329,9 +327,9 @@ static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base) } /*! - * @brief Acknowledge to clear the High-Voltage Detect flag + * @brief Acknowledges clearing the High-voltage Detect flag. * - * This function acknowledges the high voltage detection errors (write 1 to + * This function acknowledges the high-voltage detection errors (write 1 to * clear HVDF). * * @param base PMC peripheral base address. @@ -346,10 +344,10 @@ static inline void PMC_ClearHighVoltDetectFlag(PMC_Type *base) (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) || \ (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS)) /*! - * @brief Configure the PMC bandgap + * @brief Configures the PMC bandgap. * * This function configures the PMC bandgap, including the drive select and - * behavior in low power mode. + * behavior in low-power mode. * * @param base PMC peripheral base address. * @param config Pointer to the configuration structure @@ -378,7 +376,7 @@ static inline bool PMC_GetPeriphIOIsolationFlag(PMC_Type *base) } /*! - * @brief Acknowledge to Peripherals and I/O pads isolation flag. + * @brief Acknowledges the isolation flag to Peripherals and I/O pads. * * This function clears the ACK Isolation flag. Writing one to this setting * when it is set releases the I/O pads and certain peripherals to their normal @@ -394,9 +392,9 @@ static inline void PMC_ClearPeriphIOIsolationFlag(PMC_Type *base) #if (defined(FSL_FEATURE_PMC_HAS_REGONS) && FSL_FEATURE_PMC_HAS_REGONS) /*! - * @brief Gets the Regulator regulation status. + * @brief Gets the regulator regulation status. * - * This function returns the regulator to a run regulation status. It provides + * This function returns the regulator to run a regulation status. It provides * the current status of the internal voltage regulator. * * @param base PMC peripheral base address. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h index 790518ccd3c..eb8e77e6ddd 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_port.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -33,59 +33,65 @@ #include "fsl_common.h" /*! - * @addtogroup port_driver + * @addtogroup port * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! Version 2.0.1. */ -#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! Version 2.0.2. */ +#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ +#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE /*! @brief Internal resistor pull feature selection */ enum _port_pull { - kPORT_PullDisable = 0U, /*!< internal pull-up/down resistor is disabled. */ - kPORT_PullDown = 2U, /*!< internal pull-down resistor is enabled. */ - kPORT_PullUp = 3U, /*!< internal pull-up resistor is enabled. */ + kPORT_PullDisable = 0U, /*!< Internal pull-up/down resistor is disabled. */ + kPORT_PullDown = 2U, /*!< Internal pull-down resistor is enabled. */ + kPORT_PullUp = 3U, /*!< Internal pull-up resistor is enabled. */ }; +#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */ +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE /*! @brief Slew rate selection */ enum _port_slew_rate { - kPORT_FastSlewRate = 0U, /*!< fast slew rate is configured. */ - kPORT_SlowSlewRate = 1U, /*!< slow slew rate is configured. */ + kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */ + kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */ }; +#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */ #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN -/*! @brief Internal resistor pull feature enable/disable */ +/*! @brief Open Drain feature enable/disable */ enum _port_open_drain_enable { - kPORT_OpenDrainDisable = 0U, /*!< internal pull-down resistor is disabled. */ - kPORT_OpenDrainEnable = 1U, /*!< internal pull-up resistor is enabled. */ + kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */ + kPORT_OpenDrainEnable = 1U, /*!< Open drain output is enabled. */ }; #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER /*! @brief Passive filter feature enable/disable */ enum _port_passive_filter_enable { - kPORT_PassiveFilterDisable = 0U, /*!< fast slew rate is configured. */ - kPORT_PassiveFilterEnable = 1U, /*!< slow slew rate is configured. */ + kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */ + kPORT_PassiveFilterEnable = 1U, /*!< Passive input filter is enabled. */ }; +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH /*! @brief Configures the drive strength. */ enum _port_drive_strength { - kPORT_LowDriveStrength = 0U, /*!< low drive strength is configured. */ - kPORT_HighDriveStrength = 1U, /*!< high drive strength is configured. */ + kPORT_LowDriveStrength = 0U, /*!< Low-drive strength is configured. */ + kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */ }; +#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */ #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK /*! @brief Unlock/lock the pin control register field[15:0] */ @@ -96,18 +102,28 @@ enum _port_lock_register }; #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */ +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @brief Pin mux selection */ typedef enum _port_mux { - kPORT_PinDisabledOrAnalog = 0U, /*!< corresponding pin is disabled, but is used as an analog pin. */ - kPORT_MuxAsGpio = 1U, /*!< corresponding pin is configured as GPIO. */ - kPORT_MuxAlt2 = 2U, /*!< chip-specific */ - kPORT_MuxAlt3 = 3U, /*!< chip-specific */ - kPORT_MuxAlt4 = 4U, /*!< chip-specific */ - kPORT_MuxAlt5 = 5U, /*!< chip-specific */ - kPORT_MuxAlt6 = 6U, /*!< chip-specific */ - kPORT_MuxAlt7 = 7U, /*!< chip-specific */ + kPORT_PinDisabledOrAnalog = 0U, /*!< Corresponding pin is disabled, but is used as an analog pin. */ + kPORT_MuxAsGpio = 1U, /*!< Corresponding pin is configured as GPIO. */ + kPORT_MuxAlt2 = 2U, /*!< Chip-specific */ + kPORT_MuxAlt3 = 3U, /*!< Chip-specific */ + kPORT_MuxAlt4 = 4U, /*!< Chip-specific */ + kPORT_MuxAlt5 = 5U, /*!< Chip-specific */ + kPORT_MuxAlt6 = 6U, /*!< Chip-specific */ + kPORT_MuxAlt7 = 7U, /*!< Chip-specific */ + kPORT_MuxAlt8 = 8U, /*!< Chip-specific */ + kPORT_MuxAlt9 = 9U, /*!< Chip-specific */ + kPORT_MuxAlt10 = 10U, /*!< Chip-specific */ + kPORT_MuxAlt11 = 11U, /*!< Chip-specific */ + kPORT_MuxAlt12 = 12U, /*!< Chip-specific */ + kPORT_MuxAlt13 = 13U, /*!< Chip-specific */ + kPORT_MuxAlt14 = 14U, /*!< Chip-specific */ + kPORT_MuxAlt15 = 15U, /*!< Chip-specific */ } port_mux_t; +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ /*! @brief Configures the interrupt generation condition. */ typedef enum _port_interrupt @@ -129,8 +145,8 @@ typedef enum _port_interrupt kPORT_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */ kPORT_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */ #if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER - kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high trigger output. */ - kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low trigger output. */ + kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */ + kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low-trigger output. */ #endif } port_interrupt_t; @@ -150,44 +166,76 @@ typedef struct _port_digital_filter_config } port_digital_filter_config_t; #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */ -/*! @brief PORT pin config structure */ +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH +/*! @brief PORT pin configuration structure */ typedef struct _port_pin_config { - uint16_t pullSelect : 2; /*!< no-pull/pull-down/pull-up select */ - uint16_t slewRate : 1; /*!< fast/slow slew rate Configure */ +#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE + uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */ +#else + uint16_t : 2; +#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */ + +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE + uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */ +#else + uint16_t : 1; +#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */ + + uint16_t : 1; + +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER + uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */ +#else uint16_t : 1; - uint16_t passiveFilterEnable : 1; /*!< passive filter enable/disable */ +#endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */ + #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN - uint16_t openDrainEnable : 1; /*!< open drain enable/disable */ + uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */ +#else + uint16_t : 1; +#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ + +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH + uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */ #else uint16_t : 1; -#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ - uint16_t driveStrength : 1; /*!< fast/slow drive strength configure */ +#endif + uint16_t : 1; - uint16_t mux : 3; /*!< pin mux Configure */ + +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH + uint16_t mux : 3; /*!< Pin mux Configure */ +#else + uint16_t : 3; +#endif + uint16_t : 4; + #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK - uint16_t lockRegister : 1; /*!< lock/unlock the pcr field[15:0] */ + uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */ #else uint16_t : 1; #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */ } port_pin_config_t; +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ /******************************************************************************* - * API - ******************************************************************************/ +* API +******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @name Configuration */ /*@{*/ /*! * @brief Sets the port PCR register. * - * This is an example to define an input pin or output pin PCR configuration: + * This is an example to define an input pin or output pin PCR configuration. * @code * // Define a digital input pin PCR configuration * port_pin_config_t config = { @@ -203,7 +251,7 @@ extern "C" { * * @param base PORT peripheral base pointer. * @param pin PORT pin number. - * @param config PORT PCR register configure structure. + * @param config PORT PCR register configuration structure. */ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config) { @@ -215,7 +263,7 @@ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_p /*! * @brief Sets the port PCR register for multiple pins. * - * This is an example to define input pins or output pins PCR configuration: + * This is an example to define input pins or output pins PCR configuration. * @code * // Define a digital input pin PCR configuration * port_pin_config_t config = { @@ -231,8 +279,8 @@ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_p * @endcode * * @param base PORT peripheral base pointer. - * @param mask PORT pins' numbers macro. - * @param config PORT PCR register configure structure. + * @param mask PORT pin number macro. + * @param config PORT PCR register configuration structure. */ static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config) { @@ -265,15 +313,16 @@ static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, co * - #kPORT_MuxAlt6 : chip-specific. * - #kPORT_MuxAlt7 : chip-specific. * @Note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because - * the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux will - * be reset to zero : kPORT_PinDisabledOrAnalog). - * This function is recommended to use in the case you just need to reset the pin mux + * the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is + * reset to zero : kPORT_PinDisabledOrAnalog). + * This function is recommended to use to reset the pin mux * */ static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux) { base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux); } +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER @@ -281,7 +330,7 @@ static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux) * @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin. * * @param base PORT peripheral base pointer. - * @param mask PORT pins' numbers macro. + * @param mask PORT pin number macro. */ static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable) { @@ -334,8 +383,8 @@ static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digit * - #kPORT_InterruptFallingEdge: Interrupt on falling edge. * - #kPORT_InterruptEitherEdge : Interrupt on either edge. * - #kPORT_InterruptLogicOne : Interrupt when logic one. - * - #kPORT_ActiveHighTriggerOutputEnable : Enable active high trigger output(if the trigger states exit). - * - #kPORT_ActiveLowTriggerOutputEnable : Enable active low trigger output(if the trigger states exit). + * - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit). + * - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit). */ static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config) { @@ -351,9 +400,9 @@ static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, por * If configured for a level sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base PORT peripheral base pointer. + * @param base PORT peripheral base pointer. * @return Current port interrupt status flags, for example, 0x00010001 means the - * pin 0 and 17 have the interrupt. + * pin 0 and 16 have the interrupt. */ static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base) { @@ -361,10 +410,10 @@ static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base) } /*! - * @brief Clears the multiple pins' interrupt status flag. + * @brief Clears the multiple pin interrupt status flag. * * @param base PORT peripheral base pointer. - * @param mask PORT pins' numbers macro. + * @param mask PORT pin number macro. */ static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c index 538f6872a3a..0d738643b53 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -32,6 +32,8 @@ void RCM_ConfigureResetPinFilter(RCM_Type *base, const rcm_reset_pin_filter_config_t *config) { + assert(config); + #if (defined(FSL_FEATURE_RCM_REG_WIDTH) && (FSL_FEATURE_RCM_REG_WIDTH == 32)) uint32_t reg; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h index 81e25559eaf..99b843aaf3a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rcm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,7 +35,6 @@ /*! @addtogroup rcm */ /*! @{*/ -/*! @file */ /******************************************************************************* * Definitions @@ -43,8 +42,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief RCM driver version 2.0.0. */ -#define FSL_RCM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief RCM driver version 2.0.1. */ +#define FSL_RCM_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ /*! @@ -57,7 +56,7 @@ typedef enum _rcm_reset_source #if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP) kRCM_SourceWakeup = RCM_SRS_WAKEUP_MASK, /*!< Low-leakage wakeup reset */ #endif - kRCM_SourceLvd = RCM_SRS_LVD_MASK, /*!< low voltage detect reset */ + kRCM_SourceLvd = RCM_SRS_LVD_MASK, /*!< Low-voltage detect reset */ #if (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC) kRCM_SourceLoc = RCM_SRS_LOC_MASK, /*!< Loss of clock reset */ #endif /* FSL_FEATURE_RCM_HAS_LOC */ @@ -85,7 +84,7 @@ typedef enum _rcm_reset_source #if (defined(FSL_FEATURE_RCM_HAS_WAKEUP) && FSL_FEATURE_RCM_HAS_WAKEUP) kRCM_SourceWakeup = RCM_SRS0_WAKEUP_MASK, /*!< Low-leakage wakeup reset */ #endif - kRCM_SourceLvd = RCM_SRS0_LVD_MASK, /*!< low voltage detect reset */ + kRCM_SourceLvd = RCM_SRS0_LVD_MASK, /*!< Low-voltage detect reset */ #if (defined(FSL_FEATURE_RCM_HAS_LOC) && FSL_FEATURE_RCM_HAS_LOC) kRCM_SourceLoc = RCM_SRS0_LOC_MASK, /*!< Loss of clock reset */ #endif /* FSL_FEATURE_RCM_HAS_LOC */ @@ -99,7 +98,7 @@ typedef enum _rcm_reset_source kRCM_SourceJtag = RCM_SRS1_JTAG_MASK << 8U, /*!< JTAG generated reset */ #endif /* FSL_FEATURE_RCM_HAS_JTAG */ kRCM_SourceLockup = RCM_SRS1_LOCKUP_MASK << 8U, /*!< Core lock up reset */ - kRCM_SourceSw = RCM_SRS1_SW_MASK, /*!< Software reset */ + kRCM_SourceSw = RCM_SRS1_SW_MASK << 8U, /*!< Software reset */ #if (defined(FSL_FEATURE_RCM_HAS_MDM_AP) && FSL_FEATURE_RCM_HAS_MDM_AP) kRCM_SourceMdmap = RCM_SRS1_MDM_AP_MASK << 8U, /*!< MDM-AP system reset */ #endif /* FSL_FEATURE_RCM_HAS_MDM_AP */ @@ -112,7 +111,7 @@ typedef enum _rcm_reset_source } rcm_reset_source_t; /*! - * @brief Reset pin filter select in Run and Wait modes + * @brief Reset pin filter select in Run and Wait modes. */ typedef enum _rcm_run_wait_filter_mode { @@ -136,7 +135,7 @@ typedef enum _rcm_boot_rom_config #if (defined(FSL_FEATURE_RCM_HAS_SRIE) && FSL_FEATURE_RCM_HAS_SRIE) /*! - * @brief Max delay time from interrupt asserts to system reset. + * @brief Maximum delay time from interrupt asserts to system reset. */ typedef enum _rcm_reset_delay { @@ -187,7 +186,7 @@ typedef struct _rcm_version_id #endif /*! - * @brief Reset pin filter configuration + * @brief Reset pin filter configuration. */ typedef struct _rcm_reset_pin_filter_config { @@ -214,7 +213,7 @@ extern "C" { * the minor version number, and the feature specification number. * * @param base RCM peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId) { @@ -229,7 +228,7 @@ static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId) * This function gets the RCM parameter that indicates whether the corresponding reset source is implemented. * Use source masks defined in the rcm_reset_source_t to get the desired source status. * - * Example: + * This is an example. @code uint32_t status; @@ -252,7 +251,7 @@ static inline uint32_t RCM_GetResetSourceImplementedStatus(RCM_Type *base) * This function gets the current reset source status. Use source masks * defined in the rcm_reset_source_t to get the desired source status. * - * Example: + * This is an example. @code uint32_t resetStatus; @@ -283,9 +282,9 @@ static inline uint32_t RCM_GetPreviousResetSources(RCM_Type *base) * @brief Gets the sticky reset source status. * * This function gets the current reset source status that has not been cleared - * by software for some specific source. + * by software for a specific source. * - * Example: + * This is an example. @code uint32_t resetStatus; @@ -316,7 +315,7 @@ static inline uint32_t RCM_GetStickyResetSources(RCM_Type *base) * * This function clears the sticky system reset flags indicated by source masks. * - * Example: + * This is an example. @code // Clears multiple reset sources. RCM_ClearStickyResetSources(kRCM_SourceWdog | kRCM_SourcePin); @@ -403,7 +402,7 @@ void RCM_SetForceBootRomSource(RCM_Type *base, rcm_boot_rom_config_t config); /*! * @brief Sets the system reset interrupt configuration. * - * For graceful shutdown, the RCM supports delaying the assertion of the system + * For a graceful shut down, the RCM supports delaying the assertion of the system * reset for a period of time when the reset interrupt is generated. This function * can be used to enable the interrupt and the delay period. The interrupts * are passed in as bit mask. See rcm_int_t for details. For example, to diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c index 9be27499efd..6f0adc66f59 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -181,10 +181,14 @@ static uint32_t rnga_ReadEntropy(RNG_Type *base); void RNGA_Init(RNG_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock gate. */ CLOCK_EnableClock(kCLOCK_Rnga0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ CLOCK_DisableClock(kCLOCK_Rnga0); /* To solve the release version on twrkm43z75m */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Rnga0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset the registers for RNGA module to reset state. */ RNG_WR_CR(base, 0); @@ -194,8 +198,10 @@ void RNGA_Init(RNG_Type *base) void RNGA_Deinit(RNG_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock for RNGA module.*/ CLOCK_DisableClock(kCLOCK_Rnga0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h index 04950a4540c..92f5bff8bec 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rnga.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -34,11 +34,10 @@ #if defined(FSL_FEATURE_SOC_RNG_COUNT) && FSL_FEATURE_SOC_RNG_COUNT /*! - * @addtogroup rnga_driver + * @addtogroup rnga * @{ */ -/*! @file */ /******************************************************************************* * Definitions diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c index 898a544a467..d68055a2690 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -74,6 +74,8 @@ static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datet ******************************************************************************/ static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime) { + assert(datetime); + /* Table of days in a month for a non leap year. First entry in the table is not used, * valid months start from 1 */ @@ -88,13 +90,13 @@ static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime) } /* Adjust the days in February for a leap year */ - if (!(datetime->year & 3U)) + if ((((datetime->year & 3U) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0)) { daysPerMonth[2] = 29U; } /* Check the validity of the day */ - if (datetime->day > daysPerMonth[datetime->month]) + if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U)) { return false; } @@ -104,6 +106,9 @@ static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime) static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime) { + assert(datetime); + + /* Number of days from begin of the non Leap-year*/ /* Number of days from begin of the non Leap-year*/ uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U}; uint32_t seconds; @@ -131,6 +136,8 @@ static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime) static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime) { + assert(datetime); + uint32_t x; uint32_t secondsRemaining, days; uint16_t daysInYear; @@ -204,7 +211,9 @@ void RTC_Init(RTC_Type *base, const rtc_config_t *config) uint32_t reg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Issue a software reset if timer is invalid */ if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag) @@ -216,7 +225,7 @@ void RTC_Init(RTC_Type *base, const rtc_config_t *config) /* Setup the update mode and supervisor access mode */ reg &= ~(RTC_CR_UM_MASK | RTC_CR_SUP_MASK); reg |= RTC_CR_UM(config->updateMode) | RTC_CR_SUP(config->supervisorAccess); -#if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN +#if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION /* Setup the wakeup pin select */ reg &= ~(RTC_CR_WPS_MASK); reg |= RTC_CR_WPS(config->wakeupSelect); @@ -340,6 +349,8 @@ void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask) void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter) { + assert(counter); + *counter = (((uint64_t)base->MCHR << 32) | ((uint64_t)base->MCLR)); } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h index 063d1d40c34..99effc6dcb9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_rtc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup rtc_driver + * @addtogroup rtc * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -65,15 +64,19 @@ typedef enum _rtc_status_flags kRTC_AlarmFlag = RTC_SR_TAF_MASK /*!< Alarm flag*/ } rtc_status_flags_t; +#if (defined(FSL_FEATURE_RTC_HAS_OSC_SCXP) && FSL_FEATURE_RTC_HAS_OSC_SCXP) + /*! @brief List of RTC Oscillator capacitor load settings */ typedef enum _rtc_osc_cap_load { - kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2pF capacitor load */ - kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4pF capacitor load */ - kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8pF capacitor load */ - kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16pF capacitor load */ + kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16 pF capacitor load */ } rtc_osc_cap_load_t; +#endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */ + /*! @brief Structure is used to hold the date and time */ typedef struct _rtc_datetime { @@ -96,7 +99,7 @@ typedef struct _rtc_datetime */ typedef struct _rtc_config { - bool wakeupSelect; /*!< true: Wakeup pin outputs the 32KHz clock; + bool wakeupSelect; /*!< true: Wakeup pin outputs the 32 KHz clock; false:Wakeup pin used to wakeup the chip */ bool updateMode; /*!< true: Registers can be written even when locked under certain conditions, false: No writes allowed when registers are locked */ @@ -122,17 +125,17 @@ extern "C" { /*! * @brief Ungates the RTC clock and configures the peripheral for basic operation. * - * This function will issue a software reset if the timer invalid flag is set. + * This function issues a software reset if the timer invalid flag is set. * * @note This API should be called at the beginning of the application using the RTC driver. * * @param base RTC peripheral base address - * @param config Pointer to user's RTC config structure. + * @param config Pointer to the user's RTC configuration structure. */ void RTC_Init(RTC_Type *base, const rtc_config_t *config); /*! - * @brief Stop the timer and gate the RTC clock + * @brief Stops the timer and gate the RTC clock. * * @param base RTC peripheral base address */ @@ -141,14 +144,16 @@ static inline void RTC_Deinit(RTC_Type *base) /* Stop the RTC timer */ base->SR &= ~RTC_SR_TCE_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the module clock */ CLOCK_DisableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! - * @brief Fill in the RTC config struct with the default settings + * @brief Fills in the RTC config struct with the default settings. * - * The default values are: + * The default values are as follows. * @code * config->wakeupSelect = false; * config->updateMode = false; @@ -156,7 +161,7 @@ static inline void RTC_Deinit(RTC_Type *base) * config->compensationInterval = 0; * config->compensationTime = 0; * @endcode - * @param config Pointer to user's RTC config structure. + * @param config Pointer to the user's RTC configuration structure. */ void RTC_GetDefaultConfig(rtc_config_t *config); @@ -170,11 +175,11 @@ void RTC_GetDefaultConfig(rtc_config_t *config); /*! * @brief Sets the RTC date and time according to the given time structure. * - * The RTC counter must be stopped prior to calling this function as writes to the RTC - * seconds register will fail if the RTC counter is running. + * The RTC counter must be stopped prior to calling this function because writes to the RTC + * seconds register fail if the RTC counter is running. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the date and time details to set are stored + * @param datetime Pointer to the structure where the date and time details are stored. * * @return kStatus_Success: Success in setting the time and starting the RTC * kStatus_InvalidArgument: Error because the datetime format is incorrect @@ -185,18 +190,18 @@ status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime); * @brief Gets the RTC time and stores it in the given time structure. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the date and time details are stored. + * @param datetime Pointer to the structure where the date and time details are stored. */ void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime); /*! - * @brief Sets the RTC alarm time + * @brief Sets the RTC alarm time. * * The function checks whether the specified alarm time is greater than the present * time. If not, the function does not set the alarm and returns an error. * * @param base RTC peripheral base address - * @param alarmTime Pointer to structure where the alarm time is stored. + * @param alarmTime Pointer to the structure where the alarm time is stored. * * @return kStatus_Success: success in setting the RTC alarm * kStatus_InvalidArgument: Error because the alarm datetime format is incorrect @@ -208,7 +213,7 @@ status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime); * @brief Returns the RTC alarm time. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the alarm date and time details are stored. + * @param datetime Pointer to the structure where the alarm date and time details are stored. */ void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime); @@ -264,7 +269,7 @@ static inline uint32_t RTC_GetEnabledInterrupts(RTC_Type *base) */ /*! - * @brief Gets the RTC status flags + * @brief Gets the RTC status flags. * * @param base RTC peripheral base address * @@ -319,6 +324,8 @@ static inline void RTC_StopTimer(RTC_Type *base) /*! @}*/ +#if (defined(FSL_FEATURE_RTC_HAS_OSC_SCXP) && FSL_FEATURE_RTC_HAS_OSC_SCXP) + /*! * @brief This function sets the specified capacitor configuration for the RTC oscillator. * @@ -336,6 +343,8 @@ static inline void RTC_SetOscCapLoad(RTC_Type *base, uint32_t capLoad) base->CR = reg; } +#endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */ + /*! * @brief Performs a software reset on the RTC module. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c index c38165ec045..73ea64fa4ee 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -95,15 +95,17 @@ static void SAI_ReadNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWi /******************************************************************************* * Variables ******************************************************************************/ -/*!@brief SAI handle pointer */ -sai_handle_t *s_saiHandle[FSL_FEATURE_SOC_I2S_COUNT][2]; /* Base pointer array */ static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS; +/*!@brief SAI handle pointer */ +sai_handle_t *s_saiHandle[ARRAY_SIZE(s_saiBases)][2]; /* IRQ number array */ static const IRQn_Type s_saiTxIRQ[] = I2S_TX_IRQS; static const IRQn_Type s_saiRxIRQ[] = I2S_RX_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Clock name array */ static const clock_ip_name_t s_saiClock[] = SAI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointer to tx IRQ handler for each instance. */ static sai_tx_isr_t s_saiTxIsr; /*! @brief Pointer to tx IRQ handler for each instance. */ @@ -181,7 +183,7 @@ uint32_t SAI_GetInstance(I2S_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_I2S_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_saiBases); instance++) { if (s_saiBases[instance] == base) { @@ -189,7 +191,7 @@ uint32_t SAI_GetInstance(I2S_Type *base) } } - assert(instance < FSL_FEATURE_SOC_I2S_COUNT); + assert(instance < ARRAY_SIZE(s_saiBases)); return instance; } @@ -237,8 +239,10 @@ void SAI_TxInit(I2S_Type *base, const sai_config_t *config) { uint32_t val = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the SAI clock */ CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) /* Master clock source setting */ @@ -339,8 +343,10 @@ void SAI_RxInit(I2S_Type *base, const sai_config_t *config) { uint32_t val = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable SAI clock first. */ CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) /* Master clock source setting */ @@ -441,7 +447,9 @@ void SAI_Deinit(I2S_Type *base) { SAI_TxEnable(base, false); SAI_RxEnable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(s_saiClock[SAI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void SAI_TxGetDefaultConfig(sai_config_t *config) @@ -632,7 +640,7 @@ void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint uint32_t i = 0; uint8_t bytesPerWord = bitWidth / 8U; - for (i = 0; i < size; i++) + while (i < size) { /* Wait until it can write data */ while (!(base->TCSR & I2S_TCSR_FWF_MASK)) @@ -641,6 +649,7 @@ void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint SAI_WriteNonBlocking(base, channel, bitWidth, buffer, bytesPerWord); buffer += bytesPerWord; + i += bytesPerWord; } /* Wait until the last data is sent */ @@ -654,7 +663,7 @@ void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8 uint32_t i = 0; uint8_t bytesPerWord = bitWidth / 8U; - for (i = 0; i < size; i++) + while (i < size) { /* Wait until data is received */ while (!(base->RCSR & I2S_RCSR_FWF_MASK)) @@ -663,6 +672,7 @@ void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8 SAI_ReadNonBlocking(base, channel, bitWidth, buffer, bytesPerWord); buffer += bytesPerWord; + i += bytesPerWord; } } @@ -670,6 +680,9 @@ void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf { assert(handle); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + s_saiHandle[SAI_GetInstance(base)][0] = handle; handle->callback = callback; @@ -686,6 +699,9 @@ void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf { assert(handle); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + s_saiHandle[SAI_GetInstance(base)][1] = handle; handle->callback = callback; @@ -1024,19 +1040,30 @@ void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle) } #if defined(I2S0) -#if defined(FSL_FEATURE_SAI_INT_SOURCE_NUM) && (FSL_FEATURE_SAI_INT_SOURCE_NUM == 1) void I2S0_DriverIRQHandler(void) { - if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag))) +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFORequestFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif { s_saiRxIsr(I2S0, s_saiHandle[0][1]); } - if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag))) +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFORequestFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S0->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable))) +#endif { s_saiTxIsr(I2S0, s_saiHandle[0][0]); } } -#else + void I2S0_Tx_DriverIRQHandler(void) { assert(s_saiHandle[0][0]); @@ -1048,10 +1075,33 @@ void I2S0_Rx_DriverIRQHandler(void) assert(s_saiHandle[0][1]); s_saiRxIsr(I2S0, s_saiHandle[0][1]); } -#endif /* FSL_FEATURE_SAI_INT_SOURCE_NUM */ #endif /* I2S0*/ #if defined(I2S1) +void I2S1_DriverIRQHandler(void) +{ +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFORequestFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFOWarningFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiRxIsr(I2S1, s_saiHandle[1][1]); + } +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFORequestFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFOWarningFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S1->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiTxIsr(I2S1, s_saiHandle[1][0]); + } +} + void I2S1_Tx_DriverIRQHandler(void) { assert(s_saiHandle[1][0]); @@ -1063,4 +1113,80 @@ void I2S1_Rx_DriverIRQHandler(void) assert(s_saiHandle[1][1]); s_saiRxIsr(I2S1, s_saiHandle[1][1]); } +#endif /* I2S1*/ + +#if defined(I2S2) +void I2S2_DriverIRQHandler(void) +{ +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFORequestFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFOWarningFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiRxIsr(I2S2, s_saiHandle[2][1]); + } +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFORequestFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFOWarningFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S2->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiTxIsr(I2S2, s_saiHandle[2][0]); + } +} + +void I2S2_Tx_DriverIRQHandler(void) +{ + assert(s_saiHandle[2][0]); + s_saiTxIsr(I2S2, s_saiHandle[2][0]); +} + +void I2S2_Rx_DriverIRQHandler(void) +{ + assert(s_saiHandle[2][1]); + s_saiRxIsr(I2S2, s_saiHandle[2][1]); +} +#endif /* I2S2*/ + +#if defined(I2S3) +void I2S3_DriverIRQHandler(void) +{ +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFORequestFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFOWarningFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable))) +#endif + { + s_saiRxIsr(I2S3, s_saiHandle[3][1]); + } +#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) + if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFORequestFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable))) +#else + if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFOWarningFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) && + ((I2S3->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable))) #endif + { + s_saiTxIsr(I2S3, s_saiHandle[3][0]); + } +} + +void I2S3_Tx_DriverIRQHandler(void) +{ + assert(s_saiHandle[3][0]); + s_saiTxIsr(I2S3, s_saiHandle[3][0]); +} + +void I2S3_Rx_DriverIRQHandler(void) +{ + assert(s_saiHandle[3][1]); + s_saiRxIsr(I2S3, s_saiHandle[3][1]); +} +#endif /* I2S3*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h index cb38688cd92..64a2f667fce 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,14 +38,13 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -#define FSL_SAI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1 */ +#define FSL_SAI_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*!< Version 2.1.2 */ /*@}*/ /*! @brief SAI return status*/ @@ -186,16 +185,16 @@ typedef struct _sai_config /*! @brief Audio sample rate */ typedef enum _sai_sample_rate { - kSAI_SampleRate8KHz = 8000U, /*!< Sample rate 8000Hz */ - kSAI_SampleRate11025Hz = 11025U, /*!< Sample rate 11025Hz */ - kSAI_SampleRate12KHz = 12000U, /*!< Sample rate 12000Hz */ - kSAI_SampleRate16KHz = 16000U, /*!< Sample rate 16000Hz */ - kSAI_SampleRate22050Hz = 22050U, /*!< Sample rate 22050Hz */ - kSAI_SampleRate24KHz = 24000U, /*!< Sample rate 24000Hz */ - kSAI_SampleRate32KHz = 32000U, /*!< Sample rate 32000Hz */ - kSAI_SampleRate44100Hz = 44100U, /*!< Sample rate 44100Hz */ - kSAI_SampleRate48KHz = 48000U, /*!< Sample rate 48000Hz */ - kSAI_SampleRate96KHz = 96000U /*!< Sample rate 96000Hz */ + kSAI_SampleRate8KHz = 8000U, /*!< Sample rate 8000 Hz */ + kSAI_SampleRate11025Hz = 11025U, /*!< Sample rate 11025 Hz */ + kSAI_SampleRate12KHz = 12000U, /*!< Sample rate 12000 Hz */ + kSAI_SampleRate16KHz = 16000U, /*!< Sample rate 16000 Hz */ + kSAI_SampleRate22050Hz = 22050U, /*!< Sample rate 22050 Hz */ + kSAI_SampleRate24KHz = 24000U, /*!< Sample rate 24000 Hz */ + kSAI_SampleRate32KHz = 32000U, /*!< Sample rate 32000 Hz */ + kSAI_SampleRate44100Hz = 44100U, /*!< Sample rate 44100 Hz */ + kSAI_SampleRate48KHz = 48000U, /*!< Sample rate 48000 Hz */ + kSAI_SampleRate96KHz = 96000U /*!< Sample rate 96000 Hz */ } sai_sample_rate_t; /*! @brief Audio word width */ @@ -211,7 +210,7 @@ typedef enum _sai_word_width typedef struct _sai_transfer_format { uint32_t sampleRate_Hz; /*!< Sample rate of audio data */ - uint32_t bitWidth; /*!< Data length of audio data, usually 8/16/24/32bits */ + uint32_t bitWidth; /*!< Data length of audio data, usually 8/16/24/32 bits */ sai_mono_stereo_t stereo; /*!< Mono or stereo */ uint32_t masterClockHz; /*!< Master clock frequency in Hz */ #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) @@ -239,7 +238,7 @@ struct _sai_handle uint32_t state; /*!< Transfer status */ sai_transfer_callback_t callback; /*!< Callback function called at transfer event*/ void *userData; /*!< Callback parameter passed to callback function*/ - uint8_t bitWidth; /*!< Bit width for transfer, 8/16/24/32bits */ + uint8_t bitWidth; /*!< Bit width for transfer, 8/16/24/32 bits */ uint8_t channel; /*!< Transfer channel */ sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer */ size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */ @@ -301,7 +300,7 @@ void SAI_RxInit(I2S_Type *base, const sai_config_t *config); * This API initializes the configuration structure for use in SAI_TxConfig(). * The initialized structure can remain unchanged in SAI_TxConfig(), or it can be modified * before calling SAI_TxConfig(). - * Example: + * This is an example. @code sai_config_t config; SAI_TxGetDefaultConfig(&config); @@ -317,7 +316,7 @@ void SAI_TxGetDefaultConfig(sai_config_t *config); * This API initializes the configuration structure for use in SAI_RxConfig(). * The initialized structure can remain unchanged in SAI_RxConfig() or it can be modified * before calling SAI_RxConfig(). - * Example: + * This is an example. @code sai_config_t config; SAI_RxGetDefaultConfig(&config); @@ -356,7 +355,7 @@ void SAI_TxReset(I2S_Type *base); void SAI_RxReset(I2S_Type *base); /*! - * @brief Enables/disables SAI Tx. + * @brief Enables/disables the SAI Tx. * * @param base SAI base pointer * @param enable True means enable SAI Tx, false means disable. @@ -364,7 +363,7 @@ void SAI_RxReset(I2S_Type *base); void SAI_TxEnable(I2S_Type *base, bool enable); /*! - * @brief Enables/disables SAI Rx. + * @brief Enables/disables the SAI Rx. * * @param base SAI base pointer * @param enable True means enable SAI Rx, false means disable. @@ -418,7 +417,7 @@ static inline uint32_t SAI_RxGetStatusFlag(I2S_Type *base) * @brief Clears the SAI Rx status flag state. * * @param base SAI base pointer - * @param mask State mask. It can be a combination of the following source if defined: + * @param mask State mask. It can be a combination of the following sources if defined. * @arg kSAI_WordStartFlag * @arg kSAI_SyncErrorFlag * @arg kSAI_FIFOErrorFlag @@ -436,11 +435,11 @@ static inline void SAI_RxClearStatusFlags(I2S_Type *base, uint32_t mask) */ /*! - * @brief Enables SAI Tx interrupt requests. + * @brief Enables the SAI Tx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -453,11 +452,11 @@ static inline void SAI_TxEnableInterrupts(I2S_Type *base, uint32_t mask) } /*! - * @brief Enables SAI Rx interrupt requests. + * @brief Enables the SAI Rx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -470,11 +469,11 @@ static inline void SAI_RxEnableInterrupts(I2S_Type *base, uint32_t mask) } /*! - * @brief Disables SAI Tx interrupt requests. + * @brief Disables the SAI Tx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -487,11 +486,11 @@ static inline void SAI_TxDisableInterrupts(I2S_Type *base, uint32_t mask) } /*! - * @brief Disables SAI Rx interrupt requests. + * @brief Disables the SAI Rx interrupt requests. * * @param base SAI base pointer * @param mask interrupt source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_WordStartInterruptEnable * @arg kSAI_SyncErrorInterruptEnable * @arg kSAI_FIFOWarningInterruptEnable @@ -511,10 +510,10 @@ static inline void SAI_RxDisableInterrupts(I2S_Type *base, uint32_t mask) */ /*! - * @brief Enables/disables SAI Tx DMA requests. + * @brief Enables/disables the SAI Tx DMA requests. * @param base SAI base pointer * @param mask DMA source - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following sources if defined. * @arg kSAI_FIFOWarningDMAEnable * @arg kSAI_FIFORequestDMAEnable * @param enable True means enable DMA, false means disable DMA. @@ -532,10 +531,10 @@ static inline void SAI_TxEnableDMA(I2S_Type *base, uint32_t mask, bool enable) } /*! - * @brief Enables/disables SAI Rx DMA requests. + * @brief Enables/disables the SAI Rx DMA requests. * @param base SAI base pointer * @param mask DMA source - * The parameter can be a combination of the following source if defined: + * The parameter can be a combination of the following sources if defined. * @arg kSAI_FIFOWarningDMAEnable * @arg kSAI_FIFORequestDMAEnable * @param enable True means enable DMA, false means disable DMA. @@ -555,7 +554,7 @@ static inline void SAI_RxEnableDMA(I2S_Type *base, uint32_t mask, bool enable) /*! * @brief Gets the SAI Tx data register address. * - * This API is used to provide a transfer address for SAI DMA transfer configuration. + * This API is used to provide a transfer address for the SAI DMA transfer configuration. * * @param base SAI base pointer. * @param channel Which data channel used. @@ -569,7 +568,7 @@ static inline uint32_t SAI_TxGetDataRegisterAddress(I2S_Type *base, uint32_t cha /*! * @brief Gets the SAI Rx data register address. * - * This API is used to provide a transfer address for SAI DMA transfer configuration. + * This API is used to provide a transfer address for the SAI DMA transfer configuration. * * @param base SAI base pointer. * @param channel Which data channel used. @@ -594,10 +593,10 @@ static inline uint32_t SAI_RxGetDataRegisterAddress(I2S_Type *base, uint32_t cha * format to be transferred. * * @param base SAI base pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. - * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master - * clock, this value should equals to masterClockHz in format. + * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If the bit clock source is a master + * clock, this value should equal the masterClockHz. */ void SAI_TxSetFormat(I2S_Type *base, sai_transfer_format_t *format, @@ -611,10 +610,10 @@ void SAI_TxSetFormat(I2S_Type *base, * format to be transferred. * * @param base SAI base pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. - * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master - * clock, this value should equals to masterClockHz in format. + * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If the bit clock source is a master + * clock, this value should equal the masterClockHz. */ void SAI_RxSetFormat(I2S_Type *base, sai_transfer_format_t *format, @@ -628,7 +627,7 @@ void SAI_RxSetFormat(I2S_Type *base, * * @param base SAI base pointer. * @param channel Data channel used. - * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits. + * @param bitWidth How many bits in an audio word; usually 8/16/24/32 bits. * @param buffer Pointer to the data to be written. * @param size Bytes to be written. */ @@ -653,14 +652,14 @@ static inline void SAI_WriteData(I2S_Type *base, uint32_t channel, uint32_t data * * @param base SAI base pointer. * @param channel Data channel used. - * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits. + * @param bitWidth How many bits in an audio word; usually 8/16/24/32 bits. * @param buffer Pointer to the data to be read. * @param size Bytes to be read. */ void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size); /*! - * @brief Reads data from SAI FIFO. + * @brief Reads data from the SAI FIFO. * * @param base SAI base pointer. * @param channel Data channel used. @@ -681,26 +680,26 @@ static inline uint32_t SAI_ReadData(I2S_Type *base, uint32_t channel) /*! * @brief Initializes the SAI Tx handle. * - * This function initializes the Tx handle for SAI Tx transactional APIs. Call - * this function one time to get the handle initialized. + * This function initializes the Tx handle for the SAI Tx transactional APIs. Call + * this function once to get the handle initialized. * * @param base SAI base pointer * @param handle SAI handle pointer. - * @param callback pointer to user callback function - * @param userData user parameter passed to the callback function + * @param callback Pointer to the user callback function. + * @param userData User parameter passed to the callback function */ void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData); /*! * @brief Initializes the SAI Rx handle. * - * This function initializes the Rx handle for SAI Rx transactional APIs. Call - * this function one time to get the handle initialized. + * This function initializes the Rx handle for the SAI Rx transactional APIs. Call + * this function once to get the handle initialized. * * @param base SAI base pointer. * @param handle SAI handle pointer. - * @param callback pointer to user callback function - * @param userData user parameter passed to the callback function + * @param callback Pointer to the user callback function. + * @param userData User parameter passed to the callback function. */ void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData); @@ -712,11 +711,11 @@ void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf * * @param base SAI base pointer. * @param handle SAI handle pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master - * clock, this value should equal to masterClockHz in format. - * @return Status of this function. Return value is one of status_t. + * clock, this value should equal the masterClockHz in format. + * @return Status of this function. Return value is the status_t. */ status_t SAI_TransferTxSetFormat(I2S_Type *base, sai_handle_t *handle, @@ -732,10 +731,10 @@ status_t SAI_TransferTxSetFormat(I2S_Type *base, * * @param base SAI base pointer. * @param handle SAI handle pointer. - * @param format Pointer to SAI audio data format structure. + * @param format Pointer to the SAI audio data format structure. * @param mclkSourceClockHz SAI master clock source frequency in Hz. - * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master - * clock, this value should equals to masterClockHz in format. + * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is a master + * clock, this value should equal the masterClockHz in format. * @return Status of this function. Return value is one of status_t. */ status_t SAI_TransferRxSetFormat(I2S_Type *base, @@ -752,9 +751,9 @@ status_t SAI_TransferRxSetFormat(I2S_Type *base, * the transfer is finished. If the return status is not kStatus_SAI_Busy, the transfer * is finished. * - * @param base SAI base pointer - * @param handle pointer to sai_handle_t structure which stores the transfer state - * @param xfer pointer to sai_transfer_t structure + * @param base SAI base pointer. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. + * @param xfer Pointer to the sai_transfer_t structure. * @retval kStatus_Success Successfully started the data receive. * @retval kStatus_SAI_TxBusy Previous receive still not finished. * @retval kStatus_InvalidArgument The input parameter is invalid. @@ -770,8 +769,8 @@ status_t SAI_TransferSendNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_t * is finished. * * @param base SAI base pointer - * @param handle pointer to sai_handle_t structure which stores the transfer state - * @param xfer pointer to sai_transfer_t structure + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. + * @param xfer Pointer to the sai_transfer_t structure. * @retval kStatus_Success Successfully started the data receive. * @retval kStatus_SAI_RxBusy Previous receive still not finished. * @retval kStatus_InvalidArgument The input parameter is invalid. @@ -782,7 +781,7 @@ status_t SAI_TransferReceiveNonBlocking(I2S_Type *base, sai_handle_t *handle, sa * @brief Gets a set byte count. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. * @param count Bytes count sent. * @retval kStatus_Success Succeed get the transfer count. * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress. @@ -793,7 +792,7 @@ status_t SAI_TransferGetSendCount(I2S_Type *base, sai_handle_t *handle, size_t * * @brief Gets a received byte count. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. * @param count Bytes count received. * @retval kStatus_Success Succeed get the transfer count. * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress. @@ -807,18 +806,18 @@ status_t SAI_TransferGetReceiveCount(I2S_Type *base, sai_handle_t *handle, size_ * to abort the transfer early. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. */ void SAI_TransferAbortSend(I2S_Type *base, sai_handle_t *handle); /*! * @brief Aborts the the current IRQ receive. * - * @note This API can be called any time when an interrupt non-blocking transfer initiates + * @note This API can be called when an interrupt non-blocking transfer initiates * to abort the transfer early. * * @param base SAI base pointer - * @param handle pointer to sai_handle_t structure which stores the transfer state. + * @param handle Pointer to the sai_handle_t structure which stores the transfer state. */ void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle); @@ -826,7 +825,7 @@ void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle); * @brief Tx interrupt handler. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure. + * @param handle Pointer to the sai_handle_t structure. */ void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle); @@ -834,7 +833,7 @@ void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle); * @brief Tx interrupt handler. * * @param base SAI base pointer. - * @param handle pointer to sai_handle_t structure. + * @param handle Pointer to the sai_handle_t structure. */ void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c index 9b1b2f6c490..dce5a87bfa1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -132,6 +132,9 @@ void SAI_TransferTxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -157,6 +160,9 @@ void SAI_TransferRxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -187,7 +193,14 @@ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; @@ -210,7 +223,14 @@ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; @@ -253,6 +273,9 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra EDMA_PrepareTransfer(&config, xfer->data, handle->bytesPerFrame, (void *)destAddr, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -298,6 +321,9 @@ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_ EDMA_PrepareTransfer(&config, (void *)srcAddr, handle->bytesPerFrame, xfer->data, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -322,6 +348,9 @@ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable DMA enable bit */ SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Tx */ + SAI_TxEnable(base, false); + /* Set the handle state */ handle->state = kSAI_Idle; } @@ -336,6 +365,9 @@ void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable DMA enable bit */ SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Rx */ + SAI_RxEnable(base, false); + /* Set the handle state */ handle->state = kSAI_Idle; } @@ -353,7 +385,8 @@ status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; @@ -372,7 +405,8 @@ status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *hand else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h index 44506fa039d..9ae05db0e95 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,8 +38,6 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -53,6 +51,7 @@ typedef void (*sai_edma_callback_t)(I2S_Type *base, sai_edma_handle_t *handle, s struct _sai_edma_handle { edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint8_t bytesPerFrame; /*!< Bytes in a frame */ uint8_t channel; /*!< Which data channel */ uint8_t count; /*!< The transfer data count in a DMA request */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c index d2774eeabc9..3151cd22ed9 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.c @@ -1,34 +1,28 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * - * Redistribution and use in source and binary forms, with or without - * modification, + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this - * list + * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * - * o Redistributions in binary form must reproduce the above copyright notice, - * this + * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @@ -42,12 +36,8 @@ /*! @brief Clock setting */ /* Max SD clock divisor from base clock */ #define SDHC_MAX_DVS ((SDHC_SYSCTL_DVS_MASK >> SDHC_SYSCTL_DVS_SHIFT) + 1U) -#define SDHC_INITIAL_DVS (1U) /* Initial value of SD clock divisor */ -#define SDHC_INITIAL_CLKFS (2U) /* Initial value of SD clock frequency selector */ -#define SDHC_NEXT_DVS(x) ((x) += 1U) #define SDHC_PREV_DVS(x) ((x) -= 1U) #define SDHC_MAX_CLKFS ((SDHC_SYSCTL_SDCLKFS_MASK >> SDHC_SYSCTL_SDCLKFS_SHIFT) + 1U) -#define SDHC_NEXT_CLKFS(x) ((x) <<= 1U) #define SDHC_PREV_CLKFS(x) ((x) >>= 1U) /* Typedef for interrupt handler. */ @@ -85,8 +75,9 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal * @param base SDHC peripheral base address. * @param command Command to be sent. * @param data Data to be transferred. + * @param DMA mode selection */ -static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data); +static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode); /*! * @brief Receive command response @@ -94,7 +85,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da * @param base SDHC peripheral base address. * @param command Command to be sent. */ -static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command); +static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command); /*! * @brief Read DATAPORT when buffer enable bit is set. @@ -230,8 +221,10 @@ static SDHC_Type *const s_sdhcBase[] = SDHC_BASE_PTRS; /*! @brief SDHC IRQ name array */ static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief SDHC clock array name */ static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* SDHC ISR for transactional APIs. */ static sdhc_isr_t s_sdhcIsr; @@ -243,12 +236,12 @@ static uint32_t SDHC_GetInstance(SDHC_Type *base) { uint8_t instance = 0; - while ((instance < FSL_FEATURE_SOC_SDHC_COUNT) && (s_sdhcBase[instance] != base)) + while ((instance < ARRAY_SIZE(s_sdhcBase)) && (s_sdhcBase[instance] != base)) { instance++; } - assert(instance < FSL_FEATURE_SOC_SDHC_COUNT); + assert(instance < ARRAY_SIZE(s_sdhcBase)); return instance; } @@ -256,7 +249,6 @@ static uint32_t SDHC_GetInstance(SDHC_Type *base) static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal) { uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */ - sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); bool cardDetectDat3 = (bool)(base->PROCTL & SDHC_PROCTL_D3CD_MASK); /* Disable all interrupts */ @@ -267,23 +259,12 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal interruptEnabled = (kSDHC_CommandIndexErrorFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag | kSDHC_CommandTimeoutFlag | kSDHC_CommandCompleteFlag | kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag | - kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag); + kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag | kSDHC_BufferReadReadyFlag | + kSDHC_BufferWriteReadyFlag | kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag); if (cardDetectDat3) { interruptEnabled |= (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag); } - switch (dmaMode) - { - case kSDHC_DmaModeAdma1: - case kSDHC_DmaModeAdma2: - interruptEnabled |= (kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag); - break; - case kSDHC_DmaModeNo: - interruptEnabled |= (kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); - break; - default: - break; - } SDHC_EnableInterruptStatus(base, interruptEnabled); if (usingInterruptSignal) @@ -292,48 +273,47 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal } } -static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data) +static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode) { uint32_t flags = 0U; sdhc_transfer_config_t sdhcTransferConfig = {0}; - sdhc_dma_mode_t dmaMode; /* Define the flag corresponding to each response type. */ switch (command->responseType) { - case kSDHC_ResponseTypeNone: + case kCARD_ResponseTypeNone: break; - case kSDHC_ResponseTypeR1: /* Response 1 */ + case kCARD_ResponseTypeR1: /* Response 1 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR1b: /* Response 1 with busy */ + case kCARD_ResponseTypeR1b: /* Response 1 with busy */ flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR2: /* Response 2 */ + case kCARD_ResponseTypeR2: /* Response 2 */ flags |= (kSDHC_ResponseLength136Flag | kSDHC_EnableCrcCheckFlag); break; - case kSDHC_ResponseTypeR3: /* Response 3 */ + case kCARD_ResponseTypeR3: /* Response 3 */ flags |= (kSDHC_ResponseLength48Flag); break; - case kSDHC_ResponseTypeR4: /* Response 4 */ + case kCARD_ResponseTypeR4: /* Response 4 */ flags |= (kSDHC_ResponseLength48Flag); break; - case kSDHC_ResponseTypeR5: /* Response 5 */ + case kCARD_ResponseTypeR5: /* Response 5 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR5b: /* Response 5 with busy */ + case kCARD_ResponseTypeR5b: /* Response 5 with busy */ flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR6: /* Response 6 */ + case kCARD_ResponseTypeR6: /* Response 6 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR7: /* Response 7 */ + case kCARD_ResponseTypeR7: /* Response 7 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; default: break; } - if (command->type == kSDHC_CommandTypeAbort) + if (command->type == kCARD_CommandTypeAbort) { flags |= kSDHC_CommandTypeAbortFlag; } @@ -341,7 +321,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da if (data) { flags |= kSDHC_DataPresentFlag; - dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); + if (dmaMode != kSDHC_DmaModeNo) { flags |= kSDHC_EnableDmaFlag; @@ -375,14 +355,14 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da SDHC_SetTransferConfig(base, &sdhcTransferConfig); } -static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) +static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) { uint32_t i; - if (command->responseType != kSDHC_ResponseTypeNone) + if (command->responseType != kCARD_ResponseTypeNone) { command->response[0U] = SDHC_GetCommandResponse(base, 0U); - if (command->responseType == kSDHC_ResponseTypeR2) + if (command->responseType == kCARD_ResponseTypeR2) { command->response[1U] = SDHC_GetCommandResponse(base, 1U); command->response[2U] = SDHC_GetCommandResponse(base, 2U); @@ -401,6 +381,18 @@ static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command } while (i--); } } + /* check response error flag */ + if ((command->responseErrorFlags != 0U) && + ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) || + (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5))) + { + if (((command->responseErrorFlags) & (command->response[0U])) != 0U) + { + return kStatus_SDHC_SendCommandFailed; + } + } + + return kStatus_Success; } static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) @@ -411,10 +403,10 @@ static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t t uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT); /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -458,10 +450,10 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) status_t error = kStatus_Success; /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -487,13 +479,12 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) { transferredWords = SDHC_ReadDataPort(base, data, transferredWords); } - - /* Clear buffer enable flag to trigger transfer. Clear data error flag when SDHC encounter error */ - SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag)); + /* clear buffer ready and error */ + SDHC_ClearInterruptStatusFlags(base, kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag); } /* Clear data complete flag after the last read operation. */ - SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag); + SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag); return error; } @@ -506,10 +497,10 @@ static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT); /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -553,10 +544,10 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) status_t error = kStatus_Success; /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (data->blockSize % sizeof(uint32_t) != 0U) { data->blockSize += @@ -598,6 +589,7 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) error = kStatus_Fail; } } + SDHC_ClearInterruptStatusFlags(base, (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag)); return error; @@ -619,7 +611,7 @@ static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *comman /* Receive response when command completes successfully. */ if (error == kStatus_Success) { - SDHC_ReceiveCommandResponse(base, command); + error = SDHC_ReceiveCommandResponse(base, command); } SDHC_ClearInterruptStatusFlags(base, (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag)); @@ -748,7 +740,11 @@ static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint { handle->transferredWords = SDHC_WriteDataPort(base, handle->data, handle->transferredWords); } - else if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete)) + else + { + } + + if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete)) { handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData); } @@ -787,8 +783,10 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config) uint32_t proctl; uint32_t wml; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable SDHC clock. */ CLOCK_EnableClock(s_sdhcClock[SDHC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset SDHC. */ SDHC_Reset(base, kSDHC_ResetAll, 100); @@ -822,8 +820,10 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config) void SDHC_Deinit(SDHC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable clock. */ CLOCK_DisableClock(s_sdhcClock[SDHC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout) @@ -877,44 +877,83 @@ uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busCloc assert(srcClock_Hz != 0U); assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz)); - uint32_t divisor; - uint32_t prescaler; - uint32_t sysctl; - uint32_t nearestFrequency = 0; + uint32_t totalDiv = 0U; + uint32_t divisor = 0U; + uint32_t prescaler = 0U; + uint32_t sysctl = 0U; + uint32_t nearestFrequency = 0U; - divisor = SDHC_INITIAL_DVS; - prescaler = SDHC_INITIAL_CLKFS; - - /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/ - base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK; + /* calucate total divisor first */ + totalDiv = srcClock_Hz / busClock_Hz; - if (busClock_Hz > 0U) + if (totalDiv != 0U) { - while ((srcClock_Hz / prescaler / SDHC_MAX_DVS > busClock_Hz) && (prescaler < SDHC_MAX_CLKFS)) + /* calucate the divisor (srcClock_Hz / divisor) <= busClock_Hz */ + if ((srcClock_Hz / totalDiv) > busClock_Hz) { - SDHC_NEXT_CLKFS(prescaler); + totalDiv++; } - while ((srcClock_Hz / prescaler / divisor > busClock_Hz) && (divisor < SDHC_MAX_DVS)) + + /* divide the total divisor to div and prescaler */ + if (totalDiv > SDHC_MAX_DVS) { - SDHC_NEXT_DVS(divisor); + prescaler = totalDiv / SDHC_MAX_DVS; + /* prescaler must be a value which equal 2^n and smaller than SDHC_MAX_CLKFS */ + while (((SDHC_MAX_CLKFS % prescaler) != 0U) || (prescaler == 1U)) + { + prescaler++; + } + /* calucate the divisor */ + divisor = totalDiv / prescaler; + /* fine tuning the divisor until divisor * prescaler >= totalDiv */ + while ((divisor * prescaler) < totalDiv) + { + divisor++; + } + nearestFrequency = srcClock_Hz / divisor / prescaler; } - nearestFrequency = srcClock_Hz / prescaler / divisor; - SDHC_PREV_CLKFS(prescaler); + else + { + divisor = totalDiv; + prescaler = 0U; + nearestFrequency = srcClock_Hz / divisor; + } + } + /* in this condition , srcClock_Hz = busClock_Hz, */ + else + { + /* total divider = 1U */ + divisor = 0U; + prescaler = 0U; + nearestFrequency = srcClock_Hz; + } + + /* calucate the value write to register */ + if (divisor != 0U) + { SDHC_PREV_DVS(divisor); + } + /* calucate the value write to register */ + if (prescaler != 0U) + { + SDHC_PREV_CLKFS(prescaler); + } - /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */ - sysctl = base->SYSCTL; - sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK); - sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU)); - base->SYSCTL = sysctl; + /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/ + base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK; - /* Wait until the SD clock is stable. */ - while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK)) - { - } - /* Enable the SD clock. */ - base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK; + /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */ + sysctl = base->SYSCTL; + sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK); + sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU)); + base->SYSCTL = sysctl; + + /* Wait until the SD clock is stable. */ + while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK)) + { } + /* Enable the SD clock. */ + base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK; return nearestFrequency; } @@ -1008,7 +1047,7 @@ void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config) uint32_t mmcboot = 0U; mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) | - SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount)); + SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount)); if (config->enableBootAck) { mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK; @@ -1032,7 +1071,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, uint32_t dataBytes) { status_t error = kStatus_Success; - const uint32_t *startAddress; + const uint32_t *startAddress = data; uint32_t entries; uint32_t i; #if defined FSL_SDHC_ENABLE_ADMA1 @@ -1044,14 +1083,19 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, (!data) || (!dataBytes) #if !defined FSL_SDHC_ENABLE_ADMA1 || (dmaMode == kSDHC_DmaModeAdma1) -#else - /* Buffer address configured in ADMA1 descriptor must be 4KB aligned. */ - || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)data % SDHC_ADMA1_LENGTH_ALIGN) != 0U)) -#endif /* FSL_SDHC_ENABLE_ADMA1 */ +#endif ) { error = kStatus_InvalidArgument; } + else if (((dmaMode == kSDHC_DmaModeAdma2) && (((uint32_t)startAddress % SDHC_ADMA2_LENGTH_ALIGN) != 0U)) +#if defined FSL_SDHC_ENABLE_ADMA1 + || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)startAddress % SDHC_ADMA1_LENGTH_ALIGN) != 0U)) +#endif + ) + { + error = kStatus_SDHC_DMADataBufferAddrNotAlign; + } else { switch (dmaMode) @@ -1071,7 +1115,6 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */ } - startAddress = data; /* Check if ADMA descriptor's number is enough. */ entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); /* ADMA1 needs two descriptors to finish a transfer */ @@ -1113,22 +1156,24 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, /* When use ADMA, disable simple DMA */ base->DSADDR = 0U; base->ADSADDR = (uint32_t)table; + /* disable the buffer ready flag in DMA mode */ + SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } break; #endif /* FSL_SDHC_ENABLE_ADMA1 */ case kSDHC_DmaModeAdma2: /* - * Add non aligned access support ,user need make sure your buffer size is big - * enough to hold the data,in other words,user need make sure the buffer size - * is 4 byte aligned - */ + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ if (dataBytes % sizeof(uint32_t) != 0U) { dataBytes += sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */ } - startAddress = data; /* Check if ADMA descriptor's number is enough. */ entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma2_descriptor_t))) @@ -1165,6 +1210,9 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, /* When use ADMA, disable simple DMA */ base->DSADDR = 0U; base->ADSADDR = (uint32_t)table; + /* disable the buffer read flag in DMA mode */ + SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } break; default: @@ -1187,44 +1235,53 @@ status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t ad /* make sure the cmd/block count is valid */ if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT))) { - error = kStatus_InvalidArgument; + return kStatus_InvalidArgument; } - else + + /* Wait until command/data bus out of busy status. */ + while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) { - /* Wait until command/data bus out of busy status. */ - while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) + } + while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)) + { + } + + /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ + if (data && (NULL != admaTable)) + { + error = + SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, + (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize)); + /* in this situation , we disable the DMA instead of polling transfer mode */ + if (error == kStatus_SDHC_DMADataBufferAddrNotAlign) { + dmaMode = kSDHC_DmaModeNo; + SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } - while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)) + else if (error != kStatus_Success) { - } - - /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ - if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, - (data->rxData ? data->rxData : data->txData), - (data->blockCount * data->blockSize)))) - { - error = kStatus_SDHC_PrepareAdmaDescriptorFailed; + return error; } else { - /* Send command and receive data. */ - SDHC_StartTransfer(base, command, data); - if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) - { - error = kStatus_SDHC_SendCommandFailed; - } - else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data))) - { - error = kStatus_SDHC_TransferDataFailed; - } - else - { - } } } - return error; + /* Send command and receive data. */ + SDHC_StartTransfer(base, command, data, dmaMode); + if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) + { + return kStatus_SDHC_SendCommandFailed; + } + else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data))) + { + return kStatus_SDHC_TransferDataFailed; + } + else + { + } + + return kStatus_Success; } void SDHC_TransferCreateHandle(SDHC_Type *base, @@ -1271,40 +1328,49 @@ status_t SDHC_TransferNonBlocking( /* make sure cmd/block count is valid */ if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT))) { - error = kStatus_InvalidArgument; + return kStatus_InvalidArgument; } - else + + /* Wait until command/data bus out of busy status. */ + if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) || + (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))) { - /* Wait until command/data bus out of busy status. */ - if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) || - (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))) + return kStatus_SDHC_BusyTransferring; + } + + /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ + if (data && (NULL != admaTable)) + { + error = + SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, + (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize)); + /* in this situation , we disable the DMA instead of polling transfer mode */ + if (error == kStatus_SDHC_DMADataBufferAddrNotAlign) { - error = kStatus_SDHC_BusyTransferring; + /* change to polling mode */ + dmaMode = kSDHC_DmaModeNo; + SDHC_EnableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + } + else if (error != kStatus_Success) + { + return error; } else { - /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ - if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, - (data->rxData ? data->rxData : data->txData), - (data->blockCount * data->blockSize)))) - { - error = kStatus_SDHC_PrepareAdmaDescriptorFailed; - } - else - { - /* Save command and data into handle before transferring. */ - handle->command = command; - handle->data = data; - handle->interruptFlags = 0U; - /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ - handle->transferredWords = 0U; - - SDHC_StartTransfer(base, command, data); - } } } - return error; + /* Save command and data into handle before transferring. */ + handle->command = command; + handle->data = data; + handle->interruptFlags = 0U; + /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ + handle->transferredWords = 0U; + + SDHC_StartTransfer(base, command, data, dmaMode); + + return kStatus_Success; } void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h index 4976649d91a..336b9618e5b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdhc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -43,8 +43,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief Driver version 2.1.2. */ -#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 2U)) +/*! @brief Driver version 2.1.5. */ +#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 5U)) /*@}*/ /*! @brief Maximum block count can be set one time */ @@ -57,6 +57,8 @@ enum _sdhc_status kStatus_SDHC_PrepareAdmaDescriptorFailed = MAKE_STATUS(kStatusGroup_SDHC, 1U), /*!< Set DMA descriptor failed */ kStatus_SDHC_SendCommandFailed = MAKE_STATUS(kStatusGroup_SDHC, 2U), /*!< Send command failed */ kStatus_SDHC_TransferDataFailed = MAKE_STATUS(kStatusGroup_SDHC, 3U), /*!< Transfer data failed */ + kStatus_SDHC_DMADataBufferAddrNotAlign = + MAKE_STATUS(kStatusGroup_SDHC, 4U), /*!< data buffer addr not align in DMA mode */ }; /*! @brief Host controller capabilities flag mask */ @@ -282,32 +284,32 @@ typedef enum _sdhc_boot_mode } sdhc_boot_mode_t; /*! @brief The command type */ -typedef enum _sdhc_command_type +typedef enum _sdhc_card_command_type { - kSDHC_CommandTypeNormal = 0U, /*!< Normal command */ - kSDHC_CommandTypeSuspend = 1U, /*!< Suspend command */ - kSDHC_CommandTypeResume = 2U, /*!< Resume command */ - kSDHC_CommandTypeAbort = 3U, /*!< Abort command */ -} sdhc_command_type_t; + kCARD_CommandTypeNormal = 0U, /*!< Normal command */ + kCARD_CommandTypeSuspend = 1U, /*!< Suspend command */ + kCARD_CommandTypeResume = 2U, /*!< Resume command */ + kCARD_CommandTypeAbort = 3U, /*!< Abort command */ +} sdhc_card_command_type_t; /*! * @brief The command response type. * * Define the command response type from card to host controller. */ -typedef enum _sdhc_response_type +typedef enum _sdhc_card_response_type { - kSDHC_ResponseTypeNone = 0U, /*!< Response type: none */ - kSDHC_ResponseTypeR1 = 1U, /*!< Response type: R1 */ - kSDHC_ResponseTypeR1b = 2U, /*!< Response type: R1b */ - kSDHC_ResponseTypeR2 = 3U, /*!< Response type: R2 */ - kSDHC_ResponseTypeR3 = 4U, /*!< Response type: R3 */ - kSDHC_ResponseTypeR4 = 5U, /*!< Response type: R4 */ - kSDHC_ResponseTypeR5 = 6U, /*!< Response type: R5 */ - kSDHC_ResponseTypeR5b = 7U, /*!< Response type: R5b */ - kSDHC_ResponseTypeR6 = 8U, /*!< Response type: R6 */ - kSDHC_ResponseTypeR7 = 9U, /*!< Response type: R7 */ -} sdhc_response_type_t; + kCARD_ResponseTypeNone = 0U, /*!< Response type: none */ + kCARD_ResponseTypeR1 = 1U, /*!< Response type: R1 */ + kCARD_ResponseTypeR1b = 2U, /*!< Response type: R1b */ + kCARD_ResponseTypeR2 = 3U, /*!< Response type: R2 */ + kCARD_ResponseTypeR3 = 4U, /*!< Response type: R3 */ + kCARD_ResponseTypeR4 = 5U, /*!< Response type: R4 */ + kCARD_ResponseTypeR5 = 6U, /*!< Response type: R5 */ + kCARD_ResponseTypeR5b = 7U, /*!< Response type: R5b */ + kCARD_ResponseTypeR6 = 8U, /*!< Response type: R6 */ + kCARD_ResponseTypeR7 = 9U, /*!< Response type: R7 */ +} sdhc_card_response_type_t; /*! @brief The alignment size for ADDRESS filed in ADMA1's descriptor */ #define SDHC_ADMA1_ADDRESS_ALIGN (4096U) @@ -477,7 +479,8 @@ typedef struct _sdhc_config * @brief Card data descriptor * * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card - * driver want to ignore the error event to read/write all the data not to stop read/write immediately when error event + * driver + * want to ignore the error event to read/write all the data not to stop read/write immediately when error event * happen for example bus testing procedure for MMC card. */ typedef struct _sdhc_data @@ -497,11 +500,13 @@ typedef struct _sdhc_data */ typedef struct _sdhc_command { - uint32_t index; /*!< Command index */ - uint32_t argument; /*!< Command argument */ - sdhc_command_type_t type; /*!< Command type */ - sdhc_response_type_t responseType; /*!< Command response type */ - uint32_t response[4U]; /*!< Response for this command */ + uint32_t index; /*!< Command index */ + uint32_t argument; /*!< Command argument */ + sdhc_card_command_type_t type; /*!< Command type */ + sdhc_card_response_type_t responseType; /*!< Command response type */ + uint32_t response[4U]; /*!< Response for this command */ + uint32_t responseErrorFlags; /*!< response error flag, the flag which need to check + the command reponse*/ } sdhc_command_t; /*! @brief Transfer state */ @@ -829,7 +834,8 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w * @brief Sets the card transfer-related configuration. * * This function fills the card transfer-related command argument/transfer flag/data size. The command and data are sent - * by SDHC after calling this function. + by + * SDHC after calling this function. * * Example: @code @@ -929,7 +935,8 @@ static inline void SDHC_EnableCardDetectTest(SDHC_Type *base, bool enable) * * This function sets the card detection test level to indicate whether the card is inserted into the SDHC when DAT[3]/ * CD pin is selected as a card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is - * selected as the card detection pin. + * selected + * as the card detection pin. * * @param base SDHC peripheral base address. * @param high True to set the card detect level to high. @@ -1007,7 +1014,10 @@ static inline void SDHC_SetForceEvent(SDHC_Type *base, uint32_t mask) * @brief Transfers the command/data using a blocking method. * * This function waits until the command response/data is received or the SDHC encounters an error by polling the status - * flag. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support + * flag. + * This function support non word align data addr transfer support, if data buffer addr is not align in DMA mode, + * the API will continue finish the transfer by polling IO directly + * The application must not call this API in multiple threads at the same time. Because of that this API doesn't support * the re-entry mechanism. * * @note There is no need to call the API 'SDHC_TransferCreateHandle' when calling this API. @@ -1044,7 +1054,10 @@ void SDHC_TransferCreateHandle(SDHC_Type *base, * @brief Transfers the command/data using an interrupt and an asynchronous method. * * This function sends a command and data and returns immediately. It doesn't wait the transfer complete or encounter an - * error. The application must not call this API in multiple threads at the same time. Because of that this API doesn't support + * error. + * This function support non word align data addr transfer support, if data buffer addr is not align in DMA mode, + * the API will continue finish the transfer by polling IO directly + * The application must not call this API in multiple threads at the same time. Because of that this API doesn't support * the re-entry mechanism. * * @note Call the API 'SDHC_TransferCreateHandle' when calling this API. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c index ad672cfd604..baf432ed8b5 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ /*! @brief Define macros for SDRAM driver. */ #define SDRAMC_ONEMILLSEC_NANOSECONDS (1000000U) #define SDRAMC_ONESECOND_MILLISECONDS (1000U) -#define SDRAMC_TIMEOUT_COUNT (0xFFFFU) /******************************************************************************* * Prototypes @@ -53,8 +52,10 @@ static uint32_t SDRAMC_GetInstance(SDRAM_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to SDRAMC clocks for each instance. */ -const clock_ip_name_t s_sdramClock[FSL_FEATURE_SOC_SDRAM_COUNT] = SDRAM_CLOCKS; +static const clock_ip_name_t s_sdramClock[FSL_FEATURE_SOC_SDRAM_COUNT] = SDRAM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to SDRAMC bases for each instance. */ static SDRAM_Type *const s_sdramcBases[] = SDRAM_BASE_PTRS; @@ -67,7 +68,7 @@ static uint32_t SDRAMC_GetInstance(SDRAM_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_SDRAM_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_sdramcBases); instance++) { if (s_sdramcBases[instance] == base) { @@ -75,7 +76,7 @@ static uint32_t SDRAMC_GetInstance(SDRAM_Type *base) } } - assert(instance < FSL_FEATURE_SOC_SDRAM_COUNT); + assert(instance < ARRAY_SIZE(s_sdramcBases)); return instance; } @@ -92,8 +93,10 @@ void SDRAMC_Init(SDRAM_Type *base, sdramc_config_t *configure) uint32_t count; uint32_t index; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Un-gate sdram controller clock. */ CLOCK_EnableClock(s_sdramClock[SDRAMC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Initialize sdram Auto refresh timing. */ count = refreshConfig->sdramRefreshRow * (refreshConfig->busClock_Hz / SDRAMC_ONESECOND_MILLISECONDS); @@ -119,50 +122,23 @@ void SDRAMC_Deinit(SDRAM_Type *base) SDRAMC_EnableOperateValid(base, kSDRAMC_Block0, false); SDRAMC_EnableOperateValid(base, kSDRAMC_Block1, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable SDRAM clock. */ CLOCK_DisableClock(s_sdramClock[SDRAMC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } -status_t SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command) +void SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command) { - status_t result = kStatus_Success; - uint32_t count = SDRAMC_TIMEOUT_COUNT; - switch (command) { /* Initiate mrs command. */ case kSDRAMC_ImrsCommand: base->BLOCK[block].AC |= SDRAM_AC_IMRS_MASK; - while (count--) - { - if (!(base->BLOCK[block].AC & SDRAM_AC_IMRS_MASK)) - { - break; - } - } - - if (!count) - { - /* Timeout the mrs command is unfinished. */ - result = kStatus_Fail; - } - break; + break; /* Initiate precharge command. */ case kSDRAMC_PrechargeCommand: base->BLOCK[block].AC |= SDRAM_AC_IP_MASK; - while (count--) - { - if (!(base->BLOCK[block].AC & SDRAM_AC_IP_MASK)) - { - break; - } - } - - /* Timeout the precharge command is unfinished. */ - if (!count) - { - result = kStatus_Fail; - } break; /* Enable Auto refresh command. */ case kSDRAMC_AutoRefreshEnableCommand: @@ -183,5 +159,4 @@ status_t SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sd default: break; } - return result; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h index 4da5ad756f8..c409fe456ee 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sdramc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief SDRAMC driver version 2.0.0. */ -#define FSL_SDRAMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief SDRAMC driver version 2.1.0. */ +#define FSL_SDRAMC_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*@}*/ /*! @brief SDRAM controller auto-refresh timing. */ @@ -60,14 +59,14 @@ typedef enum _sdramc_refresh_time /*! * @brief Setting latency for SDRAM controller timing specifications. * - * The latency setting will affects the following SDRAM timing specifications: + * The latency setting affects the following SDRAM timing specifications: * - trcd: SRAS assertion to SCAS assertion \n * - tcasl: SCAS assertion to data out \n * - tras: ACTV command to Precharge command \n * - trp: Precharge command to ACTV command \n * - trwl, trdl: Last data input to Precharge command \n * - tep: Last data out to Precharge command \n - * the details of the latency setting and timing specifications are shown on the following table list: \n + * The details of the latency setting and timing specifications are shown in the following table list. \n * latency trcd: tcasl tras trp trwl,trdl tep \n * 0 1 bus clock 1 bus clock 2 bus clocks 1 bus clock 1 bus clock 1 bus clock \n * 1 2 bus clock 2 bus clock 4 bus clocks 2 bus clock 1 bus clock 1 bus clock \n @@ -219,10 +218,10 @@ void SDRAMC_Deinit(SDRAM_Type *base); /*! * @brief Sends the SDRAM command. - * This function sends the command to SDRAM. There are precharge command, initialize MRS command, + * This function sends commands to SDRAM. The commands are precharge command, initialization MRS command, * auto-refresh enable/disable command, and self-refresh enter/exit commands. - * Note the self-refresh enter/exit commands are all blocks setting and "block" - * are ignored. Ensure to set the right "block" when send other commands. + * Note that the self-refresh enter/exit commands are all blocks setting and "block" + * is ignored. Ensure to set the correct "block" when send other commands. * * @param base SDRAM controller peripheral base address. * @param block The block selection. @@ -233,13 +232,8 @@ void SDRAMC_Deinit(SDRAM_Type *base); * kSDRAMC_SelfrefreshExitCommand - Exit self-refresh command \n * kSDRAMC_AutoRefreshEnableCommand - Enable auto refresh command \n * kSDRAMC_AutoRefreshDisableCommand - Disable auto refresh command - * @return Command execution status. - * All commands except the "initialize MRS command" and "precharge command" - * return kStatus_Success directly. - * For "initialize MRS command" and "precharge command" - * return kStatus_Success when the command success else return kStatus_Fail. */ -status_t SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command); +void SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command); /*! * @brief Enables/disables the write protection. @@ -261,11 +255,11 @@ static inline void SDRAMC_EnableWriteProtect(SDRAM_Type *base, sdramc_block_sele } /*! - * @brief Enables/disables the operation valid. + * @brief Enables/disables the valid operation. * * @param base SDRAM peripheral base address. * @param block The block which is selected. - * @param enable True enable the operation valid, false disable the operation valid. + * @param enable True enable the valid operation; false disable the valid operation. */ static inline void SDRAMC_EnableOperateValid(SDRAM_Type *base, sdramc_block_selection_t block, bool enable) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c index 3a4b801b7b3..ade512f0306 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_sim.h" diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h index a3b69188841..0a0e4fb3092 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sim.h @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_SIM_H_ #define _FSL_SIM_H_ @@ -36,7 +36,6 @@ /*! @addtogroup sim */ /*! @{*/ -/*! @file */ /******************************************************************************* * Definitions @@ -90,10 +89,10 @@ extern "C" { * @brief Sets the USB voltage regulator setting. * * This function configures whether the USB voltage regulator is enabled in - * normal RUN mode, STOP/VLPS/LLS/VLLS modes and VLPR/VLPW modes. The configurations - * are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, enable + * normal RUN mode, STOP/VLPS/LLS/VLLS modes, and VLPR/VLPW modes. The configurations + * are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, to enable * USB voltage regulator in RUN/VLPR/VLPW modes and disable in STOP/VLPS/LLS/VLLS mode, - * please use: + * use: * * SIM_SetUsbVoltRegulatorEnableMode(kSIM_UsbVoltRegEnable | kSIM_UsbVoltRegEnableInLowPower); * @@ -103,16 +102,16 @@ void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask); #endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */ /*! - * @brief Get the unique identification register value. + * @brief Gets the unique identification register value. * * @param uid Pointer to the structure to save the UID value. */ void SIM_GetUniqueId(sim_uid_t *uid); /*! - * @brief Set the flash enable mode. + * @brief Sets the flash enable mode. * - * @param mode The mode to set, see \ref _sim_flash_mode for mode details. + * @param mode The mode to set; see \ref _sim_flash_mode for mode details. */ static inline void SIM_SetFlashMode(uint8_t mode) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c index 0018cf7dce2..dacf193476c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -29,6 +29,7 @@ */ #include "fsl_smc.h" +#include "fsl_flash.h" #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) void SMC_GetParam(SMC_Type *base, smc_param_t *param) @@ -41,6 +42,39 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param) } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +void SMC_PreEnterStopModes(void) +{ + flash_prefetch_speculation_status_t speculationStatus = + { + kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ + kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ + }; + + __disable_irq(); + __ISB(); + + /* + * Before enter stop modes, the flash cache prefetch should be disabled. + * Otherwise the prefetch might be interrupted by stop, then the data and + * and instruction from flash are wrong. + */ + FLASH_PflashSetPrefetchSpeculation(&speculationStatus); +} + +void SMC_PostExitStopModes(void) +{ + flash_prefetch_speculation_status_t speculationStatus = + { + kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ + kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ + }; + + FLASH_PflashSetPrefetchSpeculation(&speculationStatus); + + __enable_irq(); + __ISB(); +} + status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; @@ -73,7 +107,9 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } @@ -101,7 +137,9 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter Stop mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) @@ -148,16 +186,12 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base status_t SMC_SetPowerModeVlpw(SMC_Type *base) { - /* Power mode transaction to VLPW can only happen in VLPR mode */ - if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base)) - { - return kStatus_Fail; - } - /* configure VLPW mode */ /* Set the SLEEPDEEP bit to enable deep sleep mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } @@ -177,7 +211,9 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter VLPS mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) @@ -231,7 +267,9 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter LLS mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) @@ -345,7 +383,9 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; + __DSB(); __WFI(); + __ISB(); /* check whether the power mode enter LLS mode succeed */ if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h index 5149f87e346..168ce835013 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -36,7 +36,6 @@ /*! @addtogroup smc */ /*! @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -44,8 +43,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.1. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief SMC driver version 2.0.3. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ /*! @@ -54,14 +53,14 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) @@ -107,10 +106,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -120,12 +119,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -155,7 +154,7 @@ typedef enum _smc_partial_stop_mode } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -190,7 +189,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -205,7 +204,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -242,10 +241,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -257,10 +256,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -274,7 +273,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -289,13 +288,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -306,7 +305,45 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +static inline void SMC_PreEnterWaitModes(void) +{ + __disable_irq(); + __ISB(); +} + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +static inline void SMC_PostExitWaitModes(void) +{ + __enable_irq(); + __ISB(); +} + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -315,7 +352,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -324,7 +361,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -332,7 +369,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -342,7 +379,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -351,7 +388,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -360,7 +397,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -368,7 +405,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -379,7 +416,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -388,7 +425,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -399,7 +436,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c new file mode 100755 index 00000000000..b89a7b20e4e --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_sysmpu.h" + +/******************************************************************************* + * Variables + ******************************************************************************/ + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +const clock_ip_name_t g_sysmpuClock[FSL_FEATURE_SOC_SYSMPU_COUNT] = SYSMPU_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/******************************************************************************* + * Codes + ******************************************************************************/ + +void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config) +{ + assert(config); + uint8_t count; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Un-gate SYSMPU clock */ + CLOCK_EnableClock(g_sysmpuClock[0]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Initializes the regions. */ + for (count = 1; count < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT; count++) + { + base->WORD[count][3] = 0; /* VLD/VID+PID. */ + base->WORD[count][0] = 0; /* Start address. */ + base->WORD[count][1] = 0; /* End address. */ + base->WORD[count][2] = 0; /* Access rights. */ + base->RGDAAC[count] = 0; /* Alternate access rights. */ + } + + /* SYSMPU configure. */ + while (config) + { + SYSMPU_SetRegionConfig(base, &(config->regionConfig)); + config = config->next; + } + /* Enable SYSMPU. */ + SYSMPU_Enable(base, true); +} + +void SYSMPU_Deinit(SYSMPU_Type *base) +{ + /* Disable SYSMPU. */ + SYSMPU_Enable(base, false); + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Gate the clock. */ + CLOCK_DisableClock(g_sysmpuClock[0]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform) +{ + assert(hardwareInform); + + uint32_t cesReg = base->CESR; + + hardwareInform->hardwareRevisionLevel = (cesReg & SYSMPU_CESR_HRL_MASK) >> SYSMPU_CESR_HRL_SHIFT; + hardwareInform->slavePortsNumbers = (cesReg & SYSMPU_CESR_NSP_MASK) >> SYSMPU_CESR_NSP_SHIFT; + hardwareInform->regionsNumbers = (sysmpu_region_total_num_t)((cesReg & SYSMPU_CESR_NRGD_MASK) >> SYSMPU_CESR_NRGD_SHIFT); +} + +void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig) +{ + assert(regionConfig); + assert(regionConfig->regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + + uint32_t wordReg = 0; + uint8_t msPortNum; + uint8_t regNumber = regionConfig->regionNum; + + /* The start and end address of the region descriptor. */ + base->WORD[regNumber][0] = regionConfig->startAddress; + base->WORD[regNumber][1] = regionConfig->endAddress; + + /* Set the privilege rights for master 0 ~ master 3. */ + for (msPortNum = 0; msPortNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum++) + { + wordReg |= SYSMPU_REGION_RWXRIGHTS_MASTER( + msPortNum, (((uint32_t)regionConfig->accessRights1[msPortNum].superAccessRights << 3U) | + (uint32_t)regionConfig->accessRights1[msPortNum].userAccessRights)); + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + wordReg |= + SYSMPU_REGION_RWXRIGHTS_MASTER_PE(msPortNum, regionConfig->accessRights1[msPortNum].processIdentifierEnable); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + } + +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT + /* Set the normal read write rights for master 4 ~ master 7. */ + for (msPortNum = SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum < FSL_FEATURE_SYSMPU_MASTER_COUNT; + msPortNum++) + { + wordReg |= SYSMPU_REGION_RWRIGHTS_MASTER(msPortNum, + ((uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].readEnable << 1U | + (uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].writeEnable)); + } +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT */ + + /* Set region descriptor access rights. */ + base->WORD[regNumber][2] = wordReg; + + wordReg = SYSMPU_WORD_VLD(1); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + wordReg |= SYSMPU_WORD_PID(regionConfig->processIdentifier) | SYSMPU_WORD_PIDMASK(regionConfig->processIdMask); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + + base->WORD[regNumber][3] = wordReg; +} + +void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr) +{ + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + + base->WORD[regionNum][0] = startAddr; + base->WORD[regionNum][1] = endAddr; +} + +void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwxrights_master_access_control_t *accessRights) +{ + assert(accessRights); + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + assert(masterNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT); + + uint32_t mask = SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(masterNum); + uint32_t right = base->RGDAAC[regionNum]; + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + mask |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(masterNum); +#endif + + /* Build rights control value. */ + right &= ~mask; + right |= SYSMPU_REGION_RWXRIGHTS_MASTER( + masterNum, ((uint32_t)(accessRights->superAccessRights << 3U) | accessRights->userAccessRights)); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + right |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE(masterNum, accessRights->processIdentifierEnable); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + + /* Set low master region access rights. */ + base->RGDAAC[regionNum] = right; +} + +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 +void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwrights_master_access_control_t *accessRights) +{ + assert(accessRights); + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + assert(masterNum >= SYSMPU_MASTER_RWATTRIBUTE_START_PORT); + assert(masterNum <= (FSL_FEATURE_SYSMPU_MASTER_COUNT - 1)); + + uint32_t mask = SYSMPU_REGION_RWRIGHTS_MASTER_MASK(masterNum); + uint32_t right = base->RGDAAC[regionNum]; + + /* Build rights control value. */ + right &= ~mask; + right |= + SYSMPU_REGION_RWRIGHTS_MASTER(masterNum, (((uint32_t)accessRights->readEnable << 1U) | accessRights->writeEnable)); + /* Set low master region access rights. */ + base->RGDAAC[regionNum] = right; +} +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */ + +bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum) +{ + uint8_t sperr; + + sperr = ((base->CESR & SYSMPU_CESR_SPERR_MASK) >> SYSMPU_CESR_SPERR_SHIFT) & (0x1U << (FSL_FEATURE_SYSMPU_SLAVE_COUNT - slaveNum - 1)); + + return (sperr != 0) ? true : false; +} + +void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform) +{ + assert(errInform); + + uint16_t value; + uint32_t cesReg; + + /* Error address. */ + errInform->address = base->SP[slaveNum].EAR; + + /* Error detail information. */ + value = (base->SP[slaveNum].EDR & SYSMPU_EDR_EACD_MASK) >> SYSMPU_EDR_EACD_SHIFT; + if (!value) + { + errInform->accessControl = kSYSMPU_NoRegionHit; + } + else if (!(value & (uint16_t)(value - 1))) + { + errInform->accessControl = kSYSMPU_NoneOverlappRegion; + } + else + { + errInform->accessControl = kSYSMPU_OverlappRegion; + } + + value = base->SP[slaveNum].EDR; + errInform->master = (uint32_t)((value & SYSMPU_EDR_EMN_MASK) >> SYSMPU_EDR_EMN_SHIFT); + errInform->attributes = (sysmpu_err_attributes_t)((value & SYSMPU_EDR_EATTR_MASK) >> SYSMPU_EDR_EATTR_SHIFT); + errInform->accessType = (sysmpu_err_access_type_t)((value & SYSMPU_EDR_ERW_MASK) >> SYSMPU_EDR_ERW_SHIFT); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + errInform->processorIdentification = (uint8_t)((value & SYSMPU_EDR_EPID_MASK) >> SYSMPU_EDR_EPID_SHIFT); +#endif + + /* Clears error slave port bit. */ + cesReg = (base->CESR & ~SYSMPU_CESR_SPERR_MASK) | ((0x1U << (FSL_FEATURE_SYSMPU_SLAVE_COUNT - slaveNum - 1)) << SYSMPU_CESR_SPERR_SHIFT); + base->CESR = cesReg; +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h new file mode 100755 index 00000000000..6341a31e9d1 --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sysmpu.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_SYSMPU_H_ +#define _FSL_SYSMPU_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup sysmpu + * @{ + */ + + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief SYSMPU driver version 2.2.0. */ +#define FSL_SYSMPU_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*@}*/ + +/*! @brief define the start master port with read and write attributes. */ +#define SYSMPU_MASTER_RWATTRIBUTE_START_PORT (4) + +/*! @brief SYSMPU the bit shift for masters with privilege rights: read write and execute. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n) (n * 6) + +/*! @brief SYSMPU masters with read, write and execute rights bit mask. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(n) (0x1Fu << SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n)) + +/*! @brief SYSMPU masters with read, write and execute rights bit width. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_WIDTH 5 + +/*! @brief SYSMPU masters with read, write and execute rights priority setting. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n))) & SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(n)) + +/*! @brief SYSMPU masters with read, write and execute rights process enable bit shift. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n) (n * 6 + SYSMPU_REGION_RWXRIGHTS_MASTER_WIDTH) + +/*! @brief SYSMPU masters with read, write and execute rights process enable bit mask. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(n) (0x1u << SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n)) + +/*! @brief SYSMPU masters with read, write and execute rights process enable setting. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n))) & SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(n)) + +/*! @brief SYSMPU masters with normal read write permission bit shift. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n) ((n - SYSMPU_MASTER_RWATTRIBUTE_START_PORT) * 2 + 24) + +/*! @brief SYSMPU masters with normal read write rights bit mask. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER_MASK(n) (0x3u << SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n)) + +/*! @brief SYSMPU masters with normal read write rights priority setting. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n))) & SYSMPU_REGION_RWRIGHTS_MASTER_MASK(n)) + + +/*! @brief Describes the number of SYSMPU regions. */ +typedef enum _sysmpu_region_total_num +{ + kSYSMPU_8Regions = 0x0U, /*!< SYSMPU supports 8 regions. */ + kSYSMPU_12Regions = 0x1U, /*!< SYSMPU supports 12 regions. */ + kSYSMPU_16Regions = 0x2U /*!< SYSMPU supports 16 regions. */ +} sysmpu_region_total_num_t; + +/*! @brief SYSMPU slave port number. */ +typedef enum _sysmpu_slave +{ + kSYSMPU_Slave0 = 0U, /*!< SYSMPU slave port 0. */ + kSYSMPU_Slave1 = 1U, /*!< SYSMPU slave port 1. */ + kSYSMPU_Slave2 = 2U, /*!< SYSMPU slave port 2. */ + kSYSMPU_Slave3 = 3U, /*!< SYSMPU slave port 3. */ + kSYSMPU_Slave4 = 4U, /*!< SYSMPU slave port 4. */ +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 5 + kSYSMPU_Slave5 = 5U, /*!< SYSMPU slave port 5. */ +#endif +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 6 + kSYSMPU_Slave6 = 6U, /*!< SYSMPU slave port 6. */ +#endif +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 7 + kSYSMPU_Slave7 = 7U, /*!< SYSMPU slave port 7. */ +#endif +} sysmpu_slave_t; + +/*! @brief SYSMPU error access control detail. */ +typedef enum _sysmpu_err_access_control +{ + kSYSMPU_NoRegionHit = 0U, /*!< No region hit error. */ + kSYSMPU_NoneOverlappRegion = 1U, /*!< Access single region error. */ + kSYSMPU_OverlappRegion = 2U /*!< Access overlapping region error. */ +} sysmpu_err_access_control_t; + +/*! @brief SYSMPU error access type. */ +typedef enum _sysmpu_err_access_type +{ + kSYSMPU_ErrTypeRead = 0U, /*!< SYSMPU error access type --- read. */ + kSYSMPU_ErrTypeWrite = 1U /*!< SYSMPU error access type --- write. */ +} sysmpu_err_access_type_t; + +/*! @brief SYSMPU access error attributes.*/ +typedef enum _sysmpu_err_attributes +{ + kSYSMPU_InstructionAccessInUserMode = 0U, /*!< Access instruction error in user mode. */ + kSYSMPU_DataAccessInUserMode = 1U, /*!< Access data error in user mode. */ + kSYSMPU_InstructionAccessInSupervisorMode = 2U, /*!< Access instruction error in supervisor mode. */ + kSYSMPU_DataAccessInSupervisorMode = 3U /*!< Access data error in supervisor mode. */ +} sysmpu_err_attributes_t; + +/*! @brief SYSMPU access rights in supervisor mode for bus master 0 ~ 3. */ +typedef enum _sysmpu_supervisor_access_rights +{ + kSYSMPU_SupervisorReadWriteExecute = 0U, /*!< Read write and execute operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorReadExecute = 1U, /*!< Read and execute operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorReadWrite = 2U, /*!< Read write operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorEqualToUsermode = 3U /*!< Access permission equal to user mode. */ +} sysmpu_supervisor_access_rights_t; + +/*! @brief SYSMPU access rights in user mode for bus master 0 ~ 3. */ +typedef enum _sysmpu_user_access_rights +{ + kSYSMPU_UserNoAccessRights = 0U, /*!< No access allowed in user mode. */ + kSYSMPU_UserExecute = 1U, /*!< Execute operation is allowed in user mode. */ + kSYSMPU_UserWrite = 2U, /*!< Write operation is allowed in user mode. */ + kSYSMPU_UserWriteExecute = 3U, /*!< Write and execute operations are allowed in user mode. */ + kSYSMPU_UserRead = 4U, /*!< Read is allowed in user mode. */ + kSYSMPU_UserReadExecute = 5U, /*!< Read and execute operations are allowed in user mode. */ + kSYSMPU_UserReadWrite = 6U, /*!< Read and write operations are allowed in user mode. */ + kSYSMPU_UserReadWriteExecute = 7U /*!< Read write and execute operations are allowed in user mode. */ +} sysmpu_user_access_rights_t; + +/*! @brief SYSMPU hardware basic information. */ +typedef struct _sysmpu_hardware_info +{ + uint8_t hardwareRevisionLevel; /*!< Specifies the SYSMPU's hardware and definition reversion level. */ + uint8_t slavePortsNumbers; /*!< Specifies the number of slave ports connected to SYSMPU. */ + sysmpu_region_total_num_t regionsNumbers; /*!< Indicates the number of region descriptors implemented. */ +} sysmpu_hardware_info_t; + +/*! @brief SYSMPU detail error access information. */ +typedef struct _sysmpu_access_err_info +{ + uint32_t master; /*!< Access error master. */ + sysmpu_err_attributes_t attributes; /*!< Access error attributes. */ + sysmpu_err_access_type_t accessType; /*!< Access error type. */ + sysmpu_err_access_control_t accessControl; /*!< Access error control. */ + uint32_t address; /*!< Access error address. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + uint8_t processorIdentification; /*!< Access error processor identification. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_access_err_info_t; + +/*! @brief SYSMPU read/write/execute rights control for bus master 0 ~ 3. */ +typedef struct _sysmpu_rwxrights_master_access_control +{ + sysmpu_supervisor_access_rights_t superAccessRights; /*!< Master access rights in supervisor mode. */ + sysmpu_user_access_rights_t userAccessRights; /*!< Master access rights in user mode. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + bool processIdentifierEnable; /*!< Enables or disables process identifier. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_rwxrights_master_access_control_t; + +/*! @brief SYSMPU read/write access control for bus master 4 ~ 7. */ +typedef struct _sysmpu_rwrights_master_access_control +{ + bool writeEnable; /*!< Enables or disables write permission. */ + bool readEnable; /*!< Enables or disables read permission. */ +} sysmpu_rwrights_master_access_control_t; + +/*! + * @brief SYSMPU region configuration structure. + * + * This structure is used to configure the regionNum region. + * The accessRights1[0] ~ accessRights1[3] are used to configure the bus master + * 0 ~ 3 with the privilege rights setting. The accessRights2[0] ~ accessRights2[3] + * are used to configure the high master 4 ~ 7 with the normal read write permission. + * The master port assignment is the chip configuration. Normally, the core is the + * master 0, debugger is the master 1. + * Note that the SYSMPU assigns a priority scheme where the debugger is treated as the highest + * priority master followed by the core and then all the remaining masters. + * SYSMPU protection does not allow writes from the core to affect the "regionNum 0" start + * and end address nor the permissions associated with the debugger. It can only write + * the permission fields associated with the other masters. This protection guarantees that + * the debugger always has access to the entire address space and those rights can't + * be changed by the core or any other bus master. Prepare + * the region configuration when regionNum is 0. + */ +typedef struct _sysmpu_region_config +{ + uint32_t regionNum; /*!< SYSMPU region number, range form 0 ~ FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. */ + uint32_t startAddress; /*!< Memory region start address. Note: bit0 ~ bit4 always be marked as 0 by SYSMPU. The actual + start address is 0-modulo-32 byte address. */ + uint32_t endAddress; /*!< Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU. The actual end + address is 31-modulo-32 byte address. */ + sysmpu_rwxrights_master_access_control_t accessRights1[4]; /*!< Masters with read, write and execute rights setting. */ + sysmpu_rwrights_master_access_control_t accessRights2[4]; /*!< Masters with normal read write rights setting. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + uint8_t processIdentifier; /*!< Process identifier used when "processIdentifierEnable" set with true. */ + uint8_t + processIdMask; /*!< Process identifier mask. The setting bit will ignore the same bit in process identifier. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_region_config_t; + +/*! + * @brief The configuration structure for the SYSMPU initialization. + * + * This structure is used when calling the SYSMPU_Init function. + */ +typedef struct _sysmpu_config +{ + sysmpu_region_config_t regionConfig; /*!< Region access permission. */ + struct _sysmpu_config *next; /*!< Pointer to the next structure. */ +} sysmpu_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initializes the SYSMPU with the user configuration structure. + * + * This function configures the SYSMPU module with the user-defined configuration. + * + * @param base SYSMPU peripheral base address. + * @param config The pointer to the configuration structure. + */ +void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config); + +/*! + * @brief Deinitializes the SYSMPU regions. + * + * @param base SYSMPU peripheral base address. + */ +void SYSMPU_Deinit(SYSMPU_Type *base); + +/* @}*/ + +/*! + * @name Basic Control Operations + * @{ + */ + +/*! + * @brief Enables/disables the SYSMPU globally. + * + * Call this API to enable or disable the SYSMPU module. + * + * @param base SYSMPU peripheral base address. + * @param enable True enable SYSMPU, false disable SYSMPU. + */ +static inline void SYSMPU_Enable(SYSMPU_Type *base, bool enable) +{ + if (enable) + { + /* Enable the SYSMPU globally. */ + base->CESR |= SYSMPU_CESR_VLD_MASK; + } + else + { /* Disable the SYSMPU globally. */ + base->CESR &= ~SYSMPU_CESR_VLD_MASK; + } +} + +/*! + * @brief Enables/disables the SYSMPU for a special region. + * + * When SYSMPU is enabled, call this API to disable an unused region + * of an enabled SYSMPU. Call this API to minimize the power dissipation. + * + * @param base SYSMPU peripheral base address. + * @param number SYSMPU region number. + * @param enable True enable the special region SYSMPU, false disable the special region SYSMPU. + */ +static inline void SYSMPU_RegionEnable(SYSMPU_Type *base, uint32_t number, bool enable) +{ + if (enable) + { + /* Enable the #number region SYSMPU. */ + base->WORD[number][3] |= SYSMPU_WORD_VLD_MASK; + } + else + { /* Disable the #number region SYSMPU. */ + base->WORD[number][3] &= ~SYSMPU_WORD_VLD_MASK; + } +} + +/*! + * @brief Gets the SYSMPU basic hardware information. + * + * @param base SYSMPU peripheral base address. + * @param hardwareInform The pointer to the SYSMPU hardware information structure. See "sysmpu_hardware_info_t". + */ +void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform); + +/*! + * @brief Sets the SYSMPU region. + * + * Note: Due to the SYSMPU protection, the region number 0 does not allow writes from + * core to affect the start and end address nor the permissions associated with + * the debugger. It can only write the permission fields associated + * with the other masters. + * + * @param base SYSMPU peripheral base address. + * @param regionConfig The pointer to the SYSMPU user configuration structure. See "sysmpu_region_config_t". + */ +void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig); + +/*! + * @brief Sets the region start and end address. + * + * Memory region start address. Note: bit0 ~ bit4 is always marked as 0 by SYSMPU. + * The actual start address by SYSMPU is 0-modulo-32 byte address. + * Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU. + * The end address used by the SYSMPU is 31-modulo-32 byte address. + * Note: Due to the SYSMPU protection, the startAddr and endAddr can't be + * changed by the core when regionNum is 0. + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. The range is from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param startAddr Region start address. + * @param endAddr Region end address. + */ +void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr); + +/*! + * @brief Sets the SYSMPU region access rights for masters with read, write, and execute rights. + * The SYSMPU access rights depend on two board classifications of bus masters. + * The privilege rights masters and the normal rights masters. + * The privilege rights masters have the read, write, and execute access rights. + * Except the normal read and write rights, the execute rights are also + * allowed for these masters. The privilege rights masters normally range from + * bus masters 0 - 3. However, the maximum master number is device-specific. + * See the "SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX". + * The normal rights masters access rights control see + * "SYSMPU_SetRegionRwMasterAccessRights()". + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. Should range from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param masterNum SYSMPU bus master number. Should range from 0 to + * SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX. + * @param accessRights The pointer to the SYSMPU access rights configuration. See "sysmpu_rwxrights_master_access_control_t". + */ +void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwxrights_master_access_control_t *accessRights); +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 +/*! + * @brief Sets the SYSMPU region access rights for masters with read and write rights. + * The SYSMPU access rights depend on two board classifications of bus masters. + * The privilege rights masters and the normal rights masters. + * The normal rights masters only have the read and write access permissions. + * The privilege rights access control see "SYSMPU_SetRegionRwxMasterAccessRights". + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. The range is from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param masterNum SYSMPU bus master number. Should range from SYSMPU_MASTER_RWATTRIBUTE_START_PORT + * to ~ FSL_FEATURE_SYSMPU_MASTER_COUNT - 1. + * @param accessRights The pointer to the SYSMPU access rights configuration. See "sysmpu_rwrights_master_access_control_t". + */ +void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwrights_master_access_control_t *accessRights); +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */ +/*! + * @brief Gets the numbers of slave ports where errors occur. + * + * @param base SYSMPU peripheral base address. + * @param slaveNum SYSMPU slave port number. + * @return The slave ports error status. + * true - error happens in this slave port. + * false - error didn't happen in this slave port. + */ +bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum); + +/*! + * @brief Gets the SYSMPU detailed error access information. + * + * @param base SYSMPU peripheral base address. + * @param slaveNum SYSMPU slave port number. + * @param errInform The pointer to the SYSMPU access error information. See "sysmpu_access_err_info_t". + */ +void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_SYSMPU_H_ */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c index 079c06df586..9a390a2be47 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -53,8 +53,10 @@ static uint32_t TPM_GetInstance(TPM_Type *base); /*! @brief Pointers to TPM bases for each instance. */ static TPM_Type *const s_tpmBases[] = TPM_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to TPM clocks for each instance. */ static const clock_ip_name_t s_tpmClocks[] = TPM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -82,8 +84,10 @@ void TPM_Init(TPM_Type *base, const tpm_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the module clock */ CLOCK_EnableClock(s_tpmClocks[TPM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL /* TPM reset is available on certain SoC's */ @@ -118,8 +122,10 @@ void TPM_Deinit(TPM_Type *base) { /* Stop the counter */ base->SC &= ~TPM_SC_CMOD_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the TPM clock */ CLOCK_DisableClock(s_tpmClocks[TPM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void TPM_GetDefaultConfig(tpm_config_t *config) @@ -162,6 +168,12 @@ status_t TPM_SetupPwm(TPM_Type *base, assert(pwmFreq_Hz); assert(numOfChnls); assert(srcClock_Hz); +#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE + if(mode == kTPM_CombinedPwm) + { + assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base)); + } +#endif uint32_t mod; uint32_t tpmClock = (srcClock_Hz / (1U << (base->SC & TPM_SC_PS_MASK))); @@ -169,8 +181,12 @@ status_t TPM_SetupPwm(TPM_Type *base, uint8_t i; #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - /* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/ - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) + { + /* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/ + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } #endif switch (mode) @@ -351,6 +367,12 @@ void TPM_UpdatePwmDutycycle(TPM_Type *base, uint8_t dutyCyclePercent) { assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); +#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE + if(currentPwmMode == kTPM_CombinedPwm) + { + assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base)); + } +#endif uint16_t cnv, mod; @@ -401,7 +423,7 @@ void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_ /* Wait till mode change to disable channel is acknowledged */ while ((base->CONTROLS[chnlNumber].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -424,16 +446,24 @@ void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capt assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - /* Clear quadrature Decoder mode for channel 0 or 1*/ - if ((chnlNumber == 0) || (chnlNumber == 1)) + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) { - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* Clear quadrature Decoder mode for channel 0 or 1*/ + if ((chnlNumber == 0) || (chnlNumber == 1)) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } } #endif #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE - /* Clear the combine bit for chnlNumber */ - base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2)); + /* The TPM's COMBINE register required to be effective */ + if( FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base) ) + { + /* Clear the combine bit for chnlNumber */ + base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2)); + } #endif /* When switching mode, disable channel first */ @@ -464,10 +494,14 @@ void TPM_SetupOutputCompare(TPM_Type *base, assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - /* Clear quadrature Decoder mode for channel 0 or 1 */ - if ((chnlNumber == 0) || (chnlNumber == 1)) + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) { - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* Clear quadrature Decoder mode for channel 0 or 1 */ + if ((chnlNumber == 0) || (chnlNumber == 1)) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } } #endif @@ -502,13 +536,19 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, { assert(edgeParam); assert(chnlPairNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2); + assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base)); uint32_t reg; -/* Clear quadrature Decoder mode for channel 0 or 1*/ + #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL - if (chnlPairNumber == 0) + /* The TPM's QDCTRL register required to be effective */ + if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) ) { - base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + /* Clear quadrature Decoder mode for channel 0 or 1*/ + if (chnlPairNumber == 0) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } } #endif @@ -518,7 +558,7 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, /* Wait till mode change to disable channel is acknowledged */ while ((base->CONTROLS[chnlPairNumber * 2].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -527,7 +567,7 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, /* Wait till mode change to disable channel is acknowledged */ while ((base->CONTROLS[chnlPairNumber * 2 + 1].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -589,6 +629,7 @@ void TPM_SetupQuadDecode(TPM_Type *base, { assert(phaseAParams); assert(phaseBParams); + assert(FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base)); base->CONTROLS[0].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h index a15e44c1fbf..a1694b37d32 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tpm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,8 +37,6 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -525,6 +523,47 @@ static inline void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask) /*! @}*/ +/*! + * @name Read and write the timer period + * @{ + */ + +/*! + * @brief Sets the timer period in units of ticks. + * + * Timers counts from 0 until it equals the count value set here. The count value is written to + * the MOD register. + * + * @note + * 1. This API allows the user to use the TPM module as a timer. Do not mix usage + * of this API with TPM's PWM setup API's. + * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks. + * + * @param base TPM peripheral base address + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. + */ +static inline void TPM_SetTimerPeriod(TPM_Type *base, uint32_t ticks) +{ + base->MOD = ticks; +} + +/*! + * @brief Reads the current timer counting value. + * + * This function returns the real-time timer counting value in a range from 0 to a + * timer period. + * + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. + * + * @param base TPM peripheral base address + * + * @return The current counter value in ticks + */ +static inline uint32_t TPM_GetCurrentTimerCount(TPM_Type *base) +{ + return (uint32_t)((base->CNT & TPM_CNT_COUNT_MASK) >> TPM_CNT_COUNT_SHIFT); +} + /*! * @name Timer Start and Stop * @{ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c index 6acb64e7e0b..c299c90f633 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -36,7 +36,9 @@ void TSI_Init(TSI_Type *base, const tsi_config_t *config) bool is_module_enabled = false; bool is_int_enabled = false; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Tsi0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ if (base->GENCS & TSI_GENCS_TSIEN_MASK) { is_module_enabled = true; @@ -47,18 +49,31 @@ void TSI_Init(TSI_Type *base, const tsi_config_t *config) is_int_enabled = true; TSI_DisableInterrupts(base, kTSI_GlobalInterruptEnable); } - - TSI_SetHighThreshold(base, config->thresh); - TSI_SetLowThreshold(base, config->thresl); - TSI_SetElectrodeOSCPrescaler(base, config->prescaler); - TSI_SetReferenceChargeCurrent(base, config->refchrg); - TSI_SetElectrodeChargeCurrent(base, config->extchrg); - TSI_SetNumberOfScans(base, config->nscn); - TSI_SetAnalogMode(base, config->mode); - TSI_SetOscVoltageRails(base, config->dvolt); - TSI_SetElectrodeSeriesResistor(base, config->resistor); - TSI_SetFilterBits(base, config->filter); - + + if(config->mode == kTSI_AnalogModeSel_Capacitive) + { + TSI_SetHighThreshold(base, config->thresh); + TSI_SetLowThreshold(base, config->thresl); + TSI_SetElectrodeOSCPrescaler(base, config->prescaler); + TSI_SetReferenceChargeCurrent(base, config->refchrg); + TSI_SetElectrodeChargeCurrent(base, config->extchrg); + TSI_SetNumberOfScans(base, config->nscn); + TSI_SetAnalogMode(base, config->mode); + TSI_SetOscVoltageRails(base, config->dvolt); + } + else /* For noise modes */ + { + TSI_SetHighThreshold(base, config->thresh); + TSI_SetLowThreshold(base, config->thresl); + TSI_SetElectrodeOSCPrescaler(base, config->prescaler); + TSI_SetReferenceChargeCurrent(base, config->refchrg); + TSI_SetNumberOfScans(base, config->nscn); + TSI_SetAnalogMode(base, config->mode); + TSI_SetOscVoltageRails(base, config->dvolt); + TSI_SetElectrodeSeriesResistor(base, config->resistor); + TSI_SetFilterBits(base, config->filter); + } + if (is_module_enabled) { TSI_EnableModule(base, true); @@ -74,7 +89,9 @@ void TSI_Deinit(TSI_Type *base) base->GENCS = 0U; base->DATA = 0U; base->TSHD = 0U; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(kCLOCK_Tsi0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig) @@ -82,13 +99,11 @@ void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig) userConfig->thresh = 0U; userConfig->thresl = 0U; userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_5time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_3; } void TSI_GetLowPowerModeDefaultConfig(tsi_config_t *userConfig) @@ -96,13 +111,11 @@ void TSI_GetLowPowerModeDefaultConfig(tsi_config_t *userConfig) userConfig->thresh = 400U; userConfig->thresl = 0U; userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_5time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_3; } void TSI_Calibrate(TSI_Type *base, tsi_calibration_data_t *calBuff) @@ -135,44 +148,56 @@ void TSI_Calibrate(TSI_Type *base, tsi_calibration_data_t *calBuff) void TSI_EnableInterrupts(TSI_Type *base, uint32_t mask) { + uint32_t regValue = base->GENCS & (~ALL_FLAGS_MASK); + if (mask & kTSI_GlobalInterruptEnable) { - base->GENCS |= TSI_GENCS_TSIIEN_MASK; + regValue |= TSI_GENCS_TSIIEN_MASK; } if (mask & kTSI_OutOfRangeInterruptEnable) { - base->GENCS &= ~TSI_GENCS_ESOR_MASK; + regValue &= (~TSI_GENCS_ESOR_MASK); } if (mask & kTSI_EndOfScanInterruptEnable) { - base->GENCS |= TSI_GENCS_ESOR_MASK; + regValue |= TSI_GENCS_ESOR_MASK; } + + base->GENCS = regValue; /* write value to register */ } void TSI_DisableInterrupts(TSI_Type *base, uint32_t mask) { + uint32_t regValue = base->GENCS & (~ALL_FLAGS_MASK); + if (mask & kTSI_GlobalInterruptEnable) { - base->GENCS &= ~TSI_GENCS_TSIIEN_MASK; + regValue &= (~TSI_GENCS_TSIIEN_MASK); } if (mask & kTSI_OutOfRangeInterruptEnable) { - base->GENCS |= TSI_GENCS_ESOR_MASK; + regValue |= TSI_GENCS_ESOR_MASK; } if (mask & kTSI_EndOfScanInterruptEnable) { - base->GENCS &= ~TSI_GENCS_ESOR_MASK; + regValue &= (~TSI_GENCS_ESOR_MASK); } + + base->GENCS = regValue; /* write value to register */ } void TSI_ClearStatusFlags(TSI_Type *base, uint32_t mask) { + uint32_t regValue = base->GENCS & (~ALL_FLAGS_MASK); + if (mask & kTSI_EndOfScanFlag) { - base->GENCS = (base->GENCS & ~(TSI_GENCS_EOSF_MASK | TSI_GENCS_OUTRGF_MASK)) | TSI_GENCS_EOSF_MASK; + regValue |= TSI_GENCS_EOSF_MASK; } if (mask & kTSI_OutOfRangeFlag) { - base->GENCS = (base->GENCS & ~(TSI_GENCS_EOSF_MASK | TSI_GENCS_OUTRGF_MASK)) | TSI_GENCS_OUTRGF_MASK; + regValue |= TSI_GENCS_OUTRGF_MASK; } + + base->GENCS = regValue; /* write value to register */ } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h index d389a4d505f..3c204807db6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_tsi_v4.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,10 +44,13 @@ /*! @name Driver version */ /*@{*/ -/*! @brief TSI driver version 2.0.0. */ -#define FSL_TSI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief TSI driver version */ +#define FSL_TSI_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*@}*/ +/*! @brief TSI status flags macro collection */ +#define ALL_FLAGS_MASK (TSI_GENCS_EOSF_MASK | TSI_GENCS_OUTRGF_MASK) + /*! @brief resistor bit shift in EXTCHRG bit-field */ #define TSI_V4_EXTCHRG_RESISTOR_BIT_SHIFT TSI_GENCS_EXTCHRG_SHIFT @@ -57,11 +59,11 @@ /*! @brief macro of clearing the resistor bit in EXTCHRG bit-field */ #define TSI_V4_EXTCHRG_RESISTOR_BIT_CLEAR \ - ((uint32_t)((~TSI_GENCS_EXTCHRG_MASK) | (3U << TSI_V4_EXTCHRG_FILTER_BITS_SHIFT))) + ((uint32_t)((~(ALL_FLAGS_MASK | TSI_GENCS_EXTCHRG_MASK)) | (3U << TSI_V4_EXTCHRG_FILTER_BITS_SHIFT))) /*! @brief macro of clearing the filter bits in EXTCHRG bit-field */ #define TSI_V4_EXTCHRG_FILTER_BITS_CLEAR \ - ((uint32_t)((~TSI_GENCS_EXTCHRG_MASK) | (1U << TSI_V4_EXTCHRG_RESISTOR_BIT_SHIFT))) + ((uint32_t)((~(ALL_FLAGS_MASK | TSI_GENCS_EXTCHRG_MASK)) | (1U << TSI_V4_EXTCHRG_RESISTOR_BIT_SHIFT))) /*! * @brief TSI number of scan intervals for each electrode. @@ -286,13 +288,11 @@ void TSI_Deinit(TSI_Type *base); * The user configure is set to these values: * @code userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_10time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_1; userConfig->thresh = 0U; userConfig->thresl = 0U; @endcode @@ -308,13 +308,11 @@ void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig); * The user configure is set to these values: * @code userConfig->prescaler = kTSI_ElecOscPrescaler_2div; - userConfig->extchrg = kTSI_ExtOscChargeCurrent_4uA; + userConfig->extchrg = kTSI_ExtOscChargeCurrent_500nA; userConfig->refchrg = kTSI_RefOscChargeCurrent_4uA; userConfig->nscn = kTSI_ConsecutiveScansNumber_10time; userConfig->mode = kTSI_AnalogModeSel_Capacitive; userConfig->dvolt = kTSI_OscVolRailsOption_0; - userConfig->resistor = kTSI_SeriesResistance_32k; - userConfig->filter = kTSI_FilterBits_1; userConfig->thresh = 400U; userConfig->thresl = 0U; @endcode @@ -417,7 +415,7 @@ static inline bool TSI_IsScanInProgress(TSI_Type *base) */ static inline void TSI_SetElectrodeOSCPrescaler(TSI_Type *base, tsi_electrode_osc_prescaler_t prescaler) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_PS_MASK) | (TSI_GENCS_PS(prescaler)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_PS_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_PS(prescaler)); } /*! @@ -429,7 +427,7 @@ static inline void TSI_SetElectrodeOSCPrescaler(TSI_Type *base, tsi_electrode_os */ static inline void TSI_SetNumberOfScans(TSI_Type *base, tsi_n_consecutive_scans_t number) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_NSCN_MASK) | (TSI_GENCS_NSCN(number)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_NSCN_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_NSCN(number)); } /*! @@ -445,11 +443,11 @@ static inline void TSI_EnableModule(TSI_Type *base, bool enable) { if (enable) { - base->GENCS |= TSI_GENCS_TSIEN_MASK; /* Enable module */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_TSIEN_MASK; /* Enable module */ } else { - base->GENCS &= ~TSI_GENCS_TSIEN_MASK; /* Disable module */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_TSIEN_MASK); /* Disable module */ } } @@ -467,11 +465,11 @@ static inline void TSI_EnableLowPower(TSI_Type *base, bool enable) { if (enable) { - base->GENCS |= TSI_GENCS_STPE_MASK; /* Module enabled in low power stop modes */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_STPE_MASK; /* Module enabled in low power stop modes */ } else { - base->GENCS &= ~TSI_GENCS_STPE_MASK; /* Module disabled in low power stop modes */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_STPE_MASK); /* Module disabled in low power stop modes */ } } @@ -488,11 +486,11 @@ static inline void TSI_EnableHardwareTriggerScan(TSI_Type *base, bool enable) { if (enable) { - base->GENCS |= TSI_GENCS_STM_MASK; /* Enable hardware trigger scan */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_STM_MASK; /* Enable hardware trigger scan */ } else { - base->GENCS &= ~TSI_GENCS_STM_MASK; /* Enable software trigger scan */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_STM_MASK); /* Enable software trigger scan */ } } @@ -567,12 +565,12 @@ static inline void TSI_EnableEndOfScanDmaTransferOnly(TSI_Type *base, bool enabl { if (enable) { - base->GENCS |= TSI_GENCS_EOSDMEO_MASK; /* Enable End of Scan DMA transfer request only; */ + base->GENCS = (base->GENCS & ~ALL_FLAGS_MASK) | TSI_GENCS_EOSDMEO_MASK; /* Enable End of Scan DMA transfer request only; */ } else { - base->GENCS &= - ~TSI_GENCS_EOSDMEO_MASK; /* Both End-of-Scan and Out-of-Range can generate DMA transfer request. */ + base->GENCS = + (base->GENCS & ~ALL_FLAGS_MASK) & (~TSI_GENCS_EOSDMEO_MASK); /* Both End-of-Scan and Out-of-Range can generate DMA transfer request. */ } } #endif /* End of (FSL_FEATURE_TSI_HAS_END_OF_SCAN_DMA_ENABLE == 1)*/ @@ -625,7 +623,7 @@ static inline void TSI_SetHighThreshold(TSI_Type *base, uint16_t high_threshold) */ static inline void TSI_SetAnalogMode(TSI_Type *base, tsi_analog_mode_t mode) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_MODE_MASK) | (TSI_GENCS_MODE(mode)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_MODE_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_MODE(mode)); } /*! @@ -648,7 +646,7 @@ static inline uint8_t TSI_GetNoiseModeResult(TSI_Type *base) */ static inline void TSI_SetReferenceChargeCurrent(TSI_Type *base, tsi_reference_osc_charge_current_t current) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_REFCHRG_MASK) | (TSI_GENCS_REFCHRG(current)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_REFCHRG_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_REFCHRG(current)); } /*! @@ -660,7 +658,7 @@ static inline void TSI_SetReferenceChargeCurrent(TSI_Type *base, tsi_reference_o */ static inline void TSI_SetElectrodeChargeCurrent(TSI_Type *base, tsi_external_osc_charge_current_t current) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_EXTCHRG_MASK) | (TSI_GENCS_EXTCHRG(current)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_EXTCHRG_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_EXTCHRG(current)); } /*! @@ -672,7 +670,7 @@ static inline void TSI_SetElectrodeChargeCurrent(TSI_Type *base, tsi_external_os */ static inline void TSI_SetOscVoltageRails(TSI_Type *base, tsi_osc_voltage_rails_t dvolt) { - base->GENCS = ((base->GENCS) & ~TSI_GENCS_DVOLT_MASK) | (TSI_GENCS_DVOLT(dvolt)); + base->GENCS = (base->GENCS & ~(TSI_GENCS_DVOLT_MASK | ALL_FLAGS_MASK)) | (TSI_GENCS_DVOLT(dvolt)); } /*! diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c index b0b92399db4..17d9260027b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,10 +37,12 @@ /* UART transfer state. */ enum _uart_tansfer_states { - kUART_TxIdle, /* TX idle. */ - kUART_TxBusy, /* TX busy. */ - kUART_RxIdle, /* RX idle. */ - kUART_RxBusy /* RX busy. */ + kUART_TxIdle, /* TX idle. */ + kUART_TxBusy, /* TX busy. */ + kUART_RxIdle, /* RX idle. */ + kUART_RxBusy, /* RX busy. */ + kUART_RxFramingError, /* Rx framing error */ + kUART_RxParityError /* Rx parity error */ }; /* Typedef for interrupt handler. */ @@ -138,8 +140,10 @@ static UART_Type *const s_uartBases[] = UART_BASE_PTRS; /* Array of UART IRQ number. */ static const IRQn_Type s_uartIRQ[] = UART_RX_TX_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of UART clock name. */ static const clock_ip_name_t s_uartClock[] = UART_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* UART ISR for transactional APIs. */ static uart_isr_t s_uartIsr; @@ -169,6 +173,8 @@ uint32_t UART_GetInstance(UART_Type *base) static size_t UART_TransferGetRxRingBufferLength(uart_handle_t *handle) { + assert(handle); + size_t size; if (handle->rxRingBufferTail > handle->rxRingBufferHead) @@ -185,6 +191,8 @@ static size_t UART_TransferGetRxRingBufferLength(uart_handle_t *handle) static bool UART_TransferIsRxRingBufferFull(uart_handle_t *handle) { + assert(handle); + bool full; if (UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U)) @@ -199,36 +207,72 @@ static bool UART_TransferIsRxRingBufferFull(uart_handle_t *handle) return full; } -void UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz) +status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz) { assert(config); + assert(config->baudRate_Bps); #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO assert(FSL_FEATURE_UART_FIFO_SIZEn(base) >= config->txFifoWatermark); assert(FSL_FEATURE_UART_FIFO_SIZEn(base) >= config->rxFifoWatermark); #endif - uint16_t sbr; - uint8_t temp; + uint16_t sbr = 0; + uint8_t temp = 0; + uint32_t baudDiff = 0; + + /* Calculate the baud rate modulo divisor, sbr*/ + sbr = srcClock_Hz / (config->baudRate_Bps * 16); + /* set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate */ + if (sbr == 0) + { + sbr = 1; + } +#if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT + /* Determine if a fractional divider is needed to fine tune closer to the + * desired baud, each value of brfa is in 1/32 increments, + * hence the multiply-by-32. */ + uint32_t tempBaud = 0; + + uint16_t brfa = (2 * srcClock_Hz / (config->baudRate_Bps)) - 32 * sbr; + + /* Calculate the baud rate based on the temporary SBR values and BRFA */ + tempBaud = (srcClock_Hz * 2 / ((sbr * 32 + brfa))); + baudDiff = + (tempBaud > config->baudRate_Bps) ? (tempBaud - config->baudRate_Bps) : (config->baudRate_Bps - tempBaud); +#else + /* Calculate the baud rate based on the temporary SBR values */ + baudDiff = (srcClock_Hz / (sbr * 16)) - config->baudRate_Bps; + + /* Select the better value between sbr and (sbr + 1) */ + if (baudDiff > (config->baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))))) + { + baudDiff = config->baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))); + sbr++; + } +#endif + + /* next, check to see if actual baud rate is within 3% of desired baud rate + * based on the calculate SBR value */ + if (baudDiff > ((config->baudRate_Bps / 100) * 3)) + { + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_UART_BaudrateNotSupport; + } + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable uart clock */ CLOCK_EnableClock(s_uartClock[UART_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Disable UART TX RX before setting. */ base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); - /* Calculate the baud rate modulo divisor, sbr*/ - sbr = srcClock_Hz / (config->baudRate_Bps * 16); - /* Write the sbr value to the BDH and BDL registers*/ base->BDH = (base->BDH & ~UART_BDH_SBR_MASK) | (uint8_t)(sbr >> 8); base->BDL = (uint8_t)sbr; #if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT - /* Determine if a fractional divider is needed to fine tune closer to the - * desired baud, each value of brfa is in 1/32 increments, - * hence the multiply-by-32. */ - uint16_t brfa = (32 * srcClock_Hz / (config->baudRate_Bps * 16)) - 32 * sbr; - /* Write the brfa value to the register*/ base->C4 = (base->C4 & ~UART_C4_BRFA_MASK) | (brfa & UART_C4_BRFA_MASK); #endif @@ -274,6 +318,8 @@ void UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_H } base->C2 = temp; + + return kStatus_Success; } void UART_Deinit(UART_Type *base) @@ -292,8 +338,10 @@ void UART_Deinit(UART_Type *base) /* Disable the module. */ base->C2 = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable uart clock */ CLOCK_DisableClock(s_uartClock[UART_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void UART_GetDefaultConfig(uart_config_t *config) @@ -313,61 +361,101 @@ void UART_GetDefaultConfig(uart_config_t *config) config->enableRx = false; } -void UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) +status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) { - uint16_t sbr; - uint8_t oldCtrl; - - /* Store C2 before disable Tx and Rx */ - oldCtrl = base->C2; + assert(baudRate_Bps); - /* Disable UART TX RX before setting. */ - base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); + uint16_t sbr = 0; + uint32_t baudDiff = 0; + uint8_t oldCtrl; /* Calculate the baud rate modulo divisor, sbr*/ sbr = srcClock_Hz / (baudRate_Bps * 16); - - /* Write the sbr value to the BDH and BDL registers*/ - base->BDH = (base->BDH & ~UART_BDH_SBR_MASK) | (uint8_t)(sbr >> 8); - base->BDL = (uint8_t)sbr; - + /* set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate */ + if (sbr == 0) + { + sbr = 1; + } #if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT /* Determine if a fractional divider is needed to fine tune closer to the * desired baud, each value of brfa is in 1/32 increments, * hence the multiply-by-32. */ - uint16_t brfa = (32 * srcClock_Hz / (baudRate_Bps * 16)) - 32 * sbr; + uint32_t tempBaud = 0; - /* Write the brfa value to the register*/ - base->C4 = (base->C4 & ~UART_C4_BRFA_MASK) | (brfa & UART_C4_BRFA_MASK); + uint16_t brfa = (2 * srcClock_Hz / (baudRate_Bps)) - 32 * sbr; + + /* Calculate the baud rate based on the temporary SBR values and BRFA */ + tempBaud = (srcClock_Hz * 2 / ((sbr * 32 + brfa))); + baudDiff = (tempBaud > baudRate_Bps) ? (tempBaud - baudRate_Bps) : (baudRate_Bps - tempBaud); +#else + /* Calculate the baud rate based on the temporary SBR values */ + baudDiff = (srcClock_Hz / (sbr * 16)) - baudRate_Bps; + + /* Select the better value between sbr and (sbr + 1) */ + if (baudDiff > (baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))))) + { + baudDiff = baudRate_Bps - (srcClock_Hz / (16 * (sbr + 1))); + sbr++; + } +#endif + + /* next, check to see if actual baud rate is within 3% of desired baud rate + * based on the calculate SBR value */ + if (baudDiff < ((baudRate_Bps / 100) * 3)) + { + /* Store C2 before disable Tx and Rx */ + oldCtrl = base->C2; + + /* Disable UART TX RX before setting. */ + base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); + + /* Write the sbr value to the BDH and BDL registers*/ + base->BDH = (base->BDH & ~UART_BDH_SBR_MASK) | (uint8_t)(sbr >> 8); + base->BDL = (uint8_t)sbr; + +#if defined(FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT) && FSL_FEATURE_UART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT + /* Write the brfa value to the register*/ + base->C4 = (base->C4 & ~UART_C4_BRFA_MASK) | (brfa & UART_C4_BRFA_MASK); #endif + /* Restore C2. */ + base->C2 = oldCtrl; - /* Restore C2. */ - base->C2 = oldCtrl; + return kStatus_Success; + } + else + { + /* Unacceptable baud rate difference of more than 3%*/ + return kStatus_UART_BaudrateNotSupport; + } } void UART_EnableInterrupts(UART_Type *base, uint32_t mask) { + mask &= kUART_AllInterruptsEnable; + /* The interrupt mask is combined by control bits from several register: ((CFIFO<<24) | (C3<<16) | (C2<<8) |(BDH)) */ - base->BDH |= (mask & 0xFF); - base->C2 |= ((mask >> 8) & 0xFF); - base->C3 |= ((mask >> 16) & 0xFF); + base->BDH |= mask; + base->C2 |= (mask >> 8); + base->C3 |= (mask >> 16); #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - base->CFIFO |= ((mask >> 24) & 0xFF); + base->CFIFO |= (mask >> 24); #endif } void UART_DisableInterrupts(UART_Type *base, uint32_t mask) { + mask &= kUART_AllInterruptsEnable; + /* The interrupt mask is combined by control bits from several register: ((CFIFO<<24) | (C3<<16) | (C2<<8) |(BDH)) */ - base->BDH &= ~(mask & 0xFF); - base->C2 &= ~((mask >> 8) & 0xFF); - base->C3 &= ~((mask >> 16) & 0xFF); + base->BDH &= ~mask; + base->C2 &= ~(mask >> 8); + base->C3 &= ~(mask >> 16); #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - base->CFIFO &= ~((mask >> 24) & 0xFF); + base->CFIFO &= ~(mask >> 24); #endif } @@ -381,7 +469,7 @@ uint32_t UART_GetEnabledInterrupts(UART_Type *base) temp |= ((uint32_t)(base->CFIFO) << 24); #endif - return temp; + return temp & kUART_AllInterruptsEnable; } uint32_t UART_GetStatusFlags(UART_Type *base) @@ -418,14 +506,24 @@ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask) base->SFIFO = (uint8_t)(mask >> 24); #endif - if (mask & (kUART_IdleLineFlag | kUART_RxOverrunFlag | kUART_NoiseErrorFlag | kUART_FramingErrorFlag | - kUART_ParityErrorFlag)) + if (mask & (kUART_IdleLineFlag | kUART_NoiseErrorFlag | kUART_FramingErrorFlag | kUART_ParityErrorFlag)) { /* Read base->D to clear the flags. */ (void)base->S1; (void)base->D; } + if (mask & kUART_RxOverrunFlag) + { + /* Read base->D to clear the flags and Flush all data in FIFO. */ + (void)base->S1; + (void)base->D; +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + } + /* If some flags still pending. */ if (mask & UART_GetStatusFlags(base)) { @@ -457,6 +555,8 @@ void UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length) static void UART_WriteNonBlocking(UART_Type *base, const uint8_t *data, size_t length) { + assert(data); + size_t i; /* The Non Blocking write data API assume user have ensured there is enough space in @@ -469,6 +569,8 @@ static void UART_WriteNonBlocking(UART_Type *base, const uint8_t *data, size_t l status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length) { + assert(data); + uint32_t statusFlag; while (length--) @@ -509,6 +611,8 @@ status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length) static void UART_ReadNonBlocking(UART_Type *base, uint8_t *data, size_t length) { + assert(data); + size_t i; /* The Non Blocking read data API assume user have ensured there is enough space in @@ -558,7 +662,6 @@ void UART_TransferCreateHandle(UART_Type *base, s_uartHandle[instance] = handle; s_uartIsr = UART_TransferHandleIRQ; - /* Enable interrupt in NVIC. */ EnableIRQ(s_uartIRQ[instance]); } @@ -566,17 +669,21 @@ void UART_TransferCreateHandle(UART_Type *base, void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize) { assert(handle); + assert(ringBuffer); /* Setup the ringbuffer address */ - if (ringBuffer) - { - handle->rxRingBuffer = ringBuffer; - handle->rxRingBufferSize = ringBufferSize; - handle->rxRingBufferHead = 0U; - handle->rxRingBufferTail = 0U; + handle->rxRingBuffer = ringBuffer; + handle->rxRingBufferSize = ringBufferSize; + handle->rxRingBufferHead = 0U; + handle->rxRingBufferTail = 0U; - /* Enable the interrupt to accept the data when user need the ring buffer. */ - UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Enable the interrupt to accept the data when user need the ring buffer. */ + UART_EnableInterrupts( + base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | kUART_FramingErrorInterruptEnable); + /* Enable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_EnableInterrupts(base, kUART_ParityErrorInterruptEnable); } } @@ -586,7 +693,13 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle) if (handle->rxState == kUART_RxIdle) { - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } handle->rxRingBuffer = NULL; @@ -597,13 +710,12 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle) status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, uart_transfer_t *xfer) { - status_t status; + assert(handle); + assert(xfer); + assert(xfer->dataSize); + assert(xfer->data); - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } + status_t status; /* Return error if current TX busy. */ if (kUART_TxBusy == handle->txState) @@ -628,6 +740,8 @@ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, ua void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle) { + assert(handle); + UART_DisableInterrupts(base, kUART_TxDataRegEmptyInterruptEnable | kUART_TransmissionCompleteInterruptEnable); handle->txDataSize = 0; @@ -636,16 +750,14 @@ void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle) status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - *count = handle->txDataSizeAll - handle->txDataSize; return kStatus_Success; @@ -656,6 +768,11 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, uart_transfer_t *xfer, size_t *receivedBytes) { + assert(handle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); + uint32_t i; status_t status; /* How many bytes to copy from ring buffer to user memory. */ @@ -664,13 +781,6 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, size_t bytesToReceive; /* How many bytes currently have received. */ size_t bytesCurrentReceived; - uint32_t regPrimask = 0U; - - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } /* How to get data: 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize @@ -694,8 +804,8 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, /* If RX ring buffer is used. */ if (handle->rxRingBuffer) { - /* Disable IRQ, protect ring buffer. */ - regPrimask = DisableGlobalIRQ(); + /* Disable UART RX IRQ, protect ring buffer. */ + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable); /* How many bytes in RX ring buffer currently. */ bytesToCopy = UART_TransferGetRxRingBufferLength(handle); @@ -733,8 +843,8 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, handle->rxState = kUART_RxBusy; } - /* Enable IRQ if previously enabled. */ - EnableGlobalIRQ(regPrimask); + /* Enable UART RX IRQ if previously enabled. */ + UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable); /* Call user callback since all data are received. */ if (0 == bytesToReceive) @@ -753,8 +863,14 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, handle->rxDataSizeAll = bytesToReceive; handle->rxState = kUART_RxBusy; - /* Enable RX interrupt. */ - UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Enable RX/Rx overrun/framing error interrupt. */ + UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Enable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_EnableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } /* Return the how many bytes have read. */ @@ -771,11 +887,19 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle) { + assert(handle); + /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */ if (!handle->rxRingBuffer) { /* Disable RX interrupt. */ - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } handle->rxDataSize = 0U; @@ -784,6 +908,9 @@ void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle) status_t UART_TransferGetReceiveCount(UART_Type *base, uart_handle_t *handle, uint32_t *count) { + assert(handle); + assert(count); + if (kUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; @@ -801,17 +928,67 @@ status_t UART_TransferGetReceiveCount(UART_Type *base, uart_handle_t *handle, ui void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) { + assert(handle); + uint8_t count; uint8_t tempCount; - assert(handle); + /* If RX framing error */ + if (UART_S1_FE_MASK & base->S1) + { + /* Read base->D to clear framing error flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + + handle->rxState = kUART_RxFramingError; + handle->rxDataSize = 0U; + /* Trigger callback. */ + if (handle->callback) + { + handle->callback(base, handle, kStatus_UART_FramingError, handle->userData); + } + } + + /* If RX parity error */ + if (UART_S1_PF_MASK & base->S1) + { + /* Read base->D to clear parity error flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + + handle->rxState = kUART_RxParityError; + handle->rxDataSize = 0U; + /* Trigger callback. */ + if (handle->callback) + { + handle->callback(base, handle, kStatus_UART_ParityError, handle->userData); + } + } /* If RX overrun. */ if (UART_S1_OR_MASK & base->S1) { - /* Read base->D, otherwise the RX does not work. */ - (void)base->D; - + /* Read base->D to clear overrun flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif /* Trigger callback. */ if (handle->callback) { @@ -898,16 +1075,38 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) } } } - /* If no receive requst pending, stop RX interrupt. */ + else if (!handle->rxDataSize) { - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Disable RX interrupt/overrun interrupt/fram error interrupt */ + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } else { } } + /* If framing error or parity error happened, stop the RX interrupt when ues no ring buffer */ + if (((handle->rxState == kUART_RxFramingError) || (handle->rxState == kUART_RxParityError)) && + (!handle->rxRingBuffer)) + { + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } + } + /* Send data register empty and the interrupt is enabled. */ if ((base->S1 & UART_S1_TDRE_MASK) && (base->C2 & UART_C2_TIE_MASK)) { @@ -952,7 +1151,7 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) void UART_TransferHandleErrorIRQ(UART_Type *base, uart_handle_t *handle) { - /* TODO: To be implemented. */ + /* To be implemented by User. */ } #if defined(UART0) @@ -992,7 +1191,6 @@ void UART2_RX_TX_DriverIRQHandler(void) { UART2_DriverIRQHandler(); } - #endif #if defined(UART3) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h index 3eec4e66b58..451baa9ffd3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,16 +37,14 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief UART driver version 2.1.0. */ -#define FSL_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief UART driver version 2.1.4. */ +#define FSL_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 4)) /*@}*/ /*! @brief Error codes for the UART driver. */ @@ -66,6 +64,8 @@ enum _uart_status kStatus_UART_NoiseError = MAKE_STATUS(kStatusGroup_UART, 10), /*!< UART noise error. */ kStatus_UART_FramingError = MAKE_STATUS(kStatusGroup_UART, 11), /*!< UART framing error. */ kStatus_UART_ParityError = MAKE_STATUS(kStatusGroup_UART, 12), /*!< UART parity error. */ + kStatus_UART_BaudrateNotSupport = + MAKE_STATUS(kStatusGroup_UART, 13), /*!< Baudrate is not support in current clock source */ }; /*! @brief UART parity mode. */ @@ -103,10 +103,23 @@ enum _uart_interrupt_enable kUART_FramingErrorInterruptEnable = (UART_C3_FEIE_MASK << 16), /*!< Framing error flag interrupt. */ kUART_ParityErrorInterruptEnable = (UART_C3_PEIE_MASK << 16), /*!< Parity error flag interrupt. */ #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - kUART_RxFifoOverflowInterruptEnable = (UART_CFIFO_TXOFE_MASK << 24), /*!< TX FIFO overflow interrupt. */ - kUART_TxFifoOverflowInterruptEnable = (UART_CFIFO_RXUFE_MASK << 24), /*!< RX FIFO underflow interrupt. */ + kUART_RxFifoOverflowInterruptEnable = (UART_CFIFO_RXOFE_MASK << 24), /*!< RX FIFO overflow interrupt. */ + kUART_TxFifoOverflowInterruptEnable = (UART_CFIFO_TXOFE_MASK << 24), /*!< TX FIFO overflow interrupt. */ kUART_RxFifoUnderflowInterruptEnable = (UART_CFIFO_RXUFE_MASK << 24), /*!< RX FIFO underflow interrupt. */ #endif + kUART_AllInterruptsEnable = +#if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT + kUART_LinBreakInterruptEnable | +#endif + kUART_RxActiveEdgeInterruptEnable | kUART_TxDataRegEmptyInterruptEnable | + kUART_TransmissionCompleteInterruptEnable | kUART_RxDataRegFullInterruptEnable | kUART_IdleLineInterruptEnable | + kUART_RxOverrunInterruptEnable | kUART_NoiseErrorInterruptEnable | kUART_FramingErrorInterruptEnable | + kUART_ParityErrorInterruptEnable +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + | + kUART_RxFifoOverflowInterruptEnable | kUART_TxFifoOverflowInterruptEnable | kUART_RxFifoUnderflowInterruptEnable +#endif + , }; /*! @@ -128,13 +141,16 @@ enum _uart_flags kUART_ParityErrorFlag = (UART_S1_PF_MASK), /*!< If parity enabled, sets upon parity error detection */ #if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT kUART_LinBreakFlag = - (UART_S2_LBKDIF_MASK << 8), /*!< LIN break detect interrupt flag, sets when - LIN break char detected and LIN circuit enabled */ + (UART_S2_LBKDIF_MASK + << 8), /*!< LIN break detect interrupt flag, sets when + LIN break char detected and LIN circuit enabled */ #endif - kUART_RxActiveEdgeFlag = (UART_S2_RXEDGIF_MASK << 8), /*!< RX pin active edge interrupt flag, - sets when active edge detected */ - kUART_RxActiveFlag = (UART_S2_RAF_MASK << 8), /*!< Receiver Active Flag (RAF), - sets at beginning of valid start bit */ + kUART_RxActiveEdgeFlag = + (UART_S2_RXEDGIF_MASK << 8), /*!< RX pin active edge interrupt flag, + sets when active edge detected */ + kUART_RxActiveFlag = + (UART_S2_RAF_MASK << 8), /*!< Receiver Active Flag (RAF), + sets at beginning of valid start bit */ #if defined(FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS kUART_NoiseErrorInRxDataRegFlag = (UART_ED_NOISY_MASK << 16), /*!< Noisy bit, sets if noise detected. */ kUART_ParityErrorInRxDataRegFlag = (UART_ED_PARITYE_MASK << 16), /*!< Paritye bit, sets if parity error detected. */ @@ -213,11 +229,11 @@ extern "C" { */ /*! - * @brief Initializes a UART instance with user configuration structure and peripheral clock. + * @brief Initializes a UART instance with a user configuration structure and peripheral clock. * * This function configures the UART module with the user-defined settings. The user can configure the configuration * structure and also get the default configuration by using the UART_GetDefaultConfig() function. - * Example below shows how to use this API to configure UART. + * The example below shows how to use this API to configure UART. * @code * uart_config_t uartConfig; * uartConfig.baudRate_Bps = 115200U; @@ -229,10 +245,12 @@ extern "C" { * @endcode * * @param base UART peripheral base address. - * @param config Pointer to user-defined configuration structure. + * @param config Pointer to the user-defined configuration structure. * @param srcClock_Hz UART clock source frequency in HZ. + * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in current clock source. + * @retval kStatus_Success Status UART initialize succeed */ -void UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz); +status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz); /*! * @brief Deinitializes a UART instance. @@ -247,7 +265,7 @@ void UART_Deinit(UART_Type *base); * @brief Gets the default configuration structure. * * This function initializes the UART configuration structure to a default value. The default - * values are: + * values are as follows. * uartConfig->baudRate_Bps = 115200U; * uartConfig->bitCountPerChar = kUART_8BitsPerChar; * uartConfig->parityMode = kUART_ParityDisabled; @@ -272,9 +290,11 @@ void UART_GetDefaultConfig(uart_config_t *config); * * @param base UART peripheral base address. * @param baudRate_Bps UART baudrate to be set. - * @param srcClock_Hz UART clock source freqency in HZ. + * @param srcClock_Hz UART clock source freqency in Hz. + * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in the current clock source. + * @retval kStatus_Success Set baudrate succeeded. */ -void UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); +status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); /* @} */ @@ -284,12 +304,12 @@ void UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_ */ /*! - * @brief Get UART status flags. + * @brief Gets UART status flags. * - * This function get all UART status flags, the flags are returned as the logical - * OR value of the enumerators @ref _uart_flags. To check specific status, + * This function gets all UART status flags. The flags are returned as the logical + * OR value of the enumerators @ref _uart_flags. To check a specific status, * compare the return value with enumerators in @ref _uart_flags. - * For example, to check whether the TX is empty: + * For example, to check whether the TX is empty, do the following. * @code * if (kUART_TxDataRegEmptyFlag & UART_GetStatusFlags(UART1)) * { @@ -305,19 +325,19 @@ uint32_t UART_GetStatusFlags(UART_Type *base); /*! * @brief Clears status flags with the provided mask. * - * This function clears UART status flags with a provided mask. Automatically cleared flag + * This function clears UART status flags with a provided mask. An automatically cleared flag * can't be cleared by this function. - * Some flags can only be cleared or set by hardware itself. These flags are: + * These flags can only be cleared or set by hardware. * kUART_TxDataRegEmptyFlag, kUART_TransmissionCompleteFlag, kUART_RxDataRegFullFlag, * kUART_RxActiveFlag, kUART_NoiseErrorInRxDataRegFlag, kUART_ParityErrorInRxDataRegFlag, * kUART_TxFifoEmptyFlag,kUART_RxFifoEmptyFlag - * Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects. + * Note that this API should be called when the Tx/Rx is idle. Otherwise it has no effect. * * @param base UART peripheral base address. - * @param mask The status flags to be cleared, it is logical OR value of @ref _uart_flags. + * @param mask The status flags to be cleared; it is logical OR value of @ref _uart_flags. * @retval kStatus_UART_FlagCannotClearManually The flag can't be cleared by this function but * it is cleared automatically by hardware. - * @retval kStatus_Success Status in the mask are cleared. + * @retval kStatus_Success Status in the mask is cleared. */ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask); @@ -333,7 +353,7 @@ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask); * * This function enables the UART interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref _uart_interrupt_enable. - * For example, to enable TX empty interrupt and RX full interrupt: + * For example, to enable TX empty interrupt and RX full interrupt, do the following. * @code * UART_EnableInterrupts(UART1,kUART_TxDataRegEmptyInterruptEnable | kUART_RxDataRegFullInterruptEnable); * @endcode @@ -348,7 +368,7 @@ void UART_EnableInterrupts(UART_Type *base, uint32_t mask); * * This function disables the UART interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref _uart_interrupt_enable. - * For example, to disable TX empty interrupt and RX full interrupt: + * For example, to disable TX empty interrupt and RX full interrupt do the following. * @code * UART_DisableInterrupts(UART1,kUART_TxDataRegEmptyInterruptEnable | kUART_RxDataRegFullInterruptEnable); * @endcode @@ -363,9 +383,9 @@ void UART_DisableInterrupts(UART_Type *base, uint32_t mask); * * This function gets the enabled UART interrupts. The enabled interrupts are returned * as the logical OR value of the enumerators @ref _uart_interrupt_enable. To check - * specific interrupts enable status, compare the return value with enumerators + * a specific interrupts enable status, compare the return value with enumerators * in @ref _uart_interrupt_enable. - * For example, to check whether TX empty interrupt is enabled: + * For example, to check whether TX empty interrupt is enabled, do the following. * @code * uint32_t enabledInterrupts = UART_GetEnabledInterrupts(UART1); * @@ -394,7 +414,7 @@ uint32_t UART_GetEnabledInterrupts(UART_Type *base); * This function returns the UART data register address, which is mainly used by DMA/eDMA. * * @param base UART peripheral base address. - * @return UART data register address which are used both by transmitter and receiver. + * @return UART data register addresses which are used both by the transmitter and the receiver. */ static inline uint32_t UART_GetDataRegisterAddress(UART_Type *base) { @@ -526,7 +546,7 @@ static inline void UART_WriteByte(UART_Type *base, uint8_t data) /*! * @brief Reads the RX register directly. * - * This function reads data from the TX register directly. The upper layer must + * This function reads data from the RX register directly. The upper layer must * ensure that the RX register is full or that the TX FIFO has data before calling this function. * * @param base UART peripheral base address. @@ -543,7 +563,7 @@ static inline uint8_t UART_ReadByte(UART_Type *base) * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO * to have room and writes data to the TX buffer. * - * @note This function does not check whether all the data has been sent out to the bus. + * @note This function does not check whether all data is sent out to the bus. * Before disabling the TX, check kUART_TransmissionCompleteFlag to ensure that the TX is * finished. * @@ -557,15 +577,15 @@ void UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length); * @brief Read RX data register using a blocking method. * * This function polls the RX register, waits for the RX register to be full or for RX FIFO to - * have data and read data from the TX register. + * have data, and reads data from the TX register. * * @param base UART peripheral base address. * @param data Start address of the buffer to store the received data. * @param length Size of the buffer. - * @retval kStatus_UART_RxHardwareOverrun Receiver overrun happened while receiving data. - * @retval kStatus_UART_NoiseError Noise error happened while receiving data. - * @retval kStatus_UART_FramingError Framing error happened while receiving data. - * @retval kStatus_UART_ParityError Parity error happened while receiving data. + * @retval kStatus_UART_RxHardwareOverrun Receiver overrun occurred while receiving data. + * @retval kStatus_UART_NoiseError A noise error occurred while receiving data. + * @retval kStatus_UART_FramingError A framing error occurred while receiving data. + * @retval kStatus_UART_ParityError A parity error occurred while receiving data. * @retval kStatus_Success Successfully received all data. */ status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length); @@ -600,16 +620,16 @@ void UART_TransferCreateHandle(UART_Type *base, * This function sets up the RX ring buffer to a specific UART handle. * * When the RX ring buffer is used, data received are stored into the ring buffer even when the - * user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received + * user doesn't call the UART_TransferReceiveNonBlocking() API. If data is already received * in the ring buffer, the user can get the received data from the ring buffer directly. * * @note When using the RX ring buffer, one byte is reserved for internal use. In other - * words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data. + * words, if @p ringBufferSize is 32, only 31 bytes are used for saving data. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer. - * @param ringBufferSize size of the ring buffer. + * @param ringBufferSize Size of the ring buffer. */ void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize); @@ -632,23 +652,23 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle); * function and passes the @ref kStatus_UART_TxIdle as status parameter. * * @note The kStatus_UART_TxIdle is passed to the upper layer when all data is written - * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX, + * to the TX register. However, it does not ensure that all data is sent out. Before disabling the TX, * check the kUART_TransmissionCompleteFlag to ensure that the TX is finished. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART transfer structure. See #uart_transfer_t. * @retval kStatus_Success Successfully start the data transmission. - * @retval kStatus_UART_TxBusy Previous transmission still not finished, data not all written to TX register yet. + * @retval kStatus_UART_TxBusy Previous transmission still not finished; data not all written to TX register yet. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Aborts the interrupt driven data transmit. + * @brief Aborts the interrupt-driven data transmit. * - * This function aborts the interrupt driven data sending. The user can get the remainBytes to find out - * how many bytes are still not sent out. + * This function aborts the interrupt-driven data sending. The user can get the remainBytes to find out + * how many bytes are not sent out. * * @param base UART peripheral base address. * @param handle UART handle pointer. @@ -656,16 +676,16 @@ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, ua void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes written to the UART TX register. * - * This function gets the number of bytes that have been written to UART TX - * register by interrupt method. + * This function gets the number of bytes written to the UART TX + * register by using the interrupt method. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param count Send bytes count. * @retval kStatus_NoTransferInProgress No send in progress. - * @retval kStatus_InvalidArgument Parameter is invalid. + * @retval kStatus_InvalidArgument The parameter is invalid. * @retval kStatus_Success Get successfully through the parameter \p count; */ status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint32_t *count); @@ -690,7 +710,7 @@ status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint3 * * @param base UART peripheral base address. * @param handle UART handle pointer. - * @param xfer UART transfer structure, refer to #uart_transfer_t. + * @param xfer UART transfer structure, see #uart_transfer_t. * @param receivedBytes Bytes received from the ring buffer directly. * @retval kStatus_Success Successfully queue the transfer into transmit queue. * @retval kStatus_UART_RxBusy Previous receive request is not finished. @@ -705,7 +725,7 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, * @brief Aborts the interrupt-driven data receiving. * * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to know - * how many bytes not received yet. + * how many bytes are not received yet. * * @param base UART peripheral base address. * @param handle UART handle pointer. @@ -713,7 +733,7 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of bytes that have been received. * * This function gets the number of bytes that have been received. * @@ -739,7 +759,7 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle); /*! * @brief UART Error IRQ handle function. * - * This function handle the UART error IRQ request. + * This function handles the UART error IRQ request. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c index 36734044860..c51e4934639 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -125,6 +125,8 @@ extern uint32_t UART_GetInstance(UART_Type *base); static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param; /* Avoid the warning for unused variables. */ @@ -145,6 +147,8 @@ static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool trans static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param; /* Avoid warning for unused parameters. */ @@ -165,11 +169,11 @@ static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool tr } void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle) + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle) { assert(handle); @@ -219,17 +223,15 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer) { + assert(handle); assert(handle->txEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous TX not finished. */ if (kUART_TxBusy == handle->txState) { @@ -244,6 +246,9 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -259,17 +264,15 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer) { + assert(handle); assert(handle->rxEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous RX not finished. */ if (kUART_RxBusy == handle->rxState) { @@ -284,6 +287,9 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -299,6 +305,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle) { + assert(handle); assert(handle->txEdmaHandle); /* Disable UART TX EDMA. */ @@ -312,6 +319,7 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle) void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle) { + assert(handle); assert(handle->rxEdmaHandle); /* Disable UART RX EDMA. */ @@ -325,38 +333,36 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle) status_t UART_TransferGetReceiveCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->rxEdmaHandle); + assert(count); if (kUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->txEdmaHandle); + assert(count); if (kUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h index 52cc7373a9f..e411ffd7a44 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_uart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,8 +39,6 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -67,6 +65,8 @@ struct _uart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -87,18 +87,18 @@ extern "C" { /*! * @brief Initializes the UART handle which is used in transactional functions. * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param callback UART callback, NULL means no callback. * @param userData User callback function data. - * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. - * @param txEdmaHandle User requested DMA handle for TX DMA transfer. + * @param rxEdmaHandle User-requested DMA handle for RX DMA transfer. + * @param txEdmaHandle User-requested DMA handle for TX DMA transfer. */ void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -109,23 +109,23 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_TxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_TxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Receive data using eDMA. + * @brief Receives data using eDMA. * * This function receives data using eDMA. This is a non-blocking function, which returns * right away. When all data is received, the receive callback function is called. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_RxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); @@ -136,7 +136,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran * This function aborts sent data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); @@ -146,12 +146,12 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); * This function aborts receive data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes that have been written to UART TX register. * * This function gets the number of bytes that have been written to UART TX * register by DMA. @@ -166,9 +166,9 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c index 0854ca07577..24f2d1dc280 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -50,8 +50,10 @@ static uint32_t VREF_GetInstance(VREF_Type *base); /*! @brief Pointers to VREF bases for each instance. */ static VREF_Type *const s_vrefBases[] = VREF_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to VREF clocks for each instance. */ static const clock_ip_name_t s_vrefClocks[] = VREF_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -62,7 +64,7 @@ static uint32_t VREF_GetInstance(VREF_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_VREF_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_vrefBases); instance++) { if (s_vrefBases[instance] == base) { @@ -70,7 +72,7 @@ static uint32_t VREF_GetInstance(VREF_Type *base) } } - assert(instance < FSL_FEATURE_SOC_VREF_COUNT); + assert(instance < ARRAY_SIZE(s_vrefBases)); return instance; } @@ -81,15 +83,24 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config) uint8_t reg = 0U; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate clock for VREF */ CLOCK_EnableClock(s_vrefClocks[VREF_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure VREF to a known state */ #if defined(FSL_FEATURE_VREF_HAS_CHOP_OSC) && FSL_FEATURE_VREF_HAS_CHOP_OSC /* Set chop oscillator bit */ base->TRM |= VREF_TRM_CHOPEN_MASK; #endif /* FSL_FEATURE_VREF_HAS_CHOP_OSC */ + /* Get current SC register */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + reg = base->VREFH_SC; +#else reg = base->SC; +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ + /* Clear old buffer mode selection bits */ + reg &= ~VREF_SC_MODE_LV_MASK; /* Set buffer Mode selection and Regulator enable bit */ reg |= VREF_SC_MODE_LV(config->bufferMode) | VREF_SC_REGEN(1U); #if defined(FSL_FEATURE_VREF_HAS_COMPENSATION) && FSL_FEATURE_VREF_HAS_COMPENSATION @@ -99,30 +110,51 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config) /* Enable VREF module */ reg |= VREF_SC_VREFEN(1U); /* Update bit-field from value to Status and Control register */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + base->VREFH_SC = reg; +#else base->SC = reg; +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE reg = base->VREFL_TRM; - /* Clear old select external voltage reference and VREFL (0.4 V) reference buffer enable bits*/ + /* Clear old select external voltage reference and VREFL (0.4 V) reference buffer enable bits */ reg &= ~(VREF_VREFL_TRM_VREFL_EN_MASK | VREF_VREFL_TRM_VREFL_SEL_MASK); /* Select external voltage reference and set VREFL (0.4 V) reference buffer enable */ reg |= VREF_VREFL_TRM_VREFL_SEL(config->enableExternalVoltRef) | VREF_VREFL_TRM_VREFL_EN(config->enableLowRef); base->VREFL_TRM = reg; #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 + reg = base->TRM4; + /* Clear old select internal voltage reference bit (2.1V) */ + reg &= ~VREF_TRM4_VREF2V1_EN_MASK; + /* Select internal voltage reference (2.1V) */ + reg |= VREF_TRM4_VREF2V1_EN(config->enable2V1VoltRef); + base->TRM4 = reg; +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ + /* Wait until internal voltage stable */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0) +#else while ((base->SC & VREF_SC_VREFST_MASK) == 0) +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ { } } void VREF_Deinit(VREF_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate clock for VREF */ CLOCK_DisableClock(s_vrefClocks[VREF_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void VREF_GetDefaultConfig(vref_config_t *config) { + assert(config); + /* Set High power buffer mode in */ #if defined(FSL_FEATURE_VREF_MODE_LV_TYPE) && FSL_FEATURE_VREF_MODE_LV_TYPE config->bufferMode = kVREF_ModeHighPowerBuffer; @@ -136,6 +168,11 @@ void VREF_GetDefaultConfig(vref_config_t *config) /* Set VREFL (0.4 V) reference buffer disable */ config->enableLowRef = false; #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ + +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 + /* Disable internal voltage reference (2.1V) */ + config->enable2V1VoltRef = false; +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ } void VREF_SetTrimVal(VREF_Type *base, uint8_t trimValue) @@ -147,10 +184,30 @@ void VREF_SetTrimVal(VREF_Type *base, uint8_t trimValue) reg = ((reg & ~VREF_TRM_TRIM_MASK) | VREF_TRM_TRIM(trimValue)); base->TRM = reg; /* Wait until internal voltage stable */ +#if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE + while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0) +#else + while ((base->SC & VREF_SC_VREFST_MASK) == 0) +#endif/* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ + { + } +} + +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 +void VREF_SetTrim2V1Val(VREF_Type *base, uint8_t trimValue) +{ + uint8_t reg = 0U; + + /* Set TRIM bits value in voltage reference (2V1) */ + reg = base->TRM4; + reg = ((reg & ~VREF_TRM4_TRIM2V1_MASK) | VREF_TRM4_TRIM2V1(trimValue)); + base->TRM4 = reg; + /* Wait until internal voltage stable */ while ((base->SC & VREF_SC_VREFST_MASK) == 0) { } } +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE void VREF_SetLowReferenceTrimVal(VREF_Type *base, uint8_t trimValue) @@ -165,7 +222,8 @@ void VREF_SetLowReferenceTrimVal(VREF_Type *base, uint8_t trimValue) reg = ((reg & ~VREF_VREFL_TRM_VREFL_TRIM_MASK) | VREF_VREFL_TRM_VREFL_TRIM(trimValue)); base->VREFL_TRM = reg; /* Wait until internal voltage stable */ - while ((base->SC & VREF_SC_VREFST_MASK) == 0) + + while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0) { } } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h index 79378863bb6..6c6c014b913 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_vref.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ -/*! @file */ /****************************************************************************** * Definitions @@ -46,12 +45,11 @@ /*! @name Driver version */ /*@{*/ -#define FSL_VREF_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ +#define FSL_VREF_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ /*@}*/ /* Those macros below defined to support SoC family which have VREFL (0.4V) reference */ #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE -#define SC VREFH_SC #define VREF_SC_MODE_LV VREF_VREFH_SC_MODE_LV #define VREF_SC_REGEN VREF_VREFH_SC_REGEN #define VREF_SC_VREFEN VREF_VREFH_SC_VREFEN @@ -80,8 +78,8 @@ typedef enum _vref_buffer_mode { kVREF_ModeBandgapOnly = 0U, /*!< Bandgap on only, for stabilization and startup */ #if defined(FSL_FEATURE_VREF_MODE_LV_TYPE) && FSL_FEATURE_VREF_MODE_LV_TYPE - kVREF_ModeHighPowerBuffer = 1U, /*!< High power buffer mode enabled */ - kVREF_ModeLowPowerBuffer = 2U /*!< Low power buffer mode enabled */ + kVREF_ModeHighPowerBuffer = 1U, /*!< High-power buffer mode enabled */ + kVREF_ModeLowPowerBuffer = 2U /*!< Low-power buffer mode enabled */ #else kVREF_ModeTightRegulationBuffer = 2U /*!< Tight regulation buffer enabled */ #endif /* FSL_FEATURE_VREF_MODE_LV_TYPE */ @@ -97,6 +95,9 @@ typedef struct _vref_config bool enableLowRef; /*!< Set VREFL (0.4 V) reference buffer enable or disable */ bool enableExternalVoltRef; /*!< Select external voltage reference or not (internal) */ #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */ +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 + bool enable2V1VoltRef; /*!< Enable Internal Voltage Reference (2.1V) */ +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ } vref_config_t; /****************************************************************************** @@ -115,11 +116,11 @@ extern "C" { /*! * @brief Enables the clock gate and configures the VREF module according to the configuration structure. * - * This function must be called before calling all the other VREF driver functions, + * This function must be called before calling all other VREF driver functions, * read/write registers, and configurations with user-defined settings. * The example below shows how to set up vref_config_t parameters and - * how to call the VREF_Init function by passing in these parameters: - * Example: + * how to call the VREF_Init function by passing in these parameters. + * This is an example. * @code * vref_config_t vrefConfig; * vrefConfig.bufferMode = kVREF_ModeHighPowerBuffer; @@ -137,7 +138,7 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config); * @brief Stops and disables the clock for the VREF module. * * This function should be called to shut down the module. - * Example: + * This is an example. * @code * vref_config_t vrefUserConfig; * VREF_Init(VREF); @@ -153,8 +154,8 @@ void VREF_Deinit(VREF_Type *base); /*! * @brief Initializes the VREF configuration structure. * - * This function initializes the VREF configuration structure to a default value. - * Example: + * This function initializes the VREF configuration structure to default values. + * This is an example. * @code * vrefConfig->bufferMode = kVREF_ModeHighPowerBuffer; * vrefConfig->enableExternalVoltRef = false; @@ -166,9 +167,9 @@ void VREF_Deinit(VREF_Type *base); void VREF_GetDefaultConfig(vref_config_t *config); /*! - * @brief Sets a TRIM value for reference voltage. + * @brief Sets a TRIM value for the reference voltage. * - * This function sets a TRIM value for reference voltage. + * This function sets a TRIM value for the reference voltage. * Note that the TRIM value maximum is 0x3F. * * @param base VREF peripheral address. @@ -188,13 +189,40 @@ static inline uint8_t VREF_GetTrimVal(VREF_Type *base) { return (base->TRM & VREF_TRM_TRIM_MASK); } + +#if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 +/*! + * @brief Sets a TRIM value for the reference voltage (2V1). + * + * This function sets a TRIM value for the reference voltage (2V1). + * Note that the TRIM value maximum is 0x3F. + * + * @param base VREF peripheral address. + * @param trimValue Value of the trim register to set the output reference voltage (maximum 0x3F (6-bit)). + */ +void VREF_SetTrim2V1Val(VREF_Type *base, uint8_t trimValue); + +/*! + * @brief Reads the value of the TRIM meaning output voltage (2V1). + * + * This function gets the TRIM value from the VREF_TRM4 register. + * + * @param base VREF peripheral address. + * @return Six-bit value of trim setting. + */ +static inline uint8_t VREF_GetTrim2V1Val(VREF_Type *base) +{ + return (base->TRM4 & VREF_TRM4_TRIM2V1_MASK); +} +#endif /* FSL_FEATURE_VREF_HAS_TRM4 */ + #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE /*! - * @brief Sets the TRIM value for low voltage reference. + * @brief Sets the TRIM value for the low voltage reference. * * This function sets the TRIM value for low reference voltage. - * NOTE: + * Note the following. * - The TRIM value maximum is 0x05U * - The values 111b and 110b are not valid/allowed. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c index 489798ca889..781ac133c1a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h index 949a9a8e046..580adb95a0f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_wdog.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -33,11 +33,10 @@ #include "fsl_common.h" /*! - * @addtogroup wdog_driver + * @addtogroup wdog * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -136,7 +135,7 @@ typedef struct _wdog_test_config */ enum _wdog_interrupt_enable_t { - kWDOG_InterruptEnable = WDOG_STCTRLH_IRQRSTEN_MASK, /*!< WDOG timeout will generate interrupt before reset*/ + kWDOG_InterruptEnable = WDOG_STCTRLH_IRQRSTEN_MASK, /*!< WDOG timeout generates an interrupt before reset*/ }; /*! @@ -164,10 +163,10 @@ extern "C" { */ /*! - * @brief Initializes WDOG configure sturcture. + * @brief Initializes the WDOG configuration sturcture. * - * This function initializes the WDOG configure structure to default value. The default - * value are: + * This function initializes the WDOG configuration structure to default values. The default + * values are as follows. * @code * wdogConfig->enableWdog = true; * wdogConfig->clockSource = kWDOG_LpoClockSource; @@ -182,7 +181,7 @@ extern "C" { * wdogConfig->timeoutValue = 0xFFFFU; * @endcode * - * @param config Pointer to WDOG config structure. + * @param config Pointer to the WDOG configuration structure. * @see wdog_config_t */ void WDOG_GetDefaultConfig(wdog_config_t *config); @@ -191,10 +190,10 @@ void WDOG_GetDefaultConfig(wdog_config_t *config); * @brief Initializes the WDOG. * * This function initializes the WDOG. When called, the WDOG runs according to the configuration. - * If user wants to reconfigure WDOG without forcing a reset first, enableUpdate must be set to true - * in configuration. + * To reconfigure WDOG without forcing a reset first, enableUpdate must be set to true + * in the configuration. * - * Example: + * This is an example. * @code * wdog_config_t config; * WDOG_GetDefaultConfig(&config); @@ -212,18 +211,18 @@ void WDOG_Init(WDOG_Type *base, const wdog_config_t *config); * @brief Shuts down the WDOG. * * This function shuts down the WDOG. - * Make sure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. + * Ensure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which indicates that the register update is enabled. */ void WDOG_Deinit(WDOG_Type *base); /*! - * @brief Configures WDOG functional test. + * @brief Configures the WDOG functional test. * * This function is used to configure the WDOG functional test. When called, the WDOG goes into test mode * and runs according to the configuration. - * Make sure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. + * Ensure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. * - * Example: + * This is an example. * @code * wdog_test_config_t test_config; * test_config.testMode = kWDOG_QuickTest; @@ -259,9 +258,9 @@ static inline void WDOG_Enable(WDOG_Type *base) /*! * @brief Disables the WDOG module. * - * This function write value into WDOG_STCTRLH register to disable the WDOG, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to disable the WDOG. It is a write-once register. + * Ensure that the WCT window is still open and that register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address */ @@ -271,15 +270,15 @@ static inline void WDOG_Disable(WDOG_Type *base) } /*! - * @brief Enable WDOG interrupt. + * @brief Enables the WDOG interrupt. * - * This function write value into WDOG_STCTRLH register to enable WDOG interrupt, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to enable the WDOG interrupt. It is a write-once register. + * Ensure that the WCT window is still open and the register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param mask The interrupts to enable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined. * @arg kWDOG_InterruptEnable */ static inline void WDOG_EnableInterrupts(WDOG_Type *base, uint32_t mask) @@ -288,15 +287,15 @@ static inline void WDOG_EnableInterrupts(WDOG_Type *base, uint32_t mask) } /*! - * @brief Disable WDOG interrupt. + * @brief Disables the WDOG interrupt. * - * This function write value into WDOG_STCTRLH register to disable WDOG interrupt, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to disable the WDOG interrupt. It is a write-once register. + * Ensure that the WCT window is still open and the register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param mask The interrupts to disable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined. * @arg kWDOG_InterruptEnable */ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) @@ -305,50 +304,50 @@ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) } /*! - * @brief Gets WDOG all status flags. + * @brief Gets the WDOG all status flags. * * This function gets all status flags. * - * Example for getting Running Flag: + * This is an example for getting the Running Flag. * @code * uint32_t status; - * status = WDOG_GetStatusFlags(wdog_base) & kWDOG_RunningFlag; + * status = WDOG_GetStatusFlags (wdog_base) & kWDOG_RunningFlag; * @endcode * @param base WDOG peripheral base address * @return State of the status flag: asserted (true) or not-asserted (false).@see _wdog_status_flags_t - * - true: related status flag has been set. - * - false: related status flag is not set. + * - true: a related status flag has been set. + * - false: a related status flag is not set. */ uint32_t WDOG_GetStatusFlags(WDOG_Type *base); /*! - * @brief Clear WDOG flag. + * @brief Clears the WDOG flag. * - * This function clears WDOG status flag. + * This function clears the WDOG status flag. * - * Example for clearing timeout(interrupt) flag: + * This is an example for clearing the timeout (interrupt) flag. * @code * WDOG_ClearStatusFlags(wdog_base,kWDOG_TimeoutFlag); * @endcode * @param base WDOG peripheral base address * @param mask The status flags to clear. - * The parameter could be any combination of the following values: + * The parameter could be any combination of the following values. * kWDOG_TimeoutFlag */ void WDOG_ClearStatusFlags(WDOG_Type *base, uint32_t mask); /*! - * @brief Set the WDOG timeout value. + * @brief Sets the WDOG timeout value. * * This function sets the timeout value. * It should be ensured that the time-out value for the WDOG is always greater than * 2xWCT time + 20 bus clock cycles. - * This function write value into WDOG_TOVALH and WDOG_TOVALL registers which are wirte-once. - * Make sure the WCT window is still open and these two registers have not been written in this WCT - * while this function is called. + * This function writes a value into WDOG_TOVALH and WDOG_TOVALL registers which are wirte-once. + * Ensure the WCT window is still open and the two registers have not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address - * @param timeoutCount WDOG timeout value, count of WDOG clock tick. + * @param timeoutCount WDOG timeout value; count of WDOG clock tick. */ static inline void WDOG_SetTimeoutValue(WDOG_Type *base, uint32_t timeoutCount) { @@ -360,9 +359,9 @@ static inline void WDOG_SetTimeoutValue(WDOG_Type *base, uint32_t timeoutCount) * @brief Sets the WDOG window value. * * This function sets the WDOG window value. - * This function write value into WDOG_WINH and WDOG_WINL registers which are wirte-once. - * Make sure the WCT window is still open and these two registers have not been written in this WCT - * while this function is called. + * This function writes a value into WDOG_WINH and WDOG_WINL registers which are wirte-once. + * Ensure the WCT window is still open and the two registers have not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param windowValue WDOG window value. @@ -378,7 +377,7 @@ static inline void WDOG_SetWindowValue(WDOG_Type *base, uint32_t windowValue) * * This function unlocks the WDOG register written. * Before starting the unlock sequence and following congfiguration, disable the global interrupts. - * Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire, + * Otherwise, an interrupt may invalidate the unlocking sequence and the WCT may expire. * After the configuration finishes, re-enable the global interrupts. * * @param base WDOG peripheral base address @@ -393,7 +392,7 @@ static inline void WDOG_Unlock(WDOG_Type *base) * @brief Refreshes the WDOG timer. * * This function feeds the WDOG. - * This function should be called before WDOG timer is in timeout. Otherwise, a reset is asserted. + * This function should be called before the WDOG timer is in timeout. Otherwise, a reset is asserted. * * @param base WDOG peripheral base address */ @@ -405,7 +404,7 @@ void WDOG_Refresh(WDOG_Type *base); * This function gets the WDOG reset count value. * * @param base WDOG peripheral base address - * @return WDOG reset count value + * @return WDOG reset count value. */ static inline uint16_t WDOG_GetResetCount(WDOG_Type *base) { From d9a8c63b533495bbbd23f51e051032c3d8c7100b Mon Sep 17 00:00:00 2001 From: Mahadevan Mahesh Date: Fri, 25 Aug 2017 15:21:48 -0500 Subject: [PATCH 13/29] K66F: Use DSPI SDK driver API's in spi block read Signed-off-by: Mahadevan Mahesh --- .../TARGET_K66F/spi_api.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c index 8a65bd4f22a..2ca04b99c89 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c @@ -122,13 +122,17 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) { int total = (tx_length > rx_length) ? tx_length : rx_length; - for (int i = 0; i < total; i++) { - char out = (i < tx_length) ? tx_buffer[i] : write_fill; - char in = spi_master_write(obj, out); - if (i < rx_length) { - rx_buffer[i] = in; - } - } + // Default write is done in each and every call, in future can create HAL API instead + DSPI_SetDummyData(spi_address[obj->instance], write_fill); + + DSPI_MasterTransferBlocking(spi_address[obj->instance], &(dspi_transfer_t){ + .txData = (uint8_t *)tx_buffer, + .rxData = (uint8_t *)rx_buffer, + .dataSize = total, + .configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous, + }); + + DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag); return total; } From c32890294e845ec73249e275af7aaf724a4aaa64 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Mon, 25 Sep 2017 18:49:38 -0500 Subject: [PATCH 14/29] Fix LPC54114 vector table size Correct the vector table size on the LPC54114. This fixes crashes seen on boot when building with GCC. --- .../TARGET_LPC54114/device/cmsis_nvic.h | 46 +++++++++++++++++++ .../{ => TARGET_LPC54608/device}/cmsis_nvic.h | 0 2 files changed, 46 insertions(+) create mode 100644 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h rename targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/{ => TARGET_LPC54608/device}/cmsis_nvic.h (100%) diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h new file mode 100644 index 00000000000..584b9075a85 --- /dev/null +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/cmsis_nvic.h @@ -0,0 +1,46 @@ +/* mbed Microcontroller Library + * CMSIS-style functionality to support dynamic vectors + ******************************************************************************* + * Copyright (c) 2011 ARM Limited. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of ARM Limited nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + */ + +#ifndef MBED_CMSIS_NVIC_H +#define MBED_CMSIS_NVIC_H + +#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) +extern uint32_t Image$$VECTOR_RAM$$Base[]; +#define __VECTOR_RAM Image$$VECTOR_RAM$$Base +#else +extern uint32_t __VECTOR_RAM[]; +#endif + +/* Symbols defined by the linker script */ +#define NVIC_NUM_VECTORS (16 + 40) // CORE + MCU Peripherals +#define NVIC_RAM_VECTOR_ADDRESS (__VECTOR_RAM) // Vectors positioned at start of RAM + +#endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/cmsis_nvic.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54608/device/cmsis_nvic.h similarity index 100% rename from targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/cmsis_nvic.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54608/device/cmsis_nvic.h From c58d7de93da0c5f19f04d3210200d453b6b05eae Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:37:13 +0100 Subject: [PATCH 15/29] BLE: Fix GattClient destructor by adding a virtual specifier. --- features/FEATURE_BLE/ble/GattClient.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index dc194f50b36..5f043ebb22a 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -80,6 +80,9 @@ class GattClient { * The following functions are meant to be overridden in the platform-specific sub-class. */ public: + + virtual ~GattClient() { } + /** * Launch service discovery. Once launched, application callbacks will be * invoked for matching services or characteristics. isServiceDiscoveryActive() From dd303b7a91dea283da316e8ef9ebe190b519ef49 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:37:34 +0100 Subject: [PATCH 16/29] BLE: Add ArrayView in utilities. --- features/FEATURE_BLE/ble/ArrayView.h | 165 +++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 features/FEATURE_BLE/ble/ArrayView.h diff --git a/features/FEATURE_BLE/ble/ArrayView.h b/features/FEATURE_BLE/ble/ArrayView.h new file mode 100644 index 00000000000..5cf7336c1dd --- /dev/null +++ b/features/FEATURE_BLE/ble/ArrayView.h @@ -0,0 +1,165 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_ARRAY_VIEW_H_ +#define BLE_ARRAY_VIEW_H_ + +#include +#include + +namespace ble { + +/** + * Immutable view to an array. + */ +template +struct ArrayView { + + /** + * construct an array view to an empty array + */ + ArrayView() : _array(0), _size(0) { } + + /** + * construct an array view from a pointer. + * and its size. + */ + ArrayView(T* array_ptr, size_t array_size) : + _array(array_ptr), _size(array_size) { } + + /** + * Construct an array view from the reference to an array. + */ + template + ArrayView(T (&elements)[Size]): + _array(elements), _size(Size) { } + + /** + * Return the size of the array viewed. + */ + size_t size() const { + return _size; + } + + /** + * Access to a mutable element of the array. + */ + T& operator[](size_t index) { + return _array[index]; + } + + /** + * Access to an immutable element of the array. + */ + const T& operator[](size_t index) const { + return _array[index]; + } + + /** + * Get the pointer to the array + */ + T* data() { + return _array; + } + + /** + * Get the pointer to the const array + */ + const T* data() const { + return _array; + } + + /** + * Equality operator + */ + friend bool operator==(const ArrayView& lhs, const ArrayView& rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; + } + + /** + * Not equal operator + */ + friend bool operator!=(const ArrayView& lhs, const ArrayView& rhs) { + return !(lhs == rhs); + } + +private: + T* const _array; + const size_t _size; +}; + + +/** + * Generate an array view from a C/C++ array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param elements The array viewed. + * @return The array_view to elements. + */ +template +ArrayView make_ArrayView(T (&elements)[Size]) { + return ArrayView(elements); +} + +/** + * Generate an array view from a C/C++ pointer and the size of the array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param array_ptr The pointer to the array to view. + * @param array_size The size of the array. + * @return The array_view to array_ptr with a size of array_size. + */ +template +ArrayView make_ArrayView(T* array_ptr, size_t array_size) { + return ArrayView(array_ptr, array_size); +} + +/** + * Generate a const array view from a C/C++ array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param elements The array viewed. + * @return The ArrayView to elements. + */ +template +ArrayView make_const_ArrayView(T (&elements)[Size]) { + return ArrayView(elements); +} + +/** + * Generate a const array view from a C/C++ pointer and the size of the array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param array_ptr The pointer to the array to view. + * @param array_size The size of the array. + * @return The ArrayView to array_ptr with a size of array_size. + */ +template +ArrayView make_const_ArrayView(T* array_ptr, size_t array_size) { + return ArrayView(array_ptr, array_size); +} + +} // namespace ble + +#endif /* BLE_ARRAY_VIEW_H_ */ From c022c4a8f06d2b11681d028be049b0ee115f4853 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:38:30 +0100 Subject: [PATCH 17/29] BLE: use common type ble::connection_handle_t as Handle_t. --- features/FEATURE_BLE/ble/Gap.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 5a01e4e9a4b..1f8c62cb69f 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -17,6 +17,7 @@ #ifndef __GAP_H__ #define __GAP_H__ +#include "BLETypes.h" #include "ble/BLEProtocol.h" #include "GapAdvertisingData.h" #include "GapAdvertisingParams.h" @@ -171,7 +172,7 @@ class Gap { /** * Type for connection handle. */ - typedef uint16_t Handle_t; + typedef ble::connection_handle_t Handle_t; /** * Structure containing GAP connection parameters. When in peripheral role From 97995b8de91dc03b2e09cd4555592be037b5a740 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:39:13 +0100 Subject: [PATCH 18/29] BLE: Fix header inclusion of DiscoveredCharacteristicDescriptor. --- features/FEATURE_BLE/ble/DiscoveredCharacteristic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h b/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h index 3529c360ad8..4fcd719dc95 100644 --- a/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h +++ b/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h @@ -22,7 +22,7 @@ #include "GattAttribute.h" #include "GattClient.h" #include "CharacteristicDescriptorDiscovery.h" -#include "ble/DiscoveredCharacteristicDescriptor.h" +#include "DiscoveredCharacteristicDescriptor.h" /** * @brief Representation of a characteristic discovered during a GattClient From 4416ef6233cceb288d3afee2cae0bc28d45872e0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:40:49 +0100 Subject: [PATCH 19/29] BLE: Add optionnal error_code CharacteristicDescriptorDiscovery::TerminationCallbackParams_t --- features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h b/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h index 0349318b79e..e50180809a3 100644 --- a/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h +++ b/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h @@ -70,6 +70,11 @@ class CharacteristicDescriptorDiscovery { * status of the discovery operation */ ble_error_t status; + + /** + * error code associated with the status if any. + */ + uint8_t error_code; }; /** From 1fd953e33c3d31daa9a69ef1eaa2a800c05174f4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:41:35 +0100 Subject: [PATCH 20/29] BLE: Use shared type ble_attribute_handle_t in GattAttribute. --- features/FEATURE_BLE/ble/GattAttribute.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/GattAttribute.h b/features/FEATURE_BLE/ble/GattAttribute.h index 119c68c173d..1011bc0d53c 100644 --- a/features/FEATURE_BLE/ble/GattAttribute.h +++ b/features/FEATURE_BLE/ble/GattAttribute.h @@ -18,6 +18,7 @@ #define __GATT_ATTRIBUTE_H__ #include "UUID.h" +#include "BLETypes.h" /** * Instances of this class encapsulate the data that belongs to a Bluetooth Low @@ -29,7 +30,7 @@ class GattAttribute { * Type for the handle or ID of the attribute in the ATT table. These are * unique and are usually generated by the underlying BLE stack. */ - typedef uint16_t Handle_t; + typedef ble::attribute_handle_t Handle_t; /** * Define the value of an invalid attribute handle. */ From 85e88ccb2cfad895e15a314fa7d338cac0804a6d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:43:00 +0100 Subject: [PATCH 21/29] BLE NRF: Fix wrong usage of designed initializer in cpp code. --- .../source/nRF5xServiceDiscovery.cpp | 8 ++++---- .../TARGET_NRF5/source/nRF5xServiceDiscovery.cpp | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp index 4f11a9d8ae9..c81d632434e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp @@ -24,8 +24,8 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan characteristicDiscoveryStarted(connectionHandle); ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); ble_error_t err = BLE_ERROR_NONE; @@ -170,8 +170,8 @@ nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) if (startHandle < endHandle) { ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp index 87ac20c8ff0..79f691bfcf6 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp @@ -24,8 +24,8 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan characteristicDiscoveryStarted(connectionHandle); ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); ble_error_t err = BLE_ERROR_NONE; @@ -170,8 +170,8 @@ nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) if (startHandle < endHandle) { ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); @@ -288,8 +288,8 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt if (state == DISCOVER_SERVICE_UUIDS) { if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { UUID::LongUUIDBytes_t uuid; - -#if (NRF_SD_BLE_API_VERSION >= 3) + +#if (NRF_SD_BLE_API_VERSION >= 3) ble_gattc_handle_value_t iter; memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); (void) sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(const_cast(p_gattc_evt), &iter); @@ -308,7 +308,7 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { UUID::LongUUIDBytes_t uuid; - + #if (NRF_SD_BLE_API_VERSION >= 3) ble_gattc_handle_value_t iter; memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); @@ -317,7 +317,7 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt #else memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID); #endif - + unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); characteristics[charIndex].setupLongUUID(uuid, UUID::LSB); From 38bb6b4e52863a37cf2712a187a4f6bc1e8ac469 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:45:04 +0100 Subject: [PATCH 22/29] BLE: Add error code management in Gatt read and write data structures. Also fix wrong usage of designed initializer in CPP files. --- .../FEATURE_BLE/ble/GattCallbackParamTypes.h | 43 +++++++++++++++-- .../TARGET_BEETLE/source/ArmGattServer.cpp | 22 ++++----- .../targets/TARGET_Maxim/MaximGattServer.cpp | 22 ++++----- .../source/btle/btle_discovery.cpp | 32 ++++++------- .../source/nRF5xGattServer.cpp | 24 +++++----- .../source/btle/btle_discovery.cpp | 32 ++++++------- .../TARGET_NRF5/source/nRF5xGattServer.cpp | 46 +++++++++---------- 7 files changed, 129 insertions(+), 92 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattCallbackParamTypes.h b/features/FEATURE_BLE/ble/GattCallbackParamTypes.h index 40c1e61dd67..d8eb362235d 100644 --- a/features/FEATURE_BLE/ble/GattCallbackParamTypes.h +++ b/features/FEATURE_BLE/ble/GattCallbackParamTypes.h @@ -17,6 +17,16 @@ #ifndef __GATT_CALLBACK_PARAM_TYPES_H__ #define __GATT_CALLBACK_PARAM_TYPES_H__ +/** + * Parameter of the callback invoked on a write operation. + * This parameter is used whether a GattServer as received a write operation or + * if the GattClient has completed a write operation. + * + * @important The fields connHandle, handle and writeOp are used in both + * callbacks while: + * - offset, len and data are reserved for GattServer write callbacks. + * - status and error_code are reserved for GattClient write callbacks. + */ struct GattWriteCallbackParams { /** * Enumeration for write operations. @@ -34,22 +44,48 @@ struct GattWriteCallbackParams { Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event. */ GattAttribute::Handle_t handle; /**< Attribute Handle to which the write operation applies. */ WriteOp_t writeOp; /**< Type of write operation. */ - uint16_t offset; /**< Offset for the write operation. */ - uint16_t len; /**< Length (in bytes) of the data to write. */ + + // Note: offset is used in GattServer while status is used in GattClient + union { + uint16_t offset; /**< Offset for the GattServer write operation. */ + ble_error_t status; /**< Status of the GattClient Write operation */ + }; + + // Note: len is used in GattServer while error_code is used in GattClient + union { + uint16_t len; /**< Length (in bytes) of the data to write (GattServer). */ + uint8_t error_code; /**< Error code of the GattClient Write operation */ + }; + /** * Pointer to the data to write. * * @note Data might not persist beyond the callback; make a local copy if * needed. + * @note This field is not used by callbacks invoked by the GattClient module. */ const uint8_t *data; }; +/** + * Parameter of the callback invoked on a read operation. + * This parameter is used whether a GattServer as received a read operation or + * if the GattClient has completed a read operation. + * + * @important The fields connHandle, handle and offset are used in both + * callbacks while: + * - len and data are reserved for GattServer read callbacks. + * - status and error_code are reserved for GattClient read callbacks. + */ struct GattReadCallbackParams { Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event. */ GattAttribute::Handle_t handle; /**< Attribute Handle to which the read operation applies. */ uint16_t offset; /**< Offset for the read operation. */ - uint16_t len; /**< Length (in bytes) of the data to read. */ + union { + uint16_t len; /**< Length (in bytes) of the data to read. */ + uint8_t error_code; /**< Error code if any (GattClient) */ + }; + /** * Pointer to the data read. * @@ -57,6 +93,7 @@ struct GattReadCallbackParams { * needed. */ const uint8_t *data; + ble_error_t status; /**< Status of the operation BLE_ERROR_NONE in case of success or the error in case of error */ }; enum GattAuthCallbackReply_t { diff --git a/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp index 299b029f4ec..057b151edac 100644 --- a/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp @@ -367,11 +367,11 @@ void ArmGattServer::attCback(attEvt_t *pEvt) uint8_t ArmGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) { GattReadCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .offset = offset, - .len = *pAttr->pLen, - .data = pAttr->pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .offset = */ offset, + /* .len = */ *pAttr->pLen, + /* .data = */ pAttr->pValue }; getInstance().handleDataReadEvent(&cbParams); @@ -410,12 +410,12 @@ uint8_t ArmGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_ } GattWriteCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .writeOp = writeOp, - .offset = offset, - .len = len, - .data = pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .writeOp = */ writeOp, + /* .offset = */ offset, + /* .len = */ len, + /* .data = */ pValue }; getInstance().handleDataWrittenEvent(&cbParams); diff --git a/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp index c381e733f55..f303c23d068 100644 --- a/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp @@ -383,11 +383,11 @@ void MaximGattServer::attCback(attEvt_t *pEvt) uint8_t MaximGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) { GattReadCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .offset = offset, - .len = *pAttr->pLen, - .data = pAttr->pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .offset = */ offset, + /* .len = */ *pAttr->pLen, + /* .data = */ pAttr->pValue }; getInstance().handleDataReadEvent(&cbParams); @@ -426,12 +426,12 @@ uint8_t MaximGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint } GattWriteCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .writeOp = writeOp, - .offset = offset, - .len = len, - .data = pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .writeOp = */ writeOp, + /* .offset = */ offset, + /* .len = */ len, + /* .data = */ pValue }; getInstance().handleDataWrittenEvent(&cbParams); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp index d6f815d64ec..fdf0ec76ca5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp @@ -63,11 +63,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_READ_RSP: { GattReadCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle, - .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle, + /* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; gattClient.processReadResponse(&response); } @@ -75,12 +75,12 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_WRITE_RSP: { GattWriteCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle, - .writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), - .offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle, + /* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), + /* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; gattClient.processWriteResponse(&response); } @@ -88,11 +88,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_HVX: { GattHVXCallbackParams params; - params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle; - params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle; - params.type = static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); - params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; - params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; + /* params.connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle; + /* params.handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle; + /* params.type = */ static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); + /* params.len = */ p_ble_evt->evt.gattc_evt.params.hvx.len; + /* params.data = */ p_ble_evt->evt.gattc_evt.params.hvx.data; gattClient.processHVXEvent(¶ms); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp index 4c5365f1b70..26f53848f8d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp @@ -440,12 +440,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.write.op), + /* .offset = */ gattsEventP->params.write.offset, + /* .len = */ gattsEventP->params.write.len, + /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; @@ -480,12 +480,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.authorize_request.request.write.op), + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp index 99059f6623a..8090e8498b0 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp @@ -63,11 +63,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_READ_RSP: { GattReadCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle, - .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle, + /* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; gattClient.processReadResponse(&response); } @@ -75,12 +75,12 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_WRITE_RSP: { GattWriteCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle, - .writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), - .offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle, + /* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), + /* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; gattClient.processWriteResponse(&response); } @@ -88,11 +88,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_HVX: { GattHVXCallbackParams params; - params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle; - params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle; - params.type = static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); - params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; - params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; + /* params.connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle; + /* params.handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle; + /* params.type = */ static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); + /* params.len = */ p_ble_evt->evt.gattc_evt.params.hvx.len; + /* params.data = */ p_ble_evt->evt.gattc_evt.params.hvx.data; gattClient.processHVXEvent(¶ms); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp index 4a520305246..2a1c0af1a68 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp @@ -503,12 +503,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.write.op), + /* .offset = */ gattsEventP->params.write.offset, + /* .len = */ gattsEventP->params.write.len, + /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; @@ -539,7 +539,7 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) if (req->length == 0) { req->attr_handle = input_req.handle; req->offset = input_req.offset; - } else { + } else { // it should be the subsequent write if ((req->offset + req->length) != input_req.offset) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply); @@ -627,12 +627,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply); GattWriteCallbackParams writeParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .writeOp = static_cast(input_req.op), - .offset = req->offset, - .len = req->length, - .data = req->data, + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .writeOp = */ static_cast(input_req.op), + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, }; handleDataWrittenEvent(&writeParams); releaseLongWriteRequest(conn_handle); @@ -649,7 +649,7 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; - + ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, .params = { @@ -662,12 +662,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } } }; - + if (reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { reply.params.write.update = 0; } - + sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); /* @@ -679,12 +679,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.authorize_request.request.write.op), + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } @@ -789,4 +789,4 @@ void nRF5xGattServer::releaseAllWriteRequests() { req.data = NULL; } } -} \ No newline at end of file +} From daaa5b19771e27af15b2cc9f18119182f734108e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 10:55:31 +0100 Subject: [PATCH 23/29] BLE: Introduce GenericGattClient and platform abstraction over ATT/GATT. This changes introduce a platform adaptation over ATT/GATT that can be implemented by porter. Unlike the GattClient interface, the ATT/GATT adaptation is simple, follow closely the Bluetooth specification and won't change over time. Implementation of the GattClient interface is realized by the class GenericGattClient which accept in input a pal::GattClient. This change will also free design space once adopted by partners, addition to the GattClient interface won't require partner support. --- .../ble/generic/GenericGattClient.h | 154 ++ features/FEATURE_BLE/ble/pal/AttClient.h | 687 +++++++++ .../ble/pal/AttClientToGattClientAdapter.h | 297 ++++ .../FEATURE_BLE/ble/pal/AttServerMessage.h | 772 ++++++++++ features/FEATURE_BLE/ble/pal/PalGattClient.h | 642 ++++++++ .../ble/pal/SimpleAttServerMessage.h | 232 +++ .../source/generic/GenericGattClient.cpp | 1342 +++++++++++++++++ 7 files changed, 4126 insertions(+) create mode 100644 features/FEATURE_BLE/ble/generic/GenericGattClient.h create mode 100644 features/FEATURE_BLE/ble/pal/AttClient.h create mode 100644 features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h create mode 100644 features/FEATURE_BLE/ble/pal/AttServerMessage.h create mode 100644 features/FEATURE_BLE/ble/pal/PalGattClient.h create mode 100644 features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h create mode 100644 features/FEATURE_BLE/source/generic/GenericGattClient.cpp diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h new file mode 100644 index 00000000000..8b525e8d06e --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -0,0 +1,154 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef MBED_BLE_GENERIC_GATT_CLIENT +#define MBED_BLE_GENERIC_GATT_CLIENT + +#include +#include "ble/GattClient.h" +#include "ble/pal/PalGattClient.h" + +// IMPORTANT: private header. Not part of the public interface. + +namespace ble { +namespace generic { + +// forward declarations +struct procedure_control_block_t; +struct discovery_control_block_t; +struct read_control_block_t; +struct write_control_block_t; +struct descriptor_discovery_control_block_t; + +/** + * Generic implementation of the GattClient. + * It requires a pal::GattClient injected at construction site. + * @important: Not part of the public interface of BLE API. + */ +class GenericGattClient : public GattClient { + + // give access to control block classes + friend struct procedure_control_block_t; + friend struct discovery_control_block_t; + friend struct read_control_block_t; + friend struct write_control_block_t; + friend struct descriptor_discovery_control_block_t; + +public: + /** + * Create a GenericGattClient from a pal::GattClient + */ + GenericGattClient(pal::GattClient* pal_client); + + /** + * @see GattClient::launchServiceDiscovery + */ + virtual ble_error_t launchServiceDiscovery( + Gap::Handle_t connection_handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + const UUID& matching_service_uuid, + const UUID& matching_characteristic_uuid + ); + + /** + * @see GattClient::isServiceDiscoveryActive + */ + virtual bool isServiceDiscoveryActive() const; + + /** + * @see GattClient::terminateServiceDiscovery + */ + virtual void terminateServiceDiscovery(); + + /** + * @see GattClient::read + */ + virtual ble_error_t read( + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + uint16_t offset + ) const; + + /** + * @see GattClient::write + */ + virtual ble_error_t write( + GattClient::WriteOp_t cmd, + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + size_t length, + const uint8_t* value + ) const; + + /** + * @see GattClient::onServiceDiscoveryTermination + */ + virtual void onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback + ); + + /** + * @see GattClient::discoverCharacteristicDescriptors + */ + virtual ble_error_t discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ); + + /** + * @see GattClient::isCharacteristicDescriptorDiscoveryActive + */ + virtual bool isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic& characteristic + ) const; + + /** + * @see GattClient::terminateCharacteristicDescriptorDiscovery + */ + virtual void terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic& characteristic + ); + + /** + * @see GattClient::reset + */ + virtual ble_error_t reset(void); + +private: + procedure_control_block_t* get_control_block(Gap::Handle_t connection); + const procedure_control_block_t* get_control_block(Gap::Handle_t connection) const; + void insert_control_block(procedure_control_block_t* cb) const; + void remove_control_block(procedure_control_block_t* cb) const; + + void on_termination(Gap::Handle_t connection_handle); + void on_server_message_received(connection_handle_t, const pal::AttServerMessage&); + void on_server_response(connection_handle_t, const pal::AttServerMessage&); + void on_server_event(connection_handle_t, const pal::AttServerMessage&); + void on_transaction_timeout(connection_handle_t); + + uint16_t get_mtu(Gap::Handle_t connection) const; + + pal::GattClient* const _pal_client; + ServiceDiscovery::TerminationCallback_t _termination_callback; + mutable procedure_control_block_t* control_blocks; +}; + +} +} + +#endif /* MBED_BLE_GENERIC_GATT_CLIENT */ diff --git a/features/FEATURE_BLE/ble/pal/AttClient.h b/features/FEATURE_BLE/ble/pal/AttClient.h new file mode 100644 index 00000000000..56bd1a2f062 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttClient.h @@ -0,0 +1,687 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_PAL_ATTCLIENT_H_ +#define BLE_PAL_ATTCLIENT_H_ + +#include "ble/UUID.h" +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" +#include "ble/blecommon.h" +#include "platform/Callback.h" +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Send attribute protocol requests to an ATT server. It also handle reception + * of ATT response and server indication/notification. + * + * Every request send and response or response event received is for a specified + * connection. + * + * @warning This class should not be used outside mbed BLE, availability is not + * guaranteed for all ports. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F + */ +struct AttClient { + /** + * Initialization of the instance. An implementation can use this function + * to initialise the subsystems needed to realize the ATT operations of this + * interface. + * + * This function has to be called before any other operations. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t initialize() = 0; + + /** + * Termination of the instance. An implementation can use this function + * to release the subsystems initialised to realise the ATT operations of + * this interface. + * + * After a call to this function, initialise should be called again to + * allow usage of the interface. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t terminate() = 0; + + /** + * Send an exchange MTU request which negotiate the size of the MTU used by + * the connection. + * + * First the client send to the server the maximum rx mtu that it can receive + * then the client reply with the maximum rx mtu it can receive. + * + * The mtu choosen for the connection is the minimum of the client Rx mtu + * and server Rx mtu values. + * + * If an error occured then the mtu used remains the default value. + * + * @param connection The handle of the connection to send this request to. + * + * @return BLE_ERROR_NONE if the request has been succesfully sent or the + * appropriate error otherwise. + * + * @see ble::pal::AttExchangeMTUResponse The type of response received from + * the server + * @see ble::pal::AttErrorResponse::REQUEST_NOT_SUPPORTED The error code + * returned by the server in case of error. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.1 + */ + virtual ble_error_t exchange_mtu_request(connection_handle_t connection) = 0; + + /** + * Acquire the size of the mtu for a given connection. + * + * @param connection The handle of the connection for which the the MTU size + * should be acquired. + * + * @param mtu_size Output parameter which will contain the MTU size. + * + * @return BLE_ERROR_NONE if the MTU size has been acquired or the + * appropriate error otherwise. + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) = 0; + + /** + * Send a find information request to a server in order to obtain the + * mapping of attribute handles with their associated types. + * + * The server will reply with a ble::pal::AttFindInformationResponse + * containing at least one [attribute handle, attribute type] pair. If the + * last handle in the response is not equal to the end handle of the finding + * range then this request can be issued again with an updated range (begin + * equal to last handle received + 1) to discover the remaining attributes. + * + * To discover the whole ATT server, the first find information request + * should have a discovery range of [0x0001 - 0xFFFF]. + * + * The server can send a ble::pal::AttErrorResponse with the code + * ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND if no attributes have + * been found in the range specified. The attribute handle in the response + * is then equal to the first handle of the discovery range. + * + * If the range is malformed the server will reply a + * ble::pal::AttErrorResponse with the error code ble::pal::INVALID_HANDLE. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param discovery_range The attribute range where handle-type informations + * should be discovered. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.1 + */ + virtual ble_error_t find_information_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) = 0; + + /** + * Send a Find By Type Value Request which retrieve the handles of attributes + * that have known 16-bit UUID attribute type and known attribute value. + * + * The server should reply with a ble::pal::AttFindByTypeValueResponse + * containing the handle (or handle range in case of grouping attributes) of + * the attribute found. + * + * If not all attributes can be contained in the response it is necessary to + * send again this request with an updated range to continue the discovery. + * + * The server can send a ble::pal::AttErrorResponse with the code + * ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND if no attributes have + * been found in the range specified. The attribute handle in the response + * is then equal to the first handle of the discovery range. + * + * If the range is malformed the server will reply a + * ble::pal::AttErrorResponse with the error code ble::pal::INVALID_HANDLE. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param discovery_range The handle range where attributes with type and + * value are searched. + * @param type The type of attribute to find (it is a 16 bit UUID). + * @param value The value of the attributes to found. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.3 + */ + virtual ble_error_t find_by_type_value_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range, + uint16_t type, + const ArrayView& value + ) = 0; + + /** + * Send a Read By Type Request used to obtain the values of attributes where + * the attribute type is known but the handle is not known. + * + * If attributes with the type requested are present in the range, the server + * should reply with a ble::pal::AttReadByTypeResponse. If the response does + * not cover the full range, the request should be sent again with an updated + * range. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND: If there is no + * attributes matching type in the range. + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the range is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param read_range The handle range where attributes with the given type + * should be read. + * @param type The type of attributes to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.1 + */ + virtual ble_error_t read_by_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& type + ) = 0; + + /** + * Send a Read Request to read the value of an attribute in the server. + * + * In case of success, the server will reply with a ble::pal::AttReadResponse. + * containing the value of the attribute. If the length of the value in the + * response is equal to (mtu - 1) then the remaining part of the value can + * be obtained by a read_blob_request. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the attribute handle + * is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.3 + */ + virtual ble_error_t read_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) = 0; + + /** + * Send a read blob request to a server to read a part of the value of an + * attribute at a given offset. + * + * In case of success, the server will reply with a ble::pal::AttReadBlobResponse + * containing the value read. If the value of the attribute starting at the + * offset requested is longer than (mtu - 1) octets then only the first + * (mtu - 1) octets will be present in the response. + * The remaining octets can be acquired by another Read Blob Request with an + * updated index. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the attribute handle + * is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * - ble::pal::AttErrorResponse::INVALID_OFFSET: If the offset is greater + * than the attribute length. + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_LONG: If the attribute + * value has a length that is less than or equal to (mtu - 1). + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to read. + * @param offset The offset of the first octet to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.5 + */ + virtual ble_error_t read_blob_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) = 0; + + /** + * Send a read multiple request to the server. It is used to read two or more + * attributes values at once. + * + * In case of success, the server will reply with a + * ble::pal::AttReadMultipleResponse containing the concatenation of the + * values read. Given that values are concatained, all attributes values + * should be of fixed size except for the last one. The concatained value + * is also truncated to (mtu - 1) if it doesn't fit in the response. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If any of the attribute + * handle is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to read any of the attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to read any of the attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to read any of the + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to read any of the attributes. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If any of the + * attributes value cannot be read. + * The first attribute causing the error is reporter in the handle_in_error + * field in the error response. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handles Set of attribute handles to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.7 + */ + virtual ble_error_t read_multiple_request( + connection_handle_t connection_handle, + const ArrayView& attribute_handles + ) = 0; + + /** + * Send a read by group type request to the server. It is used to get + * informations about grouping attribute of a given type on a server. + * + * The server will reply with a ble::pal::ReadByGroupTypeResponse containing + * informations about the grouping attribute found. Informations are: + * - handle of the grouping attribute. + * - last handle of the group . + * - attribute value. + * + * If the last handle received is not the last handle of the discovery range + * then it is necessary to send another request with a discovery range + * updated to: [last handle + 1 : end]. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the range of handle + * provided is invalid. + * - ble::pal::AttErrorResponse::UNSUPPORTED_GROUP_TYPE: if the group type + * is not a supported grouping attribute. + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND: If no attribute with + * the given type exists within the range provided. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to read the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to read the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to read the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to read the requested attributes. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If any of the + * attributes value cannot be read. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param read_range Range where this request apply. + * @param group_type Type of the grouping attribute to find and read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.9 + */ + virtual ble_error_t read_by_group_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& group_type + ) = 0; + + /** + * Send a write request to the server to write the value of an attribute. + * + * In case of success, the server will reply with a + * ble::pal::AttWriteResponse to acknowledge that the write operation went + * well. + * + * If the attribute value has a variable length, then the attribute value + * shall be truncated or lengthened to match the length of the value in the + * request. + * + * If the attribute value has a fixed length and the Attribute Value parameter length + * is less than or equal to the length of the attribute value, the octets of the + * attribute value parameter length shall be written; all other octets in this attribute + * value shall be unchanged. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the handle to write is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to write the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to write the requested attributes. + * - ble::pal::AttErrorResponse::WRITE_NOT_PERMITTED: If the attribute + * value cannot be written due to permission. + * - ble::pal::AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: If the + * value to write exceeds the maximum valid length or of the attribute + * value; whether the attribute has a variable length value or a fixed + * length value. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 3). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.1 + */ + virtual ble_error_t write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a write command to the server. A write command is similar to a write + * request except that it won't receive any response from the server + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 3). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.3 + */ + virtual ble_error_t write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a signed write command to the server. Behaviour is similar to a write + * command except that 12 bytes of the mtu are reserved for the authentication + * signature. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 15). + * + * @note the authentication signature to send with this request is + * computed by the implementation following the rules defined in BLUETOOTH + * SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.4 + */ + virtual ble_error_t signed_write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * The Prepare Write Request is used to request the server to prepare to + * write the value of an attribute. The client can send multiple prepare + * write request which will be put in a queue until the client send an + * Execute Write Request which will execute sequentially the write request + * in the queue. + * + * In case of success the server will respond with a + * ble::pal::AttPrepareWriteResponse containing the values (attribute handle, + * offset and value) present in the write request. + * + * If a prepare write request is rejected by the server, the state queue of + * the prepare write request queue remains unaltered. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the handle to write is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to write the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to write the requested attributes. + * - ble::pal::AttErrorResponse::WRITE_NOT_PERMITTED: If the attribute + * value cannot be written due to permission. + * - ble::pal::PREPARE_QUEUE_FULL: If the queue of prepare write request + * is full. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to be written. + * @param offset The offset of the first octet to be written. + * @param value The value of the attribute to be written. It can't be longer + * than (mtu - 5). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.1 + * + */ + virtual ble_error_t prepare_write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset, + const ArrayView& value + ) = 0; + + /** + * Send an Execute Write Request to the server. This request will instruct + * the server to execute or cancel the prepare write requests currently held + * in the prepare queue from this client. + * + * If the execute parameter is set to true, the server should execute the + * request held in the queue. If the parameter is equal to false then the + * server should cancel the requests in the queue. + * + * In case of success, the server will respond with a + * ble::pal::AttExecuteWriteResponse indicating that the request was correctly + * handled. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_OFFSET: If the value offset is + * greater than the current length of the attribute to write. + * - ble::pal::AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: If the + * length of the value write exceeds the length of the attribute value + * about to be written. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * The error response will contains the attribute handle which as caused the + * error and the remaining of the prepare queue is discarded. The state of + * the attributes that were to be written from the prepare queue is not + * defined in this case. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param execute Boolean indicating if the prepare queue should be executed + * or cleared. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.3 + */ + virtual ble_error_t execute_write_request( + connection_handle_t connection_handle, + bool execute + ) = 0; + + /** + * Register a callback which will handle messages from the server. + * + * @param cb The callback object which will handle messages from the server. + * It accept two parameters in input: The handle of the connection where the + * message was received and the message received. Real type of the message + * can be obtained from its opcode. + */ + void when_server_message_received( + mbed::Callback cb + ) { + _server_message_cb = cb; + } + + /** + * Register a callback handling transaction timeout. + * + * @param cb The callback handling timeout of a transaction. It accepts as + * a parameter the connection handle involved in the timeout. + * + * @note No more attribute protocol requests, commands, indication or + * notification shall be sent over a connection implied in a transaction + * timeout. To send a new ATT message, the conenction should be + * reestablished. + */ + void when_transaction_timeout( + mbed::Callback cb + ) { + _transaction_timeout_cb = cb; + } + +protected: + AttClient() { } + + virtual ~AttClient() { } + + /** + * Upon server message reception an implementation shall call this function. + * + * @param connection_handle The handle of the connection which has received + * the server message. + * @param server_message The message received from the server. + */ + void on_server_event( + connection_handle_t connection_handle, + const AttServerMessage& server_message + ) { + if (_server_message_cb) { + _server_message_cb(connection_handle, server_message); + } + } + + /** + * Upon transaction timeout an implementation shall call this function. + * + * @param connection_handle The handle of the connection of the transaction + * which has times out. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3 + */ + void on_transaction_timeout( + connection_handle_t connection_handle + ) { + if (_transaction_timeout_cb) { + _transaction_timeout_cb(connection_handle); + } + } + +private: + /** + * Callback called when the client receive a message from the server. + */ + mbed::Callback _server_message_cb; + + /** + * Callback called when a transaction times out. + */ + mbed::Callback _transaction_timeout_cb; + + // Disallow copy construction and copy assignment. + AttClient(const AttClient&); + AttClient& operator=(const AttClient&); +}; + + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_ATTCLIENT_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h new file mode 100644 index 00000000000..d99a55e4978 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -0,0 +1,297 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ +#define BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ + +#include "AttClient.h" +#include "PalGattClient.h" + +namespace ble { +namespace pal { + +/** + * Adapt a pal::AttClient into a pal::GattClient. + * + * This class let vendors define their abstraction layer in term of an AttClient + * and adapt any AttClient into a GattClient. + */ +class AttClientToGattClientAdapter : public GattClient { + +public: + static const uint16_t END_ATTRIBUTE_HANDLE = 0xFFFF; + static const uint16_t SERVICE_TYPE_UUID = 0x2800; + static const uint16_t INCLUDE_TYPE_UUID = 0x2802; + static const uint16_t CHARACTERISTIC_TYPE_UUID = 0x2803; + + /** + * Construct an instance of GattClient from an instance of AttClient. + * @param client The client to adapt. + */ + AttClientToGattClientAdapter(AttClient& client) : + GattClient(), _client(client) { + _client.when_server_message_received( + mbed::callback(this, &AttClientToGattClientAdapter::on_server_event) + ); + _client.when_transaction_timeout( + mbed::callback( + this, &AttClientToGattClientAdapter::on_transaction_timeout + ) + ); + } + + /** + * @see ble::pal::GattClient::exchange_mtu + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection) { + return _client.exchange_mtu_request(connection); + } + + /** + * @see ble::pal::GattClient::get_mtu_size + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) { + return _client.get_mtu_size(connection_handle, mtu_size); + } + + /** + * @see ble::pal::GattClient::discover_primary_service + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ) { + return _client.read_by_group_type_request( + connection, + attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE), + SERVICE_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_primary_service_by_service_uuid + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_begining, + const UUID& uuid + ) { + return _client.find_by_type_value_request( + connection_handle, + attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE), + SERVICE_TYPE_UUID, + ArrayView( + uuid.getBaseUUID(), + (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) ? 2 : UUID::LENGTH_OF_LONG_UUID + ) + ); + } + + /** + * @see ble::pal::GattClient::find_included_service + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ) { + return _client.read_by_type_request( + connection_handle, + service_range, + INCLUDE_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_characteristics_of_a_service + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) { + return _client.read_by_type_request( + connection_handle, + discovery_range, + CHARACTERISTIC_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_characteristics_descriptors + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ) { + return _client.find_information_request( + connection_handle, + descriptors_discovery_range + ); + } + + /** + * @see ble::pal::GattClient::read_attribute_value + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) { + return _client.read_request( + connection_handle, + attribute_handle + ); + } + + /** + * @see ble::pal::GattClient::read_using_characteristic_uuid + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ) { + return _client.read_by_type_request( + connection_handle, + read_range, + uuid + ); + } + + /** + * @see ble::pal::GattClient::read_attribute_blob + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) { + return _client.read_blob_request( + connection_handle, + attribute_handle, + offset + ); + } + + /** + * @see ble::pal::GattClient::read_multiple_characteristic_values + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection_handle, + const ArrayView& characteristic_value_handles + ) { + return _client.read_multiple_request( + connection_handle, + characteristic_value_handles + ); + } + + /** + * @see ble::pal::GattClient::write_without_response + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) { + return _client.write_command( + connection_handle, + characteristic_value_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::signed_write_without_response + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) { + return _client.signed_write_command( + connection_handle, + characteristic_value_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::write_attribute + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + return _client.write_request( + connection_handle, + attribute_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::queue_prepare_write + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) { + return _client.prepare_write_request( + connection_handle, + characteristic_value_handle, + offset, + value + ); + } + + /** + * @see ble::pal::GattClient::execute_write_queue + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ) { + return _client.execute_write_request(connection_handle, execute); + } + + /** + * @see ble::pal::GattClient::initialize + */ + virtual ble_error_t initialize() { + return _client.initialize(); + } + + /** + * @see ble::pal::GattClient::terminate + */ + virtual ble_error_t terminate() { + return _client.initialize(); + } + +private: + AttClient& _client; +}; + +} // namespace pal +} // namespace ble + + +#endif /* BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/AttServerMessage.h b/features/FEATURE_BLE/ble/pal/AttServerMessage.h new file mode 100644 index 00000000000..5a61850bbf8 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttServerMessage.h @@ -0,0 +1,772 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_PAL_ATT_SERVER_MESSAGE_H_ +#define BLE_PAL_ATT_SERVER_MESSAGE_H_ + +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" + +namespace ble { +namespace pal { + +/** + * Operation code defined for attribute operations + * @note see: BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.8 + */ +struct AttributeOpcode { + enum Code { + ERROR_RESPONSE = 0x01, /// Opcode of an AttErrorResponse + EXCHANGE_MTU_REQUEST = 0x02, + EXCHANGE_MTU_RESPONSE = 0x03, /// OpCode of an AttExchangeMTUResponse + FIND_INFORMATION_REQUEST = 0x04, + FIND_INFORMATION_RESPONSE = 0x05, /// OpCode of an AttFindInformationResponse + FIND_BY_TYPE_VALUE_REQUEST = 0x06, + FIND_BY_VALUE_TYPE_RESPONSE = 0x07, /// OpCode of an AttFindByTypeValueResponse + READ_BY_TYPE_REQUEST = 0x08, + READ_BY_TYPE_RESPONSE = 0x09, /// Opcode of an AttReadByTypeResponse + READ_REQUEST = 0x0A, + READ_RESPONSE = 0x0B, /// Opcode of an AttReadResponse + READ_BLOB_REQUEST = 0x0C, + READ_BLOB_RESPONSE = 0x0D, /// Opcode of an AttReadBlobResponse + READ_MULTIPLE_REQUEST = 0x0E, + READ_MULTIPLE_RESPONSE = 0x0F, /// Opcode of an AttReadMultipleResponse + READ_BY_GROUP_TYPE_REQUEST = 0x10, + READ_BY_GROUP_TYPE_RESPONSE = 0x11, /// Opcode of an AttReadByGroupTypeResponse + WRITE_REQUEST = 0x12, + WRITE_RESPONSE = 0x13, /// Opcode of an AttWriteResponse + WRITE_COMMAND = 0x52, + SIGNED_WRITE_COMMAND = 0xD2, + PREPARE_WRITE_REQUEST = 0x16, + PREPARE_WRITE_RESPONSE = 0x17, /// Opcode of an AttPrepareWriteResponse + EXECUTE_WRITE_REQUEST = 0x18, + EXECUTE_WRITE_RESPONSE = 0x19, /// Opcode of an AttExecuteWriteResponse + HANDLE_VALUE_NOTIFICATION = 0x1B, + HANDLE_VALUE_INDICATION = 0x1D + }; + + /** + * Construct an AttributeOpcode from a Code. + */ + AttributeOpcode(Code value) : _value(value) { } + + /** + * Equality comparison operator between two AttributeOpcode + */ + friend bool operator==(AttributeOpcode lhs, AttributeOpcode rhs) { + return lhs._value == rhs._value; + } + + /** + * Non equality comparison operator between two AttributeOpcode + */ + friend bool operator!=(AttributeOpcode lhs, AttributeOpcode rhs) { + return lhs._value != rhs._value; + } + + /** + * implicit cast to uint8_t. + * Allows AttributeOpcode to be used in switch statements. + */ + operator uint8_t() const { + return _value; + } + +private: + uint8_t _value; +}; + + + +/** + * Base class for Attribute Server Message. + * The correct type of the instance can be determined with the attribute opcode. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1 + */ +struct AttServerMessage { + /** + * Op code used to identify the type of the attribute response. + */ + const AttributeOpcode opcode; + +protected: + /** + * Construction of an AttResponse is reserved for descendent of the class + */ + AttServerMessage(AttributeOpcode opcode_) : opcode(opcode_) { } +}; + + +/** + * Response to a request which can't be performed + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.1.1 + * for details about error response. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.9 + * which details possible error response by requests. + */ +struct AttErrorResponse : public AttServerMessage { + /** + * Construct an attribute error response. + * + * @param request_opcode_ The Attribute opcode of the request that generated + * the error. + * @param handle_in_error_ The attribute handle that generated this error + * response. + * @param error_code The reason why the request has generated an error. + */ + AttErrorResponse( + AttributeOpcode request_opcode_, + attribute_handle_t handle_in_error_, + uint8_t error_code_ + ) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE), + request_opcode(request_opcode_), + handle_in_error(handle_in_error_), error_code(error_code_) { + } + + /** + * Construct an attribute error response in the case where there was no + * attribute handle in the original response or if the request is not + * supported. + * + * @param request_opcode_ The Attribute opcode of the request that generated + * the error. + * @param error_code The reason why the request has generated an error. + */ + AttErrorResponse( + AttributeOpcode request_opcode_, + uint8_t error_code_ + ) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE), + request_opcode(request_opcode_), + handle_in_error(0x0000), error_code(error_code_) { + } + + /** + * The opcode of the request that generated this error response. + */ + const AttributeOpcode request_opcode; + + /** + * The attribute handle that generated this error response. + * If there was no attribute handle in the original request or if the + * request is not supported, then this field is equal to 0x0000. + */ + const attribute_handle_t handle_in_error; + + /** + * The reason why the request has generated an error response + */ + const uint8_t error_code; + + /** + * List of Error codes for the ATT protocol + */ + enum AttributeErrorCode { + /** The attribute handle given was not valid on this server. */ + INVALID_HANDLE = 0x01, + + /** The attribute cannot be read. */ + READ_NOT_PERMITTED = 0x02, + + /** The attribute cannot be written. */ + WRITE_NOT_PERMITTED = 0x03, + + /** The attribute PDU was invalid. */ + INVALID_PDU = 0x04, + + /** The attribute requires authentication before it can be read or + * written. + */ + INSUFFICIENT_AUTHENTICATION = 0x05, + + /** Attribute server does not support the request received from the + * client. + */ + REQUEST_NOT_SUPPORTED = 0x06, + + /** Offset specified was past the end of the attribute. */ + INVALID_OFFSET = 0x07, + + /** The attribute requires authorization before it can be read or written. */ + INSUFFICIENT_AUTHORIZATION = 0x08, + + /** Too many prepare writes have been queued. */ + PREPARE_QUEUE_FULL = 0x09, + + /** No attribute found within the given attribute handle range. */ + ATTRIBUTE_NOT_FOUND = 0x0A, + + /** The attribute cannot be read using the Read Blob Request. */ + ATTRIBUTE_NOT_LONG = 0x0B, + + /** The Encryption Key Size used for encrypting this link is + * insufficient. + */ + INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0C, + + /** The attribute value length is invalid for the operation. */ + INVALID_ATTRIBUTE_VALUE_LENGTH = 0x0D, + + /** The attribute request that was requested has encountered an error + * that was unlikely, and therefore could not be completed as requested. + */ + UNLIKELY_ERROR = 0x0E, + + /** The attribute requires encryption before it can be read or written. */ + INSUFFICIENT_ENCRYPTION = 0x0F, + + /** The attribute type is not a supported grouping attribute as defined + * by a higher layer specification. + */ + UNSUPPORTED_GROUP_TYPE = 0x10, + + /** Insufficient Resources to complete the request. */ + INSUFFICIENT_RESOURCES = 0x11, + + /* 0x12 - 0x7F => reserved for future use */ + + /* 0x80 - 0x9F => Application Error */ + + /* 0xA0 0xDF => Reserved for future use */ + + /* 0xE0 - 0xFF Common Profile and service Error Codes */ + + /** The Write Request Rejected error code is used when a requested write + * operation cannot be fulfilled for reasons other than permissions. + */ + WRITE_REQUEST_REJECTED = 0xFC, + + /** The Client Characteristic Configuration Descriptor Improperly + * Configured error code is used when a Client Characteristic + * Configuration descriptor is not configured according to the + * requirements of the profile or service. + */ + CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_IMPROPERLY_CONFIGURED = 0xFD, + + /** The Procedure Already in Progress error code is used when a profile + * or service request cannot be serviced because an operation that has + * been previously triggered is still in progress + */ + PROCEDURE_ALREADY_IN_PROGRESS = 0xFE, + + /** The Out of Range error code is used when an attribute value is out + * of range as defined by a profile or service specification. + */ + OUT_OF_RANGE = 0xFF + }; +}; + + +/** + * The Exchange MTU Request is used by the client to inform the server of the + * client’s maximum receive MTU size and request the server to respond with its + * maximum rx MTU size. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.2 + */ +struct AttExchangeMTUResponse : public AttServerMessage { + /** + * Construct an exchange mtu response containing the max rx mtu of the + * server. + * + * @param server_rx_mtu_ The max rx mtu the server can handle. + */ + AttExchangeMTUResponse(uint16_t server_rx_mtu_) : + AttServerMessage(AttributeOpcode::EXCHANGE_MTU_RESPONSE), + server_rx_mtu(server_rx_mtu_) { + } + + /** + * The max rx mtu the server can handle. + */ + const uint16_t server_rx_mtu; +}; + + +/** + * The Find Information Response is sent in reply to a received Find Information + * Request and contains information about this server. + * + * The Find Information Response contains a sequence of handle-uuid pairs in + * ascending order if attribute handles. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.2 + */ +struct AttFindInformationResponse : public AttServerMessage { + + /** handle-uuid pair */ + struct information_data_t { + attribute_handle_t handle; + UUID uuid; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttFindInformationResponse() : + AttServerMessage(AttributeOpcode::FIND_INFORMATION_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttFindInformationResponse() { } + + /** + * Returns the number of information_data_t present in the response. + */ + virtual size_t size() const = 0; + + /** + * Access to information_data_t elements present in the response. + * @note Out of range access is undefined. + */ + virtual information_data_t operator[](size_t index) const = 0; +}; + + +/** + * Find by type value responses are sent in response to find by type value + * request. + * + * The response contains a sequence of Found Attribute Handle, Group End Handle + * pair where: + * - Found Attribute Handle is the handle of an attribute matching the type + * and the value requested. + * - Group End Handle is the end of the attribute group if the attribute found + * is a grouping attribute or the same value as Found Attribute Handle if + * the attribute is not a grouping attribute. + * + * This class should be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.4 + */ +struct AttFindByTypeValueResponse : public AttServerMessage { + /** + * Base constructor, setup the OpCode of the response. + */ + AttFindByTypeValueResponse() : + AttServerMessage(AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttFindByTypeValueResponse() { } + + /** + * Returns the number of attribute_handle_range_t present in the response. + */ + virtual std::size_t size() const = 0; + + /** + * Access to the attribute range present in the response. + * @note Out of range access is undefined. + */ + virtual attribute_handle_range_t operator[](size_t index) const = 0; +}; + + +/** + * Response to a Read By Type request. + * + * It contains a list of handle-value pairs where: + * - handle is the handle of the attribute matching the rype requested. + * - value is the value of the attribute found. If the value is longer than + * (mtu - 4) then it can be truncated and read blob request should be used + * to read the remaining octet of the attribute. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.2 + */ +struct AttReadByTypeResponse : public AttServerMessage { + /** + * handle-value pair + */ + struct attribute_data_t { + attribute_handle_t handle; + ArrayView value; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttReadByTypeResponse() : + AttServerMessage(AttributeOpcode::READ_BY_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttReadByTypeResponse() { } + + /** + * Return the number of attribute_data_t presents in the response. + */ + virtual size_t size() const = 0; + + /** + * Return the attribute data at index. + * @note Out of range access is undefined. + */ + virtual attribute_data_t operator[](size_t index) const = 0; +}; + + +/** + * The read response is sent in reply to a received Read Request and contains + * the value of the attribute that has been read. + * + * The attribute value shall be set to the value of the attribute identified by + * the attribute handle in the request. If the attribute value is longer than + * (ATT_MTU-1) then the first (ATT_MTU-1) octets shall be included in this + * response. + * + * @note The Read Blob Request would be used to read the remaining octets of a + * long attribute value. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.4 + */ +struct AttReadResponse : public AttServerMessage { + /** + * Construct a Read Response from an array of bytes. + */ + AttReadResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + + /** + * Return the pointer to the actual data + */ + const uint8_t* data() const { + return _data.data(); + } + +private: + const ArrayView _data; +}; + + +/** + * The Read Blob Response is sent in reply to a received Read Blob Request and + * contains part of the value of the attribute that has been read. + * + * If the offset requested is equal to the length of the attribute then the + * response contains no data and the size of the data returned is equal to 0. + * + * If the value of the attribute starting at the offset requested is longer than + * (mtu - 1) octets then the first (mtu - 1) will be present in the response. + * The remaining octets will be acquired by another Read Blob Request with an + * updated index. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.6 + */ +struct AttReadBlobResponse : public AttServerMessage { + /** + * Construct a read blob response from the value responded. + */ + AttReadBlobResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_BLOB_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response value. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet of the value read at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + + /** + * Return the pointer to the actual data + */ + const uint8_t* data() const { + return _data.data(); + } + +private: + const ArrayView _data; +}; + + +/** + * Response to a Read Multiple Request. It contains the values of the attributes + * that have been read. + * + * If the set of values that has been read is longer than (mtu - 1) then only + * the first (mtu - 1) octets are included in the response. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.8 + */ +struct AttReadMultipleResponse : public AttServerMessage { + /** + * Construct a Resd Multiple Response from the set of value received. + */ + AttReadMultipleResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_MULTIPLE_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response set of value. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet of the set of value read at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + +private: + const ArrayView _data; +}; + + +/** + * The Read By Group Type Response is sent in reply to a received Read By + * Group Type Request and contains the handles and values of the attributes that + * have been read. + * + * The response is a list of group range-value pair where: + * - group range: The range of the group found where begin is the grouping + * attribute handle and end is the handle of the end of the group. + * - value: The value of the grouping attribute. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note The value responded can be trucated if it doesn't fit in the response, + * in that case a Read Blob Request could be used to read the remaining octets. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.10 + */ +struct AttReadByGroupTypeResponse : public AttServerMessage { + /** + * Data read from the grouping attribute. + * It includes the range of the group and the value of the attribute. + */ + struct attribute_data_t { + attribute_handle_range_t group_range; + ArrayView value; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttReadByGroupTypeResponse() : + AttServerMessage(AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttReadByGroupTypeResponse() { } + + /** + * Return the number of attribute_data_t present in the response. + */ + virtual size_t size() const = 0; + + /** + * Return the attribute data read at the index specified. + * @note Out of range access is undefined. + */ + virtual attribute_data_t operator[](size_t index) const = 0; +}; + + +/** + * The Write Response is sent in reply to a valid Write Request and + * acknowledges that the attribute has been successfully written. + * It is just a placeholder which indicates the client that the write request + * was successful. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.2 + */ +struct AttWriteResponse : public AttServerMessage { + /** + * Construct a write response. + */ + AttWriteResponse() : AttServerMessage(AttributeOpcode::WRITE_RESPONSE) { } +}; + + +/** + * Response to a Prepare Write Request. It acknowledges the client that the + * value has been successfully received and placed in the write queue. + * + * The response contains the same values as the one present in the request. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.2 + */ +struct AttPrepareWriteResponse : public AttServerMessage { + /** + * Construct a prepare write response. + * @param handle_ The handle of the attribute to be written. + * @param offset_: The offset of the first octet to be writen. + * @param value_: The value of the attribute to be written at the offset + * indicated. + */ + AttPrepareWriteResponse( + attribute_handle_t handle_, + uint16_t offset_, + ArrayView value_ + ) : AttServerMessage(AttributeOpcode::PREPARE_WRITE_RESPONSE), + attribute_handle(handle_), + offset(offset_), + partial_value(value_) { + } + + /** + * The handle of the attribute to be written. + */ + const attribute_handle_t attribute_handle; + + /** + * The offset of the first octet to be writen. + */ + const uint16_t offset; + + /** + * The value of the attribute to be written at the offset indicated. + */ + const ArrayView partial_value; +}; + + +/** + * The Execute Write Response is sent in response to a received Execute Write + * Request. + * + * It is just a placeholder which indicates the client that the execution of the + * write request has been successfull. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.4 + */ +struct AttExecuteWriteResponse : public AttServerMessage { + /** + * Construct an execute write response object. + */ + AttExecuteWriteResponse() : + AttServerMessage(AttributeOpcode::EXECUTE_WRITE_RESPONSE) { + } +}; + + +/** + * Notification of an attribute's value sent by the server. + * + * It contains the handle of the attribute and its value. + * + * If the attribute value is longer than (mtu - 3) then the value is truncated + * to (mtu - 3) octets to fit in the response and the client will have to use + * a read blob request to read the remaining octets of the attribute. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.1 + */ +struct AttHandleValueNotification : public AttServerMessage { + /** + * Construct an Handle Value Notification from the attribute handle and its + * value notified. + */ + AttHandleValueNotification( + attribute_handle_t attribute_handle, + ArrayView attribute_value + ) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_NOTIFICATION), + attribute_handle(attribute_handle), + attribute_value(attribute_value) { + } + + /** + * Handle of the attribute + */ + const attribute_handle_t attribute_handle; + + /** + * The current value of the attribute. + */ + const ArrayView attribute_value; +}; + + +/** + * Indication of an attribute's value sent by the server. + * + * It contains the handle of the attribute and its value. The client should + * respond with and handle value confirmation. + * + * If the attribute value is longer than (mtu - 3) then the value is truncated + * to (mtu - 3) octets to fit in the response and the client will have to use + * a read blob request to read the remaining octets of the attribute. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.2 + */ +struct AttHandleValueIndication : public AttServerMessage { + /** + * Construct an Handle Value Indication from the attribute handle and its + * value indicated. + */ + AttHandleValueIndication( + attribute_handle_t handle, ArrayView value + ) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_INDICATION), + attribute_handle(handle), attribute_value(value) { + } + + /** + * Handle of the attribute + */ + const attribute_handle_t attribute_handle; + + /** + * The current value of the attribute. + */ + const ArrayView attribute_value; +}; + + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_ATT_SERVER_MESSAGE_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h new file mode 100644 index 00000000000..2152c428f43 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -0,0 +1,642 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_PAL_GATT_CLIENT_H_ +#define BLE_PAL_GATT_CLIENT_H_ + +#include "ble/UUID.h" +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" +#include "ble/blecommon.h" + +#include "platform/Callback.h" + +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Adaptation layer for a GATT client. + * + * Define the primitive necessary to implement a proper GATT client. These + * primitives are sometime GATT procedure, ATT procedure or a bit of both. + * + * In general, discovery procedures follow strictly GATT formulation while + * attribute manipulation procedures (read/write) follow the ATT formulation + * to avoid multiple identical implementation for characteristic values and + * characteristic descriptors value, it also fill a hole leave by the + * specification which doesn't define any GATT procedure to get the UUID of an + * included service with a 128 bit UUID. + * + * Complementary informations around ATT procedures can be found in the Section + * 3.4 of the Vol3, Part F of the Bluetooth specification while more informations + * around the GATT procedures can be found in the Section 4 of the Vol 3, Part + * G of the Bluetooth specification. + * + * Complete and compliant Gatt Client used by developer is realized at an higher + * level using the primitives defined in this adaptation layer. + * + * If a stack expose the complete ATT layer then it is possible to provide an + * implementation for GattClient by subclassing the AttClient class and use + * the class AttClientToGattClientAdapter + */ +class GattClient { + +public: + /** + * Initialisation of the instance. An implementation can use this function + * to initialise the subsystems needed to realize the operations of this + * interface. + * + * This function has to be called before any other operations. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t initialize() = 0; + + /** + * Termination of the instance. An implementation can use this function + * to release the subsystems initialised to realise the operations of + * this interface. + * + * After a call to this function, initialise should be called again to + * allow usage of the interface. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t terminate() = 0; + + /** + * Negotiate the mtu to use by this connection. + * First the client send to the server the maximum rx mtu that it can receive + * then the client reply with the maximum rx mtu it can receive. + * The mtu chosen for the connection is the minimum of the client Rx mtu + * and server Rx mtu values. + * + * If an error occurred then the mtu used remains the default value. + * + * The server will reply to this request with an AttExchangeMTUResponse in + * case of success or AttErrorResponse in case of failure. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.3.1 + * + * @param connection The handle of the connection to send this request to. + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection) = 0; + + /** + * Acquire the size of the mtu for a given connection. + * + * @param connection The handle of the connection for which the the MTU size + * should be acquired. + * + * @param mtu_size Output parameter which will contain the MTU size. + * + * @return BLE_ERROR_NONE if the MTU size has been acquired or the + * appropriate error otherwise. + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) = 0; + + /** + * Discover primary services in the range [begin - 0xFFFF]. + * + * If services exists in the range provided, the server will reply with a + * ReadByGoupType response where for each attribute_data exposed: + * - attribute_handle is the service attribute handle + * - end_group_handle is the last handle of the service + * - attribute_value is the UUID of the service. + * + * If the end of the range is not reached, this procedure can be relaunched + * with the last handle of the last service discovered plus one as the + * beginning of the discovery range. + * + * If there is not services left to discover in the range, the server can + * either: + * * Reply with an ErrorResponse with the Error code set to ATTRIBUTE_NOT_FOUND + * * Set the end handle of the last service to 0xFFFF. + * + * @note This function realize a partial implementation of the Discover All + * Primary Services procedure. The complete implementation of the procedure + * is realized at an higher level. + * @note This function issue a Read By Group Type ATT request where the + * type parameter is equal to Primary Service and the Ending Handle parameter + * is equal to 0xFFFF. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.1 + * + * @param connection The handle of the connection to send this request to. + * @param begin The beginning of the discovery range. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ) = 0; + + /** + * Discover primary services by UUID in the range [discovery_range_begining - 0xFFFF]. + * + * If services exists in the range provided, the server will reply with a + * FindByTypeValueResponse containing the attribute range of each service + * discovered. + * + * If the end of the range is not reached, this procedure can be relaunched + * with the last handle of the last service discovered plus one as the + * beginning of the discovery range. + * + * If there is not services left to discover in the range, the server can + * either: + * * Reply with an ErrorResponse with the Error code set to ATTRIBUTE_NOT_FOUND + * * Set the end handle of the last service to 0xFFFF. + * + * @note This function realize a partial implementation of the Discover + * Primary Service by Service UUID procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Find By Type Value ATT request where the + * type parameter is equal to Primary Service and the Ending Handle + * parameter is equal to 0xFFFF. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.2 + * + * @param connection The handle of the connection to send this request to. + * @param begin The beginning of the discovery range. + * @param uuid The UUID of the service to discover. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_beginning, + const UUID& uuid + ) = 0; + + /** + * Find included services within a service. + * + * If services are included in the service range then the server will reply + * with a ReadByTypeResponse where for each attribute record: + * - attribute_handle The handle where the service is included within the + * service definition. + * - attribute_data Contains two handles defining the range of the included. + * If the service found have a 16 bit uuid then its UUID is also included + * in the attribute data. + * + * If the end of the service range is not reached, this procedure can be + * relaunched with the handle of the last included service discovered plus + * one as the beginning of the new discovery range. + * + * The procedure is complete when either: + * - The server reply with an ErrorResponse with the Error code set to + * ATTRIBUTE_NOT_FOUND + * - An included service handle returned is equal to the end of the range. + * + * If the service UUID is a 128 bits one then it is necessary to issue a read + * attribute request on the first handle of the service discovered to get it. + * + * @note This function realize a partial implementation of the Find Included + * Services procedure. The complete implementation of the procedure is + * realized at an higher level. + * @note This function issue a Read By Type ATT request where the + * type parameter is equal to Include. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.5.1 + * + * @param connection The handle of the connection to send this request to. + * @param service_range The range of the service where service inclusion has + * to be discovered. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ) = 0; + + /** + * Find characteristic declarations within a service definition. + * + * If characteristic declarations are found within the range then the server + * should reply with a ReadByTypeResponse where for each attribute record: + * - attribute_handle is the handle of the characteristic definition + * - attribute_data contains the the following values attached to the + * characteristic : + * + properties: the properties of the characteristic. + * + value handle: the handle of the value of the characteristic. + * + uuid: the UUID of the characteristic. + * + * The procedure is considered complete when the server send an ErrorResponse + * with the ErrorCode set to ATTRIBUTE_NOT_FOUND or a ReadByType response + * has an attribute_handle set to the end of the discovery range. + * + * If the procedure is not complete after a server response, it should be + * relaunched with an updated range starting at the last attribute_handle + * discovered plus one. + * + * @note This function realize a partial implementation of the Discover All + * Characteristics of a Service procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Read By Type ATT request where the type + * parameter is equal to Characteristic. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.6.1 + * + * @note The GATT procedure Discover Characteristics by UUID is implemented + * at a higher level using this function as a base. + * + * @param connection The handle of the connection to send this request to. + * @param discovery_range The range of attributes where the characteristics + * are discovered. It should be contained within a service. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) = 0; + + /** + * Discover characteristic descriptors of a characteristic. + * + * If descriptors are found within the range provided then the server should + * reply with a FindInformationResponse containing a list of + * attribute_handle_t, UUID pairs where the attribute handle is the + * descriptor handle and UUID is the UUID of the descriptor. + * + * The procedure is complete when the server send an ErrorResponse with the + * error code ATTRIBUTE_NOT_FOUND or the FindInformationResponse has an + * attribute handle that is equal to the end handle of the discovery range. + * + * @note This function realize a partial implementation of the Discover All + * Characteristics Descriptors procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Find Information ATT request.. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.7.1 + * + * @note It should be possible to use this function to issue a regular + * ATT Find Information Request. + * + * @param connection The handle of the connection to send this request to. + * @param descriptors_discovery_range The range of attributes where the + * descriptors are discovered. The first handle shall be no less than the + * characteristic value handle plus one and the last handle shall be no more + * than the last handle of the characteristic. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ) = 0; + + /** + * Read the value of an attribute. + * + * The server will reply with an AttReadResponse. In case of error, the + * server will reply with an AttErrorResponse. + * + * @note This function issue an ATT Read Request. + * + * @note: This function is the base function for the read Characteristic + * Value and Read Characteristic Descriptor GATT procedures. It can also + * be used to read the 128 bit UUID of a service discovered with + * find_included_service. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.1 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.1 + * + * @param connection The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) = 0; + + /** + * Read a characteristic value using its UUID (type). + * + * The server will respond a ReadByTypeResponse containing a sequence of + * attribute handle and attribute value pairs. + * To read remaining attributes, the client should launch a new request + * with an updated range. + * + * The procedure is considered complete when the server respond with an + * ErrorResponse containing the ErrorCode ATTRIBUTE_NOT_FOUND or when an + * handle in the ReadByTypeResponse is equal to the end of the discovered + * range. + * + * @note This function realize a partial implementation of the Read Using + * Characteristics Characteristic procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Read By Type ATT request. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.2 + * + * @note It should be possible to use this function to issue a regular + * ATT Read By Type Request. + * + * @param connection The handle of the connection to send this request to. + * @param attribute_range Range of the handle where an attribute with + * uuid as type is present. + * @param uuid UUID of the characteristic(s) to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ) = 0; + + /** + * Read a partial value of an attribute. + * + * The server will respond with a ReadBlobResponse containing the data read + * or an ErrorResponse in case of error. + * + * The procedure is not complete as long as the value in response have the + * same size as the mtu minus one. If the procedure is not complete, it can + * be launch again with an updated offset to read the remaining part of the + * attribute value. + * + * @note This function issue an ATT Read Blob Request. + * + * @note: This function is the base function for the Read Long + * Characteristic Value and Read Long Characteristic Descriptor GATT + * procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.2 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to read. + * @param offset Beginning offset for the read operation. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) = 0; + + /** + * Read atomically multiple characteristics values. + * + * The server will respond with a ReadMultiple response containing the + * concatenation of the values of the characteristics. + * + * @note values might be truncated + * + * In case of error, the server should respond a with an ErrorResponse. + * + * @note This function issue an ATT Read Multiple Request. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.4 + * + * @param connection_handle The handle of the connection to send this request to. + * @param characteristic_value_handles Handle of the characteristic values + * to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection_handle, + const ArrayView& characteristic_value_handles + ) = 0; + + /** + * Send a write command to the server. + * + * @note This function issue an ATT Write Command. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.1 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) = 0; + + /** + * Send a Signed Write without Response command to the server. + * + * @note This function issue an ATT Write Command with the signed flag and + * the signature. + * + * @note signature is calculated by the stack. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.2 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) = 0; + + /** + * Send a write request to the server. + * + * The server should respond with a WriteResponse in case of success or an + * ErrorResponse in case of error. + * + * @note This function issue an ATT Write Request. + * + * @note: This function is the base function for the Write Characteristic + * Value and Write Characteristic Descriptors GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.3 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a prepare write request to the server. + * + * The write request will go into a queue until the client execute or cancel + * the request with an execute write request which will write all the values + * in the queue atomically. + * + * The server should respond with a PrepareWriteResponse containing the + * content of the request in case of success and an ErrorResponse in case of + * error. + * + * If an ErrorResponse is received it doesn't invalidate what is already in + * the queue. + * + * @note This function issue an ATT Prepare Write Request. + * + * @note: This function is one of the base function for the Write Long + * Characteristic Value and Reliable Writes GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.4 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.5 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * @param offset offset where the value should be written. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) = 0; + + /** + * Send a request to the server to execute the queue of prepared write + * requests. + * + * The server should respond with an ExecuteWriteResponse in case of success + * and an Error response in case of failure. + * + * @note This function issue an ATT Execute Write Request. + * + * @note: This function is one of the base function for the Write Long + * Characteristic Value and Reliable Writes GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.4 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.5 + * + * @param connection_handle The handle of the connection to send this request to. + * @param execute If true, execute the write request queue otherwise cancel it. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ) = 0; + + /** + * Register a callback which will handle messages from the server. + * + * @param cb The callback object which will handle messages from the server. + * It accept two parameters in input: The handle of the connection where the + * message was received and the message received. Real type of the message + * can be obtained from its opcode. + */ + void when_server_message_received( + mbed::Callback cb + ) { + _server_message_cb = cb; + } + + /** + * Register a callback handling transaction timeout. + * + * @param cb The callback handling timeout of a transaction. It accepts as + * a parameter the connection handle involved in the timeout. + * + * @note No more attribute protocol requests, commands, indication or + * notification shall be sent over a connection implied in a transaction + * timeout. To send a new ATT message, the conenction should be + * reestablished. + */ + void when_transaction_timeout( + mbed::Callback cb + ) { + _transaction_timeout_cb = cb; + } + +protected: + GattClient() { } + + virtual ~GattClient() { } + + /** + * Upon server message reception an implementation shall call this function. + * + * @param connection_handle The handle of the connection which has received + * the server message. + * @param server_message The message received from the server. + */ + void on_server_event( + connection_handle_t connection_handle, + const AttServerMessage& server_message + ) { + if (_server_message_cb) { + _server_message_cb(connection_handle, server_message); + } + } + + /** + * Upon transaction timeout an implementation shall call this function. + * + * @param connection_handle The handle of the connection of the transaction + * which has times out. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.14 + */ + void on_transaction_timeout( + connection_handle_t connection_handle + ) { + if (_transaction_timeout_cb) { + _transaction_timeout_cb(connection_handle); + } + } + +private: + /** + * Callback called when the client receive a message from the server. + */ + mbed::Callback _server_message_cb; + + /** + * Callback called when a transaction times out. + */ + mbed::Callback _transaction_timeout_cb; + + // Disallow copy construction and copy assignment. + GattClient(const GattClient&); + GattClient& operator=(const GattClient&); +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_GATT_CLIENT_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h b/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h new file mode 100644 index 00000000000..a0f3346dead --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h @@ -0,0 +1,232 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ +#define BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ + +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Simple implementation of ble::pal::AttFindInformationResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttFindInformationResponse : public AttFindInformationResponse { + /** + * Format of the UUID in the response. + */ + enum Format { + FORMAT_16_BIT_UUID = 0x01,//!< FORMAT_16_BIT_UUID + FORMAT_128_BIT_UUID = 0x02//!< FORMAT_128_BIT_UUID + }; + + /** + * Construct an AttFindInformationResponse from format and an array of bytes + * containing the information data. + * @param format The format of the information data. + * @param information_data The information data whose format is determined + * by the Format field + */ + SimpleAttFindInformationResponse( + Format format, ArrayView information_data + ) : AttFindInformationResponse(), + _format(format), _information_data(information_data), + _item_size(information_data_item_size()) { + } + + /** + * @see ble::pal::AttFindInformationResponse::size + */ + virtual size_t size() const { + return _information_data.size() / _item_size; + } + + /** + * @see ble::pal::AttFindInformationResponse::operator[] + */ + virtual information_data_t operator[](size_t index) const { + const uint8_t* item = &_information_data[index * _item_size]; + + information_data_t result; + memcpy(&result.handle, item, sizeof(result.handle)); + + if (_format == FORMAT_16_BIT_UUID) { + uint16_t short_uuid = 0; + memcpy(&short_uuid, item + 2, sizeof(short_uuid)); + result.uuid = UUID(short_uuid); + } else { + result.uuid = UUID(item + 2, UUID::LSB); + } + + return result; + } + +private: + size_t information_data_item_size() const { + return sizeof(attribute_handle_t) + ((_format == FORMAT_16_BIT_UUID) ? 2 : 16); + } + + const Format _format; + const ArrayView _information_data; + const size_t _item_size; +}; + + +/** + * Simple implementation of ble::pal::AttFindByTypeValueResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttFindByTypeValueResponse : public AttFindByTypeValueResponse { + /** + * Construct a AttFindByTypeValueResponse from a raw array containing the + * Handle Informations. + * @param handles raw array containing one or more Handle Informations. + */ + SimpleAttFindByTypeValueResponse(ArrayView handles) : + AttFindByTypeValueResponse(), _handles(handles) { + } + + /** + * @see ble::pal::AttFindByTypeValueResponse::size + */ + virtual std::size_t size() const { + return _handles.size() / item_size; + } + + /** + * @see ble::pal::AttFindByTypeValueResponse::operator[] + */ + virtual attribute_handle_range_t operator[](size_t index) const { + attribute_handle_range_t result; + const uint8_t* item = &_handles[index * item_size]; + memcpy(&result.begin, item, sizeof(result.begin)); + memcpy(&result.end, item + sizeof(result.begin), sizeof(result.end)); + return result; + } + +private: + static const size_t item_size = 4; + const ArrayView _handles; +}; + + +/** + * Simple implementation of ble::pal::AttReadByTypeResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttReadByTypeResponse : public AttReadByTypeResponse { + /** + * Construct an AttReadByTypeResponse from the size of each attribute + * handle-value pair and a list of attribute data. + * @param element_size The size of each attribute-handle pair. + * @param attribute_data Raw bytes array containing the list of attribute + * data. + */ + SimpleAttReadByTypeResponse( + uint8_t element_size, ArrayView attribute_data + ) : AttReadByTypeResponse(), + _attribute_data(attribute_data), _element_size(element_size) { + } + + /** + * @see ble::pal::AttReadByTypeResponse::size + */ + virtual size_t size() const { + return _attribute_data.size() / _element_size; + } + + /** + * @see ble::pal::AttReadByTypeResponse::operator[] + */ + virtual attribute_data_t operator[](size_t index) const { + const uint8_t* item = &_attribute_data[index * _element_size]; + uint16_t handle; + memcpy(&handle, item, sizeof(handle)); + + attribute_data_t result = { + handle, + ArrayView( + item + sizeof(handle), + _element_size - sizeof(handle) + ) + }; + + return result; + } + +private: + ArrayView _attribute_data; + uint8_t _element_size; +}; + + +/** + * Simple implementation of ble::pal::AttReadByGroupTypeResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttReadByGroupTypeResponse : public AttReadByGroupTypeResponse { + /** + * Construct an instance of AttReadByGroupTypeResponse from the size of each + * attribute data and a byte array containing the list of attribute data. + * @param element_size The size of each Attribute Data + * @param attribute_data Byte array containing the list of Attribute Data. + */ + SimpleAttReadByGroupTypeResponse( + uint8_t element_size, ArrayView attribute_data + ) : AttReadByGroupTypeResponse(), + _attribute_data(attribute_data), _element_size(element_size) { + } + + /** + * @see ble::pal::AttReadByGroupTypeResponse::size + */ + virtual size_t size() const { + return _attribute_data.size() / _element_size; + } + + /** + * @see ble::pal::AttReadByGroupTypeResponse::operator[] + */ + virtual attribute_data_t operator[](size_t index) const { + const uint8_t* item = &_attribute_data[index * _element_size]; + uint16_t begin; + uint16_t end; + + memcpy(&begin, item, sizeof(begin)); + memcpy(&end, item + sizeof(begin), sizeof(end)); + + attribute_data_t result = { + { begin, end }, + ArrayView( + item + sizeof(begin) + sizeof(end), + _element_size - (sizeof(begin) + sizeof(end)) + ) + }; + + return result; + } + +private: + ArrayView _attribute_data; + uint8_t _element_size; +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ */ diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp new file mode 100644 index 00000000000..595babcccc0 --- /dev/null +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -0,0 +1,1342 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 +#include + +#include +#include +#include "ble/generic/GenericGattClient.h" +#include "ble/blecommon.h" +#include + +using ble::pal::AttServerMessage; +using ble::pal::AttReadResponse; +using ble::pal::AttReadBlobResponse; +using ble::pal::AttReadByTypeResponse; +using ble::pal::AttReadByGroupTypeResponse; +using ble::pal::AttFindByTypeValueResponse; +using ble::pal::AttErrorResponse; +using ble::pal::AttributeOpcode; +using ble::pal::AttWriteResponse; +using ble::pal::AttPrepareWriteResponse; +using ble::pal::AttExecuteWriteResponse; +using ble::pal::AttHandleValueIndication; +using ble::pal::AttHandleValueNotification; +using ble::pal::AttFindInformationResponse; + +namespace ble { +namespace generic { + +/* + * Type of procedures which can be launched by the client. + */ +enum procedure_type_t { + COMPLETE_DISCOVERY_PROCEDURE, + READ_PROCEDURE, + WRITE_PROCEDURE, + DESCRIPTOR_DISCOVERY_PROCEDURE +}; + + +/* + * Base class for a procedure control block + */ +struct procedure_control_block_t { + /* + * Base constructor for procedure control block. + */ + procedure_control_block_t(procedure_type_t type, Gap::Handle_t handle) : + type(type), connection_handle(handle), next(NULL) { } + + virtual ~procedure_control_block_t() { } + + /* + * Entry point of the control block stack machine. + */ + virtual void handle(GenericGattClient* client, const AttServerMessage& message) = 0; + + /* + * Function call in case of timeout + */ + virtual void handle_timeout_error(GenericGattClient* client) = 0; + + procedure_type_t type; + Gap::Handle_t connection_handle; + procedure_control_block_t* next; +}; + + +/* + * Procedure control block for the discovery process. + */ +struct discovery_control_block_t : public procedure_control_block_t { + discovery_control_block_t( + Gap::Handle_t handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + UUID matching_service_uuid, + UUID matching_characteristic_uuid + ) : procedure_control_block_t(COMPLETE_DISCOVERY_PROCEDURE, handle), + service_callback(service_callback), + characteristic_callback(characteristic_callback), + matching_service_uuid(matching_service_uuid), + matching_characteristic_uuid(matching_characteristic_uuid), + services_discovered(NULL), + done(false) { + } + + virtual ~discovery_control_block_t() { + while(services_discovered) { + service_t* tmp = services_discovered->next; + delete services_discovered; + services_discovered = tmp; + } + } + + virtual void handle_timeout_error(GenericGattClient* client) { + terminate(client); + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + // if end of discovery has been requested, ends it immediately + if (done) { + terminate(client); + return; + } + + switch(message.opcode) { + case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: + handle_service_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: + handle_service_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::READ_BY_TYPE_RESPONSE: + handle_characteristic_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::ERROR_RESPONSE: { + const AttErrorResponse& error = static_cast(message); + if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) { + terminate(client); + } + + switch (error.request_opcode) { + case AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST: + case AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST: + start_characteristic_discovery(client); + break; + case AttributeOpcode::READ_BY_TYPE_REQUEST: + handle_all_characteristics_discovered(client); + break; + default: + // error + break; + } + } break; + default: + // error + break; + } + } + + template + void handle_service_discovered(GenericGattClient* client, const Response& response) { + if (!response.size()) { + terminate(client); + return; + } + + uint16_t end_handle = 0x0000; + for (size_t i = 0; i < response.size(); ++i) { + uint16_t start_handle = get_start_handle(response[i]); + end_handle = get_end_handle(response[i]); + UUID uuid = get_uuid(response[i]); + + if (!characteristic_callback) { + DiscoveredService discovered_service; + discovered_service.setup(uuid, start_handle, end_handle); + service_callback(&discovered_service); + } else { + service_t* discovered_service = new (std::nothrow) service_t( + start_handle, end_handle, uuid + ); + + if (discovered_service == NULL) { + terminate(client); + return; + } + + insert_service(discovered_service); + } + } + + if (end_handle == 0xFFFF) { + start_characteristic_discovery(client); + } else { + ble_error_t err = client->_pal_client->discover_primary_service( + connection_handle, end_handle + 1 + ); + + if (err) { + terminate(client); + } + } + } + + void start_characteristic_discovery(GenericGattClient* client) { + if (!services_discovered) { + terminate(client); + return; + } + + if (!characteristic_callback) { + terminate(client); + return; + } + + if (service_callback) { + DiscoveredService discovered_service; + discovered_service.setup( + services_discovered->uuid, + services_discovered->begin, + services_discovered->end + ); + service_callback(&discovered_service); + } + + last_characteristic = characteristic_t(); + client->_pal_client->discover_characteristics_of_a_service( + connection_handle, + attribute_handle_range( + services_discovered->begin, + services_discovered->end + ) + ); + } + + void handle_characteristic_discovered(GenericGattClient* client, const AttReadByTypeResponse& response) { + for (size_t i = 0; i < response.size(); ++i) { + if (last_characteristic.is_valid() == false) { + last_characteristic.set_last_handle(response[i].handle - 1); + if (matching_characteristic_uuid == UUID() + || last_characteristic.getUUID() == matching_characteristic_uuid) { + characteristic_callback(&last_characteristic); + } + } + + last_characteristic = characteristic_t( + client, connection_handle, response[i].handle, response[i].value + ); + } + + // check if all the characteristics of the service has been discovered + if (last_characteristic.getValueHandle() == services_discovered->end) { + handle_all_characteristics_discovered(client); + } else { + ble_error_t err = client->_pal_client->discover_characteristics_of_a_service( + connection_handle, + attribute_handle_range( + last_characteristic.getValueHandle() + 1, + services_discovered->end + ) + ); + + if (err) { + terminate(client); + } + } + } + + void handle_all_characteristics_discovered(GenericGattClient* client) { + if (last_characteristic.is_valid() == false) { + if (matching_characteristic_uuid == UUID() + || matching_characteristic_uuid == last_characteristic.getUUID()) { + last_characteristic.set_last_handle(services_discovered->end); + characteristic_callback(&last_characteristic); + } + } + + service_t* old = services_discovered; + services_discovered = services_discovered->next; + delete old; + + if (!services_discovered) { + terminate(client); + } else { + start_characteristic_discovery(client); + } + } + + void terminate(GenericGattClient* client) { + // unknown error, terminate the procedure immediately + client->remove_control_block(this); + Gap::Handle_t handle = connection_handle; + delete this; + client->on_termination(handle); + } + + uint16_t get_start_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { + return data.group_range.begin; + } + + uint16_t get_start_handle(const attribute_handle_range_t& range) { + return range.begin; + } + + uint16_t get_end_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { + return data.group_range.end; + } + + uint16_t get_end_handle(const attribute_handle_range_t& range) { + return range.end; + } + + UUID get_uuid(const AttReadByGroupTypeResponse::attribute_data_t& data) { + if (data.value.size() == 2) { + return UUID(data.value[0] | data.value[1] << 8); + } else { + return UUID(data.value.data(), UUID::LSB); + } + } + + UUID get_uuid(const attribute_handle_range_t& range) { + return matching_service_uuid; + } + + struct service_t { + service_t(uint16_t begin, uint16_t end, const UUID& uuid) : + begin(begin), end(end), uuid(uuid), next(NULL) { } + uint16_t begin; + uint16_t end; + UUID uuid; + service_t* next; + }; + + struct characteristic_t : DiscoveredCharacteristic { + characteristic_t() : DiscoveredCharacteristic() { + lastHandle = 0x0001; + } + + characteristic_t( + GattClient* client, + Gap::Handle_t connection_handle, + uint16_t decl_handle, + const ArrayView value + ) : DiscoveredCharacteristic() { + gattc = client; + uuid = get_uuid(value); + props = get_properties(value); + declHandle = decl_handle; + valueHandle = get_value_handle(value); + lastHandle = 0x0000; + connHandle = connection_handle; + } + + static UUID get_uuid(const ArrayView& value) { + if (value.size() == 5) { + return UUID(value[3] | (value[4] << 8)); + } else { + return UUID(value.data() + 3, UUID::LSB); + } + } + + static DiscoveredCharacteristic::Properties_t get_properties(const ArrayView& value) { + uint8_t raw_properties = value[0]; + DiscoveredCharacteristic::Properties_t result; + result._broadcast = (raw_properties & (1 << 0)) ? true : false; + result._read = (raw_properties & (1 << 1)) ? true : false; + result._writeWoResp = (raw_properties & (1 << 2)) ? true : false; + result._write = (raw_properties & (1 << 3)) ? true : false; + result._notify = (raw_properties & (1 << 4)) ? true : false; + result._indicate = (raw_properties & (1 << 5)) ? true : false; + result._authSignedWrite = (raw_properties & (1 << 6)) ? true : false; + return result; + } + + static uint16_t get_value_handle(const ArrayView& value) { + return value[1] | (value[2] << 8); + } + + void set_last_handle(uint16_t last_handle) { + lastHandle = last_handle; + } + + bool is_valid() const { + return lastHandle != 0x0000; + } + }; + + void insert_service(service_t* service) { + if (services_discovered == NULL) { + services_discovered = service; + return; + } + + service_t* current = services_discovered; + while (current->next) { + current = current->next; + } + current->next = service; + } + + ServiceDiscovery::ServiceCallback_t service_callback; + ServiceDiscovery::CharacteristicCallback_t characteristic_callback; + UUID matching_service_uuid; + UUID matching_characteristic_uuid; + service_t* services_discovered; + characteristic_t last_characteristic; + bool done; +}; + + +struct read_control_block_t : public procedure_control_block_t { + read_control_block_t( + Gap::Handle_t connection_handle, uint16_t attribute_handle, uint16_t offset + ) : procedure_control_block_t(READ_PROCEDURE, connection_handle), + attribute_handle(attribute_handle), + offset(offset), current_offset(offset), data(NULL) { + } + + virtual ~read_control_block_t() { + if (data != NULL) { + free(data); + } + } + + virtual void handle_timeout_error(GenericGattClient* client) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } + + void terminate(GenericGattClient* client, const GattReadCallbackParams& response) { + client->remove_control_block(this); + client->processReadResponse(&response); + delete this; + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + break; + + case AttributeOpcode::READ_RESPONSE: + handle_read_response(client, static_cast(message)); + break; + + case AttributeOpcode::READ_BLOB_RESPONSE: + handle_read_response(client, static_cast(message)); + break; + + default: { + // should not happen, terminate the procedure and notify client with an error + // in such case + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + AttErrorResponse::UNLIKELY_ERROR, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } break; + } + } + + template + void handle_read_response(GenericGattClient* client, const ResponseType& read_response) { + uint16_t mtu_size = client->get_mtu(connection_handle); + + // end of responses ? + if ((uint16_t) read_response.size() < (mtu_size - 1)) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_NONE, + }; + + // is it the first response, or is there any other response already + // in the object ? + if (data == NULL) { + response.len = (uint16_t) read_response.size(); + response.data = read_response.data(); + } else { + // copy the data in the existing buffer + memcpy(data + (current_offset - offset), read_response.data(), read_response.size()); + response.len = (current_offset + read_response.size()) - offset; + response.data = data; + } + terminate(client, response); + } else { + // allocation which will contain the response data plus the next one. + data = (uint8_t*) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2)); + if (data == NULL) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + AttErrorResponse::INSUFFICIENT_RESOURCES, + NULL, + BLE_ERROR_NO_MEM, + }; + terminate(client, response); + return; + } + + memcpy(data + (current_offset - offset), read_response.data(), read_response.size()); + current_offset = current_offset + read_response.size(); + ble_error_t err = client->_pal_client->read_attribute_blob( + connection_handle, + attribute_handle, + current_offset + ); + + if (err) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + AttErrorResponse::UNLIKELY_ERROR, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + ble_error_t status = BLE_ERROR_UNSPECIFIED; + + switch (error.error_code) { + case AttErrorResponse::INVALID_HANDLE: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INSUFFICIENT_AUTHORIZATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_AUTHENTICATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::READ_NOT_PERMITTED: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + case AttErrorResponse::INVALID_OFFSET: + status = BLE_ERROR_PARAM_OUT_OF_RANGE; + break; + case AttErrorResponse::ATTRIBUTE_NOT_LONG: + status = BLE_ERROR_PARAM_OUT_OF_RANGE; + break; + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + error.error_code, + /* data */ NULL, + status + }; + + terminate(client, response); + } + + uint16_t attribute_handle; + uint16_t offset; + uint16_t current_offset; + uint8_t* data; +}; + +/* + * Control block for the write process + */ +struct write_control_block_t : public procedure_control_block_t { + write_control_block_t( + Gap::Handle_t connection_handle, uint16_t attribute_handle, + uint8_t* data, uint16_t len + ) : procedure_control_block_t(WRITE_PROCEDURE, connection_handle), + attribute_handle(attribute_handle), len(len), offset(0), data(data), + prepare_success(false), status(BLE_ERROR_UNSPECIFIED), error_code(0xFF) { + } + + virtual ~write_control_block_t() { + free(data); + } + + virtual void handle_timeout_error(GenericGattClient* client) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_UNSPECIFIED, + 0x00 + }; + terminate(client, response); + } + + void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) { + client->remove_control_block(this); + client->processWriteResponse(&response); + delete this; + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + break; + + case AttributeOpcode::WRITE_RESPONSE: + handle_write_response(client, static_cast(message)); + break; + + case AttributeOpcode::PREPARE_WRITE_RESPONSE: + handle_prepare_write_response(client, static_cast(message)); + break; + + case AttributeOpcode::EXECUTE_WRITE_RESPONSE: + handle_execute_write_response(client, static_cast(message)); + break; + + default: { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_UNSPECIFIED, + AttErrorResponse::UNLIKELY_ERROR + }; + + terminate(client, response); + } break; + } + } + + void handle_write_response(GenericGattClient* client, const AttWriteResponse& write_response) { + GattWriteCallbackParams response = { + connection_handle, attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_NONE, 0x00 + }; + + terminate(client, response); + } + + void handle_prepare_write_response(GenericGattClient* client, const AttPrepareWriteResponse& write_response) { + ble_error_t err = BLE_ERROR_UNSPECIFIED; + + uint16_t mtu_size = client->get_mtu(connection_handle); + offset = write_response.offset + write_response.partial_value.size(); + if (offset < len) { + err = client->_pal_client->queue_prepare_write( + connection_handle, attribute_handle, + make_const_ArrayView( + data + offset, + std::min((len - offset), (mtu_size - 5)) + ), + offset + ); + } else { + err = client->_pal_client->execute_write_queue( + connection_handle, true + ); + } + + if (err) { + clear_prepare_queue(client, err, AttErrorResponse::UNLIKELY_ERROR); + } + } + + void handle_execute_write_response(GenericGattClient* client, const AttExecuteWriteResponse& execute_response) { + if (prepare_success) { + status = BLE_ERROR_NONE; + error_code = 0x00; + } + + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + status, + error_code + }; + + terminate(client, response); + } + + void clear_prepare_queue(GenericGattClient* client, ble_error_t s, uint8_t e) { + prepare_success = false; + status = s; + error_code = e; + ble_error_t err = client->_pal_client->execute_write_queue( + connection_handle, false + ); + + if (err) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + err, + AttErrorResponse::UNLIKELY_ERROR + }; + + terminate(client, response); + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + ble_error_t status = BLE_ERROR_UNSPECIFIED; + + switch (error.error_code) { + case AttErrorResponse::INVALID_HANDLE: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INSUFFICIENT_AUTHORIZATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_AUTHENTICATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::WRITE_NOT_PERMITTED: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + if (error.request_opcode == AttributeOpcode(AttributeOpcode::PREPARE_WRITE_REQUEST)) { + clear_prepare_queue(client, status, error.error_code); + } else { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + status, + error.error_code + }; + + terminate(client, response); + } + } + + uint16_t attribute_handle; + uint16_t len; + uint16_t offset; + uint8_t* data; + bool prepare_success; + ble_error_t status; + uint8_t error_code; +}; + +/* + * Control block for the descriptor discovery process + */ +struct descriptor_discovery_control_block_t : public procedure_control_block_t { + descriptor_discovery_control_block_t( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ) : procedure_control_block_t(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()), + characteristic(characteristic), + discovery_cb(discoveryCallback), + termination_cb(terminationCallback), + next_handle(characteristic.getValueHandle() + 1), + done(false) { + } + + virtual ~descriptor_discovery_control_block_t() { } + + ble_error_t start(GenericGattClient* client) { + return client->_pal_client->discover_characteristics_descriptors( + connection_handle, + attribute_handle_range( + next_handle, + characteristic.getLastHandle() + ) + ); + } + + virtual void handle_timeout_error(GenericGattClient* client) { + terminate(client, BLE_ERROR_UNSPECIFIED); + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + if (done) { + terminate(client, BLE_ERROR_NONE); + return; + } + + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + return; + + case AttributeOpcode::FIND_INFORMATION_RESPONSE: + handle_response(client, static_cast(message)); + return; + + default: + break; + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) { + terminate(client, BLE_ERROR_NONE); + } else { + terminate(client, BLE_ERROR_UNSPECIFIED, error.error_code); + } + } + + void handle_response(GenericGattClient* client, const AttFindInformationResponse& response) { + for (size_t i = 0; i < response.size(); ++i) { + DiscoveredCharacteristicDescriptor descriptor( + client, connection_handle, response[i].handle, response[i].uuid + ); + CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = { + characteristic, + descriptor + }; + discovery_cb(¶ms); + if (done) { + terminate(client, BLE_ERROR_NONE); + return; + } + + if (response[i].handle == characteristic.getLastHandle()) { + terminate(client, BLE_ERROR_NONE); + return; + } + next_handle = response[i].handle + 1; + } + + ble_error_t err = start(client); + if (err) { + terminate(client, err, AttErrorResponse::UNLIKELY_ERROR); + } + } + + void terminate(GenericGattClient* client, ble_error_t status, uint8_t error_code = 0x00) { + client->remove_control_block(this); + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + status, + error_code + }; + termination_cb(¶ms); + delete this; + } + + DiscoveredCharacteristic characteristic; + CharacteristicDescriptorDiscovery::DiscoveryCallback_t discovery_cb; + CharacteristicDescriptorDiscovery::TerminationCallback_t termination_cb; + uint16_t next_handle; + bool done; +}; + + +GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : + _pal_client(pal_client), + _termination_callback(), + control_blocks(NULL) { + _pal_client->when_server_message_received( + mbed::callback(this, &GenericGattClient::on_server_message_received) + ); + _pal_client->when_transaction_timeout( + mbed::callback(this, &GenericGattClient::on_transaction_timeout) + ); +} + +ble_error_t GenericGattClient::launchServiceDiscovery( + Gap::Handle_t connection_handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + const UUID& matching_service_uuid, + const UUID& matching_characteristic_uuid +) { + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + // terminate and return if there is no callback to call + if (!service_callback && !characteristic_callback) { + on_termination(connection_handle); + return BLE_ERROR_NONE; + } + + discovery_control_block_t* discovery_pcb = new(std::nothrow) discovery_control_block_t( + connection_handle, + service_callback, + characteristic_callback, + matching_service_uuid, + matching_characteristic_uuid + ); + + if (discovery_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + // note: control block inserted prior the request because they are part of + // of the transaction and the callback can be call synchronously + insert_control_block(discovery_pcb); + + // launch the request + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (matching_service_uuid == UUID()) { + err = _pal_client->discover_primary_service( + connection_handle, + 0x0001 + ); + } else { + err = _pal_client->discover_primary_service_by_service_uuid( + connection_handle, + 0x0001, + matching_service_uuid + ); + } + + if (err) { + remove_control_block(discovery_pcb); + delete discovery_pcb; + } + + return err; +} + +bool GenericGattClient::isServiceDiscoveryActive() const { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { + return true; + } + pcb = pcb->next; + } + + return false; +} + +void GenericGattClient::terminateServiceDiscovery() +{ + procedure_control_block_t* pcb = control_blocks; + while (pcb) { + if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { + static_cast(pcb)->done = true; + } + pcb = pcb->next; + } +} + +ble_error_t GenericGattClient::read( + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + uint16_t offset) const +{ + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + read_control_block_t* read_pcb = new(std::nothrow) read_control_block_t( + connection_handle, + attribute_handle, + offset + ); + + if (read_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + insert_control_block(read_pcb); + + ble_error_t err = BLE_ERROR_NONE; + + if (offset == 0) { + err = _pal_client->read_attribute_value( + connection_handle, attribute_handle + ); + } else { + err = _pal_client->read_attribute_blob( + connection_handle, attribute_handle, offset + ); + } + + if (err) { + remove_control_block(read_pcb); + delete read_pcb; + } + + return err; +} + +ble_error_t GenericGattClient::write( + GattClient::WriteOp_t cmd, + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + size_t length, + const uint8_t* value +) const { + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + uint16_t mtu = get_mtu(connection_handle); + + if (cmd == GattClient::GATT_OP_WRITE_CMD) { + if (length > (uint16_t)(mtu - 3)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->write_without_response( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } else { + uint8_t* data = NULL; + + if (length > (uint16_t)(mtu - 3)) { + data = (uint8_t*) malloc(length); + if (data == NULL) { + return BLE_ERROR_NO_MEM; + } + memcpy(data, value, length); + } + + write_control_block_t* write_pcb = new(std::nothrow) write_control_block_t( + connection_handle, + attribute_handle, + data, + length + ); + + if (write_pcb == NULL) { + free(data); + return BLE_ERROR_NO_MEM; + } + + insert_control_block(write_pcb); + + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (data) { + err = _pal_client->queue_prepare_write( + connection_handle, + attribute_handle, + make_const_ArrayView(value, mtu - 5), + /* offset */ 0 + ); + } else { + err = _pal_client->write_attribute( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } + + if (err) { + remove_control_block(write_pcb); + delete write_pcb; + } + + return err; + } + + return BLE_ERROR_NOT_IMPLEMENTED; +} + +void GenericGattClient::onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback +) { + _termination_callback = callback; +} + +ble_error_t GenericGattClient::discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback +) { + // verify that there is no other procedures going on this connection + if (get_control_block(characteristic.getConnectionHandle())) { + return BLE_ERROR_INVALID_STATE; + } + + if (characteristic.getValueHandle() == characteristic.getLastHandle()) { + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + BLE_ERROR_NONE, + /* error code */ 0x00 + }; + + terminationCallback(¶ms); + return BLE_ERROR_NONE; + } + + descriptor_discovery_control_block_t* discovery_pcb = + new(std::nothrow) descriptor_discovery_control_block_t( + characteristic, + discoveryCallback, + terminationCallback + ); + + if (discovery_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + insert_control_block(discovery_pcb); + + ble_error_t err = discovery_pcb->start(this); + + if (err) { + remove_control_block(discovery_pcb); + delete discovery_pcb; + } + + return err; +} + +bool GenericGattClient::isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic& characteristic +) const { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE && + static_cast(pcb)->characteristic == characteristic) { + return true; + } + pcb = pcb->next; + } + + return false; +} + +void GenericGattClient::terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic& characteristic +) { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) { + descriptor_discovery_control_block_t* dpcb = + static_cast(pcb); + if (dpcb->characteristic == characteristic) { + dpcb->done = true; + return; + } + } + + pcb = pcb->next; + } + +} + +ble_error_t GenericGattClient::reset(void) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +void GenericGattClient::on_termination(Gap::Handle_t connection_handle) { + if (_termination_callback) { + _termination_callback(connection_handle); + } +} + +void GenericGattClient::on_server_message_received( + connection_handle_t connection_handle, + const AttServerMessage& message +) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + case AttributeOpcode::EXCHANGE_MTU_RESPONSE: + case AttributeOpcode::FIND_INFORMATION_RESPONSE: + case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: + case AttributeOpcode::READ_BY_TYPE_RESPONSE: + case AttributeOpcode::READ_RESPONSE: + case AttributeOpcode::READ_BLOB_RESPONSE: + case AttributeOpcode::READ_MULTIPLE_RESPONSE: + case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: + case AttributeOpcode::WRITE_RESPONSE: + case AttributeOpcode::PREPARE_WRITE_RESPONSE: + case AttributeOpcode::EXECUTE_WRITE_RESPONSE: { + on_server_response(connection_handle, message); + } break; + + case AttributeOpcode::HANDLE_VALUE_INDICATION: + case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { + on_server_event(connection_handle, message); + } break; + + default: + // invalid message receive + return; + } +} + +void GenericGattClient::on_server_response( + connection_handle_t connection, + const AttServerMessage& message +) { + procedure_control_block_t* pcb = get_control_block(connection); + if (pcb == NULL) { + return; + } + + pcb->handle(this, message); +} + +void GenericGattClient::on_server_event(connection_handle_t connection, const AttServerMessage& message) { + GattHVXCallbackParams callbacks_params = { + (Gap::Handle_t) connection, 0 + }; + + switch (message.opcode) { + case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { + const AttHandleValueNotification& notification = + static_cast(message); + callbacks_params.handle = notification.attribute_handle; + callbacks_params.type = BLE_HVX_NOTIFICATION; + callbacks_params.len = notification.attribute_value.size(); + callbacks_params.data = notification.attribute_value.data(); + } break; + + case AttributeOpcode::HANDLE_VALUE_INDICATION: { + const AttHandleValueIndication& indication = + static_cast(message); + callbacks_params.handle = indication.attribute_handle; + callbacks_params.type = BLE_HVX_INDICATION; + callbacks_params.len = indication.attribute_value.size(); + callbacks_params.data = indication.attribute_value.data(); + } break; + + default: + return; + } + + processHVXEvent(&callbacks_params); +} + +void GenericGattClient::on_transaction_timeout(connection_handle_t connection) { + procedure_control_block_t* pcb = get_control_block(connection); + if (pcb == NULL) { + return; + } + + pcb->handle_timeout_error(this); +} + +procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) { + procedure_control_block_t* it = control_blocks; + while (it && it->connection_handle != connection) { + it = it->next; + } + return it; +} + +const procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) const { + procedure_control_block_t* it = control_blocks; + while (it && it->connection_handle != connection) { + it = it->next; + } + return it; +} + +void GenericGattClient::insert_control_block(procedure_control_block_t* cb) const { + if (control_blocks == NULL) { + control_blocks = cb; + return; + } + + procedure_control_block_t* current = control_blocks; + while (current->next) { + current = current->next; + } + current->next = cb; +} + +void GenericGattClient::remove_control_block(procedure_control_block_t* cb) const { + if (control_blocks == NULL) { + return; + } + + if (cb == control_blocks) { + control_blocks = control_blocks->next; + return; + } + + procedure_control_block_t* current = control_blocks; + while (current->next && current->next != cb) { + current = current->next; + } + + if (current->next == NULL) { + return; + } + + current->next = cb->next; + cb->next = NULL; +} + +uint16_t GenericGattClient::get_mtu(Gap::Handle_t connection) const { + uint16_t result = 23; + if(_pal_client->get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) { + result = 23; + } + return result; +} + +} // namespace pal +} // namespace ble From 512dd8c387681b748f43660144d64895f593973f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 11:01:06 +0100 Subject: [PATCH 24/29] BLE: Add collection of basic BLE types shared accross all layers. --- features/FEATURE_BLE/ble/BLETypes.h | 77 +++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 features/FEATURE_BLE/ble/BLETypes.h diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h new file mode 100644 index 00000000000..f20f03c432a --- /dev/null +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -0,0 +1,77 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef BLE_TYPES_H_ +#define BLE_TYPES_H_ + +#include +#include + +namespace ble { + +/** + * A connection handle is an unsigned integer capable of holding a pointer. + * The real type (either a pointer to an object or an integer) is opaque and + * platform dependent. + */ +typedef uintptr_t connection_handle_t; + +/** + * Model an attribute handle in a GATT database. + */ +typedef uint16_t attribute_handle_t; + + + /** + * Model an inclusive range of GATT attributes handles. + */ +struct attribute_handle_range_t { + attribute_handle_t begin; + attribute_handle_t end; + + friend bool operator==( + const attribute_handle_range_t& lhs, const attribute_handle_range_t& rhs + ) { + return (lhs.begin == rhs.begin) && (lhs.end == rhs.end); + } + + friend bool operator!=( + const attribute_handle_range_t& lhs, const attribute_handle_range_t& rhs + ) { + return !(lhs == rhs); + } +}; + + +/** + * Construct an attribute_handle_range_t from its start and end handle. + * @note This function is defined instead of a constructor to keep "POD-ness" + * of attribute_handle_range_t. + */ +static inline attribute_handle_range_t attribute_handle_range( + attribute_handle_t begin, + attribute_handle_t end +) { + attribute_handle_range_t result = { + begin, + end + }; + return result; +} + +} // namespace ble + +#endif /* BLE_TYPES_H_ */ From aa0b5d5a22662bd67248470f717e255e141d30b0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 13:45:57 +0100 Subject: [PATCH 25/29] BLE: Fix space --- features/FEATURE_BLE/ble/pal/AttServerMessage.h | 1 - 1 file changed, 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/pal/AttServerMessage.h b/features/FEATURE_BLE/ble/pal/AttServerMessage.h index 5a61850bbf8..1862549673d 100644 --- a/features/FEATURE_BLE/ble/pal/AttServerMessage.h +++ b/features/FEATURE_BLE/ble/pal/AttServerMessage.h @@ -90,7 +90,6 @@ struct AttributeOpcode { }; - /** * Base class for Attribute Server Message. * The correct type of the instance can be determined with the attribute opcode. From 75c9dfce68a4c0f3ba533877d4a7f7a150b37fe9 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 8 Sep 2017 13:53:28 +0100 Subject: [PATCH 26/29] BLE: Add Cordio port. It allows mbed users to enable BLE on targets with an external BLE module. --- .../targets/TARGET_CORDIO/CordioBLE.h | 153 ++ .../targets/TARGET_CORDIO/CordioGap.h | 262 ++ .../targets/TARGET_CORDIO/CordioGattServer.h | 217 ++ .../TARGET_CORDIO/CordioPalAttClient.h | 622 +++++ .../TARGET_CORDIO/CordioSecurityManager.h | 48 + .../targets/TARGET_CORDIO/README.md | 29 + .../TARGET_CORDIO/doc/HCIAbstraction.md | 44 + .../targets/TARGET_CORDIO/doc/PortingGuide.md | 551 ++++ .../doc/resources/architecture.png | Bin 0 -> 14239 bytes .../doc/resources/architecture_layer.png | Bin 0 -> 12761 bytes .../TARGET_CORDIO/driver/CordioHCIDriver.cpp | 261 ++ .../TARGET_CORDIO/driver/CordioHCIDriver.h | 145 + .../driver/CordioHCITransportDriver.cpp | 33 + .../driver/CordioHCITransportDriver.h | 73 + .../driver/H4TransportDriver.cpp | 70 + .../TARGET_CORDIO/driver/H4TransportDriver.h | 76 + .../TARGET_CORDIO/source/CordioBLE.cpp | 452 +++ .../TARGET_CORDIO/source/CordioGap.cpp | 543 ++++ .../TARGET_CORDIO/source/CordioGattServer.cpp | 763 ++++++ .../source/wsf_mbed_os_adaptation.c | 28 + .../LICENSE-permissive-binary-license-1.0.txt | 49 + .../sw/hci/dual_chip/hci_core_ps.h | 45 + .../cordio_stack/sw/hci/include/hci_cmd.h | 46 + .../cordio_stack/sw/hci/include/hci_core.h | 129 + .../cordio_stack/sw/hci/include/hci_drv.h | 83 + .../cordio_stack/sw/hci/include/hci_evt.h | 64 + .../cordio_stack/sw/hci/include/hci_tr.h | 45 + .../cordio_stack/sw/sec/include/sec_api.h | 246 ++ .../cordio_stack/sw/stack/cfg/cfg_stack.h | 103 + .../cordio_stack/sw/stack/include/att_api.h | 1111 ++++++++ .../cordio_stack/sw/stack/include/att_defs.h | 225 ++ .../sw/stack/include/att_handler.h | 70 + .../cordio_stack/sw/stack/include/att_uuid.h | 475 ++++ .../cordio_stack/sw/stack/include/dm_api.h | 2423 +++++++++++++++++ .../sw/stack/include/dm_handler.h | 70 + .../cordio_stack/sw/stack/include/hci_api.h | 837 ++++++ .../sw/stack/include/hci_handler.h | 70 + .../cordio_stack/sw/stack/include/l2c_api.h | 431 +++ .../cordio_stack/sw/stack/include/l2c_defs.h | 118 + .../sw/stack/include/l2c_handler.h | 96 + .../cordio_stack/sw/stack/include/smp_api.h | 242 ++ .../cordio_stack/sw/stack/include/smp_defs.h | 155 ++ .../sw/stack/include/smp_handler.h | 70 + .../cordio_stack/ws-core/include/hci_defs.h | 891 ++++++ .../cordio_stack/ws-core/include/ll_defs.h | 341 +++ .../stack/cordio_stack/ws-core/sw/util/bda.h | 143 + .../cordio_stack/ws-core/sw/util/bstream.h | 152 ++ .../ws-core/sw/wsf/generic/wsf_os_int.h | 108 + .../ws-core/sw/wsf/generic/wsf_types.h | 66 + .../ws-core/sw/wsf/include/wsf_buf.h | 199 ++ .../ws-core/sw/wsf/include/wsf_math.h | 48 + .../ws-core/sw/wsf/include/wsf_msg.h | 140 + .../ws-core/sw/wsf/include/wsf_os.h | 179 ++ .../ws-core/sw/wsf/include/wsf_queue.h | 158 ++ .../ws-core/sw/wsf/include/wsf_timer.h | 167 ++ .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 0 -> 46166 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 0 -> 94784 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 0 -> 15676 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 0 -> 446290 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 0 -> 24540 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 0 -> 52210 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 0 -> 8668 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 0 -> 270784 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a | Bin 0 -> 48498 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a | Bin 0 -> 93270 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a | Bin 0 -> 17880 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a | Bin 0 -> 451060 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 0 -> 46254 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 0 -> 94840 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 0 -> 15716 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 0 -> 446718 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 0 -> 24540 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 0 -> 52210 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 0 -> 8668 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 0 -> 270784 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a | Bin 0 -> 48542 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a | Bin 0 -> 93298 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a | Bin 0 -> 17896 bytes .../TOOLCHAIN_IAR/libcordio_stack.a | Bin 0 -> 451272 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 0 -> 45796 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 0 -> 95978 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 0 -> 15508 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 0 -> 454916 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 0 -> 24248 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 0 -> 50834 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 0 -> 8652 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 0 -> 270228 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a | Bin 0 -> 49310 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a | Bin 0 -> 94644 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a | Bin 0 -> 17976 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a | Bin 0 -> 462866 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 0 -> 45872 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 0 -> 96014 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 0 -> 15528 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 0 -> 455248 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 0 -> 24256 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 0 -> 50778 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 0 -> 8652 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 0 -> 270236 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a | Bin 0 -> 49310 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a | Bin 0 -> 94644 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a | Bin 0 -> 17976 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a | Bin 0 -> 462942 bytes .../hci_mbed_os_adaptation.h | 65 + .../wsf_mbed_os_adaptation.h | 44 + 105 files changed, 14274 insertions(+) create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/README.md create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h new file mode 100644 index 00000000000..da4b345a628 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -0,0 +1,153 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_BLE_H_ +#define CORDIO_BLE_H_ + +#include "ble/BLE.h" +#include "ble/blecommon.h" +#include "ble/BLEInstanceBase.h" + +#include "CordioHCIDriver.h" +#include "CordioGap.h" +#include "CordioGattServer.h" +#include "CordioSecurityManager.h" +#include "CordioPalAttClient.h" +#include "ble/pal/AttClientToGattClientAdapter.h" +#include "ble/generic/GenericGattClient.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * @see BLEInstanceBase + */ +class BLE : public ::BLEInstanceBase { + /** + * Construction with an HCI driver. + */ + BLE(CordioHCIDriver& hci_driver); + + /** + * Destructor + */ + virtual ~BLE(); + +public: + + /** + * Access to the singleton containing the implementation of BLEInstanceBase + * for the Cordio stack. + */ + static BLE& deviceInstance(); + + /** + * @see BLEInstanceBase::init + */ + virtual ble_error_t init( + ::BLE::InstanceID_t instanceID, + FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> initCallback + ); + + /** + * @see BLEInstanceBase::hasInitialized + */ + virtual bool hasInitialized() const; + + /** + * @see BLEInstanceBase::shutdown + */ + virtual ble_error_t shutdown(); + + /** + * @see BLEInstanceBase::getVersion + */ + virtual const char *getVersion(); + + /** + * @see BLEInstanceBase::getGap + */ + virtual Gap& getGap(); + + /** + * @see BLEInstanceBase::getGap + */ + virtual const Gap& getGap() const; + + /** + * @see BLEInstanceBase::getGattServer + */ + virtual GattServer &getGattServer(); + + /** + * @see BLEInstanceBase::getGattServer + */ + virtual const GattServer &getGattServer() const; + + /** + * @see BLEInstanceBase::getGattClient + */ + virtual ::GattClient &getGattClient(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; + + /** + * @see BLEInstanceBase::waitForEvent + */ + virtual void waitForEvent(); + + /** + * @see BLEInstanceBase::processEvents + */ + virtual void processEvents(); + +private: + static void stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg); + static void device_manager_cb(dmEvt_t* dm_event); + static void connection_handler(dmEvt_t* dm_event); + static void timeoutCallback(); + + void stack_setup(); + void start_stack_reset(); + void callDispatcher(); + + static CordioHCIDriver* _hci_driver; + static FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> _init_callback; + + enum { + NOT_INITIALIZED, + INITIALIZING, + INITIALIZED + } initialization_status; + + ::BLE::InstanceID_t instanceID; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + + +#endif /* CORDIO_BLE_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h new file mode 100644 index 00000000000..ab139d5b908 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h @@ -0,0 +1,262 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_GAP_H_ +#define CORDIO_GAP_H_ + +#include +#include "ble/blecommon.h" +#include "ble/GapAdvertisingParams.h" +#include "ble/GapAdvertisingData.h" +#include "ble/Gap.h" +#include "ble/GapScanningParams.h" +#include "dm_api.h" +#include "att_api.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * @see ::Gap + */ +class Gap : public ::Gap +{ +public: + /** + * Return the Gap singleton implementing ::Gap for the Cordio stac. + */ + static Gap &getInstance(); + + /** + * This function shall be called once the stack has been initialized + */ + void initialize(); + + /** + * @see ::Gap::setAddress + */ + virtual ble_error_t setAddress(AddressType_t type, const Address_t address); + + /** + * @see ::Gap::getAddress + */ + virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); + + /** + * @see ::Gap::setAdvertisingData + */ + virtual ble_error_t setAdvertisingData( + const GapAdvertisingData&, const GapAdvertisingData& + ); + + /** + * @see ::Gap::connect + */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams + ); + + /** + * @see ::Gap::getMinAdvertisingInterval + */ + virtual uint16_t getMinAdvertisingInterval() const; + + /** + * @see ::Gap::getMinNonConnectableAdvertisingInterval + */ + virtual uint16_t getMinNonConnectableAdvertisingInterval() const; + + /** + * @see ::Gap::getMaxAdvertisingInterval + */ + virtual uint16_t getMaxAdvertisingInterval() const; + + /** + * @see ::Gap::startAdvertising + */ + virtual ble_error_t startAdvertising(const GapAdvertisingParams &); + + /** + * @see ::Gap::stopAdvertising + */ + virtual ble_error_t stopAdvertising(); + + /** + * @see ::Gap::disconnect + */ + virtual ble_error_t disconnect( + Handle_t connectionHandle, + DisconnectionReason_t reason + ); + + /** + * @see ::Gap::disconnect + */ + virtual ble_error_t disconnect(DisconnectionReason_t reason); + + /** + * @see ::Gap::setDeviceName + */ + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + + /** + * @see ::Gap::getDeviceName + */ + virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP); + + /** + * @see ::Gap::setAppearance + */ + virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance); + + /** + * @see ::Gap::getAppearance + */ + virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP); + + /** + * @see ::Gap::setTxPower + */ + virtual ble_error_t setTxPower(int8_t txPower); + + /** + * @see ::Gap::getPermittedTxPowerValues + */ + virtual void getPermittedTxPowerValues( + const int8_t **valueArrayPP, size_t *countP + ); + + /** + * Set the internal connection handle + */ + void setConnectionHandle(uint16_t m_connectionHandle); + + /** + * Get the current connection handle + */ + uint16_t getConnectionHandle(); + + /** + * @see ::Gap::getPreferredConnectionParams + */ + virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params); + + /** + * @see ::Gap::setPreferredConnectionParams + */ + virtual ble_error_t setPreferredConnectionParams( + const ConnectionParams_t *params + ); + + /** + * @see ::Gap::updateConnectionParams + */ + virtual ble_error_t updateConnectionParams( + Handle_t handle, const ConnectionParams_t *params + ); + + /** + * @see ::Gap::startRadioScan + */ + virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); + + /** + * @see ::Gap::stopScan + */ + virtual ble_error_t stopScan(); + + /** + * Called when advertising is stopped. + */ + void advertisingStopped(); + + // Whitelist management + + /** + * @see ::Gap::getMaxWhitelistSize + */ + virtual uint8_t getMaxWhitelistSize(void) const; + + /** + * @see ::Gap::getWhitelist + */ + virtual ble_error_t getWhitelist(Whitelist_t &whitelist) const; + + /** + * @see ::Gap::setWhitelist + */ + virtual ble_error_t setWhitelist(const Whitelist_t &whitelist); + + /** + * @see ::Gap::setAdvertisingPolicyMode + */ + virtual ble_error_t setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode); + + /** + * @see ::Gap::getAdvertisingPolicyMode + */ + virtual AdvertisingPolicyMode_t getAdvertisingPolicyMode(void) const; + + /** + * @see ::Gap::setScanningPolicyMode + */ + virtual ble_error_t setScanningPolicyMode(ScanningPolicyMode_t mode); + + /** + * @see ::Gap::getScanningPolicyMode + */ + virtual ScanningPolicyMode_t getScanningPolicyMode(void) const; + + /** + * @see ::Gap::setInitiatorPolicyMode + */ + virtual ble_error_t setInitiatorPolicyMode(InitiatorPolicyMode_t mode); + + /** + * @see ::Gap::getInitiatorPolicyMode + */ + virtual InitiatorPolicyMode_t getInitiatorPolicyMode(void) const; + + /** + * @see ::Gap::reset + */ + virtual ble_error_t reset(void); + +private: + Gap(); + + Gap(Gap const &); + void operator=(Gap const &); + + uint16_t m_connectionHandle; + addr_type_t m_type; + Address_t m_addr; + + AdvertisingPolicyMode_t advertising_policy_mode; + ScanningPolicyMode_t scanning_policy_mode; + InitiatorPolicyMode_t initiator_policy_mode; + Whitelist_t whitelist; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_GAP_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h new file mode 100644 index 00000000000..26dc08a78e8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -0,0 +1,217 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_GATT_SERVER_H_ +#define CORDIO_GATT_SERVER_H_ + +#include +#include "ble/blecommon.h" +#include "ble/GattServer.h" +#include "ble/Gap.h" +#include "wsf_types.h" +#include "att_api.h" + +/*! client characteristic configuration descriptors settings */ +#define MAX_CCC_CNT 20 + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Cordio implementation of ::GattServer + */ +class GattServer : public ::GattServer +{ +public: + /** + * Return the singleton of the Cordio implementation of ::GattServer. + */ + static GattServer &getInstance(); + + /** + * Initialize the GattServer and add mandatory services (generic access and + * generic attribute service). + */ + void initialize(); + + /** + * @see ::GattServer::addService + */ + virtual ble_error_t addService(GattService &); + + /** + * @see ::GattServer::read + */ + virtual ble_error_t read( + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], + uint16_t *lengthP + ); + + /** + * @see ::GattServer::read + */ + virtual ble_error_t read( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], uint16_t *lengthP + ); + + /** + * @see ::GattServer::write + */ + virtual ble_error_t write( + GattAttribute::Handle_t, + const uint8_t[], uint16_t, + bool localOnly = false + ); + + /** + * @see ::GattServer::write + */ + virtual ble_error_t write( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t, + const uint8_t[], + uint16_t, + bool localOnly = false + ); + + /** + * @see ::GattServer::areUpdatesEnabled + */ + virtual ble_error_t areUpdatesEnabled( + const GattCharacteristic &characteristic, bool *enabledP + ); + + /** + * @see ::GattServer::areUpdatesEnabled + */ + virtual ble_error_t areUpdatesEnabled( + Gap::Handle_t connectionHandle, + const GattCharacteristic &characteristic, + bool *enabledP + ); + + /** + * @see ::GattServer::isOnDataReadAvailable + */ + virtual bool isOnDataReadAvailable() const; + + /** + * @see ::GattServer::getPreferredConnectionParams + */ + virtual ::Gap::ConnectionParams_t getPreferredConnectionParams(); + + /** + * @see ::GattServer::setPreferredConnectionParams + */ + virtual void setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params); + + /** + * @see ::GattServer::setDeviceName + */ + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + + /** + * @see ::GattServer::getDeviceName + */ + virtual void getDeviceName(const uint8_t*& name, uint16_t& length); + + /** + * @see ::GattServer::setAppearance + */ + virtual void setAppearance(GapAdvertisingData::Appearance appearance); + + /** + * @see ::GattServer::getAppearance + */ + virtual GapAdvertisingData::Appearance getAppearance(); + + /** + * @see ::GattServer::reset + */ + virtual ble_error_t reset(void); + +private: + static void cccCback(attsCccEvt_t *pEvt); + static void attCback(attEvt_t *pEvt); + static uint8_t attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr); + static uint8_t attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr); + void add_generic_access_service(); + void add_generic_attribute_service(); + void* alloc_block(size_t block_size); + + struct alloc_block_t { + alloc_block_t* next; + uint8_t data[1]; + }; + + struct internal_char_t { + uint16_t descLen; + }; + + struct internal_service_t { + uint16_t uuidLen; + internal_char_t *chars; + attsGroup_t *attGroup; + internal_service_t *next; + }; + + attsCccSet_t cccSet[MAX_CCC_CNT]; + uint16_t cccValues[MAX_CCC_CNT]; + uint16_t cccHandles[MAX_CCC_CNT]; + uint8_t cccCnt; + + struct { + attsGroup_t service; + attsAttr_t attributes[7]; + uint8_t device_name_declaration_value[5]; + uint16_t device_name_length; + uint8_t appearance_declaration_value[5]; + uint16_t appearance; + uint8_t ppcp_declaration_value[5]; + uint8_t ppcp[8]; + + uint8_t*& device_name_value() { + return attributes[2].pValue; + } + } generic_access_service; + + struct { + attsGroup_t service; + attsAttr_t attributes[4]; + uint8_t service_changed_declaration[5]; + } generic_attribute_service; + + internal_service_t* registered_service; + alloc_block_t* allocated_blocks; + + uint16_t currentHandle; + +private: + GattServer(); + + GattServer(const GattServer &); + const GattServer& operator=(const GattServer &); +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_GATT_SERVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h new file mode 100644 index 00000000000..401cffa8b83 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -0,0 +1,622 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_PAL_ATT_CLIENT_ +#define CORDIO_PAL_ATT_CLIENT_ + +#include "ble/pal/AttClient.h" +#include "ble/pal/SimpleAttServerMessage.h" +#include "att_api.h" +#include "att_defs.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace cordio { + +class CordioAttClient : public ::ble::pal::AttClient { + +public: + CordioAttClient() : ::ble::pal::AttClient() { } + virtual ~CordioAttClient() { } + + /** + * @see ble::pal::AttClient::exchange_mtu_request + */ + virtual ble_error_t exchange_mtu_request(connection_handle_t connection) + { + AttcMtuReq(connection, pAttCfg->mtu); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::GattClient::get_mtu_size + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) { + mtu_size = AttGetMtu(connection_handle); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::find_information_request + */ + virtual ble_error_t find_information_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) { + AttcFindInfoReq( + connection_handle, + discovery_range.begin, + discovery_range.end, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::find_by_type_value_request + */ + virtual ble_error_t find_by_type_value_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range, + uint16_t type, + const ArrayView& value + ) { + AttcFindByTypeValueReq( + connection_handle, + discovery_range.begin, + discovery_range.end, + type, + value.size(), + const_cast(value.data()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_by_type_request + */ + virtual ble_error_t read_by_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& type + ) { + AttcReadByTypeReq( + connection_handle, + read_range.begin, + read_range.end, + type.getLen(), + const_cast(type.getBaseUUID()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_request + */ + virtual ble_error_t read_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) { + AttcReadReq(connection_handle, attribute_handle); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_blob_request + */ + virtual ble_error_t read_blob_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) { + AttcReadLongReq( + connection_handle, + attribute_handle, + offset, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_multiple_request + */ + virtual ble_error_t read_multiple_request( + connection_handle_t connection_handle, + const ArrayView& attribute_handles + ) { + AttcReadMultipleReq( + connection_handle, + attribute_handles.size(), + const_cast(attribute_handles.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_by_group_type_request + */ + virtual ble_error_t read_by_group_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& group_type + ) { + AttcReadByGroupTypeReq( + connection_handle, + read_range.begin, + read_range.end, + group_type.getLen(), + const_cast(group_type.getBaseUUID()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::write_request + */ + virtual ble_error_t write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcWriteReq( + connection_handle, + attribute_handle, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::write_command + */ + virtual ble_error_t write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcWriteCmd( + connection_handle, + attribute_handle, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::signed_write_command + */ + virtual ble_error_t signed_write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcSignedWriteCmd( + connection_handle, + attribute_handle, + /* sign counter from flash or AttsGetSignCounter() ? */ 0, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::prepare_write_request + */ + virtual ble_error_t prepare_write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset, + const ArrayView& value + ) { + AttcPrepareWriteReq( + connection_handle, + attribute_handle, + offset, + value.size(), + const_cast(value.data()), + false, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::execute_write_request + */ + virtual ble_error_t execute_write_request( + connection_handle_t connection_handle, + bool execute + ) { + AttcExecuteWriteReq( + connection_handle, + execute + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::initialize + */ + virtual ble_error_t initialize() + { + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::terminate + */ + virtual ble_error_t terminate() + { + return BLE_ERROR_NONE; + } + + // singleton of the ARM Cordio client + static CordioAttClient& get_client() + { + static CordioAttClient _client; + return _client; + } + +private: + // convert an array of byte to an uint16_t + static uint16_t to_uint16_t(const uint8_t* array) + { + uint16_t result; + memcpy(&result, array, sizeof(result)); + return result; + } + + /** + * Type of an event handler. + * @param The event to handle + * @return true if the event has been handled and false otherwise. + */ + typedef bool (*event_handler_t)(const attEvt_t*); + +public: + /** + * Callback which handle attEvt_t and forward them to on_server_event. + */ + static void att_client_handler(const attEvt_t* event) + { + // all handlers are stored in a static array + static const event_handler_t handlers[] = { + &timeout_event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler + }; + + // event->hdr.param: connection handle + // event->header.event: opcode from the request + // event->header.status: success or error code ... + // event->pValue: starting after opcode for response; starting after opcode + handle for server initiated responses. + // event->handle: handle for server initiated responses + + // traverse all handlers and execute them with the event in input. + // exit if an handler has handled the event. + for(size_t i = 0; i < (sizeof(handlers)/sizeof(handlers[0])); ++i) { + if (handlers[i](event)) { + return; + } + } + } + +private: + /** + * Event handler generator. + * @tparam Description of an event converter. It contains two static member + * function: + * - bool can_convert(const attEvt_t* event): return true if the event can + * be converted by the converter + * - convert(const attEvt_t* event): return the + * AttServerMessage converted from event. + * @param event + * @return + */ + template + static bool event_handler(const attEvt_t* event) + { + if (T::can_convert(event)) { + generated_handler(event, T::convert); + return true; + } + return false; + } + + static bool timeout_event_handler(const attEvt_t* event) + { + if(event->hdr.status != ATT_ERR_TIMEOUT) { + return false; + } + + get_client().on_transaction_timeout(event->hdr.param); + return true; + } + + template + static void generated_handler( + const attEvt_t* event, ResultType (*convert)(const attEvt_t*) + ) { + get_client().on_server_event( + event->hdr.param, + convert(event) + ); + } + + /** + * Traits defining can_convert for non ErrorResponse events. + */ + template + struct ResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status == ATT_SUCCESS && event->hdr.event == RequestID) { + return true; + } + return false; + } + }; + + /** + * Converter for an AttErrorResponse. + */ + struct ErrorResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status != ATT_SUCCESS) { + return true; + } + return false; + } + + static AttErrorResponse convert(const attEvt_t* event) + { + return AttErrorResponse( + static_cast(event->hdr.event * 2), + event->handle, + event->hdr.status + ); + } + }; + + /** + * Converter for an AttExchangeMTUResponse. + */ + struct ExchangeMtuResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status == ATT_SUCCESS && + event->hdr.event == ATT_MTU_UPDATE_IND) { + return true; + } + return false; + } + + static AttExchangeMTUResponse convert(const attEvt_t* event) + { + return AttExchangeMTUResponse(event->mtu); + } + }; + + /** + * Converter for a SimpleAttFindInformationResponse. + */ + struct FindInformationResponseConverter : ResponseConverter { + static SimpleAttFindInformationResponse convert(const attEvt_t* event) + { + return SimpleAttFindInformationResponse( + static_cast(event->pValue[0]), + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a SimpleAttFindByTypeValueResponse. + */ + struct FindByTypeValueResponseConverter : ResponseConverter { + static SimpleAttFindByTypeValueResponse convert(const attEvt_t* event) + { + return SimpleAttFindByTypeValueResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a SimpleAttReadByTypeResponse. + */ + struct ReadByTypeResponseConverter : ResponseConverter { + static SimpleAttReadByTypeResponse convert(const attEvt_t* event) + { + return SimpleAttReadByTypeResponse( + event->pValue[0], + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a AttReadResponse. + */ + struct ReadResponseConverter : ResponseConverter { + static AttReadResponse convert(const attEvt_t* event) + { + return AttReadResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttReadBlobResponse. + */ + struct ReadBlobResponseConverter : ResponseConverter { + static AttReadBlobResponse convert(const attEvt_t* event) + { + return AttReadBlobResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttReadMultipleResponse. + */ + struct ReadMultipleResponseConverter : ResponseConverter { + static AttReadMultipleResponse convert(const attEvt_t* event) + { + return AttReadMultipleResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a SimpleAttReadByGroupTypeResponse. + */ + struct ReadBygroupTypeResponseConverter : ResponseConverter { + static SimpleAttReadByGroupTypeResponse convert(const attEvt_t* event) + { + return SimpleAttReadByGroupTypeResponse( + event->pValue[0], + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a AttWriteResponse. + */ + struct WriteResponseConverter : ResponseConverter { + static AttWriteResponse convert(const attEvt_t* event) + { + return AttWriteResponse(); + } + }; + + /** + * Converter for a AttPrepareWriteResponse. + */ + struct PrepareWriteResponseConverter : ResponseConverter { + static AttPrepareWriteResponse convert(const attEvt_t* event) + { + // WARNING: Not sure if correct, the stack erase the length parameter + return AttPrepareWriteResponse( + event->handle, + to_uint16_t(event->pValue + 2), + // FIXME: the stack set the lenght to 0, the data won't be seen ... + make_const_ArrayView( + event->pValue + 4, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttExecuteWriteResponse. + */ + struct ExecuteWriteResponseConverter : ResponseConverter { + static AttExecuteWriteResponse convert(const attEvt_t* event) + { + return AttExecuteWriteResponse(); + } + }; + + /** + * Converter for a AttHandleValueNotification. + */ + struct HandleValueNotificationConverter : ResponseConverter { + static AttHandleValueNotification convert(const attEvt_t* event) + { + return AttHandleValueNotification( + event->handle, + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttHandleValueIndication. + */ + struct HandleValueIndicationConverter : ResponseConverter { + static AttHandleValueIndication convert(const attEvt_t* event) + { + return AttHandleValueIndication( + event->handle, + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; +}; + +} // cordio +} // vendor +} // pal +} // ble + +#endif /* CORDIO_PAL_ATT_CLIENT_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h new file mode 100644 index 00000000000..6522a0f50b3 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h @@ -0,0 +1,48 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_SECURITY_MANAGER_H_ +#define CORDIO_SECURITY_MANAGER_H_ + +#include + +#include "ble/SecurityManager.h" + +namespace ble { +namespace vendor { +namespace cordio { + +class SecurityManager : public ::SecurityManager +{ +public: + static SecurityManager &getInstance() + { + static SecurityManager m_instance; + return m_instance; + } + +public: + SecurityManager() + { + /* empty */ + } +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_SECURITY_MANAGER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md new file mode 100644 index 00000000000..b6c208d2dc7 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md @@ -0,0 +1,29 @@ +# BLE API Cordio Implementation + +The BLE API Cordio implementation allows Cordio licensee to easily deliver a +complete and up to date implementation of mbed BLE to their custommers using +mbed OS. + +To deliver a BLE port, vendors simply have to provide an HCI driver taillored +for the BLE module present on the board they want to support. + +## Source Organization + +The root contains the public header of the classes implementing BLE API public +interface. + +* `doc`: Documentation such as the HCI extension guide and the +porting guide. +* `driver`: HCI driver and transport interfaces. Also contains standard driver +implementation. +* `sources`: BLE API Implementation files +* `stack`: Cordio stack + * `cordio_stack`: Headerd of the cordio stack + * `lib`: precompiled libraries of the cordio stack + * `mbed_os_adaptation`: Headers of the interface responsible for the bridge + between BLE API and the Cordio stack. + +## Documentation + +* [HCI architecture](doc/HCIAbstraction.md) +* [Porting guide](doc/PortingGuide.md) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md new file mode 100644 index 00000000000..1a69a0d44c1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md @@ -0,0 +1,44 @@ +# HCI abstraction architecture + +The HCI driver is split into two interfaces: +* `CordioHCIDriver`: It is the driver for a BLE controller. It contains +the primitive necessary to start and initialize the controller. +* `CordioHCITransport`: It is the transport interface which is used by the HCI +driver to communicate with the controller. + +A `CordioHCITransport` is injected into a `CordioHCIDriver` at construction +time. A `CordioHCIDriver` is also injected at construction time of a `BLECordio` +instance. + +This can be summarized in the following diagram: + +![](resources/architecture.png) + +## CordioHCITransportDriver + +The single responsabilities of this a driver is to handle the communication with +the Bluetooth module. Basically, sending and reading bytes. + +Given that the Bluetooth specification define standard transport interface, an +implementation of the H4 interface is bundled in this port. It might be extended +in the future with an implementation of the H5 interface. However there is no +plan to provide the SDIO implementation at the moment. + +This interface is defined in the header file +[CordioHCITransportDriver.h](../driver/CordioHCITransportDriver.h) + +## CordioHCIDriver + +The responsibilities of this driver are: +* Provide the memory which will used by the Bluetooth stack. +* Initialize the bluetooth controller. +* Handle the reset/startup sequence of the bluetooth controller. + +This interface is defined in the header file +[CordioHCIDriver.h](../driver/CordioHCIDriver.h) + +A partial implementation is present in the file +[CordioHCIDriver.cpp](../driver/CordioHCIDriver.cpp). It defines the function +delivering memory to the stack and a complete reset sequence. However it does +not define any initialization for the Bluetooth controller, this part being +specific to the controller used. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md new file mode 100644 index 00000000000..dea13bcdf02 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md @@ -0,0 +1,551 @@ +# Porting guide + +Enabling the mbed BLE Cordio port for a given target is a two step process: +* The target shall be configured to include Cordio BLE port and Cordio libraries +during the build process. +* An implementation of the `CordioHCIDriver` class targeting the bluetooth +controller used shall be provided. + +## Target configuration + +This step happens in the file defining all mbed os targets. The file is located +in `targets/target.json`. + +### Add BLE feature + +First of all support for BLE has to be added to the target. This is achieved by +adding the string `BLE` in the list of `features` of the target. Once this +value has been added the sources of BLE api are added to the list of sources +compiled for the target. + +```json + "TARGET_NAME": { + "features": ["target features ...", "BLE"] + } +``` + +### Include Cordio BLE implementation + +The target should also compile the sources of the BLE Cordio port. It is +achieved by adding the string `CORDIO` in the list of the `extra_labels` +property of the target. + +```json + "TARGET_NAME": { + "extra_labels": ["target extra labels ...", "CORDIO"], + "features": ["target features ...", "BLE"] + } +``` + +### Include prebuilt libraries + +Last, the target shall also include the cordio libraries into the build. + +Four prebuilt libraries are provided: +* `wscore`: which contains the base component used by the Cordio stack. +* `wsstack`: The BLE stack itself, if contains the GAP and GATT layer as well as +the Security manager implementation. +* `wssec`: The low level implementation of the security layer. +* `wshci`: The HCI layer. + +The `wssec` and `wshci` libraries are delivered in feature folders. It allows +vendors to override those library if necessary. This can be required if the port +use specific crypto routine or require an highly modified HCI layer. + +To include the default library in the target, the features have to be added in +this list of the features of the target: +* `WSSEC`: Include the default `wssec` library. +* `WSHCI`: Include the default `wshci` library. + +The target should also compile the sources of the BLE Cordio port. It is +achieved by adding the string `CORDIO` in the list of the `extra_labels` +property of the target. + +```json + "TARGET_NAME": { + "extra_labels": ["target extra labels ...", "CORDIO"], + "features": ["target features ...", "BLE", "WSHCI", "WSSEC"] + } +``` + +## CordioHCIDriver implementation: + +A port shall include an HCI driver for the BLE module used by the target and +a factory function which create the BLE instance used by the user of BLE API. + +### Create source folder + +The port shall live in the folder of BLE API which host targets port : +`features/FEATURE_BLE/targets`. + +To isolate the port code from other code a folder containing the port code has +to be created. The name of this folder shall start with `TARGET_` and end with +the target name in capital. + +### Create the HCI driver + +The HCI driver is split in two entities: one which handle HCI communication with +the Bluetooth module and the other handling the initialization, reset sequence +and memory dedicated for the Bluetooth controller. + +More information about the architecture can be found in the +[HCI abstraction architecture](HCIAbstraction.md) document. + +#### HCITransport + +> **Note:** If the Bluetooth controller uses an H4 communication interface, this +step can be skipped. + +An empty transport driver can be coded as: + +```c++ +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace target_name { + +class TransportDriver : public cordio::CordioHCITransportDriver { +public: + TransportDriver(/* specific constructor arguments*/); + + virtual ~TransportDriver(); + + virtual void initialize(); + + virtual void terminate(); + + virtual uint16_t write(uint8_t packet_type, uint16_t len, uint8_t *data); + +private: + // private driver declarations +}; + +} // namespace target_name +} // namespace vendor +} // namespace ble +``` + +It shall inherits publicly from the base class `CordioHCITransportDriver`. + +* **Initialization/termination:** The functions `initialize` and `terminate` are +responsible for initializing and terminating the transport driver. It is not +necessary to initialize the transport in the constructor. + +* **Sending data** The function `write` shall sends data in input to the +Bluetooth controller and return the number of bytes in the `data` buffer sent. +Depending on the type of transport being implemented, the packet `type` might +have to be sent to the controller before the packet data. + +* **Receiving data**: HCI data from the Bluetooth controller shall be injected +in the system by invoking the function `on_data_received`. This function is +a static one and is provided by the base class. Its prototype is: + +```c++ +void on_data_received(uint8_t* data_received, uint16_t length_of_data_received); +``` + +#### HCIDriver + +The skeleton of driver is: + +```c++ +#include "CordioHCIDriver.h" + +namespace ble { +namespace vendor { +namespace target_name { + +class HCIDriver : public cordio::CordioHCIDriver { +public: + HCIDriver( + cordio::CordioHCITransportDriver& transport_driver, + /* specific constructor arguments*/ + ); + + virtual ~HCIDriver(); + + virtual void do_initialize(); + + virtual void do_terminate(); + + virtual buf_pool_desc_t get_buffer_pool_description(); + + virtual void start_reset_sequence(); + + virtual void handle_reset_sequence(uint8_t *msg); +private: + // private driver declarations +}; + +} // namespace target_name +} // namespace vendor +} // namespace ble +``` + +##### Initialization process + +The initialization/termination process is achieved by the couple of functions +`do_initialize` and `do_terminate`. Those function manages the state of the +bluetooth controller. + +> **Important:** It is unnecessary to initialize or terminate the hci transport +in those function because it is handled by the base class. The HCI transport is +initialized right before the call to `do_initialize` and is terminated right +after the call to `do_terminate`. + +##### Memory pool + +The implementation of the function `get_buffer_pool_description` in the base +class will return a buffer of 1040 bytes divided in different memory pools: + +| Chunk size (bytes) | Number of chunks | +|--------------------|------------------| +| 16 | 8 | +| 32 | 4 | +| 64 | 2 | +| 128 | 2 | +| 272 | 1 | + +A port shall override this function if the memory provided by the base class +doesn't match what is required by the Bluetooth controller driven. + +```c++ +buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() { + static uint8_t buffer[/* buffer size */]; + static const wsfBufPoolDesc_t pool_desc[] = { + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + }; + + return buf_pool_desc_t(buffer, pool_desc); +} +``` + +##### Reset sequence + +The reset sequence process is handled by three functions: + +* `start_reset_sequence`: This function start the process. The basic +implementation sends an HCI reset command to the Bluetooth controller. The +function shall be overridden in the driver if the bluetooth controller requires +more than just sending the standard reset command. + +* `handle_reset_sequence`: Entry point to the state machine handling the reset +process. Every time an HCI packet is received during the reset sequence, this +function is called with the HCI packet received. It's purpose is to prepare the +Bluetooth controller and set the parameters the stack needs to operate properly. +This function can be overridden if necessary. + +* `signal_reset_sequence_done`: This function shall be called once the reset +sequence is achieved. It cannot be overridden. + +###### Controller parameters to set + +This instruct the controller which events are relevant for the stack. + +The following parameters should be set in the controller (if supported): +* event mask: The reset sequence should issue the call +`HciSetEventMaskCmd((uint8_t *) hciEventMask)` +* LE event mask: The call `HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask)` +should be issued. +* 2nd page of events mask: Can be achieved by invoking +`HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2)`. + + +###### Stack runtime parameters + +Some stack parameters shall be acquired at runtime from the controller: + +* Bluetooth address: Can be queried with `HciReadBdAddrCmd`. Response shall be +copied into `hciCoreCb.bdAddr` with `BdaCpy`. +* Buffer size of the controller: Can be obtained by `HciLeReadBufSizeCmd`. The +return parameter *HC_ACL_Data_Packet_Length* shall be copied into +`hciCoreCb.bufSize` and the response parameter +`HC_Synchronous_Data_Packet_Length`shall be copied into `hciCoreCb.numBufs`. +The value of `hciCoreCb.availBufs` shall be initialized with `hciCoreCb.numBufs`. +* Supported state: Queried with `HciLeReadSupStatesCmd`, the response shall go +into `hciCoreCb.leStates`. +* Whitelist size: Queried with `HciLeReadWhiteListSizeCmd` the response shall go +into `hciCoreCb.whiteListSize`. +* LE features supported: Obtained with `HciLeReadLocalSupFeatCmd`. The response +shall be stored into `hciCoreCb.leSupFeat`. +* Resolving list size: Obtained with `hciCoreReadResolvingListSize`. The response +shall go into `hciCoreCb.resListSize`. +* Max data length: Acquired with `hciCoreReadMaxDataLen`. The response parameter +`supportedMaxTxOctets` and `supportedMaxTxTime` shall be pass to the function +`HciLeWriteDefDataLen`. + + +The default implementation is: + +```c++ +void HCIDriver::handle_reset_sequence(uint8_t *pMsg) { + // only accept command complete event: + if (*pMsg != HCI_CMD_CMPL_EVT) { + return; + } + + uint16_t opcode; + static uint8_t randCnt; + + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); // copy opcode + pMsg++; /* skip status */ + + /* decode opcode */ + switch (opcode) + { + case HCI_OPCODE_RESET: + /* initialize rand command count */ + randCnt = 0; + // set the event mask to control which events are generated by the + // controller for the host + HciSetEventMaskCmd((uint8_t *) hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + // set the event mask to control which LE events are generated by + // the controller for the host + HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + // set the event mask to control which events are generated by the + // controller for the host (2nd page of flags ) + HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + // Ask the Bluetooth address of the controller + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + // Store the Bluetooth address in the stack runtime parameter + BdaCpy(hciCoreCb.bdAddr, pMsg); + + // Read the size of the buffer of the controller + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + // Store the buffer parameters in the stack runtime parameters + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + // read the states and state combinations supported by the link + // layer of the controller + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + // store supported state and combination in the runtime parameters + // of the stack + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + // read the total of whitelist entries that can be stored in the + // controller. + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + // store the number of whitelist entries in the stack runtime + // parameters + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + // Read the LE features supported by the controller + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + // Store the set of LE features supported by the controller + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + // read the total number of address translation entries which can be + // stored in the controller resolving list. + hciCoreReadResolvingListSize(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + // store the number of address translation entries in the stack + // runtime parameter + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + // read the Controller’s maximum supported payload octets and packet + // duration times for transmission and reception + hciCoreReadMaxDataLen(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: + { + // store payload definition in the runtime stack parameters. + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + } + break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) + { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + else + { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + // handle extended command + if (hciCoreCb.extResetSeq) + { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT-1)) + { + randCnt++; + HciLeRandCmd(); + } + else + { + /* last command in sequence; set resetting state and call callback */ + signal_reset_sequence_done(); + } + break; + + default: + break; + } +} + +static void hciCoreReadMaxDataLen(void) +{ + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) + { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } + else + { + /* send next command in sequence */ + HciLeRandCmd(); + } +} + +static void hciCoreReadResolvingListSize(void) +{ + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) + { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } + else + { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + } +} +``` + + + +### HCI accessor function + +The HCI driver is injected in the `CordioBLE` class at construction site. +Given that the CordioBLE class doesn't know what class shall be used to +construct the driver nor it knows how to construct it, the port shall provide a +function returning a reference to the HCI driver. + +This function lives in the global namespace and its signature is: + +```c++ +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver(); +``` + +A common implementation might be: + +```c++ +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() { + static ble::vendor::target_name::TransportDriver transport_driver( + /* transport parameters */ + ); + + static ble::vendor::target_name::HCIDriver hci_driver( + transport_driver, /* other hci driver parameters */ + ); + + return hci_driver; +} +``` + +## Examples + +Implementation examples might be found for: +* [ST BlueNRG module](../../TARGET_NUCLEO_F401RE/BlueNrgHCIDriver.cpp): It uses +a custom transport driver and a vendor specific is sent right after the answer +to the reset command to switch the controller to link layer mode only. +* [EM9301 module](../../TARGET_Maxim/TARGET_MAX32620HSP/EM9301HCIDriver.cpp): +it uses a custom transport driver and doesn't doesn't send the command *Set +Event Mask Page 2* to the controller during the reset sequence because this +command is not supported by the controller. +* [PAN1326](../../TARGET_Maxim/TARGET_MAX32630FTHR/CC2564HCIDriver.cpp): It +uses the H4 transport driver. The reset sequence start by sending a +*service pack* then once the service pack has been transferred it continue +with the regular reset sequence. + + + + + + + + + + + + + + + + + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..f3bc8634c6cbe16de77e8056eec7fabdc062d9d3 GIT binary patch literal 14239 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 sKBqFz`=KM)_9uO+(-R2NLOHl>h($ literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png new file mode 100644 index 0000000000000000000000000000000000000000..7e765aa260411e3a05de19b7499316ff72468a61 GIT binary patch literal 12761 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

^uM$sA@Rf`N=LfO#h^9d-n$!fQco*f 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 HSO@$Ms +#include + +#include "CordioHCIDriver.h" +#include "hci_api.h" +#include "hci_cmd.h" +#include "hci_core.h" +#include "bstream.h" +#include "hci_mbed_os_adaptation.h" + +#define HCI_RESET_RAND_CNT 4 + +namespace ble { +namespace vendor { +namespace cordio { + +namespace { + +static void hciCoreReadMaxDataLen(void) +{ + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } else { + /* send next command in sequence */ + HciLeRandCmd(); + } +} + +static void hciCoreReadResolvingListSize(void) +{ + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } else { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + } +} + +} // end of anonymous namespace + + +CordioHCIDriver::CordioHCIDriver(CordioHCITransportDriver& transport_driver) : + _transport_driver(transport_driver) { } + +void CordioHCIDriver::initialize() +{ + _transport_driver.initialize(); + do_initialize(); +} + +void CordioHCIDriver::terminate() +{ + do_terminate(); + _transport_driver.terminate(); +} + +buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() +{ + static union { + uint8_t buffer[2250]; + uint64_t align; + }; + static const wsfBufPoolDesc_t pool_desc[] = { + { 16, 16 }, + { 32, 16 }, + { 64, 8 }, + { 128, 4 }, + { 272, 1 } + }; + + return buf_pool_desc_t(buffer, pool_desc); +} + +void CordioHCIDriver::start_reset_sequence() +{ + /* send an HCI Reset command to start the sequence */ + HciResetCmd(); +} + +void CordioHCIDriver::handle_reset_sequence(uint8_t *pMsg) +{ + uint16_t opcode; + static uint8_t randCnt; + + /* if event is a command complete event */ + if (*pMsg == HCI_CMD_CMPL_EVT) { + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); + pMsg++; /* skip status */ + + /* decode opcode */ + switch (opcode) { + case HCI_OPCODE_RESET: + /* initialize rand command count */ + randCnt = 0; + + /* send next command in sequence */ + HciSetEventMaskCmd((uint8_t *) hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + /* send next command in sequence */ + HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + /* send next command in sequence */ + HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + /* send next command in sequence */ + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + /* parse and store event parameters */ + BdaCpy(hciCoreCb.bdAddr, pMsg); + + /* send next command in sequence */ + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + /* send next command in sequence */ + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + /* parse and store event parameters */ + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + /* send next command in sequence */ + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + /* send next command in sequence */ + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + /* send next command in sequence */ + hciCoreReadResolvingListSize(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: { + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + } break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } else { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + if (hciCoreCb.extResetSeq) { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT-1)) { + randCnt++; + HciLeRandCmd(); + } else { + /* last command in sequence; set resetting state and call callback */ + signal_reset_sequence_done(); + } + break; + + default: + break; + } + } +} + +void CordioHCIDriver::signal_reset_sequence_done() +{ + hci_mbed_os_signal_reset_sequence_done(); +} + +uint16_t CordioHCIDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ + return _transport_driver.write(type, len, pData); +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h new file mode 100644 index 00000000000..10ac769c82c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h @@ -0,0 +1,145 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_HCI_DRIVER_H_ +#define CORDIO_HCI_DRIVER_H_ + +#include +#include +#include "wsf_buf.h" +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Contain description of the memory pool used by the Cordio stack. + */ +struct buf_pool_desc_t { + /** + * Create a new memory pool description + * @param buffer the Buffer used by the memory pool. + * @param pool_desc How the memory is split + */ + template + buf_pool_desc_t( + uint8_t (&buffer)[BufferSize], + const wsfBufPoolDesc_t (&pool_desc)[PoolCount] + ) : buffer_memory(buffer), buffer_size(BufferSize), + pool_description(pool_desc), pool_count(PoolCount) + { + } + + uint8_t* buffer_memory; /// Pointer to the buffer memory + size_t buffer_size; /// Size of the buffer + const wsfBufPoolDesc_t* pool_description; /// Pointer to the first element describing the pool + size_t pool_count; /// Number of pools +}; + +/** + * Base class of the HCI driver use by the BLE port of the Cordio stack. + * This class provide to the stack: + * - The buffer necessary to run BLE API + * - The reset sequence of the BLE module + * - Access to the write function of the underlying HCITransport driver. + */ +class CordioHCIDriver { +public: + /** + * Construct a new instance of an HCI driver. + * @param transport_driver The driver used to communicate with the chip. + */ + CordioHCIDriver(CordioHCITransportDriver& transport_driver); + + /** + * Driver destructor + */ + virtual ~CordioHCIDriver() { } + + /** + * Return the set of memory pool which will be used by the Cordio stack + */ + virtual buf_pool_desc_t get_buffer_pool_description(); + + /** + * Initialize the HCI driver. + * This function start by initializing the transport driver then it delegates + * what's remain of the initialization to the function do_initialize. + */ + void initialize(); + + /** + * Termination of the driver. + * It call in sequence: + * - do_terminate + * - terminate the transport driver. + */ + void terminate(); + + /** + * Start the reset sequence of the BLE module. + */ + virtual void start_reset_sequence(); + + /** + * Handle HCI messages received during the reset sequence. + * + * @param msg The HCI message received. + * @note The driver should signal to the stack that the initialization + * sequence is done by calling the function: signal_reset_sequence_done. + */ + virtual void handle_reset_sequence(uint8_t *msg); + + /** + * Signal to the stack that the reset sequence has been done. + */ + void signal_reset_sequence_done(); + + /** + * Write data in the transport channel. + * + * @param type The type of packet to transmit. It might be an HCI command + * packet, ACL packet or EVT packet. Depending on the type of transport + * it can prefix the packet itself. + * @param len Number of bytes to transmit. + * @param pData pointer to the data to transmit. + * + * @return The number of bytes which have been transmited. + */ + uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + /** + * Initialize the chip. + * The transport is up at that time. + */ + virtual void do_initialize() = 0; + + /** + * Terminate the driver + */ + virtual void do_terminate() = 0; + + CordioHCITransportDriver& _transport_driver; +}; + + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_HCI_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp new file mode 100644 index 00000000000..01b0b1016a8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp @@ -0,0 +1,33 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 "CordioHCITransportDriver.h" +#include "CordioHCIDriver.h" + +extern "C" void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len); + +namespace ble { +namespace vendor { +namespace cordio { + +void CordioHCITransportDriver::on_data_received(uint8_t* data, uint16_t len) +{ + hciTrSerialRxIncoming(data, len); +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h new file mode 100644 index 00000000000..a7e7499f210 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_HCI_TRANSPORT_DRIVER_H_ +#define CORDIO_HCI_TRANSPORT_DRIVER_H_ + +#include + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Base class of the HCI transport driver. + * It allow the stack to write data in the HCI channel. + */ +class CordioHCITransportDriver { +public: + /** + * Driver destructor. + */ + virtual ~CordioHCITransportDriver() { } + + /** + * Inialization of the transport. + */ + virtual void initialize() = 0; + + /** + * termination of the transport. + */ + virtual void terminate() = 0; + + /** + * Write data in the transport channel. + * + * @param type The type of packet to transmit. It might be an HCI command + * packet, ACL packet or EVT packet. Depending on the type of transport + * it can prefix the packet itself. + * @param len Number of bytes to transmit. + * @param pData pointer to the data to transmit. + * + * @return The number of bytes which have been transmited. + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData) = 0; + + /** + * The driver shall call this function whenever data bytes are received. + * + * @param data Pointer to the data received. + * @param len Number of bytes received. + */ + static void on_data_received(uint8_t* data, uint16_t len); +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_HCI_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp new file mode 100644 index 00000000000..5ceff2b12ed --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp @@ -0,0 +1,70 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 "H4TransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +H4TransportDriver::H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud) : + uart(tx, rx, baud), cts(cts), rts(rts) { } + +void H4TransportDriver::initialize() +{ + uart.format( + /* bits */ 8, + /* parity */ SerialBase::None, + /* stop bit */ 1 + ); + + uart.set_flow_control( + /* flow */ SerialBase::RTSCTS, + /* rts */ rts, + /* cts */ cts + ); + + uart.attach( + callback(this, &H4TransportDriver::on_controller_irq), + SerialBase::RxIrq + ); +} + +void H4TransportDriver::terminate() { } + +uint16_t H4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ + uint16_t i = 0; + while (i < len + 1) { + uint8_t to_write = i == 0 ? type : pData[i - 1]; + while (uart.writeable() == 0); + uart.putc(to_write); + ++i; + } + return len; +} + +void H4TransportDriver::on_controller_irq() +{ + while (uart.readable()) { + uint8_t char_received = uart.getc(); + on_data_received(&char_received, 1); + } +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h new file mode 100644 index 00000000000..6e6e1d4b011 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h @@ -0,0 +1,76 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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. + */ + +#ifndef CORDIO_H4_TRANSPORT_DRIVER_H_ +#define CORDIO_H4_TRANSPORT_DRIVER_H_ + +#include +#include "mbed.h" +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Implementation of the H4 driver. + */ +class H4TransportDriver : public CordioHCITransportDriver { +public: + /** + * Initialize the transport driver. + * + * @param tx tx pin name. + * @param rx rx pin name + * @param cts cts pin name + * @param rts rts pin name. + * @param baud baud use to communicate with the ble module + */ + H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud); + + /** + * Destructor + */ + virtual ~H4TransportDriver() { } + + /** + * @see CordioHCITransportDriver::initialize + */ + virtual void initialize(); + + /** + * @see CordioHCITransportDriver::terminate + */ + virtual void terminate(); + + /** + * @see CordioHCITransportDriver::write + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + void on_controller_irq(); + + Serial uart; + PinName cts; + PinName rts; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_H4_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp new file mode 100644 index 00000000000..ba2d5e15bd0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -0,0 +1,452 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 "mbed.h" +#include "us_ticker_api.h" +#include "BLE.h" +#include "wsf_types.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "wsf_buf.h" +#include "wsf_timer.h" +#include "hci_handler.h" +#include "dm_handler.h" +#include "l2c_handler.h" +#include "att_handler.h" +#include "smp_handler.h" +#include "l2c_api.h" +#include "att_api.h" +#include "smp_api.h" +#include "hci_drv.h" +#include "CordioBLE.h" +#include "mbed_assert.h" + +#include "CordioPalAttClient.h" + +/*! WSF handler ID */ +wsfHandlerId_t stack_handler_id; + +/* Store the Event signaling state */ +bool isEventsSignaled = false; + +/** + * Weak definition of ble_cordio_get_hci_driver. + * A runtime error is generated if the user does not define any + * ble_cordio_get_hci_driver. + */ +MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() +{ + error("Please provide an implementation for the HCI driver"); + ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL; + return *bad_instance; +} + +/** + * Low level HCI interface between Cordio stack and the port. + */ +extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData) +{ + return ble_cordio_get_hci_driver().write(type, len, pData); +} + +extern "C" void hci_mbed_os_start_reset_sequence(void) +{ + ble_cordio_get_hci_driver().start_reset_sequence(); +} + +extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg) +{ + ble_cordio_get_hci_driver().handle_reset_sequence(msg); +} + +/* + * This function will signal to the user code by calling signalEventsToProcess. + * It is registered and called into the Wsf Stack. + */ +extern "C" void wsf_mbed_ble_signal_event(void) +{ + if(isEventsSignaled == false) { + isEventsSignaled = true; + ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE); + } +} + +/** + * BLE-API requires an implementation of the following function in order to + * obtain its transport handle. + */ +BLEInstanceBase *createBLEInstance() +{ + return (&(ble::vendor::cordio::BLE::deviceInstance())); +} + +namespace ble { +namespace vendor { +namespace cordio { + +BLE::BLE(CordioHCIDriver& hci_driver) : + initialization_status(NOT_INITIALIZED), + instanceID(::BLE::DEFAULT_INSTANCE) +{ + _hci_driver = &hci_driver; + stack_setup(); +} + +BLE::~BLE() { } + +/** + * The singleton which represents the BLE transport for the BLE. + */ +BLE& BLE::deviceInstance() +{ + static BLE instance( + ble_cordio_get_hci_driver() + ); + return instance; +} + +ble_error_t BLE::init( + ::BLE::InstanceID_t instanceID, + FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback) +{ + + switch (initialization_status) { + case NOT_INITIALIZED: + _init_callback = initCallback; + start_stack_reset(); + return BLE_ERROR_NONE; + + case INITIALIZING: + return BLE_ERROR_INITIALIZATION_INCOMPLETE; + + case INITIALIZED: + return BLE_ERROR_NONE; + + default: + return BLE_ERROR_UNSPECIFIED; + } +} + +bool BLE::hasInitialized() const +{ + return initialization_status == INITIALIZED; +} + +ble_error_t BLE::shutdown() +{ + if (initialization_status != INITIALIZED) { + return BLE_ERROR_INITIALIZATION_INCOMPLETE; + } + + initialization_status = NOT_INITIALIZED; + _hci_driver->terminate(); + + getGattServer().reset(); + getGattClient().reset(); + getGap().reset(); + + return BLE_ERROR_NONE; +} + +const char* BLE::getVersion() +{ + static const char version[] = "generic-cordio"; + return version; +} + +Gap& BLE::getGap() +{ + return cordio::Gap::getInstance(); +} + +const Gap& BLE::getGap() const +{ + return cordio::Gap::getInstance(); +} + +GattServer& BLE::getGattServer() +{ + return cordio::GattServer::getInstance(); +} + +const GattServer& BLE::getGattServer() const +{ + return cordio::GattServer::getInstance(); +} + +::GattClient& BLE::getGattClient() +{ + static pal::AttClientToGattClientAdapter pal_client( + pal::vendor::cordio::CordioAttClient::get_client() + ); + static generic::GenericGattClient client(&pal_client); + + return client; +} + +SecurityManager& BLE::getSecurityManager() +{ + return cordio::SecurityManager::getInstance(); +} + +const SecurityManager& BLE::getSecurityManager() const +{ + return cordio::SecurityManager::getInstance(); +} + +void BLE::waitForEvent() +{ + static Timeout nextTimeout; + timestamp_t nextTimestamp; + bool_t pTimerRunning; + + callDispatcher(); + + if (wsfOsReadyToSleep()) { + // setup an mbed timer for the next cordio timeout + nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000; + if (pTimerRunning) { + nextTimeout.attach_us(timeoutCallback, nextTimestamp); + } + } +} + +void BLE::processEvents() +{ + if (isEventsSignaled) { + isEventsSignaled = false; + callDispatcher(); + } + } + + void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg) + { + if (msg == NULL) { + return; + } + + switch(msg->event) { + case DM_RESET_CMPL_IND: { + ::BLE::InitializationCompleteCallbackContext context = { + ::BLE::Instance(::BLE::DEFAULT_INSTANCE), + BLE_ERROR_NONE + }; + deviceInstance().getGattServer().initialize(); + deviceInstance().getGap().initialize(); + deviceInstance().initialization_status = INITIALIZED; + _init_callback.call(&context); + } break; + + case DM_ADV_START_IND: + break; + + case DM_ADV_STOP_IND: + Gap::getInstance().advertisingStopped(); + break; + + case DM_SCAN_REPORT_IND: { + hciLeAdvReportEvt_t *scan_report = (hciLeAdvReportEvt_t*) msg; + Gap::getInstance().processAdvertisementReport( + scan_report->addr, + scan_report->rssi, + (scan_report->eventType == DM_RPT_SCAN_RESPONSE) ? true : false, + (GapAdvertisingParams::AdvertisingType_t) scan_report->eventType, + scan_report->len, + scan_report->pData + ); + } break; + + case DM_CONN_OPEN_IND: { + hciLeConnCmplEvt_t* conn_evt = (hciLeConnCmplEvt_t*) msg; + dmConnId_t connection_id = conn_evt->hdr.param; + Gap::getInstance().setConnectionHandle(connection_id); + Gap::AddressType_t own_addr_type; + Gap::Address_t own_addr; + Gap::getInstance().getAddress(&own_addr_type, own_addr); + + Gap::ConnectionParams_t params = { + conn_evt->connInterval, + conn_evt->connInterval, + conn_evt->connLatency, + conn_evt->supTimeout + }; + + Gap::getInstance().processConnectionEvent( + connection_id, + (conn_evt->role == DM_ROLE_MASTER) ? Gap::CENTRAL : Gap::PERIPHERAL, + (Gap::AddressType_t) conn_evt->addrType, + conn_evt->peerAddr, + own_addr_type, + own_addr, + ¶ms + ); + } break; + + case DM_CONN_CLOSE_IND: { + dmEvt_t *disconnect_evt = (dmEvt_t*) msg; + Gap::getInstance().setConnectionHandle(DM_CONN_ID_NONE); + Gap::getInstance().processDisconnectionEvent( + disconnect_evt->hdr.param, + (Gap::DisconnectionReason_t) disconnect_evt->connClose.reason + ); + } break; + + default: + break; + } +} + +void BLE::device_manager_cb(dmEvt_t* dm_event) +{ + BLE::deviceInstance().stack_handler(0, &dm_event->hdr); +} + +/* + * AttServerInitDeInitCback callback is used to Initialize/Deinitialize + * the CCC Table of the ATT Server when a remote peer requests to Open + * or Close the connection. + */ + void BLE::connection_handler(dmEvt_t* dm_event) + { + dmConnId_t connId = (dmConnId_t)dm_event->hdr.param; + + switch (dm_event->hdr.event) { + case DM_CONN_OPEN_IND: + /* set up CCC table with uninitialized (all zero) values */ + AttsCccInitTable(connId, NULL); + break; + case DM_CONN_CLOSE_IND: + /* clear CCC table on connection close */ + AttsCccClearTable(connId); + break; + default: + break; + } +} + +void BLE::timeoutCallback() +{ + wsf_mbed_ble_signal_event(); +} + +void BLE::stack_setup() +{ + MBED_ASSERT(_hci_driver != NULL); + + wsfHandlerId_t handlerId; + + buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description(); + + // Initialize buffers with the ones provided by the HCI driver + uint16_t bytes_used = WsfBufInit( + buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory, + buf_pool_desc.pool_count, buf_pool_desc.pool_description + ); + + MBED_ASSERT(bytes_used != 0); + + WsfTimerInit(); + SecInit(); + + // Note: enable once security is supported +#if 0 + SecAesInit(); + SecCmacInit(); + SecEccInit(); +#endif + + handlerId = WsfOsSetNextHandler(HciHandler); + HciHandlerInit(handlerId); + + handlerId = WsfOsSetNextHandler(DmHandler); + DmAdvInit(); + DmScanInit(); + DmConnInit(); + DmConnMasterInit(); + DmConnSlaveInit(); + DmSecInit(); + + // Note: enable once security is supported +#if 0 + DmSecLescInit(); + DmPrivInit(); +#endif + DmHandlerInit(handlerId); + + handlerId = WsfOsSetNextHandler(L2cSlaveHandler); + L2cSlaveHandlerInit(handlerId); + L2cInit(); + L2cSlaveInit(); + L2cMasterInit(); + + handlerId = WsfOsSetNextHandler(AttHandler); + AttHandlerInit(handlerId); + AttsInit(); + AttsIndInit(); + AttcInit(); + + handlerId = WsfOsSetNextHandler(SmpHandler); + SmpHandlerInit(handlerId); + SmprScInit(); + SmpiInit(); + + stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler); + + DmRegister(BLE::device_manager_cb); + DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb); + AttConnRegister(BLE::connection_handler); + AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler); +} + +void BLE::start_stack_reset() +{ + _hci_driver->initialize(); + DmDevReset(); +} + +void BLE::callDispatcher() +{ + static uint32_t lastTimeUs = us_ticker_read(); + uint32_t currTimeUs, deltaTimeMs; + + // Update the current cordio time + currTimeUs = us_ticker_read(); + deltaTimeMs = (currTimeUs - lastTimeUs) / 1000; + if (deltaTimeMs > 0) { + WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK); + lastTimeUs += deltaTimeMs * 1000; + } + + wsfOsDispatcher(); + + if (wsfOsReadyToSleep()) { + static Timeout nextTimeout; + // setup an mbed timer for the next Cordio timeout + bool_t pTimerRunning; + timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000; + if (pTimerRunning) { + nextTimeout.attach_us(timeoutCallback, nextTimestamp); + } + } +} + +CordioHCIDriver* BLE::_hci_driver = NULL; + +FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback; + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp new file mode 100644 index 00000000000..450a2def4bc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp @@ -0,0 +1,543 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 + +#include "CordioGap.h" +#include "mbed.h" +#include "dm_api.h" +#include "CordioGattServer.h" +#include "hci_core.h" + +/**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x0020 + +/**< Minimum Advertising interval in 625 us units for non connectable mode, i.e. 100 ms. */ +#define BLE_GAP_ADV_NONCON_INTERVAL_MIN 0x00A0 + +/**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x4000 + +namespace ble { +namespace vendor { +namespace cordio { + +Gap &Gap::getInstance() +{ + static Gap m_instance; + return m_instance; +} + +void Gap::initialize() +{ + uint8_t whitelist_size = HciGetWhiteListSize(); + + if (whitelist_size == 0) { + return; + } + + whitelist.addresses = new(std::nothrow) BLEProtocol::Address_t[whitelist_size]; + if (whitelist.addresses == NULL) { + return; + } + + whitelist.size = 0; + whitelist.capacity = hciCoreCb.whiteListSize; +} + +ble_error_t Gap::setAddress(AddressType_t type, const Address_t address) +{ + switch (type) { + case BLEProtocol::AddressType::PUBLIC: + // TODO: use vendor specific commands from the driver + return BLE_ERROR_OPERATION_NOT_PERMITTED; + + // See bluetooth 5, Vol 6 part, part B, 1.3.2 + case BLEProtocol::AddressType::RANDOM_STATIC: + if ((address[5] >> 6) != 3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + m_type = type; + BdaCpy(m_addr, address); + DmDevSetRandAddr(m_addr); + break; + + // should not be here, generation is supposed to be handled by the controller. + case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: + case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: + m_type = type; + return BLE_ERROR_NONE; + + default: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + DmAdvSetAddrType(m_type); + DmConnSetAddrType(m_type); + DmScanSetAddrType(m_type); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::getAddress(AddressType_t *typeP, Address_t address) +{ + *typeP = m_type; + + if(m_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE || + m_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { + return BLE_ERROR_NONE; + } + + BdaCpy(address, m_addr); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) +{ + /* Make sure we don't exceed the advertising payload length */ + if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + /* Make sure we have a payload! */ + if (advData.getPayloadLen() == 0) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* set advertising and scan response data for discoverable mode */ + DmAdvSetData(DM_ADV_HANDLE_DEFAULT, HCI_ADV_DATA_OP_COMP_FRAG, DM_DATA_LOC_ADV, advData.getPayloadLen(), (uint8_t*)advData.getPayload()); + DmAdvSetData(DM_ADV_HANDLE_DEFAULT, HCI_ADV_DATA_OP_COMP_FRAG, DM_DATA_LOC_SCAN, scanResponse.getPayloadLen(), (uint8_t*)scanResponse.getPayload()); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams +) { + // prepare the scan interval + if (scanParams != NULL) { + DmConnSetScanInterval(scanParams->getInterval(), scanParams->getWindow()); + } + + if (connectionParams != NULL) { + hciConnSpec_t conn_spec = { + /* connIntervalMin */ connectionParams->minConnectionInterval, + /* connIntervalMax */ connectionParams->maxConnectionInterval, + /* connLatency */ connectionParams->slaveLatency, + /* supTimeout */ connectionParams->connectionSupervisionTimeout, + /* minCeLen */ DM_GAP_CONN_EST_MIN_CE_LEN, + /* maxCeLen */ DM_GAP_CONN_EST_MAX_CE_LEN + }; + DmConnSetConnSpec(&conn_spec); + } + + DmScanStop(); + dmConnId_t connection_id = DmConnOpen( + DM_CLIENT_ID_APP, + HCI_INIT_PHY_LE_1M_BIT, + peerAddrType, + (uint8_t*) peerAddr + ); + + if (connection_id == DM_CONN_ID_NONE) { + return BLE_ERROR_INTERNAL_STACK_FAILURE; + } + + return BLE_ERROR_NONE; +} + +uint16_t Gap::getMinAdvertisingInterval() const +{ + return BLE_GAP_ADV_INTERVAL_MIN; +} + +uint16_t Gap::getMinNonConnectableAdvertisingInterval() const +{ + return BLE_GAP_ADV_NONCON_INTERVAL_MIN; +} + +uint16_t Gap::getMaxAdvertisingInterval() const +{ + return BLE_GAP_ADV_INTERVAL_MAX; +} + +ble_error_t Gap::startAdvertising(const GapAdvertisingParams ¶ms) +{ + /* Make sure we support the advertising type */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { + /* ToDo: This requires a proper security implementation, etc. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /* Check interval range */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { + /* Min delay is slightly longer for unconnectable devices */ + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } else { + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + /* Check timeout is zero for Connectable Directed */ + if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { + /* Timeout must be 0 with this type, although we'll never get here */ + /* since this isn't implemented yet anyway */ + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check timeout for other advertising types */ + if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && + (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + uint16_t adv_interval_min = params.getIntervalInADVUnits(); + if (adv_interval_min == GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX) { + --adv_interval_min; + } + uint16_t adv_interval_max = adv_interval_min + 1; + + DmAdvSetInterval(DM_ADV_HANDLE_DEFAULT, adv_interval_min, adv_interval_max); + + /* Peer Addr Type 0 = Public */ + uint8_t peerAddrType = 0; + uint8_t peerAddr[6] = { 0 }; + DmAdvConfig(DM_ADV_HANDLE_DEFAULT, params.getAdvertisingType(), peerAddrType, peerAddr); + + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + uint16_t adv_durations[] = { (uint16_t) (params.getTimeout() * 1000) }; + uint8_t max_ea_events[] = { 0 }; + DmAdvStart(1, adv_handles, adv_durations, max_ea_events); + + state.advertising = 1; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::stopAdvertising(void) +{ + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + DmAdvStop(1, adv_handles); + + state.advertising = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) +{ + DmConnClose(DM_CLIENT_ID_APP, connectionHandle, reason); + + state.advertising = 0; + state.connected = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect(DisconnectionReason_t reason) +{ + DmConnClose(DM_CLIENT_ID_APP, m_connectionHandle, reason); + + state.advertising = 0; + state.connected = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setDeviceName(const uint8_t *deviceName) +{ + return GattServer::getInstance().setDeviceName(deviceName); +} + +ble_error_t Gap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) +{ + const uint8_t* name = NULL; + uint16_t length = 0; + + GattServer::getInstance().getDeviceName(name, length); + + if (deviceName != NULL) { + memcpy(deviceName, name, std::min((uint16_t) *lengthP, length)); + } + + *lengthP = length; + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAppearance(GapAdvertisingData::Appearance appearance) +{ + GattServer::getInstance().setAppearance(appearance); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::getAppearance(GapAdvertisingData::Appearance *appearanceP) +{ + *appearanceP = GattServer::getInstance().getAppearance(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setTxPower(int8_t txPower) +{ +#if 0 + HciVsSetTxPower(txPower); + return BLE_ERROR_NONE; +#else + return BLE_ERROR_NOT_IMPLEMENTED; +#endif +} + +void Gap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) +{ + *valueArrayPP = NULL; + *countP = 0; +} + +void Gap::setConnectionHandle(uint16_t connectionHandle) +{ + m_connectionHandle = connectionHandle; +} + +uint16_t Gap::getConnectionHandle(void) +{ + return m_connectionHandle; +} + +ble_error_t Gap::getPreferredConnectionParams(ConnectionParams_t *params) +{ + *params = GattServer::getInstance().getPreferredConnectionParams(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setPreferredConnectionParams(const ConnectionParams_t *params) +{ + // ensure that parameters are correct + // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] + // section 12.3 PERIPHERAL PREFERRED CONNECTION PARAMETERS CHARACTERISTIC + if (((0x0006 > params->minConnectionInterval) || (params->minConnectionInterval > 0x0C80)) && + params->minConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((params->minConnectionInterval > params->maxConnectionInterval) || (params->maxConnectionInterval > 0x0C80)) && + params->maxConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (params->slaveLatency > 0x01F3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((0x000A > params->connectionSupervisionTimeout) || (params->connectionSupervisionTimeout > 0x0C80)) && + params->connectionSupervisionTimeout != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + GattServer::getInstance().setPreferredConnectionParams(*params); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) +{ + if (DmConnCheckIdle(handle) != 0) { + return BLE_STACK_BUSY; + } + + hciConnSpec_t connSpec; + connSpec.connIntervalMin = newParams->minConnectionInterval; + connSpec.connIntervalMax = newParams->maxConnectionInterval; + connSpec.connLatency = newParams->slaveLatency; + connSpec.supTimeout = newParams->connectionSupervisionTimeout; + DmConnUpdate(handle, &connSpec); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::startRadioScan(const GapScanningParams &scanningParams) +{ + // not needed to start scanning if the whitelist is empty and the scanning + // policy filter all the advertising packets + if ((whitelist.size == 0) && (scanning_policy_mode == Gap::SCAN_POLICY_FILTER_ALL_ADV)) { + return BLE_ERROR_INVALID_STATE; + } + + uint16_t scan_intervals[] = { scanningParams.getInterval() }; + uint16_t scan_windows[] = { scanningParams.getWindow() }; + + DmScanSetInterval(HCI_SCAN_PHY_LE_1M_BIT, scan_intervals, scan_windows); + + uint8_t scanType = scanningParams.getActiveScanning() ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE; + uint32_t duration = (uint32_t)scanningParams.getTimeout() * 1000; + if (duration > 0xFFFF) { + // saturate to 16-bits + duration = 0xFFFF; + } + + DmScanStart(HCI_SCAN_PHY_LE_1M_BIT, DM_DISC_MODE_NONE, &scanType, TRUE, duration, 0); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::stopScan(void) +{ + DmScanStop(); + return BLE_ERROR_NONE; +} + +void Gap::advertisingStopped(void) +{ + /* If advertising stopped due to a call to stopAdvertising(), state.advertising will + * be '0.' Otherwise, advertising must have stopped due to a timeout + */ + if (state.advertising) { + processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); + } +} + +uint8_t Gap::getMaxWhitelistSize(void) const +{ + return whitelist.capacity; +} + +ble_error_t Gap::getWhitelist(Whitelist_t &other) const +{ + // i is a shorthand for other.size + uint8_t& i = other.size; + + for (i = 0; (i < whitelist.capacity) && (i < other.capacity); ++i) { + other.addresses[i] = whitelist.addresses[i]; + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setWhitelist(const Whitelist_t& other) +{ + if (other.capacity > whitelist.capacity) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + // note : can be improved by sending the diff instead of the full list + + DmDevWhiteListClear(); + + // alias i to whitelist.size + uint8_t& i = whitelist.size; + + for (i = 0; (i < other.capacity) && (i < whitelist.capacity); ++i) { + whitelist.addresses[i] = other.addresses[i]; + DmDevWhiteListAdd( + (whitelist.addresses[i].type > 1) ? 0xFF : whitelist.addresses[i].type, + whitelist.addresses[i].address + ); + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_ADV, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + advertising_policy_mode = mode; + return BLE_ERROR_NONE; +} + +Gap::AdvertisingPolicyMode_t Gap::getAdvertisingPolicyMode(void) const +{ + return advertising_policy_mode; +} + +ble_error_t Gap::setScanningPolicyMode(ScanningPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_SCAN, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + scanning_policy_mode = mode; + return BLE_ERROR_NONE; + +} + +Gap::ScanningPolicyMode_t Gap::getScanningPolicyMode(void) const +{ + return scanning_policy_mode; +} + +ble_error_t Gap::setInitiatorPolicyMode(InitiatorPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_INIT, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + initiator_policy_mode = mode; + return BLE_ERROR_NONE; +} + +Gap::InitiatorPolicyMode_t Gap::getInitiatorPolicyMode(void) const +{ + return initiator_policy_mode; +} + +ble_error_t Gap::reset(void) +{ + this->::Gap::reset(); + delete[] whitelist.addresses; + whitelist.addresses = NULL; + whitelist.size = 0; + whitelist.capacity = 0; + return BLE_ERROR_NONE; +} + +Gap::Gap() : + ::Gap(), + m_connectionHandle(DM_CONN_ID_NONE), + m_type(BLEProtocol::AddressType::RANDOM_STATIC), + m_addr(), + advertising_policy_mode(ADV_POLICY_IGNORE_WHITELIST), + scanning_policy_mode(SCAN_POLICY_IGNORE_WHITELIST), + initiator_policy_mode(INIT_POLICY_IGNORE_WHITELIST), + whitelist() +{ +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp new file mode 100644 index 00000000000..6f1a68da17f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -0,0 +1,763 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 +#include "CordioGattServer.h" +#include "CordioGap.h" +#include "mbed.h" +#include "wsf_types.h" +#include "att_api.h" + +static UUID cccUUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG); +static const uint16_t cccSize = sizeof(uint16_t); + +namespace ble { +namespace vendor { +namespace cordio { + +GattServer &GattServer::getInstance() +{ + static GattServer m_instance; + return m_instance; +} + +void GattServer::initialize() +{ + add_generic_access_service(); + add_generic_attribute_service(); +} + +ble_error_t GattServer::addService(GattService &service) +{ + ++currentHandle; + uint16_t startHandle = currentHandle; + + internal_service_t *internal_service = new internal_service_t; + + if (registered_service) { + internal_service->next = registered_service; + } else { + internal_service->next = NULL; + } + + registered_service = internal_service; + + // Create cordio attribute group + internal_service->attGroup = new attsGroup_t; + + // Determine the attribute list length + unsigned int attListLen = 1; + for (int i = 0; i < service.getCharacteristicCount(); i++) { + attListLen += 2; + GattCharacteristic *p_char = service.getCharacteristic(i); + + attListLen += p_char->getDescriptorCount(); + if (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) { + // add a CCCD + attListLen++; + } + } + + // Create cordio attribute list + internal_service->attGroup->pAttr = (attsAttr_t*)alloc_block(attListLen * sizeof(attsAttr_t)); + if (internal_service->attGroup->pAttr == NULL) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + // Create characteristics + internal_service->chars = new internal_char_t [service.getCharacteristicCount()]; + + attsAttr_t *currAtt = internal_service->attGroup->pAttr; + + /* Service */ + currAtt->pUuid = attPrimSvcUuid; + if (service.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + internal_service->uuidLen = UUID::LENGTH_OF_LONG_UUID; + } else { + internal_service->uuidLen = sizeof(UUID::ShortUUIDBytes_t); + } + currAtt->pValue = (uint8_t*)alloc_block(internal_service->uuidLen); + memcpy(currAtt->pValue, service.getUUID().getBaseUUID(), internal_service->uuidLen); + currAtt->maxLen = internal_service->uuidLen; + currAtt->pLen = &internal_service->uuidLen; + currAtt->settings = 0; + currAtt->permissions = ATTS_PERMIT_READ; + + currAtt++; + + /* Add characteristics to the service */ + for (int i = 0; i < service.getCharacteristicCount(); i++) { + GattCharacteristic *p_char = service.getCharacteristic(i); + + /* Skip any incompletely defined, read-only characteristics. */ + if ((p_char->getValueAttribute().getValuePtr() == NULL) && + (p_char->getValueAttribute().getLength() == 0) && + (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { + continue; + } + + // Create Characteristic Attribute + currentHandle += 2; + currAtt->pUuid = attChUuid; + + p_char->getValueAttribute().setHandle(currentHandle); + internal_service->chars[i].descLen = 1 + sizeof(currentHandle) + p_char->getValueAttribute().getUUID().getLen(); + currAtt->pValue = (uint8_t*) alloc_block(internal_service->chars[i].descLen); + uint8_t *pValue = currAtt->pValue; + *pValue++ = p_char->getProperties(); + memcpy(pValue, ¤tHandle, sizeof(currentHandle)); + pValue += sizeof(currentHandle); + memcpy(pValue, p_char->getValueAttribute().getUUID().getBaseUUID(), p_char->getValueAttribute().getUUID().getLen()); + + currAtt->pLen = &internal_service->chars[i].descLen; + currAtt->maxLen = internal_service->chars[i].descLen; + currAtt->settings = 0; + currAtt->permissions = ATTS_PERMIT_READ; + currAtt++; + + // Create Value Attribute + currAtt->pUuid = p_char->getValueAttribute().getUUID().getBaseUUID(); + currAtt->maxLen = p_char->getValueAttribute().getMaxLength(); + currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); + *currAtt->pLen = p_char->getValueAttribute().getLength(); + currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); + memcpy(currAtt->pValue, p_char->getValueAttribute().getValuePtr(), *currAtt->pLen); + memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); + + currAtt->settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK; + if (p_char->getValueAttribute().getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + currAtt->settings |= ATTS_SET_UUID_128; + } + if (p_char->getValueAttribute().hasVariableLength()) { + currAtt->settings |= ATTS_SET_VARIABLE_LEN; + } + + currAtt->permissions = 0; + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) { currAtt->permissions |= ATTS_PERMIT_READ; } + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) { currAtt->permissions |= ATTS_PERMIT_WRITE; } + currAtt++; + + bool cccCreated = false; + + for (int i = 0; i < p_char->getDescriptorCount(); i++) { + GattAttribute *p_att = p_char->getDescriptor(i); + + currentHandle++; + + p_att->setHandle(currentHandle); + + currAtt->pUuid = p_att->getUUID().getBaseUUID(); + currAtt->maxLen = p_att->getMaxLength(); + currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); + *currAtt->pLen = p_att->getLength(); + currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); + memcpy(currAtt->pValue, p_att->getValuePtr(), *currAtt->pLen); + memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); + + currAtt->settings = 0; + currAtt->permissions = ATTS_PERMIT_READ | ATTS_PERMIT_WRITE; + if (p_att->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + currAtt->settings |= ATTS_SET_UUID_128; + } + if (p_att->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) { + cccCreated = true; + currAtt->settings |= ATTS_SET_CCC; + currAtt->permissions |= ATTS_PERMIT_READ; + currAtt->permissions |= ATTS_PERMIT_WRITE; + + if (cccCnt < MAX_CCC_CNT) { + cccSet[cccCnt].handle = currentHandle; + cccSet[cccCnt].valueRange = 0; + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; + cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); + cccCnt++; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + if (p_att->hasVariableLength()) { + currAtt->settings |= ATTS_SET_VARIABLE_LEN; + } + currAtt++; + } + + if (!cccCreated && (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) { + /* There was not a CCCD included in the descriptors, but this + * characteristic is notifiable and/or indicatable. A CCCD is + * required so create one now. + */ + if (cccCnt >= MAX_CCC_CNT) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + currentHandle++; + + currAtt->pUuid = cccUUID.getBaseUUID(); + currAtt->pValue = (uint8_t*)&cccValues[cccCnt]; + currAtt->pLen = (uint16_t*)&cccSize; + currAtt->maxLen = sizeof(uint16_t); + currAtt->settings = ATTS_SET_CCC; + currAtt->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + + cccSet[cccCnt].handle = currentHandle; + cccSet[cccCnt].valueRange = 0; + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { + cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; + cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); + + cccCnt++; + currAtt++; + } + } + + internal_service->attGroup->pNext = NULL; + internal_service->attGroup->readCback = attsReadCback; + internal_service->attGroup->writeCback = attsWriteCback; + internal_service->attGroup->startHandle = startHandle; + internal_service->attGroup->endHandle = currentHandle; + AttsAddGroup(internal_service->attGroup); + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + + service.setHandle(startHandle); + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t * lengthP) +{ + uint16_t attribute_length = 0; + uint8_t* attribute_value = NULL; + + if (AttsGetAttr(attributeHandle, &attribute_length, &attribute_value) != ATT_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (buffer) { + memcpy(buffer, attribute_value, std::min(*lengthP, attribute_length)); + } + + *lengthP = attribute_length; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) +{ + // Check to see if this is a CCCD + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccSet[idx].handle) { + if (connectionHandle == DM_CONN_ID_NONE) { // CCCDs are always 16 bits + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + *((uint16_t*)buffer) = AttsCccGet(connectionHandle, idx); + *lengthP = 2; // CCCDs are always 16 bits + return BLE_ERROR_NONE; + } + } + + // This is not a CCCD. Use the non-connection specific update method. + return read(attributeHandle, buffer, lengthP); +} + +ble_error_t GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + uint16_t connectionHandle = Gap::getInstance().getConnectionHandle(); + + if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (!localOnly) { + if (connectionHandle != DM_CONN_ID_NONE) { + + // Check to see if this characteristic has a CCCD attribute + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccHandles[idx]) { + break; + } + } + if (idx < cccCnt) { + // This characteristic has a CCCD attribute. Handle notifications and indications. + uint16_t cccEnabled = AttsCccEnabled(connectionHandle, idx); + if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { + AttsHandleValueNtf(connectionHandle, attributeHandle, len, (uint8_t*)buffer); + } + if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { + AttsHandleValueInd(connectionHandle, attributeHandle, len, (uint8_t*)buffer); + } + } + } + } + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + // Check to see if this is a CCCD + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccSet[idx].handle) { + if ((connectionHandle == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + AttsCccSet(connectionHandle, idx, *((uint16_t*)buffer)); + return BLE_ERROR_NONE; + } + } + + // This is not a CCCD. Use the non-connection specific update method. + return write(attributeHandle, buffer, len, localOnly); +} + +ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) +{ + uint16_t connectionHandle = Gap::getInstance().getConnectionHandle(); + + if (connectionHandle != DM_CONN_ID_NONE) { + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (characteristic.getValueHandle() == cccHandles[idx]) { + uint16_t cccValue = AttsCccGet(connectionHandle, idx); + if (cccValue & ATT_CLIENT_CFG_NOTIFY) { + *enabledP = true; + } else { + *enabledP = false; + } + return BLE_ERROR_NONE; + } + } + } + + return BLE_ERROR_PARAM_OUT_OF_RANGE; +} + +ble_error_t GattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) +{ + if (connectionHandle != DM_CONN_ID_NONE) { + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (characteristic.getValueHandle() == cccHandles[idx]) { + uint16_t cccValue = AttsCccGet(connectionHandle, idx); + if (cccValue & ATT_CLIENT_CFG_NOTIFY) { + *enabledP = true; + } else { + *enabledP = false; + } + return BLE_ERROR_NONE; + } + } + } + + return BLE_ERROR_PARAM_OUT_OF_RANGE; +} + +bool GattServer::isOnDataReadAvailable() const +{ + return true; +} + +::Gap::ConnectionParams_t GattServer::getPreferredConnectionParams() +{ + ::Gap::ConnectionParams_t params = { 0 }; + memcpy(¶ms.minConnectionInterval, generic_access_service.ppcp, 2); + memcpy(¶ms.maxConnectionInterval, generic_access_service.ppcp + 2, 2); + memcpy(¶ms.slaveLatency, generic_access_service.ppcp + 4, 2); + memcpy(¶ms.connectionSupervisionTimeout, generic_access_service.ppcp + 6, 2); + return params; +} + +void GattServer::setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params) +{ + memcpy(generic_access_service.ppcp, ¶ms.minConnectionInterval, 2); + memcpy(generic_access_service.ppcp + 2, ¶ms.maxConnectionInterval, 2); + memcpy(generic_access_service.ppcp + 4, ¶ms.slaveLatency, 2); + memcpy(generic_access_service.ppcp + 6, ¶ms.connectionSupervisionTimeout, 2); +} + +ble_error_t GattServer::setDeviceName(const uint8_t *deviceName) +{ + size_t length = 0; + + if (deviceName != NULL) { + length = strlen((const char*)deviceName); + } + + if (length == 0) { + free(generic_access_service.device_name_value()); + } else { + uint8_t* res = (uint8_t*) realloc(generic_access_service.device_name_value(), length); + if (res == NULL) { + return BLE_ERROR_NO_MEM; + } + + generic_access_service.device_name_value() = res; + memcpy(res, deviceName, length); + } + + generic_access_service.device_name_length = length; + + return BLE_ERROR_NONE; +} + +void GattServer::getDeviceName(const uint8_t*& name, uint16_t& length) +{ + length = generic_access_service.device_name_length; + name = generic_access_service.device_name_value(); +} + +void GattServer::setAppearance(GapAdvertisingData::Appearance appearance) +{ + generic_access_service.appearance = appearance; +} + +GapAdvertisingData::Appearance GattServer::getAppearance() +{ + return (GapAdvertisingData::Appearance) generic_access_service.appearance; +} + +ble_error_t GattServer::reset(void) +{ + this->::GattServer::reset(); + + while (registered_service) { + internal_service_t* s = registered_service; + registered_service = s->next; + AttsRemoveGroup(s->attGroup->startHandle); + delete s->attGroup; + delete[] s->chars; + delete s; + } + + while (allocated_blocks) { + alloc_block_t* b = allocated_blocks; + allocated_blocks = b->next; + free(b); + } + + AttsRemoveGroup(generic_access_service.service.startHandle); + AttsRemoveGroup(generic_attribute_service.service.startHandle); + free(generic_access_service.device_name_value()); + + currentHandle = 0; + cccCnt = 0; + + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + + return BLE_ERROR_NONE; +} + +void GattServer::cccCback(attsCccEvt_t *pEvt) +{ + if (pEvt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, pEvt->handle); + } else { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, pEvt->handle); + } +} + +void GattServer::attCback(attEvt_t *pEvt) +{ + // TODO enable again + if (pEvt->hdr.status == ATT_SUCCESS) { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, pEvt->handle); + } +} + +uint8_t GattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) +{ + GattReadCallbackParams cbParams = { + connId, + handle, + offset, + *pAttr->pLen, + pAttr->pValue, + /* status */ BLE_ERROR_NONE, + }; + getInstance().handleDataReadEvent(&cbParams); + + return ATT_SUCCESS; +} + +uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr) +{ + uint8_t err; + + /* TODO: offset is not handled properly */ + if ((err = AttsSetAttr(handle, len, pValue)) != ATT_SUCCESS) { + return err; + } + + GattWriteCallbackParams::WriteOp_t writeOp; + switch (operation) { + case ATT_PDU_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_WRITE_REQ; + break; + case ATT_PDU_WRITE_CMD: + writeOp = GattWriteCallbackParams::OP_WRITE_CMD; + break; + case ATT_PDU_SIGNED_WRITE_CMD: + writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD; + break; + case ATT_PDU_PREP_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_PREP_WRITE_REQ; + break; + case ATT_PDU_EXEC_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_EXEC_WRITE_REQ_NOW; + break; + default: + writeOp = GattWriteCallbackParams::OP_INVALID; + break; + } + + GattWriteCallbackParams cbParams = { + connId, + handle, + writeOp, + offset, + len, + pValue + }; + getInstance().handleDataWrittenEvent(&cbParams); + + return ATT_SUCCESS; +} + +void GattServer::add_generic_access_service() +{ + ++currentHandle; + generic_access_service.service.pNext = NULL; + generic_access_service.service.startHandle = currentHandle; + generic_access_service.service.readCback = attsReadCback; + generic_access_service.service.writeCback = attsWriteCback; + + // bind attributes to the service + generic_access_service.service.pAttr = generic_access_service.attributes; + + attsAttr_t* current_attribute = generic_access_service.attributes; + + // service attribute + current_attribute->pUuid = attPrimSvcUuid; + current_attribute->pValue = (uint8_t*) attGapSvcUuid; + current_attribute->maxLen = sizeof(attGapSvcUuid); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // device name declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.device_name_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.device_name_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.device_name_declaration_value + 3, attDnChUuid, sizeof(attDnChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.device_name_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.device_name_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // device name value + ++current_attribute; + generic_access_service.device_name_length = 0; + current_attribute->pUuid = attDnChUuid; + current_attribute->maxLen = 248; + current_attribute->pLen = &generic_access_service.device_name_length; + current_attribute->pValue = NULL; + current_attribute->settings = ATTS_SET_VARIABLE_LEN; + current_attribute->permissions = ATTS_PERMIT_READ; + + // appearance declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.appearance_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.appearance_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.appearance_declaration_value + 3, attApChUuid, sizeof(attApChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.appearance_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.appearance_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // appearance value + ++current_attribute; + generic_access_service.appearance = 0; // unknown appearance + current_attribute->pUuid = attApChUuid; + current_attribute->maxLen = sizeof(generic_access_service.appearance); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = (uint8_t*) &generic_access_service.appearance; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + + // peripheral prefered connection parameters declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.ppcp_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.ppcp_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.ppcp_declaration_value + 3, attPpcpChUuid, sizeof(attPpcpChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.ppcp_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.ppcp_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // peripheral prefered connection parameters value + ++current_attribute; + const uint8_t default_ppcp_value[] = { + 0xFF, 0xFF, // no specific min connection interval + 0xFF, 0xFF, // no specific max connection interval + 0x00, 0x00, // no slave latency + 0xFF, 0xFF // no specific connection supervision timeout + }; + memcpy(&generic_access_service.ppcp, default_ppcp_value, sizeof(default_ppcp_value)); + current_attribute->pUuid = attPpcpChUuid; + current_attribute->maxLen = sizeof(generic_access_service.ppcp); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = generic_access_service.ppcp; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + generic_access_service.service.endHandle = currentHandle; + AttsAddGroup(&generic_access_service.service); +} + +void GattServer::add_generic_attribute_service() +{ + ++currentHandle; + generic_attribute_service.service.pNext = NULL; + generic_attribute_service.service.startHandle = currentHandle; + generic_attribute_service.service.readCback = attsReadCback; + generic_attribute_service.service.writeCback = attsWriteCback; + + // bind attributes to the service + generic_attribute_service.service.pAttr = generic_attribute_service.attributes; + + attsAttr_t* current_attribute = generic_attribute_service.attributes; + + // service attribute + current_attribute->pUuid = attPrimSvcUuid; + current_attribute->pValue = (uint8_t*) attGattSvcUuid; + current_attribute->maxLen = sizeof(attGattSvcUuid); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // service changed declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_attribute_service.service_changed_declaration[0] = ATT_PROP_INDICATE; + // set value handle + memcpy(generic_attribute_service.service_changed_declaration + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_attribute_service.service_changed_declaration + 3, attScChUuid, sizeof(attScChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_attribute_service.service_changed_declaration; + current_attribute->maxLen = sizeof(generic_attribute_service.service_changed_declaration); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // service changed value + ++current_attribute; + current_attribute->pUuid = attScChUuid; + current_attribute->maxLen = 0; + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = NULL; + current_attribute->settings = 0; + current_attribute->permissions = 0; + + // CCCD + ++current_attribute; + current_attribute->pUuid = attCliChCfgUuid; + current_attribute->pValue = (uint8_t*)&cccValues[cccCnt]; + current_attribute->maxLen = 2; + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = ATTS_SET_CCC; + current_attribute->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + + cccSet[cccCnt].handle = currentHandle; + cccSet[cccCnt].valueRange = ATT_CLIENT_CFG_INDICATE; + cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; + cccHandles[cccCnt] = currentHandle - 1; + cccCnt++; + + generic_attribute_service.service.endHandle = currentHandle; + AttsAddGroup(&generic_attribute_service.service); + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); +} + +void* GattServer::alloc_block(size_t block_size) { + alloc_block_t* block = (alloc_block_t*) malloc(sizeof(alloc_block_t) + block_size); + if (block == NULL) { + return NULL; + } + + if (allocated_blocks) { + block->next = allocated_blocks; + } else { + block->next = NULL; + } + + allocated_blocks = block; + + return block->data; +} + +GattServer::GattServer() : + ::GattServer(), cccSet(), cccValues(), cccHandles(), cccCnt(0), + generic_access_service(), generic_attribute_service(), + registered_service(NULL), allocated_blocks(NULL), + currentHandle(0) +{ +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c new file mode 100644 index 00000000000..f42dff73f54 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c @@ -0,0 +1,28 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * 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 "wsf_mbed_os_adaptation.h" +#include "mbed_critical.h" + +void wsf_mbed_os_critical_section_enter(void) +{ + core_util_critical_section_enter(); +} + +void wsf_mbed_os_critical_section_exit(void) +{ + core_util_critical_section_exit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt new file mode 100644 index 00000000000..9a4f65e654f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, September 2015 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named “DEPENDENCIES” and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h new file mode 100644 index 00000000000..3ae594c3dbb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file hci_core_ps.h + * + * \brief HCI core platform-specific interfaces for dual-chip. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_PS_H +#define HCI_CORE_PS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCoreResetSequence(uint8_t *pMsg); +void hciCoreNumCmplPkts(uint8_t *pMsg); +void hciCoreRecv(uint8_t msgType, uint8_t *pCoreRecvMsg); +uint8_t hciCoreVsCmdCmplRcvd(uint16_t opcode, uint8_t *pMsg, uint8_t len); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_PS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h new file mode 100644 index 00000000000..33b5098d5bf --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h @@ -0,0 +1,46 @@ +/*************************************************************************************************/ +/*! + * \file hci_cmd.h + * + * \brief HCI command module. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CMD_H +#define HCI_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCmdSend(uint8_t *pData); +uint8_t *hciCmdAlloc(uint16_t opcode, uint16_t len); +void hciCmdInit(void); +void hciCmdTimeout(wsfMsgHdr_t *pMsg); +void hciCmdRecvCmpl(uint8_t numCmdPkts); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CMD_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h new file mode 100644 index 00000000000..74ad361b8a6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h @@ -0,0 +1,129 @@ +/*************************************************************************************************/ +/*! + * \file hci_core.h + * + * \brief HCI core interfaces. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_H +#define HCI_CORE_H + +#include "hci_core_ps.h" +#include "wsf_queue.h" +#include "wsf_os.h" +#include "hci_api.h" +#include "cfg_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +typedef void(*hciResetSeq_t)(uint8_t *pMsg, uint16_t opcode); + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Per-connection structure for ACL packet accounting */ +typedef struct +{ + uint8_t *pTxAclPkt; /* Fragmenting TX ACL packet pointer */ + uint8_t *pNextTxFrag; /* Next TX ACL packet fragment */ + uint8_t *pRxAclPkt; /* RX ACL packet pointer */ + uint8_t *pNextRxFrag; /* Next RX ACL packet fragment */ + uint16_t handle; /* Connection handle */ + uint16_t txAclRemLen; /* Fragmenting TX ACL packet remaining length */ + uint16_t rxAclRemLen; /* Fragmented RX ACL packet remaining length */ + bool_t fragmenting; /* TRUE if fragmenting a TX ACL packet */ + bool_t flowDisabled; /* TRUE if data flow disabled */ + uint8_t queuedBufs; /* Queued ACL buffers on this connection */ + uint8_t outBufs; /* Outstanding ACL buffers sent to controller */ +} hciCoreConn_t; + +/* Main control block for dual-chip implementation */ +typedef struct +{ + hciCoreConn_t conn[DM_CONN_MAX]; /* Connection structures */ + uint8_t leStates[HCI_LE_STATES_LEN]; /* Controller LE supported states */ + bdAddr_t bdAddr; /* Bluetooth device address */ + wsfQueue_t aclQueue; /* HCI ACL TX queue */ + hciCoreConn_t *pConnRx; /* Connection struct for current transport RX packet */ + uint16_t maxRxAclLen; /* Maximum reassembled RX ACL packet length */ + uint16_t bufSize; /* Controller ACL data buffer size */ + uint8_t aclQueueHi; /* Disable flow when this many ACL buffers queued */ + uint8_t aclQueueLo; /* Enable flow when this many ACL buffers queued */ + uint8_t availBufs; /* Current avail ACL data buffers */ + uint8_t numBufs; /* Controller number of ACL data buffers */ + uint8_t whiteListSize; /* Controller white list size */ + uint8_t numCmdPkts; /* Controller command packed count */ + uint16_t leSupFeat; /* Controller LE supported features */ + int8_t advTxPwr; /* Controller advertising TX power */ + uint8_t resListSize; /* Controller resolving list size */ + uint16_t maxAdvDataLen; /* Controller maximum advertisement (or scan response) data length */ + uint8_t numSupAdvSets; /* Controller maximum number of advertising sets */ + uint8_t perAdvListSize; /* Controller periodic advertising list size */ + hciResetSeq_t extResetSeq; /* HCI extended reset sequence callback */ +} hciCoreCb_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/* Control block */ +extern hciCoreCb_t hciCoreCb; + +/* Event mask */ +extern const uint8_t hciEventMask[HCI_EVT_MASK_LEN]; + +/* LE event mask */ +extern const uint8_t hciLeEventMask[HCI_LE_EVT_MASK_LEN]; + +/* Event mask page 2 */ +extern const uint8_t hciEventMaskPage2[HCI_EVT_MASK_LEN]; + +/* LE supported features configuration mask */ +extern uint16_t hciLeSupFeatCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCoreInit(void); +void hciCoreResetStart(void); +void hciCoreConnOpen(uint16_t handle); +void hciCoreConnClose(uint16_t handle); +hciCoreConn_t *hciCoreConnByHandle(uint16_t handle); +void hciCoreSendAclData(hciCoreConn_t *pConn, uint8_t *pData); +void hciCoreTxReady(uint8_t bufs); +void hciCoreTxAclStart(hciCoreConn_t *pConn, uint16_t len, uint8_t *pData); +bool_t hciCoreTxAclContinue(hciCoreConn_t *pConn); +void hciCoreTxAclComplete(hciCoreConn_t *pConn, uint8_t *pData); +uint8_t *hciCoreAclReassembly(uint8_t *pData); +bool_t hciCoreTxAclDataFragmented(hciCoreConn_t *pConn); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h new file mode 100644 index 00000000000..b0b6e562d5d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h @@ -0,0 +1,83 @@ +/*************************************************************************************************/ +/*! + * \file hci_drv.h + * + * \brief HCI driver interface. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2012-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_DRV_H +#define HCI_DRV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn hciDrvWrite + * + * \brief Write data the driver. + * + * \param type HCI packet type + * \param len Number of bytes to write. + * \param pData Byte array to write. + * + * \return Return actual number of data bytes written. + * + * \note The type parameter allows the driver layer to prepend the data with a header on the + * same write transaction. + */ +/*************************************************************************************************/ +uint16_t hciDrvWrite(uint8_t type, uint16_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn hciDrvRead + * + * \brief Read data bytes from the driver. + * + * \param len Number of bytes to read. + * \param pData Byte array to store data. + * + * \return Return actual number of data bytes read. + */ +/*************************************************************************************************/ +uint16_t hciDrvRead(uint16_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn hciDrvReadyToSleep + * + * \brief Returns TRUE if driver allows MCU to enter low power sleep mode. + * + * \return TRUE if ready to sleep, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t hciDrvReadyToSleep(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_DRV_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h new file mode 100644 index 00000000000..6e94e7f7985 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h @@ -0,0 +1,64 @@ +/*************************************************************************************************/ +/*! + * \file hci_evt.h + * + * \brief HCI event module. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_EVT_H +#define HCI_EVT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* HCI event statistics */ +typedef struct +{ + uint16_t numDiscCmplEvt; + uint16_t numEncChangeEvt; + uint16_t numReadRemoteVerInfoCmpEvt; + uint16_t numCmdCmplEvt; + uint16_t numCmdStatusEvt; + uint16_t numHwErrorEvt; + uint16_t numCmplPktsEvt; + uint16_t numDataBufOverflowEvt; + uint16_t numEncKeyRefreshCmplEvt; + uint16_t numLeMetaEvt; + uint16_t numVendorSpecEvt; + uint16_t numAuthToEvt; +} hciEvtStats_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciEvtProcessMsg(uint8_t *pEvt); +hciEvtStats_t *hciEvtGetStats(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_EVT_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h new file mode 100644 index 00000000000..e91baa3ed6f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file hci_tr.h + * + * \brief HCI transport interface. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_TR_H +#define HCI_TR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciTrSendAclData(void *pContext, uint8_t *pAclData); +void hciTrSendCmd(uint8_t *pCmdData); +bool_t hciTrInit(uint8_t port, uint32_t baudRate, bool_t flowControl); +void hciTrShutdown(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_TR_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h new file mode 100644 index 00000000000..d16cbb4dd61 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h @@ -0,0 +1,246 @@ +/*************************************************************************************************/ +/*! + * \file sec_api.h + * + * \brief AES and random number security service API. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SEC_API_H +#define SEC_API_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! CMAC algorithm key length */ +#define SEC_CMAC_KEY_LEN 16 + +/*! CMAC algorithm result length */ +#define SEC_CMAC_HASH_LEN 16 + +/*! ECC algorithm key length */ +#define SEC_ECC_KEY_LEN 32 + +/*! Invalid AES Token */ +#define SEC_TOKEN_INVALID 0xFF + +/************************************************************************************************** + Data Types +**************************************************************************************************/ +/*! AES Security callback parameters structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! header */ + uint8_t *pCiphertext; /*! pointer to 16 bytes of ciphertext data */ +} secMsg_t; + +/*! AES Security callback are the same as secMsg_t */ +typedef secMsg_t secAes_t; + +/*! CMAC Security callback are the same as secMsg_t */ +typedef secMsg_t secCmacMsg_t; + +/*! ECC Security public/private key pair */ +typedef struct +{ + uint8_t pubKey_x[SEC_ECC_KEY_LEN]; /*! x component of ecc public key */ + uint8_t pubKey_y[SEC_ECC_KEY_LEN]; /*! y component of ecc public key */ + uint8_t privKey[SEC_ECC_KEY_LEN]; /*! ecc private key */ +} secEccKey_t; + +/*! ECC security DH Key shared secret */ +typedef struct +{ + uint8_t secret[SEC_ECC_KEY_LEN]; /*! DH Key Shared secret */ +} secEccSharedSec_t; + + +/*! ECC Security callback parameters structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! header */ + union + { + secEccSharedSec_t sharedSecret; /*! shared secret */ + secEccKey_t key; /*! ecc public/private key pair */ + } data; +} secEccMsg_t; + + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SecInit + * + * \brief Initialize the security service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecRandInit + * + * \brief Initialize the random number service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecRandInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecAesInit + * + * \brief Initialize the AES service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecAesInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecCmacInit + * + * \brief Called to initialize CMAC security. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecCmacInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecEccInit + * + * \brief Called to initialize ECC security. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecEccInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecAes + * + * \brief Execute an AES calculation. When the calculation completes, a WSF message will be + * sent to the specified handler. This function returns a token value that + * the client can use to match calls to this function with messages. + * + * \param pKey Pointer to 16 byte key. + * \param pPlaintext Pointer to 16 byte plaintext. + * \param handlerId WSF handler ID. + * \param param Client-defined parameter returned in message. + * \param event Event for client's WSF handler. + * + * \return Token value. + */ +/*************************************************************************************************/ +uint8_t SecAes(uint8_t *pKey, uint8_t *pPlaintext, wsfHandlerId_t handlerId, + uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecAesCmac + * + * \brief Execute the CMAC algorithm. + * + * \param pKey Key used in CMAC operation. + * \param pPlaintext Data to perform CMAC operation over + * \param len Size of pPlaintext in bytes. + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecCmac(const uint8_t *pKey, uint8_t *pPlaintext, uint8_t textLen, wsfHandlerId_t handlerId, + uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecEccGenKey + * + * \brief Generate an ECC key. + * + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecEccGenKey(wsfHandlerId_t handlerId, uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecEccGenSharedSecret + * + * \brief Generate an ECC key. + * + * \param pKey ECC Key structure. + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecEccGenSharedSecret(secEccKey_t *pKey, wsfHandlerId_t handlerId, uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecRand + * + * \brief This function returns up to 16 bytes of random data to a buffer provided by the + * client. + * + * \param pRand Pointer to returned random data. + * \param randLen Length of random data. + * + * \return None. + */ +/*************************************************************************************************/ +void SecRand(uint8_t *pRand, uint8_t randLen); + +#ifdef __cplusplus +}; +#endif + +#endif /* SEC_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h new file mode 100644 index 00000000000..8cc4bc47aef --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h @@ -0,0 +1,103 @@ +/*************************************************************************************************/ +/*! + * \file cfg_stack.h + * + * \brief Stack configuration. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef CFG_STACK_H +#define CFG_STACK_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + HCI +**************************************************************************************************/ + +/*! Vendor specific targets */ +#define HCI_VS_GENERIC 0 +#define HCI_VS_EMM 1 + +/*! Vendor specific target configuration */ +#ifndef HCI_VS_TARGET +#define HCI_VS_TARGET HCI_VS_GENERIC +#endif + +/* Extra byte allocation required for LL operations (i.e. MIC) in single-chip implementation */ +#ifndef HCI_TX_DATA_TAILROOM +#define HCI_TX_DATA_TAILROOM 0 +#endif + +/************************************************************************************************** + DM +**************************************************************************************************/ + +/*! Maximum number of connections */ +#ifndef DM_CONN_MAX +#define DM_CONN_MAX 3 +#endif + +/*! Number of supported advertising sets: must be set to 1 for legacy advertising */ +#ifndef DM_NUM_ADV_SETS +#define DM_NUM_ADV_SETS 1 +#endif + +/*! Number of scanner and initiator PHYs (LE 1M, LE 2M and LE Coded): must be set to 1 for + legacy scanner and initiator */ +#ifndef DM_NUM_PHYS +#define DM_NUM_PHYS 1 +#endif + +/************************************************************************************************** + L2C +**************************************************************************************************/ + +/*! Maximum number of connection oriented channels */ +#ifndef L2C_COC_CHAN_MAX +#define L2C_COC_CHAN_MAX 8 +#endif + +/*! Maximum number of connection oriented channel registered clients */ +#ifndef L2C_COC_REG_MAX +#define L2C_COC_REG_MAX 4 +#endif + +/************************************************************************************************** + ATT +**************************************************************************************************/ + +/*! Maximum number of simultanous ATT notifications */ +#ifndef ATT_NUM_SIMUL_NTF +#define ATT_NUM_SIMUL_NTF 1 +#endif + +/************************************************************************************************** + SMP +**************************************************************************************************/ + + +#ifdef __cplusplus +}; +#endif + +#endif /* CFG_STACK_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h new file mode 100644 index 00000000000..ba81dd509da --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h @@ -0,0 +1,1111 @@ +/*************************************************************************************************/ +/*! + * \file att_api.h + * + * \brief Attribute protocol client and server API. + * + * $Date: 2017-03-03 17:46:38 -0600 (Fri, 03 Mar 2017) $ + * $Revision: 11375 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_API_H +#define ATT_API_H + +#include "wsf_timer.h" +#include "att_defs.h" +#include "att_uuid.h" +#include "dm_api.h" +#include "cfg_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! ATT server attribute settings */ +#define ATTS_SET_UUID_128 0x01 /*! Set if the UUID is 128 bits in length */ +#define ATTS_SET_WRITE_CBACK 0x02 /*! Set if the group callback is executed when + this attribute is written by a client device */ +#define ATTS_SET_READ_CBACK 0x04 /*! Set if the group callback is executed when + this attribute is read by a client device */ +#define ATTS_SET_VARIABLE_LEN 0x08 /*! Set if the attribute has a variable length */ +#define ATTS_SET_ALLOW_OFFSET 0x10 /*! Set if writes are allowed with an offset */ +#define ATTS_SET_CCC 0x20 /*! Set if the attribute is a client characteristic + configuration descriptor */ +#define ATTS_SET_ALLOW_SIGNED 0x40 /*! Set if signed writes are allowed */ +#define ATTS_SET_REQ_SIGNED 0x80 /*! Set if signed writes are required if link + is not encrypted */ + +/*! ATT server attribute permissions */ +#define ATTS_PERMIT_READ 0x01 /*! Set if attribute can be read */ +#define ATTS_PERMIT_READ_AUTH 0x02 /*! Set if attribute read requires authentication */ +#define ATTS_PERMIT_READ_AUTHORIZ 0x04 /*! Set if attribute read requires authorization */ +#define ATTS_PERMIT_READ_ENC 0x08 /*! Set if attribute read requires encryption */ +#define ATTS_PERMIT_WRITE 0x10 /*! Set if attribute can be written */ +#define ATTS_PERMIT_WRITE_AUTH 0x20 /*! Set if attribute write requires authentication */ +#define ATTS_PERMIT_WRITE_AUTHORIZ 0x40 /*! Set if attribute write requires authorization */ +#define ATTS_PERMIT_WRITE_ENC 0x80 /*! Set if attribute write requires encryption */ + +/*! ATT client characteristic discovery and configuration settings */ +#define ATTC_SET_UUID_128 0x01 /*! Set if the UUID is 128 bits in length */ +#define ATTC_SET_REQUIRED 0x02 /*! Set if characteristic must be discovered */ +#define ATTC_SET_DESCRIPTOR 0x04 /*! Set if this is a characteristic descriptor */ + +/*! ATT callback events */ +#define ATT_CBACK_START 0x02 /*! ATT callback event starting value */ +enum /*! Internal note: event values match method values */ +{ + /*! ATT client callback events */ + ATTC_FIND_INFO_RSP = ATT_CBACK_START, /*! Find information response */ + ATTC_FIND_BY_TYPE_VALUE_RSP, /*! Find by type value response */ + ATTC_READ_BY_TYPE_RSP, /*! Read by type value response */ + ATTC_READ_RSP, /*! Read response */ + ATTC_READ_LONG_RSP, /*! Read long response */ + ATTC_READ_MULTIPLE_RSP, /*! Read multiple response */ + ATTC_READ_BY_GROUP_TYPE_RSP, /*! Read group type response */ + ATTC_WRITE_RSP, /*! Write response */ + ATTC_WRITE_CMD_RSP, /*! Write command response */ + ATTC_PREPARE_WRITE_RSP, /*! Prepare write response */ + ATTC_EXECUTE_WRITE_RSP, /*! Execute write response */ + ATTC_HANDLE_VALUE_NTF, /*! Handle value notification */ + ATTC_HANDLE_VALUE_IND, /*! Handle value indication */ + /*! ATT server callback events */ + ATTS_HANDLE_VALUE_CNF, /*! Handle value confirmation */ + ATTS_CCC_STATE_IND, /*! Client chracteristic configuration state change */ + /*! ATT common callback events */ + ATT_MTU_UPDATE_IND /*! Negotiated MTU value */ +}; + +/*! ATT callback events */ +#define ATT_CBACK_END ATT_MTU_UPDATE_IND /*! ATT callback event ending value */ + +/*! Base value for HCI error status values passed through ATT */ +#define ATT_HCI_ERR_BASE 0x20 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Configurable parameters */ +typedef struct +{ + wsfTimerTicks_t discIdleTimeout; /*! ATT server service discovery connection idle timeout in seconds */ + uint16_t mtu; /*! desired ATT MTU */ + uint8_t transTimeout; /*! transcation timeout in seconds */ + uint8_t numPrepWrites; /*! number of queued prepare writes supported by server */ +} attCfg_t; + +/*! + * Attribute server data types + */ + +/*! Attribute structure */ +typedef struct +{ + uint8_t const *pUuid; /*! Pointer to the attribute's UUID */ + uint8_t *pValue; /*! Pointer to the attribute's value */ + uint16_t *pLen; /*! Pointer to the length of the attribute's value */ + uint16_t maxLen; /*! Maximum length of attribute's value */ + uint8_t settings; /*! Attribute settings */ + uint8_t permissions; /*! Attribute permissions */ +} attsAttr_t; + +/*! Attribute group read callback */ +typedef uint8_t (*attsReadCback_t)(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, attsAttr_t *pAttr); + +/*! Attribute group write callback */ +typedef uint8_t (*attsWriteCback_t)(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, uint16_t len, uint8_t *pValue, + attsAttr_t *pAttr); + +/*! Attribute group */ +typedef struct attsGroup_tag +{ + struct attsGroup_tag *pNext; /*! For internal use only */ + attsAttr_t *pAttr; /*! Pointer to attribute list for this group */ + attsReadCback_t readCback; /*! Read callback function */ + attsWriteCback_t writeCback; /*! Write callback function */ + uint16_t startHandle; /*! The handle of the first attribute in this group */ + uint16_t endHandle; /*! The handle of the last attribute in this group */ +} attsGroup_t; + +/*! Client characteristc configuration settings */ +typedef struct +{ + uint16_t handle; /*! Client characteristc configuration descriptor handle */ + uint16_t valueRange; /*! Acceptable value range of the descriptor value */ + uint8_t secLevel; /*! Security level of characteristic value */ +} attsCccSet_t; + +/*! ATT client structure for characteristic and descriptor discovery */ +typedef struct attcDiscChar_tag +{ + uint8_t const *pUuid; /*! Pointer to UUID */ + uint8_t settings; /*! Characteristic discovery settings */ +} attcDiscChar_t; + +/*! ATT client structure for characteristic and descriptor configuration */ +typedef struct +{ + uint8_t const *pValue; /*! Pointer to default value or NULL */ + uint8_t valueLen; /*! Default value length */ + uint8_t hdlIdx; /*! Index of its handle in handle list */ +} attcDiscCfg_t; + +/*! ATT client discovery control block */ +typedef struct +{ + attcDiscChar_t **pCharList; /*! Characterisic list for discovery */ + uint16_t *pHdlList; /*! Characteristic handle list */ + attcDiscCfg_t *pCfgList; /*! Characterisic list for configuration */ + uint8_t charListLen; /*! Characteristic and handle list length */ + uint8_t cfgListLen; /*! Configuration list length */ + + /* the following are for internal use only */ + uint16_t svcStartHdl; + uint16_t svcEndHdl; + uint8_t charListIdx; + uint8_t endHdlIdx; +} attcDiscCb_t; + +/*! + * ATT callback parameters: + * + * \param hdr.event Callback event + * \param hdr.param DM connection ID + * \param hdr.status Event status: ATT_SUCCESS or error status + * \param pValue Pointer to value data, valid if valueLen > 0 + * \param valueLen Length of value data + * \param handle Attribute handle + * \param continuing TRUE if more response packets expected + * \param mtu Negotiated MTU value + */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint8_t *pValue; /*! Value */ + uint16_t valueLen; /*! Value length */ + uint16_t handle; /*! Attribute handle */ + bool_t continuing; /*! TRUE if more response packets expected */ + uint16_t mtu; /*! Negotiated MTU value */ +} attEvt_t; + +/*! ATTS client characteristic configuration callback structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t handle; /*! CCCD handle */ + uint16_t value; /*! CCCD value */ + uint8_t idx; /*! CCCD settings index */ +} attsCccEvt_t; + +/*! ATT callback type */ +typedef void (*attCback_t)(attEvt_t *pEvt); + +/*! ATTS authorization callback type */ +typedef uint8_t (*attsAuthorCback_t)(dmConnId_t connId, uint8_t permit, uint16_t handle); + +/*! ATTS client characteristic configuration callback */ +typedef void (*attsCccCback_t)(attsCccEvt_t *pEvt); + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! Configuration pointer */ +extern attCfg_t *pAttCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn AttRegister + * + * \brief Register a callback with ATT. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttRegister(attCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttConnRegister + * + * \brief Register a connection callback with ATT. The callback is typically used to + * manage the attribute server database. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttConnRegister(dmCback_t cback); + + +/*************************************************************************************************/ +/*! + * \fn AttGetMtu + * + * \brief Get the attribute protocol MTU of a connection. + * + * \param connId DM connection ID. + * + * \return MTU of the connection. + */ +/*************************************************************************************************/ +uint16_t AttGetMtu(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttsInit + * + * \brief Initialize ATT server. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsIndInit + * + * \brief Initialize ATT server for indications/notifications. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsIndInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsSignInit + * + * \brief Initialize ATT server for data signing. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSignInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsAuthorRegister + * + * \brief Register an authorization callback with the attribute server. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsAuthorRegister(attsAuthorCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttsAddGroup + * + * \brief Add an attribute group to the attribute server. + * + * \param pGroup Pointer to an attribute group structure. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsAddGroup(attsGroup_t *pGroup); + +/*************************************************************************************************/ +/*! + * \fn AttsRemoveGroup + * + * \brief Remove an attribute group from the attribute server. + * + * \param startHandle Start handle of attribute group to be removed. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsRemoveGroup(uint16_t startHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsSetAttr + * + * \brief Set an attribute value in the attribute server. + * + * \param handle Attribute handle. + * \param valueLen Attribute length. + * \param pValue Attribute value. + * + * \return ATT_SUCCESS if successful otherwise error. + */ +/*************************************************************************************************/ +uint8_t AttsSetAttr(uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsGetAttr + * + * \brief Get an attribute value in the attribute server. + * + * \param handle Attribute handle. + * \param pLen Returned attribute length pointer. + * \param pValue Returned attribute value pointer. + * + * \return ATT_SUCCESS if successful otherwise error. + * \return This function returns the attribute length in pLen and a pointer to the attribute + * value in pValue. + */ +/*************************************************************************************************/ +uint8_t AttsGetAttr(uint16_t handle, uint16_t *pLen, uint8_t **pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueInd + * + * \brief Send an attribute protocol Handle Value Indication. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueInd(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueNtf + * + * \brief Send an attribute protocol Handle Value Notification. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueNtf(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueIndZeroCpy + * + * \brief Send an attribute protocol Handle Value Indication without copying the attribute + * value data. + * + * Note: attribute value buffer 'pValue' must be allocated with AttMsgAlloc(). + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueIndZeroCpy(dmConnId_t connId, uint16_t handle, uint16_t valueLen, + uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueNtfZeroCpy + * + * \brief Send an attribute protocol Handle Value Notification without copying the attribute + * value data. + * + * Note: attribute value buffer 'pValue' must be allocated with AttMsgAlloc(). + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueNtfZeroCpy(dmConnId_t connId, uint16_t handle, uint16_t valueLen, + uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsCccRegister + * + * \brief Register the utility service for managing client characteristic + * configuration descriptors. This function is typically called once on + * system initialization. + * + * \param setLen Length of settings array. + * \param pSet Array of CCC descriptor settings. + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccRegister(uint8_t setLen, attsCccSet_t *pSet, attsCccCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttsCccInitTable + * + * \brief Initialize the client characteristic configuration descriptor value table for a + * connection. The table is initialized with the values from pCccTbl. If pCccTbl + * is NULL the table will be initialized to zero. + * + * This function must be called when a connection is established or when a + * device is bonded. + * + * \param connId DM connection ID. + * \param pCccTbl Pointer to the descriptor value array. The length of the array + * must equal the value of setLen passed to AttsCccRegister(). + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccInitTable(dmConnId_t connId, uint16_t *pCccTbl); + +/*************************************************************************************************/ +/*! + * \fn AttsCccClearTable + * + * \brief Clear and deallocate the client characteristic configuration descriptor value + * table for a connection. This function must be called when a connection is closed. + * + * \param connId DM connection ID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccClearTable(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttsCccGet + * + * \brief Get the value of a client characteristic configuration descriptor by its index. + * If not found, return zero. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * + * \return Value of the descriptor. + */ +/*************************************************************************************************/ +uint16_t AttsCccGet(dmConnId_t connId, uint8_t idx); + +/*************************************************************************************************/ +/*! + * \fn AttsCccSet + * + * \brief Set the value of a client characteristic configuration descriptor by its index. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * \param value Value of the descriptor. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccSet(dmConnId_t connId, uint8_t idx, uint16_t value); + +/*************************************************************************************************/ +/*! + * \fn AttsCccEnabled + * + * \brief Check if a client characteristic configuration descriptor is enabled and if + * the characteristic's security level has been met. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * + * \return Value of the descriptor if security level is met, otherwise zero. + */ +/*************************************************************************************************/ +uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx); + +/*************************************************************************************************/ +/*! + * \fn AttsSetCsrk + * + * \brief Set the peer's data signing key on this connection. This function + * is typically called from the ATT connection callback when the connection is + * established. The caller is responsible for maintaining the memory that + * contains the key. + * + * \param connId DM connection ID. + * \param pCsrk Pointer to data signing key (CSRK). + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk); + +/*************************************************************************************************/ +/*! + * \fn AttsSetSignCounter + * + * \brief Set the peer's sign counter on this connection. This function + * is typically called from the ATT connection callback when the connection is + * established. ATT maintains the value of the sign counter internally and + * sets the value when a signed packet is successfully received. + * + * \param connId DM connection ID. + * \param signCounter Sign counter. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSetSignCounter(dmConnId_t connId, uint32_t signCounter); + +/*************************************************************************************************/ +/*! + * \fn AttsGetSignCounter + * + * \brief Get the current value peer's sign counter on this connection. This function + * is typically called from the ATT connection callback when the connection is + * closed so the application can store the sign counter for use on future + * connections. + * + * \param connId DM connection ID. + * + * \return Sign counter. + */ +/*************************************************************************************************/ +uint32_t AttsGetSignCounter(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttcInit + * + * \brief Initialize ATT client. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttcSignInit + * + * \brief Initialize ATT client for data signing. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcSignInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttcFindInfoReq + * + * \brief Initiate an attribute protocol Find Information Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcFindInfoReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcFindByTypeValueReq + * + * \brief Initiate an attribute protocol Find By Type Value Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuid16 16-bit UUID to find. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcFindByTypeValueReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint16_t uuid16, uint16_t valueLen, uint8_t *pValue, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadByTypeReq + * + * \brief Initiate an attribute protocol Read By Type Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuidLen Length of UUID (2 or 16). + * \param pUuid Pointer to UUID data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadByTypeReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint8_t uuidLen, uint8_t *pUuid, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadReq + * + * \brief Initiate an attribute protocol Read Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadReq(dmConnId_t connId, uint16_t handle); + +/*************************************************************************************************/ +/*! + * \fn AttcReadLongReq + * + * \brief Initiate an attribute protocol Read Long Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param offset Read attribute data starting at this offset. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadLongReq(dmConnId_t connId, uint16_t handle, uint16_t offset, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadMultipleReq + * + * \brief Initiate an attribute protocol Read Multiple Request. + * + * \param connId DM connection ID. + * \param numHandles Number of handles in attribute handle list. + * \param pHandles List of attribute handles. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadMultipleReq(dmConnId_t connId, uint8_t numHandles, uint16_t *pHandles); + +/*************************************************************************************************/ +/*! + * \fn AttcReadByGroupTypeReq + * + * \brief Initiate an attribute protocol Read By Group Type Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuidLen Length of UUID (2 or 16). + * \param pUuid Pointer to UUID data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadByGroupTypeReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint8_t uuidLen, uint8_t *pUuid, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcWriteReq + * + * \brief Initiate an attribute protocol Write Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcWriteReq(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcWriteCmd + * + * \brief Initiate an attribute protocol Write Command. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcWriteCmd(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcSignedWriteCmd + * + * \brief Initiate an attribute protocol signed Write Command. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param signCounter Value of the sign counter. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcSignedWriteCmd(dmConnId_t connId, uint16_t handle, uint32_t signCounter, + uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcPrepareWriteReq + * + * \brief Initiate an attribute protocol Prepare Write Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param offset Write attribute data starting at this offset. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * \param valueByRef TRUE if pValue data is accessed by reference rather than copied. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcPrepareWriteReq(dmConnId_t connId, uint16_t handle, uint16_t offset, uint16_t valueLen, + uint8_t *pValue, bool_t valueByRef, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcExecuteWriteReq + * + * \brief Initiate an attribute protocol Execute Write Request. + * + * \param connId DM connection ID. + * \param writeAll TRUE to write all queued writes, FALSE to cancel all queued writes. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcExecuteWriteReq(dmConnId_t connId, bool_t writeAll); + +/*************************************************************************************************/ +/*! + * \fn AttcCancelReq + * + * \brief Cancel an attribute protocol request in progress. + * + * \param connId DM connection ID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcCancelReq(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscService + * + * \brief This utility function discovers the given service on a peer device. Function + * AttcFindByTypeValueReq() is called to initiate the discovery procedure. + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * \param uuidLen Length of service UUID (2 or 16). + * \param pUuid Pointer to service UUID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcDiscService(dmConnId_t connId, attcDiscCb_t *pCb, uint8_t uuidLen, uint8_t *pUuid); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscServiceCmpl + * + * \brief This utility function processes a service discovery result. It should be called + * when an ATTC_FIND_BY_TYPE_VALUE_RSP callback event is received after service + * discovery is initiated by calling AttcDiscService(). + * + * \param pCb Pointer to discovery control block. + * \param pMsg ATT callback event message. + * + * \return ATT_SUCCESS if successful otherwise error. + */ +/*************************************************************************************************/ +uint8_t AttcDiscServiceCmpl(attcDiscCb_t *pCb, attEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscCharStart + * + * \brief This utility function starts characteristic and characteristic descriptor + * discovery for a service on a peer device. The service must have been previously + * discovered by calling AttcDiscService() and AttcDiscServiceCmpl(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcDiscCharStart(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscCharCmpl + * + * \brief This utility function processes a characteristic discovery result. It should be + * called when an ATTC_READ_BY_TYPE_RSP or ATTC_FIND_INFO_RSP callback event is + * received after characteristic discovery is initiated by calling AttcDiscCharStart(). + * + * \param pCb Pointer to discovery control block. + * \param pMsg ATT callback event message. + * + * \return ATT_CONTINUING if successful and the discovery procedure is continuing. + * ATT_SUCCESS if the discovery procedure completed successfully. + * Otherwise the discovery procedure failed. + */ +/*************************************************************************************************/ +uint8_t AttcDiscCharCmpl(attcDiscCb_t *pCb, attEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigStart + * + * \brief This utility function starts characteristic configuration for characteristics on a + * peer device. The characteristics must have been previously discovered by calling + * AttcDiscCharStart() and AttcDiscCharCmpl(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if nothing to configure. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigStart(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigCmpl + * + * \brief This utility function initiates the next characteristic configuration procedure. + * It should be called when an ATTC_READ_RSP or ATTC_WRITE_RSP callback event is received + * after characteristic configuration is initiated by calling AttcDiscConfigStart(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if configuration procedure completed successfully. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigCmpl(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigResume + * + * \brief This utility function resumes the characteristic configuration procedure. It can + * be called when an ATTC_READ_RSP or ATTC_WRITE_RSP callback event is received + * with failure status to attempt the read or write procedure again. + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if configuration procedure completed successfully. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigResume(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcMtuReq + * + * \brief For internal use only. + * + * \param connId DM connection ID. + * \param mtu Attribute protocol MTU. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcMtuReq(dmConnId_t connId, uint16_t mtu); + +/*************************************************************************************************/ +/*! + * \fn AttsErrorTest + * + * \brief For testing purposes only. + * + * \param status ATT status + * + * \return None. + */ +/*************************************************************************************************/ +void AttsErrorTest(uint8_t status); + +/*************************************************************************************************/ +/*! + * \fn AttMsgAlloc + * + * \brief Allocate an ATT message buffer to be sent with the ATT attribute protocol + * zero-copy APIs. + * + * \param len Message length in bytes. + * \param opcode Opcode for ATT message. + * + * \return Pointer to message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *AttMsgAlloc(uint16_t len, uint8_t opcode); + +/*************************************************************************************************/ +/*! + * \fn AttMsgFree + * + * \brief Free an ATT message buffer allocated with AttMsgAlloc(). + * + * \param pMsg Pointer to message buffer. + * \param opcode Opcode for ATT message. + * + * \return None. + */ +/*************************************************************************************************/ +void AttMsgFree(void *pMsg, uint8_t opcode); + +/*************************************************************************************************/ +/*! + * \fn AttsDynInit + * + * \brief Initialize the Dynamic ATT Service subsystem. + * + * \param None. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsDynCreateGroup + * + * \brief Dynamically create an ATT Service at runtime. + * + * \param startHandle Starting attribute handle in the service + * \param endHandle Last attribute handle in the service + * + * \return Service Handle. + */ +/*************************************************************************************************/ +void *AttsDynCreateGroup(uint16_t startHandle, uint16_t endHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsDynDeleteGroup + * + * \brief Dynamically delete an ATT Service at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynDeleteGroup(void *pSvcHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsDynRegister + * + * \brief Register callback functions for a dynamic ATT Service at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynRegister(void *pSvcHandle, attsReadCback_t readCback, attsWriteCback_t writeCback); + +/*************************************************************************************************/ +/*! + * \fn AttsDynAddAttr + * + * \brief Dynamically add an attribute to a dynamic ATT Services at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * \param pUuid Constant UUID + * \param pValue Initial value of attribute (copied into attribute memory) + * \param len Length of pValue in bytes + * \param maxLen Maximum length of the attribute in bytes + * \param settings Attribute settings + * \param permissions Attribute permissions + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynAddAttr(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, uint16_t len, + const uint16_t maxLen, uint8_t settings, uint8_t permissions); + +/*************************************************************************************************/ +/*! + * \fn AttsDynAddAttrConst + * + * \brief Dynamically add an attribute with a constant value to a dynamic ATT Services at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * \param pUuid Constant UUID + * \param pValue Pointer to constant attribute memory + * \param len Length of pValue in bytes + * \param settings Attribute settings + * \param permissions Attribute permissions + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynAddAttrConst(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, + const uint16_t len, uint8_t settings, uint8_t permissions); + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h new file mode 100644 index 00000000000..cbb5250c17c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h @@ -0,0 +1,225 @@ +/*************************************************************************************************/ +/*! + * \file att_defs.h + * + * \brief Attribute protocol constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_DEFS_H +#define ATT_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Attribute PDU format */ +#define ATT_HDR_LEN 1 /*! Attribute PDU header length */ +#define ATT_AUTH_SIG_LEN 12 /*! Authentication signature length */ +#define ATT_DEFAULT_MTU 23 /*! Default value of ATT_MTU */ +#define ATT_MAX_MTU 517 /*! Maximum value of ATT_MTU */ +#define ATT_DEFAULT_PAYLOAD_LEN 20 /*! Default maximum payload length for most PDUs */ + +/*! Attribute value parameters */ +#define ATT_VALUE_MAX_LEN 512 /*! Maximum attribute value length */ +#define ATT_VALUE_MAX_OFFSET 511 /*! Maximum attribute value offset */ + +/*! Transaction timeout */ +#define ATT_MAX_TRANS_TIMEOUT 30 /*! Maximum transaction timeout in seconds */ + +/*! Error codes */ +#define ATT_SUCCESS 0x00 /*! Operation successful */ +#define ATT_ERR_HANDLE 0x01 /*! Invalid handle */ +#define ATT_ERR_READ 0x02 /*! Read not permitted */ +#define ATT_ERR_WRITE 0x03 /*! Write not permitted */ +#define ATT_ERR_INVALID_PDU 0x04 /*! Invalid pdu */ +#define ATT_ERR_AUTH 0x05 /*! Insufficient authentication */ +#define ATT_ERR_NOT_SUP 0x06 /*! Request not supported */ +#define ATT_ERR_OFFSET 0x07 /*! Invalid offset */ +#define ATT_ERR_AUTHOR 0x08 /*! Insufficient authorization */ +#define ATT_ERR_QUEUE_FULL 0x09 /*! Prepare queue full */ +#define ATT_ERR_NOT_FOUND 0x0A /*! Attribute not found */ +#define ATT_ERR_NOT_LONG 0x0B /*! Attribute not long */ +#define ATT_ERR_KEY_SIZE 0x0C /*! Insufficient encryption key size */ +#define ATT_ERR_LENGTH 0x0D /*! Invalid attribute value length */ +#define ATT_ERR_UNLIKELY 0x0E /*! Other unlikely error */ +#define ATT_ERR_ENC 0x0F /*! Insufficient encryption */ +#define ATT_ERR_GROUP_TYPE 0x10 /*! Unsupported group type */ +#define ATT_ERR_RESOURCES 0x11 /*! Insufficient resources */ +#define ATT_ERR_CCCD 0xFD /*! CCCD improperly configured */ +#define ATT_ERR_IN_PROGRESS 0xFE /*! Procedure already in progress */ +#define ATT_ERR_RANGE 0xFF /*! Value out of range */ + +/*! Proprietary internal error codes */ +#define ATT_ERR_MEMORY 0x70 /*! Out of memory */ +#define ATT_ERR_TIMEOUT 0x71 /*! Transaction timeout */ +#define ATT_ERR_OVERFLOW 0x72 /*! Transaction overflow */ +#define ATT_ERR_INVALID_RSP 0x73 /*! Invalid response PDU */ +#define ATT_ERR_CANCELLED 0x74 /*! Request cancelled */ +#define ATT_ERR_UNDEFINED 0x75 /*! Other undefined error */ +#define ATT_ERR_REQ_NOT_FOUND 0x76 /*! Required characteristic not found */ +#define ATT_ERR_MTU_EXCEEDED 0x77 /*! Attribute PDU length exceeded MTU size */ +#define ATT_CONTINUING 0x78 /*! Procedure continuing */ + +/*! Application error codes */ +#define ATT_ERR_VALUE_RANGE 0x80 /*! Value out of range */ + +/*! PDU types */ +#define ATT_PDU_ERR_RSP 0x01 /*! Error response */ +#define ATT_PDU_MTU_REQ 0x02 /*! Exchange mtu request */ +#define ATT_PDU_MTU_RSP 0x03 /*! Exchange mtu response */ +#define ATT_PDU_FIND_INFO_REQ 0x04 /*! Find information request */ +#define ATT_PDU_FIND_INFO_RSP 0x05 /*! Find information response */ +#define ATT_PDU_FIND_TYPE_REQ 0x06 /*! Find by type value request */ +#define ATT_PDU_FIND_TYPE_RSP 0x07 /*! Find by type value response */ +#define ATT_PDU_READ_TYPE_REQ 0x08 /*! Read by type request */ +#define ATT_PDU_READ_TYPE_RSP 0x09 /*! Read by type response */ +#define ATT_PDU_READ_REQ 0x0A /*! Read request */ +#define ATT_PDU_READ_RSP 0x0B /*! Read response */ +#define ATT_PDU_READ_BLOB_REQ 0x0C /*! Read blob request */ +#define ATT_PDU_READ_BLOB_RSP 0x0D /*! Read blob response */ +#define ATT_PDU_READ_MULT_REQ 0x0E /*! Read multiple request */ +#define ATT_PDU_READ_MULT_RSP 0x0F /*! Read multiple response */ +#define ATT_PDU_READ_GROUP_TYPE_REQ 0x10 /*! Read by group type request */ +#define ATT_PDU_READ_GROUP_TYPE_RSP 0x11 /*! Read by group type response */ +#define ATT_PDU_WRITE_REQ 0x12 /*! Write request */ +#define ATT_PDU_WRITE_RSP 0x13 /*! Write response */ +#define ATT_PDU_WRITE_CMD 0x52 /*! Write command */ +#define ATT_PDU_SIGNED_WRITE_CMD 0xD2 /*! Signed write command */ +#define ATT_PDU_PREP_WRITE_REQ 0x16 /*! Prepare write request */ +#define ATT_PDU_PREP_WRITE_RSP 0x17 /*! Prepare write response */ +#define ATT_PDU_EXEC_WRITE_REQ 0x18 /*! Execute write request */ +#define ATT_PDU_EXEC_WRITE_RSP 0x19 /*! Execute write response */ +#define ATT_PDU_VALUE_NTF 0x1B /*! Handle value notification */ +#define ATT_PDU_VALUE_IND 0x1D /*! Handle value indication */ +#define ATT_PDU_VALUE_CNF 0x1E /*! Handle value confirmation */ +#define ATT_PDU_MAX 0x1F /*! PDU Maximum */ + +/*! Length of PDU fixed length fields */ +#define ATT_ERR_RSP_LEN 5 +#define ATT_MTU_REQ_LEN 3 +#define ATT_MTU_RSP_LEN 3 +#define ATT_FIND_INFO_REQ_LEN 5 +#define ATT_FIND_INFO_RSP_LEN 2 +#define ATT_FIND_TYPE_REQ_LEN 7 +#define ATT_FIND_TYPE_RSP_LEN 1 +#define ATT_READ_TYPE_REQ_LEN 5 +#define ATT_READ_TYPE_RSP_LEN 2 +#define ATT_READ_REQ_LEN 3 +#define ATT_READ_RSP_LEN 1 +#define ATT_READ_BLOB_REQ_LEN 5 +#define ATT_READ_BLOB_RSP_LEN 1 +#define ATT_READ_MULT_REQ_LEN 1 +#define ATT_READ_MULT_RSP_LEN 1 +#define ATT_READ_GROUP_TYPE_REQ_LEN 5 +#define ATT_READ_GROUP_TYPE_RSP_LEN 2 +#define ATT_WRITE_REQ_LEN 3 +#define ATT_WRITE_RSP_LEN 1 +#define ATT_WRITE_CMD_LEN 3 +#define ATT_SIGNED_WRITE_CMD_LEN (ATT_WRITE_CMD_LEN + ATT_AUTH_SIG_LEN) +#define ATT_PREP_WRITE_REQ_LEN 5 +#define ATT_PREP_WRITE_RSP_LEN 5 +#define ATT_EXEC_WRITE_REQ_LEN 2 +#define ATT_EXEC_WRITE_RSP_LEN 1 +#define ATT_VALUE_NTF_LEN 3 +#define ATT_VALUE_IND_LEN 3 +#define ATT_VALUE_CNF_LEN 1 + +/*! Find information response format */ +#define ATT_FIND_HANDLE_16_UUID 0x01 /*! Handle and 16 bit UUID */ +#define ATT_FIND_HANDLE_128_UUID 0x02 /*! Handle and 128 bit UUID */ + +/*! Execute write request flags */ +#define ATT_EXEC_WRITE_CANCEL 0x00 /*! Cancel all prepared writes */ +#define ATT_EXEC_WRITE_ALL 0x01 /*! Write all pending prepared writes */ + +/*! PDU masks */ +#define ATT_PDU_MASK_SERVER 0x01 /*! Server bit mask */ +#define ATT_PDU_MASK_COMMAND 0x40 /*! Command bit mask */ +#define ATT_PDU_MASK_SIGNED 0x80 /*! Auth signature bit mask */ + +/*! Handles */ +#define ATT_HANDLE_NONE 0x0000 +#define ATT_HANDLE_START 0x0001 +#define ATT_HANDLE_MAX 0xFFFF + +/*! UUID lengths */ +#define ATT_NO_UUID_LEN 0 /*! Length when no UUID is present ;-) */ +#define ATT_16_UUID_LEN 2 /*! Length in bytes of a 16 bit UUID */ +#define ATT_128_UUID_LEN 16 /*! Length in bytes of a 128 bit UUID */ + +/*! GATT characteristic properties */ +#define ATT_PROP_BROADCAST 0x01 /*! Permit broadcasts */ +#define ATT_PROP_READ 0x02 /*! Permit reads */ +#define ATT_PROP_WRITE_NO_RSP 0x04 /*! Permit writes without response */ +#define ATT_PROP_WRITE 0x08 /*! Permit writes with response */ +#define ATT_PROP_NOTIFY 0x10 /*! Permit notifications */ +#define ATT_PROP_INDICATE 0x20 /*! Permit indications */ +#define ATT_PROP_AUTHENTICATED 0x40 /*! Permit signed writes */ +#define ATT_PROP_EXTENDED 0x80 /*! More properties defined in extended properties */ + +/*! GATT characteristic extended properties */ +#define ATT_EXT_PROP_RELIABLE_WRITE 0x0001 /*! Permit reliable writes */ +#define ATT_EXT_PROP_WRITEABLE_AUX 0x0002 /*! Permit write to characteristic descriptor */ + +/*! GATT client characteristic configuration */ +#define ATT_CLIENT_CFG_NOTIFY 0x0001 /*! Notify the value */ +#define ATT_CLIENT_CFG_INDICATE 0x0002 /*! Indicate the value */ + +/*! GATT server characteristic configuration */ +#define ATT_SERVER_CFG_BROADCAST 0x0001 /*! Broadcast the value */ + +/*! GATT characteristic format */ +#define ATT_FORMAT_BOOLEAN 0x01 /*! Boolean */ +#define ATT_FORMAT_2BIT 0x02 /*! Unsigned 2 bit integer */ +#define ATT_FORMAT_NIBBLE 0x03 /*! Unsigned 4 bit integer */ +#define ATT_FORMAT_UINT8 0x04 /*! Unsigned 8 bit integer */ +#define ATT_FORMAT_UINT12 0x05 /*! Unsigned 12 bit integer */ +#define ATT_FORMAT_UINT16 0x06 /*! Unsigned 16 bit integer */ +#define ATT_FORMAT_UINT24 0x07 /*! Unsigned 24 bit integer */ +#define ATT_FORMAT_UINT32 0x08 /*! Unsigned 32 bit integer */ +#define ATT_FORMAT_UINT48 0x09 /*! Unsigned 48 bit integer */ +#define ATT_FORMAT_UINT64 0x0A /*! Unsigned 64 bit integer */ +#define ATT_FORMAT_UINT128 0x0B /*! Unsigned 128 bit integer */ +#define ATT_FORMAT_SINT8 0x0C /*! Signed 8 bit integer */ +#define ATT_FORMAT_SINT12 0x0D /*! Signed 12 bit integer */ +#define ATT_FORMAT_SINT16 0x0E /*! Signed 16 bit integer */ +#define ATT_FORMAT_SINT24 0x0F /*! Signed 24 bit integer */ +#define ATT_FORMAT_SINT32 0x10 /*! Signed 32 bit integer */ +#define ATT_FORMAT_SINT48 0x11 /*! Signed 48 bit integer */ +#define ATT_FORMAT_SINT64 0x12 /*! Signed 64 bit integer */ +#define ATT_FORMAT_SINT128 0x13 /*! Signed 128 bit integer */ +#define ATT_FORMAT_FLOAT32 0x14 /*! IEEE-754 32 bit floating point */ +#define ATT_FORMAT_FLOAT64 0x15 /*! IEEE-754 64 bit floating point */ +#define ATT_FORMAT_SFLOAT 0x16 /*! IEEE-11073 16 bit SFLOAT */ +#define ATT_FORMAT_FLOAT 0x17 /*! IEEE-11073 32 bit FLOAT */ +#define ATT_FORMAT_DUINT16 0x18 /*! IEEE-20601 format */ +#define ATT_FORMAT_UTF8 0x19 /*! UTF-8 string */ +#define ATT_FORMAT_UTF16 0x1A /*! UTF-16 string */ +#define ATT_FORMAT_STRUCT 0x1B /*! Opaque structure */ + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h new file mode 100644 index 00000000000..a88edbf91b6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file att_handler.h + * + * \brief Interface to ATT event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_HANDLER_H +#define ATT_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn AttHandlerInit + * + * \brief ATT handler init function called during system initialization. + * + * \param handlerID WSF handler ID for ATT. + * + * \return None. + */ +/*************************************************************************************************/ +void AttHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn AttHandler + * + * \brief WSF event handler for ATT. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void AttHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h new file mode 100644 index 00000000000..177a52e0a21 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h @@ -0,0 +1,475 @@ +/*************************************************************************************************/ +/*! + * \file att_uuid.h + * + * \brief Attribute protocol UUIDs from the Bluetooth specification. + * + * $Date: 2017-03-08 12:55:18 -0600 (Wed, 08 Mar 2017) $ + * $Revision: 11435 $ + * + * Copyright (c) 2011-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_UUID_H +#define ATT_UUID_H + +#include "att_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Service UUIDs */ +#define ATT_UUID_GAP_SERVICE 0x1800 /*! Generic Access Profile Service */ +#define ATT_UUID_GATT_SERVICE 0x1801 /*! Generic Attribute Profile Service */ +#define ATT_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /*! Immediate Alert Service */ +#define ATT_UUID_LINK_LOSS_SERVICE 0x1803 /*! Link Loss Service */ +#define ATT_UUID_TX_POWER_SERVICE 0x1804 /*! Tx Power Service */ +#define ATT_UUID_CURRENT_TIME_SERVICE 0x1805 /*! Current Time Service */ +#define ATT_UUID_REF_TIME_UPDATE_SERVICE 0x1806 /*! Reference Time Update Service */ +#define ATT_UUID_DST_CHANGE_SERVICE 0x1807 /*! Next DST Change Service */ +#define ATT_UUID_GLUCOSE_SERVICE 0x1808 /*! Glucose Service */ +#define ATT_UUID_HEALTH_THERM_SERVICE 0x1809 /*! Health Thermometer Service */ +#define ATT_UUID_DEVICE_INFO_SERVICE 0x180A /*! Device Information Service */ +#define ATT_UUID_NETWORK_AVAIL_SERVICE 0x180B /*! Network Availability Service */ +#define ATT_UUID_WATCHDOG_SERVICE 0x180C /*! Watchdog Service */ +#define ATT_UUID_HEART_RATE_SERVICE 0x180D /*! Heart Rate Service */ +#define ATT_UUID_PHONE_ALERT_SERVICE 0x180E /*! Phone Alert Status Service */ +#define ATT_UUID_BATTERY_SERVICE 0x180F /*! Battery Service */ +#define ATT_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /*! Blood Pressure Service */ +#define ATT_UUID_ALERT_NOTIF_SERVICE 0x1811 /*! Alert Notification Service */ +#define ATT_UUID_HID_SERVICE 0x1812 /*! Human Interface Device Service */ +#define ATT_UUID_SCAN_PARAM_SERVICE 0x1813 /*! Scan Parameter Service */ +#define ATT_UUID_RUNNING_SPEED_SERVICE 0x1814 /*! Running Speed Service */ +#define ATT_UUID_CYCLING_SPEED_SERVICE 0x1816 /*! Cycling Speed Service */ +#define ATT_UUID_CYCLING_POWER_SERVICE 0x1818 /*! Cycling Power Service */ +#define ATT_UUID_USER_DATA_SERVICE 0x181C /*! User Data Service */ +#define ATT_UUID_IP_SUPPORT_SERVICE 0x1820 /*! IP Support Service */ +#define ATT_UUID_PULSE_OXIMITER_SERVICE 0x1822 /*! Pulse Oximeter Service */ + +/*! GATT UUIDs */ +#define ATT_UUID_PRIMARY_SERVICE 0x2800 /*! Primary Service */ +#define ATT_UUID_SECONDARY_SERVICE 0x2801 /*! Secondary Service */ +#define ATT_UUID_INCLUDE 0x2802 /*! Include */ +#define ATT_UUID_CHARACTERISTIC 0x2803 /*! Characteristic */ + +/*! Descriptor UUIDs */ +#define ATT_UUID_CHARACTERISTIC_EXT 0x2900 /*! Characteristic Extended Properties */ +#define ATT_UUID_CHAR_USER_DESC 0x2901 /*! Characteristic User Description */ +#define ATT_UUID_CLIENT_CHAR_CONFIG 0x2902 /*! Client Characteristic Configuration */ +#define ATT_UUID_SERVER_CHAR_CONFIG 0x2903 /*! Server Characteristic Configuration */ +#define ATT_UUID_CHAR_PRES_FORMAT 0x2904 /*! Characteristic Presentation Format */ +#define ATT_UUID_AGGREGATE_FORMAT 0x2905 /*! Characteristic Aggregate Format */ +#define ATT_UUID_VALID_RANGE 0x2906 /*! Valid Range */ +#define ATT_UUID_HID_EXT_REPORT_MAPPING 0x2907 /*! HID External Report ID Mapping */ +#define ATT_UUID_HID_REPORT_ID_MAPPING 0x2908 /*! HID Report ID Mapping */ + +/*! Characteristic UUIDs */ +#define ATT_UUID_DEVICE_NAME 0x2A00 /*! Device Name */ +#define ATT_UUID_APPEARANCE 0x2A01 /*! Appearance */ +#define ATT_UUID_PERIPH_PRIVACY_FLAG 0x2A02 /*! Peripheral Privacy Flag */ +#define ATT_UUID_RECONN_ADDR 0x2A03 /*! Reconnection Address */ +#define ATT_UUID_PREF_CONN_PARAM 0x2A04 /*! Peripheral Preferred Connection Parameters */ +#define ATT_UUID_SERVICE_CHANGED 0x2A05 /*! Service Changed */ +#define ATT_UUID_ALERT_LEVEL 0x2A06 /*! Alert Level */ +#define ATT_UUID_TX_POWER_LEVEL 0x2A07 /*! Tx Power Level */ +#define ATT_UUID_DATE_TIME 0x2A08 /*! Date Time */ +#define ATT_UUID_DAY_OF_WEEK 0x2A09 /*! Day of Week */ +#define ATT_UUID_DAY_DATE_TIME 0x2A0A /*! Day Date Time */ +#define ATT_UUID_EXACT_TIME_100 0x2A0B /*! Exact Time 100 */ +#define ATT_UUID_EXACT_TIME_256 0x2A0C /*! Exact Time 256 */ +#define ATT_UUID_DST_OFFSET 0x2A0D /*! DST Offset */ +#define ATT_UUID_TIME_ZONE 0x2A0E /*! Time Zone */ +#define ATT_UUID_LOCAL_TIME_INFO 0x2A0F /*! Local Time Information */ +#define ATT_UUID_SECONDARY_TIME_ZONE 0x2A10 /*! Secondary Time Zone */ +#define ATT_UUID_TIME_WITH_DST 0x2A11 /*! Time with DST */ +#define ATT_UUID_TIME_ACCURACY 0x2A12 /*! Time Accuracy */ +#define ATT_UUID_TIME_SOURCE 0x2A13 /*! Time Source */ +#define ATT_UUID_REFERENCE_TIME_INFO 0x2A14 /*! Reference Time Information */ +#define ATT_UUID_TIME_BROADCAST 0x2A15 /*! Time Broadcast */ +#define ATT_UUID_TIME_UPDATE_CP 0x2A16 /*! Time Update Control Point */ +#define ATT_UUID_TIME_UPDATE_STATE 0x2A17 /*! Time Update State */ +#define ATT_UUID_GLUCOSE_MEAS 0x2A18 /*! Glucose Measurement */ +#define ATT_UUID_BATTERY_LEVEL 0x2A19 /*! Battery Level */ +#define ATT_UUID_BATTERY_POWER_STATE 0x2A1A /*! Battery Power State */ +#define ATT_UUID_BATTERY_LEVEL_STATE 0x2A1B /*! Battery Level State */ +#define ATT_UUID_TEMP_MEAS 0x2A1C /*! Temperature Measurement */ +#define ATT_UUID_TEMP_TYPE 0x2A1D /*! Temperature Type */ +#define ATT_UUID_INTERMEDIATE_TEMP 0x2A1E /*! Intermediate Temperature */ +#define ATT_UUID_TEMP_C 0x2A1F /*! Temperature Celsius */ +#define ATT_UUID_TEMP_F 0x2A20 /*! Temperature Fahrenheit */ +#define ATT_UUID_MEAS_INTERVAL 0x2A21 /*! Measurement Interval */ +#define ATT_UUID_HID_BOOT_KEYBOARD_IN 0x2A22 /*! HID Boot Keyboard In */ +#define ATT_UUID_SYSTEM_ID 0x2A23 /*! System ID */ +#define ATT_UUID_MODEL_NUMBER 0x2A24 /*! Model Number String */ +#define ATT_UUID_SERIAL_NUMBER 0x2A25 /*! Serial Number String */ +#define ATT_UUID_FIRMWARE_REV 0x2A26 /*! Firmware Revision String */ +#define ATT_UUID_HARDWARE_REV 0x2A27 /*! Hardware Revision String */ +#define ATT_UUID_SOFTWARE_REV 0x2A28 /*! Software Revision String */ +#define ATT_UUID_MANUFACTURER_NAME 0x2A29 /*! Manufacturer Name String */ +#define ATT_UUID_11073_CERT_DATA 0x2A2A /*! IEEE 11073-20601 Regulatory Certification Data List */ +#define ATT_UUID_CURRENT_TIME 0x2A2B /*! Current Time */ +#define ATT_UUID_ELEVATION 0x2A2C /*! Elevation */ +#define ATT_UUID_LATITUDE 0x2A2D /*! Latitude */ +#define ATT_UUID_LONGITUDE 0x2A2E /*! Longitude */ +#define ATT_UUID_POSITION_2D 0x2A2F /*! Position 2D */ +#define ATT_UUID_POSITION_3D 0x2A30 /*! Position 3D */ +#define ATT_UUID_VENDOR_ID 0x2A31 /*! Vendor ID */ +#define ATT_UUID_HID_BOOT_KEYBOARD_OUT 0x2A32 /*! HID Boot Keyboard Out */ +#define ATT_UUID_HID_BOOT_MOUSE_IN 0x2A33 /*! HID Boot Mouse In */ +#define ATT_UUID_GLUCOSE_MEAS_CONTEXT 0x2A34 /*! Glucose Measurement Context */ +#define ATT_UUID_BP_MEAS 0x2A35 /*! Blood Pressure Measurement */ +#define ATT_UUID_INTERMEDIATE_BP 0x2A36 /*! Intermediate Cuff Pressure */ +#define ATT_UUID_HR_MEAS 0x2A37 /*! Heart Rate Measurement */ +#define ATT_UUID_HR_SENSOR_LOC 0x2A38 /*! Body Sensor Location */ +#define ATT_UUID_HR_CP 0x2A39 /*! Heart Rate Control Point */ +#define ATT_UUID_REMOVABLE 0x2A3A /*! Removable */ +#define ATT_UUID_SERVICE_REQ 0x2A3B /*! Service Required */ +#define ATT_UUID_SCI_TEMP_C 0x2A3C /*! Scientific Temperature in Celsius */ +#define ATT_UUID_STRING 0x2A3D /*! String */ +#define ATT_UUID_NETWORK_AVAIL 0x2A3E /*! Network Availability */ +#define ATT_UUID_ALERT_STATUS 0x2A3F /*! Alert Status */ +#define ATT_UUID_RINGER_CP 0x2A40 /*! Ringer Control Point */ +#define ATT_UUID_RINGER_SETTING 0x2A41 /*! Ringer Setting */ +#define ATT_UUID_ALERT_CAT_ID_MASK 0x2A42 /*! Alert Category ID Bit Mask */ +#define ATT_UUID_ALERT_CAT_ID 0x2A43 /*! Alert Category ID */ +#define ATT_UUID_ALERT_NOTIF_CP 0x2A44 /*! Alert Notification Control Point */ +#define ATT_UUID_UNREAD_ALERT_STATUS 0x2A45 /*! Unread Alert Status */ +#define ATT_UUID_NEW_ALERT 0x2A46 /*! New Alert */ +#define ATT_UUID_SUP_NEW_ALERT_CAT 0x2A47 /*! Supported New Alert Category */ +#define ATT_UUID_SUP_UNREAD_ALERT_CAT 0x2A48 /*! Supported Unread Alert Category */ +#define ATT_UUID_BP_FEATURE 0x2A49 /*! Blood Pressure Feature */ +#define ATT_UUID_HID_INFORMATION 0x2A4A /*! HID Information */ +#define ATT_UUID_HID_REPORT_MAP 0x2A4B /*! HID Report Map */ +#define ATT_UUID_HID_CONTROL_POINT 0x2A4C /*! HID Control Point */ +#define ATT_UUID_HID_REPORT 0x2A4D /*! HID Report */ +#define ATT_UUID_HID_PROTOCOL_MODE 0x2A4E /*! HID Protocol Mode */ +#define ATT_UUID_SCAN_INT_WIND 0x2A4F /*! Scan Interval Window */ +#define ATT_UUID_PNP_ID 0x2A50 /*! PnP ID */ +#define ATT_UUID_GLUCOSE_FEATURE 0x2A51 /*! Glucose Feature */ +#define ATT_UUID_RACP 0x2A52 /*! Record Access Control Point */ +#define ATT_UUID_CAR 0x2AA6 /*! Central Address Resolution */ +#define ATT_UUID_RUNNING_SPEED_FEATURE 0x2A54 /*! Running Speed Feature */ +#define ATT_UUID_RUNNING_SPEED_MEASUREMENT 0x2A53 /*! Running Speed Measurement */ +#define ATT_UUID_PULSE_OX_FEATURES 0x2A60 /*! Pulse Oximeter Features */ +#define ATT_UUID_PULSE_OX_SPOT_CHECK 0x2A5E /*! Pulse Oximeter Features */ +#define ATT_UUID_PULSE_OX_CONTINUOUS 0x2A5F /*! Pulse Oximeter Features */ +#define ATT_UUID_CYCLING_POWER_FEATURE 0x2A65 /*! Cycling Power Feature */ +#define ATT_UUID_CYCLING_POWER_MEASUREMENT 0x2A63 /*! Cycling Power Measurement */ +#define ATT_UUID_CYCLING_SPEED_FEATURE 0x2A5C /*! Cycling Speed Feature */ +#define ATT_UUID_CYCLING_SPEED_MEASUREMENT 0x2A5B /*! Cycling Speed Measurement */ +#define ATT_UUID_SENSOR_LOCATION 0x2A5D /*! Sensor Location */ +#define ATT_UUID_DB_CHANGE_INCREMENT 0x2A99 /*! Database Change Increment */ +#define ATT_UUID_USER_INDEX 0x2A9A /*! User Index */ +#define ATT_UUID_USER_CONTROL_POINT 0x2A9F /*! User Control Point */ +#define ATT_UUID_RPAO 0x2AC9 /*! Resolvable Prviate Address Only */ + +/* remove when adopted */ +#define ATT_UUID_GENERIC_CTRL_SERVICE 0xF011 +#define ATT_UUID_COMMAND_ENUM 0xE010 /*! Command Enumeration */ +#define ATT_UUID_GENERIC_COMMAND_CP 0xE011 /*! Generic Command Control Point */ +#define ATT_UUID_WEIGHT_SCALE_SERVICE 0x181D /*! Weight Scale Service */ +#define ATT_UUID_WEIGHT_MEAS 0x2A9D /*! Weight Measurement */ +#define ATT_UUID_WEIGHT_SCALE_FEATURE 0x2A9E /*! Weight Scale Feature */ + +/*! Unit UUIDs */ +#define ATT_UUID_UNITLESS 0x2700 /*! unitless */ +#define ATT_UUID_LENGTH_M 0x2701 /*! length metre */ +#define ATT_UUID_MASS_KG 0x2702 /*! mass kilogram */ +#define ATT_UUID_TIME_SEC 0x2703 /*! time second */ +#define ATT_UUID_ELECTRIC_CURRENT_AMP 0x2704 /*! electric current ampere */ +#define ATT_UUID_THERMO_TEMP_K 0x2705 /*! thermodynamic temperature kelvin */ +#define ATT_UUID_AMOUNT_OF_SUBSTANCE_MOLE 0x2706 /*! amount of substance mole */ +#define ATT_UUID_LUMINOUS_INTENSITY_CAND 0x2707 /*! luminous intensity candela */ +#define ATT_UUID_AREA_SQ_M 0x2710 /*! area square metres */ +#define ATT_UUID_VOLUME_CU_M 0x2711 /*! volume cubic metres */ +#define ATT_UUID_VELOCITY_MPS 0x2712 /*! velocity metres per second */ +#define ATT_UUID_ACCELERATION_MPS_SQ 0x2713 /*! acceleration metres per second squared */ +#define ATT_UUID_WAVENUMBER_RECIPROCAL_M 0x2714 /*! wavenumber reciprocal metre */ +#define ATT_UUID_DENSITY_KG_PER_CU_M 0x2715 /*! density kilogram per cubic metre */ +#define ATT_UUID_SURFACE_DENS_KG_PER_SQ_M 0x2716 /*! surface density kilogram per square metre */ +#define ATT_UUID_SPECIFIC_VOL_CU_M_PER_KG 0x2717 /*! specific volume cubic metre per kilogram */ +#define ATT_UUID_CURRENT_DENS_AMP_PER_SQ_M 0x2718 /*! current density ampere per square metre */ +#define ATT_UUID_MAG_FIELD_STR_AMP_PER_M 0x2719 /*! magnetic field strength ampere per metre */ +#define ATT_UUID_AMOUNT_CONC_MOLE_PER_CU_M 0x271A /*! amount concentration mole per cubic metre */ +#define ATT_UUID_MASS_CONC_KG_PER_CU_M 0x271B /*! mass concentration kilogram per cubic metre */ +#define ATT_UUID_LUM_CAND_PER_SQ_M 0x271C /*! luminance candela per square metre */ +#define ATT_UUID_REFRACTIVE_INDEX 0x271D /*! refractive index */ +#define ATT_UUID_RELATIVE_PERMEABILITY 0x271E /*! relative permeability */ +#define ATT_UUID_PLANE_ANGLE_R 0x2720 /*! plane angle radian */ +#define ATT_UUID_SOLID_ANGLE_STER 0x2721 /*! solid angle steradian */ +#define ATT_UUID_FREQUENCY_HERTZ 0x2722 /*! frequency hertz */ +#define ATT_UUID_FORCE_NEWT 0x2723 /*! force newton */ +#define ATT_UUID_PRESSURE_PASCAL 0x2724 /*! pressure pascal */ +#define ATT_UUID_ENERGY_J 0x2725 /*! energy joule */ +#define ATT_UUID_POWER_W 0x2726 /*! power watt */ +#define ATT_UUID_ELECTRIC_CHG_C 0x2727 /*! electric charge coulomb */ +#define ATT_UUID_ELECTRIC_POTENTIAL_VOLT 0x2728 /*! electric potential difference volt */ +#define ATT_UUID_CAPACITANCE_F 0x2729 /*! capacitance farad */ +#define ATT_UUID_ELECTRIC_RESISTANCE_OHM 0x272A /*! electric resistance ohm */ +#define ATT_UUID_ELECTRIC_COND_SIEMENS 0x272B /*! electric conductance siemens */ +#define ATT_UUID_MAGNETIC_FLEX_WEBER 0x272C /*! magnetic flex weber */ +#define ATT_UUID_MAGNETIC_FLEX_DENS_TESLA 0x272D /*! magnetic flex density tesla */ +#define ATT_UUID_INDUCTANCE_H 0x272E /*! inductance henry */ +#define ATT_UUID_C_TEMP_DEG_C 0x272F /*! Celsius temperature degree Celsius */ +#define ATT_UUID_LUMINOUS_FLUX_LUMEN 0x2730 /*! luminous flux lumen */ +#define ATT_UUID_ILLUMINANCE_LUX 0x2731 /*! illuminance lux */ +#define ATT_UUID_RADIONUCLIDE_BECQUEREL 0x2732 /*! activity referred to a radionuclide becquerel */ +#define ATT_UUID_ABSORBED_DOSE_GRAY 0x2733 /*! absorbed dose gray */ +#define ATT_UUID_DOSE_EQUIVALENT_SIEVERT 0x2734 /*! dose equivalent sievert */ +#define ATT_UUID_CATALYTIC_ACTIVITY_KATAL 0x2735 /*! catalytic activity katal */ +#define ATT_UUID_DYNAMIC_VISC_PASCAL_SEC 0x2740 /*! dynamic viscosity pascal second */ +#define ATT_UUID_MOMENT_OF_FORCE_NEWT_M 0x2741 /*! moment of force newton metre */ +#define ATT_UUID_SURFACE_TENSION_NEWT_PER_M 0x2742 /*! surface tension newton per metre */ +#define ATT_UUID_ANG_VELOCITY_R_PER_SEC 0x2743 /*! angular velocity radian per second */ +#define ATT_UUID_ANG_ACCEL_R_PER_SEC_SQD 0x2744 /*! angular acceleration radian per second squared */ +#define ATT_UUID_HEAT_FLUX_DEN_W_PER_SQ_M 0x2745 /*! heat flux density watt per square metre */ +#define ATT_UUID_HEAT_CAP_J_PER_K 0x2746 /*! heat capacity joule per kelvin */ +#define ATT_UUID_SPEC_HEAT_CAP_J_PER_KG_K 0x2747 /*! specific heat capacity joule per kilogram kelvin */ +#define ATT_UUID_SPEC_ENERGY_J_PER_KG 0x2748 /*! specific energy joule per kilogram */ +#define ATT_UUID_THERMAL_COND_W_PER_M_K 0x2749 /*! thermal conductivity watt per metre kelvin */ +#define ATT_UUID_ENERGY_DENSITY_J_PER_CU_M 0x274A /*! energy density joule per cubic metre */ +#define ATT_UUID_ELEC_FIELD_STR_VOLT_PER_M 0x274B /*! electric field strength volt per metre */ +#define ATT_UUID_ELEC_CHG_DENS_C_PER_CU_M 0x274C /*! electric charge density coulomb per cubic metre */ +#define ATT_UUID_SURF_CHG_DENS_C_PER_SQ_M 0x274D /*! surface charge density coulomb per square metre */ +#define ATT_UUID_ELEC_FLUX_DENS_C_PER_SQ_M 0x274E /*! electric flux density coulomb per square metre */ +#define ATT_UUID_PERMITTIVITY_F_PER_M 0x274F /*! permittivity farad per metre */ +#define ATT_UUID_PERMEABILITY_H_PER_M 0x2750 /*! permeability henry per metre */ +#define ATT_UUID_MOLAR_ENERGY_J_PER_MOLE 0x2751 /*! molar energy joule per mole */ +#define ATT_UUID_MOLAR_ENTROPY_J_PER_MOLE_K 0x2752 /*! molar entropy joule per mole kelvin */ +#define ATT_UUID_EXPOSURE_C_PER_KG 0x2753 /*! exposure coulomb per kilogram */ +#define ATT_UUID_DOSE_RATE_GRAY_PER_SEC 0x2754 /*! absorbed dose rate gray per second */ +#define ATT_UUID_RT_INTENSITY_W_PER_STER 0x2755 /*! radiant intensity watt per steradian */ +#define ATT_UUID_RCE_W_PER_SQ_METER_STER 0x2756 /*! radiance watt per square meter steradian */ +#define ATT_UUID_CATALYTIC_KATAL_PER_CU_M 0x2757 /*! catalytic activity concentration katal per cubic metre */ +#define ATT_UUID_TIME_MIN 0x2760 /*! time minute */ +#define ATT_UUID_TIME_HR 0x2761 /*! time hour */ +#define ATT_UUID_TIME_DAY 0x2762 /*! time day */ +#define ATT_UUID_PLANE_ANGLE_DEG 0x2763 /*! plane angle degree */ +#define ATT_UUID_PLANE_ANGLE_MIN 0x2764 /*! plane angle minute */ +#define ATT_UUID_PLANE_ANGLE_SEC 0x2765 /*! plane angle second */ +#define ATT_UUID_AREA_HECTARE 0x2766 /*! area hectare */ +#define ATT_UUID_VOLUME_L 0x2767 /*! volume litre */ +#define ATT_UUID_MASS_TONNE 0x2768 /*! mass tonne */ +#define ATT_UUID_PRESSURE_BAR 0x2780 /*! pressure bar */ +#define ATT_UUID_PRESSURE_MM 0x2781 /*! pressure millimetre of mercury */ +#define ATT_UUID_LENGTH_ANGSTROM 0x2782 /*! length angstrom */ +#define ATT_UUID_LENGTH_NAUTICAL_MILE 0x2783 /*! length nautical mile */ +#define ATT_UUID_AREA_BARN 0x2784 /*! area barn */ +#define ATT_UUID_VELOCITY_KNOT 0x2785 /*! velocity knot */ +#define ATT_UUID_LOG_RADIO_QUANT_NEPER 0x2786 /*! logarithmic radio quantity neper */ +#define ATT_UUID_LOG_RADIO_QUANT_BEL 0x2787 /*! logarithmic radio quantity bel */ +#define ATT_UUID_LOG_RADIO_QUANT_DB 0x2788 /*! logarithmic radio quantity decibel */ +#define ATT_UUID_LENGTH_YARD 0x27A0 /*! length yard */ +#define ATT_UUID_LENGTH_PARSEC 0x27A1 /*! length parsec */ +#define ATT_UUID_LENGTH_IN 0x27A2 /*! length inch */ +#define ATT_UUID_LENGTH_FOOT 0x27A3 /*! length foot */ +#define ATT_UUID_LENGTH_MILE 0x27A4 /*! length mile */ +#define ATT_UUID_PRESSURE_POUND_PER_SQ_IN 0x27A5 /*! pressure pound-force per square inch */ +#define ATT_UUID_VELOCITY_KPH 0x27A6 /*! velocity kilometre per hour */ +#define ATT_UUID_VELOCITY_MPH 0x27A7 /*! velocity mile per hour */ +#define ATT_UUID_ANG_VELOCITY_RPM 0x27A8 /*! angular velocity revolution per minute */ +#define ATT_UUID_ENERGY_GRAM_CALORIE 0x27A9 /*! energy gram calorie */ +#define ATT_UUID_ENERGY_KG_CALORIE 0x27AA /*! energy kilogram calorie */ +#define ATT_UUID_ENERGY_KILOWATT_HR 0x27AB /*! energy kilowatt hour */ +#define ATT_UUID_THERM_TEMP_F 0x27AC /*! thermodynamic temperature degree Fahrenheit */ +#define ATT_UUID_PERCENTAGE 0x27AD /*! percentage */ +#define ATT_UUID_PER_MILLE 0x27AE /*! per mille */ +#define ATT_UUID_PERIOD_BEATS_PER_MIN 0x27AF /*! period beats per minute */ +#define ATT_UUID_ELECTRIC_CHG_AMP_HRS 0x27B0 /*! electric charge ampere hours */ +#define ATT_UUID_MASS_DENSITY_MG_PER_DL 0x27B1 /*! mass density milligram per decilitre */ +#define ATT_UUID_MASS_DENSITY_MMOLE_PER_L 0x27B2 /*! mass density millimole per litre */ +#define ATT_UUID_TIME_YEAR 0x27B3 /*! time year */ +#define ATT_UUID_TIME_MONTH 0x27B4 /*! time month */ + +/*! ARM Ltd. proprietary UUIDs */ + +/*! Base UUID: E0262760-08C2-11E1-9073-0E8AC72EXXXX */ +#define ATT_UUID_ARM_BASE 0x2E, 0xC7, 0x8A, 0x0E, 0x73, 0x90, \ + 0xE1, 0x11, 0xC2, 0x08, 0x60, 0x27, 0x26, 0xE0 + +/*! Macro for building ARM Ltd. UUIDs */ +#define ATT_UUID_ARM_BUILD(part) UINT16_TO_BYTES(part), ATT_UUID_ARM_BASE + +/*! Partial proprietary service UUIDs */ +#define ATT_UUID_P1_SERVICE_PART 0x1001 /*! Proprietary service P1 */ + +/*! Partial proprietary characteristic UUIDs */ +#define ATT_UUID_D1_DATA_PART 0x0001 /*! Proprietary data D1 */ + +/* Proprietary services */ +#define ATT_UUID_P1_SERVICE ATT_UUID_ARM_BUILD(ATT_UUID_P1_SERVICE_PART) + +/* Proprietary characteristics */ +#define ATT_UUID_D1_DATA ATT_UUID_ARM_BUILD(ATT_UUID_D1_DATA_PART) + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! Service UUIDs */ +extern const uint8_t attGapSvcUuid[ATT_16_UUID_LEN]; /*! Generic Access Profile Service */ +extern const uint8_t attGattSvcUuid[ATT_16_UUID_LEN]; /*! Generic Attribute Profile Service */ +extern const uint8_t attIasSvcUuid[ATT_16_UUID_LEN]; /*! Immediate Alert Service */ +extern const uint8_t attLlsSvcUuid[ATT_16_UUID_LEN]; /*! Link Loss Service */ +extern const uint8_t attTpsSvcUuid[ATT_16_UUID_LEN]; /*! Tx Power Service */ +extern const uint8_t attCtsSvcUuid[ATT_16_UUID_LEN]; /*! Current Time Service */ +extern const uint8_t attRtusSvcUuid[ATT_16_UUID_LEN]; /*! Reference Time Update Service */ +extern const uint8_t attNdcsSvcUuid[ATT_16_UUID_LEN]; /*! Next DST Change Service */ +extern const uint8_t attGlsSvcUuid[ATT_16_UUID_LEN]; /*! Glucose Service */ +extern const uint8_t attHtsSvcUuid[ATT_16_UUID_LEN]; /*! Health Thermometer Service */ +extern const uint8_t attDisSvcUuid[ATT_16_UUID_LEN]; /*! Device Information Service */ +extern const uint8_t attNwaSvcUuid[ATT_16_UUID_LEN]; /*! Network Availability Service */ +extern const uint8_t attWdsSvcUuid[ATT_16_UUID_LEN]; /*! Watchdog Service */ +extern const uint8_t attHrsSvcUuid[ATT_16_UUID_LEN]; /*! Heart Rate Service */ +extern const uint8_t attPassSvcUuid[ATT_16_UUID_LEN]; /*! Phone Alert Status Service */ +extern const uint8_t attBasSvcUuid[ATT_16_UUID_LEN]; /*! Battery Service */ +extern const uint8_t attBpsSvcUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Service */ +extern const uint8_t attAnsSvcUuid[ATT_16_UUID_LEN]; /*! Alert Notification Service */ +extern const uint8_t attHidSvcUuid[ATT_16_UUID_LEN]; /*! Human Interface Device Service */ +extern const uint8_t attSpsSvcUuid[ATT_16_UUID_LEN]; /*! Scan Parameter Service */ +extern const uint8_t attPlxsSvcUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Service */ +extern const uint8_t attUdsSvcUuid[ATT_16_UUID_LEN]; /*! User Data Service */ + +/*! GATT UUIDs */ +extern const uint8_t attPrimSvcUuid[ATT_16_UUID_LEN]; /*! Primary Service */ +extern const uint8_t attSecSvcUuid[ATT_16_UUID_LEN]; /*! Secondary Service */ +extern const uint8_t attIncUuid[ATT_16_UUID_LEN]; /*! Include */ +extern const uint8_t attChUuid[ATT_16_UUID_LEN]; /*! Characteristic */ + +/*! Descriptor UUIDs */ +extern const uint8_t attChExtUuid[ATT_16_UUID_LEN]; /*! Characteristic Extended Properties */ +extern const uint8_t attChUserDescUuid[ATT_16_UUID_LEN]; /*! Characteristic User Description */ +extern const uint8_t attCliChCfgUuid[ATT_16_UUID_LEN]; /*! Client Characteristic Configuration */ +extern const uint8_t attSrvChCfgUuid[ATT_16_UUID_LEN]; /*! Server Characteristic Configuration */ +extern const uint8_t attChPresFmtUuid[ATT_16_UUID_LEN]; /*! Characteristic Presentation Format */ +extern const uint8_t attAggFmtUuid[ATT_16_UUID_LEN]; /*! Characteristic Aggregate Format */ +extern const uint8_t attHidErmUuid[ATT_16_UUID_LEN]; /*! HID External Report Reference */ +extern const uint8_t attHidRimUuid[ATT_16_UUID_LEN]; /*! HID Report ID Mapping */ +extern const uint8_t attValRangeUuid[ATT_16_UUID_LEN]; /*! Valid Range */ + +/*! Characteristic UUIDs */ +extern const uint8_t attDnChUuid[ATT_16_UUID_LEN]; /*! Device Name */ +extern const uint8_t attApChUuid[ATT_16_UUID_LEN]; /*! Appearance */ +extern const uint8_t attPpfChUuid[ATT_16_UUID_LEN]; /*! Peripheral Privacy Flag */ +extern const uint8_t attRaChUuid[ATT_16_UUID_LEN]; /*! Reconnection Address */ +extern const uint8_t attPpcpChUuid[ATT_16_UUID_LEN]; /*! Peripheral Preferred Connection Parameters */ +extern const uint8_t attScChUuid[ATT_16_UUID_LEN]; /*! Service Changed */ +extern const uint8_t attAlChUuid[ATT_16_UUID_LEN]; /*! Alert Level */ +extern const uint8_t attTxpChUuid[ATT_16_UUID_LEN]; /*! Tx Power Level */ +extern const uint8_t attDtChUuid[ATT_16_UUID_LEN]; /*! Date Time */ +extern const uint8_t attDwChUuid[ATT_16_UUID_LEN]; /*! Day of Week */ +extern const uint8_t attDdtChUuid[ATT_16_UUID_LEN]; /*! Day Date Time */ +extern const uint8_t attEt100ChUuid[ATT_16_UUID_LEN]; /*! Exact Time 100 */ +extern const uint8_t attEt256ChUuid[ATT_16_UUID_LEN]; /*! Exact Time 256 */ +extern const uint8_t attDstoChUuid[ATT_16_UUID_LEN]; /*! DST Offset */ +extern const uint8_t attTzChUuid[ATT_16_UUID_LEN]; /*! Time Zone */ +extern const uint8_t attLtiChUuid[ATT_16_UUID_LEN]; /*! Local Time Information */ +extern const uint8_t attStzChUuid[ATT_16_UUID_LEN]; /*! Secondary Time Zone */ +extern const uint8_t attTdstChUuid[ATT_16_UUID_LEN]; /*! Time with DST */ +extern const uint8_t attTaChUuid[ATT_16_UUID_LEN]; /*! Time Accuracy */ +extern const uint8_t attTsChUuid[ATT_16_UUID_LEN]; /*! Time Source */ +extern const uint8_t attRtiChUuid[ATT_16_UUID_LEN]; /*! Reference Time Information */ +extern const uint8_t attTbChUuid[ATT_16_UUID_LEN]; /*! Time Broadcast */ +extern const uint8_t attTucpChUuid[ATT_16_UUID_LEN]; /*! Time Update Control Point */ +extern const uint8_t attTusChUuid[ATT_16_UUID_LEN]; /*! Time Update State */ +extern const uint8_t attGlmChUuid[ATT_16_UUID_LEN]; /*! Glucose Measurement */ +extern const uint8_t attBlChUuid[ATT_16_UUID_LEN]; /*! Battery Level */ +extern const uint8_t attBpsChUuid[ATT_16_UUID_LEN]; /*! Battery Power State */ +extern const uint8_t attBlsChUuid[ATT_16_UUID_LEN]; /*! Battery Level State */ +extern const uint8_t attTmChUuid[ATT_16_UUID_LEN]; /*! Temperature Measurement */ +extern const uint8_t attTtChUuid[ATT_16_UUID_LEN]; /*! Temperature Type */ +extern const uint8_t attItChUuid[ATT_16_UUID_LEN]; /*! Intermediate Temperature */ +extern const uint8_t attTcelChUuid[ATT_16_UUID_LEN]; /*! Temperature Celsius */ +extern const uint8_t attTfahChUuid[ATT_16_UUID_LEN]; /*! Temperature Fahrenheit */ +extern const uint8_t attSidChUuid[ATT_16_UUID_LEN]; /*! System ID */ +extern const uint8_t attMnsChUuid[ATT_16_UUID_LEN]; /*! Model Number String */ +extern const uint8_t attSnsChUuid[ATT_16_UUID_LEN]; /*! Serial Number String */ +extern const uint8_t attFrsChUuid[ATT_16_UUID_LEN]; /*! Firmware Revision String */ +extern const uint8_t attHrsChUuid[ATT_16_UUID_LEN]; /*! Hardware Revision String */ +extern const uint8_t attSrsChUuid[ATT_16_UUID_LEN]; /*! Software Revision String */ +extern const uint8_t attMfnsChUuid[ATT_16_UUID_LEN]; /*! Manufacturer Name String */ +extern const uint8_t attIeeeChUuid[ATT_16_UUID_LEN]; /*! IEEE 11073-20601 Regulatory Certification Data List */ +extern const uint8_t attCtChUuid[ATT_16_UUID_LEN]; /*! Current Time */ +extern const uint8_t attElChUuid[ATT_16_UUID_LEN]; /*! Elevation */ +extern const uint8_t attLatChUuid[ATT_16_UUID_LEN]; /*! Latitude */ +extern const uint8_t attLongChUuid[ATT_16_UUID_LEN]; /*! Longitude */ +extern const uint8_t attP2dChUuid[ATT_16_UUID_LEN]; /*! Position 2D */ +extern const uint8_t attP3dChUuid[ATT_16_UUID_LEN]; /*! Position 3D */ +extern const uint8_t attVidChUuid[ATT_16_UUID_LEN]; /*! Vendor ID */ +extern const uint8_t attGlmcChUuid[ATT_16_UUID_LEN]; /*! Glucose Measurement Context */ +extern const uint8_t attBpmChUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Measurement */ +extern const uint8_t attIcpChUuid[ATT_16_UUID_LEN]; /*! Intermediate Cuff Pressure */ +extern const uint8_t attHrmChUuid[ATT_16_UUID_LEN]; /*! Heart Rate Measurement */ +extern const uint8_t attBslChUuid[ATT_16_UUID_LEN]; /*! Body Sensor Location */ +extern const uint8_t attHrcpChUuid[ATT_16_UUID_LEN]; /*! Heart Rate Control Point */ +extern const uint8_t attRemChUuid[ATT_16_UUID_LEN]; /*! Removable */ +extern const uint8_t attSrChUuid[ATT_16_UUID_LEN]; /*! Service Required */ +extern const uint8_t attStcChUuid[ATT_16_UUID_LEN]; /*! Scientific Temperature in Celsius */ +extern const uint8_t attStrChUuid[ATT_16_UUID_LEN]; /*! String */ +extern const uint8_t attNwaChUuid[ATT_16_UUID_LEN]; /*! Network Availability */ +extern const uint8_t attAsChUuid[ATT_16_UUID_LEN]; /*! Alert Status */ +extern const uint8_t attRcpChUuid[ATT_16_UUID_LEN]; /*! Ringer Control Point */ +extern const uint8_t attRsChUuid[ATT_16_UUID_LEN]; /*! Ringer Setting */ +extern const uint8_t attAcbmChUuid[ATT_16_UUID_LEN]; /*! Alert Category ID Bit Mask */ +extern const uint8_t attAcChUuid[ATT_16_UUID_LEN]; /*! Alert Category ID */ +extern const uint8_t attAncpChUuid[ATT_16_UUID_LEN]; /*! Alert Notification Control Point */ +extern const uint8_t attUasChUuid[ATT_16_UUID_LEN]; /*! Unread Alert Status */ +extern const uint8_t attNaChUuid[ATT_16_UUID_LEN]; /*! New Alert */ +extern const uint8_t attSnacChUuid[ATT_16_UUID_LEN]; /*! Supported New Alert Category */ +extern const uint8_t attSuacChUuid[ATT_16_UUID_LEN]; /*! Supported Unread Alert Category */ +extern const uint8_t attBpfChUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Feature */ +extern const uint8_t attHidBmiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidBkiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidBkoChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidRmChUuid[ATT_16_UUID_LEN]; /*! Report Map */ +extern const uint8_t attHidcpChUuid[ATT_16_UUID_LEN]; /*! HID Control Point */ +extern const uint8_t attHidRepChUuid[ATT_16_UUID_LEN]; /*! Report */ +extern const uint8_t attHidPmChUuid[ATT_16_UUID_LEN]; /*! Protocol Mode */ +extern const uint8_t attSiwChUuid[ATT_16_UUID_LEN]; /*! Scan Interval Window */ +extern const uint8_t attPnpChUuid[ATT_16_UUID_LEN]; /*! PnP ID */ +extern const uint8_t attGlfChUuid[ATT_16_UUID_LEN]; /*! Glucose Feature */ +extern const uint8_t attRacpChUuid[ATT_16_UUID_LEN]; /*! Record Access Control Point */ +extern const uint8_t attCarChUuid[ATT_16_UUID_LEN]; /*! Central Address Resolution */ +extern const uint8_t attRsfChUuid[ATT_16_UUID_LEN]; /*! Running Speed Features */ +extern const uint8_t attRsmChUuid[ATT_16_UUID_LEN]; /*! Running Speed Measurement */ +extern const uint8_t attCpfChUuid[ATT_16_UUID_LEN]; /*! Cycling Power Features */ +extern const uint8_t attCpmChUuid[ATT_16_UUID_LEN]; /*! Cycling Power Measurement */ +extern const uint8_t attCsfChUuid[ATT_16_UUID_LEN]; /*! Cycling Speed Features */ +extern const uint8_t attCsmChUuid[ATT_16_UUID_LEN]; /*! Cycling Speed Measurement */ +extern const uint8_t attSlChUuid[ATT_16_UUID_LEN]; /*! Sensor Location */ +extern const uint8_t attPlxfChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Features */ +extern const uint8_t attPlxscmChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Spot Check Measurement */ +extern const uint8_t attPlxcmChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Continuous Measurement */ +extern const uint8_t attRpaoChUuid[ATT_16_UUID_LEN]; /*! Resolvable Private Address Only */ +extern const uint8_t attDbciChUuid[ATT_16_UUID_LEN]; /*! Database Change Increment */ +extern const uint8_t attUiChUuid[ATT_16_UUID_LEN]; /*! User Index */ +extern const uint8_t attUcpChUuid[ATT_16_UUID_LEN]; /*! User Control Point */ + +/* remove when adopted */ +extern const uint8_t attWssSvcUuid[ATT_16_UUID_LEN]; /*! Weight scale service */ +extern const uint8_t attWmChUuid[ATT_16_UUID_LEN]; /*! Weight measurement */ +extern const uint8_t attWsfChUuid[ATT_16_UUID_LEN]; /*! Weight scale feature */ + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_UUID_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h new file mode 100644 index 00000000000..ad01975349d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h @@ -0,0 +1,2423 @@ +/*************************************************************************************************/ +/*! + * \file dm_api.h + * + * \brief Device Manager subsystem API. + * + * $Date: 2017-02-09 11:58:21 -0600 (Thu, 09 Feb 2017) $ + * $Revision: 11135 $ + * + * Copyright (c) 2016-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef DM_API_H +#define DM_API_H + +#include "hci_api.h" +#include "cfg_stack.h" +#include "smp_defs.h" +#include "sec_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Device role */ +#define DM_ROLE_MASTER HCI_ROLE_MASTER /*! Role is master */ +#define DM_ROLE_SLAVE HCI_ROLE_SLAVE /*! Role is slave */ + +/*! The GAP discovery mode */ +#define DM_DISC_MODE_NONE 0 /*! GAP non-discoverable */ +#define DM_DISC_MODE_LIMITED 1 /*! GAP limited discoverable mode */ +#define DM_DISC_MODE_GENERAL 2 /*! GAP general discoverable mode */ + +/*! The type of connectable or discoverable of advertising */ +#define DM_ADV_CONN_UNDIRECT 0 /*! Connectable and scannable undirected advertising */ +#define DM_ADV_CONN_DIRECT 1 /*! Connectable directed advertising */ +#define DM_ADV_SCAN_UNDIRECT 2 /*! Scannable undirected advertising */ +#define DM_ADV_NONCONN_UNDIRECT 3 /*! Non-connectable and non-scannable undirected advertising */ +#define DM_ADV_CONN_DIRECT_LO_DUTY 4 /*! Connectable directed low duty cycle advertising */ + +/*! The type of extended advertising -- only applicable to AE */ +#define DM_EXT_ADV_CONN_UNDIRECT 5 /*! Connectable undirected advertising */ +#define DM_EXT_ADV_NONCONN_DIRECT 6 /*! Non-connectable and non-scannable directed advertising */ +#define DM_EXT_ADV_SCAN_DIRECT 7 /*! Scannable directed advertising */ +#define DM_ADV_NONE 255 /*! For internal use only */ + +/*! The type of advertising report */ +#define DM_RPT_CONN_UNDIRECT 0 /*! Connectable and scannable undirected advertising */ +#define DM_RPT_CONN_DIRECT 1 /*! Connectable directed advertising */ +#define DM_RPT_SCAN_UNDIRECT 2 /*! Scannable undirected advertising */ +#define DM_RPT_NONCONN_UNDIRECT 3 /*! Non-connectable undirected advertising */ +#define DM_RPT_SCAN_RESPONSE 4 /*! Scan response */ + +/*! Whether data is located in the advertising data or the scan response data */ +#define DM_DATA_LOC_ADV 0 /*! Locate data in the advertising data */ +#define DM_DATA_LOC_SCAN 1 /*! Locate data in the scan response data */ + +/*! The scan type */ +#define DM_SCAN_TYPE_PASSIVE 0 /*! Passive scan */ +#define DM_SCAN_TYPE_ACTIVE 1 /*! Active scan */ + +/*! Advertising channel map */ +#define DM_ADV_CHAN_37 HCI_ADV_CHAN_37 /*! Advertising channel 37 */ +#define DM_ADV_CHAN_38 HCI_ADV_CHAN_38 /*! Advertising channel 38 */ +#define DM_ADV_CHAN_39 HCI_ADV_CHAN_39 /*! Advertising channel 39 */ +#define DM_ADV_CHAN_ALL (HCI_ADV_CHAN_37 | HCI_ADV_CHAN_38 | HCI_ADV_CHAN_39) + +/*! The client ID parameter to function DmConnRegister() */ +#define DM_CLIENT_ID_ATT 0 /*! Identifier for attribute protocol, for internal use only */ +#define DM_CLIENT_ID_SMP 1 /*! Identifier for security manager protocol, for internal use only */ +#define DM_CLIENT_ID_DM 2 /*! Identifier for device manager, for internal use only */ +#define DM_CLIENT_ID_APP 3 /*! Identifier for the application */ +#define DM_CLIENT_ID_L2C 4 /*! Identifier for L2CAP */ +#define DM_CLIENT_ID_MAX 5 /*! For internal use only */ + +/*! Unknown connection ID or other error */ +#define DM_CONN_ID_NONE 0 + +/*! The address type */ +#define DM_ADDR_PUBLIC 0x00 /*! Public device address */ +#define DM_ADDR_RANDOM 0x01 /*! Random device address */ +#define DM_ADDR_PUBLIC_IDENTITY 0x02 /*! Public identity address (corresponds to resolved private address) */ +#define DM_ADDR_RANDOM_IDENTITY 0x03 /*! Random (static) identity address (corresponds to resolved private address) */ +#define DM_ADDR_RANDOM_UNRESOLVED 0xFE /*! Random device address (Controller unable to resolve) */ +#define DM_ADDR_NONE 0xFF /*! No address provided (anonymous) */ + +/*! Advertising data types */ +#define DM_ADV_TYPE_FLAGS 0x01 /*! Flag bits */ +#define DM_ADV_TYPE_16_UUID_PART 0x02 /*! Partial list of 16 bit UUIDs */ +#define DM_ADV_TYPE_16_UUID 0x03 /*! Complete list of 16 bit UUIDs */ +#define DM_ADV_TYPE_32_UUID_PART 0x04 /*! Partial list of 32 bit UUIDs */ +#define DM_ADV_TYPE_32_UUID 0x05 /*! Complete list of 32 bit UUIDs */ +#define DM_ADV_TYPE_128_UUID_PART 0x06 /*! Partial list of 128 bit UUIDs */ +#define DM_ADV_TYPE_128_UUID 0x07 /*! Complete list of 128 bit UUIDs */ +#define DM_ADV_TYPE_SHORT_NAME 0x08 /*! Shortened local name */ +#define DM_ADV_TYPE_LOCAL_NAME 0x09 /*! Complete local name */ +#define DM_ADV_TYPE_TX_POWER 0x0A /*! TX power level */ +#define DM_ADV_TYPE_SM_TK_VALUE 0x10 /*! Security manager TK value */ +#define DM_ADV_TYPE_SM_OOB_FLAGS 0x11 /*! Security manager OOB flags */ +#define DM_ADV_TYPE_CONN_INTERVAL 0x12 /*! Slave preferred connection interval */ +#define DM_ADV_TYPE_SIGNED_DATA 0x13 /*! Signed data */ +#define DM_ADV_TYPE_16_SOLICIT 0x14 /*! Service soliticiation list of 16 bit UUIDs */ +#define DM_ADV_TYPE_128_SOLICIT 0x15 /*! Service soliticiation list of 128 bit UUIDs */ +#define DM_ADV_TYPE_SERVICE_DATA 0x16 /*! Service data - 16-bit UUID */ +#define DM_ADV_TYPE_PUBLIC_TARGET 0x17 /*! Public target address */ +#define DM_ADV_TYPE_RANDOM_TARGET 0x18 /*! Random target address */ +#define DM_ADV_TYPE_APPEARANCE 0x19 /*! Device appearance */ +#define DM_ADV_TYPE_ADV_INTERVAL 0x1A /*! Advertising interval */ +#define DM_ADV_TYPE_BD_ADDR 0x1B /*! LE Bluetooth device address */ +#define DM_ADV_TYPE_ROLE 0x1C /*! LE role */ +#define DM_ADV_TYPE_32_SOLICIT 0x1F /*! Service soliticiation list of 32 bit UUIDs */ +#define DM_ADV_TYPE_SVC_DATA_32 0x20 /*! Service data - 32-bit UUID */ +#define DM_ADV_TYPE_SVC_DATA_128 0x21 /*! Service data - 128-bit UUID */ +#define DM_ADV_TYPE_LESC_CONFIRM 0x22 /*! LE Secure Connections confirm value */ +#define DM_ADV_TYPE_LESC_RANDOM 0x23 /*! LE Secure Connections random value */ +#define DM_ADV_TYPE_URI 0x24 /*! URI */ +#define DM_ADV_TYPE_MANUFACTURER 0xFF /*! Manufacturer specific data */ + +/*! Bit mask for flags advertising data type */ +#define DM_FLAG_LE_LIMITED_DISC 0x01 /*! Limited discoverable flag */ +#define DM_FLAG_LE_GENERAL_DISC 0x02 /*! General discoverable flag */ +#define DM_FLAG_LE_BREDR_NOT_SUP 0x04 /*! BR/EDR not supported flag */ + +/*! Advertising data element indexes */ +#define DM_AD_LEN_IDX 0 /*! Advertising data element len */ +#define DM_AD_TYPE_IDX 1 /*! Advertising data element type */ +#define DM_AD_DATA_IDX 2 /*! Advertising data element data */ + +/*! Advertising URI Scheme */ +#define DM_URI_SCHEME_HTTP 0x16 /*! URI HTTP Scheme */ +#define DM_URI_SCHEME_HTTPS 0x17 /*! URI HTTPS Scheme */ + +/*! Timeouts defined by the GAP specification; in units of milliseconds */ +#define DM_GAP_LIM_ADV_TIMEOUT 180000 /*! Maximum advertising duration in limited discoverable mode */ +#define DM_GAP_GEN_DISC_SCAN_MIN 10240 /*! Minimum scan duration for general discovery */ +#define DM_GAP_LIM_DISC_SCAN_MIN 10240 /*! Minimum scan duration for limited discovery */ +#define DM_GAP_CONN_PARAM_TIMEOUT 30000 /*! Connection parameter update timeout */ +#define DM_GAP_SCAN_FAST_PERIOD 30720 /*! Minimum time to perform scanning when user initiated */ +#define DM_GAP_ADV_FAST_PERIOD 30000 /*! Minimum time to perform advertising when user initiated */ + +/*! + * Advertising, scanning, and connection parameters defined in the GAP specification for the LE 1M PHY. + * In units of 625 microseconds. + */ +#define DM_GAP_SCAN_FAST_INT_MIN 48 /*! Minimum scan interval when user initiated */ +#define DM_GAP_SCAN_FAST_INT_MAX 96 /*! Maximum scan interval when user initiated */ +#define DM_GAP_SCAN_FAST_WINDOW 48 /*! Scan window when user initiated */ +#define DM_GAP_SCAN_SLOW_INT_1 2048 /*! Scan interval 1 when background scannning */ +#define DM_GAP_SCAN_SLOW_WINDOW_1 18 /*! Scan window 1 when background scanning */ +#define DM_GAP_SCAN_SLOW_INT_2 4096 /*! Scan interval 2 when background scannning */ +#define DM_GAP_SCAN_SLOW_WINDOW_2 36 /*! Scan window 2 when background scanning */ +#define DM_GAP_ADV_FAST_INT_MIN_1 48 /*! Minimum advertising interval 1 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MAX_1 96 /*! Maximum advertising interval 1 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MIN_2 160 /*! Minimum advertising interval 2 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MAX_2 240 /*! Maximum advertising interval 2 when user initiated */ +#define DM_GAP_ADV_SLOW_INT_MIN 1600 /*! Minimum advertising interval when background advertising */ +#define DM_GAP_ADV_SLOW_INT_MAX 1920 /*! Maximum advertising interval when background advertising */ + + /*! + * Advertising, scanning, and connection parameters defined in the GAP specification for the LE Coded PHY. + * In units of 625 microseconds. + */ +#define DM_GAP_SCAN_CODED_FAST_INT_MIN 144 /*! Minimum scan interval when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_FAST_INT_MAX 288 /*! Maximum scan interval when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_FAST_WINDOW 144 /*! Scan window when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_INT_1 6144 /*! Scan interval 1 when background scannning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_WINDOW_1 54 /*! Scan window 1 when background scanning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_INT_2 12288 /*! Scan interval 2 when background scannning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_WINDOW_2 108 /*! Scan window 2 when background scanning on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MIN_1 144 /*! Minimum advertising interval 1 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MAX_1 288 /*! Maximum advertising interval 1 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MIN_2 480 /*! Minimum advertising interval 2 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MAX_2 720 /*! Maximum advertising interval 2 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_SLOW_INT_MIN 4800 /*! Minimum advertising interval when background advertising on LE Coded PHY */ +#define DM_GAP_ADV_CODED_SLOW_INT_MAX 5760 /*! Maximum advertising interval when background advertising on LE Coded PHY */ + +/*! GAP connection establishment latency */ +#define DM_GAP_CONN_EST_LATENCY 0 + +/*! GAP connection intervals in 1.25ms units */ +#define DM_GAP_INITIAL_CONN_INT_MIN 24 /*! Minimum initial connection interval */ +#define DM_GAP_INITIAL_CONN_INT_MAX 40 /*! Maximum initial onnection interval */ + +/*! GAP connection establishment minimum and maximum connection event lengths */ +#define DM_GAP_CONN_EST_MIN_CE_LEN 0 +#define DM_GAP_CONN_EST_MAX_CE_LEN 0 + +/*! GAP peripheral privacy flag characteristic values */ +#define DM_GAP_PRIV_DISABLED 0 +#define DM_GAP_PRIV_ENABLED 1 + +/*! Connection establishment supervision timeout default, in 10ms units */ +#define DM_DEFAULT_EST_SUP_TIMEOUT 2000 + +/*! Pairing authentication/security properties bit mask */ +#define DM_AUTH_BOND_FLAG SMP_AUTH_BOND_FLAG /*! Bonding requested */ +#define DM_AUTH_MITM_FLAG SMP_AUTH_MITM_FLAG /*! MITM (authenticated pairing) requested */ +#define DM_AUTH_SC_FLAG SMP_AUTH_SC_FLAG /*! LE Secure Connections requested */ +#define DM_AUTH_KP_FLAG SMP_AUTH_KP_FLAG /*! Keypress notifications requested */ + +/*! Key distribution bit mask */ +#define DM_KEY_DIST_LTK SMP_KEY_DIST_ENC /*! Distribute LTK used for encryption */ +#define DM_KEY_DIST_IRK SMP_KEY_DIST_ID /*! Distribute IRK used for privacy */ +#define DM_KEY_DIST_CSRK SMP_KEY_DIST_SIGN /*! Distribute CSRK used for signed data */ + +/*! Key type used in DM_SEC_KEY_IND */ +#define DM_KEY_LOCAL_LTK 0x01 /*! LTK generated locally for this device */ +#define DM_KEY_PEER_LTK 0x02 /*! LTK received from peer device */ +#define DM_KEY_IRK 0x04 /*! IRK and identity info of peer device */ +#define DM_KEY_CSRK 0x08 /*! CSRK of peer device */ + +/*! Base value for HCI error status values for DM_SEC_PAIR_CMPL_IND */ +#define DM_SEC_HCI_ERR_BASE 0x20 + +#define DM_SEC_LEVEL_NONE 0 /*! Connection has no security */ +#define DM_SEC_LEVEL_ENC 1 /*! Connection is encrypted with unauthenticated key */ +#define DM_SEC_LEVEL_ENC_AUTH 2 /*! Connection is encrypted with authenticated key */ +#define DM_SEC_LEVEL_ENC_LESC 3 /*! Connection is encrypted with LE Secure Connections */ + +/*! Random address types */ +#define DM_RAND_ADDR_STATIC 0xC0 /*! Static address */ +#define DM_RAND_ADDR_RESOLV 0x40 /*! Resolvable private address */ +#define DM_RAND_ADDR_NONRESOLV 0x00 /*! Non-resolvable private address */ + +/*! Privacy modes */ +#define DM_PRIV_MODE_NETWORK 0x00 /*! Network privacy mode (default) */ +#define DM_PRIV_MODE_DEVICE 0x01 /*! Device privacy mode */ + +/*! Get the type of random address */ +#define DM_RAND_ADDR_GET(addr) ((addr)[5] & 0xC0) + +/*! Set the type of random address */ +#define DM_RAND_ADDR_SET(addr, type) {(addr)[5] = ((addr)[5] & 0x3F) | (type);} + +/*! Check for Resolvable Random Address */ +#define DM_RAND_ADDR_RPA(addr, type) (((type) == DM_ADDR_RANDOM) && \ + (DM_RAND_ADDR_GET((addr)) == DM_RAND_ADDR_RESOLV)) + +/*! Connection busy/idle state */ +#define DM_CONN_IDLE 0 /*! Connection is idle */ +#define DM_CONN_BUSY 1 /*! Connection is busy */ + +/*! Connection busy/idle state bitmask */ +#define DM_IDLE_SMP_PAIR 0x0001 /*! SMP pairing in progress */ +#define DM_IDLE_DM_ENC 0x0002 /*! DM Encryption setup in progress */ +#define DM_IDLE_ATTS_DISC 0x0004 /*! ATTS service discovery in progress */ +#define DM_IDLE_APP_DISC 0x0008 /*! App framework service discovery in progress */ +#define DM_IDLE_USER_1 0x0010 /*! For use by user application */ +#define DM_IDLE_USER_2 0x0020 /*! For use by user application */ +#define DM_IDLE_USER_3 0x0040 /*! For use by user application */ +#define DM_IDLE_USER_4 0x0080 /*! For use by user application */ + +/*! Filter policy modes */ +#define DM_FILT_POLICY_MODE_ADV 0 /*! Advertising filter policy mode */ +#define DM_FILT_POLICY_MODE_SCAN 1 /*! Scanning filter policy mode */ +#define DM_FILT_POLICY_MODE_INIT 2 /*! Initiator filter policy mode */ + +/*! Proprietary internal error codes */ +#define DM_ERR_SMP_RX_PDU_LEN_EXCEEDED 0x01 /*! LESC key length exceeded maximum RX PDU length */ +#define DM_ERR_ATT_RX_PDU_LEN_EXCEEDED 0x02 /*! Configured ATT MTU exceeded maximum RX PDU length */ +#define DM_ERR_L2C_RX_PDU_LEN_EXCEEDED 0x03 /*! Registered COC MPS exceeded maximum RX PDU length */ + +/*! Advertising handle */ +#define DM_ADV_HANDLE_DEFAULT 0 /*! Default advertising handle for legacy advertising */ + +/*! DM callback events */ +#define DM_CBACK_START 0x20 /*! DM callback event starting value */ +enum +{ + DM_RESET_CMPL_IND = DM_CBACK_START, /*! Reset complete */ + DM_ADV_START_IND, /*! Advertising started */ + DM_ADV_STOP_IND, /*! Advertising stopped */ + DM_ADV_NEW_ADDR_IND, /*! New resolvable address has been generated */ + DM_SCAN_START_IND, /*! Scanning started */ + DM_SCAN_STOP_IND, /*! Scanning stopped */ + DM_SCAN_REPORT_IND, /*! Scan data received from peer device */ + DM_CONN_OPEN_IND, /*! Connection opened */ + DM_CONN_CLOSE_IND, /*! Connection closed */ + DM_CONN_UPDATE_IND, /*! Connection update complete */ + DM_SEC_PAIR_CMPL_IND, /*! Pairing completed successfully */ + DM_SEC_PAIR_FAIL_IND, /*! Pairing failed or other security failure */ + DM_SEC_ENCRYPT_IND, /*! Connection encrypted */ + DM_SEC_ENCRYPT_FAIL_IND, /*! Encryption failed */ + DM_SEC_AUTH_REQ_IND, /*! PIN or OOB data requested for pairing */ + DM_SEC_KEY_IND, /*! Security key indication */ + DM_SEC_LTK_REQ_IND, /*! LTK requested for encyption */ + DM_SEC_PAIR_IND, /*! Incoming pairing request from master */ + DM_SEC_SLAVE_REQ_IND, /*! Incoming security request from slave */ + DM_SEC_CALC_OOB_IND, /*! Result of OOB Confirm Calculation Generation */ + DM_SEC_ECC_KEY_IND, /*! Result of ECC Key Generation */ + DM_SEC_COMPARE_IND, /*! Result of Just Works/Numeric Comparison Compare Value Calculation */ + DM_SEC_KEYPRESS_IND, /*! Keypress indication from peer in passkey security */ + DM_PRIV_RESOLVED_ADDR_IND, /*! Private address resolved */ + DM_CONN_READ_RSSI_IND, /*! Connection RSSI read */ + DM_PRIV_ADD_DEV_TO_RES_LIST_IND, /*! Device added to resolving list */ + DM_PRIV_REM_DEV_FROM_RES_LIST_IND, /*! Device removed from resolving list */ + DM_PRIV_CLEAR_RES_LIST_IND, /*! Resolving list cleared */ + DM_PRIV_READ_PEER_RES_ADDR_IND, /*! Peer resolving address read */ + DM_PRIV_READ_LOCAL_RES_ADDR_IND, /*! Local resolving address read */ + DM_PRIV_SET_ADDR_RES_ENABLE_IND, /*! Address resolving enable set */ + DM_REM_CONN_PARAM_REQ_IND, /*! Remote connection parameter requested */ + DM_CONN_DATA_LEN_CHANGE_IND, /*! Data length changed */ + DM_CONN_WRITE_AUTH_TO_IND, /*! Write authenticated payload complete */ + DM_CONN_AUTH_TO_EXPIRED_IND, /*! Authenticated payload timeout expired */ + DM_PHY_READ_IND, /*! Read PHY */ + DM_PHY_SET_DEF_IND, /*! Set default PHY */ + DM_PHY_UPDATE_IND, /*! PHY update */ + DM_ADV_SET_START_IND, /*! Advertising set(s) started */ + DM_ADV_SET_STOP_IND, /*! Advertising set(s) stopped */ + DM_SCAN_REQ_RCVD_IND, /*! Scan request received */ + DM_EXT_SCAN_START_IND, /*! Extended scanning started */ + DM_EXT_SCAN_STOP_IND, /*! Extended scanning stopped */ + DM_EXT_SCAN_REPORT_IND, /*! Extended scan data received from peer device */ + DM_PER_ADV_SET_START_IND, /*! Periodic advertising set started */ + DM_PER_ADV_SET_STOP_IND, /*! Periodic advertising set stopped */ + DM_PER_ADV_SYNC_EST_IND, /*! Periodic advertising sync established */ + DM_PER_ADV_SYNC_LOST_IND, /*! Periodic advertising sync lost */ + DM_PER_ADV_REPORT_IND, /*! Periodic advertising data received from peer device */ + DM_REMOTE_FEATURES_IND, /*! Remote features from peer device */ + DM_ERROR_IND, /*! General error */ + DM_VENDOR_SPEC_IND, /*! Vendor specific event */ +}; + +#define DM_CBACK_END DM_VENDOR_SPEC_IND /*! DM callback event ending value */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection identifier */ +typedef uint8_t dmConnId_t; + +/*! Configuration structure */ +typedef struct +{ + uint8_t dummy; +} dmCfg_t; + +/*! LTK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; + uint8_t rand[SMP_RAND8_LEN]; + uint16_t ediv; +} dmSecLtk_t; + +/*! IRK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; + bdAddr_t bdAddr; + uint8_t addrType; +} dmSecIrk_t; + +/*! CSRK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; +} dmSecCsrk_t; + +/*! union of key types */ +typedef union +{ + dmSecLtk_t ltk; + dmSecIrk_t irk; + dmSecCsrk_t csrk; +} dmSecKey_t; + +/*! Data type for DM_SEC_PAIR_CMPL_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ +} dmSecPairCmplIndEvt_t; + +/*! Data type for DM_SEC_ENCRYPT_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bool_t usingLtk; /*! TRUE if connection encrypted with LTK */ +} dmSecEncryptIndEvt_t; + +/*! Data type for DM_SEC_AUTH_REQ_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bool_t oob; /*! Out-of-band data requested */ + bool_t display; /*! TRUE if pin is to be displayed */ +} dmSecAuthReqIndEvt_t; + +/*! Data type for DM_SEC_PAIR_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ + bool_t oob; /*! Out-of-band pairing data present or not present */ + uint8_t iKeyDist; /*! Initiator key distribution flags */ + uint8_t rKeyDist; /*! Responder key distribution flags */ +} dmSecPairIndEvt_t; + +/*! Data type for DM_SEC_SLAVE_REQ_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ +} dmSecSlaveIndEvt_t; + +/*! Data type for DM_SEC_KEY_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + dmSecKey_t keyData; /*! Key data */ + uint8_t type; /*! Key type */ + uint8_t secLevel; /*! Security level of pairing when key was exchanged */ + uint8_t encKeyLen; /*! Length of encryption key used when data was transferred */ +} dmSecKeyIndEvt_t; + +/*! Data type for DM_SEC_COMPARE_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t confirm[SMP_CONFIRM_LEN]; /*! Confirm value */ +} dmSecCnfIndEvt_t; + +/*! Data type for DM_SEC_KEYPRESS_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t notificationType; /*! Type of keypress notification */ +} dmSecKeypressIndEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t confirm[SMP_CONFIRM_LEN]; /*! Local confirm value */ + uint8_t random[SMP_RAND_LEN]; /*! Local random value */ +} dmSecOobCalcIndEvt_t; + +/*! Data type for DM_ADV_NEW_ADDR_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bdAddr_t addr; /*! New resolvable private address */ + bool_t firstTime; /*! TRUE when address is generated for the first time */ +} dmAdvNewAddrIndEvt_t; + +/* Data structure for DM_ADV_SET_START_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t numSets; /*! Number of advertising sets */ + uint8_t advHandle[DM_NUM_ADV_SETS];/*! Advertising handle array */ +} dmAdvSetStartEvt_t; + +/* Data structure for DM_PER_ADV_SET_START_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t advHandle; /*! Advertising handle */ +} dmPerAdvSetStartEvt_t; + +/* Data structure for DM_PER_ADV_SET_STOP_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t advHandle; /*! Advertising handle */ +} dmPerAdvSetStopEvt_t; + +/*! Union of DM callback event data types */ +typedef union +{ + wsfMsgHdr_t hdr; /*! Common header */ + /*! common header used by DM_RESET_CMPL_IND */ + /*! common header used by DM_ADV_START_IND */ + /*! common header used by DM_ADV_STOP_IND */ + dmAdvNewAddrIndEvt_t advNewAddr; /*! DM_ADV_NEW_ADDR_IND */ + /*! common header used by DM_SCAN_START_IND */ + /*! common header used by DM_SCAN_STOP_IND */ + hciLeAdvReportEvt_t scanReport; /*! DM_SCAN_REPORT_IND */ + hciLeConnCmplEvt_t connOpen; /*! DM_CONN_OPEN_IND */ + hciDisconnectCmplEvt_t connClose; /*! DM_CONN_CLOSE_IND */ + hciLeConnUpdateCmplEvt_t connUpdate; /*! DM_CONN_UPDATE_IND */ + dmSecPairCmplIndEvt_t pairCmpl; /*! DM_SEC_PAIR_CMPL_IND */ + /*! common header used by DM_SEC_PAIR_FAIL_IND */ + dmSecEncryptIndEvt_t encryptInd; /*! DM_SEC_ENCRYPT_IND */ + /*! common header used by DM_SEC_ENCRYPT_FAIL_IND */ + dmSecAuthReqIndEvt_t authReq; /*! DM_SEC_AUTH_REQ_IND */ + dmSecKeyIndEvt_t keyInd; /*! DM_SEC_KEY_IND */ + hciLeLtkReqEvt_t ltkReqInd; /*! DM_SEC_LTK_REQ_IND */ + dmSecPairIndEvt_t pairInd; /*! DM_SEC_PAIR_IND */ + dmSecSlaveIndEvt_t slaveInd; /*! DM_SEC_SLAVE_REQ_IND */ + dmSecOobCalcIndEvt_t oobCalcInd; /*! DM_SEC_CALC_OOB_IND */ + secEccMsg_t eccMsg; /*! DM_SEC_ECC_KEY_IND */ + dmSecCnfIndEvt_t cnfInd; /*! DM_SEC_COMPARE_IND */ + dmSecKeypressIndEvt_t keypressInd; /*! DM_SEC_KEYPRESS_IND */ + /*! common header used by DM_PRIV_RESOLVED_ADDR_IND */ + hciReadRssiCmdCmplEvt_t readRssi; /*! DM_CONN_READ_RSSI_IND */ + hciLeAddDevToResListCmdCmplEvt_t addDevToResList; /*! DM_PRIV_ADD_DEV_TO_RES_LIST_IND */ + hciLeRemDevFromResListCmdCmplEvt_t remDevFromResList;/*! DM_PRIV_REM_DEV_FROM_RES_LIST_IND */ + hciLeClearResListCmdCmplEvt_t clearResList; /*! DM_PRIV_CLEAR_RES_LIST_IND */ + hciLeReadPeerResAddrCmdCmplEvt_t readPeerResAddr; /*! DM_PRIV_READ_PEER_RES_ADDR_IND */ + hciLeReadLocalResAddrCmdCmplEvt_t readLocalResAddr; /*! DM_PRIV_READ_LOCAL_RES_ADDR_IND */ + hciLeSetAddrResEnableCmdCmplEvt_t setAddrResEnable; /*! DM_PRIV_SET_ADDR_RES_ENABLE_IND */ + hciLeRemConnParamReqEvt_t remConnParamReq; /*! DM_REM_CONN_PARAM_REQ_IND */ + hciLeDataLenChangeEvt_t dataLenChange; /*! DM_CONN_DATA_LEN_CHANGE_IND */ + hciWriteAuthPayloadToCmdCmplEvt_t writeAuthTo; /*! DM_CONN_WRITE_AUTH_TO_IND */ + hciAuthPayloadToExpiredEvt_t authToExpired; /*! DM_CONN_AUTH_TO_EXPIRED_IND */ + hciLeReadPhyCmdCmplEvt_t readPhy; /*! DM_PHY_READ_IND */ + hciLeSetDefPhyCmdCmplEvt_t setDefPhy; /*! DM_PHY_SET_DEF_IND */ + hciLePhyUpdateEvt_t phyUpdate; /*! DM_PHY_UPDATE_IND */ + dmAdvSetStartEvt_t advSetStart; /*! DM_ADV_SET_START_IND */ + hciLeAdvSetTermEvt_t advSetStop; /*! DM_ADV_SET_STOP_IND */ + hciLeScanReqRcvdEvt_t scanReqRcvd; /*! DM_SCAN_REQ_RCVD_IND */ + /*! common header used by DM_EXT_SCAN_START_IND */ + /*! common header used by DM_EXT_SCAN_STOP_IND */ + hciLeExtAdvReportEvt_t extScanReport; /*! DM_EXT_SCAN_REPORT_IND */ + dmPerAdvSetStartEvt_t perAdvSetStart; /*! DM_PER_ADV_SET_START_IND */ + dmPerAdvSetStopEvt_t perAdvSetStop; /*! DM_PER_ADV_SET_STOP_IND */ + hciLePerAdvSyncEstEvt_t perAdvSyncEst; /*! DM_PER_ADV_SYNC_EST_IND */ + hciLePerAdvSyncLostEvt_t perAdvSyncLost; /*! DM_PER_ADV_SYNC_LOST_IND */ + hciLePerAdvReportEvt_t perAdvReport; /*! DM_PER_ADV_REPORT_IND */ + hciLeReadRemoteFeatCmplEvt_t readRemoteFeat; /*! DM_REMOTE_FEATURES_IND */ + /*! common header used by DM_ERROR_IND */ + hciVendorSpecEvt_t vendorSpec; /*! DM_VENDOR_SPEC_IND */ +} dmEvt_t; + +/*! Data type for DmSecSetOob */ +typedef struct +{ + uint8_t localRandom[SMP_RAND_LEN]; /*! Random value of the local device */ + uint8_t localConfirm[SMP_CONFIRM_LEN]; /*! Confirm value of the local device */ + uint8_t peerRandom[SMP_RAND_LEN]; /*! Random value of the peer device */ + uint8_t peerConfirm[SMP_CONFIRM_LEN]; /*! Confirm value of the peer device */ +} dmSecLescOobCfg_t; + +/*! Callback type */ +typedef void (*dmCback_t)(dmEvt_t *pDmEvt); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn DmRegister + * + * \brief Register a callback with DM for scan and advertising events. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRegister(dmCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn DmFindAdType + * + * \brief Find an advertising data element in the given advertising or scan response data. + * + * \param adType Advertising data element type to find. + * \param dataLen Data length. + * \param pData Pointer to advertising or scan response data. + * + * \return Pointer to the advertising data element byte array or NULL if not found. + */ +/*************************************************************************************************/ +uint8_t *DmFindAdType(uint8_t adType, uint16_t dataLen, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn DmAdvInit + * + * \brief Initialize DM legacy advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtAdvInit + * + * \brief Initialize DM extended advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtAdvInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvModeLeg + * + * \brief Whether DM advertising is in legacy mode. + * + * \return TRUE if DM advertising is in legacy mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvModeLeg(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvModeExt + * + * \brief Whether DM advertising is in extended mode. + * + * \return TRUE if DM advertising is in extended mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvModeExt(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvConfig + * + * \brief Set the advertising parameters using the given advertising type, and peer address. + * + * \param advHandle Advertising handle. + * \param advType Advertising type. + * \param peerAddrType Peer address type. + * \param pPeerAddr Peer address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvConfig(uint8_t advHandle, uint8_t advType, uint8_t peerAddrType, uint8_t *pPeerAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetData + * + * \brief Set the advertising or scan response data to the given data. + * + * \param advHandle Advertising handle. + * \param op Data operation. + * \param location Data location. + * \param len Length of the data. Maximum length is 236 bytes. + * \param pData Pointer to the data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetData(uint8_t advHandle, uint8_t op, uint8_t location, uint8_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn DmAdvStart + * + * \brief Start advertising using the given advertising set and duration. + * + * \param numSets Number of advertising sets to enable. + * \param advHandle Advertising handle array. + * \param duration Advertising duration (in milliseconds) array. + * \param maxEaEvents Maximum number of extended advertising events array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvStart(uint8_t numSets, uint8_t *pAdvHandles, uint16_t *pDuration, uint8_t *pMaxEaEvents); + +/*************************************************************************************************/ +/*! + * \fn DmAdvStop + * + * \brief Stop advertising for the given advertising set. If the number of sets is set to 0 + * then all advertising sets are disabled. + * + * \param numSets Number of advertising sets to disable. + * \param pAdvHandles Advertising handles array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvStop(uint8_t numSets, uint8_t *pAdvHandles); + +/*************************************************************************************************/ +/*! + * \fn DmAdvRemoveAdvSet + * + * \brief Remove an advertising set. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvRemoveAdvSet(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmAdvClearAdvSets + * + * \brief Clear advertising sets. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvClearAdvSets(void); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvConfig + * + * \brief Set the advertising parameters for periodic advertising. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvConfig(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvSetData + * + * \brief Set the advertising data to the given data for periodic advertising. + * + * \param advHandle Advertising handle. + * \param op Data operation. + * \param len Length of the data. Maximum length is 236 bytes. + * \param pData Pointer to the data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvSetData(uint8_t advHandle, uint8_t op, uint8_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! +* \fn DmPerAdvStart + * + * \brief Start periodic advertising for the advertising set specified by the advertising handle. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvStart(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvStop + * + * \brief Stop periodic advertising for the advertising set specified by the advertising handle. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvStop(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetInterval + * + * \brief Set the minimum and maximum advertising intervals. + * + * \param advHandle Advertising handle. + * \param intervalMin Minimum advertising interval. + * \param intervalMax Maximum advertising interval. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetChannelMap + * + * \brief Include or exclude certain channels from the advertising channel map. + * + * \param advHandle Advertising handle. + * \param channelMap Advertising channel map. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetChannelMap(uint8_t advHandle, uint8_t channelMap); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetAddrType + * + * \brief Set the local address type used while advertising. This function can be used to + * configure advertising to use a random address. + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetAdValue + * + * \brief Set the value of an advertising data element in the given advertising or + * scan response data. If the element already exists in the data then it is replaced + * with the new value. If the element does not exist in the data it is appended + * to it, space permitting. + * + * \param adType Advertising data element type. + * \param len Length of the value. Maximum length is 29 bytes. + * \param pValue Pointer to the value. + * \param pAdvDataLen Advertising or scan response data length. The new length is returned + * in this parameter. + * \param pAdvData Pointer to advertising or scan response data. + * \param advDataBufLen Length of the advertising or scan response data buffer maintained by + * Application. + * + * \return TRUE if the element was successfully added to the data, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvSetAdValue(uint8_t adType, uint8_t len, uint8_t *pValue, uint16_t *pAdvDataLen, + uint8_t *pAdvData, uint16_t advDataBufLen); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetName + * + * \brief Set the device name in the given advertising or scan response data. If the + * name can only fit in the data if it is shortened, the name is shortened + * and the AD type is changed to DM_ADV_TYPE_SHORT_NAME. + * + * \param len Length of the name. Maximum length is 29 bytes. + * \param pValue Pointer to the name in UTF-8 format. + * \param pAdvDataLen Advertising or scan response data length. The new length is returned + * in this parameter. + * \param pAdvData Pointer to advertising or scan response data. + * \param advDataBufLen Length of the advertising or scan response data buffer maintained by + * Application. + * + * \return TRUE if the element was successfully added to the data, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvSetName(uint8_t len, uint8_t *pValue, uint16_t *pAdvDataLen, uint8_t *pAdvData, + uint16_t advDataBufLen); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetRandAddr + * + * \brief Set the random device address for a given advertising set. + * + * \param advHandle Advertising handle. + * \param pAddr Random device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetRandAddr(uint8_t advHandle, const uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvUseLegacyPdu + * + * \brief Set whether or not to use legacy advertising PDUs with extended advertising. + * + * \param advHandle Advertising handle. + * \param useLegacyPdu Whether to use legacy advertising PDUs (default value is TRUE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvUseLegacyPdu(uint8_t advHandle, bool_t useLegacyPdu); + +/*************************************************************************************************/ +/*! + * \fn DmAdvOmitAdvAddr + * + * \brief Set whether or not to omit advertiser�s address from all PDUs (anonymous advertising). + * + * \param advHandle Advertising handle. + * \param omitAdvAddr Whether to omit advertiser�s address from all PDUs (default value is FALSE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvOmitAdvAddr(uint8_t advHandle, bool_t omitAdvAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvIncTxPwr + * + * \brief Set whether or not to include TxPower in extended header of advertising PDU. + * + * \param advHandle Advertising handle. + * \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default + * value is FALSE). + * \param advTxPwr Advertising tx power (127 = no preference). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr, int8_t advTxPwr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetPhyParam + * + * \brief Set extended advertising PHY parameters. + * + * \param advHandle Advertising handle. + * \param priAdvPhy Primary advertising Phy. + * \param secAdvMaxSkip Maximum advertising events Controller can skip before sending AUX_ADV_IND + * on secondary advertising channel (0 = AUX_ADV_IND will be sent prior to + * next advertising event). + * \param secAdvPhy Secondary advertising Phy. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetPhyParam(uint8_t advHandle, uint8_t priAdvPhy, uint8_t secAdvMaxSkip, uint8_t secAdvPhy); + +/*************************************************************************************************/ +/*! + * \fn DmAdvScanReqNotifEnable + * + * \brief Set scan request notification enable. + * + * \param advHandle Advertising handle. + * \param scanReqNotifEna Scan request notification enable. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvScanReqNotifEnable(uint8_t advHandle, bool_t scanReqNotifEna); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetfragPref + * + * \brief Set fragment preference for advertising data. + * + * \param advHandle Advertising handle. + * \param fragPref Fragment preference. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetFragPref(uint8_t advHandle, uint8_t fragPref); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvSetInterval + * + * \brief Set the minimum and maximum advertising intervals for periodic advertising. + * + * \param advHandle Advertising handle. + * \param intervalMin Minimum advertising interval. + * \param intervalMax Maximum advertising interval. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvIncTxPwr + * + * \brief Set whether or not to include TxPower in extended header of advertising PDU for + * periodic advertising. + * + * \param advHandle Advertising handle. + * \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default + * value is FALSE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivInit + * + * \brief Initialize private advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivStart + * + * \brief Start using a private resolvable address. + * + * \param changeInterval Interval between automatic address changes, in seconds. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivStart(uint16_t changeInterval); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivStop + * + * \brief Stop using a private resolvable address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivStop(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanInit + * + * \brief Initialize DM legacy scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtScanInit + * + * \brief Initialize DM extended scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtScanInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanModeLeg + * + * \brief Whether DM scanning is in legacy mode. + * + * \return TRUE if DM scanning is in legacy mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmScanModeLeg(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanModeExt + * + * \brief Whether DM scanning is in extended mode. + * + * \return TRUE if DM scanning is in extended mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmScanModeExt(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanStart + * + * \brief Start scanning on the given PHYs. + * + * \param scanPhys Scanner PHYs. + * \param mode Discoverability mode. + * \param pScanType Scan type array. + * \param filterDup Filter duplicates. Set to TRUE to filter duplicate responses received + * from the same device. Set to FALSE to receive all responses. + * \param duration The scan duration, in milliseconds. If set to zero or both duration and + * period set to non-zero, scanning will continue until DmScanStop() is called. + * \param period The scan period, in 1.28 sec units (only applicable to AE). If set to zero, + * periodic scanning is disabled. + * + * \return None. + */ + /*************************************************************************************************/ +void DmScanStart(uint8_t scanPhys, uint8_t mode, const uint8_t *pScanType, bool_t filterDup, + uint16_t duration, uint16_t period); + +/*************************************************************************************************/ +/*! + * \fn DmScanStop + * + * \brief Stop scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanStop(void); + +/*************************************************************************************************/ +/*! + * \fn DmSyncStart + * + * \brief Synchronize with periodic advertising from the given advertisier, and start receiving + * periodic advertising packets. + * + * \param filterPolicy Filter policy. + * \param advSid Advertising SID. + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param skip Number of periodic advertising packets that can be skipped after + * successful receive. + * \param syncTimeout Synchronization timeout. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncStart(uint8_t filterPolicy, uint8_t advSid, uint8_t advAddrType, const uint8_t *pAdvAddr, + uint16_t skip, uint16_t syncTimeout); + +/*************************************************************************************************/ +/*! + * \fn DmSyncStop + * + * \brief Stop reception of the periodic advertising identified by the given sync handle. + * + * \param syncHandle Sync handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncStop(uint16_t syncHandle); + +/*************************************************************************************************/ +/*! + * \fn DmSyncCancel + * + * \brief Cancel creation of a sync while it's pending. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncCancel(void); + +/*************************************************************************************************/ +/*! + * \fn DmAddDeviceToPerAdvList + * + * \brief Add device to periodic advertiser list. + * + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param advSid Advertising SID. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAddDeviceToPerAdvList(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); + +/*************************************************************************************************/ +/*! + * \fn DmRemoveDeviceFromPerAdvList + * + * \brief DM remove device from periodic advertiser list. + * + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param advSid Advertising SID. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoveDeviceFromPerAdvList(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); + +/*************************************************************************************************/ +/*! + * \fn DmClearPerAdvList + * + * \brief DM clear periodic advertiser list. + * + * \return None. + */ +/*************************************************************************************************/ +void DmClearPerAdvList(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanSetInterval + * + * \brief Set the scan interval and window for the specified PHYs. + * + * \param scanPhys Scanning PHYs. + * \param pScanInterval Scan interval array. + * \param pScanWindow Scan window array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanSetInterval(uint8_t scanPhys, uint16_t *pScanInterval, uint16_t *pScanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmScanSetAddrType + * + * \brief Set the local address type used while scanning. This function can be used to + * configure scanning to use a random address. + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmConnInit + * + * \brief Initialize DM connection manager. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnMasterInit + * + * \brief Initialize DM connection manager for operation as legacy master. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnMasterInit + * + * \brief Initialize DM connection manager for operation as extended master. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnSlaveInit + * + * \brief Initialize DM connection manager for operation as legacy slave. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnSlaveInit + * + * \brief Initialize DM connection manager for operation as extended slave. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnRegister + * + * \brief Register with the DM connection manager. + * + * \param clientId The client identifier. + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnRegister(uint8_t clientId, dmCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn DmConnOpen + * + * \brief Open a connection to a peer device with the given address. + * + * \param clientId The client identifier. + * \param initPhys Initiator PHYs. + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return Connection identifier. + */ +/*************************************************************************************************/ +dmConnId_t DmConnOpen(uint8_t clientId, uint8_t initPhys, uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmConnClose + * + * \brief Close the connection with the give connection identifier. + * + * \param clientId The client identifier. + * \param connId Connection identifier. + * \param reason Reason connection is being closed. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnClose(uint8_t clientId, dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmConnAccept + * + * \brief Accept a connection from the given peer device by initiating directed advertising. + * + * \param clientId The client identifier. + * \param advHandle Advertising handle. + * \param advType Advertising type. + * \param duration Advertising duration (in ms). + * \param maxEaEvents Maximum number of extended advertising events. + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return Connection identifier. + */ +/*************************************************************************************************/ +dmConnId_t DmConnAccept(uint8_t clientId, uint8_t advHandle, uint8_t advType, uint16_t duration, + uint8_t maxEaEvents, uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmConnUpdate + * + * \brief Update the connection parameters of an open connection + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnUpdate(dmConnId_t connId, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetScanInterval + * + * \brief Set the scan interval and window for connections to be created with DmConnOpen(). + * + * \param scanInterval The scan interval. + * \param scanWindow The scan window. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetScanInterval(uint16_t scanInterval, uint16_t scanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnSetScanInterval + * + * \brief Set the scan interval and window for extended connections to be created with + * DmConnOpen(). + * + * \param initPhy Initiator PHYs. + * \param pScanInterval Scan interval array. + * \param pScanWindow Scan window array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSetScanInterval(uint8_t initPhys, uint16_t *pScanInterval, uint16_t *pScanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetConnSpec + * + * \brief Set the connection spec parameters for connections to be created with DmConnOpen(). + * + * \param pConnSpec Connection spec parameters. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetConnSpec(hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetExtConnSpec + * + * \brief Set the extended connection spec parameters for extended connections to be created + * with DmConnOpen(). + * + * \param initPhys The initiator PHYs. + * \param pConnSpec Connection spec parameters array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSetConnSpec(uint8_t initPhys, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetAddrType + * + * \brief Set the local address type used for connections created with DmConnOpen(). + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetIdle + * + * \brief Configure a bit in the connection idle state mask as busy or idle. + * + * \param connId Connection identifier. + * \param idleMask Bit in the idle state mask to configure. + * \param idle DM_CONN_BUSY or DM_CONN_IDLE. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetIdle(dmConnId_t connId, uint16_t idleMask, uint8_t idle); + +/*************************************************************************************************/ +/*! + * \fn DmConnCheckIdle + * + * \brief Check if a connection is idle. + * + * \param connId Connection identifier. + * + * \return Zero if connection is idle, nonzero if busy. + */ +/*************************************************************************************************/ +uint16_t DmConnCheckIdle(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnReadRssi + * + * \brief Read RSSI of a given connection. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnReadRssi(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmRemoteConnParamReqReply + * + * \brief Reply to the HCI remote connection parameter request event. This command is used to + * indicate that the Host has accepted the remote device�s request to change connection + * parameters. + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoteConnParamReqReply(dmConnId_t connId, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmRemoteConnParamReqNegReply + * + * \brief Negative reply to the HCI remote connection parameter request event. This command + * is used to indicate that the Host has rejected the remote device�s request to change + * connection parameters. + * + * \param connId Connection identifier. + * \param reason Reason for rejection. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoteConnParamReqNegReply(dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetDataLen + * + * \brief Set data length for a given connection. + * + * \param connId Connection identifier. + * \param txOctets Maximum number of payload octets for a Data PDU. + * \param txTime Maximum number of microseconds for a Data PDU. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetDataLen(dmConnId_t connId, uint16_t txOctets, uint16_t txTime); + +/*************************************************************************************************/ +/*! + * \fn DmWriteAuthPayloadTimeout + * + * \brief Set authenticated payload timeout for a given connection. + * + * \param connId Connection identifier. + * \param timeout Timeout period in units of 10ms + * + * \return None. + */ +/*************************************************************************************************/ +void DmWriteAuthPayloadTimeout(dmConnId_t connId, uint16_t timeout); + +/*************************************************************************************************/ +/*! + * \fn DmReadPhy + * + * \brief Read the current transmitter PHY and receiver PHY for a given connection. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void DmReadPhy(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSetDefaultPhy + * + * \brief Set the preferred values for the transmitter PHY and receiver PHY for all subsequent + * connections. + * + * \param allPhys All PHYs preferences. + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSetDefaultPhy(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); + +/*************************************************************************************************/ +/*! + * \fn DmSetPhy + * + * \brief Set the PHY preferences for a given connection. + * + * \param connId Connection identifier. + * \param allPhys All PHYs preferences. + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * \param phyOptions PHY options. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSetPhy(dmConnId_t connId, uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys, uint16_t phyOptions); + +/*************************************************************************************************/ +/*! + * \fn DmDevReset + * + * \brief Reset the device. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevReset(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevRole + * + * \brief Return the device role indicating master or slave. + * + * \return Device role. + */ +/*************************************************************************************************/ +uint8_t DmDevRole(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetRandAddr + * + * \brief Set the random address to be used by the local device. + * + * \param pAddr Random address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevSetRandAddr(uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListAdd + * + * \brief Add a peer device to the white list. Note that this function cannot be called + * while advertising, scanning, or connecting with white list filtering active. + * + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListAdd(uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListRemove + * + * \brief Remove a peer device from the white list. Note that this function cannot be called + * while advertising, scanning, or connecting with white list filtering active. + * + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListRemove(uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListClear + * + * \brief Clear the white list. Note that this function cannot be called while + * advertising, scanning, or connecting with white list filtering active. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListClear(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetFilterPolicy + * + * \brief Set the Advertising, Scanning or Initiator filter policy. + * + * \param mode Policy mode. + * \param policy Filter policy. + * + * \return TRUE if the filter policy was successfully set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmDevSetFilterPolicy(uint8_t mode, uint8_t policy); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetExtFilterPolicy + * + * \brief Set the Advertising filter policy for the given advertising, Scanning or Initiator + * filter policy. + * + * \param advHandle Advertising handle. + * \param mode Policy mode. + * \param policy Filter policy. + * + * \return TRUE if the filter policy was successfully set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmDevSetExtFilterPolicy(uint8_t advHandle, uint8_t mode, uint8_t policy); + +/*************************************************************************************************/ +/*! + * \fn DmDevVsInit + * + * \brief Vendor-specific controller initialization function. + * + * \param param Vendor-specific parameter. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevVsInit(uint8_t param); + +/*************************************************************************************************/ +/*! + * \fn DmSecInit + * + * \brief Initialize DM security. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecLescInit + * + * \brief Initialize DM LE Secure Connections security. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecLescInit(void); + +/*************************************************************************************************/ +/*! +* \fn DmPhyInit +* +* \brief Initialize DM PHY. +* +* \return None. +*/ +/*************************************************************************************************/ +void DmPhyInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecPairReq + * + * \brief This function is called by a master device to initiate pairing. + * + * \param connId DM connection ID. + * \param oob Out-of-band pairing data present or not present. + * \param auth Authentication and bonding flags. + * \param iKeyDist Initiator key distribution flags. + * \param rKeyDist Responder key distribution flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecPairReq(dmConnId_t connId, bool_t oob, uint8_t auth, uint8_t iKeyDist, uint8_t rKeyDist); + +/*************************************************************************************************/ +/*! + * \fn DmSecPairRsp + * + * \brief This function is called by a slave device to proceed with pairing after a + * DM_SEC_PAIR_IND event is received. + * + * \param connId DM connection ID. + * \param oob Out-of-band pairing data present or not present. + * \param auth Authentication and bonding flags. + * \param iKeyDist Initiator key distribution flags. + * \param rKeyDist Responder key distribution flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecPairRsp(dmConnId_t connId, bool_t oob, uint8_t auth, uint8_t iKeyDist, uint8_t rKeyDist); + +/*************************************************************************************************/ +/*! + * \fn DmSecCancelReq + * + * \brief This function is called to cancel the pairing process. + * + * \param connId DM connection ID. + * \param reason Failure reason. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecCancelReq(dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmSecAuthRsp + * + * \brief This function is called in response to a DM_SEC_AUTH_REQ_IND event to provide + * PIN or OOB data during pairing. + * + * \param connId DM connection ID. + * \param authDataLen Length of PIN or OOB data. + * \param pAuthData pointer to PIN or OOB data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecAuthRsp(dmConnId_t connId, uint8_t authDataLen, uint8_t *pAuthData); + +/*************************************************************************************************/ +/*! + * \fn DmSecSlaveReq + * + * \brief This function is called by a slave device to request that the master initiates + * pairing or link encryption. + * + * \param connId DM connection ID. + * \param auth Authentication flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSlaveReq(dmConnId_t connId, uint8_t auth); + +/*************************************************************************************************/ +/*! + * \fn DmSecEncryptReq + * + * \brief This function is called by a master device to initiate link encryption. + * + * \param connId DM connection ID. + * \param secLevel Security level of pairing when LTK was exchanged. + * \param pLtk Pointer to LTK parameter structure. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecEncryptReq(dmConnId_t connId, uint8_t secLevel, dmSecLtk_t *pLtk); + +/*************************************************************************************************/ +/*! + * \fn DmSecLtkRsp + * + * \brief This function is called by a slave in response to a DM_SEC_LTK_REQ_IND event + * to provide the long term key used for encryption. + * + * \param connId DM connection ID. + * \param keyFound TRUE if key found. + * \param secLevel Security level of pairing when key was exchanged. + * \param pKey Pointer to the key, if found. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecLtkRsp(dmConnId_t connId, bool_t keyFound, uint8_t secLevel, uint8_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetLocalCsrk + * + * \brief This function sets the local CSRK used by the device. + * + * \param pCsrk Pointer to CSRK. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalCsrk(uint8_t *pCsrk); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetLocalIrk + * + * \brief This function sets the local IRK used by the device. + * + * \param pCsrk Pointer to IRK. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalIrk(uint8_t *pIrk); + +/*************************************************************************************************/ +/*! + * \fn DmPrivInit + * + * \brief Initialize DM privacy module. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmPrivResolveAddr + * + * \brief Resolve a private resolvable address. When complete the client's callback function + * is called with a DM_PRIV_RESOLVED_ADDR_IND event. The client must wait to receive + * this event before executing this function again. + * + * \param pAddr Peer device address. + * \param pIrk The peer's identity resolving key. + * \param param Client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivResolveAddr(uint8_t *pAddr, uint8_t *pIrk, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivAddDevToResList + * + * \brief Add device to resolving list. When complete the client's callback function + * is called with a DM_PRIV_ADD_DEV_TO_RES_LIST_IND event. The client must wait + * to receive this event before executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * Note: If the local or peer IRK associated with the peer Identity Address is all + * zeros then the LL will use or accept the local or peer Identity Address. + * + * Note: 'enableLlPriv' should be set to TRUE when the last device is being added + * to resolving list to enable address resolution in LL. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param pPeerIrk The peer's identity resolving key. + * \param pLocalIrk The local identity resolving key. + * \param enableLlPriv Set to TRUE to enable address resolution in LL. + * \param param client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivAddDevToResList(uint8_t addrType, const uint8_t *pIdentityAddr, uint8_t *pPeerIrk, + uint8_t *pLocalIrk, bool_t enableLlPriv, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivRemDevFromResList + * + * \brief Remove device from resolving list. When complete the client's callback function + * is called with a DM_PRIV_REM_DEV_FROM_RES_LIST_IND event. The client must wait to + * receive this event before executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param param client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivRemDevFromResList(uint8_t addrType, const uint8_t *pIdentityAddr, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivClearResList + * + * \brief Clear resolving list. When complete the client's callback function is called with a + * DM_PRIV_CLEAR_RES_LIST_IND event. The client must wait to receive this event before + * executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * Note: Address resolution in LL will be disabled when resolving list's cleared + * successfully. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivClearResList(void); + +/*************************************************************************************************/ +/*! + * \fn DmPrivReadPeerResolvableAddr + * + * \brief HCI read peer resolvable address command. When complete the client's callback + * function is called with a DM_PRIV_READ_PEER_RES_ADDR_IND event. The client must + * wait to receive this event before executing this function again. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivReadPeerResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); + +/*************************************************************************************************/ +/*! + * \fn DmPrivReadLocalResolvableAddr + * + * \brief Read local resolvable address command. When complete the client's callback + * function is called with a DM_PRIV_READ_LOCAL_RES_ADDR_IND event. The client must + * wait to receive this event before executing this function again. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivReadLocalResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetAddrResEnable + * + * \brief Enable or disable address resolution in LL. When complete the client's callback + * function is called with a DM_PRIV_SET_ADDR_RES_ENABLE_IND event. The client must + * wait to receive this event before executing this function again. + * + * Note: This command can be used at any time except when: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * \param enable Set to TRUE to enable address resolution or FALSE to disable it. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetAddrResEnable(bool_t enable); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetResolvablePrivateAddrTimeout + * + * \brief Set resolvable private address timeout command. + * + * \param rpaTimeout Timeout measured in seconds. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetResolvablePrivateAddrTimeout(uint16_t rpaTimeout); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetPrivacyMode + * + * \brief Set privacy mode for a given entry in the resolving list. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param mode Privacy mode (by default, network privacy mode is used). + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetPrivacyMode(uint8_t addrType, const uint8_t *pIdentityAddr, uint8_t mode); + +/*************************************************************************************************/ +/*! + * \fn DmLlPrivEnabled + * + * \brief Whether LL Privacy is enabled. + * + * \return TRUE if LL Privacy is enabled. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmLlPrivEnabled(void); + +/*************************************************************************************************/ +/*! + * \fn DmLlAddrType + * + * \brief Map an address type to a type used by LL. + * + * \param addrType Address type used by Host. + * + * \return Address type used by LL. + */ +/*************************************************************************************************/ +uint8_t DmLlAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmHostAddrType + * + * \brief Map an address type to a type used by Host. + * + * \param addrType Address type used by LL. + * + * \return Address type used by Host. + */ +/*************************************************************************************************/ +uint8_t DmHostAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmSizeOfEvt + * + * \brief Return size of a DM callback event. + * + * \param pDmEvt DM callback event. + * + * \return Size of DM callback event. + */ +/*************************************************************************************************/ +uint16_t DmSizeOfEvt(dmEvt_t *pDmEvt); + +/*************************************************************************************************/ +/*! + * \fn DmL2cConnUpdateCnf + * + * \brief For internal use only. L2C calls this function to send the result of an L2CAP + * connection update response to DM. + * + * \param handle Connection handle. + * \param reason Connection update response reason code. + * \return None. + */ +/*************************************************************************************************/ +void DmL2cConnUpdateCnf(uint16_t handle, uint16_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmL2cConnUpdateInd + * + * \brief For internal use only. L2C calls this function when it receives a connection update + * request from a peer device. + * + * \param identifier Identifier value. + * \param handle Connection handle. + * \param pConnSpec Connection spec parameters. + * \return None. + */ +/*************************************************************************************************/ +void DmL2cConnUpdateInd(uint8_t identifier, uint16_t handle, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnIdByHandle + * + * \brief For internal use only. Find the connection ID with matching handle. + * + * \param handle Handle to find. + * + * \return Connection ID or DM_CONN_ID_NONE if error. + */ +/*************************************************************************************************/ +dmConnId_t DmConnIdByHandle(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \fn DmConnInUse + * + * \brief For internal use only. Return TRUE if the connection is in use. + * + * \param connId Connection ID. + * + * \return TRUE if the connection is in use, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmConnInUse(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnPeerAddrType + * + * \brief For internal use only. Return the peer address type. + * + * \param connId Connection ID. + * + * \return Peer address type. + */ +/*************************************************************************************************/ +uint8_t DmConnPeerAddrType(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnPeerAddr + * + * \brief For internal use only. Return the peer device address. + * + * \param connId Connection ID. + * + * \return Pointer to peer device address. + */ +/*************************************************************************************************/ +uint8_t *DmConnPeerAddr(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnLocalAddrType + * + * \brief For internal use only. Return the local address type. + * + * \param connId Connection ID. + * + * \return Local address type. + */ +/*************************************************************************************************/ +uint8_t DmConnLocalAddrType(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnLocalAddr + * + * \brief For internal use only. Return the local address. + * + * \param connId Connection ID. + * + * \return Pointer to local address. + */ +/*************************************************************************************************/ +uint8_t *DmConnLocalAddr(dmConnId_t connId); + +/*************************************************************************************************/ +/*! +* \fn DmConnPeerRpa +* +* \brief For internal use only. Return the peer resolvable private address (RPA). +* +* \param connId Connection ID. +* +* \return Pointer to peer RPA. +*/ +/*************************************************************************************************/ +uint8_t *DmConnPeerRpa(dmConnId_t connId); + +/*************************************************************************************************/ +/*! +* \fn DmConnLocalRpa +* +* \brief For internal use only. Return the local resolvable private address (RPA). +* +* \param connId Connection ID. +* +* \return Pointer to local RPA. +*/ +/*************************************************************************************************/ +uint8_t *DmConnLocalRpa(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnSecLevel + * + * \brief For internal use only. Return the security level of the connection. + * + * \param connId Connection ID. + * + * \return Security level of the connection. + */ +/*************************************************************************************************/ +uint8_t DmConnSecLevel(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSmpEncryptReq + * + * \brief For internal use only. This function is called by SMP to request encryption. + * + * \param connId DM connection ID. + * \param secLevel Security level of pairing when key was exchanged. + * \param pKey Pointer to key. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSmpEncryptReq(dmConnId_t connId, uint8_t secLevel, uint8_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSmpCbackExec + * + * \brief For internal use only. Execute DM callback from SMP procedures. + * + * \param pDmEvt Pointer to callback event data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSmpCbackExec(dmEvt_t *pDmEvt); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetLocalCsrk + * + * \brief For internal use only. This function gets the local CSRK used by the device. + * + * \return Pointer to CSRK. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalCsrk(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetLocalIrk + * + * \brief For internal use only. This function gets the local IRK used by the device. + * + * \return Pointer to IRK. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalIrk(void); + +/*************************************************************************************************/ +/*! + * \fn DmReadRemoteFeatures + * + * \brief For internal use only. Read the features of the remote device. + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmReadRemoteFeatures(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSecGenerateEccKeyReq + * + * \brief This function generates an ECC key for use with LESC security. + * + * \return none. + */ +/*************************************************************************************************/ +void DmSecGenerateEccKeyReq(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetEccKey + * + * \brief This function sets the ECC key for use with LESC security. + * + * \param pKey Pointer to key. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetEccKey(secEccKey_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetEccKey + * + * \brief This function gets the local ECC key for use with LESC security. + * + * \return Pointer to local ECC key. + */ +/*************************************************************************************************/ +secEccKey_t *DmSecGetEccKey(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetDebugEccKey + * + * \brief This function sets the ECC key for use with LESC security to standard debug keys values. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetDebugEccKey(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetOob + * + * \brief This function configures the DM to use OOB pairing for the given connection. + * The pRand and pConfirm contain the Random and Confirm values exchanged via + * out of band methods. + * + * \param connId ID of the connection + * \param pConfig Pointer to OOB configuration. + * + * \return Pointer to IRK. + */ +/*************************************************************************************************/ +void DmSecSetOob(dmConnId_t connId, dmSecLescOobCfg_t *pConfig); + +/*************************************************************************************************/ +/*! + * \fn DmSecCalcOobReq + * + * \brief This function calculates the local random and confirm values used in LESC OOB pairing. + * The operation's result is posted as a DM_SEC_CALC_OOB_IND event to the application's DM + * callback handler. The local rand and confirm values are exchanged with the peer via + * out-of-band (OOB) methods and passed into the DmSecSetOob after DM_CONN_OPEN_IND. + * + * \param pRand Random value used in calculation. + * \param pPubKeyX X component of the local public key. + * + * \return none. + */ +/*************************************************************************************************/ +void DmSecCalcOobReq(uint8_t *pRand, uint8_t *pPubKeyX); + +/*************************************************************************************************/ +/*! + * \fn DmSecCompareRsp + * + * \brief This function is called by the application in response to a DM_SEC_COMPARE_IND event. + * The valid parameter indicates if the compare value of the DM_SEC_COMPARE_IND was valid. + * + * \param connId ID of the connection + * \param valid TRUE if compare value was valid + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecCompareRsp(dmConnId_t connId, bool_t valid); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetCompareValue + * + * \brief This function returns the 6-digit compare value for the specified 128-bit confirm value. + * + * \param pConfirm Pointer to 128-bit comfirm value. + * + * \return Six-digit compare value. + */ +/*************************************************************************************************/ +uint32_t DmSecGetCompareValue(uint8_t *pConfirm); + +#ifdef __cplusplus +}; +#endif + +#endif /* DM_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h new file mode 100644 index 00000000000..650ecb06461 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file dm_handler.h + * + * \brief Interface to DM event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef DM_HANDLER_H +#define DM_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn DmHandlerInit + * + * \brief DM handler init function called during system initialization. + * + * \param handlerID WSF handler ID for DM. + * + * \return None. + */ +/*************************************************************************************************/ +void DmHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn DmHandler + * + * \brief WSF event handler for DM. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void DmHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* DM_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h new file mode 100644 index 00000000000..30ea3c099bd --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h @@ -0,0 +1,837 @@ +/*************************************************************************************************/ +/*! + * \file hci_api.h + * + * \brief HCI subsystem API. + * + * $Date: 2017-02-09 11:58:21 -0600 (Thu, 09 Feb 2017) $ + * $Revision: 11135 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_API_H +#define HCI_API_H + +#include "wsf_types.h" +#include "hci_defs.h" +#include "wsf_os.h" +#include "bda.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Internal event values for the HCI event and sec callbacks */ +#define HCI_RESET_SEQ_CMPL_CBACK_EVT 0 /*! Reset sequence complete */ +#define HCI_LE_CONN_CMPL_CBACK_EVT 1 /*! LE connection complete */ +#define HCI_LE_ENHANCED_CONN_CMPL_CBACK_EVT 2 /*! LE enhanced connection complete */ +#define HCI_DISCONNECT_CMPL_CBACK_EVT 3 /*! LE disconnect complete */ +#define HCI_LE_CONN_UPDATE_CMPL_CBACK_EVT 4 /*! LE connection update complete */ +#define HCI_LE_CREATE_CONN_CANCEL_CMD_CMPL_CBACK_EVT 5 /*! LE create connection cancel command complete */ +#define HCI_LE_ADV_REPORT_CBACK_EVT 6 /*! LE advertising report */ +#define HCI_READ_RSSI_CMD_CMPL_CBACK_EVT 7 /*! Read RSSI command complete */ +#define HCI_LE_READ_CHAN_MAP_CMD_CMPL_CBACK_EVT 8 /*! LE Read channel map command complete */ +#define HCI_READ_TX_PWR_LVL_CMD_CMPL_CBACK_EVT 9 /*! Read transmit power level command complete */ +#define HCI_READ_REMOTE_VER_INFO_CMPL_CBACK_EVT 10 /*! Read remote version information complete */ +#define HCI_LE_READ_REMOTE_FEAT_CMPL_CBACK_EVT 11 /*! LE read remote features complete */ +#define HCI_LE_LTK_REQ_REPL_CMD_CMPL_CBACK_EVT 12 /*! LE LTK request reply command complete */ +#define HCI_LE_LTK_REQ_NEG_REPL_CMD_CMPL_CBACK_EVT 13 /*! LE LTK request negative reply command complete */ +#define HCI_ENC_KEY_REFRESH_CMPL_CBACK_EVT 14 /*! Encryption key refresh complete */ +#define HCI_ENC_CHANGE_CBACK_EVT 15 /*! Encryption change */ +#define HCI_LE_LTK_REQ_CBACK_EVT 16 /*! LE LTK request */ +#define HCI_VENDOR_SPEC_CMD_STATUS_CBACK_EVT 17 /*! Vendor specific command status */ +#define HCI_VENDOR_SPEC_CMD_CMPL_CBACK_EVT 18 /*! Vendor specific command complete */ +#define HCI_VENDOR_SPEC_CBACK_EVT 19 /*! Vendor specific */ +#define HCI_HW_ERROR_CBACK_EVT 20 /*! Hardware error */ +#define HCI_LE_ADD_DEV_TO_RES_LIST_CMD_CMPL_CBACK_EVT 21 /*! LE add device to resolving list command complete */ +#define HCI_LE_REM_DEV_FROM_RES_LIST_CMD_CMPL_CBACK_EVT 22 /*! LE remove device from resolving command complete */ +#define HCI_LE_CLEAR_RES_LIST_CMD_CMPL_CBACK_EVT 23 /*! LE clear resolving list command complete */ +#define HCI_LE_READ_PEER_RES_ADDR_CMD_CMPL_CBACK_EVT 24 /*! LE read peer resolving address command complete */ +#define HCI_LE_READ_LOCAL_RES_ADDR_CMD_CMPL_CBACK_EVT 25 /*! LE read local resolving address command complete */ +#define HCI_LE_SET_ADDR_RES_ENABLE_CMD_CMPL_CBACK_EVT 26 /*! LE set address resolving enable command complete */ +#define HCI_LE_ENCRYPT_CMD_CMPL_CBACK_EVT 27 /*! LE encrypt command complete */ +#define HCI_LE_RAND_CMD_CMPL_CBACK_EVT 28 /*! LE rand command complete */ +#define HCI_LE_REM_CONN_PARAM_REP_CMD_CMPL_CBACK_EVT 29 /*! LE remote connection parameter request reply complete */ +#define HCI_LE_REM_CONN_PARAM_NEG_REP_CMD_CMPL_CBACK_EVT 30 /*! LE remote connection parameter request negative reply complete */ +#define HCI_LE_READ_DEF_DATA_LEN_CMD_CMPL_CBACK_EVT 31 /*! LE read suggested default data length command complete */ +#define HCI_LE_WRITE_DEF_DATA_LEN_CMD_CMPL_CBACK_EVT 32 /*! LE write suggested default data length command complete */ +#define HCI_LE_SET_DATA_LEN_CMD_CMPL_CBACK_EVT 33 /*! LE set data length command complete */ +#define HCI_LE_READ_MAX_DATA_LEN_CMD_CMPL_CBACK_EVT 34 /*! LE read maximum data length command complete */ +#define HCI_LE_REM_CONN_PARAM_REQ_CBACK_EVT 35 /*! LE remote connection parameter request */ +#define HCI_LE_DATA_LEN_CHANGE_CBACK_EVT 36 /*! LE data length change */ +#define HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_CBACK_EVT 37 /*! LE read local P-256 public key */ +#define HCI_LE_GENERATE_DHKEY_CMPL_CBACK_EVT 38 /*! LE generate DHKey complete */ +#define HCI_WRITE_AUTH_PAYLOAD_TO_CMD_CMPL_CBACK_EVT 39 /*! Write authenticated payload timeout command complete */ +#define HCI_AUTH_PAYLOAD_TO_EXPIRED_CBACK_EVT 40 /*! Authenticated payload timeout expired event */ +#define HCI_LE_READ_PHY_CMD_CMPL_CBACK_EVT 41 /*! LE read phy command complete */ +#define HCI_LE_SET_DEF_PHY_CMD_CMPL_CBACK_EVT 42 /*! LE set default phy command complete */ +#define HCI_LE_PHY_UPDATE_CMPL_CBACK_EVT 43 /*! LE phy update complete */ +#define HCI_LE_EXT_ADV_REPORT_CBACK_EVT 44 /*! LE extended advertising report */ +#define HCI_LE_SCAN_TIMEOUT_CBACK_EVT 45 /*! LE scan timeout event */ +#define HCI_LE_ADV_SET_TERM_CBACK_EVT 46 /*! LE advertising set terminated event */ +#define HCI_LE_SCAN_REQ_RCVD_CBACK_EVT 47 /*! LE scan request received event */ +#define HCI_LE_PER_ADV_SYNC_EST_CBACK_EVT 48 /*! LE periodic advertising sync established event */ +#define HCI_LE_PER_ADV_REPORT_CBACK_EVT 49 /*! LE periodic advertising report event */ +#define HCI_LE_PER_ADV_SYNC_LOST_CBACK_EVT 50 /*! LE periodic advertising synch lost event */ +#define HCI_LE_CH_SEL_ALGO_CBACK_EVT 51 /*! LE channel selection algorithm event */ +#define HCI_LE_SCAN_ENABLE_CMPL_CBACK_EVT 52 /*! LE scan enable complete event */ +#define HCI_LE_ADV_ENABLE_CMPL_CBACK_EVT 53 /*! LE advertise enable complete event */ +#define HCI_LE_EXT_SCAN_ENABLE_CMPL_CBACK_EVT 54 /*! LE extended scan enable complete event */ +#define HCI_LE_EXT_ADV_ENABLE_CMPL_CBACK_EVT 55 /*! LE extended advertise enable complete event */ +#define HCI_LE_PER_ADV_ENABLE_CMPL_CBACK_EVT 56 /*! LE periodic advertise enable complete event */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection specification type */ +typedef struct +{ + uint16_t connIntervalMin; /*!< Minimum connection interval. */ + uint16_t connIntervalMax; /*!< Maximum connection interval. */ + uint16_t connLatency; /*!< Connection latency. */ + uint16_t supTimeout; /*!< Supervision timeout. */ + uint16_t minCeLen; /*!< Minimum CE length. */ + uint16_t maxCeLen; /*!< Maximum CE length. */ +} hciConnSpec_t; + +/*! Initiating parameters */ +typedef struct +{ + uint8_t filterPolicy; /*!< Scan filter policy. */ + uint8_t ownAddrType; /*!< Address type used by this device. */ + uint8_t peerAddrType; /*!< Address type used for peer device. */ + const uint8_t *pPeerAddr; /*!< Address of peer device. */ + uint8_t initPhys; /*!< Initiating PHYs. */ +} hciExtInitParam_t; + +/*! Initiating scan parameters */ +typedef struct +{ + uint16_t scanInterval; /*! Scan interval. */ + uint16_t scanWindow; /*! Scan window. */ +} hciExtInitScanParam_t; + +/*! Extended advertising parameters */ +typedef struct +{ + uint16_t advEventProp; /*! Advertising Event Properties. */ + uint32_t priAdvInterMin; /*! Primary Advertising Interval Minimum. */ + uint32_t priAdvInterMax; /*! Primary Advertising Interval Maximum. */ + uint8_t priAdvChanMap; /*! Primary Advertising Channel Map. */ + uint8_t ownAddrType; /*! Own Address Type. */ + uint8_t peerAddrType; /*! Peer Address Type. */ + uint8_t *pPeerAddr; /*! Peer Address. */ + uint8_t advFiltPolicy; /*! Advertising Filter Policy. */ + int8_t advTxPwr; /*! Advertising Tx Power. */ + uint8_t priAdvPhy; /*! Primary Advertising PHY. */ + uint8_t secAdvMaxSkip; /*! Secondary Advertising Maximum Skip. */ + uint8_t secAdvPhy; /*! Secondary Advertising PHY. */ + uint8_t advSetId; /*! Advertising set ID. */ + uint8_t scanReqNotifEna; /*! Scan Request Notification Enable. */ +} hciExtAdvParam_t; + +/*! Extended advertising enable parameters */ +typedef struct +{ + uint8_t advHandle; /*! Advertising handle. */ + uint16_t duration; /*! Advertising duration in 10 ms units. */ + uint8_t maxEaEvents; /*! Maximum number of extended advertising events. */ +} hciExtAdvEnableParam_t; + +/*! Extended scanning parameters */ +typedef struct +{ + uint16_t scanInterval; /*! Scan interval. */ + uint16_t scanWindow; /*! Scan window. */ + uint8_t scanType; /*! Scan type. */ +} hciExtScanParam_t; + +/*! LE connection complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t role; + uint8_t addrType; + bdAddr_t peerAddr; + uint16_t connInterval; + uint16_t connLatency; + uint16_t supTimeout; + uint8_t clockAccuracy; + + /* enhanced fields */ + bdAddr_t localRpa; + bdAddr_t peerRpa; +} hciLeConnCmplEvt_t; + +/*! Disconnect complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t reason; +} hciDisconnectCmplEvt_t; + +/*! LE connection update complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint16_t connInterval; + uint16_t connLatency; + uint16_t supTimeout; +} hciLeConnUpdateCmplEvt_t; + +/*! LE create connection cancel command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeCreateConnCancelCmdCmplEvt_t; + +/*! LE advertising report event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t *pData; + uint8_t len; + int8_t rssi; + uint8_t eventType; + uint8_t addrType; + bdAddr_t addr; + + /* direct fields */ + uint8_t directAddrType; + bdAddr_t directAddr; +} hciLeAdvReportEvt_t; + +/*! LE extended advertising report */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t eventType; /*!< Event type. */ + uint8_t addrType; /*!< Address type. */ + bdAddr_t addr; /*!< Address. */ + uint8_t priPhy; /*!< Primary PHY. */ + uint8_t secPhy; /*!< Secondary PHY. */ + uint8_t advSid; /*!< Advertising SID. */ + int8_t txPower; /*!< Tx Power. */ + int8_t rssi; /*!< RSSI. */ + int16_t perAdvInter; /*!< Periodic advertising interval. */ + uint8_t directAddrType; /*!< Directed address type. */ + bdAddr_t directAddr; /*!< Directed address. */ + uint8_t len; /*!< Data buffer length. */ + uint8_t *pData; /*!< Data buffer. */ +} hciLeExtAdvReportEvt_t; + +/*! LE scan timeout */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ +} hciLeScanTimeoutEvt_t; + +/*! LE advertising set terminated */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint8_t advHandle; /*!< Advertising handle. */ + uint16_t handle; /*!< Connection handle. */ + uint8_t numComplEvts; /*!< Number of completed extended advertising events. */ +} hciLeAdvSetTermEvt_t; + +/*! LE scan request received */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t advHandle; /*!< Advertising handle. */ + uint8_t scanAddrType; /*!< Scanner address type. */ + bdAddr_t scanAddr; /*!< Scanner address. */ +} hciLeScanReqRcvdEvt_t; + +/*! LE periodic advertising sync established */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint16_t syncHandle; /*!< Sync handle. */ + uint8_t advSid; /*!< Advertising SID. */ + uint8_t advAddrType; /*!< Advertiser address type. */ + bdAddr_t advAddr; /*!< Advertiser address. */ + uint8_t advPhy; /*!< Advertiser PHY. */ + uint16_t perAdvInterval; /*!< Periodic advertising interval. */ + uint8_t clockAccuracy; /*!< Advertiser clock accuracy. */ +} hciLePerAdvSyncEstEvt_t; + +/*! LE periodic advertising report */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle. */ + uint8_t txPower; /*!< Tx power. */ + uint8_t rssi; /*!< RSSI. */ + uint8_t unused; /*!< Intended to be used in a future feature. */ + uint8_t status; /*!< Data status. */ + uint8_t len; /*!< Data buffer length. */ + uint8_t *pData; /*!< Data buffer. */ +} hciLePerAdvReportEvt_t; + +/*! LE periodic advertising synch lost */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle. */ +} hciLePerAdvSyncLostEvt_t; + +/*! LE channel selection algorithm */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t handle; /*!< Connection handle. */ + uint8_t chSelAlgo; /*!< Channel selection algorithm */ +} hciLeChSelAlgoEvt_t; + +/*! Read RSSI command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + int8_t rssi; +} hciReadRssiCmdCmplEvt_t; + +/*! LE Read channel map command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t chanMap[HCI_CHAN_MAP_LEN]; +} hciReadChanMapCmdCmplEvt_t; + +/*! Read transmit power level command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t handle; + int8_t pwrLvl; +} hciReadTxPwrLvlCmdCmplEvt_t; + +/*! Read remote version information complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t version; + uint16_t mfrName; + uint16_t subversion; +} hciReadRemoteVerInfoCmplEvt_t; + +/*! LE read remote features complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t features[HCI_FEAT_LEN]; +} hciLeReadRemoteFeatCmplEvt_t; + +/*! LE LTK request reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeLtkReqReplCmdCmplEvt_t; + +/*! LE LTK request negative reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeLtkReqNegReplCmdCmplEvt_t; + +/*! Encryption key refresh complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciEncKeyRefreshCmpl_t; + +/*! Encryption change event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t enabled; +} hciEncChangeEvt_t; + +/*! LE LTK request event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint8_t randNum[HCI_RAND_LEN]; + uint16_t encDiversifier; +} hciLeLtkReqEvt_t; + +/*! Vendor specific command status event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t opcode; +} hciVendorSpecCmdStatusEvt_t; + +/*! Vendor specific command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t opcode; + uint8_t param[1]; +} hciVendorSpecCmdCmplEvt_t; + +/*! Vendor specific event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t param[1]; +} hciVendorSpecEvt_t; + +/*! Hardware error event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t code; +} hciHwErrorEvt_t; + +/*! LE encrypt command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t data[HCI_ENCRYPT_DATA_LEN]; +} hciLeEncryptCmdCmplEvt_t; + +/*! LE rand command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t randNum[HCI_RAND_LEN]; +} hciLeRandCmdCmplEvt_t; + +/*! LE remote connection parameter request reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeRemConnParamRepEvt_t; + +/*! LE remote connection parameter request negative reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeRemConnParamNegRepEvt_t; + +/*! LE read suggested default data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t suggestedMaxTxOctets; + uint16_t suggestedMaxTxTime; +} hciLeReadDefDataLenEvt_t; + +/*! LE write suggested default data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeWriteDefDataLenEvt_t; + +/*! LE set data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeSetDataLenEvt_t; + +/*! LE read maximum data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t supportedMaxTxOctets; + uint16_t supportedMaxTxTime; + uint16_t supportedMaxRxOctets; + uint16_t supportedMaxRxTime; +} hciLeReadMaxDataLenEvt_t; + +/*! LE remote connetion parameter request event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint16_t intervalMin; + uint16_t intervalMax; + uint16_t latency; + uint16_t timeout; +} hciLeRemConnParamReqEvt_t; + +/*! LE data length change event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint16_t maxTxOctets; + uint16_t maxTxTime; + uint16_t maxRxOctets; + uint16_t maxRxTime; +} hciLeDataLenChangeEvt_t; + +/*! LE local p256 ecc key command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t key[HCI_P256_KEY_LEN]; +} hciLeP256CmplEvt_t; + +/*! LE generate DH key command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t key[HCI_DH_KEY_LEN]; +} hciLeGenDhKeyEvt_t; + +/*! LE read peer resolving address command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t peerRpa[BDA_ADDR_LEN]; +} hciLeReadPeerResAddrCmdCmplEvt_t; + +/*! LE read local resolving address command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t localRpa[BDA_ADDR_LEN]; +} hciLeReadLocalResAddrCmdCmplEvt_t; + +/*! LE set address resolving enable command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeSetAddrResEnableCmdCmplEvt_t; + +/*! LE add device to resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeAddDevToResListCmdCmplEvt_t; + +/*! LE remove device from resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeRemDevFromResListCmdCmplEvt_t; + +/*! LE clear resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeClearResListCmdCmplEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciWriteAuthPayloadToCmdCmplEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; +} hciAuthPayloadToExpiredEvt_t; + +/*! LE read PHY command complete event */ + typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t txPhy; + uint8_t rxPhy; +} hciLeReadPhyCmdCmplEvt_t; + +/*! LE set default PHY command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeSetDefPhyCmdCmplEvt_t; + +/*! LE PHY update complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t txPhy; + uint8_t rxPhy; +} hciLePhyUpdateEvt_t; + +/*! Union of all event types */ +typedef union +{ + wsfMsgHdr_t hdr; + wsfMsgHdr_t resetSeqCmpl; + hciLeConnCmplEvt_t leConnCmpl; + hciDisconnectCmplEvt_t disconnectCmpl; + hciLeConnUpdateCmplEvt_t leConnUpdateCmpl; + hciLeCreateConnCancelCmdCmplEvt_t leCreateConnCancelCmdCmpl; + hciLeAdvReportEvt_t leAdvReport; + hciReadRssiCmdCmplEvt_t readRssiCmdCmpl; + hciReadChanMapCmdCmplEvt_t readChanMapCmdCmpl; + hciReadTxPwrLvlCmdCmplEvt_t readTxPwrLvlCmdCmpl; + hciReadRemoteVerInfoCmplEvt_t readRemoteVerInfoCmpl; + hciLeReadRemoteFeatCmplEvt_t leReadRemoteFeatCmpl; + hciLeLtkReqReplCmdCmplEvt_t leLtkReqReplCmdCmpl; + hciLeLtkReqNegReplCmdCmplEvt_t leLtkReqNegReplCmdCmpl; + hciEncKeyRefreshCmpl_t encKeyRefreshCmpl; + hciEncChangeEvt_t encChange; + hciLeLtkReqEvt_t leLtkReq; + hciVendorSpecCmdStatusEvt_t vendorSpecCmdStatus; + hciVendorSpecCmdCmplEvt_t vendorSpecCmdCmpl; + hciVendorSpecEvt_t vendorSpec; + hciHwErrorEvt_t hwError; + hciLeEncryptCmdCmplEvt_t leEncryptCmdCmpl; + hciLeRandCmdCmplEvt_t leRandCmdCmpl; + hciLeReadPeerResAddrCmdCmplEvt_t leReadPeerResAddrCmdCmpl; + hciLeReadLocalResAddrCmdCmplEvt_t leReadLocalResAddrCmdCmpl; + hciLeSetAddrResEnableCmdCmplEvt_t leSetAddrResEnableCmdCmpl; + hciLeAddDevToResListCmdCmplEvt_t leAddDevToResListCmdCmpl; + hciLeRemDevFromResListCmdCmplEvt_t leRemDevFromResListCmdCmpl; + hciLeClearResListCmdCmplEvt_t leClearResListCmdCmpl; + hciLeRemConnParamRepEvt_t leRemConnParamRepCmdCmpl; + hciLeRemConnParamNegRepEvt_t leRemConnParamNegRepCmdCmpl; + hciLeReadDefDataLenEvt_t leReadDefDataLenCmdCmpl; + hciLeWriteDefDataLenEvt_t leWriteDefDataLenCmdCmpl; + hciLeSetDataLenEvt_t leSetDataLenCmdCmpl; + hciLeReadMaxDataLenEvt_t leReadMaxDataLenCmdCmpl; + hciLeRemConnParamReqEvt_t leRemConnParamReq; + hciLeDataLenChangeEvt_t leDataLenChange; + hciLeP256CmplEvt_t leP256; + hciLeGenDhKeyEvt_t leGenDHKey; + hciWriteAuthPayloadToCmdCmplEvt_t writeAuthPayloadToCmdCmpl; + hciAuthPayloadToExpiredEvt_t authPayloadToExpired; + hciLeReadPhyCmdCmplEvt_t leReadPhyCmdCmpl; + hciLeSetDefPhyCmdCmplEvt_t leSetDefPhyCmdCmpl; + hciLePhyUpdateEvt_t lePhyUpdate; + hciLeExtAdvReportEvt_t leExtAdvReport; + hciLeScanTimeoutEvt_t leScanTimeout; + hciLeAdvSetTermEvt_t leAdvSetTerm; + hciLeScanReqRcvdEvt_t leScanReqRcvd; + hciLePerAdvSyncEstEvt_t lePerAdvSyncEst; + hciLePerAdvReportEvt_t lePerAdvReport; + hciLePerAdvSyncLostEvt_t lePerAdvSyncLost; + hciLeChSelAlgoEvt_t leChSelAlgo; +} hciEvt_t; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +typedef void (*hciEvtCback_t)(hciEvt_t *pEvent); +typedef void (*hciSecCback_t)(hciEvt_t *pEvent); +typedef void (*hciAclCback_t)(uint8_t *pData); +typedef void (*hciFlowCback_t)(uint16_t handle, bool_t flowDisabled); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*! Initialization, registration, and reset */ +void HciEvtRegister(hciEvtCback_t evtCback); +void HciSecRegister(hciSecCback_t secCback); +void HciAclRegister(hciAclCback_t aclCback, hciFlowCback_t flowCback); +void HciResetSequence(void); +void HciVsInit(uint8_t param); +void HciCoreInit(void); +void HciCoreHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); +void HciSetMaxRxAclLen(uint16_t len); +void HciSetAclQueueWatermarks(uint8_t queueHi, uint8_t queueLo); +void HciSetLeSupFeat(uint16_t feat, bool_t flag); + +/*! Optimization interface */ +uint8_t *HciGetBdAddr(void); +uint8_t HciGetWhiteListSize(void); +int8_t HciGetAdvTxPwr(void); +uint16_t HciGetBufSize(void); +uint8_t HciGetNumBufs(void); +uint8_t *HciGetSupStates(void); +uint16_t HciGetLeSupFeat(void); +uint16_t HciGetMaxRxAclLen(void); +uint8_t HciGetResolvingListSize(void); +bool_t HciLlPrivacySupported(void); +uint16_t HciGetMaxAdvDataLen(void); +uint8_t HciGetNumSupAdvSets(void); +bool_t HciLeAdvExtSupported(void); +uint8_t HciGetPerAdvListSize(void); + +/*! ACL data interface */ +void HciSendAclData(uint8_t *pAclData); + +/*! Command interface */ +void HciDisconnectCmd(uint16_t handle, uint8_t reason); +void HciLeAddDevWhiteListCmd(uint8_t addrType, uint8_t *pAddr); +void HciLeClearWhiteListCmd(void); +void HciLeConnUpdateCmd(uint16_t handle, hciConnSpec_t *pConnSpec); +void HciLeCreateConnCmd(uint16_t scanInterval, uint16_t scanWindow, uint8_t filterPolicy, + uint8_t peerAddrType, uint8_t *pPeerAddr, uint8_t ownAddrType, + hciConnSpec_t *pConnSpec); +void HciLeCreateConnCancelCmd(void); +void HciLeEncryptCmd(uint8_t *pKey, uint8_t *pData); +void HciLeLtkReqNegReplCmd(uint16_t handle); +void HciLeLtkReqReplCmd(uint16_t handle, uint8_t *pKey); +void HciLeRandCmd(void); +void HciLeReadAdvTXPowerCmd(void); +void HciLeReadBufSizeCmd(void); +void HciLeReadChanMapCmd(uint16_t handle); +void HciLeReadLocalSupFeatCmd(void); +void HciLeReadRemoteFeatCmd(uint16_t handle); +void HciLeReadSupStatesCmd(void); +void HciLeReadWhiteListSizeCmd(void); +void HciLeRemoveDevWhiteListCmd(uint8_t addrType, uint8_t *pAddr); +void HciLeSetAdvEnableCmd(uint8_t enable); +void HciLeSetAdvDataCmd(uint8_t len, uint8_t *pData); +void HciLeSetAdvParamCmd(uint16_t advIntervalMin, uint16_t advIntervalMax, uint8_t advType, + uint8_t ownAddrType, uint8_t peerAddrType, uint8_t *pPeerAddr, + uint8_t advChanMap, uint8_t advFiltPolicy); +void HciLeSetEventMaskCmd(uint8_t *pLeEventMask); +void HciLeSetHostChanClassCmd(uint8_t *pChanMap); +void HciLeSetRandAddrCmd(uint8_t *pAddr); +void HciLeSetScanEnableCmd(uint8_t enable, uint8_t filterDup); +void HciLeSetScanParamCmd(uint8_t scanType, uint16_t scanInterval, uint16_t scanWindow, + uint8_t ownAddrType, uint8_t scanFiltPolicy); +void HciLeSetScanRespDataCmd(uint8_t len, uint8_t *pData); +void HciLeStartEncryptionCmd(uint16_t handle, uint8_t *pRand, uint16_t diversifier, uint8_t *pKey); +void HciReadBdAddrCmd(void); +void HciReadBufSizeCmd(void); +void HciReadLocalSupFeatCmd(void); +void HciReadLocalVerInfoCmd(void); +void HciReadRemoteVerInfoCmd(uint16_t handle); +void HciReadRssiCmd(uint16_t handle); +void HciReadTxPwrLvlCmd(uint16_t handle, uint8_t type); +void HciResetCmd(void); +void HciSetEventMaskCmd(uint8_t *pEventMask); +void HciSetEventMaskPage2Cmd(uint8_t *pEventMask); +void HciReadAuthPayloadTimeout(uint16_t handle); +void HciWriteAuthPayloadTimeout(uint16_t handle, uint16_t timeout); +void HciLeAddDeviceToResolvingListCmd(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr, + const uint8_t *pPeerIrk, const uint8_t *pLocalIrk); +void HciLeRemoveDeviceFromResolvingList(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr); +void HciLeClearResolvingList(void); +void HciLeReadResolvingListSize(void); +void HciLeReadPeerResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); +void HciLeReadLocalResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); +void HciLeSetAddrResolutionEnable(uint8_t enable); +void HciLeSetResolvablePrivateAddrTimeout(uint16_t rpaTimeout); +void HciLeSetPrivacyModeCmd(uint8_t addrType, uint8_t *pAddr, uint8_t mode); +void HciLeReadPhyCmd(uint16_t handle); +void HciLeSetDefaultPhyCmd(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); +void HciLeSetPhyCmd(uint16_t handle, uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys, uint16_t phyOptions); +void HciVendorSpecificCmd(uint16_t opcode, uint8_t len, uint8_t *pData); + +void HciLeRemoteConnParamReqReply(uint16_t handle, uint16_t intervalMin, uint16_t intervalMax, uint16_t latency, + uint16_t timeout, uint16_t minCeLen, uint16_t maxCeLen); +void HciLeRemoteConnParamReqNegReply(uint16_t handle, uint8_t reason); +void HciLeSetDataLen(uint16_t handle, uint16_t txOctets, uint16_t txTime); +void HciLeReadDefDataLen(void); +void HciLeWriteDefDataLen(uint16_t suggestedMaxTxOctets, uint16_t suggestedMaxTxTime); +void HciLeReadLocalP256PubKey(void); +void HciLeGenerateDHKey(uint8_t *pPubKeyX, uint8_t *pPubKeyY); +void HciLeReadMaxDataLen(void); +void HciWriteAuthPayloadTimeout(uint16_t handle, uint16_t timeout); + +/* AE slave interface */ +void HciLeSetAdvSetRandAddrCmd(uint8_t advHandle, const uint8_t *pAddr); +void HciLeSetExtAdvParamCmd(uint8_t advHandle, hciExtAdvParam_t *pExtAdvParam); +void HciLeSetExtAdvDataCmd(uint8_t advHandle, uint8_t op, uint8_t fragPref, uint8_t len, + const uint8_t *pData); +void HciLeSetExtScanRespDataCmd(uint8_t advHandle, uint8_t op, uint8_t fragPref, uint8_t len, + const uint8_t *pData); +void HciLeSetExtAdvEnableCmd(uint8_t enable, uint8_t numSets, hciExtAdvEnableParam_t *pEnableParam); +void HciLeReadMaxAdvDataLen(void); +void HciLeReadNumSupAdvSets(void); +void HciLeRemoveAdvSet(uint8_t advHandle); +void HciLeClearAdvSets(void); +void HciLeSetPerAdvParamCmd(uint8_t advHandle, uint16_t advIntervalMin, uint16_t advIntervalMax, + uint16_t advProps); +void HciLeSetPerAdvDataCmd(uint8_t advHandle, uint8_t op, uint8_t len, const uint8_t *pData); +void HciLeSetPerAdvEnableCmd(uint8_t enable, uint8_t advHandle); + +/* AE master interface */ +void HciLeSetExtScanParamCmd(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t scanPhys, + hciExtScanParam_t *pScanParam); +void HciLeExtScanEnableCmd(uint8_t enable, uint8_t filterDup, uint16_t duration, uint16_t period); +void HciLeExtCreateConnCmd(hciExtInitParam_t *pInitParam, hciExtInitScanParam_t *pScanParam, + hciConnSpec_t *pConnSpec); +void HciLePerAdvCreateSyncCmd(uint8_t filterPolicy, uint8_t advSid, uint8_t advAddrType, + const uint8_t *pAdvAddr, uint16_t skip, uint16_t syncTimeout, uint8_t unused); +void HciLePerAdvCreateSyncCancelCmd(void); +void HciLePerAdvTerminateSyncCmd(uint16_t syncHandle); +void HciLeAddDeviceToPerAdvListCmd(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); +void HciLeRemoveDeviceFromPerAdvListCmd(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); +void HciLeClearPerAdvListCmd(void); +void HciLeReadPerAdvListSizeCmd(void); + +/* AE common interface */ +void HciVsAeInit(uint8_t param); +void HciLeReadTxPower(void); +void HciLeReadRfPathComp(void); +void HciLeWriteRfPathComp(int16_t txPathComp, int16_t rxPathComp); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h new file mode 100644 index 00000000000..4b7f6bad624 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file hci_handler.h + * + * \brief Interface to HCI event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_HANDLER_H +#define HCI_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn HciHandlerInit + * + * \brief HCI handler init function called during system initialization. + * + * \param handlerID WSF handler ID for HCI. + * + * \return None. + */ +/*************************************************************************************************/ +void HciHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn HciHandler + * + * \brief WSF event handler for HCI. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void HciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h new file mode 100644 index 00000000000..006791edfae --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h @@ -0,0 +1,431 @@ +/*************************************************************************************************/ +/*! + * \file l2c_api.h + * + * \brief L2CAP subsystem API. + * + * $Date: 2017-03-21 16:36:53 -0500 (Tue, 21 Mar 2017) $ + * $Revision: 11626 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_API_H +#define L2C_API_H + +#include "dm_api.h" +#include "l2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Control callback message events */ +#define L2C_CTRL_FLOW_ENABLE_IND 0 /*! Data flow enabled */ +#define L2C_CTRL_FLOW_DISABLE_IND 1 /*! Data flow disabled */ + +/*! Invalid channel registration ID for connection oriented channels */ +#define L2C_COC_REG_ID_NONE 0 + +/*! Invalid channel ID for connection oriented channels */ +#define L2C_COC_CID_NONE 0 + +/*! Connection oriented channel initiator/acceptor role */ +#define L2C_COC_ROLE_NONE 0x00 /*! No role (unallocated) */ +#define L2C_COC_ROLE_INITIATOR 0x01 /*! Channel initiator */ +#define L2C_COC_ROLE_ACCEPTOR 0x02 /*! Channel acceptor */ + +/*! Connection oriented channel data confirm status values */ +#define L2C_COC_DATA_SUCCESS 0 /*! Data request successful */ +#define L2C_COC_DATA_ERR_MEMORY 1 /*! Out of memory */ +#define L2C_COC_DATA_ERR_OVERFLOW 2 /*! Transaction overflow */ + +/*! Connection oriented channel callback events */ +#define L2C_COC_CBACK_START 0x70 /*! L2C callback event starting value */ +enum +{ + L2C_COC_CONNECT_IND = L2C_COC_CBACK_START, /*! Channel connect indication */ + L2C_COC_DISCONNECT_IND, /*! Channel disconnect indication */ + L2C_COC_DATA_IND, /*! Received data indication */ + L2C_COC_DATA_CNF /*! Transmit data confirm */ +}; + +#define L2C_COC_CBACK_CBACK_END L2C_COC_DATA_CNF /*! L2C callback event ending value */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection oriented channel registration ID */ +typedef uint16_t l2cCocRegId_t; + +/*! Connection oriented channel registration structure */ +typedef struct +{ + uint16_t psm; /*! Protocol service multiplexer */ + uint16_t mps; /*! Maximum receive PDU fragment size */ + uint16_t mtu; /*! Maximum receive data packet size */ + uint16_t credits; /*! Data packet receive credits for this channel */ + bool_t authoriz; /*! TRUE if authorization is required */ + uint8_t secLevel; /*! Channel minimum security level requirements */ + uint8_t role; /*! Channel initiator/acceptor role */ +} l2cCocReg_t; + +/* Connection oriented channel connect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint16_t peerMtu; /*! Data packet MTU peer can receive */ + uint16_t psm; /*! Connected PSM */ +} l2cCocConnectInd_t; + +/* Connection oriented channel disconnect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint16_t result; /*! Connection failure result code */ +} l2cCocDisconnectInd_t; + +/* Connection oriented channel data indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint8_t *pData; /*! Pointer to packet data */ + uint16_t dataLen; /*! packet data length */ +} l2cCocDataInd_t; + +/* Connection oriented channel disconnect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ +} l2cCocDataCnf_t; + +/*! + * Connection oriented channel event structure + * + * Connection oriented channel callback header parameters: + * + * \param hdr.event Callback event + * \param hdr.param DM connection ID + * \param hdr.status Event status (L2C_COC_DATA_CNF only) + */ +typedef union +{ + wsfMsgHdr_t hdr; /*! Header structure */ + l2cCocConnectInd_t connectInd; /*! Channel connect indication */ + l2cCocDisconnectInd_t disconnectInd; /*! Channel disconnect indication */ + l2cCocDataInd_t dataInd; /*! Received data indication */ + l2cCocDataCnf_t dataCnf; /*! Transmit data confirm */ +} l2cCocEvt_t; + +/*! Configurable parameters */ +typedef struct +{ + uint16_t reqTimeout; /*! Request timeout in seconds */ +} l2cCfg_t; + +/************************************************************************************************** + Global Variables; +**************************************************************************************************/ + +/*! Configuration pointer */ +extern l2cCfg_t *pL2cCfg; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn l2cDataCback_t + * + * \brief This callback function sends a received L2CAP packet to the client. + * + * \param handle The connection handle. + * \param len The length of the L2CAP payload data in pPacket. + * \param pPacket A buffer containing the packet. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cDataCback_t)(uint16_t handle, uint16_t len, uint8_t *pPacket); + +/*************************************************************************************************/ +/*! + * \fn l2cCtrlCback_t + * + * \brief This callback function sends control messages to the client. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cCtrlCback_t)(wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn l2cCocCback_t + * + * \brief This callback function sends data and other events to connection oriented + * channels clients. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cCocCback_t)(l2cCocEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn l2cCocAuthorCback_t + * + * \brief This callback function is used for authoriztion of connection oriented channels. + * + * \param connId DM connection ID. + * \param regId The registration instance requiring authorization. + * \param psm The PSM of the registration instance. + * + * \return L2C_CONN_SUCCESS if authorization is successful, any other value for failure. + */ +/*************************************************************************************************/ +typedef uint16_t (*l2cCocAuthorCback_t)(dmConnId_t connId, l2cCocRegId_t regId, uint16_t psm); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn L2cInit + * + * \brief Initialize L2C subsystem. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cMasterInit + * + * \brief Initialize L2C for operation as a Bluetooth LE master. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveInit + * + * \brief Initialize L2C for operation as a Bluetooth LE slave. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cRegister + * + * \brief called by the L2C client, such as ATT or SMP, to register for the given CID. + * + * \param cid channel identifier. + * \param dataCback Callback function for L2CAP data received for this CID. + * \param ctrlCback Callback function for control events for this CID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cRegister(uint16_t cid, l2cDataCback_t dataCback, l2cCtrlCback_t ctrlCback); + +/*************************************************************************************************/ +/*! + * \fn L2cDataReq + * + * \brief Send an L2CAP data packet on the given CID. + * + * \param cid The channel identifier. + * \param handle The connection handle. The client receives this handle from DM. + * \param len The length of the payload data in pPacket. + * \param pPacket A buffer containing the packet. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDataReq(uint16_t cid, uint16_t handle, uint16_t len, uint8_t *pL2cPacket); + +/*************************************************************************************************/ +/*! + * \fn L2cCocInit + * + * \brief Initialize L2C connection oriented channel subsystem. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cCocRegister + * + * \brief Register to use a connection oriented channel, as either a channel acceptor, + * initiator, or both. If registering as channel acceptor then the PSM is specified. + * After registering a connection can be established by the client using this + * registration instance. + * + * \param cback Client callback function. + * \param pReg Registration parameter structure. + * + * \return Registration instance ID or L2C_COC_REG_ID_NONE if registration failed. + */ +/*************************************************************************************************/ +l2cCocRegId_t L2cCocRegister(l2cCocCback_t cback, l2cCocReg_t *pReg); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDeregister + * + * \brief Deregister and deallocate a connection oriented channel registration instance. + * This function should only be called if there are no active channels using this + * registration instance. + * + * \param regId Registration instance ID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDeregister(l2cCocRegId_t regId); + +/*************************************************************************************************/ +/*! + * \fn L2cCocConnectReq + * + * \brief Initiate a connection to the given peer PSM. + * + * \param connId DM connection ID. + * \param regId The associated registration instance. + * \param psm Peer PSM. + * + * \return Local CID or L2C_COC_CID_NONE none if failure. + */ +/*************************************************************************************************/ +uint16_t L2cCocConnectReq(dmConnId_t connId, l2cCocRegId_t regId, uint16_t psm); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDisconnectReq + * + * \brief Disconnect the channel for the given CID. + * + * \param cid Channel ID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDisconnectReq(uint16_t cid); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDataReq + * + * \brief Send an L2CAP data packet on the given connection oriented CID. + * + * \param cid The local channel identifier. + * \param len The length of the payload data in pPacket. + * \param pPacket Packet payload data. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDataReq(uint16_t cid, uint16_t len, uint8_t *pPayload); + +/*************************************************************************************************/ +/*! + * \fn L2cCocErrorTest + * + * \brief For testing purposes only. + * + * \param result Result code + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocErrorTest(uint16_t result); + +/*************************************************************************************************/ +/*! + * \fn L2cCocCreditSendTest + * + * \brief For testing purposes only. + * + * \param cid The local channel identifier. + * \param credits Credits to send. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocCreditSendTest(uint16_t cid, uint16_t credits); + +/*************************************************************************************************/ +/*! + * \fn L2cDmConnUpdateReq + * + * \brief For internal use only. This function is called by DM to send an L2CAP + * connection update request. + * + * \param handle The connection handle. + * \param pConnSpec Pointer to the connection specification structure. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDmConnUpdateReq(uint16_t handle, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn L2cDmConnUpdateRsp + * + * \brief For internal use only. This function is called by DM to send an L2CAP + * connection update response. + * + * \param identifier Identifier value previously passed from L2C to DM. + * \param handle The connection handle. + * \param result Connection update response result. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDmConnUpdateRsp(uint8_t identifier, uint16_t handle, uint16_t result); + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h new file mode 100644 index 00000000000..7754abb7f67 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h @@ -0,0 +1,118 @@ +/*************************************************************************************************/ +/*! + * \file l2c_defs.h + * + * \brief L2CAP constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_DEFS_H +#define L2C_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Packet definitions */ +#define L2C_HDR_LEN 4 /*! L2CAP packet header length */ +#define L2C_MIN_MTU 23 /*! Minimum packet payload MTU for LE */ +#define L2C_SIG_HDR_LEN 4 /*! L2CAP signaling command header length */ +#define L2C_LE_SDU_HDR_LEN 2 /*! L2CAP LE SDU data header length */ + +/*! Start of L2CAP payload in an HCI ACL packet buffer */ +#define L2C_PAYLOAD_START (HCI_ACL_HDR_LEN + L2C_HDR_LEN) + +/*! L2CAP signaling packet base length, including HCI header */ +#define L2C_SIG_PKT_BASE_LEN (HCI_ACL_HDR_LEN + L2C_HDR_LEN + L2C_SIG_HDR_LEN) + +/*! L2CAP LE SDU packet base length, including HCI header */ +#define L2C_LE_SDU_PKT_BASE_LEN (HCI_ACL_HDR_LEN + L2C_HDR_LEN + L2C_LE_SDU_HDR_LEN) + +/*! Signaling packet parameter lengths */ +#define L2C_SIG_CONN_UPDATE_REQ_LEN 8 +#define L2C_SIG_CONN_UPDATE_RSP_LEN 2 +#define L2C_SIG_CMD_REJ_LEN 2 +#define L2C_SIG_DISCONN_REQ_LEN 4 +#define L2C_SIG_DISCONN_RSP_LEN 4 +#define L2C_SIG_LE_CONN_REQ_LEN 10 +#define L2C_SIG_LE_CONN_RSP_LEN 10 +#define L2C_SIG_FLOW_CTRL_CREDIT_LEN 4 + +/*! Connection identifiers */ +#define L2C_CID_ATT 0x0004 /*! CID for attribute protocol */ +#define L2C_CID_LE_SIGNALING 0x0005 /*! CID for LE signaling */ +#define L2C_CID_SMP 0x0006 /*! CID for security manager protocol */ + +/*! Signaling codes */ +#define L2C_SIG_CMD_REJ 0x01 /*! Comand reject */ +#define L2C_SIG_DISCONNECT_REQ 0x06 /*! Disconnect request */ +#define L2C_SIG_DISCONNECT_RSP 0x07 /*! Disconnect response */ +#define L2C_SIG_CONN_UPDATE_REQ 0x12 /*! Connection parameter update request */ +#define L2C_SIG_CONN_UPDATE_RSP 0x13 /*! Connection parameter update response */ +#define L2C_SIG_LE_CONNECT_REQ 0x14 /*! LE credit based connection request */ +#define L2C_SIG_LE_CONNECT_RSP 0x15 /*! LE credit based connection response */ +#define L2C_SIG_FLOW_CTRL_CREDIT 0x16 /*! LE flow control credit */ + +/*! Signaling response code flag */ +#define L2C_SIG_RSP_FLAG 0x01 + +/*! Command reject reason codes */ +#define L2C_REJ_NOT_UNDERSTOOD 0x0000 /*! Command not understood */ +#define L2C_REJ_MTU_EXCEEDED 0x0001 /*! Signaling MTU exceeded */ +#define L2C_REJ_INVALID_CID 0x0002 /*! Invalid CID in request */ + +/*! Connection parameter update result */ +#define L2C_CONN_PARAM_ACCEPTED 0x0000 /*! Connection parameters accepted */ +#define L2C_CONN_PARAM_REJECTED 0x0001 /*! Connection parameters rejected */ + +/*! LE connection result */ +#define L2C_CONN_SUCCESS 0x0000 /*! Connection successful */ +#define L2C_CONN_NONE 0x0001 /*! No connection result value available */ +#define L2C_CONN_FAIL_PSM 0x0002 /*! Connection refused LE_PSM not supported */ +#define L2C_CONN_FAIL_RES 0x0004 /*! Connection refused no resources available */ +#define L2C_CONN_FAIL_AUTH 0x0005 /*! Connection refused insufficient authentication */ +#define L2C_CONN_FAIL_AUTHORIZ 0x0006 /*! Connection refused insufficient authorization */ +#define L2C_CONN_FAIL_KEY_SIZE 0x0007 /*! Connection refused insufficient encryption key size */ +#define L2C_CONN_FAIL_ENC 0x0008 /*! Connection Refused insufficient encryption */ +#define L2C_CONN_FAIL_INVALID_SCID 0x0009 /*! Connection refused invalid source CID */ +#define L2C_CONN_FAIL_ALLOCATED_SCID 0x000A /*! Connection refused source CID already allocated */ +#define L2C_CONN_FAIL_UNACCEPT_PARAM 0x000B /*! Connection refused unacceptable parameters */ + +/*! LE connection result proprietary codes */ +#define L2C_CONN_FAIL_TIMEOUT 0xF000 /*! Request timeout */ + +/*! Signaling parameter value ranges */ +#define L2C_PSM_MIN 0x0001 +#define L2C_PSM_MAX 0x00FF +#define L2C_CID_DYN_MIN 0x0040 +#define L2C_CID_DYN_MAX 0x007F +#define L2C_MTU_MIN 0x0017 +#define L2C_MPS_MIN 0x0017 +#define L2C_MPS_MAX 0xFFFD +#define L2C_CREDITS_MAX 0xFFFF + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h new file mode 100644 index 00000000000..5b8fde42eee --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h @@ -0,0 +1,96 @@ +/*************************************************************************************************/ +/*! + * \file l2c_handler.h + * + * \brief L2CAP handler interface. + * + * $Date $ + * $Revision $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_HANDLER_H +#define L2C_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveHandlerInit + * + * \brief Event handler initialization function for L2C when operating as a slave. + * + * \param handlerId ID for this event handler. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveHandlerInit(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveHandler + * + * \brief The WSF event handler for L2C when operating as a slave. + * + * \param event Event mask. + * \param pMsg Pointer to message. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn L2cCocHandlerInit + * + * \brief Event handler initialization function for L2C with connection oriented channels. + * + * \param handlerId ID for this event handler. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocHandlerInit(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn L2cCocHandler + * + * \brief The WSF event handler for L2C with connection oriented channels. + * + * \param event Event mask. + * \param pMsg Pointer to message. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h new file mode 100644 index 00000000000..f1624f1c4df --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h @@ -0,0 +1,242 @@ +/*************************************************************************************************/ +/*! + * \file smp_api.h + * + * \brief SMP subsystem API. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_API_H +#define SMP_API_H + +#include "wsf_os.h" +#include "smp_defs.h" +#include "dm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Event handler messages for SMP state machines */ +enum +{ + SMP_MSG_API_PAIR_REQ = 1, /*! API pairing request */ + SMP_MSG_API_PAIR_RSP, /*! API pairing response */ + SMP_MSG_API_CANCEL_REQ, /*! API cancel request */ + SMP_MSG_API_AUTH_RSP, /*! API pin response */ + SMP_MSG_API_SECURITY_REQ, /*! API security request */ + SMP_MSG_CMD_PKT, /*! SMP command packet received */ + SMP_MSG_CMD_PAIRING_FAILED, /*! SMP pairing failed packet received */ + SMP_MSG_DM_ENCRYPT_CMPL, /*! Link encrypted */ + SMP_MSG_DM_ENCRYPT_FAILED, /*! Link encryption failed */ + SMP_MSG_DM_CONN_CLOSE, /*! Connection closed */ + SMP_MSG_WSF_AES_CMPL, /*! AES calculation complete */ + SMP_MSG_INT_SEND_NEXT_KEY, /*! Send next key to be distributed */ + SMP_MSG_INT_MAX_ATTEMPTS, /*! Maximum pairing attempts reached */ + SMP_MSG_INT_PAIRING_CMPL, /*! Pairing complete */ + SMP_MSG_INT_TIMEOUT, /*! Pairing protocol timeout */ + SMP_MSG_INT_LESC, /*! Pair with Secure Connections */ + SMP_MSG_INT_LEGACY, /*! Pair with Legacy Security */ + SMP_MSG_INT_JW_NC, /*! LESC Just-Works/Numeric Comparison pairing */ + SMP_MSG_INT_PASSKEY, /*! LESC Passkey pairing */ + SMP_MSG_INT_OOB, /*! LESC Out-of-Band Pairing */ + SMP_MSG_API_USER_CONFIRM, /*! User confirms valid numeric comparison */ + SMP_MSG_API_USER_KEYPRESS, /*! User keypress in passkey pairing */ + SMP_MSG_API_KEYPRESS_CMPL, /*! User keypress complete in passkey pairing */ + SMP_MSG_WSF_ECC_CMPL, /*! WSF ECC operation complete */ + SMP_MSG_INT_PK_NEXT, /*! Continue to next passkey bit */ + SMP_MSG_INT_PK_CMPL, /*! Passkey operation complete */ + SMP_MSG_WSF_CMAC_CMPL, /*! WSF CMAC operation complete */ + SMP_MSG_DH_CHECK_FAILURE, /*! WSF CMAC operation complete */ + SMP_MSG_EARLY_CNF, /*! An early Confirm from the initiator in passkey pairing */ + SMP_NUM_MSGS +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Configurable parameters */ +typedef struct +{ + uint16_t attemptTimeout; /*! 'Repeated attempts' timeout in msec */ + uint8_t ioCap; /*! I/O Capability */ + uint8_t minKeyLen; /*! Minimum encryption key length */ + uint8_t maxKeyLen; /*! Maximum encryption key length */ + uint8_t maxAttempts; /*! Attempts to trigger 'repeated attempts' timeout */ + uint8_t auth; /*! Device authentication requirements */ +} smpCfg_t; + +/*! Data type for SMP_MSG_API_PAIR_REQ and SMP_MSG_API_PAIR_RSP */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t oob; + uint8_t auth; + uint8_t iKeyDist; + uint8_t rKeyDist; +} smpDmPair_t; + +/*! Data type for SMP_MSG_API_AUTH_RSP */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t authData[SMP_OOB_LEN]; + uint8_t authDataLen; +} smpDmAuthRsp_t; + +/*! Data type for SMP_MSG_API_USER_KEYPRESS */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t keypress; +} smpDmKeypress_t; + +/*! Data type for SMP_MSG_API_SECURITY_REQ */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t auth; +} smpDmSecurityReq_t; + +/*! Union SMP DM message data types */ +typedef union +{ + wsfMsgHdr_t hdr; + smpDmPair_t pair; + smpDmAuthRsp_t authRsp; + smpDmSecurityReq_t securityReq; + smpDmKeypress_t keypress; +} smpDmMsg_t; + +/************************************************************************************************** + Global Variables; +**************************************************************************************************/ + +/*! Configuration pointer */ +extern smpCfg_t *pSmpCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SmpiInit + * + * \brief Initialize SMP initiator role. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpiInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmprInit + * + * \brief Initialize SMP responder role. + * + * \return None. + */ +/*************************************************************************************************/ +void SmprInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpiScInit + * + * \brief Initialize SMP initiator role utilizing BTLE Secure Connections. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpiScInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmprScInit + * + * \brief Initialize SMP responder role utilizing BTLE Secure Connections. + * + * \return None. + */ +/*************************************************************************************************/ +void SmprScInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpNonInit + * + * \brief Use this SMP init function when SMP is not supported. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpNonInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpDmMsgSend + * + * \brief This function is called by DM to send a message to SMP. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpDmMsgSend(smpDmMsg_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn SmpDmEncryptInd + * + * \brief This function is called by DM to notify SMP of encrypted link status. + * + * \param pMsg Pointer to HCI message structure. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpDmEncryptInd(wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn SmpDmGetStk + * + * \brief Return the STK for the given connection. + * + * \param connId Connection identifier. + * \param pSecLevel Returns the security level of pairing when STK was created. + * + * \return Pointer to STK or NULL if not available. + */ +/*************************************************************************************************/ +uint8_t *SmpDmGetStk(dmConnId_t connId, uint8_t *pSecLevel); + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h new file mode 100644 index 00000000000..317b84802cb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h @@ -0,0 +1,155 @@ +/*************************************************************************************************/ +/*! + * \file smp_defs.h + * + * \brief Security manager constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_DEFS_H +#define SMP_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! PDU format */ +#define SMP_HDR_LEN 1 /*! Attribute PDU header length */ + +/*! Protocol timeout */ +#define SMP_TIMEOUT 30 /*! Protocol timeout in seconds */ + +/*! Encryption key size */ +#define SMP_KEY_SIZE_MAX 16 /*! Maximum encryption key size */ +#define SMP_KEY_SIZE_MIN 7 /*! Minimum encryption key size */ + +/*! OOB and PIN data lengths in bytes */ +#define SMP_OOB_LEN 16 +#define SMP_PIN_LEN 3 + +/*! Error codes */ +#define SMP_ERR_PASSKEY_ENTRY 0x01 /*! User input of passkey failed */ +#define SMP_ERR_OOB 0x02 /*! OOB data is not available */ +#define SMP_ERR_AUTH_REQ 0x03 /*! Authentication requirements cannot be met */ +#define SMP_ERR_CONFIRM_VALUE 0x04 /*! Confirm value does not match */ +#define SMP_ERR_PAIRING_NOT_SUP 0x05 /*! Pairing is not supported by the device */ +#define SMP_ERR_ENC_KEY_SIZE 0x06 /*! Insufficient encryption key size */ +#define SMP_ERR_COMMAND_NOT_SUP 0x07 /*! Command not supported */ +#define SMP_ERR_UNSPECIFIED 0x08 /*! Unspecified reason */ +#define SMP_ERR_ATTEMPTS 0x09 /*! Repeated attempts */ +#define SMP_ERR_INVALID_PARAM 0x0A /*! Invalid parameter or command length */ +#define SMP_ERR_DH_KEY_CHECK 0x0B /*! DH Key check did not match */ +#define SMP_ERR_NUMERIC_COMPARISON 0x0C /*! Numeric comparison did not match */ +#define SMP_ERR_BR_EDR_IN_PROGRESS 0x0D /*! BR/EDR in progress */ +#define SMP_ERR_CROSS_TRANSPORT 0x0E /*! BR/EDR Cross transport key generation not allowed */ + +/*! Proprietary internal error codes */ +#define SMP_ERR_MEMORY 0xE0 /*! Out of memory */ +#define SMP_ERR_TIMEOUT 0xE1 /*! Transaction timeout */ + +/*! Command codes */ +#define SMP_CMD_PAIR_REQ 0x01 /*! Pairing Request */ +#define SMP_CMD_PAIR_RSP 0x02 /*! Pairing Response */ +#define SMP_CMD_PAIR_CNF 0x03 /*! Pairing Confirm */ +#define SMP_CMD_PAIR_RAND 0x04 /*! Pairing Random */ +#define SMP_CMD_PAIR_FAIL 0x05 /*! Pairing Failed */ +#define SMP_CMD_ENC_INFO 0x06 /*! Encryption Information */ +#define SMP_CMD_MASTER_ID 0x07 /*! Master Identification */ +#define SMP_CMD_ID_INFO 0x08 /*! Identity Information */ +#define SMP_CMD_ID_ADDR_INFO 0x09 /*! Identity Address Information */ +#define SMP_CMD_SIGN_INFO 0x0A /*! Signing Information */ +#define SMP_CMD_SECURITY_REQ 0x0B /*! Security Request */ +#define SMP_CMD_PUBLIC_KEY 0x0C /*! Public Key */ +#define SMP_CMD_DHKEY_CHECK 0x0D /*! DH Key Check */ +#define SMP_CMD_KEYPRESS 0x0E /*! User Key Press */ +#define SMP_CMD_MAX 0x0F /*! Command code maximum */ + +/*! Command packet lengths */ +#define SMP_PAIR_REQ_LEN 7 +#define SMP_PAIR_RSP_LEN 7 +#define SMP_PAIR_CNF_LEN 17 +#define SMP_PAIR_RAND_LEN 17 +#define SMP_PAIR_FAIL_LEN 2 +#define SMP_ENC_INFO_LEN 17 +#define SMP_MASTER_ID_LEN 11 +#define SMP_ID_INFO_LEN 17 +#define SMP_ID_ADDR_INFO_LEN 8 +#define SMP_SIGN_INFO_LEN 17 +#define SMP_SECURITY_REQ_LEN 2 +#define SMP_PUB_KEY_MSG_LEN (1 + 2*SMP_PUB_KEY_LEN) +#define SMP_DHKEY_CHECK_MSG_LEN (1 + SMP_DHKEY_CHECK_LEN) +#define SMP_KEYPRESS_MSG_LEN 2 + +/*! I/O capabilities */ +#define SMP_IO_DISP_ONLY 0x00 /*! DisplayOnly */ +#define SMP_IO_DISP_YES_NO 0x01 /*! DisplayYesNo */ +#define SMP_IO_KEY_ONLY 0x02 /*! KeyboardOnly */ +#define SMP_IO_NO_IN_NO_OUT 0x03 /*! NoInputNoOutput */ +#define SMP_IO_KEY_DISP 0x04 /*! KeyboardDisplay */ + +/*! OOB data present */ +#define SMP_OOB_DATA_NONE 0x00 +#define SMP_OOB_DATA_PRESENT 0x01 + +/*! Authentication/security properties bit mask */ +#define SMP_AUTH_BOND_MASK 0x03 /*! Mask for bonding bits */ +#define SMP_AUTH_BOND_FLAG 0x01 /*! Bonding requested */ +#define SMP_AUTH_MITM_FLAG 0x04 /*! MITM (authenticated pairing) requested */ +#define SMP_AUTH_SC_FLAG 0x08 /*! LE Secure Connections requested */ +#define SMP_AUTH_KP_FLAG 0x10 /*! Keypress notifications requested */ + +/*! Key distribution bit mask */ +#define SMP_KEY_DIST_ENC 0x01 /*! Distribute LTK */ +#define SMP_KEY_DIST_ID 0x02 /*! Distribute IRK */ +#define SMP_KEY_DIST_SIGN 0x04 /*! Distribute CSRK */ +#define SMP_KEY_DIST_MASK (SMP_KEY_DIST_ENC | SMP_KEY_DIST_ID | SMP_KEY_DIST_SIGN) + +/*! LESC Passkey keypress types */ +#define SMP_PASSKEY_ENTRY_STARTED 0x00 /*! Passkey entry started keypress type */ +#define SMP_PASSKEY_DIGIT_ENTERED 0x01 /*! Passkey digit entered keypress type */ +#define SMP_PASSKEY_DIGIT_ERASED 0x02 /*! Passkey digit erased keypress type */ +#define SMP_PASSKEY_CLEARED 0x03 /*! Passkey cleared keypress type */ +#define SMP_PASSKEY_ENTRY_COMPLETED 0x04 /*! Passkey entry complete keypress type */ + +/*! Various parameter lengths */ +#define SMP_RAND_LEN 16 +#define SMP_CONFIRM_LEN 16 +#define SMP_KEY_LEN 16 +#define SMP_RAND8_LEN 8 +#define SMP_PRIVATE_KEY_LEN 32 +#define SMP_PUB_KEY_LEN 32 +#define SMP_DHKEY_LEN 32 +#define SMP_DHKEY_CHECK_LEN 16 + +/* CMAC Input Lengths */ +#define SMP_F4_TEXT_LEN (SMP_PUB_KEY_LEN * 2 + 1) +#define SMP_G2_TEXT_LEN (SMP_PUB_KEY_LEN * 2 + SMP_RAND_LEN) +#define SMP_F5_TKEY_TEXT_LEN (SMP_DHKEY_LEN) +#define SMP_F5_TEXT_LEN (9 + 2*BDA_ADDR_LEN + 2*SMP_RAND_LEN) +#define SMP_F6_TEXT_LEN (2*BDA_ADDR_LEN + 3*SMP_RAND_LEN + 5) + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h new file mode 100644 index 00000000000..b324afba3f4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file smp_handler.h + * + * \brief Interface to SMP event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_HANDLER_H +#define SMP_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SmpHandlerInit + * + * \brief SMP handler init function called during system initialization. + * + * \param handlerID WSF handler ID for SMP. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn SmpHandler + * + * \brief WSF event handler for SMP. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h new file mode 100644 index 00000000000..4acda1153e6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h @@ -0,0 +1,891 @@ +/*************************************************************************************************/ +/*! + * \file hci_defs.h + * + * \brief HCI constants and definitions from the Bluetooth specification. + * + * $Date: 2017-03-09 12:18:38 -0600 (Thu, 09 Mar 2017) $ + * $Revision: 11460 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_DEFS_H +#define HCI_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Packet definitions */ +#define HCI_CMD_HDR_LEN 3 /*!< Command packet header length */ +#define HCI_ACL_HDR_LEN 4 /*!< ACL packet header length */ +#define HCI_EVT_HDR_LEN 2 /*!< Event packet header length */ +#define HCI_EVT_PARAM_MAX_LEN 255 /*!< Maximum length of event packet parameters */ +#define HCI_ACL_DEFAULT_LEN 27 /*!< Default maximum ACL packet length */ +#define HCI_PB_FLAG_MASK 0x3000 /*!< ACL packet boundary flag mask */ +#define HCI_PB_START_H2C 0x0000 /*!< Packet boundary flag, start, host-to-controller */ +#define HCI_PB_CONTINUE 0x1000 /*!< Packet boundary flag, continue */ +#define HCI_PB_START_C2H 0x2000 /*!< Packet boundary flag, start, controller-to-host */ +#define HCI_HANDLE_MASK 0x0FFF /*!< Mask for handle bits in ACL packet */ +#define HCI_HANDLE_NONE 0xFFFF /*!< Value for invalid handle */ + +/* Packet types */ +#define HCI_CMD_TYPE 1 /*!< HCI command packet */ +#define HCI_ACL_TYPE 2 /*!< HCI ACL data packet */ +#define HCI_EVT_TYPE 4 /*!< HCI event packet */ + +/* Error codes */ +#define HCI_SUCCESS 0x00 /*!< Success */ +#define HCI_ERR_UNKNOWN_CMD 0x01 /*!< Unknown HCI command */ +#define HCI_ERR_UNKNOWN_HANDLE 0x02 /*!< Unknown connection identifier */ +#define HCI_ERR_HARDWARE_FAILURE 0x03 /*!< Hardware failure */ +#define HCI_ERR_PAGE_TIMEOUT 0x04 /*!< Page timeout */ +#define HCI_ERR_AUTH_FAILURE 0x05 /*!< Authentication failure */ +#define HCI_ERR_KEY_MISSING 0x06 /*!< PIN or key missing */ +#define HCI_ERR_MEMORY_EXCEEDED 0x07 /*!< Memory capacity exceeded */ +#define HCI_ERR_CONN_TIMEOUT 0x08 /*!< Connection timeout */ +#define HCI_ERR_CONN_LIMIT 0x09 /*!< Connection limit exceeded */ +#define HCI_ERR_SYNCH_CONN_LIMIT 0x0A /*!< Synchronous connection limit exceeded */ +#define HCI_ERR_ACL_CONN_EXISTS 0x0B /*!< ACL connection already exists */ +#define HCI_ERR_CMD_DISALLOWED 0x0C /*!< Command disallowed */ +#define HCI_ERR_REJ_RESOURCES 0x0D /*!< Connection rejected limited resources */ +#define HCI_ERR_REJ_SECURITY 0x0E /*!< Connection rejected security reasons */ +#define HCI_ERR_REJ_BD_ADDR 0x0F /*!< Connection rejected unacceptable BD_ADDR */ +#define HCI_ERR_ACCEPT_TIMEOUT 0x10 /*!< Connection accept timeout exceeded */ +#define HCI_ERR_UNSUP_FEAT 0x11 /*!< Unsupported feature or parameter value */ +#define HCI_ERR_INVALID_PARAM 0x12 /*!< Invalid HCI command parameters */ +#define HCI_ERR_REMOTE_TERMINATED 0x13 /*!< Remote user terminated connection */ +#define HCI_ERR_REMOTE_RESOURCES 0x14 /*!< Remote device low resources */ +#define HCI_ERR_REMOTE_POWER_OFF 0x15 /*!< Remote device power off */ +#define HCI_ERR_LOCAL_TERMINATED 0x16 /*!< Connection terminated by local host */ +#define HCI_ERR_REPEATED_ATTEMPTS 0x17 /*!< Repeated attempts */ +#define HCI_ERR_PAIRING_NOT_ALLOWED 0x18 /*!< Pairing not allowed */ +#define HCI_ERR_UNKNOWN_LMP_PDU 0x19 /*!< Unknown LMP PDU */ +#define HCI_ERR_UNSUP_REMOTE_FEAT 0x1A /*!< Unsupported remote feature */ +#define HCI_ERR_SCO_OFFSET 0x1B /*!< SCO offset rejected */ +#define HCI_ERR_SCO_INTERVAL 0x1C /*!< SCO interval rejected */ +#define HCI_ERR_SCO_MODE 0x1D /*!< SCO air mode rejected */ +#define HCI_ERR_LMP_PARAM 0x1E /*!< Invalid LMP parameters */ +#define HCI_ERR_UNSPECIFIED 0x1F /*!< Unspecified error */ +#define HCI_ERR_UNSUP_LMP_PARAM 0x20 /*!< Unsupported LMP parameter value */ +#define HCI_ERR_ROLE_CHANGE 0x21 /*!< Role change not allowed */ +#define HCI_ERR_LL_RESP_TIMEOUT 0x22 /*!< LL response timeout */ +#define HCI_ERR_LMP_COLLISION 0x23 /*!< LMP error transaction collision */ +#define HCI_ERR_LMP_PDU 0x24 /*!< LMP pdu not allowed */ +#define HCI_ERR_ENCRYPT_MODE 0x25 /*!< Encryption mode not acceptable */ +#define HCI_ERR_LINK_KEY 0x26 /*!< Link key can not be changed */ +#define HCI_ERR_UNSUP_QOS 0x27 /*!< Requested qos not supported */ +#define HCI_ERR_INSTANT_PASSED 0x28 /*!< Instant passed */ +#define HCI_ERR_UNSUP_UNIT_KEY 0x29 /*!< Pairing with unit key not supported */ +#define HCI_ERR_TRANSACT_COLLISION 0x2A /*!< Different transaction collision */ +#define HCI_ERR_CHANNEL_CLASS 0x2E /*!< Channel classification not supported */ +#define HCI_ERR_MEMORY 0x2F /*!< Insufficient security */ +#define HCI_ERR_PARAMETER_RANGE 0x30 /*!< Parameter out of mandatory range */ +#define HCI_ERR_ROLE_SWITCH_PEND 0x32 /*!< Role switch pending */ +#define HCI_ERR_RESERVED_SLOT 0x34 /*!< Reserved slot violation */ +#define HCI_ERR_ROLE_SWITCH 0x35 /*!< Role switch failed */ +#define HCI_ERR_INQ_TOO_LARGE 0x36 /*!< Extended inquiry response too large */ +#define HCI_ERR_UNSUP_SSP 0x37 /*!< Secure simple pairing not supported by host */ +#define HCI_ERR_HOST_BUSY_PAIRING 0x38 /*!< Host busy - pairing */ +#define HCI_ERR_NO_CHANNEL 0x39 /*!< Connection rejected no suitable channel */ +#define HCI_ERR_CONTROLLER_BUSY 0x3A /*!< Controller busy */ +#define HCI_ERR_CONN_INTERVAL 0x3B /*!< Unacceptable connection interval */ +#define HCI_ERR_ADV_TIMEOUT 0x3C /*!< Advertising timeout */ +#define HCI_ERR_MIC_FAILURE 0x3D /*!< Connection terminated due to MIC failure */ +#define HCI_ERR_CONN_FAIL 0x3E /*!< Connection failed to be established */ +#define HCI_ERR_MAC_CONN_FAIL 0x3F /*!< MAC connection failed */ +#define HCI_ERR_COARSE_CLK_ADJ_REJ 0x40 /*!< Coarse clock adjustment rejected */ +#define HCI_ERR_TYPE0_SUBMAP_NOT_DEF 0x41 /*!< Type0 submap not defined */ +#define HCI_ERR_UNKNOWN_ADV_ID 0x42 /*!< Unknown advertising identifier */ +#define HCI_ERR_LIMIT_REACHED 0x43 /*!< Limit reached */ +#define HCI_ERR_OP_CANCELLED_BY_HOST 0x44 /*!< Operation cancelled by host */ + +/* Command groups */ +#define HCI_OGF_NOP 0x00 /*!< No operation */ +#define HCI_OGF_LINK_CONTROL 0x01 /*!< Link control */ +#define HCI_OGF_LINK_POLICY 0x02 /*!< Link policy */ +#define HCI_OGF_CONTROLLER 0x03 /*!< Controller and baseband */ +#define HCI_OGF_INFORMATIONAL 0x04 /*!< Informational parameters */ +#define HCI_OGF_STATUS 0x05 /*!< Status parameters */ +#define HCI_OGF_TESTING 0x06 /*!< Testing */ +#define HCI_OGF_LE_CONTROLLER 0x08 /*!< LE controller */ +#define HCI_OGF_VENDOR_SPEC 0x3F /*!< Vendor specific */ + +/* NOP command */ +#define HCI_OCF_NOP 0x00 + +/* Link control commands */ +#define HCI_OCF_DISCONNECT 0x06 +#define HCI_OCF_READ_REMOTE_VER_INFO 0x1D + +/* Link policy commands (none used for LE) */ + +/* Controller and baseband commands */ +#define HCI_OCF_SET_EVENT_MASK 0x01 +#define HCI_OCF_RESET 0x03 +#define HCI_OCF_READ_TX_PWR_LVL 0x2D +#define HCI_OCF_SET_CONTROLLER_TO_HOST_FC 0x31 +#define HCI_OCF_HOST_BUFFER_SIZE 0x33 +#define HCI_OCF_HOST_NUM_CMPL_PKTS 0x35 +#define HCI_OCF_SET_EVENT_MASK_PAGE2 0x63 +#define HCI_OCF_READ_AUTH_PAYLOAD_TO 0x7B +#define HCI_OCF_WRITE_AUTH_PAYLOAD_TO 0x7C + +/* Informational commands */ +#define HCI_OCF_READ_LOCAL_VER_INFO 0x01 +#define HCI_OCF_READ_LOCAL_SUP_CMDS 0x02 +#define HCI_OCF_READ_LOCAL_SUP_FEAT 0x03 +#define HCI_OCF_READ_BUF_SIZE 0x05 +#define HCI_OCF_READ_BD_ADDR 0x09 + +/* Status commands */ +#define HCI_OCF_READ_RSSI 0x05 + +/* LE controller commands */ +#define HCI_OCF_LE_SET_EVENT_MASK 0x01 +#define HCI_OCF_LE_READ_BUF_SIZE 0x02 +#define HCI_OCF_LE_READ_LOCAL_SUP_FEAT 0x03 +#define HCI_OCF_LE_SET_RAND_ADDR 0x05 +#define HCI_OCF_LE_SET_ADV_PARAM 0x06 +#define HCI_OCF_LE_READ_ADV_TX_POWER 0x07 +#define HCI_OCF_LE_SET_ADV_DATA 0x08 +#define HCI_OCF_LE_SET_SCAN_RESP_DATA 0x09 +#define HCI_OCF_LE_SET_ADV_ENABLE 0x0A +#define HCI_OCF_LE_SET_SCAN_PARAM 0x0B +#define HCI_OCF_LE_SET_SCAN_ENABLE 0x0C +#define HCI_OCF_LE_CREATE_CONN 0x0D +#define HCI_OCF_LE_CREATE_CONN_CANCEL 0x0E +#define HCI_OCF_LE_READ_WHITE_LIST_SIZE 0x0F +#define HCI_OCF_LE_CLEAR_WHITE_LIST 0x10 +#define HCI_OCF_LE_ADD_DEV_WHITE_LIST 0x11 +#define HCI_OCF_LE_REMOVE_DEV_WHITE_LIST 0x12 +#define HCI_OCF_LE_CONN_UPDATE 0x13 +#define HCI_OCF_LE_SET_HOST_CHAN_CLASS 0x14 +#define HCI_OCF_LE_READ_CHAN_MAP 0x15 +#define HCI_OCF_LE_READ_REMOTE_FEAT 0x16 +#define HCI_OCF_LE_ENCRYPT 0x17 +#define HCI_OCF_LE_RAND 0x18 +#define HCI_OCF_LE_START_ENCRYPTION 0x19 +#define HCI_OCF_LE_LTK_REQ_REPL 0x1A +#define HCI_OCF_LE_LTK_REQ_NEG_REPL 0x1B +#define HCI_OCF_LE_READ_SUP_STATES 0x1C +#define HCI_OCF_LE_RECEIVER_TEST 0x1D +#define HCI_OCF_LE_TRANSMITTER_TEST 0x1E +#define HCI_OCF_LE_TEST_END 0x1F +/* New in version 4.1 */ +#define HCI_OCF_LE_REM_CONN_PARAM_REP 0x20 +#define HCI_OCF_LE_REM_CONN_PARAM_NEG_REP 0x21 +/* New in version 4.2 */ +#define HCI_OCF_LE_SET_DATA_LEN 0x22 +#define HCI_OCF_LE_READ_DEF_DATA_LEN 0x23 +#define HCI_OCF_LE_WRITE_DEF_DATA_LEN 0x24 +#define HCI_OCF_LE_READ_LOCAL_P256_PUB_KEY 0x25 +#define HCI_OCF_LE_GENERATE_DHKEY 0x26 +#define HCI_OCF_LE_ADD_DEV_RES_LIST 0x27 +#define HCI_OCF_LE_REMOVE_DEV_RES_LIST 0x28 +#define HCI_OCF_LE_CLEAR_RES_LIST 0x29 +#define HCI_OCF_LE_READ_RES_LIST_SIZE 0x2A +#define HCI_OCF_LE_READ_PEER_RES_ADDR 0x2B +#define HCI_OCF_LE_READ_LOCAL_RES_ADDR 0x2C +#define HCI_OCF_LE_SET_ADDR_RES_ENABLE 0x2D +#define HCI_OCF_LE_SET_RES_PRIV_ADDR_TO 0x2E +#define HCI_OCF_LE_READ_MAX_DATA_LEN 0x2F +/* New in version 5.0 */ +#define HCI_OCF_LE_READ_PHY 0x30 +#define HCI_OCF_LE_SET_DEF_PHY 0x31 +#define HCI_OCF_LE_SET_PHY 0x32 +#define HCI_OCF_LE_ENHANCED_RECEIVER_TEST 0x33 +#define HCI_OCF_LE_ENHANCED_TRANSMITTER_TEST 0x34 +#define HCI_OCF_LE_SET_ADV_SET_RAND_ADDR 0x35 +#define HCI_OCF_LE_SET_EXT_ADV_PARAM 0x36 +#define HCI_OCF_LE_SET_EXT_ADV_DATA 0x37 +#define HCI_OCF_LE_SET_EXT_SCAN_RESP_DATA 0x38 +#define HCI_OCF_LE_SET_EXT_ADV_ENABLE 0x39 +#define HCI_OCF_LE_READ_MAX_ADV_DATA_LEN 0x3A +#define HCI_OCF_LE_READ_NUM_SUP_ADV_SETS 0x3B +#define HCI_OCF_LE_REMOVE_ADV_SET 0x3C +#define HCI_OCF_LE_CLEAR_ADV_SETS 0x3D +#define HCI_OCF_LE_SET_PER_ADV_PARAM 0x3E +#define HCI_OCF_LE_SET_PER_ADV_DATA 0x3F +#define HCI_OCF_LE_SET_PER_ADV_ENABLE 0x40 +#define HCI_OCF_LE_SET_EXT_SCAN_PARAM 0x41 +#define HCI_OCF_LE_SET_EXT_SCAN_ENABLE 0x42 +#define HCI_OCF_LE_EXT_CREATE_CONN 0x43 +#define HCI_OCF_LE_PER_ADV_CREATE_SYNC 0x44 +#define HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL 0x45 +#define HCI_OCF_LE_PER_ADV_TERM_SYNC 0x46 +#define HCI_OCF_LE_ADD_DEV_PER_ADV_LIST 0x47 +#define HCI_OCF_LE_REMOVE_DEV_PER_ADV_LIST 0x48 +#define HCI_OCF_LE_CLEAR_PER_ADV_LIST 0x49 +#define HCI_OCF_LE_READ_PER_ADV_LIST_SIZE 0x4A +#define HCI_OCF_LE_READ_TX_POWER 0x4B +#define HCI_OCF_LE_READ_RF_PATH_COMP 0x4C +#define HCI_OCF_LE_WRITE_RF_PATH_COMP 0x4D +#define HCI_OCF_LE_SET_PRIVACY_MODE 0x4E + +/* Opcode manipulation macros */ +#define HCI_OPCODE(ogf, ocf) (((ogf) << 10) + (ocf)) +#define HCI_OGF(opcode) ((opcode) >> 10) +#define HCI_OCF(opcode) ((opcode) & 0x03FF) + +/* Command opcodes */ +#define HCI_OPCODE_NOP HCI_OPCODE(HCI_OGF_NOP, HCI_OCF_NOP) + +#define HCI_OPCODE_DISCONNECT HCI_OPCODE(HCI_OGF_LINK_CONTROL, HCI_OCF_DISCONNECT) +#define HCI_OPCODE_READ_REMOTE_VER_INFO HCI_OPCODE(HCI_OGF_LINK_CONTROL, HCI_OCF_READ_REMOTE_VER_INFO) + +#define HCI_OPCODE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK) +#define HCI_OPCODE_RESET HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_RESET) +#define HCI_OPCODE_READ_TX_PWR_LVL HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_TX_PWR_LVL) +#define HCI_OPCODE_SET_EVENT_MASK_PAGE2 HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK_PAGE2) +#define HCI_OPCODE_READ_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_AUTH_PAYLOAD_TO) +#define HCI_OPCODE_WRITE_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_WRITE_AUTH_PAYLOAD_TO) + +#define HCI_OPCODE_READ_LOCAL_VER_INFO HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_VER_INFO) +#define HCI_OPCODE_READ_LOCAL_SUP_CMDS HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_SUP_CMDS) +#define HCI_OPCODE_READ_LOCAL_SUP_FEAT HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_SUP_FEAT) +#define HCI_OPCODE_READ_BUF_SIZE HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_BUF_SIZE) +#define HCI_OPCODE_READ_BD_ADDR HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_BD_ADDR) + +#define HCI_OPCODE_READ_RSSI HCI_OPCODE(HCI_OGF_STATUS, HCI_OCF_READ_RSSI) + +#define HCI_OPCODE_LE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EVENT_MASK) +#define HCI_OPCODE_LE_READ_BUF_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_BUF_SIZE) +#define HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_SUP_FEAT) +#define HCI_OPCODE_LE_SET_RAND_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_RAND_ADDR) +#define HCI_OPCODE_LE_SET_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_PARAM) +#define HCI_OPCODE_LE_READ_ADV_TX_POWER HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_ADV_TX_POWER) +#define HCI_OPCODE_LE_SET_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_DATA) +#define HCI_OPCODE_LE_SET_SCAN_RESP_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_RESP_DATA) +#define HCI_OPCODE_LE_SET_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_ENABLE) +#define HCI_OPCODE_LE_SET_SCAN_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_PARAM) +#define HCI_OPCODE_LE_SET_SCAN_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_ENABLE) +#define HCI_OPCODE_LE_CREATE_CONN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CREATE_CONN) +#define HCI_OPCODE_LE_CREATE_CONN_CANCEL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CREATE_CONN_CANCEL) +#define HCI_OPCODE_LE_READ_WHITE_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_WHITE_LIST_SIZE) +#define HCI_OPCODE_LE_CLEAR_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_WHITE_LIST) +#define HCI_OPCODE_LE_ADD_DEV_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_WHITE_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_WHITE_LIST) +#define HCI_OPCODE_LE_CONN_UPDATE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CONN_UPDATE) +#define HCI_OPCODE_LE_SET_HOST_CHAN_CLASS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_HOST_CHAN_CLASS) +#define HCI_OPCODE_LE_READ_CHAN_MAP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_CHAN_MAP) +#define HCI_OPCODE_LE_READ_REMOTE_FEAT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_REMOTE_FEAT) +#define HCI_OPCODE_LE_ENCRYPT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENCRYPT) +#define HCI_OPCODE_LE_RAND HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_RAND) +#define HCI_OPCODE_LE_START_ENCRYPTION HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_START_ENCRYPTION) +#define HCI_OPCODE_LE_LTK_REQ_REPL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_LTK_REQ_REPL) +#define HCI_OPCODE_LE_LTK_REQ_NEG_REPL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_LTK_REQ_NEG_REPL) +#define HCI_OPCODE_LE_READ_SUP_STATES HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_SUP_STATES) +#define HCI_OPCODE_LE_RECEIVER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_RECEIVER_TEST) +#define HCI_OPCODE_LE_TRANSMITTER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_TRANSMITTER_TEST) +#define HCI_OPCODE_LE_TEST_END HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_TEST_END) +/* New in version 4.1 */ +#define HCI_OPCODE_LE_REM_CONN_PARAM_REP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REM_CONN_PARAM_REP) +#define HCI_OPCODE_LE_REM_CONN_PARAM_NEG_REP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REM_CONN_PARAM_NEG_REP) +/* New in version 4.2 */ +#define HCI_OPCODE_LE_SET_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DATA_LEN) +#define HCI_OPCODE_LE_READ_DEF_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_DEF_DATA_LEN) +#define HCI_OPCODE_LE_WRITE_DEF_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_WRITE_DEF_DATA_LEN) +#define HCI_OPCODE_LE_READ_LOCAL_P256_PUB_KEY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_P256_PUB_KEY) +#define HCI_OPCODE_LE_GENERATE_DHKEY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_GENERATE_DHKEY) +#define HCI_OPCODE_LE_ADD_DEV_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_RES_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_RES_LIST) +#define HCI_OPCODE_LE_CLEAR_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_RES_LIST) +#define HCI_OPCODE_LE_READ_RES_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_RES_LIST_SIZE) +#define HCI_OPCODE_LE_READ_PEER_RES_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PEER_RES_ADDR) +#define HCI_OPCODE_LE_READ_LOCAL_RES_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_RES_ADDR) +#define HCI_OPCODE_LE_SET_ADDR_RES_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADDR_RES_ENABLE) +#define HCI_OPCODE_LE_SET_RES_PRIV_ADDR_TO HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_RES_PRIV_ADDR_TO) +#define HCI_OPCODE_LE_READ_MAX_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_MAX_DATA_LEN) +/* New in version 5.0 */ +#define HCI_OPCODE_LE_READ_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PHY) +#define HCI_OPCODE_LE_SET_DEF_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DEF_PHY) +#define HCI_OPCODE_LE_SET_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PHY) +#define HCI_OPCODE_LE_ENHANCED_RECEIVER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENHANCED_RECEIVER_TEST) +#define HCI_OPCODE_LE_ENHANCED_TRANSMITTER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENHANCED_TRANSMITTER_TEST) +#define HCI_OPCODE_LE_SET_ADV_SET_RAND_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_SET_RAND_ADDR) +#define HCI_OPCODE_LE_SET_EXT_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_PARAM) +#define HCI_OPCODE_LE_SET_EXT_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_DATA) +#define HCI_OPCODE_LE_SET_EXT_SCAN_RESP_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_RESP_DATA) +#define HCI_OPCODE_LE_SET_EXT_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_ENABLE) +#define HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_MAX_ADV_DATA_LEN) +#define HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_NUM_SUP_ADV_SETS) +#define HCI_OPCODE_LE_REMOVE_ADV_SET HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_ADV_SET) +#define HCI_OPCODE_LE_CLEAR_ADV_SETS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_ADV_SETS) +#define HCI_OPCODE_LE_SET_PER_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_PARAM) +#define HCI_OPCODE_LE_SET_PER_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_DATA) +#define HCI_OPCODE_LE_SET_PER_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_ENABLE) +#define HCI_OPCODE_LE_SET_EXT_SCAN_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_PARAM) +#define HCI_OPCODE_LE_SET_EXT_SCAN_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_ENABLE) +#define HCI_OPCODE_LE_EXT_CREATE_CONN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_EXT_CREATE_CONN) +#define HCI_OPCODE_LE_PER_ADV_CREATE_SYNC HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_CREATE_SYNC) +#define HCI_OPCODE_LE_PER_ADV_CREATE_SYNC_CANCEL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL) +#define HCI_OPCODE_LE_PER_ADV_TERMINATE_SYNC HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_TERM_SYNC) +#define HCI_OPCODE_LE_ADD_DEV_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_PER_ADV_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_PER_ADV_LIST) +#define HCI_OPCODE_LE_CLEAR_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_PER_ADV_LIST) +#define HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PER_ADV_LIST_SIZE) +#define HCI_OPCODE_LE_READ_TX_POWER HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_TX_POWER) +#define HCI_OPCODE_LE_WRITE_RF_PATH_COMP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_WRITE_RF_PATH_COMP) +#define HCI_OPCODE_LE_READ_RF_PATH_COMP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_RF_PATH_COMP) +#define HCI_OPCODE_LE_SET_PRIVACY_MODE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PRIVACY_MODE) + +/* ARM Vendor Specific */ +#define HCI_OPCODE_LE_VS_ENABLE_READ_FEAT_ON_CONN ((uint16_t)(0xfff3)) + +/* Command parameter lengths */ +#define HCI_LEN_NOP 0 + +#define HCI_LEN_DISCONNECT 3 +#define HCI_LEN_READ_REMOTE_VER_INFO 2 + +#define HCI_LEN_SET_EVENT_MASK 8 +#define HCI_LEN_SET_EVENT_MASK_PAGE2 8 +#define HCI_LEN_RESET 0 +#define HCI_LEN_READ_TX_PWR_LVL 3 +#define HCI_LEN_SET_CONTROLLER_TO_HOST_FC 1 +#define HCI_LEN_HOST_BUFFER_SIZE 8 +#define HCI_LEN_HOST_NUM_CMPL_PKTS 1 + +#define HCI_LEN_READ_LOCAL_VER_INFO 0 +#define HCI_LEN_READ_LOCAL_SUP_CMDS 0 +#define HCI_LEN_READ_LOCAL_SUP_FEAT 0 +#define HCI_LEN_READ_BUF_SIZE 0 +#define HCI_LEN_READ_BD_ADDR 0 + +#define HCI_LEN_READ_RSSI 2 +#define HCI_LEN_READ_AUTH_PAYLOAD_TO 2 +#define HCI_LEN_WRITE_AUTH_PAYLOAD_TO 4 + +#define HCI_LEN_LE_SET_EVENT_MASK 8 +#define HCI_LEN_LE_READ_BUF_SIZE 0 +#define HCI_LEN_LE_READ_LOCAL_SUP_FEAT 0 +#define HCI_LEN_LE_SET_RAND_ADDR 6 +#define HCI_LEN_LE_SET_ADV_PARAM 15 +#define HCI_LEN_LE_READ_ADV_TX_POWER 0 +#define HCI_LEN_LE_SET_ADV_DATA 32 +#define HCI_LEN_LE_SET_SCAN_RESP_DATA 32 +#define HCI_LEN_LE_SET_ADV_ENABLE 1 +#define HCI_LEN_LE_SET_SCAN_PARAM 7 +#define HCI_LEN_LE_SET_SCAN_ENABLE 2 +#define HCI_LEN_LE_CREATE_CONN 25 +#define HCI_LEN_LE_CREATE_CONN_CANCEL 0 +#define HCI_LEN_LE_READ_WHITE_LIST_SIZE 0 +#define HCI_LEN_LE_CLEAR_WHITE_LIST 0 +#define HCI_LEN_LE_ADD_DEV_WHITE_LIST 7 +#define HCI_LEN_LE_REMOVE_DEV_WHITE_LIST 7 +#define HCI_LEN_LE_CONN_UPDATE 14 +#define HCI_LEN_LE_SET_HOST_CHAN_CLASS 5 +#define HCI_LEN_LE_READ_CHAN_MAP 2 +#define HCI_LEN_LE_READ_REMOTE_FEAT 2 +#define HCI_LEN_LE_ENCRYPT 32 +#define HCI_LEN_LE_RAND 0 +#define HCI_LEN_LE_START_ENCRYPTION 28 +#define HCI_LEN_LE_LTK_REQ_REPL 18 +#define HCI_LEN_LE_LTK_REQ_NEG_REPL 2 +#define HCI_LEN_LE_READ_SUP_STATES 0 +#define HCI_LEN_LE_RECEIVER_TEST 1 +#define HCI_LEN_LE_TRANSMITTER_TEST 3 +#define HCI_LEN_LE_TEST_END 0 +/* New in version 4.1 */ +#define HCI_LEN_LE_REM_CONN_PARAM_REP 14 +#define HCI_LEN_LE_REM_CONN_PARAM_NEG_REP 3 +/* New in version 4.2 */ +#define HCI_LEN_LE_SET_DATA_LEN 6 +#define HCI_LEN_LE_READ_DEF_DATA_LEN 0 +#define HCI_LEN_LE_WRITE_DEF_DATA_LEN 4 +#define HCI_LEN_LE_READ_LOCAL_P256_PUB_KEY 0 +#define HCI_LEN_LE_GENERATE_DHKEY 64 +#define HCI_LEN_LE_ADD_DEV_RES_LIST 39 +#define HCI_LEN_LE_REMOVE_DEV_RES_LIST 7 +#define HCI_LEN_LE_CLEAR_RES_LIST 0 +#define HCI_LEN_LE_READ_RES_LIST_SIZE 0 +#define HCI_LEN_LE_READ_PEER_RES_ADDR 7 +#define HCI_LEN_LE_READ_LOCAL_RES_ADDR 7 +#define HCI_LEN_LE_SET_ADDR_RES_ENABLE 1 +#define HCI_LEN_LE_SET_RES_PRIV_ADDR_TO 2 +#define HCI_LEN_LE_READ_MAX_DATA_LEN 0 +/* New in version 5.0 */ +#define HCI_LEN_LE_READ_PHY 2 +#define HCI_LEN_LE_SET_DEF_PHY 3 +#define HCI_LEN_LE_SET_PHY 7 +#define HCI_LEN_LE_ENHANCED_RECEIVER_TEST 3 +#define HCI_LEN_LE_ENHANCED_TRANSMITTER_TEST 4 +#define HCI_LEN_LE_SET_ADV_SET_RAND_ADDR 7 +#define HCI_LEN_LE_SET_EXT_ADV_PARAM 25 +#define HCI_LEN_LE_SET_EXT_ADV_DATA(len) (4 + (len)) +#define HCI_LEN_LE_SET_EXT_SCAN_RESP_DATA(len) (4 + (len)) +#define HCI_LEN_LE_EXT_ADV_ENABLE(numSets) (2 + (4 * (numSets))) +#define HCI_LEN_LE_READ_MAX_ADV_DATA_LEN 0 +#define HCI_LEN_LE_READ_NUM_OF_SUP_ADV_SETS 0 +#define HCI_LEN_LE_REMOVE_ADV_SET 1 +#define HCI_LEN_LE_CLEAR_ADV_SETS 0 +#define HCI_LEN_LE_SET_PER_ADV_PARAM 7 +#define HCI_LEN_LE_SET_PER_ADV_DATA(len) (3 + (len)) +#define HCI_LEN_LE_SET_PER_ADV_ENABLE 2 +#define HCI_LEN_LE_SET_EXT_SCAN_PARAM(numPhys) (3 + (5 * (numPhys))) +#define HCI_LEN_LE_SET_EXT_SCAN_ENABLE 6 +#define HCI_LEN_LE_EXT_CREATE_CONN(numPhys) (10 + (16 * (numPhys))) +#define HCI_LEN_LE_PER_ADV_CREATE_SYNC 14 +#define HCI_LEN_LE_PER_ADV_CREATE_SYNC_CANCEL 0 +#define HCI_LEN_LE_PER_ADV_TERMINATE_SYNC 2 +#define HCI_LEN_LE_ADD_DEV_PER_ADV_LIST 8 +#define HCI_LEN_LE_REMOVE_DEV_PER_ADV_LIST 8 +#define HCI_LEN_LE_CLEAR_PER_ADV_LIST 0 +#define HCI_LEN_LE_READ_PER_ADV_LIST_SIZE 0 +#define HCI_LEN_LE_READ_TX_POWER 0 +#define HCI_LEN_LE_READ_RF_PATH_COMP 0 +#define HCI_LEN_LE_WRITE_RF_PATH_COMP 4 +#define HCI_LEN_LE_SET_PRIVACY_MODE 8 + +/* Events */ +#define HCI_DISCONNECT_CMPL_EVT 0x05 +#define HCI_ENC_CHANGE_EVT 0x08 +#define HCI_READ_REMOTE_VER_INFO_CMPL_EVT 0x0C +#define HCI_CMD_CMPL_EVT 0x0E +#define HCI_CMD_STATUS_EVT 0x0F +#define HCI_HW_ERROR_EVT 0x10 +#define HCI_NUM_CMPL_PKTS_EVT 0x13 +#define HCI_DATA_BUF_OVERFLOW_EVT 0x1A +#define HCI_ENC_KEY_REFRESH_CMPL_EVT 0x30 +#define HCI_LE_META_EVT 0x3E +#define HCI_AUTH_PAYLOAD_TIMEOUT_EVT 0x57 +#define HCI_VENDOR_SPEC_EVT 0xFF + +/* LE Subevents */ +#define HCI_LE_CONN_CMPL_EVT 0x01 +#define HCI_LE_ADV_REPORT_EVT 0x02 +#define HCI_LE_CONN_UPDATE_CMPL_EVT 0x03 +#define HCI_LE_READ_REMOTE_FEAT_CMPL_EVT 0x04 +#define HCI_LE_LTK_REQ_EVT 0x05 +/* New in version 4.1 */ +#define HCI_LE_REM_CONN_PARAM_REQ_EVT 0x06 +/* New in version 4.2 */ +#define HCI_LE_DATA_LEN_CHANGE_EVT 0x07 +#define HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_EVT 0x08 +#define HCI_LE_GENERATE_DHKEY_CMPL_EVT 0x09 +#define HCI_LE_ENHANCED_CONN_CMPL_EVT 0x0A +#define HCI_LE_DIRECT_ADV_REPORT_EVT 0x0B +/* New in version 5.0 */ +#define HCI_LE_PHY_UPDATE_CMPL_EVT 0x0C +#define HCI_LE_EXT_ADV_REPORT_EVT 0x0D +#define HCI_LE_PER_ADV_SYNC_EST_EVT 0x0E +#define HCI_LE_PER_ADV_REPORT_EVT 0x0F +#define HCI_LE_PER_ADV_SYNC_LOST_EVT 0x10 +#define HCI_LE_SCAN_TIMEOUT_EVT 0x11 +#define HCI_LE_ADV_SET_TERM_EVT 0x12 +#define HCI_LE_SCAN_REQ_RCVD_EVT 0x13 +#define HCI_LE_CH_SEL_ALGO_EVT 0x14 + +/* Event parameter lengths */ +#define HCI_LEN_DISCONNECT_CMPL 4 /*!< Disconnect event length. */ +#define HCI_LEN_READ_REMOTE_VER_INFO_CMPL 8 /*!< Read remove version info complete event length. */ +#define HCI_LEN_CMD_CMPL 3 /*!< Command complete event length. */ +#define HCI_LEN_CMD_STATUS 4 /*!< Command status event length. */ +#define HCI_LEN_HW_ERR 1 /*!< Hardware error event length. */ +#define HCI_LEN_NUM_CMPL_PKTS 5 /*!< Number of completed packets event length. */ +#define HCI_LEN_ENC_CHANGE 4 /*!< Encryption change event length. */ +#define HCI_LEN_ENC_KEY_REFRESH_CMPL 3 /*!< Encryption key refresh complete event length. */ +#define HCI_LEN_LE_CONN_CMPL 19 /*!< Connection complete event length. */ +#define HCI_LEN_LE_ADV_RPT_MIN 12 /*!< Advertising report event minimum length. */ +#define HCI_LEN_LE_CONN_UPDATE_CMPL 10 /*!< Connection update complete event length. */ +#define HCI_LEN_LE_READ_REMOTE_FEAT_CMPL 12 /*!< Read remote feature event length. */ +#define HCI_LEN_LE_LTK_REQ 13 /*!< LTK request event length. */ +/* New in version 4.1 */ +#define HCI_LEN_LE_REM_CONN_PARAM_REQ 11 /*!< Remote connection parameter event length. */ +#define HCI_LEN_LE_DATA_LEN_CHANGE 11 /*!< Data length change event length. */ +#define HCI_LEN_LE_READ_PUB_KEY_CMPL 66 /*!< Read local P256 public key compete event length. */ +#define HCI_LEN_LE_GEN_DHKEY_CMPL 34 /*!< Generate DH key complete event length. */ +#define HCI_LEN_LE_ENHANCED_CONN_CMPL 31 /*!< Enhanced connection complete event length. */ +#define HCI_LEN_LE_DIRECT_ADV_REPORT 18 /*!< Direct advertising report event length. */ +#define HCI_LEN_AUTH_PAYLOAD_TIMEOUT 2 /*!< Authenticated payload timeout event length. */ +/* New in version 5.0 */ +#define HCI_LEN_LE_PHY_UPDATE_CMPL 6 /*!< PHY update complete event length. */ +#define HCI_LEN_LE_CH_SEL_ALGO 4 /*!< Channel selection algorithm event length. */ +#define HCI_LEN_LE_PHY_UPDATE_CMPL 6 /*!< PHY update complete event length. */ +#define HCI_LEN_LE_EXT_ADV_REPORT_MIN 26 /*!< Extended advertising report minimum length. */ +#define HCI_LEN_LE_PER_ADV_SYNC_EST 16 /*!< Periodic advertising sync established event length. */ +#define HCI_LEN_LE_PER_ADV_REPORT 8 /*!< Periodic advertising report event length. */ +#define HCI_LEN_LE_PER_ADV_SYNC_LOST 3 /*!< Periodic advertising sync lost event length. */ +#define HCI_LEN_LE_SCAN_TIMEOUT 1 /*!< Scan timeout event length. */ +#define HCI_LEN_LE_ADV_SET_TERM 6 /*!< Advertising set terminated event length. */ +#define HCI_LEN_LE_SCAN_REQ_RCVD 9 /*!< Scan request received event length. */ + +/* Supported commands */ +#define HCI_SUP_DISCONNECT 0x20 /* Byte 0 */ +#define HCI_SUP_READ_REMOTE_VER_INFO 0x80 /* Byte 2 */ +#define HCI_SUP_SET_EVENT_MASK 0x40 /* Byte 5 */ +#define HCI_SUP_RESET 0x80 /* Byte 5 */ +#define HCI_SUP_READ_TX_PWR_LVL 0x04 /* Byte 10 */ +#define HCI_SUP_READ_LOCAL_VER_INFO 0x08 /* Byte 14 */ +#define HCI_SUP_READ_LOCAL_SUP_FEAT 0x20 /* Byte 14 */ +#define HCI_SUP_READ_BD_ADDR 0x02 /* Byte 15 */ +#define HCI_SUP_READ_RSSI 0x20 /* Byte 15 */ +#define HCI_SUP_SET_EVENT_MASK_PAGE2 0x04 /* Byte 22 */ +#define HCI_SUP_LE_SET_EVENT_MASK 0x01 /* Byte 25 */ +#define HCI_SUP_LE_READ_BUF_SIZE 0x02 /* Byte 25 */ +#define HCI_SUP_LE_READ_LOCAL_SUP_FEAT 0x04 /* Byte 25 */ +#define HCI_SUP_LE_SET_RAND_ADDR 0x10 /* Byte 25 */ +#define HCI_SUP_LE_SET_ADV_PARAM 0x20 /* Byte 25 */ +#define HCI_SUP_LE_READ_ADV_TX_POWER 0x40 /* Byte 25 */ +#define HCI_SUP_LE_SET_ADV_DATA 0x80 /* Byte 25 */ +#define HCI_SUP_LE_SET_SCAN_RESP_DATA 0x01 /* Byte 26 */ +#define HCI_SUP_LE_SET_ADV_ENABLE 0x02 /* Byte 26 */ +#define HCI_SUP_LE_SET_SCAN_PARAM 0x04 /* Byte 26 */ +#define HCI_SUP_LE_SET_SCAN_ENABLE 0x08 /* Byte 26 */ +#define HCI_SUP_LE_CREATE_CONN 0x10 /* Byte 26 */ +#define HCI_SUP_LE_CREATE_CONN_CANCEL 0x20 /* Byte 26 */ +#define HCI_SUP_LE_READ_WHITE_LIST_SIZE 0x40 /* Byte 26 */ +#define HCI_SUP_LE_CLEAR_WHITE_LIST 0x80 /* Byte 26 */ +#define HCI_SUP_LE_ADD_DEV_WHITE_LIST 0x01 /* Byte 27 */ +#define HCI_SUP_LE_REMOVE_DEV_WHITE_LIST 0x02 /* Byte 27 */ +#define HCI_SUP_LE_CONN_UPDATE 0x04 /* Byte 27 */ +#define HCI_SUP_LE_SET_HOST_CHAN_CLASS 0x08 /* Byte 27 */ +#define HCI_SUP_LE_READ_CHAN_MAP 0x10 /* Byte 27 */ +#define HCI_SUP_LE_READ_REMOTE_FEAT 0x20 /* Byte 27 */ +#define HCI_SUP_LE_ENCRYPT 0x40 /* Byte 27 */ +#define HCI_SUP_LE_RAND 0x80 /* Byte 27 */ +#define HCI_SUP_LE_START_ENCRYPTION 0x01 /* Byte 28 */ +#define HCI_SUP_LE_LTK_REQ_REPL 0x02 /* Byte 28 */ +#define HCI_SUP_LE_LTK_REQ_NEG_REPL 0x04 /* Byte 28 */ +#define HCI_SUP_LE_READ_SUP_STATES 0x08 /* Byte 28 */ +#define HCI_SUP_LE_RECEIVER_TEST 0x10 /* Byte 28 */ +#define HCI_SUP_LE_TRANSMITTER_TEST 0x20 /* Byte 28 */ +#define HCI_SUP_LE_TEST_END 0x40 /* Byte 28 */ +#define HCI_SUP_READ_AUTH_PAYLOAD_TO 0x10 /* Byte 32 */ +#define HCI_SUP_WRITE_AUTH_PAYLOAD_TO 0x20 /* Byte 32 */ +/* New in version 4.1 */ +#define HCI_SUP_LE_REM_CONN_PARAM_REQ_REPL 0x10 /* Byte 33 */ +#define HCI_SUP_LE_REM_CONN_PARAM_REQ_NEG_REPL 0x20 /* Byte 33 */ +/* New in version 4.2 */ +#define HCI_SUP_LE_SET_DATA_LEN 0x40 /* Byte 33 */ +#define HCI_SUP_LE_READ_DEF_DATA_LEN 0x80 /* Byte 33 */ +#define HCI_SUP_LE_WRITE_DEF_DATA_LEN 0x01 /* Byte 34 */ +#define HCI_SUP_LE_READ_LOCAL_P256_PUB_KEY 0x02 /* Byte 34 */ +#define HCI_SUP_LE_GENERATE_DHKEY 0x04 /* Byte 34 */ +#define HCI_SUP_LE_ADD_DEV_RES_LIST_EVT 0x08 /* Byte 34 */ +#define HCI_SUP_LE_REMOVE_DEV_RES_LIST 0x10 /* Byte 34 */ +#define HCI_SUP_LE_CLEAR_RES_LIST 0x20 /* Byte 34 */ +#define HCI_SUP_LE_READ_RES_LIST_SIZE 0x40 /* Byte 34 */ +#define HCI_SUP_LE_READ_PEER_RES_ADDR 0x80 /* Byte 34 */ +#define HCI_SUP_LE_READ_LOCAL_RES_ADDR 0x01 /* Byte 35 */ +#define HCI_SUP_LE_SET_ADDR_RES_ENABLE 0x02 /* Byte 35 */ +#define HCI_SUP_LE_SET_RES_PRIV_ADDR_TO 0x04 /* Byte 35 */ +#define HCI_SUP_LE_READ_MAX_DATA_LEN 0x08 /* Byte 35 */ +/* New in version 5.0 */ +#define HCI_SUP_LE_READ_PHY 0x10 /* Byte 35 */ +#define HCI_SUP_LE_SET_DEF_PHY 0x20 /* Byte 35 */ +#define HCI_SUP_LE_SET_PHY 0x40 /* Byte 35 */ +#define HCI_SUP_LE_ENHANCED_RECEIVER_TEST 0x80 /* Byte 35 */ +#define HCI_SUP_LE_ENHANCED_TRANSMITTER_TEST 0x01 /* Byte 36 */ +#define HCI_SUP_LE_SET_ADV_SET_RAND_ADDR 0x02 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_PARAM 0x04 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_DATA 0x08 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_SCAN_RESP_DATA 0x10 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_ENABLE 0x20 /* Byte 36 */ +#define HCI_SUP_LE_READ_MAX_ADV_DATA_LEN 0x40 /* Byte 36 */ +#define HCI_SUP_LE_READ_NUM_OF_SUP_ADV_SETS 0x80 /* Byte 36 */ +#define HCI_SUP_LE_REMOVE_ADV_SET 0x01 /* Byte 37 */ +#define HCI_SUP_LE_CLEAR_ADV_SETS 0x02 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_PARAM 0x04 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_DATA 0x08 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_ENABLE 0x10 /* Byte 37 */ +#define HCI_SUP_LE_SET_EXT_SCAN_PARAM 0x20 /* Byte 37 */ +#define HCI_SUP_LE_SET_EXT_SCAN_ENABLE 0x40 /* Byte 37 */ +#define HCI_SUP_LE_EXT_CREATE_CONN 0x80 /* Byte 37 */ +#define HCI_SUP_LE_PER_ADV_CREATE_SYNC 0x01 /* Byte 38 */ +#define HCI_SUP_LE_PER_ADV_CREATE_SYNC_CANCEL 0x02 /* Byte 38 */ +#define HCI_SUP_LE_PER_ADV_TERMINATE_SYNC 0x04 /* Byte 38 */ +#define HCI_SUP_LE_ADD_DEV_PER_ADV_LIST 0x08 /* Byte 38 */ +#define HCI_SUP_LE_REMOVE_DEV_PER_ADV_LIST 0x10 /* Byte 38 */ +#define HCI_SUP_LE_CLEAR_PER_ADV_LIST 0x20 /* Byte 38 */ +#define HCI_SUP_LE_READ_PER_ADV_LIST_SIZE 0x40 /* Byte 38 */ +#define HCI_SUP_LE_READ_TX_POWER 0x80 /* Byte 38 */ +#define HCI_SUP_LE_READ_RF_PATH_COMP 0x01 /* Byte 39 */ +#define HCI_SUP_LE_WRITE_RF_PATH_COMP 0x02 /* Byte 39 */ +#define HCI_SUP_LE_SET_PRIVACY_MODE 0x04 /* Byte 39 */ +#define HCI_SUP_LE_SET_MIN_NUM_OF_USED_CH 0x08 /* Byte 39 */ + +/* Event mask */ +#define HCI_EVT_MASK_DISCONNECT_CMPL 0x10 /* Byte 0 */ +#define HCI_EVT_MASK_ENC_CHANGE 0x80 /* Byte 0 */ +#define HCI_EVT_MASK_READ_REMOTE_VER_INFO_CMPL 0x08 /* Byte 1 */ +#define HCI_EVT_MASK_HW_ERROR 0x80 /* Byte 1 */ +#define HCI_EVT_MASK_DATA_BUF_OVERFLOW 0x02 /* Byte 3 */ +#define HCI_EVT_MASK_ENC_KEY_REFRESH_CMPL 0x80 /* Byte 5 */ +#define HCI_EVT_MASK_LE_META 0x20 /* Byte 7 */ + +/* Event mask page 2 */ +#define HCI_EVT_MASK_AUTH_PAYLOAD_TIMEOUT 0x80 /* Byte 2 */ + +/* LE event mask */ +#define HCI_EVT_MASK_LE_CONN_CMPL_EVT 0x01 /* Byte 0 */ +#define HCI_EVT_MASK_LE_ADV_REPORT_EVT 0x02 /* Byte 0 */ +#define HCI_EVT_MASK_LE_CONN_UPDATE_CMPL_EVT 0x04 /* Byte 0 */ +#define HCI_EVT_MASK_LE_READ_REMOTE_FEAT_CMPL_EVT 0x08 /* Byte 0 */ +#define HCI_EVT_MASK_LE_LTK_REQ_EVT 0x10 /* Byte 0 */ +/* New in version 4.1 */ +#define HCI_EVT_MASK_LE_REMOTE_CONN_PARAM_REQ_EVT 0x20 /* Byte 0 */ +/* New in version 4.2 */ +#define HCI_EVT_MASK_LE_DATA_LEN_CHANGE_EVT 0x40 /* Byte 0 */ +#define HCI_EVT_MASK_LE_READ_LOCAL_P256_PUB_KEY_CMPL 0x80 /* Byte 0 */ +#define HCI_EVT_MASK_LE_GENERATE_DHKEY_CMPL 0x01 /* Byte 1 */ +#define HCI_EVT_MASK_LE_ENHANCED_CONN_CMPL_EVT 0x02 /* Byte 1 */ +#define HCI_EVT_MASK_LE_DIRECT_ADV_REPORT_EVT 0x04 /* Byte 1 */ +/* New in version 5.0 */ +#define HCI_EVT_MASK_LE_PHY_UPDATE_CMPL_EVT 0x08 /* Byte 1 */ +#define HCI_EVT_MASK_LE_EXT_ADV_REPORT_EVT 0x10 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_SYNC_EST_EVT 0x20 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_REPORT_EVT 0x40 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_SYNC_LOST_EVT 0x80 /* Byte 1 */ +#define HCI_EVT_MASK_LE_SCAN_TIMEOUT_EVT 0x01 /* Byte 2 */ +#define HCI_EVT_MASK_LE_ADV_SET_TERM_EVT 0x02 /* Byte 2 */ +#define HCI_EVT_MASK_LE_SCAN_REQ_RCVD_EVT 0x04 /* Byte 2 */ +#define HCI_EVT_MASK_LE_CH_SEL_ALGO_EVT 0x08 /* Byte 2 */ + +/* LE supported features */ +/* New in version 4.0 */ +#define HCI_LE_SUP_FEAT_ENCRYPTION 0x0001 /*!< Encryption supported */ +/* New in version 4.1 */ +#define HCI_LE_SUP_FEAT_CONN_PARAM_REQ_PROC 0x0002 /*!< Connection Parameters Request Procedure supported */ +#define HCI_LE_SUP_FEAT_EXT_REJECT_IND 0x0004 /*!< Extended Reject Indication supported */ +#define HCI_LE_SUP_FEAT_SLV_INIT_FEAT_EXCH 0x0008 /*!< Slave-Initiated Features Exchange supported */ +#define HCI_LE_SUP_FEAT_LE_PING 0x0010 /*!< LE Ping supported */ +/* New in version 4.2 */ +#define HCI_LE_SUP_FEAT_DATA_LEN_EXT 0x0020 /*!< Data Length Extension supported */ +#define HCI_LE_SUP_FEAT_PRIVACY 0x0040 /*!< LL Privacy supported */ +#define HCI_LE_SUP_FEAT_EXT_SCAN_FILT_POLICY 0x0080 /*!< Extended Scan Filter Policy supported */ +/* New in version 5.0 */ +#define HCI_LE_SUP_FEAT_LE_2M_PHY 0x0100 /*!< LE 2M PHY supported */ +#define HCI_LE_SUP_FEAT_STABLE_MOD_IDX_TRANSMITTER 0x0200 /*!< Stable Modulation Index - Transmitter supported */ +#define HCI_LE_SUP_FEAT_STABLE_MOD_IDX_RECEIVER 0x0400 /*!< Stable Modulation Index - Receiver supported */ +#define HCI_LE_SUP_FEAT_LE_CODED_PHY 0x0800 /*!< LE Coded PHY supported */ +#define HCI_LE_SUP_FEAT_LE_EXT_ADV 0x1000 /*!< LE Extended Advertising supported */ +#define HCI_LE_SUP_FEAT_LE_PER_ADV 0x2000 /*!< LE Periodic Advertising supported */ +#define HCI_LE_SUP_FEAT_CH_SEL_2 0x4000 /*!< Channel Selection Algorithm #2 supported */ +#define HCI_LE_SUP_FEAT_LE_POWER_CLASS_1 0x8000 /*!< LE Power Class 1 supported */ + +/* Advertising command parameters */ +#define HCI_ADV_MIN_INTERVAL 0x0020 /*!< Minimum advertising interval */ +#define HCI_ADV_MAX_INTERVAL 0x4000 /*!< Maximum advertising interval */ +#define HCI_ADV_DIRECTED_MAX_DURATION 0x0500 /*!< Maximum high duty cycle connectable directed advertising duration */ +#define HCI_ADV_TYPE_CONN_UNDIRECT 0x00 /*!< Connectable undirected advertising */ +#define HCI_ADV_TYPE_CONN_DIRECT 0x01 /*!< Connectable directed high duty cycle advertising */ +#define HCI_ADV_TYPE_DISC_UNDIRECT 0x02 /*!< Discoverable undirected advertising */ +#define HCI_ADV_TYPE_NONCONN_UNDIRECT 0x03 /*!< Nonconnectable undirected advertising */ +#define HCI_ADV_TYPE_CONN_DIRECT_LO_DUTY 0x04 /*!< Connectable directed low duty cycle advertising */ +#define HCI_ADV_CHAN_37 0x01 /*!< Advertising channel 37 */ +#define HCI_ADV_CHAN_38 0x02 /*!< Advertising channel 38 */ +#define HCI_ADV_CHAN_39 0x04 /*!< Advertising channel 39 */ +#define HCI_ADV_FILT_NONE 0x00 /*!< No scan request or connection filtering */ +#define HCI_ADV_FILT_SCAN 0x01 /*!< White list filters scan requests */ +#define HCI_ADV_FILT_CONN 0x02 /*!< White list filters connections */ +#define HCI_ADV_FILT_ALL 0x03 /*!< White list filters scan req. and conn. */ + +/* Scan command parameters */ +#define HCI_SCAN_TYPE_PASSIVE 0 /*!< Passive scan */ +#define HCI_SCAN_TYPE_ACTIVE 1 /*!< Active scan */ +#define HCI_SCAN_INTERVAL_MIN 0x0004 /*!< Minimum scan interval */ +#define HCI_SCAN_INTERVAL_MAX 0x4000 /*!< Maximum scan interval */ +#define HCI_SCAN_INTERVAL_DEFAULT 0x0010 /*!< Default scan interval */ +#define HCI_SCAN_WINDOW_MIN 0x0004 /*!< Minimum scan window */ +#define HCI_SCAN_WINDOW_MAX 0x4000 /*!< Maximum scan window */ +#define HCI_SCAN_WINDOW_DEFAULT 0x0010 /*!< Default scan window */ + +/* Connection command parameters */ +#define HCI_CONN_INTERVAL_MIN 0x0006 /*!< Minimum connection interval */ +#define HCI_CONN_INTERVAL_MAX 0x0C80 /*!< Maximum connection interval */ +#define HCI_CONN_LATENCY_MAX 0x01F3 /*!< Maximum connection latency */ +#define HCI_SUP_TIMEOUT_MIN 0x000A /*!< Minimum supervision timeout */ +#define HCI_SUP_TIMEOUT_MAX 0x0C80 /*!< Maximum supervision timeout */ + +/* Connection event parameters */ +#define HCI_ROLE_MASTER 0 /*!< Role is master */ +#define HCI_ROLE_SLAVE 1 /*!< Role is slave */ +#define HCI_CLOCK_500PPM 0x00 /*!< 500 ppm clock accuracy */ +#define HCI_CLOCK_250PPM 0x01 /*!< 250 ppm clock accuracy */ +#define HCI_CLOCK_150PPM 0x02 /*!< 150 ppm clock accuracy */ +#define HCI_CLOCK_100PPM 0x03 /*!< 100 ppm clock accuracy */ +#define HCI_CLOCK_75PPM 0x04 /*!< 75 ppm clock accuracy */ +#define HCI_CLOCK_50PPM 0x05 /*!< 50 ppm clock accuracy */ +#define HCI_CLOCK_30PPM 0x06 /*!< 30 ppm clock accuracy */ +#define HCI_CLOCK_20PPM 0x07 /*!< 20 ppm clock accuracy */ + +/* Advertising report event parameters */ +#define HCI_ADV_CONN_UNDIRECT 0x00 /*!< Connectable undirected advertising */ +#define HCI_ADV_CONN_DIRECT 0x01 /*!< Connectable directed advertising */ +#define HCI_ADV_DISC_UNDIRECT 0x02 /*!< Discoverable undirected advertising */ +#define HCI_ADV_NONCONN_UNDIRECT 0x03 /*!< Non-connectable undirected advertising */ +#define HCI_ADV_SCAN_RESPONSE 0x04 /*!< Scan response */ + +/*! Extended advertising data operations */ +#define HCI_ADV_DATA_OP_FRAG_INTER 0x00 /*!< Intermediate fragment */ +#define HCI_ADV_DATA_OP_FRAG_FIRST 0x01 /*!< First fragment */ +#define HCI_ADV_DATA_OP_FRAG_LAST 0x02 /*!< Last fragment */ +#define HCI_ADV_DATA_OP_COMP_FRAG 0x03 /*!< Complete extended advertising data */ +#define HCI_ADV_DATA_OP_UNCHANGED_DATA 0x04 /*!< Unchanged data (just update Advertising DID) */ + +/*! Advertising data fragment preference */ +#define HCI_ADV_DATA_FRAG_PREF_FRAG 0x00 /*!< Controller may fragment all Host advertising data */ +#define HCI_ADV_DATA_FRAG_PREF_NO_FRAG 0x01 /*!< Controller should not fragment nor minimize fragmentation of Host advertising data */ + +/*! Number of advertising sets */ +#define HCI_ADV_NUM_SETS_ALL_DISABLE 0x00 /*!< Disable all advertising sets */ + +/*! Maximum number of scanning or initiating PHYs */ +#define HCI_MAX_NUM_PHYS 3 /*! Maximum number of scanning or initiating PHYs */ + +/*! Advertising PHY values */ +#define HCI_ADV_PHY_LE_1M 0x01 /*!< LE 1M PHY */ +#define HCI_ADV_PHY_LE_2M 0x02 /*!< LE 2M PHY */ +#define HCI_ADV_PHY_LE_CODED 0x03 /*!< LE Coded PHY */ + +/*! Scanner PHY value bits */ +#define HCI_SCAN_PHY_LE_1M_BIT (1<<0) /*!< LE 1M PHY */ +#define HCI_SCAN_PHY_LE_2M_BIT (1<<1) /*!< LE 2M PHY */ +#define HCI_SCAN_PHY_LE_CODED_BIT (1<<2) /*!< LE Coded PHY */ + +/*! Initiator PHY value bits */ +#define HCI_INIT_PHY_LE_1M_BIT (1<<0) /*!< LE 1M PHY */ +#define HCI_INIT_PHY_LE_2M_BIT (1<<1) /*!< LE 2M PHY */ +#define HCI_INIT_PHY_LE_CODED_BIT (1<<2) /*!< LE Coded PHY */ + +/*! Advertising event properties type bits */ +#define HCI_ADV_PROP_CONN_ADV_BIT (1<<0) /*!< Connectable advertising bit */ +#define HCI_ADV_PROP_SCAN_ADV_BIT (1<<1) /*!< Scannable advertising bit */ +#define HCI_ADV_PROP_DIRECT_ADV_BIT (1<<2) /*!< Directed advertising bit */ +#define HCI_ADV_PROP_CONN_DIRECT_ADV_BIT (1<<3) /*!< High duty cycle connectable directed advertising bit */ +#define HCI_ADV_PROP_USE_LEG_PDU_BIT (1<<4) /*!< Use legacy advertising PDUs bit */ +#define HCI_ADV_PROP_OMIT_ADV_ADDR_BIT (1<<5) /*!< Omit advertiser's address from all PDUs (anonymous advertising) bit */ +#define HCI_ADV_PROP_INC_TX_PWR_BIT (1<<6) /*!< Include TxPower in extended header of advertising PDU bit */ + +/*! Advertising event properties for legacy PDUs */ +#define HCI_ADV_PROP_LEG_CONN_UNDIRECT 0x13 /*!< Connectable and scannable undirected advertising (00010011b) */ +#define HCI_ADV_PROP_LEG_CONN_DIRECT 0x1D /*!< Connectable directed high duty cycle advertising (00011101b) */ +#define HCI_ADV_PROP_LEG_SCAN_UNDIRECT 0x12 /*!< Scannable undirected advertising (00010010b) */ +#define HCI_ADV_PROP_LEG_NONCONN_UNDIRECT 0x10 /*!< Non-connectable and non-scannable undirected advertising (00010000b) */ +#define HCI_ADV_PROP_LEG_CONN_DIRECT_LO_DUTY 0x15 /*!< Connectable directed low duty cycle advertising (00010101b) */ + +/*! Extended advertising report event type bits */ +#define HCI_ADV_RPT_CONN_ADV_BIT (1<<0) /*!< Connectable advertising event bit */ +#define HCI_ADV_RPT_SCAN_ADV_BIT (1<<1) /*!< Scannable advertising event bit */ +#define HCI_ADV_RPT_DIRECT_ADV_BIT (1<<2) /*!< Directed advertising event bit */ +#define HCI_ADV_RPT_SCAN_RSP_BIT (1<<3) /*!< Scan response event bit */ +#define HCI_ADV_RPT_LEG_ADV_BIT (1<<4) /*!< Legacy advertising PDU event bit */ +#define HCI_ADV_RPT_DATA_STATUS_BITS (3<<5) /*!< Data status bits */ + +/*! Advertising report event types for legacy PDUs */ +#define HCI_ADV_RPT_LEG_CONN_UNDIRECT 0x13 /*! Connectable and scannable undirected advertising (0010011b) */ +#define HCI_ADV_RPT_LEG_CONN_DIRECT 0x15 /*! Connectable directed advertising (0010101b) */ +#define HCI_ADV_RPT_LEG_SCAN_UNDIRECT 0x12 /*! Scannable undirected advertising (0010010b) */ +#define HCI_ADV_RPT_LEG_NONCONN_UNDIRECT 0x10 /*! Non-connectable and non-scannable undirected advertising (0010000b) */ +#define HCI_ADV_RPT_LEG_CONN_UNDIRECT_SCAN_RSP 0x1B /*! Scan response to connectable and scannable undirected advertising (0011011b) */ +#define HCI_ADV_RPT_LEG_SCAN_UNDIRECT_SCAN_RSP 0x1A /*! Scan response to scannable undirected advertising (0011010b) */ + +/*! Advertising report data status */ +#define HCI_ADV_RPT_DATA_CMPL 0x00 /*!< Data complete */ +#define HCI_ADV_RPT_DATA_INCMPL_MORE 0x01 /*!< Data incomplete, more date to come */ +#define HCI_ADV_RPT_DATA_INCMPL_TRUNC 0x02 /*!< Data incomplete, data truncated, no more date to come */ + +/*! Extended advertising report event primary PHY values */ +#define HCI_ADV_RPT_PHY_PRIM_LE_1M 0x01 /*!< Advertiser PHY is LE 1M */ +#define HCI_ADV_RPT_PHY_PRIM_LE_CODED 0x03 /*!< Advertiser PHY is LE Coded */ + +/*! Extended advertising report event seconday PHY values */ +#define HCI_ADV_RPT_PHY_SEC_NONE 0x00 /*!< No packets on seconday advertising channel */ +#define HCI_ADV_RPT_PHY_SEC_LE_1M 0x01 /*!< Advertiser PHY is LE 1M */ +#define HCI_ADV_RPT_PHY_SEC_LE_2M 0x02 /*!< Advertiser PHY is LE 2M */ +#define HCI_ADV_RPT_PHY_SEC_LE_CODED 0x03 /*!< Advertiser PHY is LE Coded */ + +/*! Channel selection algorithm used */ +#define HCI_CH_SEL_ALGO_1 0x00 /*!< LE channel selection algorithm #1 used */ +#define HCI_CH_SEL_ALGO_2 0x01 /*!< LE channel selection algorithm #2 used */ + +/*! Minimum number of used channels */ +#define HCI_MIN_NUM_OF_USED_CHAN 8 /*!< Minimum number of used channels */ + +/* Misc command parameters */ +#define HCI_READ_TX_PWR_CURRENT 0 /*!< Read current tx power */ +#define HCI_READ_TX_PWR_MAX 1 /*!< Read maximum tx power */ +#define HCI_TX_PWR_MIN -30 /*!< Minimum tx power dBm */ +#define HCI_TX_PWR_MAX 20 /*!< Maximum tx power dBm */ +#define HCI_TX_PWR_NO_PREFERENCE 127 /*!< Tx power no preference */ +#define HCI_VERSION 6 /*!< HCI specification version */ +#define HCI_RSSI_MIN -127 /*!< Minimum RSSI dBm */ +#define HCI_RSSI_MAX 20 /*!< Maximum RSSI dBm */ +#define HCI_ADDR_TYPE_PUBLIC 0 /*!< Public device address */ +#define HCI_ADDR_TYPE_RANDOM 1 /*!< Random device address */ +#define HCI_ADDR_TYPE_PUBLIC_IDENTITY 2 /*!< Public identity address */ +#define HCI_ADDR_TYPE_RANDOM_IDENTITY 3 /*!< Random identity address */ +#define HCI_ADDR_TYPE_ANONYMOUS 0xFF /*!< Anonymous device address */ +#define HCI_FILT_NONE 0 /*!< Accept all advertising packets */ +#define HCI_FILT_WHITE_LIST 1 /*!< Accept from While List only */ +#define HCI_FILT_RES_INIT 2 /*!< Accept directed advertisements with RPAs */ +#define HCI_FILT_WHITE_LIST_RES_INIT 3 /*!< Accept from White List or directed advertisements with RPAs */ +#define HCI_FILT_PER_ADV_PARAM 0 /*!< Listen to advertiser specified by create sync command parameters */ +#define HCI_FILT_PER_ADV_LIST 1 /*!< Listen to advertiser from Periodic Advertiser List only */ +#define HCI_ROLE_MASTER 0 /*!< Role is master */ +#define HCI_ROLE_SLAVE 1 /*!< Role is slave */ +#define HCI_PRIV_MODE_NETWORK 0x00 /*!< Network privacy mode (default) */ +#define HCI_PRIV_MODE_DEVICE 0x01 /*!< Device privacy mode */ + +/*! PHY types */ +#define HCI_PHY_NONE 0x00 /*! No selected PHY */ +#define HCI_PHY_LE_1M_BIT (1<<0) /*! LE 1M PHY */ +#define HCI_PHY_LE_2M_BIT (1<<1) /*! LE 2M PHY */ +#define HCI_PHY_LE_CODED_BIT (1<<2) /*! LE Coded PHY */ + +/*! All PHYs preference */ +#define HCI_ALL_PHY_ALL_PREFERENCES 0x00 /*! All PHY preferences */ +#define HCI_ALL_PHY_TX_PREFERENCE_BIT (1<<0) /*! Tx PHY preference */ +#define HCI_ALL_PHY_RX_PREFERENCE_BIT (1<<1) /*! Rx PHY preference */ + +/*! PHY options */ +#define HCI_PHY_OPTIONS_NONE 0x00 /*! No preferences */ + +/* Parameter lengths */ +#define HCI_EVT_MASK_LEN 8 /*!< Length of event mask byte array */ +#define HCI_EVT_MASK_PAGE_2_LEN 8 /*!< Length of event mask page 2 byte array */ +#define HCI_LE_EVT_MASK_LEN 8 /*!< Length of LE event mask byte array */ +#define HCI_FEAT_LEN 8 /*!< Length of features byte array */ +#define HCI_ADV_DATA_LEN 31 /*!< Length of advertising data */ +#define HCI_SCAN_DATA_LEN 31 /*!< Length of scan response data */ +#define HCI_EXT_ADV_DATA_LEN 251 /*!< Length of extended advertising data */ +#define HCI_PER_ADV_DATA_LEN 252 /*!< Length of periodic advertising data */ +#define HCI_EXT_ADV_RPT_DATA_LEN 229 /*!< Length of extended advertising report data */ +#define HCI_PER_ADV_RPT_DATA_LEN 248 /*!< Length of periodic advertising report data */ +#define HCI_CHAN_MAP_LEN 5 /*!< Length of channel map byte array */ +#define HCI_KEY_LEN 16 /*!< Length of encryption key */ +#define HCI_ENCRYPT_DATA_LEN 16 /*!< Length of data used in encryption */ +#define HCI_RAND_LEN 8 /*!< Length of random number */ +#define HCI_LE_STATES_LEN 8 /*!< Length of LE states byte array */ +#define HCI_P256_KEY_LEN 64 /*!< Length of P256 key */ +#define HCI_DH_KEY_LEN 32 /*!< Length of DH Key */ + +#define HCI_EXT_ADV_RPT_DATA_LEN_OFFSET 23 /*!< Length field offset of extended advertising report data */ +#define HCI_PER_ADV_RPT_DATA_LEN_OFFSET 5 /*!< Length field offset of periodic advertising report data */ + +/* Company ID */ +#define HCI_ID_ARM 0x005F /*! ARM Ltd. company ID */ + +/* Manufacturer location in Local version */ +#define HCI_LOCAL_VER_MANUFACTURER_POS 4 + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h new file mode 100644 index 00000000000..8c00ef377c2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h @@ -0,0 +1,341 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer constant definitions. + * + * $Date: 2017-03-10 20:10:06 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11511 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ + +#ifndef LL_DEFS_H +#define LL_DEFS_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*** Version ***/ + +#define LL_VER_BT_CORE_SPEC_4_0 0x06 /*!< Bluetooth core specification 4.0 */ +#define LL_VER_BT_CORE_SPEC_4_1 0x07 /*!< Bluetooth core specification 4.1 */ +#define LL_VER_BT_CORE_SPEC_4_2 0x08 /*!< Bluetooth core specification 4.2 */ +#define LL_VER_BT_CORE_SPEC_5_0 0x09 /*!< Bluetooth core specification 5.0 */ + +#define LL_COMP_ID_ARM 0x005F /*!< ARM Ltd. company ID. */ + +/*** Common ***/ + +#define LL_RSSI_MIN -127 /*!< Minimum RSSI value. */ +#define LL_RSSI_MAX 20 /*!< Maximum RSSI value. */ +#define LL_RSSI_NOT_AVAIL 127 /*!< RSSI is not available. */ + +#define LL_CRC_LEN 3 /*!< CRC length. */ +#define LL_AA_LEN 4 /*!< Access address length. */ +#define LL_PREAMBLE_LEN_1M 1 /*!< Preamble length (LE 1M PHY). */ +#define LL_PREAMBLE_LEN_2M 2 /*!< Preamble length (LE 2M PHY). */ +#define LL_PREAMBLE_LEN_CODED_BITS 10 /*!< Preamble length (LE Coded PHY). */ +#define LL_CI_LEN_BITS 2 /*!< Coding indicator length (LE Coded PHY). */ +#define LL_TERM1_LEN_BITS 3 /*!< TERM1 length (LE Coded PHY). */ +#define LL_TERM2_LEN_BITS 3 /*!< TERM2 length (LE Coded PHY). */ + +#define LL_RAND_ADDR_MSBS_MASK 0x03 /*!< Mask of 2 most significant bits of BD Random Address */ +#define LL_RAND_ADDR_MSBS_POS 46 /*!< Position of 2 MSBs of BD Random Address */ +#define LL_RAND_ADDR_MSBS_STATIC 0x03 /*!< 2 most significant bits of BD Random Address are '0b11', static random address */ +#define LL_RAND_ADDR_MSBS_RPA 0x01 /*!< 2 most significant bits of BD Random Address are '0b01', resolvable private address */ +#define LL_RAND_ADDR_MSBS_NRPA 0x00 /*!< 2 most significant bits of BD Random Address are '0b00', non-resolvable private address */ +#define LL_RAND_ADDR_MSBS_IVLD 0x02 /*!< 2 most significant bits of BD Random Address are '0b10', invalid random address */ + +/*** Advertising PDU ***/ + +/*! \brief Advertising channel PDU types. */ +enum +{ + /* --- Core Spec 4.0 --- */ + LL_PDU_ADV_IND = 0, /*!< Connectable undirected advertising PDU. */ + LL_PDU_ADV_DIRECT_IND = 1, /*!< Connectable directed advertising PDU. */ + LL_PDU_ADV_NONCONN_IND = 2, /*!< Non-connectable undirected advertising PDU. */ + LL_PDU_SCAN_REQ = 3, /*!< Scan request PDU. */ + LL_PDU_SCAN_RSP = 4, /*!< Scan response PDU. */ + LL_PDU_CONNECT_IND = 5, /*!< Connect indication PDU. */ + LL_PDU_ADV_SCAN_IND = 6, /*!< Scannable undirected advertising PDU. */ + /* --- Core Spec 5.0 --- */ + LL_PDU_AUX_SCAN_REQ = 3, /*!< Auxiliary scan request PDU. */ + LL_PDU_AUX_CONNECT_REQ = 5, /*!< Auxiliary connect request PDU. */ + LL_PDU_ADV_EXT_IND = 7, /*!< Extended advertising PDU. */ + LL_PDU_AUX_ADV_IND = 7, /*!< Auxiliary advertising PDU. */ + LL_PDU_AUX_SCAN_RSP = 7, /*!< Auxiliary scan response PDU. */ + LL_PDU_AUX_SYNC_IND = 7, /*!< Auxiliary synchronize PDU. */ + LL_PDU_AUX_CHAIN_IND = 7, /*!< Auxiliary chain PDU. */ + LL_PDU_AUX_CONNECT_RSP = 8, /*!< Auxiliary connect response PDU. */ +}; + +#define LL_SCAN_REQ_PDU_LEN 12 /*!< Size of a scan request PDU. */ +#define LL_CONN_IND_PDU_LEN 34 /*!< Size of a connect indication PDU. */ + +#define LL_CHAN_ADV_MIN_IDX 37 /*!< Minimum advertising channel index. */ +#define LL_CHAN_ADV_MAX_IDX 39 /*!< Maximum advertising channel index. */ +#define LL_NUM_CHAN_ADV 3 /*!< Total number of advertising channels. */ + +#define LL_ADVBU_MAX_LEN 31 /*!< Maximum advertising channel host data length. */ +#define LL_ADVB_MAX_LEN 39 /*!< Maximum advertising channel PDU length. */ +#define LL_ADVB_MIN_LEN (LL_ADVB_MAX_LEN - LL_ADVBU_MAX_LEN) /*!< Minimum advertising channel packet length. */ +#define LL_ADVB_MAX_TIME_1M ((LL_BLE_US_PER_BYTE_1M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Maximum time for a 1M advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_2M ((LL_BLE_US_PER_BYTE_2M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_2M) + /*!< Maximum time for a 2M advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_S2 ((LL_BLE_US_PER_BYTE_CODED_S2 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) + /*!< Maximum time for a Coded S2 advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_S8 ((LL_BLE_US_PER_BYTE_CODED_S8 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) + /*!< Maximum time for a Coded S8 advertising channel PDU. */ + +#define LL_ADV_PKT_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for an advertising packet. */ +#define LL_SCAN_REQ_MAX_USEC ((8 * (LL_ADV_PREFIX_LEN + LL_SCAN_PREFIX_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Maximum time in microseconds for a scan request packet. */ +#define LL_SCAN_RSP_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for a scan response packet. */ + +#define LL_ADV_HDR_LEN 2 /*!< Advertising channel header length. */ +#define LL_ADV_HDR_TYPE_OFFS 0 /*!< Advertising header type offset. */ +#define LL_ADV_HDR_TYPE_MSK 0x0F /*!< Advertising header type mask. */ +#define LL_ADV_HDR_LEN_OFFS 1 /*!< Advertising header length offset. */ +#define LL_ADV_HDR_LEN_MSK 0x3F /*!< Advertising header length mask for 4.2. */ +#define LL_ADV_EXT_HDR_LEN_MSK 0xFF /*!< Advertising extension header length mask for 5.0. */ +#define LL_ADV_PREFIX_LEN 6 /*!< Advertising PDU payload prefix length (AdvA). */ +#define LL_SCAN_PREFIX_LEN 6 /*!< Scan request/response PDU payload prefix length (AdvA). */ + +#define LL_ADV_ACCESS_ADDR UINT32_C(0x8E89BED6) /*!< Advertising channel access address. */ +#define LL_ADV_CRC_INIT UINT32_C(0x555555) /*!< Advertising CRC initial value. */ + +#define LL_DIR_ADV_INTER_TICKS 6 /*!< Advertising interval between directed advertising events (3.75 ms). */ +#define LL_DIR_ADV_DUR_TICKS 2048 /*!< Maximum high duty cycle directed advertising duration (1.28 seconds). */ + +enum +{ + LL_EXT_HDR_ADV_ADDR_BIT = (1 << 0), /*!< Extended header AdvA bit. */ + LL_EXT_HDR_TGT_ADDR_BIT = (1 << 1), /*!< Extended header TargetA bit. */ + LL_EXT_HDR_SUPP_INFO_BIT = (1 << 2), /*!< Extended header SuppInfo bit. */ + LL_EXT_HDR_ADI_BIT = (1 << 3), /*!< Extended header AdvDataInfo bit. */ + LL_EXT_HDR_AUX_PTR_BIT = (1 << 4), /*!< Extended header AuxPtr bit. */ + LL_EXT_HDR_SYNC_INFO_BIT = (1 << 5), /*!< Extended header SyncInfo bit. */ + LL_EXT_HDR_TX_PWR_BIT = (1 << 6), /*!< Extended header TxPower bit. */ +}; + +#define LL_MAX_ADV_HANDEL 0xEF /*!< Maximum advertising handle. */ +#define LL_MAX_ADV_SID 0x0F /*!< Maximum advertising SID */ + + +#define LL_EXT_ADV_HDR_MIN_LEN 1 /*!< Minimum extended advertising header length (+1 for ExtHdrLen and AdvMode fields). */ +#define LL_EXT_ADV_HDR_MAX_LEN 64 /*!< Maximum extended advertising header length (+1 for ExtHdrLen and AdvMode fields). */ +#define LL_EXT_ADVBU_MAX_LEN 251 /*!< Maximum extended advertising channel PDU host data length. */ +#define LL_EXT_ADVB_MAX_LEN 257 /*!< Maximum extended advertising channel PDU length. */ + +#define LL_AUX_PTR_MAX_USEC 2457600 /*!< Maximum AuxPtr offset value in microseconds. */ + +#define LL_SYNC_MIN_TIMEOUT 0x000A /*!< Minimum synchronization timeout. */ +#define LL_SYNC_MAX_TIMEOUT 0x4000 /*!< Maximum synchronization timeout. */ +#define LL_SYNC_MAX_SKIP 0x01F3 /*!< Maximum synchronization skip. */ +#define LL_SYNC_MAX_HANDLE 0x0EFF /*!< Maximum synchronization handle. */ + +#define LL_PER_ADV_INT_MIN 0x0006 /*!< Minimum periodic advertising interval. */ + + +/*** Data PDU ***/ + +/*! \brief Data channel LL Control PDU types. */ +enum +{ + /* --- Core Spec 4.0 --- */ + LL_PDU_CONN_UPDATE_IND = 0x00, /*!< Connection update indication PDU. */ + LL_PDU_CHANNEL_MAP_IND = 0x01, /*!< Channel map indication PDU. */ + LL_PDU_TERMINATE_IND = 0x02, /*!< Terminate indication PDU. */ + LL_PDU_ENC_REQ = 0x03, /*!< Encryption request PDU. */ + LL_PDU_ENC_RSP = 0x04, /*!< Encryption response PDU. */ + LL_PDU_START_ENC_REQ = 0x05, /*!< Start encryption request PDU. */ + LL_PDU_START_ENC_RSP = 0x06, /*!< Start encryption response PDU. */ + LL_PDU_UNKNOWN_RSP = 0x07, /*!< Unknown response PDU. */ + LL_PDU_FEATURE_REQ = 0x08, /*!< Feature request PDU. */ + LL_PDU_FEATURE_RSP = 0x09, /*!< Feature response PDU. */ + LL_PDU_PAUSE_ENC_REQ = 0x0A, /*!< Pause encryption request PDU. */ + LL_PDU_PAUSE_ENC_RSP = 0x0B, /*!< Pause encryption response PDU. */ + LL_PDU_VERSION_IND = 0x0C, /*!< Version indication PDU. */ + LL_PDU_REJECT_IND = 0x0D, /*!< Reject indication PDU. */ + /* --- Core Spec 4.2 --- */ + LL_PDU_SLV_FEATURE_REQ = 0x0E, /*!< Slave feature request PDU. */ + LL_PDU_CONN_PARAM_REQ = 0x0F, /*!< Connection parameter request PDU. */ + LL_PDU_CONN_PARAM_RSP = 0x10, /*!< Connection parameter response PDU. */ + LL_PDU_REJECT_EXT_IND = 0x11, /*!< Reject extended indication PDU. */ + LL_PDU_PING_REQ = 0x12, /*!< Ping request PDU. */ + LL_PDU_PING_RSP = 0x13, /*!< Ping response PDU. */ + LL_PDU_LENGTH_REQ = 0x14, /*!< Data length request PDU. */ + LL_PDU_LENGTH_RSP = 0x15, /*!< Data length response PDU. */ + /* --- Core Spec 5.0 --- */ + LL_PDU_PHY_REQ = 0x16, /*!< PHY request PDU. */ + LL_PDU_PHY_RSP = 0x17, /*!< PHY response PDU. */ + LL_PDU_PHY_UPDATE_IND = 0x18, /*!< PHY update indication PDU. */ + LL_PDU_MIN_USED_CHAN_IND = 0x19, /*!< Minimum used channels indication PDU. */ + LL_PDU_UNSPECIFIED = 0xFF /*!< Unspecified PDU. */ +}; + +/* Data PDU length */ +/* --- Core Spec 4.0 --- */ +#define LL_CONN_UPD_IND_PDU_LEN 12 /*!< Connection update indication PDU length. */ +#define LL_CHAN_MAP_IND_PDU_LEN 8 /*!< Channel map indication PDU length. */ +#define LL_TERMINATE_IND_PDU_LEN 2 /*!< Terminate indication PDU length. */ +#define LL_ENC_REQ_LEN 23 /*!< Encryption request PDU length. */ +#define LL_ENC_RSP_LEN 13 /*!< Encryption response PDU length. */ +#define LL_START_ENC_LEN 1 /*!< Start encryption request/response PDU length. */ +#define LL_UNKNOWN_RSP_LEN 2 /*!< Unknown response PDU length. */ +#define LL_FEATURE_PDU_LEN 9 /*!< Feature request/response PDU length. */ +#define LL_PAUSE_ENC_LEN 1 /*!< Pause encryption request/response PDU length. */ +#define LL_VERSION_IND_PDU_LEN 6 /*!< Version indication PDU length. */ +#define LL_REJECT_IND_PDU_LEN 2 /*!< Reject indication PDU length. */ +/* --- Core Spec 4.2 --- */ +#define LL_CONN_PARAM_PDU_LEN 24 /*!< Connection parameter request or response PDU length. */ +#define LL_REJECT_EXT_IND_PDU_LEN 3 /*!< Reject extended indication PDU length. */ +#define LL_PING_PDU_LEN 1 /*!< Ping request/response PDU length. */ +#define LL_DATA_LEN_PDU_LEN 9 /*!< Data length request or response PDU length. */ +/* --- Core Spec 5.0 --- */ +#define LL_PHY_PDU_LEN 3 /*!< PHY request/response PDU length. */ +#define LL_PHY_UPD_IND_PDU_LEN 5 /*!< PHY update indication PDU length. */ +#define LL_MIN_USED_CHAN_PDU_LEN 3 /*!< Minimum used channels indication PDU length. */ + +#define LL_EMPTY_PDU_LEN 2 /*!< Length of an empty data PDU. */ + +#define LL_DATA_HDR_LEN 2 /*!< Data channel header length. */ +#define LL_DATA_MIC_LEN 4 /*!< Data channel PDU MIC length. */ + +#define LL_DATA_HDR_LLID_MSK 0x03 /*!< Data PDU LLID mask. */ +#define LL_DATA_HDR_LEN_MSK 0xFF /*!< Data header length mask. BLE 4.2 data len extension allows 8 bits. */ + +#define LL_MAX_NUM_CHAN_DATA 37 /*!< Maximum number of used data channels. */ +#define LL_MIN_NUM_CHAN_DATA 2 /*!< Minimum number of used data channels. */ + +/*! \brief Data PDU LLID types. */ +enum +{ + LL_LLID_VS_PDU = 0x00, /*!< Vendor specific PDU. */ + /* N.B. next two enumerations intentionally use identical values. */ + LL_LLID_EMPTY_PDU = 0x01, /*!< Empty PDU. */ + LL_LLID_CONT_PDU = 0x01, /*!< Data PDU: continuation fragment of an L2CAP message. */ + LL_LLID_START_PDU = 0x02, /*!< Data PDU: start of an L2CAP message or a complete L2CAP message with no fragmentation. */ + LL_LLID_CTRL_PDU = 0x03, /*!< Control PDU. */ +}; + +/*** Encryption ***/ + +#define LL_ECC_KEY_LEN 32 /*!< ECC key length. */ + +#define LL_DEF_RES_ADDR_TO_SEC 900 /*!< Default resolvable address timeout in seconds. */ + +#define LL_RAND_LEN 8 /*!< Length of random number */ +#define LL_KEY_LEN 16 /*!< Encryption key length. */ +#define LL_SKD_LEN LL_KEY_LEN /*!< Session key diversifier length. */ +#define LL_IV_LEN 8 /*!< Initialization vector length. */ + +#define LL_DEF_AUTH_TO_MS 30000 /*!< Default authentication timeout in milliseconds. */ + +/*** LLCP ***/ + +#define LL_DATA_LEN_TO_TIME_1M(len) ((LL_BLE_US_PER_BYTE_1M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_2M(len) ((LL_BLE_US_PER_BYTE_2M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_2M) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_CODED_S8(len) ((LL_BLE_US_PER_BYTE_CODED_S8 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_CODED_S2(len) ((LL_BLE_US_PER_BYTE_CODED_S2 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) + /*!< Convert data length to time. */ + +#define LL_MIN_INSTANT 6 /*!< Minimum number of CE to apply a CONN_UPD or CHAN_MAP. */ + +#define LL_MAX_DATA_LEN_MIN 27 /*!< Minimum value for maximum Data PDU length */ +#define LL_MAX_DATA_LEN_ABS_MAX 251 /*!< Absolute maximum limit for maximum Data PDU length */ + +#define LL_MAX_DATA_TIME_MIN 328 /*!< Minimum value for maximum Data PDU time */ +#define LL_MAX_DATA_TIME_ABS_MAX 17040 /*!< Absolute maximum limit for maximum Data PDU time */ +#define LL_MAX_DATA_TIME_ABS_MAX_1M 2120 /*!< Absolute maximum limit for maximum Data PDU time (LE 1M PHY) */ + +#define LL_T_PRT_SEC 40 /*!< LLCP procedure response timeout in seconds. */ + +#define LL_MAX_ADV_DLY_MS 10 /*!< Maximum advertising delay in milliseconds. */ + +#define LL_MIN_CONN_INTERVAL 6 /*!< Minimum value for connection interval. */ +#define LL_MAX_CONN_INTERVAL 3200 /*!< Maximum value for connection interval. */ + +#define LL_MIN_TX_WIN_SIZE 1 /*!< Minimum value for transmit window size. */ +#define LL_MAX_TX_WIN_SIZE 8 /*!< Maximum value for transmit window size. */ + +#define LL_MAX_CONN_LATENCY 499 /*!< Maximum value for connection slave latency. */ + +#define LL_MIN_SUP_TIMEOUT 10 /*!< Minimum value for connection supervision timeout. */ +#define LL_MAX_SUP_TIMEOUT 3200 /*!< Maximum value for connection supervision timeout. */ + +#define LL_MIN_POWER_THRESHOLD -128 /*!< Minimum value for power threshold. */ +#define LL_MAX_POWER_THRESHOLD 127 /*!< Maximum value for power threshold. */ + +#define LL_ALL_PHYS_MSK 0x7 /*!< All supported LE PHYs mask. */ + +/*** DTM ***/ + +#define LL_DTM_HDR_LEN 2 /*!< Direct Test Mode PDU header length. */ +#define LL_DTM_SYNC_WORD UINT32_C(0x71764129) /*!< Direct Test Mode sync word. */ +#define LL_DTM_CRC_INIT UINT32_C(0x555555) /*!< Direct Test Mode CRC initial value. */ +#define LL_DTM_MAX_INT_US 12500 /*!< Maximum time interval between packets in microseconds. */ +#define LL_DTM_PDU_ABS_MAX_LEN 255 /*!< Absolute maximum DTM PDU length. */ +#define LL_DTM_MAX_CHAN_IDX 39 /*!< Maximum channel index. */ + +/*** Baseband ***/ + +#define LL_CHAN_DATA_MIN_IDX 0 /*!< Minimum data channel index. */ +#define LL_CHAN_DATA_MAX_IDX 36 /*!< Maximum data channel index. */ +#define LL_CHAN_DATA_ALL UINT64_C(0x0000001FFFFFFFFF) /*!< Maximum data channel index. */ + +#define LL_BLE_BIT_PER_US 1 /*!< BLE PHY rate. */ +#define LL_BLE_US_PER_BYTE_1M 8 /*!< BLE PHY speed (LE 1M PHY). */ +#define LL_BLE_US_PER_BYTE_2M 4 /*!< BLE PHY speed (LE 2M PHY). */ +#define LL_BLE_US_PER_BYTE_CODED_S8 64 /*!< BLE PHY speed (LE Coded PHY, S=8). */ +#define LL_BLE_US_PER_BIT_CODED_S8 8 /*!< BLE PHY speed (LE Coded PHY, S=8). */ +#define LL_BLE_US_PER_BYTE_CODED_S2 16 /*!< BLE PHY speed (LE Coded PHY, S=2). */ +#define LL_BLE_US_PER_BIT_CODED_S2 2 /*!< BLE PHY speed (LE Coded PHY, S=2). */ +#define LL_BLE_TIFS_US 150 /*!< BLE inter-frame space. */ +#define LL_BLE_MAFS_US 300 /*!< BLE minimum AUX frame space. */ +#define LL_BLE_US_PER_TICK 625 /*!< Microseconds per BLE tick. */ + +#define LL_MIN_PKT_TIME_US_1M 80 /*!< Minimum packet time (i.e. empty PDU) on LE 1M PHY. */ +#define LL_MIN_PKT_TIME_US_2M 44 /*!< Minimum packet time (i.e. empty PDU) on LE 2M PHY. */ +#define LL_MIN_PKT_TIME_US_CODED_S8 720 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=8. */ +#define LL_MIN_PKT_TIME_US_CODED_S2 462 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=2. */ + +#define LL_MIN_ADV_TX_PWR_LVL -20 /*!< Minimum Tx power level for advertising. */ +#define LL_MAX_ADV_TX_PWR_LVL 10 /*!< Maximum Tx power level for advertising. */ + +#define LL_MIN_TX_PWR_LVL -30 /*!< Minimum Tx power level for connections. */ +#define LL_MAX_TX_PWR_LVL 20 /*!< Maximum Tx power level for connections. */ + +#define LL_MAX_TIFS_DEVIATION 2 /*!< Maximum TIFS deviation in microseconds. */ + +#ifdef __cplusplus +}; +#endif + +#endif /* LL_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h new file mode 100644 index 00000000000..7948f672ed8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h @@ -0,0 +1,143 @@ +/*************************************************************************************************/ +/*! + * \file bda.h + * + * \brief Bluetooth device address utilities. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef BDA_H +#define BDA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief BD address length */ +#define BDA_ADDR_LEN 6 + +/*! \brief BD address string length */ +#define BDA_ADDR_STR_LEN (BDA_ADDR_LEN * 2) + +/*! \brief BDA RPA check */ +#define BDA_ADDR_IS_RPA(bda) (((bda)[5] & 0xC0) == 0x40) + +/*! \brief BDA NRPA check */ +#define BDA_ADDR_IS_NRPA(bda) (((bda)[5] & 0xC0) == 0x00) + +/*! \brief BDA static random check */ +#define BDA_ADDR_IS_STATIC(bda) (((bda)[5] & 0xC0) == 0xC0) + +/*! \brief BDA64 RPA check */ +#define BDA64_ADDR_IS_RPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x40) + +/*! \brief BDA64 NRPA check */ +#define BDA64_ADDR_IS_NRPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x00) + +/*! \brief BDA64 static random check */ +#define BDA64_ADDR_IS_STATIC(bda64) ((((bda64) >> 40) & 0xC0) == 0xC0) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief BD address data type */ +typedef uint8_t bdAddr_t[BDA_ADDR_LEN]; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn BdaCpy + * + * \brief Copy a BD address from source to destination. + * + * \param pDst Pointer to destination. + * \param pSrc Pointer to source. + * + * \return None. + */ +/*************************************************************************************************/ +void BdaCpy(uint8_t *pDst, const uint8_t *pSrc); + + +/*************************************************************************************************/ +/*! + * \fn BdaCmp + * + * \brief Compare two BD addresses. + * + * \param pAddr1 First address. + * \param pAddr2 Second address. + * + * \return TRUE if addresses match, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t BdaCmp(const uint8_t *pAddr1, const uint8_t *pAddr2); + +/*************************************************************************************************/ +/*! + * \fn BdaClr + * + * \brief Set a BD address to all zeros. + * + * \param pDst Pointer to destination. + * + * \return pDst + BDA_ADDR_LEN + */ +/*************************************************************************************************/ +uint8_t *BdaClr(uint8_t *pDst); + +/*************************************************************************************************/ +/*! +* \fn BdaIsZeros +* +* \brief Check if a BD address is all zeros. +* +* \param pAddr Pointer to address. +* +* \return TRUE if address is all zeros, FALSE otherwise. +*/ +/*************************************************************************************************/ +bool_t BdaIsZeros(const uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn Bda2Str + * + * \brief Convert a BD address to a string. + * + * \param pAddr Pointer to BD address. + * + * \return Pointer to string. + */ +/*************************************************************************************************/ +char *Bda2Str(const uint8_t *pAddr); + +#ifdef __cplusplus +}; +#endif + +#endif /* BDA_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h new file mode 100644 index 00000000000..a8749b340fe --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h @@ -0,0 +1,152 @@ +/*************************************************************************************************/ +/*! + * \file bstream.h + * + * \brief Byte stream to integer conversion macros. + * + * $Date: 2017-02-06 19:25:09 -0600 (Mon, 06 Feb 2017) $ + * $Revision: 11104 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef BSTREAM_H +#define BSTREAM_H + +#include "bda.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! + * Macros for converting a little endian byte buffer to integers. + */ +#define BYTES_TO_UINT16(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8));} + +#define BYTES_TO_UINT24(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8) + \ + ((uint16_t)(p)[2] << 16));} + +#define BYTES_TO_UINT32(n, p) {n = ((uint32_t)(p)[0] + ((uint32_t)(p)[1] << 8) + \ + ((uint32_t)(p)[2] << 16) + ((uint32_t)(p)[3] << 24));} + +#define BYTES_TO_UINT40(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \ + ((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \ + ((uint64_t)(p)[4] << 32));} + +#define BYTES_TO_UINT64(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \ + ((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \ + ((uint64_t)(p)[4] << 32) + ((uint64_t)(p)[5] << 40) + \ + ((uint64_t)(p)[6] << 48) + ((uint64_t)(p)[7] << 56));} + +/*! + * Macros for converting little endian integers to array of bytes + */ +#define UINT16_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)) +#define UINT32_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)), ((uint8_t)((n) >> 16)), ((uint8_t)((n) >> 24)) + +/*! + * Macros for converting little endian integers to single bytes + */ +#define UINT16_TO_BYTE0(n) ((uint8_t) (n)) +#define UINT16_TO_BYTE1(n) ((uint8_t) ((n) >> 8)) + +#define UINT32_TO_BYTE0(n) ((uint8_t) (n)) +#define UINT32_TO_BYTE1(n) ((uint8_t) ((n) >> 8)) +#define UINT32_TO_BYTE2(n) ((uint8_t) ((n) >> 16)) +#define UINT32_TO_BYTE3(n) ((uint8_t) ((n) >> 24)) + +/*! + * Macros for converting a little endian byte stream to integers, with increment. + */ +#define BSTREAM_TO_INT8(n, p) {n = (int8_t)(*(p)++);} +#define BSTREAM_TO_UINT8(n, p) {n = (uint8_t)(*(p)++);} +#define BSTREAM_TO_UINT16(n, p) {BYTES_TO_UINT16(n, p); p += 2;} +#define BSTREAM_TO_UINT24(n, p) {BYTES_TO_UINT24(n, p); p += 3;} +#define BSTREAM_TO_UINT32(n, p) {BYTES_TO_UINT32(n, p); p += 4;} +#define BSTREAM_TO_UINT40(n, p) {BYTES_TO_UINT40(n, p); p += 5;} +#define BSTREAM_TO_UINT64(n, p) {n = BstreamToUint64(p); p += 8;} +#define BSTREAM_TO_BDA(bda, p) {BdaCpy(bda, p); p += BDA_ADDR_LEN;} +#define BSTREAM_TO_BDA64(bda, p) {bda = BstreamToBda64(p); p += BDA_ADDR_LEN;} + +/*! + * Macros for converting integers to a little endian byte stream, with increment. + */ +#define UINT8_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n);} +#define UINT16_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8);} +#define UINT24_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16);} +#define UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} +#define UINT40_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24); \ + *(p)++ = (uint8_t)((n) >> 32);} +#define UINT64_TO_BSTREAM(p, n) {Uint64ToBstream(p, n); p += sizeof(uint64_t);} +#define BDA_TO_BSTREAM(p, bda) {BdaCpy(p, bda); p += BDA_ADDR_LEN;} +#define BDA64_TO_BSTREAM(p, bda) {Bda64ToBstream(p, bda); p += BDA_ADDR_LEN;} + +/*! + * Macros for converting integers to a little endian byte stream, without increment. + */ +#define UINT16_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8);} +#define UINT24_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16);} +#define UINT32_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);} +#define UINT40_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);\ + (p)[4] = (uint8_t)((n) >> 32);} + +/*! + * Macros for comparing a little endian byte buffer to integers. + */ +#define BYTES_UINT16_CMP(p, n) ((p)[1] == UINT16_TO_BYTE1(n) && (p)[0] == UINT16_TO_BYTE0(n)) + +/*! + * Macros for IEEE FLOAT type: exponent = byte 3, mantissa = bytes 2-0 + */ +#define FLT_TO_UINT32(m, e) ((m) | ((int32_t)(e) << 24)) +#define UINT32_TO_FLT(m, e, n) {m = UINT32_TO_FLT_M(n); e = UINT32_TO_FLT_E(n);} +#define UINT32_TO_FLT_M(n) ((((n) & 0x00FFFFFF) >= 0x00800000) ? \ + ((int32_t)(((n) | 0xFF000000))) : ((int32_t)((n) & 0x00FFFFFF))) +#define UINT32_TO_FLT_E(n) ((int8_t)(n >> 24)) +/*! + * Macros for IEEE SFLOAT type: exponent = bits 15-12, mantissa = bits 11-0 + */ +#define SFLT_TO_UINT16(m, e) ((m) | ((int16_t)(e) << 12)) +#define UINT16_TO_SFLT(m, e, n) {m = UINT16_TO_SFLT_M(n); e = UINT16_TO_SFLT_E(n);} +#define UINT16_TO_SFLT_M(n) ((((n) & 0x0FFF) >= 0x0800) ? \ + ((int16_t)(((n) | 0xF000))) : ((int16_t)((n) & 0x0FFF))) +#define UINT16_TO_SFLT_E(n) (((n >> 12) >= 0x0008) ? \ + ((int8_t)(((n >> 12) | 0xF0))) : ((int8_t)(n >> 12))) + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +uint64_t BstreamToBda64(const uint8_t *p); +uint64_t BstreamToUint64(const uint8_t *p); +void Bda64ToBstream(uint8_t *p, uint64_t bda); +void Uint64ToBstream(uint8_t *p, uint64_t n); + +#ifdef __cplusplus +}; +#endif + +#endif /* BSTREAM_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h new file mode 100644 index 00000000000..69b40254f5f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h @@ -0,0 +1,108 @@ +/*************************************************************************************************/ +/*! + * \file wsf_os_int.h + * + * \brief Software foundation OS platform-specific interface file. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_OS_INT_H +#define WSF_OS_INT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* Task events */ +#define WSF_MSG_QUEUE_EVENT 0x01 /* Message queued for event handler */ +#define WSF_TIMER_EVENT 0x02 /* Timer expired for event handler */ +#define WSF_HANDLER_EVENT 0x04 /* Event set for event handler */ + +/* Derive task from handler ID */ +#define WSF_TASK_FROM_ID(handlerID) (((handlerID) >> 4) & 0x0F) + +/* Derive handler from handler ID */ +#define WSF_HANDLER_FROM_ID(handlerID) ((handlerID) & 0x0F) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Event handler ID data type */ +typedef uint8_t wsfHandlerId_t; + +/* Event handler event mask data type */ +typedef uint8_t wsfEventMask_t; + +/* Task ID data type */ +typedef wsfHandlerId_t wsfTaskId_t; + +/* Task event mask data type */ +typedef uint8_t wsfTaskEvent_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfOsReadyToSleep + * + * \brief Check if WSF is ready to sleep. + * + * \param None. + * + * \return Return TRUE if there are no pending WSF task events set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t wsfOsReadyToSleep(void); + +/*************************************************************************************************/ +/*! + * \fn wsfOsDispatcher + * + * \brief Event dispatched. Designed to be called repeatedly from infinite loop. + * + * \param None. + * + * \return None. + */ +/*************************************************************************************************/ +void wsfOsDispatcher(void); + +/*************************************************************************************************/ +/*! + * \fn WsfOsShutdown + * + * \brief Shutdown OS. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfOsShutdown(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_OS_INT_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h new file mode 100644 index 00000000000..0347086c06f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h @@ -0,0 +1,66 @@ +/*************************************************************************************************/ +/*! + * \file wsf_types.h + * + * \brief Platform-independent data types. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_TYPES_H +#define WSF_TYPES_H + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Integer data types */ +#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \ + (!defined(__ICC8051__) || (__ICC8051__ == 0))) || \ + defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) +#include +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed long int32_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; +#endif + +/* Boolean data type */ +typedef uint8_t bool_t; + +#endif /* WSF_TYPES_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h new file mode 100644 index 00000000000..e15476ed4ba --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h @@ -0,0 +1,199 @@ +/*************************************************************************************************/ +/*! + * \file wsf_buf.h + * + * \brief Buffer pool service. + * + * $Date: 2017-03-04 13:45:34 -0600 (Sat, 04 Mar 2017) $ + * $Revision: 11379 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_BUF_H +#define WSF_BUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Length of the buffer statistics array */ +#define WSF_BUF_STATS_MAX_LEN 128 + +/*! Failure Codes */ +#define WSF_BUF_ALLOC_FAILED 0x01 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Buffer pool descriptor structure */ +typedef struct +{ + uint16_t len; /*! length of buffers in pool */ + uint8_t num; /*! number of buffers in pool */ +} wsfBufPoolDesc_t; + +/*! Pool statistics */ +typedef struct +{ + uint16_t bufSize; /*!< Pool buffer size. */ + uint8_t numBuf; /*!< Total number of buffers. */ + uint8_t numAlloc; /*!< Number of outstanding allocations. */ + uint8_t maxAlloc; /*!< High allocation watermark. */ + uint16_t maxReqLen; /*!< Maximum requested buffer length. */ +} WsfBufPoolStat_t; + +/*! WSF buffer diagnostics - buffer allocation failure */ +typedef struct +{ + uint8_t taskId; /*! Task handler ID where failure occured */ + uint16_t len; /*! Length of buffer being allocated */ +} wsfBufDiagAllocFail_t; + +/*! WSF buffer diagnostics message */ +typedef struct +{ + union + { + wsfBufDiagAllocFail_t alloc; /*! Buffer allocation failure */ + } param; + + uint8_t type; /*! Type of error */ +} WsfBufDiag_t; + +/************************************************************************************************** + Callback Function Datatypes +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfBufDiagCback_t + * + * \brief Callback providing WSF buffer diagnostic messages. + * + * \param pInfo Diagnostics message + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*wsfBufDiagCback_t)(WsfBufDiag_t *pInfo); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfBufInit + * + * \brief Initialize the buffer pool service. This function should only be called once + * upon system initialization. + * + * \param bufMemLen Length in bytes of memory pointed to by pBufMem. + * \param pBufMem Memory in which to store the pools used by the buffer pool service. + * \param numPools Number of buffer pools. + * \param pDesc Array of buffer pool descriptors, one for each pool. + * + * \return Amount of pBufMem used or 0 for failures. + */ +/*************************************************************************************************/ +uint16_t WsfBufInit(uint16_t bufMemLen, uint8_t *pBufMem, uint8_t numPools, const wsfBufPoolDesc_t *pDesc); + +/*************************************************************************************************/ +/*! + * \fn WsfBufAlloc + * + * \brief Allocate a buffer. + * + * \param len Length of buffer to allocate. + * + * \return Pointer to allocated buffer or NULL if allocation fails. + */ +/*************************************************************************************************/ +void *WsfBufAlloc(uint16_t len); + +/*************************************************************************************************/ +/*! + * \fn WsfBufFree + * + * \brief Free a buffer. + * + * \param pBuf Buffer to free. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfBufFree(void *pBuf); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetAllocStats + * + * \brief Diagnostic function to get the buffer allocation statistics. + * + * \return Buffer allocation statistics array. + */ +/*************************************************************************************************/ +uint8_t *WsfBufGetAllocStats(void); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetNumPool + * + * \brief Get number of pools. + * + * \return Number of pools. + */ +/*************************************************************************************************/ +uint8_t WsfBufGetNumPool(void); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetPoolStats + * + * \brief Get statistics for each pool. + * + * \param pStat Buffer to store the statistics. + * \param numPool Number of pool elements. + * + * \return Pool statistics. + */ +/*************************************************************************************************/ +void WsfBufGetPoolStats(WsfBufPoolStat_t *pStat, uint8_t numPool); + +/*************************************************************************************************/ +/*! + * \fn WsfBufDiagRegister + * + * \brief Called to register the buffer diagnostics callback function. + * + * \param pCallback Pointer to the callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfBufDiagRegister(wsfBufDiagCback_t callback); + + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_BUF_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h new file mode 100644 index 00000000000..abc7c112adc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h @@ -0,0 +1,48 @@ +/*************************************************************************************************/ +/*! + * \file wsf_math.h + * + * \brief Common math utilities. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_MATH_H +#define WSF_MATH_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Returns the minimum of two values. */ +#define WSF_MIN(a,b) ((a) < (b) ? (a) : (b)) + +/*! \brief Returns the maximum of two values. */ +#define WSF_MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MATH_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h new file mode 100644 index 00000000000..7235130f4fa --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h @@ -0,0 +1,140 @@ +/*************************************************************************************************/ +/*! + * \file wsf_msg.h + * + * \brief Message passing service. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_MSG_H +#define WSF_MSG_H + +#include "wsf_queue.h" +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfMsgDataAlloc + * + * \brief Allocate a data message buffer to be sent with WsfMsgSend(). + * + * \param len Message length in bytes. + * \param tailroom Tailroom length in bytes. + * + * \return Pointer to data message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *WsfMsgDataAlloc(uint16_t len, uint8_t tailroom); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgAlloc + * + * \brief Allocate a message buffer to be sent with WsfMsgSend(). + * + * \param len Message length in bytes. + * + * \return Pointer to message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *WsfMsgAlloc(uint16_t len); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgFree + * + * \brief Free a message buffer allocated with WsfMsgAlloc(). + * + * \param pMsg Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgFree(void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgSend + * + * \brief Send a message to an event handler. + * + * \param handlerId Event handler ID. + * \param pMsg Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgSend(wsfHandlerId_t handlerId, void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgEnq + * + * \brief Enqueue a message. + * + * \param pQueue Pointer to queue. + * \param handerId Set message handler ID to this value. + * \param pElem Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgEnq(wsfQueue_t *pQueue, wsfHandlerId_t handlerId, void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgDeq + * + * \brief Dequeue a message. + * + * \param pQueue Pointer to queue. + * \param pHandlerId Handler ID of returned message; this is a return parameter. + * + * \return Pointer to message that has been dequeued or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfMsgDeq(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgPeek + * + * \brief Get the next message without removing it from the queue. + * + * \param pQueue Pointer to queue. + * \param pHandlerId Handler ID of returned message; this is a return parameter. + * + * \return Pointer to the next message on the queue or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfMsgPeek(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MSG_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h new file mode 100644 index 00000000000..0ad337556d5 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h @@ -0,0 +1,179 @@ +/*************************************************************************************************/ +/*! + * \file wsf_os.h + * + * \brief Software foundation OS API. + * + * $Date: 2017-03-02 16:50:43 -0600 (Thu, 02 Mar 2017) $ + * $Revision: 11350 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_OS_H +#define WSF_OS_H + +#include "wsf_os_int.h" +#include "wsf_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Configuration +**************************************************************************************************/ + +/* OS Diagnistics */ +#ifndef WSF_OS_DIAG +#define WSF_OS_DIAG FALSE +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* Invalid Task Identifier */ +#define WSF_INVALID_TASK_ID 0xFF + +#if WSF_OS_DIAG == TRUE +#define WSF_OS_GET_ACTIVE_HANDLER_ID() WsfActiveHandler +#else +#define WSF_OS_GET_ACTIVE_HANDLER_ID() WSF_INVALID_TASK_ID +#endif /* WSF_OS_DIAG */ + +/************************************************************************************************** + External Variables +**************************************************************************************************/ + +/* Diagnistic Task Identifier */ +extern wsfHandlerId_t WsfActiveHandler; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Common message structure passed to event handler */ +typedef struct +{ + uint16_t param; /*! General purpose parameter passed to event handler */ + uint8_t event; /*! General purpose event value passed to event handler */ + uint8_t status; /*! General purpose status value passed to event handler */ +} wsfMsgHdr_t; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfEventHandler_t + * + * \brief Event handler callback function. + * + * \param event Mask of events set for the event handler. + * \param pMsg Pointer to message for the event handler. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*wsfEventHandler_t)(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfSetEvent + * + * \brief Set an event for an event handler. + * + * \param handlerId Handler ID. + * \param event Event or events to set. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfSetEvent(wsfHandlerId_t handlerId, wsfEventMask_t event); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskLock + * + * \brief Lock task scheduling. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskLock(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskUnlock + * + * \brief Unlock task scheduling. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskUnlock(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskSetReady + * + * \brief Set the task used by the given handler as ready to run. + * + * \param handlerId Event handler ID. + * \param event Task event mask. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskSetReady(wsfHandlerId_t handlerId, wsfTaskEvent_t event); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskMsgQueue + * + * \brief Return the task message queue used by the given handler. + * + * \param handlerId Event handler ID. + * + * \return Task message queue. + */ +/*************************************************************************************************/ +wsfQueue_t *WsfTaskMsgQueue(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn WsfOsSetNextHandler + * + * \brief Set the next WSF handler function in the WSF OS handler array. This function + * should only be called as part of the OS initialization procedure. + * + * \param handler WSF handler function. + * + * \return WSF handler ID for this handler. + */ +/*************************************************************************************************/ +wsfHandlerId_t WsfOsSetNextHandler(wsfEventHandler_t handler); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_OS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h new file mode 100644 index 00000000000..14d0cf19f75 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h @@ -0,0 +1,158 @@ +/*************************************************************************************************/ +/*! + * \file wsf_queue.h + * + * \brief General purpose queue service. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_QUEUE_H +#define WSF_QUEUE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Initialize a queue */ +#define WSF_QUEUE_INIT(pQueue) {(pQueue)->pHead = NULL; (pQueue)->pTail = NULL;} + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Queue structure */ +typedef struct +{ + void *pHead; /*! head of queue */ + void *pTail; /*! tail of queue */ +} wsfQueue_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfQueueEnq + * + * \brief Enqueue an element to the tail of a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueDeq + * + * \brief Dequeue an element from the head of a queue. + * + * \param pQueue Pointer to queue. + * + * \return Pointer to element that has been dequeued or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfQueueDeq(wsfQueue_t *pQueue); + +/*************************************************************************************************/ +/*! + * \fn WsfQueuePush + * + * \brief Push an element to the head of a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueuePush(wsfQueue_t *pQueue, void *pElem); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueInsert + * + * \brief Insert an element into a queue. This function is typically used when iterating + * over a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element to be inserted. + * \param pPrev Pointer to previous element in the queue before element to be inserted. + * Note: set pPrev to NULL if pElem is first element in queue. + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueRemove + * + * \brief Remove an element from a queue. This function is typically used when iterating + * over a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element to be removed. + * \param pPrev Pointer to previous element in the queue before element to be removed. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueCount + * + * \brief Count the number of elements in a queue. + * + * \param pQueue Pointer to queue. + * + * \return Number of elements in queue. + */ +/*************************************************************************************************/ +uint16_t WsfQueueCount(wsfQueue_t *pQueue); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueEmpty + * + * \brief Return TRUE if queue is empty. + * + * \param pQueue Pointer to queue. + * + * \return TRUE if queue is empty, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t WsfQueueEmpty(wsfQueue_t *pQueue); + + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_QUEUE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h new file mode 100644 index 00000000000..7d75e254638 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h @@ -0,0 +1,167 @@ +/*************************************************************************************************/ +/*! + * \file wsf_timer.h + * + * \brief Timer service. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_TIMER_H +#define WSF_TIMER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifndef WSF_MS_PER_TICK +/*! Default milliseconds per tick rate */ +#define WSF_MS_PER_TICK 1 +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Timer ticks data type */ +typedef uint32_t wsfTimerTicks_t; + +/*! Timer structure */ +typedef struct wsfTimer_tag +{ + struct wsfTimer_tag *pNext; /*! pointer to next timer in queue */ + wsfTimerTicks_t ticks; /*! number of ticks until expiration */ + wsfHandlerId_t handlerId; /*! event handler for this timer */ + bool_t isStarted; /*! TRUE if timer has been started */ + wsfMsgHdr_t msg; /*! application-defined timer event parameters */ +} wsfTimer_t; + + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfTimerInit + * + * \brief Initialize the timer service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerInit(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStartSec + * + * \brief Start a timer in units of seconds. Before this function is called parameter + * pTimer->handlerId must be set to the event handler for this timer and parameter + * pTimer->msg must be set to any application-defined timer event parameters. + * + * \param pTimer Pointer to timer. + * \param sec Seconds until expiration. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStartMs + * + * \brief Start a timer in units of milliseconds. + * + * \param pTimer Pointer to timer. + * \param ms Milliseconds until expiration. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStop + * + * \brief Stop a timer. + * + * \param pTimer Pointer to timer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStop(wsfTimer_t *pTimer); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerUpdate + * + * \brief Update the timer service with the number of elapsed ticks. This function is + * typically called only from timer porting code. + * + * \param ticks Number of ticks since last update. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerUpdate(wsfTimerTicks_t ticks); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerNextExpiration + * + * \brief Return the number of ticks until the next timer expiration. Note that this + * function can return zero even if a timer is running, indicating the timer + * has expired but has not yet been serviced. + * + * \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running. + * + * \return The number of ticks until the next timer expiration. + */ +/*************************************************************************************************/ +wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerServiceExpired + * + * \brief Service expired timers for the given task. This function is typically called only + * WSF OS porting code. + * + * \param taskId OS Task ID of task servicing timers. + * + * \return Pointer to next expired timer or NULL if there are no expired timers. + */ +/*************************************************************************************************/ +wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_TIMER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar new file mode 100644 index 0000000000000000000000000000000000000000..3384be486f3acdfbd30eae612c727e3fd75c45ef GIT binary patch literal 46166 zcmeHw3v^sZnPzpjUY2FMZJES&Y}1w%BRi4Yl4VB;2_vbcwuI%_v1AgS>Q<|5HPNHp z-EyQ%NR-3`Clfd(%MO9b?s^!8@c_ekbL^SynPk^M$S@2uD<{BY_Q0%{lO-I6hr=*~ z!vNXut9$?3b+6P?`$59)ex)sHD4pBNh%85`{% zNsc6jGmZV*W_qV5>5Ut=HTR9RXLFfkd_>tcJm{Z?dsCx1V9UzW6Y=3hV^fP2al`@< zBq#60O*Xh=EHir|TGZ`$u06?v$xJqBx+&>)By5z9yR!S*$M@YjKC*jkY&dJfoyn1& z6^&VNS;T7Tay#H&WUs? z6VIi_MjcLXGIKDMNa~QJPON4lTQa$wI`i_lH>vaA_83b$LiVNy<2jxCZCOdMEDna%ov+#n_eYP3HLMUGdSuVXLyhr}JRaDvQ2&_RgL$L;*o`qx|xD2n_C?WPDJU z4#W43q7v!^?aFqfvgvp(F$Aed@UE;T_Ko!pCzEMaIWQP+7&Ds8#;xJ4En9AEY`y_4 zV>sMs{NJ{%ITUK%)@(PZvC8{8d!jy{4~?c}e5y|6ky3Y5Y5&q@ZPlr3RgJ3ZUbG{4 zVrtDN+7~^)@a?T@OD1X;EProR8g_Z@lI8F1Nk6>$6YW2JL4_*P!KZy)>Ft(mOO#T< zlO@sDe*Wv%j;;wl6FgZ~L$|8)O{-Aw86U3TN%{nzQ70cfuGXoK`aW7#lhSvnIzL!} z;|e_fx8z2~M$%)W$mW|uXu3j#DHK3xYeRTjXk1sA(3Vi$z<6qSFtjBc-Wck`>v&Tr zo*79bLho)K+_H6F_`S-4_4SDxZw%Gf=Z3~d24H8?!>L?9stW6JHdLR0-~Q3@Q2p3u zEik+JuI%Rap3cpvYxRk-%wTG)KAS^Ts@K7r_ib&yVawL=K8wBCVxW1=Bscf9?b+Vh z*S|Boxo_95o=8_)_pQ3^?d|Ijo|c3dC^@+~d)MaiTxxi;E^wqHksiM#GM33DC+c^G zf#c~!_7=3X$;@42nL9)EySCuU;gt>5cb{i!?R2{1PmLyq#|JN!H2Y~TQQ9C4ug2#6 z$47b}A;#D&NR z;XW}naI{t5_Yq%P^*uW(tM6-D*j{}f{EB<73Y|AAL>TNQT#@Sg4*B}3)w9~4?PCzv zQlfRfbX)rV^cT~<18oP=+l!0EDgkK^DTeYWw;C67vU0+o-Z2qLKQi$^`fC$kN-vxY z9C-U=`$fdC3Q}j99~q5(iF)O=9~hV^dKs8GU>Toshx1*GDRjNq`@&1Kshk=*+m#Q@` zyj=ZHq?bu%87=es)N?jw-CE}NqocIKS*Moy1L}m0`Nl8vm#9CnG2fbH{!)boK+9u& zT;>m|aT~MtEb~{Zt6+;+=C`p{FsBa*!In|7b;Z(yAqLTyB2=L>y<)7q$+{K zsk48wQgDzltMUL-EeGiN zS3`Dkgb}40X3Vs#Db*|i))cHEfe}a!YXQ zFr-lpB_|Y0PqlNX*X9&%ZEauI&i?M+wu4)C*7nx!?yPOQsi&!__Kur+8XIeS;p*<} z>};&ZBAYKVMQBXqIfbskW#))a7LOM z8pEp88ELArss+BKzGeR9{;Pc}d@Fscd~5x9XBA#4br!rBJQydsHytmZYZ%u8Tw->kl5rHvd|`T+KGwT_TqbV_p7bY=@d$5^hnF^Z zs5%a>)5DuEc#8sb{+lFe7dDA;TyJzCVoEMQk7NEj&7+MB^^Gox@>9X zx`-dMsx>7`t2RbfSKgmq<6pXXW8{nJz=4hf;iuEvgD3pa-U&6aa`83(k4>zItgosq z2}Qm!u`;s0a%H4?vbJo`WGJ#Sf)VV~OC#h*Cj6RxXkwLS*F>JR*#WRuMk13nk!$=b zBM(lVn!KiDWki+vBEhGF(e(E8j1=9UUW@cJB4uApuc>01RxSSEfiE3MBW29O%TFIA zl?3XJD>|t=O?}PpN}d4RpWD?FfnY@{WC6x?HA>OKYxOkGEp3s_3));+@#uyA} zjA@C+=;t)%gyTYV0QT%XKLPj5y;BX|MNUlMtT&@?%w7gHe5`d+J;yWGQD>jQ7nqD+ z!1Q{qN%U`H@_Z@s>{8E#o#yQIoDV;OYRP(T&WHKFh>@Wj^@JwxUBIm0VuZIJ9wv|S z`F@EJ-d=c^yyt-V-iZ+&$NS`o`57D>qlytX<1l&Wh>d}%ggNssTfnQ}xZ4#gz{_hx zL_PLBv2ZYzv7!zphz-ju;(JcW2i44ye(^3ETQg2y?s7|B2H{Nb%g{D&nFWO33q=MS6*b%-#7 zm#{W<6hD7xDt`XZ?3q7Y4NXt*WKgds=U0(~Cn{=M*LJUsO!Q17S|jNPCmx-6cy*%n z!SvMXJ!}8vbkH8PUxwp$r*N)}+qq(YnU33~79@<<*K*dunt%K~b2*s}&xI`GE;mxZ zM)3S(%v`#y)iN-4-))WE0oiV`O{VUr&>HI_lMfvD+sQ9q#9C_&q|Y>?(s&|>ze2kLSgX90Gjak$j|KDh178}R^AsaI{mthfc zzO_g8iIq?ka;#E`x)g@(%n#6yX)N;tM5?jO2hf*j9JJ>LOyq^k5A+&g#M#P-{fpM} zU)~E#jB~C4ws3WC=0e|$d4?^K`yvZX7xW^I-o%Ner2?~uSr`6VRKnbvS>Vuc^vkW_%8xrdEoMkAzuYm6&hJo5}oXaXNM#lTz^{=;q z!1q;*@VG8x%8LT?Jr*Op55t2zF~e~1y%i(wL+~(pX<`gG#YmXUgGBxTaPSH{MtI)& z!~NiOIIMhJUfx%Vd6@$&R%6e4{0X4v4uM<@;-}jF_M4YdC(>#-rQ>> zJld!tte)EZ7>Vx?09$x>L7U)Ag0Mg`-#SXuwrxf4(S3;-i_aZcMpRG+k=tia?5I%J zE&h%_s%jTqQ@7_yJ_(>6nbaWb)~1P zCe-!5>5{bXjBkBux^*?~Ui;J2T&K|qy8PBdtirxBsk)3ORk{jX_)5qoygBx2K`&Pe z>VW5;iOrk=HEB7R0o{K7s}~{ME5=ICJ%>s@7}GbB&_Qz?_q~*CfhZa|q61ehNO@Xg(n4B>%_8 z%s9?TzGY)8oGHp1XAPp#v&JB64(MCLp!?BLv2Dio$_txQ%)jQ~eCCvDFg}K|Hk272 z1t$vpcJ)=e=o=8M6@7=by|$@ zyn6p5Aj~GutM`8zJdUZvh}*08KLx_SOJs1%`|}pV4X64m45HlcE`62q@&bsc7~T%> zc3UF!e~DMWhlc+XOgI9e7I4OiLAbr+*eCGr(w}2a<~?t#z~$wA-r$wb!F$@^QI5#- zj!(Z1-hBucBhTR-pYA}S`Xmr!and%&r~d_s>JVWD5Bn7Q2gdg~L)7`kr_C)}i{9sR zjDv7vd|IR4tkNgTqD#6;Cpv~y{ngW=LiM+Jpxr$Bc ze^Wz4;T1>Q8(s)T_pE*XNmbW0jW2-@SJe5QuLzZ%X~U?yt-O0l>#BC<%tG0akQ3OMR;%|F1lmO54&H+~ZCw(8$KRQkb^hXNns_jBhb%iJQ=u4UPS?DPB*&y+)* z9X@`u2J3Uksqj_!E1a(at;qv*C1Tho70Q?S?qwfY=-%1BMl|!3eRNy(-9_c;eCaTT z9`ab~*U~w{hjWyFH!yq7bHFSM%lMQ#-0#5w&1arlCg2G#@!(R;m+>3AMNfE{4rd-% zrpyywuESaHEQ2|WoqmoZ0?^{VWIPXNEc`}H4Chc^a^ZmbybG78Pq=WYI^@D->Mj>9 zSEUB#9PFPZGT1)oqE5T;V)d6UyhKrVEXIdX)`J3I`=C92zY8x^x4CeYQ&vpIQha>2 z6*kMA7x8tlS(kYce-A`*S;n06owhOgobyr7$8eS@*P*^(W8TkwXn$a1mLb2Hd&tHt zvt?NKnzS*?XqmrUg4^=7?Eo% z-`)ig*#)no-L4PW(1%M{t7w)7PTj~KsNo5aqc==%ePo8|VV$ud>u?R8PwHl@v^lXF zXMJFztrOQ_o)0qnIvj}R$q}9WK%eJ0;G_{8K$3Umk0No7DY;||Z%tbYt^YNJ3x!GP&QXcZD{ktg503Gb8}+Fp*t|ktq|{yB6&x_ySa#Xzg;A61q!;D=NJTUws;>$ zTBJ@eSx3P;4v!GrYjH9E*!?_&YXL4Xy8%J~=*o27k;i-=$7S-;0Oe5W! zVF2Dwd3bb(*XiLMG2|hs4v+n)Desse59%6+x8B1$4j!M6@p4a-q|eJcW$^f(6yi-A zJgRI8@y-}L3@Zxq&Kf*fb7nqy)5nbm@*K1a#Tztu)PD)jt1}CM_XC8Bk$TU2SdL;U zk!kNTDvdb;CE5cJx zQs0E3;dDhf_)P1HnSQ~ORnA#SzR7iI@)kyeCznPmZd`bPcXMxSMT_N9(6{-g{gaj8 z;aj(pi=x)qOdG+j(rn+lkd|lZ%PwR6kuK^h`lBoQBm1>4c6E2={#Z8H=eM_YrVPxp zRQp99*@SlTqSL_!`$E#ej#Ugh>tYmEvnh_44`S#pCST`Lda*;B#msk3(xp8YsmyaO zQn~uJbUH{Ibvj>jVZZwCESuI<1QRj_quSUO1khu^-qYON#LtO9nIHm%p#_a=9CNP&o$EH2S#V` z^I5#q(eRrV{ONHbbu{mUTMTtHw+etw-0s2KJa~f#&!^+z_^2}9CfMBCv{XX@Nny7;K9R4O#+WCbz$dhRMXd^$>DO3J{D;<9S$PV zC#DwE((u?#?=hUX$vLJ|JIq5Uj=>z$QkF@LJ$u%KLp_ z4i&@*&#RX?0Rr1oG2;FVJSb1hQ*g|tm+|UR&Sww!Z1Y5~yq!o;F}#l!$t(2jsyE&> zP)-yRZydbY^ez7x`6YSIJfuD-29FTj?3a*ST`wMmjV>u~FzM&KpYw0#KY7Flahbdd zgU5J;x6i{18a&SDh4&5*Z-v1lM|hncUdZ6#ksKc1FEf30;PE;69CPVqTEXM{K_2VB z#EWj+C68w`32!d_P0ZlUrN7}BO(JhD{mqoY<9k;qeMb!5T>6`%29NQJJg;8nICx)2 zxEOgCnNKW7G4~+TyN!w_Jlf!;h4&R?T89AG!lPaWM<0$SZOzQQdzrSi6usAengw9& zWm>O7djFBCr9NfjklI)>J-B+o(5IhN8-H<{ej)5$O4}!1UyI#NCDV07p%^qcr(@3U zCOHv11Z_;ov?VJP#c9~JufEKCRcKMPLbJ&zosJEa#*+4KrfXy5Too0~4HA{?xw1V43p)Q*FhcNy!D>}q*Mi*!Yc`LJhnhnIM8 zsRx&NaJk;+B59(I>8Oz&?i)Jd!U6Sw3zw(^E?lYxT)0f#=ECK!Z#$@C`ievjn>wb? zx$q+OQ5RmU?sDNJ>b));^o$LxeLzCt+1kgE9wv#!OC8gvY#h?quO728i;eq$xDSea zzINOP#IwSQSzW1P8niKA1L~OgJwC%(4KHLL5a)T+4Pk4Istj439t*fzrxW-W!X;1yrHf}Hb$8X%8E`^l7)B5!sH_N4_(k$!Ocbv^d zg;Y`nwNNwn3SH496|GA$i(Tu2@WLV*IwlIak@noO6e4H!b0P2yRmz=lX1i#0ZajE==BIz-(W|2rmW? zllK?EYuJJjNru2jMn(pEr0cKH(kk@SZk!}Mx@yuj--nn#8s}0^v zKnn4C4BlKisP`B=3>6B>8#Z`z>7b}Hl6;{p>GSHK9tH285H3dEH^!jLhf|09$y}LGhQj6dg_i;U0|9% z{LXGubX~Nh%R;e?b-%S2=o~ati=)=PvAeI@rRu7uZyHh|wQ0%py6C6cOQwU-WkYJy zxzpum)TYvDe{_*0XI(tw3&k?~Vl9ZNY`SgeBkh3~_|2cHJ9nD#1vHOwSzp%SymQ3$ zfzT<{7Rkr>rXpgjDl$gDCq~J?gUxzcDmhpSS z13H}fVVQs@9A~LRKFiNCC7$q79nQL9nNm-9nGR=}S*FYrUhav%T&=O6uL3vlo4&=y z^HMkWuQJfk;eOBluz+WOSc&>e7r#{T+XXQ^JM!Z$T&~Y*mvHLl78>FFrtg(}AX2kf z{eufHk)LMOzWk=|k6htP)gvyvP#tjLDrauT=jS(jK|DW`z%r(;?&ko+EK}|Wll@{W zL+a{ezZlDmy1M^n^I1mJ)qU2+EEDSLK4D|){&KYo{$jZQt5pDO;(T4PaIGi&Di3B_ z#nj+_3>%dn167VwD>vCXz3Z*#G5sm068@CWZ~frZnDLXx{Neq?4CnlV-v-8LgFFPA zJPsMjyNNb<1GK?o{*X5e+l&`MnisaiIbSxzb$YI|=FGfb(nG!<6K;){+B!Yx7&V4& zPlsbruJLjkL&2#r9#)6Tw}a3vYK%ryheMaBv3#otUE)RQ2=&iP+rKF7X!W#bZw|jX z?e)U%RP%SKXYt0*S9^Tjzjf^n^!z@yJJ9;rQBM4s`^&_FDn#S=qp`ngwry?lOVnDW zWvfX+)zDUtVG5)3LjThNg+3HK|8qd!_@5)1bxW%f^YzMvcAfHgp*|Tt?z)r@@YJJx zfK`Wn<6kD`^!)bqRaO2qUU{~qWw>bAE(Ep9`p5Q^=Cim=UI#FmDaQ!!!|*YAX<)W> zVuZ)FCX;szm~EyQ;lM6OlbhD6P3y*0r<(&eUEqy<-c_M;m7>Eq| ziTfoF@0Z}srl+Kigz-Yxp$)$!tgzj*M4nflxdJ@%IVgk1%j*NL#|qN_3-P$etQg)8 z!RshO9?v)JDuOowUNQ2XE+Fq)hy&fcV@k@EIs=ay_=IpV|5$Ioj0-9$$GilD#LzX+dZV&Gs z@Ivro`jABqkMFA~?+Js4EOL13J-nyEV}4QITzbl{8@#GH`Kb&iZ<=? z)uzo-9}?EPQ3tD7P1MhZdH z4XrXTTd=EvnR3hclsnw7!+QRVxE6Q-ORs`!sXIwa- zMh#5e%7Be2&j)#3MmT?WW3vm-{9V0rq=!l3Gg3El4mL5LiMo;R+L+Hk-H4rhAdE-Q zCt!N5{1w(XgEo1z!?e+v>A5#LZH*DAG5R}=(O+oHPWfW?>$K_4r7sgtcaFvfhLiaT zwH1P6TfAP*4{6MEfY0pHMn_*kio4E$Dp-vTrD8TqHDgZaEOptADok{?<# zYkTv$o{p>ZccfDHQ6qKT4AEg5zGF0daGAV5V2&5X2+uqJih;0PNU()>7;f{u${As# z3-3M;ZvyyD#z0MEOxipN`Uo5%13}K*;w?6hel(AP*I_yJf05_qeG9x|=4t%>_t|*V z*BZk~wHv(Mh>YWN8Ly(LP;p%5c%Sn*G%Z?>%e3*Ch;PMZ@{Soi#v?qoH74)4!DC(t zZ@q{26nIPznyop%-TA7)W4a2-d(q%AJ;L*j&%Y1e;|Lcc<>4KlPoc5?fCPdpPTF{` zwA}xz^4ZIm$Ezb}DLUWz`8q=$uS>^Inolca+uxq_Yll|BF4KN{N|Q=#CL zH7YOZ_D8$!jjY~rFtFo(^{(CY4QVmlZy?``Y%H(nTCk*IMJVi>EU8%+@f|4b^4+^M z;yXy`ykupZ_ez|qE4`h4kDPQ;f_reUa}U?yP5#-F4<6stLusLCC|r84+EAvs-!I3> z!_ja!74;oqXt`Q4Jrq?FH%6ya%^fOqWP6KV$4B_%R`^d&A1e=jQ-z3B-NI?#-4CmQ zJABc~MzY2KUrrB|ul%OEcHhd-w(z8?TQdFU>dZUI=Y8Qx-w_oG>$6q9`%diIc>Kur zk<~wXazXv~UI-jNYwsZlbm0^EIv?gWoYSPY^Lc3Ah;y2ef#e`6Z-0C+p3cQ{Df_%$ zR_80zmpAtGrEt+Ftoknh>)@Du#!^1#8Mf@x=epOsCT;fZZ2vE0UHgqBV}%p|>;|15 z^Pej`+dc?0PdHDRFJI@IMY6vwu3TrHYs~Jf(7p4;%P~ZuduMy@5cp!g0Eg?W=(g$! ze_!?QO1RiJa3EtF&S#qq%#nc`<9Fa);Q`eMoFB{Lci~;(B|6;d(iusKC%jaLv#c#s z>IpCN;Bw7pd03|06JDXi^YiZtPxt~4uGDS{ zW*!9aYiBEs=jZI#{N|tEHJvjCviwb%@49e_`i2Xas^?s|Or3Dya`h<}u27G;@B%gE z!j)>+g%_${$ly;u;4814F|ZFK?B`s#+I4=j53>_~wUXQQZ*pgSK{=&wLkKbi|+Qydt zq(Xhn#b2Nvurcf8GVDbewK3};f0y**u*Gn1$fE*a6Z0DfF~si{0GqhQgSqEJ48x7= z*ZLZGsmfMs{#Ds#?>qaCJw zot-{BjKF$!6SZ?N$i8)Jg3`FKbjj?B^+ z6FQAI+Bjt6O*Y2fmJ8Q=Vb-=QyC)eRoa`Ix9Zn`?&x!W$NM+OUTw(}^Md!DO;Dn;R zqr+o~JKcWHsYNa(PRz0PZMb~()(^)AcXl4sM<(fCu7xIPR~CNUThJ9B9UL}ek7Ro> zK1YK0r?Nc5+7V)ZvSwm^$hGqkoM#`)Ko%QjJV!LmuBGF=RtAZQOe&X3#E1K{$pmK! z{mF?`j=Hxw7;@IOMS)(iKbzV=3K>cL(0E*HUxs^+1-y}Wa;6iU`~(aUSkI7 zkn#lO*ATOBnT_`n{7qg5a1fW665H`L*e0(J z7)`!og!dGDOkNt;?5BnI84vFm@NDTj;^7_l@I>C-9v;&X!X-v{``}@w??vF*;@$1x zodG_9ON_|lvzhWf2C!U6u!Xk`{^W@{1|VVd6L%y0nI0K>^9*#BofzTO!5@E)A@851 z@Zl?AH8xM=Jq`gJ|A`TK=*FFU81`udnDL4{FYgR^9U{z-;pNprpIZ!Xs7M}vFRmDQ zXTj?#B7OW_=3?aC170!t@>G$$pB2dqmt&n^mgnG_tWoT03cPTMQd_{S#|5W;pBI4V z(*I-Kk@XD2K3(qQ5xIlO}&UJ$$x{FpwCp>>SGodcT;R*H_kC=E$f}efQ>p@zn5O7Fo8ry{B_C z=9BeS4%h1(uGhhv_ib&yVawJqf5xY9?x#i*!{dX=P<_YFT^)OSI{UjjZb9~sj1T8h z1CzOAe_|+}$--wKlS=OEAH?rWjgDn80j6IjnayFVUoLbB6J&1Ru&P5szbCGL4;qNN zX|`o~^U7=T{?d^Y1e#6<^)`XmjC*uPt z<>P1}($vrxR;7`#OfET5zcZ}LsuuW``j+{Z`>*z`^sVx(^|QgnuXZaRd+o)(WoE|1 zXD-7&+oTg)O`>&|xUci@I7g_SrA=QCe-^cv9&lO#INl+h^4Q0F`;tcy*a3erk|u9o XG7a8$g#=r8v=QX=B~K!v+2s8{dJ~YP literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar new file mode 100644 index 0000000000000000000000000000000000000000..abd590ab593fddd987bd35823a67eb590c98ba2a GIT binary patch literal 94784 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 0000000000000000000000000000000000000000..a5fb4ab0ce783fb1c437808463bf87ae6a37f9b6 GIT binary patch literal 15676 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 Gy8jDL8rqKl literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 0000000000000000000000000000000000000000..c5f20081e858b1336b584440682f0d95eae4a2d5 GIT binary patch literal 24540 zcmeHP4RBmXec!v2W%(@Il5i49{@`rMi4xn2zAVd$36f6!itNO-mD)*Ed?)#mQ*BA- zyK{1e6x7tD0>U&?+^K2O5*lZkX)+;W5TzYN-4Gbcq>K!iVhU|NCBZ4BU~7MphFAfVvMCzZ{m z0<7AVyQ}lyU0a3*^6Fk)yyf8F_Tl0EIfvbr8r+&1a?CpR?;q}W${Vw(lvCW4%4^Ne zd@`T&WDb%iAg*oGHITe}N9yi@Tt1ccs-yk3+}&6tq1rHXz&T)NYG|)h z>`IAndn&b$!rwWVI+${7b=fh|T4nLf654|n3H<{NJYuzoWLViOb zGmuT@2ZnWjm_t(8dj|SbT9eYJ-;tB{n-Y3~n1<=eCNmp`l70I%a6G4b!|sB3Zo?3I zBi@(n-^UXJUl_<+tUh8FT9zG5X7}BeGpFMm#)`}l`ZSWceOrft!wZ1&Z9^D6n%kMm zZ@4Fg3yB(THRlgKq&rf{y%?^>9=+>c&0BNO@)~ST4(;7-emo-<=|Z3)(k(^(9mf8Z*7HFYid{nuSZHmKd@oz#!x5(7iTD>>XgSR zb)rbiXSL|8PF;5X%-M0LnW~|&skvoM>)N(;9i8#64IAOx;_(||b(?OvE!M+X9lL8d8|&Dy zEw*8>FSU1XYHw_NcDO&4%ME99vDVd14UKD8A81^CP!GOqW3Bbg^^LePjcXg48rQ_? zvZ?*4WG;1W>`q`@pK>r(x32EXCWrddv25y|fgHwXtf^(qn#QKzQymRxS~8XF8&ILE zQJfVY&gN5v)!Q0Wap~-Bb3zqG3qx0gu8LHKszTMFrRKWI>FC_P?nUayuiMIquUC|c zsIaXD9|`b9YPL_}uP~yD1Nvg0bwrf}^d$j(G@$1)=}|-Z8c$Jy+T2bDBJdDQj+`{j`zxv#v!F;k0 zc|L3Mw3IM>^Qs=sIjQRVayeCxNl{N>J(g=OuYLiV=@%d}@ChVF@CkLaKzKI5T#@?h zFe|NhuS|Xa@Zcc5XgwxleKMcV4)h(&r*dfiOlc7e**7xE?Y2wmc+Mvw z+L7`|Hr`nak8?oq9zfadx6gqWzk{N#i}?|!EbXNo{frRXM0y;FW%e`apOHpbaELml zr;*U4j3ZWCAZ!!{Ic-SHrB3qqL2wp{Q}rq&o(HcJ&lPws?FZBAavmPrY}*mw3sczj zVfGsCPp*h9n@yw?3XgJf6DKD*<|7@l@8adE;pt^L?{6Eaxf8dJ;GMhRM zMGnmgSH%Y$lFlF8^Rb#tXahQp5^# ztubLnnJ0*-S<0`U!X=X?%l6hHG}uS&RQzA`W{%h3v6qPcRzgb z3*eiz{;~hqFES#yo>C?xzOEAj+b#i~eJvz*yCJac-Vc5%yTO3nBj6=oMA7xJ_d9mt zzmJ0-K@wtJOdmml8*}}46NEGI-+N)#fW-072=!e4`v^{OEA&FFlN9vdr(yT7QR)9; z=WK_ZhyQMAo2mca9`N4_Fgwe}%G`Uv5~rkU%ErFh`&@5d`?Ecv=CYNqoh)N9_5l<54M;ZLP2i`(>ww&j(VwyK z*cQPH`uNSzacl|UFiiva&w7Pt{L3*XL>-B11j{^c(te~77966E>5q|YAO8dJGx6~; z9Ndn?`-nI4@d-4P=OV;9NkJd~IoSQVQR)9;cQ5adt&P5EWAvux8OP{n%|&!$^iq12 znzLg|u)2n>`Ofjb?o_9+`?k91akHF2Ck#4#a>j3AH zN1P2FF$VYRC&%D^z07Wd!5G{o#@viaIJWAL=;t}d$X9B9mh0!~|G6KAjb{u%?ZjvD zz~#K$vkseGRO5jI4|667)y2DD^;U|D*$+bE)3}zhPoy{Lf@3i`qv?A~Wo z`oGxWdCH!?gLk>^a5`Vuw6?)K;GMyK#bPs6Twi!4o_hRzEVebaZCRqU_PWeG)e}Ea zazceZR$5h3dAKw5EfxFqxVrAziO|DKM`zbxb*kj*`jODX^`oCCyjt?9%>KkviC0zV z`tnnUJOBGs=;6=}Ma`j)shY1JuSt}yIac-WXJ%h>Q|C()Ux=5q{@0nqo!>n5SXJoV zHHp`cFIL|@ldO((j~=fa`Ij@+Wl*n;6|4E(OVabZ7Z>1t8%xy5=PpD>GJ#Cp4uumv&ba7NvXQrRx`0J<>V% z8-3|N>zt#pW_RyPJeFRWcwFOT#!J`#@XU#g(w2D>PyRy1GMhr(m4(bEBhQS@>n>7@ z3iH%QI>V<_O=Kja>n>eZa`U!$d3sCL+|inmj}#uusG9F)Y7TsNgf07l*QQNCfBQZ` zF0sxdm`U{49u?_5lEbbbxL!=YZ{VIvyK65V#Rz0QaMf5JXy4`v{HqJ^8~p9DBR=|$ zxdHuLjpw2GkB-1w_$BiK_1n9 t7wpZxrX?e~aY$fJn%G&WzMCG;=!iE`iLxHIT} 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..85cd5e02cebf40b54a0c17842daccc0d75e7696f GIT binary patch literal 52210 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 IdTP6W0bUj7`2YX_ literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..fa947cc2ea16b9f8b37fa1a43e1ce3c8127f7fde GIT binary patch literal 270784 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 z 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 M>}>|=vTZZ|FCo>;NdN!< literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..49243d1927ca19ba404fb9d1d2340f125ff329d8 GIT binary patch literal 93270 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 0000000000000000000000000000000000000000..fe97d4d83fd03b1f341ef19f702084bf30fdba1c GIT binary patch literal 17880 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..3efbdd6402578a6cfab1283b54021ee49990c97c GIT binary patch literal 451060 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㺖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 z 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 0000000000000000000000000000000000000000..a8ba7678d45c697fe6d1288feb5dcdd935e86df7 GIT binary patch literal 15716 zcmeHOZEPIJd7j%llBd%bMamLoQS_2J*~dmCj}#@J1j`Uf-HI2HkxEjLlh{2Tk4y0s zew^-(5-F>;>`1m_3xSQ=u9W6OMeRmT4OCGpz&|XYY5T*C{ex;7AV`ctEl{*5io!l#)ST2Nb$0x59=Y>#LLqQ02wT6YbdgbkO&xjbb(}}4}fp#D@HL9#kOD4Mp`jhGD z$;s)d38{K%Kv_7Hx6{eVRA#Dm+8M$2&C$)VOxesxMX~gc%&^9SJ0Yxj^s2|NeZT z`jS)Lbd1Pe{NB3n2SZjxg1Hk7fq$SKZ5X}qe}A8Kxz!g%Sf2r>m#e?*GByF8zR2>2P4ZbFPC+RNN9dz zxyg)-%w#4;%}vp0vpF<9J+aM9LR{pAZggX-RM0YPPf##%Cr+VDs6D zOd*LWDP*Rn@@7jKX$Pie%$Dgk=`i1RB;VHE7jGMxuv^m8xzWsYOTK`6rbTAAZRzN+ z$I=}g4!g}^&|lk7*TAm$P_jR|w{2+8p1z*muEb~LJvlhEv&f^Tw)~Mc7I5xWM%~*3 zO-W~Gw)afu3ifPEe>6KWgBG@=vg!Qx%v8b79huI3(QMhX30EOAX`3yHn{2dduHKBy zRC;1&^md&c$#b-9_U%Z1tnGk3W#=*&+}moQ$LXDEDMw%S|IWBmZM?JI(8!rWX2NXQ z*}rG!zP@-ev2#0ag~^$TLS|&HU?Z(0< z!hh2E3YV~(@w1W++^`C^tM;iA^m3~{YHrbo-k%2Pu=;8BGp6)CZQro9vb;^T#L z8pbl z{uM^0*zIDP6~;1g+U0XhYYd;@9nJC_!y3a7$6d@Dt;X<+11{$5)fh{~qp&K}7(%ou z086~VgRjn=lh3+TXac_)AhgbT;0)}x>VauZ+WU~l{0C5$7MU^~i2)6V(D=Q?YlV0W zmgOIJZIrfF2<|fs?BpcIQzYsU*k^Oo+A}$dLfoq!$Yqmy2g7BWg&t$?Tc%8` zT*l^d8SR~AbJ|5WH&tE5X$gmidi#@!!LGxb`on|az436@w!V&z@MGKh+S|i}h$Z6j zczZapKfG@+KKR)!;im?NcK7Vw>A;5pd;7wBh7$epaJ;)K79NQIZY;caAU+ri$Gf@{ zhdVGE=wES0%g#-vm7|IAlT%qlD2{YzdO2y~Q4ubPyYk-a;#wdlTliWL?dfQ3kBW+t z-I}OevdFi>S7WR+R{QFFYkc?n8u+*f%(w7WAyT71xxl|597G=3l`e|TraX%FuhFxLYWu#CvSe(L^S1|F6<&L36pp8)E;`3P9$k*VU}Ks<=c&qRbD z<6<2uDBf#G(EXA3O;t$Cdq|5TD*gZtdKqzp^5NzE2)vz&1Y3^xK*f#m(%@aI-lyOj zOJOm*4Iba%ybrLn%5h%TQD&F(_nyY%t4;CN zAgwBTh``IpeBUIkzk59=vjN_q9U!Mxu0hD{yO z8~)z#vNJKo?+vw>nT3nboL^_HwxVX}8`Sdwv37p>?z*F0^?!F^O>QA#Tn<`^`Zc*L z*$v14G%Ff6n!bHa)>f;|BHK9QJ576Kw&MIpmljO^b?%ESzBL4+_gRT`!^31WS`k@- z-zSWOulK!?>@KbQf*%Tg%f1`PX@=sv_t`*xsYyD*UP*HITg07F=J!4ul=~8Pt&d9D zX9M1&H}};bqCM3Eh;Rw`9W6R&9nIs<5TI}T(&@2+LM|{w|B&PvUBAW z;w`AnUyY{JMp-IEeS}rQT@i~Zx!V2Gwc_vLmgF;`YenwgRp6eKA%RQhodV`FtO6b- z8K}>6-Z^0I!BtTHW|5#ji|+udJaSch+QWMn`0LuHSNSMv9TrCT931HVD98H_c)d;$ z`L`VJXW(5+I~_nN)pt6GL1P_<6YkB`o}T^xJT7Moj0nOz7;qDoX{?j|<=PU*rSpCO z9?LV0^(Y?K6P@?(8jr)Hc(ww3@LoW^3Tm7= zPTF*e^WgoV%0!-u(t?*&<#(a;*P1tKm^6-Gm58~nhS|D#%Z;9y9^;}fgh#`iJpZ`4 z?3>FS1=G+nZ(7l)uW4iB*^&GDL;ISK{&TkZXrjJ3_YgEp<(bBG)tT>}5Dz|g!e^Q7 z!LNpLpUG7>iFFlcs8qgn5Ffl>H(rmJ{@1_zM3bvqGFEIIbA9HbqQ?2?;>m+AoyVDK z%LAw}7)`A6zf6v~Idio7!BlVHWzoEH-q-x}ywSYuvj22-Q|MkY~_ZJO_P>+$_QQvHRq2VW&MaxyD&om#N&AoZ>+^OdA|2Va%uKNC6 z7pmLpKCEsUmu;wSTQvWZwe6OJGS+ePP@TE;y(7)m%62EsFq<2D_xZ1=66a0{oFI=| zK{;~gPBmH8(Q_vvX4ew|sS7h!WZl*)3;*_z^~S-ory9rqMb;X>P~E~>E6;HZs#_M# z&#Y~>98~$%aWf-pZA7h38fy*8S{-~=)>?VaFKaz}Y8z@ji&}kdt(9+?a;`Y0CT&|5U^DX=gFdO0opD4{YWIhML35F-%FY|*c z8*lO>MK0g#KF_(W;W@YUU+3I5C@vIzv$d7tObMRgp=rVdr-xNIYJ z=vTDz)RABE;JgPP@L+xK$?{%Z+vVXu?7I3TG4`|`%hqO41_%B-M=AXOiOE8Ya4Ya7In-=`N zwBV1r`2{!qSr@-b3;x$=(HPDL+r@b>umRo}@-~&X2FnTb$EI_? zVOqU7Q&O9k%u+GsuE_N?HAY(e()IcfHw>yd#^YDhS zR^hQL2F2qiQ~Fb36g-v3G!^Iis`JLdyOFclDu_{i%~U=f^7u=Fx0e;Vp&ake!FxoJ zU={Bm;%HJa{3m! zW3ByAWokSop)NEwj}M$ueeBqpMxbra!I=N_820%TcaAb45|N^K9~k*;Q!4hR9O<_BnLfY|5;2 zG-G7$O19C8x@VPF)0-{RGMhHEhofv+DU15D_ny8i-a_{z<~@md^%v#8c0Ywy_vy{4 z%sMV(Zs5!B#?Bvq@vo{k-i9C3Z3_)I8XnbqFm0;h4)UyLFW}j+|fUsdzpg!$W z0G9Y}pSy-o4|ShO3!NFJh3;g3sP}kw!hD&I{8nN-2Qk;~poP9RF_7T&P3Ye*-#m2`$QzN1Z8kBlZgtW0NB>_COLVory+EjE$nqr<2>!nQ`|&y^1mu z37=G%NW_1TmHg9~UcmkDvb%fYtBFf$O*9feO2*Hd`=-;WiM<`0x9pu6;s3bF47AA3 z;h(K`_A===_xHy*D^@co#il-cD#1H*S~>^kZv5=ncDK{N0(C0HQ9Ke@YD)AepBWVb zZiL^JblxcNUPXdcyo87MmmZ$da$Fa5e*u7Mq^Y3%eH97hsjw12XX0W zW`8+OhjC%KD~5L=B26GlDEcCgYv<>2>AVlYiz1CY)}wfF4{r$yM_it+ce#%0{yM>9 zd+3k8ls~U7-l_4>gtELLjfZGi-l)c7d&<>Y(0F`@DV|q9p8)UM$X7wlhgUzhqO$*1 TnINkut*)ONF(AFlna2Bnd8I6Z literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 0000000000000000000000000000000000000000..cdaedc932fb07a602423d8e85517b6b20a342707 GIT binary patch literal 446718 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

KZ-58Sa(gOviFwSGZ4x zXWxr_u5iB$&*s_h3NMi1>>rjZaD^9&f7bcMT!i1neox^5BKTnc_o@z;*dtCjuva|c zz&^Pzo=Oby{o)=+c!5YcF!as_re60aIx_OZ?`HqE!pslt5hr!H#52SnIq*#Jc?X^) z_Bb$ptIvT;#B~l_D!zsMFiUJR>T&->VYU(VxWA(?+k|>t>aEFV8&Hq?358kb)Z>mS z%zn*%0b6j^j(SCmC!s&fL41qCew_K8D$7Ivkn(4Fh|3hN;~6C8-|N=H;-y4}S7i0D662*t z^5?2>t>?vifehDr-ZBV1AG^v_%TD!qsr+=6DqHxp#0F#OnB0=hP`)Cd8Jnd|8_?9> zkGM&E*qJi*wTPlZg#Dvl{n2z(;G@~0q1Z6E(`jcd#T_Esy1(fyF~nh<(h7N#>c zG_pgLgc!N8iuLZPYwL1-v|9hZoFVVJjtJYXF@k>$As@`BXg550gV^bTM zy~Xx4dy4Jp=p}AnvC8Th@0EhKU(O(!8gR$_B27Z&Zy$0j;_i$97uYt1jNl;OR1vj3HLK zui-!CY4;j{mO(##{l~bro}Cu+BqQNjrk$2?93J|bVdPDxcctEtJReDL4MmoG3uV*A zBfufA5xlE3$p~}v_`Pg<9=sR9YsrIGio)lUZYy{ldB{5q-gNoyx6!=CF5V9e9xik8es1vi49_L66oI-Nm=@&ZRT?}@2XgXO z7`!v-Nv|?^Okd~Et^aHX?;jAZoxXQ;y=(t^WWLSl7@DWfV1XB@i^Uz zU)EGV;qs39&xSR14f%ej+sF=O=s(wBmy^2Vdya}F3u`=|77tNR=Q~<=f_|Q9{KS$4 z)9{>rGumdh&b&GhEgKIcJ)zcJrPl-^f8JYJH)q_J^e+DMy~VBj`pd=}>H|q1LIZ7u zt@~^}A2Zj3BZQ+7hj#ozct)f!QX+q0#@g9V)K+EcB9&FG&2?>!6_pM1Gh(3Sz_WLY zLo9_@5zL6gqPCniwGY(ccVli}JgZ8EtoCJs5Bm@Eni^J~fBdHJ@UxZT(2;Q6$$yDdo%vSB@O;5-{BIqYhh21sJ$d39`;Q1#5dvyKI}|sptLUH+7EgP&qpOCd=7_<1PID%)YTbM=z_b&(zkgo_rB| z7p}^L>i+at!`&?D#cg6~OGV{XNA}a2+LHIB-3@npKJ7j9o&92YLFV$vtSa#trudJ$ z#ge!vns+6>Q!dPSKIc8GLq51?sB&fD%9;O~p0Tka>7*j?}!^>v8(jSW@b;nT|@Oc7aS|l}zKJ%oAgt z%c^QCGS#&+Cs|I|WiS2G?%J{M>}Lz=vV{h|e#fa3PmER7{?}w&?#FoQ#BK3KcP?Bt zGZQ)>YG-C{-d8)unog=()~qSWd}}f^uzJjM;3NCy@AJ#{Ubrfd2@Oo#Eox`U`2Re) zWY4J+|FHXuyQ@Q?RG?MFckQ(D3(fiB2L6&!mG~6vS!vRBx$d^hh1#o-B`cLBE6=br zvoc@WZOM58X$2;0@BYsIDaZ=nZ;cU=@0bqz<>onKqtbr)>~zVMhRknDnNHpB+2k)|$m*4{jJ+L^ zzrnn1y{+;xZSAIT;m~vA8}{2|dDHU$+2qqKGv8Ux?N@b9x4m8uS?8J$zNf1-iTgds z(55*b`<0M|VmsVTzAWV0!u1B`8;cWrUD)Tseitqfosh?NvRr{HyikTu>0oF@oaq(G zaNc{CD{_SgWH|f27zz(s<;udN-|PIfym_EK=*p!je7k|`to z=5we!FN{7MJDM1&l;LKHdh zEb&7f8D|f)1J9s5q)g%PqCfn$!t4XIf&Yxcy%Gn+UWM7lUT8VKhcg}9Z??A-uWFV& z-tSy%nd89tMnc86!hPa94(u2FJ#yxUeVA)4w=2v(Q;y9)U&mQHuATga1~?Nx@4|oR z!oTanM_l+J7rxhpM_oAX!XI+sE(6m>zsbPNZ@mj+nZ|Yur`}6D#=lqtoTsz-he}1- z{O3AThw6nv+*Ld`3V}c2#lIGHZdK=Yp0Nhh!7~DbI0xTv>63zJoK?gSLVhr8wSVvm zYt4!N!}LdD2YGH*d#L`J5Y(jxuT*=fZm@oDoAIaM&wQ~zc^j>@qu>X#@_XS=p6r+4 z$^0N6_>=z3C&T-3rknsV0$EP_%W$NZP*sle#rLkX>=?b5tFKkSYha(B)>*s+*}f)Gs*NWR(Pqx7b$$1!uV$6T-WBN+fz2hEjQ%vYBdjUQ_FJH z!L`ZXy)rkHRld#X6Zq%scZ8#`Ey|WqytrA@6&>7?m*HU9USb9_T9#? zjYEm_&K4|8S``By#4(o>Q9gVI(mgN~OLnD45(bDS)7Z*ZdPGyVT|YcH0+HkbVb5E6 zjik9@483uwch0pl)V`*VX>$)7>!Xsk;pVLTV?nSv@uj4+neX{pp z*2}*CEHC43K@;=dvsOj{jCEFnW!!TX(;23s8=jD)@3qq+AdHLgShjy}S6>I@d+aZI z^>rC0J@~WNDLHOq7`L5QT@|}{eEv+wdkg-iyjybcGA>>s2anHfQ{Gh`X~LSmUETK?DR;?eEM zUn6*Cx;pP}-b3J-<;}&L0_3>|$@V0VxWL7G+TbxA z&HDkaO?l56JoZV=d)dX~-au_zRTWj!U8ob3W zUMqO08Y%BgYvDH;Jo0tAZh3Koha%Lr!^5 z8$7&r*^b);C5C#h*| zfwmxl{kOytu8Ia*{c-GNm8sibwSQmO_v(^J4e+VS<&pY`uayiQ)^1*q-4?KS%<{Cg zruh|652T(tJ~MJrMAQt(m2**Bkl7V4-d8`-7_aRSQ^A^0$dE7M9iIb3H-*NsIl_riHl`3GJ*Y1V6UyxNHNf<$$}}d%$KQ-cwIR>b^MaZ z%!pr=Z9uJD`^Buxk^7Efr?MGKN~YG}Hx7H`O7xMtM3L`XN8*JO$fK-{TI90~zfZ`N zMQx$n2TiYjpPDQ?!QU?2H#Q?uTRV4B`@318yBWI?l0%U|9j|?@%OVr;=i{Nsp-omz zo;rRJzF;d<>CDTlxU+nP@Aaz4#Tx?4JSU?8|5WFSS(#UGh^mXO*)KkKlem0FX71J3 z-SU-i(MkSF2Rpgn zk`$rC$&<;2sRHbfZmpwRtJfSmu(#W0f21~!2~h3qOz3V;wO`s_6t#-+P&yO}jfU>- z*oD<~-N`3mrU;NhI~-Eg%KlJELG)Y!J;JI}eTJ6mhxrmVf^ zDU0)3?I<^&@7dgYpmFZ0T?;PG_4gsoys&Q1B`o4#&Zdpba&VrRUpdbFts-US z&cm7G@?9}^+|zAD%>1v(JO5{vlYc#&F30SrR=+rR`w~-DjVxQfvfjClAd2d>7hAVug3}?T$+)VLfRe!7l zA2bX9q;QqQ<>I>vw@5rkyrwYY(=Osq9M~)Vz=3_@Q3v*m&p2>_*z3TBVuu44i5>?I zhzboZIB0hfR(P+(K`}>R_Bk(h#qlf5KIVlTN|BP!{x#cM zCQd0eM2p08#9t{s?|Is7Jf|@4aegEFKONX7epBHZ8SWQ{6{dXJZQQFc?^%8$JEm}p z#6_Z4VUBs_-hf!^;FpM{3UeM&?kyGH&#Fy;VK?Byf9b+6xG=vJ(~j|f+l4>t!uPxI zgbR%q?OL=a$p0U9j)P1e;AN&x0Ka=6N2=Q^Aw^-kT z^V{rwz|8kt`fpbGyk6DAt(LCdi}G-e$oR6p5MS4iOds)Nxse{77mdaIdq1dnu+w3D z?^VhljVCJfPCUc?IR7aCJO?RM{cL6~0oH z1DTWI?^hU=CGjeSYZP9sFzj4pIR34pTr`fv^$IUj7=xP(zf9q^3RfwNKpBqCDdS(E z@Ir;xD_pJc`xIWRaD&1jg*PaCDKd4A-@dC)jbYJZu6;`b7pkIRcHy>=fsICXE#ESA zA#-Cg*_lch);KK#slM=NN}I!wleH_!#^Wy_yOWT+RNB9(lQQgPuped zhBq!d9c+r}iiYftB)jq3XNIVz(R6$SzubJ)7<%oE|k{1O^LkS@dfg-Zo|U z*fyMsCDS%+f%y@F^j5d086}|;w!uhDnJ6{KV|}+tteXyn>+T(tO)InhF4-xq%ehy= zy82w!NNaPNL#_S4(;jN`z;H+ZXnSl}R{t;8G|C=4E%PSFz-f7@LDK^EfT^HuglFOG zK&kLxESj`$;FL0U(gUPr-eeAr+LmfS?+>g8MJpgXAX?Zp7%ES_X^47k`~u9Slt%Iw zZ7+4B$9f;)yp4{}Z9IN$$N3B$=h^tP?WzWG%{h#Anz!7=8v|iFUWJRd7d%WyY=^0? zbZ$GXC*aGuk9IoUe}{*ezt@1LE63lvc>LY87A*{Co$l9Nybka<=hIH}z6=jD-9dm> zO~P5{?>Ah$r@%Wn4Uc}NyhbF1>7(tmyt`byaquv$vz^Xgzl--I0;X#ZzIT}EJ`LV< z^*jy|dD?vsJe?={>FYZ{3IJ>M!1uwc(2)!tzsoS?k=IKD8Rc|X7?{@xmaZMbtJF15 zI$gFoc{<$$cr7F-r+JvVI?{a#ymn18!rVL>x#YuZ2hU7bm%}aZ5O}S5qQanB@w7kD{@t!ewMF#I{F5Vm9aXetUEVq{T z2QJ=^!Q(q5dCZUIea^+JnVT&Kx}we7=itLl?7oci`GA?;v<=Px8>zHm?WQ zCT|=(-EK1s9#jJk-d;oAOoInifrIyukw5B4ba~ggcu#>BhadBYDzbTtUA#&dndx#M zN>1JigNMtUysHczbul`B?sVG?-X&+?-D2?AA9BeXGe;vF=2Py^-U zJ!0_q{LdxtNrMM9M^4@|1`q0yoV=F}9@QSX(tX3=h0ehHfx)XXcy9Z@pM!T0V~KY9 zayC3T-e|WEjoLlUbDDhc5}Nl0Dy>xmoV7f@LvBq#J>a(gTN4V^*VWY<|JScy7YeQ4 zaK(C9X2HF){oh=a0nWDny9_hS;ML`Ev3yo$&i*~&;*(wYU-)XU=el_L{t4`&9;irc zV)(yK;+H))F>={cGp|_?7nfg@socLe?0x-USey(+_F|9mTY!sR{ZM?t{;$nn;CZQH zc261h6esteCd;1D@lPF}5xF>06se3{9`;RomiaTj5G?IhdNbZBFRp5eLq(0VewML* zsk5rc^DX=yXeL;@mW zv*XTUZ)3%tqZ7wGhi2cEk?0f0JlJK(lX*Jqf8A4K?c2U*Dt;iKb_x=QMC~0JUnH>h z|7Gu8;H#?6yy12Bx#r|TE`SFJuyX-Uj$9HzjY>5)4he!HptY8kT;W8MaL7f%O%jZl zfNjy*HmG%?V>{T}P(GQ@cI*tceLL3a^gYqqYR7pe?bvGjbvm|nrgmoD`u?A_*E(nI zMNZgUY~SBkmWI9m>-n!|-PhTBt!J<0HA8Wid0TvSz3Ui@Jz97j&L;g(!Z>^w`96t! z=S2@A-!;Jgmuh0{Z~!Hi8)9Xi@wF3VL-(`s=)}RjFZ%Nm?BU?@hia}LH;P;56~~+6 z8NtWnuNS&vxy6?4VD8F_i93#bKU6&TlQoN9DvAe#&2b}^-~U9M#j5%z;tT6b=ML7) z#|fh&Co7|0shRzXFKX5ssF@jwTv%%wubx19T+v~qX9KYRr46XT!?W{U14z%a!W;(9iqEh7EGx6>ldE!2Nq$KJoa`D~nX|ExxeAsB&5p#B+^5992$sXaB zjAEzzci$zuL0_`0?>%|h687R{+=kLMe;Rh-85ka{F&sG0YYanv|m9UDXG zXNP7d%CVo6%XA(6x4o5Ba}$+lO%d!XMe)0$*Z93Ai@1Ks%KV97$zRt_OXTvJ`oXx% zyyA#ES{w})SvjV>8|K?@7-heHso$URaw%_b1+X+lTNoW(!@@ruKfbrxpY^hF>|-&u zERbNIU?t@Tg2hGAXVzp*1kCThG2jcnJhOgHJ6q;Ms*0oDqB~>HAmq2lkH=iY@gp_! z9;k8sFc4)ERrBscy=I6O=wW}G$Sf-AHlx?Tubo?{9w_|k$qK3)tNcXiqd%T9VE>xO z?MHLJ=ISr#KUU)%uj;?Ke;DTmxJ=kl;xG49LG<8W7JJceBy!78_7euqG{`N>Nw}gR z5jGgLPBoyuL18HDtms>BSpDfw(&o|{hcDS&Ub4BoWOI4R=JLI=x#XkFxt$hEZ!FT$ zTlx7|`Kdav0D6u(&fL9cF?59ScXn&eGfxz-@^E0tb!!mE2~=m+;a_LE&a~!i=6P{y z*>#fk>O|LbNfU9Uqc4YSyG=z4`i)2V#!KtzxZLyAJ6qRVU(j#u=VaW- zkKvUGNL~*a$y>ZT{p#I&6ija+1He?1mUA(?+~9JmEz232+|A`w1D11Zau1iMzN7MJ zaxa%tsawvg$$eZ-xwf27llwIsV4X_-$d2uUHf-4TeWm?0Gd*T4%#KY`G0jW3(P19qp&{dkJu*{eE7z;e7V@Hk`>$ z+He-%Ux-vv9g`i_hmd~4RHtNzb%Vgo9J|>S0#lvQSp}s6Qyq~V7TMlVc&Zb!!-5Kq zX++64{OoP`liboDV1JH#=_u?265vYskcMeKUpkU^NPsKhMh&OhjwP?t4BxWbxqp!D>T zKlHvuSMWWg7wO0s`U`O-{Q;7rkff?N?#8CB?edi0Gb|>~v^8n!?%aCU zwzjP?n1SHX;HkHJ>1^w4K@Lf+SY@W$fhL3-O@p8@bB5l!2dUFzw*c0aYZ)XR8zJZu7%Y`oAMD2 zHszro5x{y~SG__^aBCVOv7WRi;?Pu(N zVo1S|mt4oEafZeu={(}*E4ZpW8rQ3Yj4qN#zjG?@N#Ga}gp<4xV3kMf?zC1eo#gdu zyng%^ZIL8gCGW!;kM_GWC(*Z7K)7_g?>gko#^PGN zREBFhea+y}Z?<&lcwbG!`!NE_x*;9YvoKGKI;Q8FBK%Q(;AfdXFQRCZZfKhIn~$Gd zo;KpqGr%eQsl59Y9>pVhWY3}U9s-ZzA$^EG$-7tMJqg|h!6RK#UtHt84PLq6c@^I6 z8m|h#<$Xut;ju0)?=^*o$Gs#^UuXLTc_ai``dkVbI8B4rDKhGZYBCZFaSn0}=L_dvHCFTbi%X#K`{V9< zlG8)G3xBj$L+)MdT`{{J=O@R4k4=lRC71JeER%5| zyZQMTv>KN=>TNWmbP`99$J|<29z(q4<&81q!1dCzH9vio;(rONhVn#Yiu<>xK8_W+ zImYSGNBN3e0aoM)WiLN;GV{T2&wsFR_+;*b(~er}b0_%vTn=Bk`J0KH(W>MMof|83 zcP9en{vyv&SG)?RfEZ@h(ah1{(dK&BqkgQ$#1oZBiM1+5IVyZ*H*z!!Iogdf%??eQ z2uFiBF`BPRg^dJTJZ*gM#3tm%pJ**aUasipIeEI~=dWH5eLooQn0RyVX@5>)8rBXk zPtf|!w9&yD-?$NNkLB_-vhaMI?{T8${V!IdZZ{{WW)0KJ)3vIeQngk~)%848tCFc& zK9M?L-rIG7c8O;k*jOt52Xj)H>|b9pS(eN^D23Jd^~%iFm2wR9(RvId-)*N1>Is@&?6d&>^ipQ|y}P$gB*$Lkq35l_4K4zRKxGPFyA7BUvJ4 zgn1W2TYm5aGkr&mqld>>Ebpjn*#js2M`gP{bh2T7_VVXXPJb}_s1f!ja5pVT>=$L0kG5DG z{l?z>QCAV;JI&-EN7)JgLtmQ6P3rs7L@;@Od?H`zMLw|O32!uTMV^`QiEw<{X#TN* zSi=!Ee0Y9m;n5oQQf~D0N%Xb3;dn>f3?7f0(SI$Z9)mq%;w%_Lh%Xja$HGy!wOTw{ ze^WSQ9DTN?i}#_YYwma@do=Utbo9$wKEgGNapr^=XO{4BCXyUy=1&A4&OA1a=a0?- z%KZdeT#sB1#)8A{V~1;M#woYOQHGXc_1wHf<;1fX`&tX9jnW7-?Wi>ZJzeuEAA!C# z9-b(ga33>9t3vt5*xa>8GLGFG8m^i9iZSYm8=p3j3p4t~DRV`6dgzV3WGQ-4iWGYe zYA=w;AI&XdM{*wV^D>x$_TfWpKG7#oH=<9FgvMbx22;P-5IS-Kqu9~dk?Gh^hb_!l zIdGCR)A-hp@okzI-;AUF(V?2=7n}Oc{tVbN96A|zsyzB6Pjv>kfy6h^dzMG7Qt`9m zao2=v(fo;w(E;?F?3V+)=VT-@Mq%4f5rr<7YYJv(bM-FBkLvGad5f(b`z} zfVYUGSqY2_SPP~Ug^yetT^`NhrJjkL#4sk+gbdWl^jF=-szb(TV0Ol_K>0{);AGD5 zA+#M|l(bdH3|>~o=)f#17mvO~wIRn0>S?5(bixK<(F=UFIrTd+bkgceA3bq8G=Sa| zI76QvL9tW6+B)Lbv?k2n$e7h1H2dcqAOW2 z5k!i-)f<1uxEnx=&ysWHoW(QXC z{fV5>8)6KlO{L^!H;t>mOkUK+{)8tQSeapZ9x~&>(HzmIg7aH>p9;*UJ~dEi#<#`G zgJWR4jy_~2`_Ns5X6WgY#?ioI8Kc=pb4Rm|w(-7mccS$sdOk?~rp@QQr!d)j@+Pt# z&OR0ty$8S2=skJkAD359! z-dd&a1+@{x8b7W^e-0qELp3X5=R)PcCYDW5SrqfKDAUG~dAua%BugUKRuXPr68Dei zq$!6tc{#j1?nS%wPWoGxSHg3BB*5Fh{B=w9u$f$ zqEnJcN|X7nTYppCE$dcqZK!)6`gbQj(rjUyIEy~YQ);x!jyC-4hQi&Pi%4|(tP9CF`heAKnN;11)T zQwcuba(DtWFgCpn1$VgL=i-X%k>GRDTaLU-N2}g8dx_eDxN$pI+fM(&Jmi0T>+h;F z&qY6RrCX_|ySiYTJ7}eQ9j`&jl-FI#Toc(%sQa(bOzBR@sa06cW!s;HW@1U6oRk8# zhj(*1)sp4hn%u+X)H*EZ(d5=SHk2#Nc{RC@hfmoO_%ykn%c(Xk=V$Lv-qU=Vi&fjO z!7jI9H=AL@9`>Kfyij;Ad)4#_T}R$!_#vWr+EFx64M;bxZ!Om#wb5&sQ; z3Qu)Fb`d`nn97{&A`${q8IxVar@@tu>e>P6TcgRZ z(r}rEvGksF6kfG^AWV6ct{Auqfb0Wq6xU%~X`c*QKO%ohFJW%?aJjWcLv{$1Z<7Cz zt`%4dg5uzOobN+d_&-TkEXsU=t_b&6;`&Xx!d`;f5&2X53NB=f>WAVnNgwPPpn}^s ze3Gt+?+bLrQ1Df{g8u?tq33(JQn>2~L*Hg`ZKdlnt6c<5oEJ_Q_7YDD`3Z6T8@fXO zJ9I_*seMvB++G8T7$A&rJiUxg3iuTrTZG@&%T5Au|P*b|J9y;QT@n zemWw#AiEE_I4<|IP|P%ht%uxB<4lQdQ;jpla%&B{gqG0HjEsC~6~CctG7FGRZQXaZ zx3uy2R@0#*J-a)5o0{oxlFrVyF6>z1$Ph#^0Ff30wCF+imc0O>4a%ZFVMyh7xbRbEi}wYGykh*;IMKJqA@47jm6hC{NenZg~ir|mO1YXWa3VRuU8TgZqzU2%7fX>T{>LY-^zs8@+TMQnBCmzKk zd5>$nRp7-0578%i_i4N*!K)NJ(k1m#ST$by{&rOGR67lN4pDi%_|2~pJT%#)K6+kI zc~65!=4pc@HxJp&_hev!mWooZL})-$~;s z>+4bvTY**V@&i~8?P2h5%_oKq60$S(JC4dn+Yce5H+hqB&x9ACY96F3)ypL0U%&@uSTO*D?Mxra_# z-^}{i7aFI7vpkwxL91%!-jX6(HxAbS`lNf`)zKLLl9Yx2dEBxmvFrs>YucsAZzKK& z`%B99kH2-w)t^;-bL|al?>q6)P}X(Tv8Q8!V$X5X+%#fFrBitU-maN}2g`q`sqD!d_hVddE&mtHF#aZAdz$*R1w05(5!P=6+yPI( z8}J4EXMUqgPn_xFy^yd|rM^4v*Jl-B~MLb{k;ZfJ5tle;y!Ta$aZ zoJ!Mj9!>7$a%v%#^J;P*ms3q!&d074>8F-J-+mS;`JpwG0vk5?oUaT`-=6+kQWu5y zuvcx^%f4m9KDJrG^lfQ_z!bj=@h?;4w1zUnhO-&HyG!RnN&iR!TxkvEc^eM0zqH{@ z_K(mQriSLtY8oZcs; zBYeLExDp=JaG!?THB8?ONJrr}OMokV+qquDs}xLpwZ{`y*GwpUs%=^6qr6K;YbNx* zW}tBND_+64Kc>AIee-D26>9|aOi6R?)Ps$s;+sq)0=IlkfaZXL3#^wkT8lVL800bG ze}b-1@-4dJ#W_J&tPy-)Tqkg)^t>*vZ_+g);z2kb&oZ%wfOwyVoZ{j7pyxY;F@f_I zU6Br&L!$WT+hB^Xl&;{>UZ{L+16PW#imu3Coxt^UMZDz{Ki)HGF2Im$2g+Iim*c&b z%jH@E3XkJl5niq};6<17a#8f)bdY8@$Z=* zgz}xVS9kHPv-!QYjkdL;c6CR`ju!U*O}*G>{jRp|p0?WfZnmkdrM9!FCEX_0Y4@;B zyM^`g@^rc?u1YIOyS;Wr1^0I-V$&!_N8G+r)#9z8zD^3&(qTd6Cvo;Go+c%6WE3bAu*B++IQs&wVP%$$R}I) z)KAa}%xqTl2$y=1IJ>_q5ObJ@gF=Q*mjIoy)@Zs~jeCITTy`abLs|Bl6-{6Z{ydBgleC+|NQc+mTl_3fRP1rqvkV& z$6q*_5qzrqm)#Y?vYujatnYDJ=RR@r>LZtn-7Hh(vdj>t#A0K7U!} zxU6wsq5w5scEnX|eZ@riaFygQ`_J+4k$k1}s11<&lUxT751~2z@*c1E@qb-TuynhoT16xTuxHHk5p0~Xs&rwU`jLD@6)?7{^vG!WWUcJ z%tRbCcl%`}KEj{X@Ti9G*YJRbcWRj4#iS$sAC>@Dnk!zbV3J?2;iVd;cTDMsug*1- zKFX_fG}lb?7(vXXV)~T@F^7DO!0W`7=E8$e(jnyE5&krn5JX_ATay2hu7&sq5d=e) zeR&WsK#K`u4wlNF&O@a>K=D-46^Y$OSJ;HzO;^n2ewD7!!}UVX1YykO{+zDR$L;6g zPd1FCm+H}gK^*0q^ip|{-cQmMyw8bn^iEFv1YL!GN>4ekftNsfhowEDIL3P#$9Spb zI7{FFNEb9WOw+3B^e?@skzew-Haa-bK4)w@KJh$FzT=o?uHCks&sLswDp#@W*3a9d zNrJQaqAJ11Ug`c8JX0x9$)hWHRAk)!GYXf= zN;=8I5V(~eJ-K5U9j;@ZZEmfi{3>C{diHa868K$$OWLt+W;Zie!}Hsu^&sq7T~#5o zvg(NC6JQyMgZAS#KgWju0&=zLh+MB=HR4|xj3hX6;;iqIhfq9WfuMJ zjoee&>xNE@Z6lw|1~xw?JHvyS((MdqqS;lTKt!{$AgnT_{^`^{b3cm2h# zH+Go^Xz!zVS6TGy*iGf=n)2k`aqOhU#ux4SRTo1}!_nb2@{FMP8u|~v{ip6d(Gd-N z+8lU1{x5N6nuE=QW{R!VM~E@V+~Z+^;v(PWPZ#WY&F{UzotV=#CszJ!Xw3)3)hdV?rbQ03$?Jcud}QkYV*~tQ z2)<$bO>X^p=7}UGxYFTO7V}AW4;lBm*3elg|D!symM-b_O>LQpSK)I?OGqXJ*K2rM z&hK;->k-IOb}QH8?8KIUYwG;aBj5R!#nfS^wvIhpSbx$g*V;`6Qz}VE_ZNDCk9nRt z)Osl8I`$8_@5K%=n6$j9VE+_ld1gCRb|r}wS&>6kh!9<_(D)(i61O&Y zBfazqM|0FSD45>7>wzinmUA(?+~D$5ec>z{TX;8@Qyp5)t;s!HPVK~U9!>7muusE& z9-ivia(+!7;BsoqmJ4X|3@%T#`wUGUD-Ef>_}nHtX0aJGhXxV}=U4p!Rs@|wow zG{#$QnkLWX@>F@|YVte{=W{-d3zo~*u)CP-pAvbX;aWx{~$?ccOvFZ)Lu_OXAkVLyA;h6C*LHk`p8w&5T< zWW$-P+lI4PqYY=X8*Mm;t+L^1EMmjCtk8z@xGh>LzxnLH=|@U9H_G?0f@#g=Zh@(M zUHH1ZRgt^c9Jbbm3t71h&t)@hcpl#qNyg`bMcj|&8@B$XK;e~unLTYfaMXbOkpT&MBg}AyfqW!ZCm$Cn0!x8p*8@}AOXOoM~ zW{;x$DGKVN1}xpK6PWstfmuA-Gz$kR6ap0@DUES zi0?GuPrtK9iDgquJW7voqgZ3Q$(m<1)?4)*+-7|z6U0P1#S?55a)et&;o4L28YFMF z;w8PeksMblXS#Aet}=aSCXDn`Ig^~)S1@Lkvq6F2j4jrjtMMT#e!5aSGd?KNjd?O2 z9{=!spzt|fEHD~5$14QBR$wgDaXu2o4bIHN0xlM8i8AF;|-+uYP5zaznMA z>gcd@t<$?SYHdq%a)YR3T->vEM^{$^wyWxH>)@XiY;4=!-edc$1&NGyx5*RFuvn?3 z8b0++U9BB$-S+Qfgl9@M9W#a#%92r0)T!v?r!iJZCU?!6>;oCTG`G4l-n(1Ik@BfS zMOc|n`B6lcpQF>)u<9xEY~7Mh>k}AML^8$c4o*uFteR-BZOw(xcIw);HDPyFTJNo; zPjb$2d#$U}1-T;a@oHD3-FfSZw4dCh{YqzL+HY}Iru`OYWktF~uSolu(2BGvSg|~v zw&iIHXL;Jf`2%iCh8nMF>S?3V;g7ZMt&L2)kBCu;-zWPvN4C*O`lLo8?qeH;ET8k~ znLMOAc5x4N+)8(>30A;IGbmN**4`ZRvX*yegrCE;8PK#XYFWav@u$$@2S(#v@xQ zHD0Oj8yb(w36F0{Cwb%W$N$NAj|0fG6ItGWP2+to4e#?B?+a;oUxaRmlJTAZz++d^ z$@F~+J}U1OfT|=bRepmSFNB1flkj$Eyh`xsT|+vV->vXaBA$hjkgcH z(n)xaKpE+iZVWuBgZ$(@*+2$>-GWGasP>9`x=7wfG=0Qt^rnb1E=n`qL(H8A$|q}A z_X&M6-su`o>cgY3Egz-eQJ<489j_NWwZEm~odB<1D#JA$?;Y^gIpEd7_{2%P0}gr5 zI^?|rUY&#VtwQ5-!W#h3Nq)cMkQahYkdt_~IOL6i=cJrp1J6l5!dcGrwL0XDf#)Q@ zuczT1Ktq&$h^jT5&DaV2h;76@wSN!(s9&{%hpJDyS767ArpmvWrM65w!XMCh6AF*w zk-U11_ol+5zAAYuG~Qd_RYAU3a3rrtz3J<2eN#4gb-hje` z`B##+U*iocJW8jG_fCy>RN;{wn&e^X#8!Tz3J)gANnWkS8v{?43#vNFTdDC*fM>#w z$`7W~NnQ!=)p|=P`pBM6rcdWhC_I`|Ovigm;mw(XhbjAHJ_@JcqG3b+ln4Fd4x$@(T|B$gFi+4 zJ*$i_+3#Jl-@9bLcgcS5J+j~9gG>v3*cLKE?vN+s4f#TT>|dM_3WhR6S)uGuPH0*v zHSkA{!z%M>a-28`&J$6lsgJM7Bge z82M17G4kQa*2uRb$083${wy*#^y$cB^mA-;&(aHkaAd3VWr6AahHNYB*rQ>uhJ70L zYdE0c3=Ic0oT=d~4QFdON5j)JoU7qH4d-jPK*Q5DJVV1XHGG+dLmHl?;n^CVqv1jg z&(-ie4bRuGso^3G7i+jg!=)Ntpy7oYUZml$hRZY@(eULOUaa9I8eXd5Wg0HmaD|4K zYj}l*S8DhQ4PU9@t2A7x;j1-#jfSt)@G1?zPs7(~_<9XjX}DU$H5#tfaGi!%YdEUm zH5#thaD#@|YWM~XuhZ~)4d1BYn>4&Z!#8VqqlPzWc(aCY(eSMre!qrq)9?p0e7lA} zsNpRd{*Z=0tl_O1Zq#s-hMP6qqTyBzw`q8rhPP`trr~xC-=X0qY=v#;Cm_3V@lSF__b+`%5P;oI0pZMcdJ*l+>svEdK0Z8p4{ zeZYq2vU(dXVprPmJhs?|3t6EJ&u7zYcprl~p;BJ^*}seRDyzKiW^dZ?0rr{=-^9La z!vS{MhVNznj}4cz&)9G_J7&WR*%2FF!4BB)Qr2U`%h+}s-oS3N;R@DZ!^_z!8(zzn z+OV6=w_y*=qktXHgptva4;liCu2PmhEgR{hL^xO}?4I{FghceDc_D=myTh_pqPX@F4rX z4PVB-Wy1&AS8Vt$_IVqQu*YmT%sytrv)Da0T*mrrxSz#rxP^VthCjsC+wf5G{9*FW zGg|pMyQ%!`VT)}1y==A(U&AtOID@?_CT}f$m-D^nQ~G8n&nvd%YuFEL{66;gHax({ zh9VXI4n{T)Dcr!Gu;H1>{g5pEA7&#q`8u}ShD}EMWTfI z?!{rnSDCbpxA3)Wo-O=pMr(wr@K-UibxGkUKQ}goYuKBXShP2Pa<2|c|J8gyo)o{9 zeci@i#ZKAq`;zA~Tj7_mM{V+z>|-_@V+U>czNB4+6+XoGvn7g!4<+~Nuy6^(h{K(Q zZ(%S`R`4_ivt=s+FTUz3ZsHrCfHt$jH z`xVyaK9$v{D%jksgi%>>HL07GOl;oP6jQ>q_NW?K+By_jvvS{*y5H2-)S{qXCE3`a zUX`e{?z?JZ*k(x<(57xBwVTvXwv=z`QfXbbh?S&nYTu>At5ytl$ycg&laiv1y?tsK zZR}O5Y-5j7VjI==uu)0R#(2|?RJ0r0)G%r#ZEUimRG1Cj?VU>UHpG>dw;`^E+R&vm zhz%Y6JuOOXgjF>i{i>dhejB&R*4Q_!P+IYZD3$CRTU*rlZd63;)e2j` zO-1X}5?;5XYkNxJx(-#}x+bMfHmLVq$xhnP*4CB^-=G#%LzAkk9%o3T`gVP{hEh7} zyOk2H?^ZR|x3?;d14t995wy2%RP_M1cgjYOkQ>{SdIa8JC$H{S$u*t!Xlw3N+8YAb z+^Nc&RrVTNiLUABR9ZezD%)#1l(w=4!=I9wHBE5^Mb$35x_9{%SEjVA?yV>y)lpr&MNLPp^`jx~^2{x^}ga>RQ!6%`HlnYi)H~tMF>o4qU5t;M%y7`C7HZ)pkI& zGDM{kgu9-$?z*;~Wb>?H#Q>%XVGJDkfU@GW=O~2RKrLzTsd<))JLEm;koTBF-k3w)6ApP# zI^=!UA@8_D-sc?hzTlAeC5OBd4tXaX@}73c`zwdMXB_gr>X7%WL*Cyw@`;#{@Wq% z_YQgVagmeyrF97>JdZ=3&mk}1kQa2w%W}xeamdSc$jf)go9>V|(;+Y9kT=^QkJhi8 zw1asLd8R{Nu|r;|L*7D%ys$%F#37H?1D%xLQir^9hrHzuc`F_AXr0qZJ}MpZu5rj) z<&bxsLtd3bUX4RuokL#KA&=IVos{!hhrD$Tc{e)bZE(oj=#aPBA@5d)yxSb|Zg{IR);*YYjD!8Vh(wCIOKIWvzc8c@H||J>-!0Nr${qhrEX!@*Z`_ zd(0tk%pvayhrA~p@;;k}SAscGbzD3SUKOTyKLYM(#~~`*sujrIYil zG&3wrO1S7MeE6G7AM*+)d2|IYF8$Y-lYb-EvTgfT{@s%JNbYRsDXb_L$0?X+|3>b0 zD_zNN zTH7vA*{+@?Ejzl~mi6pf*4NwKaq+b6>e;qzds|mqcl(7FosvXSn#_0I`kU%*S+{y? zL*4t(zdNz>TYK~F-nOkRv8L`G_%wI7w{6?n+TOIiYe!FSdkgttX}1?C>NPJ)UD`*P z7L2j<9X{=$a2cEDc_!2Cr}NLx=Dw>C=-aVx2yFe9xS7QCdq(^6N=(DNn|U?tOP=LN zzj1EtOz}0L&%yx>XJ|NR+vA38#~Va=iZ9RbvRZ*DeR(jnlzX92`tl49yF$npWWLm9nXLw0=7okNUbyD}|?Z*(xNM zo}a0UQW$y~Ex{idStK34FQNPr2e+I@Smy;49?41HWIXzQMe3t?((ytHPu)vLe=jh> z`vCMvC)s$`oE}=hmjyyX4LpXWu)c@~VpEbRL`O z;Jx5DZC0e5v$l#|jdQiEv(a44oA8>$aigB?wN5qTT=woMe{}G~jA%|Yho7D1Vc7|s z?iJs*bJ5Pv?3|cuop$f8FN#{>yg2inLPBrU$3wW7FX4e^cYW4QUH9M#X0oGM(YeuC z!@-ALqZISDLKdEz@b~|}HU9D9=s=XKw@z70bJ)sN_A-yx|Np_?YKm zlCZFEylgmNN|c3?@;rQ?@VQx+4m|?3Gnb{3FH+rM*E((Sy++}@_xLQLcJY>s3f61o46^QlIz0CJ=AIteg zqI_?l``>%sQgon6|4F?+w{|X*L(!#o=S%O-m)@N(Z7_3@->a$KTGo>pucI@%fY zeDY)_H83{Jbtvtzy5KIOx?u0QlrwRq8^VpPeM8^AV8Pz%%o?=H$y`{zutG?4TniLT zZ%M_#RC|_lF}vL0a_UuuI%c%uf&aKHk8uoHNm8|8wn%u|bRD+iDX>vc8Q?Im~ zUy}#8Jk{d@nmj|pLC&XMX}O>#&*XCIX_m{>VwV-`!D4s-i=N>cYuHU$No2Y|Mu9*nKvf&khJo^_OQ%W0|Nw zijw*eosIRsQ67Y;&(PUeKNFbx2%U}f1A%E|$j6-RHwC6Xk&ijvzZ97I0G*9BCNQ;m zIveXF0#p2SHWrhpz@{gRPGdC6|R(y0AYlq`lWDGj}(sUK{}|NPl$xx0L30x*H63O`yfr|u2WpaM0 zz=)LN1p;GIl4ES9%)>7g7?sZPGJ#QP9OEC(HwCT`c)q~P1x6up{tAIhkSV8Y4{gnT z+qZ7(Zt9fBKecvNx89|k^Tcs&v*J@nj7_~e;^Lquft$K}Z60mCH>R{&oVMPEE}T4d zS5t?^r1O_Fui98sS65rd`X+lcZN1g4t=*e<$7On@=IT~_A>U{7#rM)X?rNjNw%L+~ z<6pM5Z&%~1?PzQ2wun7!X=*8^v$L%WK_@$+YVw1ou&zQUKJicfwsy94QUX-m65q}6 z_5bFko;z>p>ezuJzyw++?s2}&rnatD@=l)AQ`Z@7?`o}X<+-kDZK{QmR;mOZ*Eyap zmF{GvOD8zBl~z=|=WAgbSKnM&YWoDWeJQU?-oeDZ=x*&xt;S7VEqPDfOajrxQZU)Q zQeM1krJ&NSQl7~!rFvQ2N%+{hlJFDVNFrMoy2wW;sW0i(G^UGhYB7SI{hQj5_^OuH z!}(XWe%zeHH??6rP|!1l4}aunOg8C8IQmT_H&f$nh99L>I?4MzJXC%61LG$n=_Kz> z_^7-Sz{5!ve!s;1xW=PBW$5=;I;rm&c&Pd|0MPHPbdvWOc&I$uPPy&WE^zT@E0@40l6N6!W-?{)B~?xd4Esw0&b z!ZU20B;hJ~w3iR@q}u|Xl#!pjUk_3M7-H@kaWh#t*J=8Qce_^v!bQe~$B*PaNxur^ zlsD{x}dXs90E_Rk97K8aLCKabQbTe4tbA( z=OleU25&>MR8n=S*YENy>+D!bmHAzT8`)P#c0YI%Xmr=$o}Q1X{pI41&M`w3BwYs< zhiN>ZXKB(!JZhgb1gg9t@J#pX{>eG4ORCu^e z%ln?fQ_sWE^}Vj}rca^oZG|^u3Z4g%$#S9hMp++vywerlROj%NDm-cr>GZ8scx0E6 zj#sDf@QRt1hsAbn=$kgj;&z`cqWa zZpB0L=nC(+q;5r_P4;_aE!=MHXxnbtk(|x8yrR5fWw}Eek}cK`YSOm6o?&miQ)HRo zZE)8I8tIPya$yA`e|tUk-Ub#Mu5pdKOsvY&A9p0D`@Du1_Or;m@!)<}WKO~pnU#3! zRQ64)cOTmQ&AIoUc!%4g1lGEv&+NN-KQ;<{$auhg^yb64ha=o_0@~wbsUWplx(Vf; z3N(CsKP&T(yP^ko2P#hQW)UM{rB0@i*cm+jY#x6Q@dpyQr`*La^qn3K+~eX_3b{$` zxu^W~&+T`WWsJMSNGAB}QQ<_a{4yf&MGP ztHu}AvjxxXcb6FnFaC^)q6KWCcmZ4JT4W$SIBfxGng^LVK4;>`{Wx(U@vXku6TYas zEN8sp2!q^bmiNryu}_D+%JllG*kH_z4zJ0tXZ_`UzwLALaDl|%^|2+ML{9x@;+FiK zulb{1 z_PfH_2~RjP;paM8Q7rmgytrsE?x`P)#gHZ{qW~`%OY2*w^6KwBae9C7&oUol;m~-_ zy6or#Zz1mJ*uLPpNVI7``;_aG)JB>Pn};d94=uznC;F_q*!+WpqI|Gr(^1NPA}Gz zxFz&*Cmh+QL=;T3H;aHNdds<(U2brBO0}WM-5U0AJ`G8h^JsFfhJBn*!;R&9n%vLj zG?ZA*ugL>kZb~s`q3r3;(Bv7KJjms#W);-rnVLLPlV@@H@nrm2nmn7!Q(Y)qljm?b zb#u$*X!2=XPF=@x(=>T5ms3};TrMjV^-JB<4SSH80$cCc(^*ide{K(>ypMBx7#nu8 z@7pl!VQkpTPS`N)DQwu!9<$|avJcpBCR<~}S?mfM&St9pl^fOp1vdFK z_AZV8!nrX!LiQag_p5h@1g0UA>}PfZ(>>K0;VvPk@^isDfz}YDbKz^qYiu~gOdFoX zd^S9r{elz;NA@x=+HfIz#)jvz$82~W8?xc~><$|?8Lh!c=VCbT#fFPnp$(TXw++u= zKa+uRbzv1LVZ$?77TOO5p)rHosK90%B-4QH?pfvFFZJajp`W>X+0j`Aa)9?-rw`lkl4X@U4rH0EDoQL>Q zW2F^;ktR=#^<-aV)t#i!H>miZ1wUxD|6rpvpBUUC>~Bn~Zy3$OP6t;i7X$wIp9OEV z)((RBpp5F9$c8wV5Qf%!CE&V`yn3xdaJyRwIW|o%ER3#%6*e4kDEog zA(NC2qgL4IED#utW+nMA68K7i!vbF=aGAi!Bk5V%U<#R69ge7V3i0v8KhCvXWed7gGj%0AsoyW2X1 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 z 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≫4#*kLWP?ieO@X|9hEzl%Co!?L+;dVkE1$3j-mQ^9JMSf2KjC0 zU?8tmbF9Y9B=SgVtke>n8F8D6%r zD!%97pvcP02^0qKoFBX>Fe5NCFe@;Zo81eT_7#C_925ocCtb%)m&ni3C-B~mM+?sd z_0fKZcQwNKGtTg?cX*!x0gt4fE-Wg@S07btTMX!`zUznQ;U8q-L3A9(5H@2|jXO+y}s z=5%K8m^@i;6PUZo@NGx)f;c-sUmRB<~$>V&A;r*?{8wStROP#q?EklmOLD$$AuUz74MRhcr~F-sn% z%2M)-eND>46kJN4v9C#9bON5SuSs6n1UzG3lf3c?c*edad2Fjx?MC~WroU87z-zO3 z^C#eSTD%1l@ZuJa_uN$Z8?|_q6Yw6ic#9_B9k+OkC*Ym5c$_jc`D5Sa_-fo~@ciGk hR1B|WoA-Hix|QQRUtyReFK*<$h(_gjU>xJ={y*u(Lk|D| literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 0000000000000000000000000000000000000000..315783eb7492db2eb1efdac0a80c5188dd54b99a GIT binary patch literal 24540 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..95fbae95fe1f2464a8dece97575125c7417307dc GIT binary patch literal 52210 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 0000000000000000000000000000000000000000..ded76db7c342579da9e14d83dac40a1b4e7c4b9e GIT binary patch literal 8668 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 AumAu6 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..750ca8fec9058f550ad339de9648181216d63b3e GIT binary patch literal 270784 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a new file mode 100644 index 0000000000000000000000000000000000000000..72d535b26a743c1e9318eae8a60102a3a7714282 GIT binary patch literal 48542 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 F{{&T+-f#c_ literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..444a46fa9b035d0ef408d6e576f886860a63226c GIT binary patch literal 93298 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 Py@(?pelLY1U;h69i((Q; literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 0000000000000000000000000000000000000000..bb4be319bec3288d3918274a822b41b718635e7f GIT binary patch literal 17896 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Π zC+J!oR#HB|{Thh7P*ygKdl63+6o z?TYdp#t%&-V&xeIy6$Ko!l0XtNGul_)BwrvW&CU%;!zz2oed{$onHg-4Cq1#BtLdW zI`RwG)Irr>x8B}(@PQhLsnfcB-@#{~^?>s<5W^^Wk1aL+-@fnQIuuZ}K2LS7lOof9 zsD@~CaMtuD2d7$KTMXViMte!!)Q1rsZ6C2`G4Ota#}JODVO)ybcVIEzZ*UBVZ7<~a zk_`mp{RSrhb3MNlk=Mn4gs=%t_|Ls(#vdf|y5YZ%2~YLqKUM62EeXv(21g4I{L<7U z2ggfE_MuyP;#5j0{JGJ

* zS85OR%cWl5Jgv?HeWS?Rryje%9G5YB`_yCibm!Zx+`jGW_8fMft%%*!ZG(OL)v?1n zR!`ECL)&2og5%?A?N(`n$|hwzm(<{_@>O-TA>)DW<(ryZ)QMysZ9HrZ_XxvCVflHj z$>#G~lk-}W^IDUCSgi?$!O8gPsovj9WfCLAIXhlFhAZEcag-&zyB8-;SALy;=VVl0 zT^*T)n|&)&H>pr+)$A%-X9PIafzvnsY7FWO{PX|CS)23%;7q5xYJuo1OV1wi5SNEQ z^UF18zaRl+LIFJlXBeEO$oeAm5fUGtJ~F9>I)F10dh*Ma(~nF-{1Ht7K0&}jEH6olvp)wEzA7vsw z=U1rwGcxom+Z`O*QFwNve*}3xokE2*Y4h?q&~b8Zos<`lBK*it$_tQmZrND6%M2ZW zxSxQ|hS9@5&%-nMN&Nu62|CwV*>8qtcj)-xXXB6$`Gxr4b9VrD>4K;r%ItUh;ej6P zxhp`&dZN5+gLEvnNAPp$7J#k_exzgF(~-`f?&rIi?ysD5u`5noJbwSxO@2iX-sZy& z5Apa_fUd-(=K_DZ+~x3-p%ujO_;2P8lL7M^vWqrcz%7#=RajiAeeANg4&GvlSLEvQ*mvmtsFrl%R27T-3d zpdf!bg5W;bHsy|4NWswzRkI17*9=La@DB}Ct_6&C>{FdO0EV+8{}eSHHu%$krw~5D;9moriqX%;e;xSu&!``P(!n|GmO3~!S=7u}$D2B1weKnFCWLRb z1fZ{pp}#N$zBMMipV|#P)ALJF_j=Flhy&zA%pA`z#X0ek;e*r{5XRHuwSz&9 z_ssAM)hoa&Jiiq6UGJIUL)0&T|H|`AQNQ(`89q$?75HyFzZ8|s9%&qJ>Kp`|r@w2L zqDI7oUnHkqrg?rTs>pjL|7=wbe1hkfq85113?Hd(2Hx!XrAU3b_)3J`>V$9bo*93% z)R!C1Q!yX&Xj0T&-ZSYhRu2IGuIGoFSG{M3kCmG)-}n4d)EB&GhL2ZY13m}s&6bCI zN@fCdcswQZpcBsa=i=`m{81s`6XEmh+aB$Y{9K$jV=i>U`vG6#;6uH% zD1W~2cf)ye=5HPPf*ATKs)YQ!iIGm<#aR~DJK>9gFLm&xz^fd*7Pxf@I8%oG%?)ot zc%hvgA-~&V=%=Z@z+Z8~KN1r@L&|ms-z4Hv)RQscm#QxV&-30y&@9JZFjR~Kt zJ_`ItPB`Up@q-BOaKax4{&NRE62ou4$mfPXkMMuOWJ0?X^>PgTRq6-8UvR?Tj0wM5 zodW)*6aHT@;fqx-wB3{Vu(AC6du^HZca6#ho?&N{Xs_d9!mm>^fLA%;r7__*sH=gm zbi!|p3BO6z0e{d5XZg8!1HvD6!fye7(7|^Cf7HS60e;BA9{~P@gMSkEVFy11{AmY& z3iz`Q{v7ZxJNQ?DTSo&?${Te!l{qH7mwGz}*B#~GO&q?@-*>|K?R|mQ_q8r!gb$zS z!>{z=bA0%nwf<9#Ma^R=X-YtFu@M_RA8OE;z{tNWa z=M26X`0K!J_-^1|0zTA)-w*tg;6KXXp9ap8#~(HL5#YZD&etIMKM$O95_UP_uLDm< zV2;6m37jWw&olU6fo}so&ftA9_RBld;5op5iswrVUI6^Fptt2wX5JMu;m4J*9vLS5A>dPh4>b7Wz(0d`!ea*i z67Xv<=6uZH-v<64z*idlT&?WkyK1TZwmRLy-r9n)4K*{Xo2nPpRyQ`*u3L^PjS&Z) zxKvmB*Bg(rriQg;ym;5(3@xi$5#wbp6pj+{=3)}+IP2Hf)->^wV zcyO{e#S0kOh6RH{!aKRwSNG?)Xo& zB6)@B9Z_CjqwsKYH;PS*<>~rcX?bY5>u-hRt>do0$3M2%i>yd2e}}%vOBY#?JbL9n zCAOT4JV|29xyVXV7@MOaD~VS@g|S(fW<_F6IU-H7A{EAFVVV`dtHDAmGpo$y;E5EQ zg=wBhv00dIC7BwVh3QrjR;a^&x|L*VY>uYebf?DVXu3^zYHW^Xcyg4D)K&t9b=xK(CKEab6#C!Lisom>#=DoP+7@CG$(F8`t0h_BD*n=WEvEt^$qK zt*dQV%)>O0yaa2H4H5tO^%$bdmUEy+5;{3NFKS*~w`zU$+Pd|t7OrWs!+6=c6^m+D zW4KolNY3N)2{z!r_YyE3GRRZPCAE!BhRVL8G|9}`25ZJ)JYrrj+ONE!VMBw%!kTyJ zP}jmk`-riJe)K9~Ekq1guPYBC)0g6zn0A=ZwyYsSM59v#{REo677qU`Q zQyYjN6Mb37zUj~JEjn){bKXkkyp_y9td$JL$;tT1ve)0s zNXC`noY}~@OiyDX^ZTQB9`2lt@7>Y7zpQ_L;NrAqHEw8o@0{d^LUIgB(t{mUo3h62 z_-vCLc5+ejLzS(qr73TOE0S6kVJ}evPO1M{m{-jY=m?A%SlDZu8vE0>;22zXkJETB z$tS<>wIu+*Ov2jRR4C=}$zvH$!z4%DcdHto)OO$2kEaA*AJBSt>BzQ$c>~m#DOt^G zLQ>oPw?7L1`}gcEy|67q<>qB=qi@zN^j+Gzx3o8WFUzYa7`T=G{hJTK|BXF+N)^(` z_;O@c-%= z)m}96`6b0zIqIK3XJ=YVLe8GZr5%BsO!Z*iD?;(xwji(*d3WMyHO6?mEg`2hRID;H zKW%(|+?JU0nD{(zd``3_<-909KQ%tzY)j60Q+)nvd|qfv$!Q6-fKTT<@_o*f1@0=S z3LdqG6a+_ zv@44DNMshO(Vy9zD)%E)g;j2_jjgPgXMZ11ek*$=MN^6F$%!Y}vDKN6VgjUT8_XC%C;= z_#0@i35V6OQ%83m?wpr8y8hz8=W)WqQk6Tntt#BoTvyTS*4EOD_E7kESndBpgnoG~ z2lpLr34~6z=zbA6q#kOWby?xM5kG5BLVLD{{OCI?RBosZmn7y7&Pj`O&KWiGwWV_- z{M$JmZEd9LxG8JY#jjnHh*qI;UXJvsAD1?#eqVh-+ROD&+T!MlBsp5>)Ul-~r&CA! zKz*fm=wZjblu&lKvQ=HQy)^hkF=D$YPo?G!%n6#b$|SAn7r%AQsFB}W+Bq3%UaUH9 z&-&hyG?a+Sc_EU76ie$rwQmQ0{nK8k&j}xB4L0y^|FqJE?G3#Wd-Z+3Av^qy)<7fw z_DU;hoTB>XgewBAS~j$VaG*7WbSc3pn9*_Rap|ef&fg#1e)vLI-`G8cC2f;bYSExj zUL;(hwnidpp~DdsIvG(DLUHqQa9>{i!F?(%QXdMpv>ukfD(z%_enV=a>Kkc5t+XDN zzbY-cBd?HBQLfZc za<}TJFKTB_{XHl*T}P)ciOWz9)}6%os*j7BuBzHnr*_n-+zIWu&2`Paf)$xhW-*6P z9ce9{{n|4}4re`E+NV8S(ST94I=s6%(DKN>?JdEN?AneRK#MKzxU01A4V9fIJ)xso z|~n~uH5hji?GWN!=78PSFR z&+3BrKC*YaNu#5VF;u9dx>rX+s3^N?$w>97ecAiaH(MFPmVOewD^ablDC{U7nv42x zIl_<>HKFavBjeP;y6U|pnW?z{&h+ZN#Y3ugcHC1uqT|j>p(d_ktJ%jGReQ7dwwCs5 zKWNfCSlwt^Mzp_$D|FruqTKqlb=<=nQmVqon^kUdd-dMX-r9Rghkm5=xi_ABhxPmW zqjw!vV=|hrM(Gx3)>X`I*`F0?E^X$mDXS~`wX`_cy*pg&>g~jen^iCs@lv;kD_ZW> zxl--_+|fC|b9QcK;{KhxL%7TRfsSxRN$Yf}g@paMZzfl@-`$am(LXgisEP^(G^_C! zv?YWC4}ThOo3il7o4f0w)$Wu0+nTp4;lbmrkzK*iwCue2h^rT0CB-uF_A4h$e`-`m3$|gF7-09LX4dS7}n4!hv@>&J!Jj$4+Zc9H-ho z)p6*SU*6IySdzK>NbW7Gal=tdX3G&h8&R)4*wJ-95=5-M9Z0@?cSqvz<@em3*)n=v z@SjT)U%fiB`cBsPwvGg}KG)x zAByo^+K~+3#Bqybe6Q|E89N@nv)i@I#gJ6bqGqDjqq8erx(T^6+U@)CgKKYOM__DL zdvM&)ADa1v8f03v%FSpCgufN8tEk6(p%n9(w3Z$F_Ot|YUT$G-!xaZ-C3cKcGfa-y zP9aTe|KtOGc4yAZZ)pzXaz_012+iLEt(|kylRw_))y#PXcQju-KB@iQ$nn;U78PoX z1dip754P`bCfC3*zRUAuCWV%>dqCi0Ll3AH%nEm!wlf_gx5^#WK4*8$J^QonC>`{} zx9-VQ{V_hj)T}1%b8^=7%d9(SlWWM#t>%!RiB9IXhLTYNyWe z0Ql+rkS2)lifBvMZ-JnpNI0CwyTWF7R&KBAtSqVStPCvgtV|4Pxnbasoa#2oJYYqy zJu)ln=yr^BNo~QgS#3$LC5+8$8*q&D_*=Q7Rp)LuadlE_5A9xMIl`X!megZsAMb2{qc%%bd)rGc>+1;%Ey$E(qkIsJpt zIvs#{FYgAUl-YR65GKlB-VhergLy9Ix*3=oGo*8N^@!a^_Nc2f*~9r=Lf?#IUpa~u z+R;KW4h&3Fe%olZbSiF9%Q-Oet)*)GG#qO= zT0J=R6~Xe_g1}Bpy>sMEilMn}3E8c9{zYcd6yl+_#O%i$JhLq+`$Y%OXiLt1)4@~Q zQnD8ZZR|js8lBuxH1bzVit``eRktG{d+bIvF|jQdZ=Mj|JmD(lKusLhW)I!Gpe?0^ z$8J83Q5s|V?&n*0uUaUxWh*HU?Mvw()TJhILy3nEOKItLqHWb~RZdW+aQ;zTyKBtc9 zbWfqZq_*&mH~an4IXgShYnUE`i!)31RSqfHH4bKa#ioUkBkp>O>x#|1l5Lt}ZK=VN zaMxO1g31f>KafD8>|N>IWe1Di)1pJW?r(8@QW@7dcT`{HM&5X0P;LUg)#S-L0VGjB zd3Zu7sPunCh#m?8BuU2x1O1;~p#($hMM;_-RPKLJCHtsA8$WJBMo{Vh2=CoBmM5C` z06P5R-&A3mn3=$nO}yN|I{+~)Rgx|dHyNZEfZc&447worXjVyHBKjdV&`Ttml*kdy zLM~cEcefkKwja}awgQ$6*s?R}&cs~_cga0qO%&(o)ccI z#KMLbQe8tFiPAz@J!vkrJD?9$<)!n>=s!uRD#F9sa$4PEZpJ}jt)@Q;B|-=x>j^)v z)D}YUV==QZX_dllS}lYh)>|cLR65$8Ygbt$0C5Hb(2+J2#fzTt0;`xO# z+Mqm+6GweNPl&>Nfe`P`mkGi5+k~KNBLv-RgplI|A)=WW8fm3oJ8fl}`h!eZ$pA?oY*gb@BcLd5$sA?W`?i2C{~;XL5wut0kY_9*_)j1N z{bWLvi&%vtzf*}r{^^8}=Tbt*dj%onEg}3k+AAUCDJQ(qSdAyadY<@F6d_>>te*%` zX^RM}a491pG_{on_;ALCp?`kIQDz`7bHHIbT{XJpnzD+S{Kz`k~>3YKy9|t{Q z>dF}srg-(6I*%BZ_>SlaOLt1loj2%~yr!K>kKmo=lJ*9}y1r+u&m?V=VcFO-mhP)= zp%j2Kut*EoWEgMk8RNLEsoC(_+%sNo)l;U}s^4muZb1NE_~-1Lltl1KAFJ;ZNPAE# ziPH9A3$pR=AS}{bx=ELV$|mH;IN=-v`O%hsso8qHM{lua_hP4?^8hXeZqu4O^E!xU|<^{>5EVhq`w3(y#mSu;t$~CpAdXo2oZ0efo~In{!b=6 zHA(X+2BiN?;^4D@IQVc2G3DUa;ow7h%W&`$__${Hy-K}Ei1P0+us;ST=6?d=b5LFo zLXHm+g07hm>Fgo|T^1A%X;6Z2yIcAav^>IVaYhOKpN3L_@Gz8WseoUE5`wT7KHdot z?`6U#kUk;GKN(>RA4SOW1ti}O5q?OiP4tI6j}bzS7YRZ4eZq%P|A3@_j}Y{kY4Arr ziU|8CRZNJo=T>5tOA~R#`xIdMD%2Mt;=M|L$n-8D;=fOr4rM5QY3P3A2;nyeknxrf zBHjx6BOf~mA=d+hccVQJBA>^Ne;eV)^%i8t{{wKs!Qh?td6Xw0@dCm+D0S$M{I(K8 zuKk24|04!|88H18rT&d@8`>G+ZBU93-i~r6Y=II4Fm12iN}Rr3ZxLoWyib3$sYH}f z`VJ`52=72X0n?sEe=+`-8UO3)k8=5t@n3EH@2CHh&^Hm@kMblu3ONZs0(p%8%YaPh zN5=nM$|C@wQLfJ?N{_hcjKKTOBBY$atq|YKm zyBR}>@GA(>o)-X;ZV_?N-AIUX2j+u`xmze z2alk>3DKt>B}8B0R^VU?%7YN)&8@$L+|o;^&wmOUhjXCd5`(zf3qOqs!V{wOgQh^B zb{L*eX`LG(%CkqdADO9a$75 zJBk$=QYc#q$4gS8Oz%fLk6Sk33e2KGp;@Cvi2P+}Gp z%0x6d;aMhk73QS&S^7OeWwm_u&NGV+3q)j566cWLB7HY6FEAcO9OKYv!s}4)gf~i7 zL#Oo#NqP(0!e4~D8 zQt3FAI9{G83RyXrMu`52B9YUrXAq))UP9Ocr7|Jf<7I?sZzw8RVL(yI3Io1f%?bk_ zq7FqK*9G94;DnIwq=VZ>*1NPJ<1q>m55tpj?>2sDUR}=p;*kVzNn{d zbgU=JD}5M{<@N}EF5NSr%R_yTE*(EQ()rVU8-2Q5LSz5<(;bh7Z_~BK9gp9opqm@Z zN-#gaT@F7PV?Y&;-vgkNzT)HQ=l80^Z-AkV$M4N<@*9DUWb zqYgiLN1R5!r@P7Tq{A=!4DxZnnQg*d;IEI_ptI#S@(ld02VHmi+b0};qtC$a$!_xd zox|_qGw=)I1%}sg7w6A!CFpE^0E|>khvg9e$I~z;89^7MgGu_{;A(ho8(bKpaoLm%Az708BJ&elf&} zi^p#y=(;0cqr(qf<+S|n=qA6{9Db<6)AD<(oBXC=LS^%dD5vFD2DU|*M=}!YPJf#ZI-6gaBc6ue&7kW}exG#sm6(jglkXVl zx-;JY+2L1q27bN3%%*3^1o+Eu4(M!t?RXhaz8gWuIh^15`90?Fv*jI+-!t8m?>`-W zcKnFPF9nqk(k{*~Um56Ze(n4z9>2w)v*qhD_49kc;Wyt9#^d)G=xq6(iQlgses(;M z$M65^rhHf6gU9Cg>NCi<0CcuI&LrPM4nNyJS@yB>@`P~P)lZeRgnPrBE{N$Y5xHlk83x)DR zboy^mVWD8t3JMWI_rd4fP8%#KB^9a=9&%xf2no)gb1Q|yKRoA_jX7GO`UWJ_yHpg< zo!f50S#iWa0*D6Xg+GC3PB6BLUyAw?;J@HUg$(Jx31}V9p>4N_z+`Q;X#98%?GK%B zodf40=88$LKDJk{4eQq{#V;l0$17(7i~?ch{$F8ASU zefTXte2)+Rm=FI9@ZHGIDDdXFc87uI1E)fg__M%i5z4fQzi8s;0_Qn;F9W|A;b|uP zyTCc1vVV~NUEmxn=NSB4pK~W;>*)`=tC?B5vU=m%rkHc=jGvrkXV12C{hagdaMBV^ zSn^KL0V*fZNvwbDljr34D;_ncAMANr`Sv`me0!c2cIX-!d!AN7?4e&gQ0<%^oi(#| z)1nPH(@PSSl*0+na5mPw=xJJbv}ZwijBwsXS&t98I)D7p`QwkyAAfZI z_@jULvZDoE4GtXhO}^a>|5CQhgq2eiLU*+@1OHBcq2Wj!*jG*yh!8=ERd( zszYV(K9V;4zS80CIXuy9b|P2mS; zC3TF%ngZUG`B_N_HKJ3(zzg9aSG>yJc097^6NCL z2W$j2_nqQvG`p|tVO6<9+IT8W0A~)&j|9!>Gkxo)q|L3@`&!emBld+za(1A;v>rFb z*S{e5#7D5(T4giMpxJjFs4BtEYwo^&zA8|ycVGvyM`6!>XC?M!gEDZeb8cd8uzg6? z8@PV$hN_{sd<}EW)4GZiw_7{!pY>{~tt#*7r-hq5i>omG=GmOsSW^F-A_Z zTQJRbO{KT0CUEB^!h+sb)u7(NDSmcSrrF#H5X9Wr;f0-=oH=)QUyofvr9hl`=MknG zn>bFn=>VAsKMUo{uaBOAqrvDU*bB_wN_^IG7LRGW-dhR1^f2O+VV*)bz?eIL$!Oxx z(~lt>WXu*Ytp}-0?I{OsDe?)SO2+DqAfoEVk}bT%w&GGkED;nF!oP$NiIx)Lvs!8j z%tS>6{-R1l`l2!&Zd5s7zKHY}8`U;GU#};Q#Q)~9>}$#rW%f7og8qzO)0)ELp_%I3(t`iR?pHpF$##d zNWUkX-BRGUqQhC(W*WAj>j_&Fn&;SGqE_F?ipV+S>=}-WVTe8?4AH!MBB9&GQPsMO zk1)K@1$x5E%`HFZqqzka5e|LmoZ8W%|EM&K3aE9Jevv-DpKyo4_ZWDLCPli%kYes~lYkKc0$oMpmYupfw9E&+5PE1&csgvaC84|L@& zBlGO%cdf(Ew%2(4R)TI$H~1ZP_}SNFJbuSP*PZ;PAd@z~7=FaX<98wGO1dH6^$tG_ zW2fa8?k2y-9e#KLo|fMiLD!x3_eX~xhSk&ZOB&d{{8oU@mS48R?hbo^7}04_QQ|-@OltOer7GQ zv8lFU(uT=cVf>&wHwz1=<#Q#nJ8O|C@|IHGTI67g-s81M>XQA+U|cgWb6#cXvW4Y~ zmdsvMUNWg zmw-|D6CTEgWOWdK8CSbxb;v#fCg2F2F93eu^GjA=@!>B3|B(~^GM+me{8c>v+`-?# z^SciIruWSBGDJQ%{8UUhuCsJ-wsQF_Hh#Q5Y+$r-z^|7Y@8B5L^dTpPo_M7b&Ue67 z4$g2n#KfWJyziI5@hyt^QnI=ocsriiFNmM}Whv=qXIPk;Urh?%^%$~Hf)y0!>J!`w zGzyJdR#{>%Iq?=>3Kh;|))aOb#;(HHMVQ!YS-40OyW%pfOQ)LN#Yei?3^j8d)p;6CUxKqy}tVvNZ!LoM3ZBb5ZbtAn8nX*a3&GX{7wsv{ zc(t@OrS-Ye-meks_3HN4|H@gU?k!Dx<9KV@^v=rG(!sCU<&D9zyfFaF8}np&0cZ_TFs2zcKx=izk+MKOb)%+^-LX zce(4skg@2H7z##Dv;?k~E6kaix!~X3wT2LAt>e_P%V8e1<}i;Wqf4|p5kQ%J;oC=4 zEBO47&k^VZC7V#)%4a{mH8Yq1zHvBZqaKKALmv1jpS94)W)X*{e5N5@Pvm!sRHk)# zU=_stu8lR5bibu5K=jtxS1n?Tb2Iu0TAOCpO2y9g1F64Cod*;r8)vJV@s?9?56}EPu*t zMP*xf7(bVe=LS^4k8~&^aisI7y9socnQ#~Q)8)AWHeGZwaq;-^oB@`p-}(9VLg%pj z2DF>Q)_#0ye&Lkv>TG^0!*Wz-GmN75SZ9O#clF1o z|C_SQ2V@tI{{xB}+Yxo0oa$tUqhlrEplCUrmleJcKiY%u2aLL89ti3=+JAq{!`Se8 z^Wb5}rSKqFr(>q@fLqVe{`;%ID3f-6`}2NsD((pzjP&00o|)bNbqaWg=cna$@joN% z=T3M4nS0m4djbEAgZF3VjZ44~%KW(D*)id%zVb=cr`vk*d+F0_Jv>bdU8v%!aN z_2GB>aM!+^vko~G*6=64&-v(ix+|4+x8g_pWuDsl?|A0RllV`7zm8{&JA(fX_|vVvZ`0K8=#q3_%g(DwPVNN+p=^x*=AB1n7EOMUqcBWlef* zu(kEI{`s+{zPtfCR`JwT%`_waFab_J%~RR>m9FNAH`kv2uG+KEOW}5M=%u7k%>}W3 z+*$?;&3V-oZh)V>`Mm1tyz1(_>gpd}b=4?y*1xyrN=tFhFFMt1Pjl5N^*MvKE_Sq5 z2ZkItvMUQ0{FL@@AAsvDgX8+P=QY>EthYQf&=Hsj(_b-Vef)^l7D2a@Gep^EUO)78 z=#3(BWlZP%5!w3Em-X8R8e`i@qA}_ZZPaP5fE>N}np9(io70+BpM%R6=hQE6-Gg6$ zTr>Eo*0hFC(XZjn);;*auK{yYT%x5lSrJ?>1N~NGYC|e6A;m<;bC~tu%A*!sc@!8M zY}eOcdFHdxn?*deR2(mw%I1P$chyv`YKD_;ziI|kutIp#XiFR*rfBj7E?&?w$%hv# z3pj^EF>6CBc*=+7C}T*4uU*dZRkk@K44Q>3;`k%lDf|f$$A=q8#4u|NAv6^i6Xuvh zypUc`vL`YzJ{;$idH4nKMJ;)Pj6LDy78U2S{-Q!!!WLQW30qf0K8uJbJK=@m=m{@Q z$*toQd!~0PFA856qCC&3ij7Ru@!?wpn1)7x4e}}tl{AMiq(8pWA=V<`>G(qU5FzMS zFdUV?mJpTC0%iCs#L+lT5C>fcpr?X^+UH&3BlNW*Oh;P~dOA3?N$4M>O@bIKj1CUv zD9sfd(V|6Tno5WirTL;*{Ej(`=K}DQG)y4rPR1cb(xQK`LA3K*2!#aWQgFHq{Ft=M zuZaj17e43L#Wg_>_wU`%#Z^O))9K<^1~%Gz@%W7gU3cVLlYk?o@P5L|_`F#gJw;g;0bXLcTAkY06PcFYtg02{T75M0IzbwF9W{9!OMY%9ee?B>k=?`_R?K3;iX+}yFUCseR#5$SD6~9J`T2;iDa#;rTxNN*_MQhcENtt9|%pAKnUl4btI!f_8TYftMjqoMjPz3OKXK zHctFFad?y({59Z@sW;4?PJ4T{)_yUHS!?O%)7M%>Y^=VPCohO4VXQj1pul*?nh6#_H7wN7 z<~q9I0-GdMvR1vk3}%X&HsA8fkF{1TuoBU1(cv})BE_nNdt{49L&U|kO_eKf-owmw zi`PZUcs56Qb8U@A%h%U5Y>6~2f-)Bh;?j*POV+O4zzV6ZtzKTYY+dcTnzekjMA66= zMc;K16(PHos}w4-ta@$D;(U2p&cE{;S7}CgUf8gqW>L+ixwTsuLR&}Yaba~`L*4pS z71ecXYggFtg=?DRaUJD^sj(nU)eTLsg%lk&J#g?yQ(3sSX3b*IG}JY1VIHji`jyw# zHq@<@6iLWroN$UnFRI8*6zfHEOUEk?^Jrek*~yPan>I#}znOK7k_Yi?T4RbChPfq+ zLM00pSBA4!# z#&yd>6DO|UuxxWfb!6F!y6RQyH#9cY)ij1C)*^r&%NjREA`P{Tjh8R1&YPMy0e`0# z^6!i(@>~#_cvTp*o7Pq{#@f2&%W5{PUs<;*G;1l#VyCQPg@9&!pZwum3)q zQfu5iS!+zgHFbY;6?n|**4M1vxB?C6Z>&>~Ar_I&9W!*obHc2)X7ahpsBOH+@W!UP zwSTjC4!_NfD<`k2U5`QQZ!bb0TQBz$SJXx@`qr+msjF?gd|hMD?G<&;)}4KsZjnn$ z7R@SOvTT0d!pTdnx@un8?2^g_%P`7Kj-m3J2x@gQhgbQ&`g^IrV}v+o+V2>yr&WIQ zCizJ!R20YwWJhk1vm8Pv8@0;1SQOTIRTl_MR>Ruzc}hemHPSgd7(UQECz7*ePh|O) zmm{!%+mc#;aLerajxDYADLJ_+BagiDp2Z z;pq6hKu$2Sx}q{%xwT(?OLIm`L1;hDtzg`Q!%EJ#prk9qsYNMJbYCdk!`te&Y%fb_ zKeX*Bz|^+1P)8&obTDEKOdF4N&Rbof9hBhRRK93s(f2OPX_44e-Wee}eLV zv{t(G|ib`usZs?Vlkux@&mrt2yC>?$Z98#c|xlDx$ z$AmK=StvgoCWXqqu&raO%1v)Ocx!Ri!KTj2Ug63u$B(p@2HSgu`eX+>5<>~u??xVv zjD;l;W1KoRMdeK?P#IWtw?27C?>wBS1{VHeOQ`u!sd_aDMOYcu<&qI985XW69>Tbx z+lx~IuLrYnIY9R6imKb_mvlG}<;GGYma7Kly$~+BtzS!GcEauHrGd8KNKlV_ZF8{s zt6M%+s(vt3eKi~!^Ra7G&I_CFXfEA4wD`4@0k1>uW;M2VTVOR|YTLaj=_h(SWgIz{ zoc;W!$g%s7eroog-$^U|kG8bzKfZ$rI^47P9mh`_&5l7k8=MzFdg;Zh!}(!dhPVW% zO`*;84jn>SXg__HN*`6VE&KLBv879D>+8_u9|L2BwTfgM@!|UqUwftpLVzWB_qGG+ zawWaKV;z4<8L|etK-|0T?O`EjVXNzE_W7yg*X$=6i_$(3) z;h5;nD*OuMIUl0Y$~Pvuh$Knkvnq?>lgv>eP$xmPE#{9S33K$97S&Uui9;1Tkr4dz z2=NCjB~gB%@d%JDVy&;|^(mrR1K$M<&oHOC zUy7ao#32+lE)?cQLZovOAu_p?5Q$b3BK`_Oq*qG_CDuy9>H2F`O;Bn*anNlbglaoN zI72R5kxVudM|dtkch|D|F^+LV0V}-K59t4>rspbFPZ+xGf}gzhuGg!~U9V6N3R~1$ zPuNm6>#oOx)7`5?CS_@mW-kwP8vSqJxY7gyI1yKjW z7LC3qY^};0EJVFRw$U4qF-!+1`!W6a|IydQOOxZCaMU>X{9D%3&Sz| z+;8X(5n@c`xvY$*mlNf>F1e@+K2W6czbt?y5~i9pMfA;N;^;~kUu0B8kc^rb7-Uog zi7cw2JIl}yQW^Tu3uRP9XOYp5z;&$acn-PMvY0^9{W=aI(?gCtC;I?QKC+E(1|ZjM zByYy=r^sN5>tX!aOPRKHA!M{WXN;sFgKopN@lj*KPs$I^7lH2I9D${r;XlpL0f_rC zgtlSyu+OvbO!+K}pD}Zev$Auv?GD{~LuXl#-xiBFkln!YruU8g;;+TsjWB5wB!YVc zbQF>DO4|Tr+j$s2m+mRhMUVjLq%9dbf4bSI$P$G4oj={>ptI>p+d~AV>*v=1I+m&5 z`T6n82+NOE35?X>(}2i;r~?gGDjA#@I#U%W5G#gi`&bls_s%?>{f>2&e<-PKKguQ>c*F;0M)LEf7fcP&eek^lKggDp zyfxk;ihh2LmxaQ!K5hhz*5#>AuaUr?YrLCDXdKV>*kuuc$!a$s>rlI7b+3H{ZZJuAU z`hxe&@G+AARCZ8tdJVs~gG>21xa8l#zXpC|9Q->m{BvbXN}dz`PE7bXxr=(I6W$pU zK0)g20T#sfqnK(QP zhpya*+iMbR_$*)ec*B$7%?^LQlkf21ykpxshJVV3f6j+LcjW=@CSYPXMnSKIRE2+kt-@ zc-Y{-2F|%d$l#s8*WmdwgAc%@mvaHmeaUYu9`M?tvPAI9fVU&TYYl!C@H@djWbhTh zX_v6X;9G!y7S9}`$nS38gAm{H`vmYifG;rNp9jwKfzk~AJn$QUgQdiO9XMMd=a=Mn z&TRn9Yxw^GGl1xFzi(fcXA%H20B3POy66w90LPz;{$g3+GZKKd+W7m71gs@Oeyo|p z6ffOaJBKNru|ce%L!p;$tffPtmu{@7L!nLAcV$JPO_v+moO~66?O7W$(8eIYV0sx0 z5MaqrTQjS+sl29!wgh6>;8-#sa8WhRU0MutgBnJwC{))iZh{5CrrL(aT5@nL8oC-d z)aayctZmrPXssQvyn_@Mt|`S?YIt5;gT?=njZNXjwQFl@qF!PN5w32iT>&W?YNG*j zHm|p`*yz@4R)OY7TY{Ohkt4Bdi26CE3X5wA8f3!+pH9Oy@$Rv_0Gh7r-oS8Z6%k}4Bx5lsazF%@CWd5OTYE5C(n zByM$-%=kFm;6vjOmxPS0#fRi-A#6wdveL&C?|Ea5^P3gV!oppL+(Ie9!mfLw_ z4QrG0zsgv{%+UVs_8L}U({sy}53ojYrl4_-+G;t<75xD2+~}P%8I}|pn~t^qjO_55 z<6?i%IWJrBSz9#d=RC1)NC-{N4ll{aZ6)u&!#KTFMou-XA4sjOHmv;wX?RmeMowM0 z3ZcakpSO#ID<)=FFAcOLW~g^}vKhi0>J*a2nxT5l%i+KQ^}yXQ4uAh0dlBjCej8PMd zXgl(*S2igqoBZZz$z0I!ZgX+gyRc=cUh|FSfnx(d9GV^MNXULFG6dyD%J<))?0vE5 z-G6Fsa{x9fy(*alU2{zLmsIHQEbOXK#y2U00C{{)wT38>1~M3`wj# zPb12zCoMUXH{ViYUqV9nvK7}|CM&wR9S#X3_K^A@BDavqY0I*IWW*bx> zsLN$dQoiiPkYKSfN5QJ4?9sj2n4?^2_TYDlr)88bV}(N)PhCiSPj*(Fidtlz3KudFW%C@R>WL3is)2ARP8=j0j*Bh`QBK7LL8O#9m2`xQ0;~Kj2~*SzEA&RrSI)6 zQR*kek?zk3Azv=Q*>n)L>u3i_F&zXQpeGCmQ3&Ix{fafg=w+Cuo;}mVE=S8~Dnp zdfJeN*Vzh&&(ixF)9{*lfH+=L2MIy^G$8qWnK<}--M}{p5&vBSe@BRP|3o-bsrLyl z#dIuy^osQQZm<;VlE4{n0wL%M2tg<7x1gI%9MhCVgmW;{0p#3@W^;^pD6O1P}Mf_@xvgEsgiMDJ z>HZTTrUg$M{A+}m2K<~5@!uyb!7l;7V&sPq@0baMNXIj~!%@0oe5U~duq4X=GMP;z zOg&5MJB%DMY+|VGLp~TL@hX!^8eVNO8DlHqD14m<6G*yW$05XIK%t;KN2|S#Bpnx(Cyp{w9w`&;r8+Us`IQuo@h|{c)E@>0 z|0NRmJ^1wbg+a7P&HpN|L9AvtlUKv(DpVnsj$is3gJ%xoAV+Glhup|g1& z>r2$ibbUAJ)*Ctiapd==MI3k=o-J>B(@?d<3Ac}T;{mfi&&>lJ%b)VHuISJlyIAcl z1zj76NXPd*9qIh(PC#4iPP*$rXVaB7dm4V*K!?Gui}UB>1&5!s`P1-wwVV7d92%8R z`pjwgT@1SJ$hX$vCw=ZT{BG?gzvmr(s2Xwc>Z2WWY?FTHFTYH5EL$I#5{iq*FBf#( z;kUuz2N6!o?{?5(knQ69^1bBn!>mwTJo#P+U3c2wU@)=y9dQPJV?c*Ny^Hh9x7^_u zGSudR_n5;k_YC~L4Z7~+_d-;v&F{D~@Vgjv-Ri#%Kg>nN#jD?2yUFi)haYEbbn*DL zgN~C4zw_7ch>N26%`?R0cNjms<GcB+$jEAZ3Yc3Jst`af z3=<)GkF8J}HsBJgYHfAmx83M+z)%;D|JDa+~-Z{U8j%D~Femuv0$$2U1{|#_2aMm^P?*cyR;J*d_u!HmP@cSJ+2hThK$Ht$5 z=MxUT5YNAHaDFxX!NGUpnX+>%VEPXMf5Hhrg6F3l{F{76ek}dZfS*8In?LfN;L!6l zok9nv73L@hzZ^I>3R(HD1I`UX7U$Oozf^2`t$2RX2|oxNf_wC|H2ed+Z25i%IKPlA zzh44po-Izx!5=yJ5a2&|@I2tZ0Y6J$0i0!O@hae92fqb4ztC*>{lKdn{PVygz^!~Q z15b6re+v9BPWT^zf7uD|mx%YH6FwPu)L})&!D&f4BL?rSW;-~S4CVr7*=m=f$j`+W z10QIEL4OnQkb~C%w~mMFlYhv1fS&yF9Gv0TI(P$cmalf2-o>{fob_qLcK~O7TYL|2 z_9u%U0G{RG9|z9%Xu}@`ewl+m34FGLKLb2!>5N+!fwO*X{I3JQ)xq0=?{)AufIsNq zZvlVQ!G8n%u!H{*IP2H)e;@eQ9XusTZ+x@i8NlCl!iNC=lY{2~Ph_7Em!if4AL!tP zz(+aw<-nts&nc<`_+?J`Rluncu>7tEUghA`z#|U68hDF?Hv-@9;I{&Q)WPor{;Y%V z10J=MPEj8P{(UF>AaH6JtUQkcKk48{fd9q8zXaSm-jW&HUsBb#V#0f=pTyv4>OBXS z?;QKG2UFtxefSt3KHZ0x`S5Ffc%2Ww-G_g~hkw?Gf6>9I)A)*mQ{HwT{**z=7Gp$N2EeefV4- zexnax@55Vs`29Zo2_OD7AO409|E&*CbS90gj|+YHI3Iqc4`1TLSNiZ~AHLg%KkUN~ z`|uZmb2#EVgqL}I2RPp!eBbp0{s!=DJb%lC|94o5W2$^QLvhb&v~I)tCCk?u)6d0C zxP`SVTGG^1yDrky=%b3Y=!Idbja~+8Rk54(MWBDh)Okzh#`T|HEe6V3GM81w)FsA( z*G*&nO0tu4)Vg|$k#MXx%ydr^!Gv^)vtix34eNcP&J0T?ips4)trgS@uy(aJz#eB7 zn=d(JF4k+#<^?rkhwIOi7vPtW0gm;sO_AQ$Ro68|?RWhl*EHe`)Y#Nf!rnP-(VCoB zyQ;co%fdQ;G0dxNtm*1If5VE}sEM~z{9P@Rtwac+sBv=P7;-zD<$nwqiwo%yoe7plBx$!}Wy|W_=tnl8kkp)&>@5IOg%h}r)QeZiI zTSBH-&faE_DVFmTEAte~+1mgz#d7wxeoV2Py-gp5mNU0|#BS5*$u&faxj8~^`$2Ey zCJ8;#;@Cv7>xYjt26q64-~8%kpU;8~>*eG}1e$*1jdihJGK56E+(EI6uS<(_C(G7F zg0A`yqr-@5tb* z#EimSe52xUj|GOc$l7Xspe8q>uz;AI>h(3Xk|Bw2e4WEJg?5eC<4{4GP&Puu^|re< zkcdtdJZ-T+#&8BnaO)%)qptIeXSq`D6BA*P#IPi7LeM{X$bj?_1N)7kUy7zmPQ?m6+^}9)xhCWd zOK^h*j1`!ie$n9cP-1T?QHJ#ysr~wn((r;Dfx|LJ3mnord#H(~hV{Q#(+tQJm^n}{ z`wkm4UdI_cLBk7S?F2V0Q!l#?8=|eAl5?~gKXDi|)NtupS~HqHTx$%IM^N2}d|ae8 zaOokfxk}HbnhNwe1Nw}D@`o;U=U(sOktl(ram@`tVHkl>vh@FBzIOB9t>~ zOzyY|lky4*ilv$%W_iy3LnWl{?ll`qDI42_qS%q#Prk%)bk zR4ffsG0%(27nYYSLENjZDut*EW-c@G5SQc(KCgUMN!bm{7FI6MJm-}!F4I^gbF+*I zQ*!e4a7Zrcu)LUM$|z;0^DJ>HrY>6|1%`O!0epT*nJz-|GJaGb3U9%SmX()i-Z~t3 zsm8A@UsPFf!?KyPmr3F2IFJwiU1aq9jGT*?%oQ4@Q@)^V(G3fAokEypGb|VcfR>ImQL2m^8ujoLVL`onWoDg$&kffrFd0ZalbA z>&$~IwZ1&KO0TI0*XZ+tgJHd{8m!Zn%)u2pqrv4;CMsBCgkNohzf~XP8QiMvvw|>8 zC}#S%Y5S_+HmrLRzeREHj|$#_b#1~O`jnVpi|naV!R^{II(Q$}{TRMeTSy1@m{Zes z>-+qIcWEPHC2=V5Y14aky^-u0HSwVl;n}!MTMqf*a zw<^~|gE=S%!ciy(!qF%P!jXD?G&lz3Kpby(+BEQf!@Y!P&0H@HrlA}N@ydLV5Uu-R z!VHuHVL!c&8XSvqAdcC?6NKp~2g2UkGCK%6rDutUP!5EBP!5EBVMjrji}hy0{(9Y& zN7=R!Ptxr){Uf@grDGNVkyIKw97IsTwWggWns%CC+UW(l-K4`Hcq!=8XXtj5eu-{3 z>6hwulYW_QH|dw_c9VXEZa3*y>UNV}tlLd`iEcOPrMlgum+5wsK2x`w^m5&9(kpbk zNuQ3_V2udAi-C&)4lHeSvN_=~wA?lfF>5oAj%7yGdW9 z?PSsyYm5K%C3+1j{TjXDEgeP;C&>3Yz2PnWdf1f^$9u4Y5byM#6W*kE2&A)c0=UES z+&a{p*t4NFWG;%@5!-RprmVZ6HA_9Am0^l!#>|V2X&VAr#oQx_RunzF7EK+kM(o4U zYNWnV%h)lXn*vWwL~E3B39U$u3Px^UL2`6?9wC}GNMwU+0pVqG%DU{a zEF_MmJ(UnmyNIyZ9NCVhJ)L-|u#!EIU?t--dWqOwf|b~ZqL+x>DOkz44OV#l3M;Yq z1S>f~46I~4M=udOM)VTdK#N`?dp6NaWSpNxc(r~7a1Sq7$)46ZgiFjprfAyeC1S6G zULt!((MzO%qnF6uTJ#dxn+jI4cNVO4zbAB@l!JrY#{eFrtr`!~b=p7&vONYJoR`=| zdg-{;#-GCy+nvkr(`Z}og3j;QzL>UkcMpUaiF6X{qaoXmOLq$zsI=u+GO2&kSs8H} zfI49j_)9+o#Aqn|q#xpW1sZm$Be11o{krL{4Mlk%$m7R)aMO)|&UKbY6+F8`x5?01 z9^@x|-+CCh3()eW*S1i6v-0~8<`)0IfsXaWqCvM6mx{lS;^)%65;D^p_{&%XNIHMI z?}1MG2*O|xP|-{8?r_jjO^=>q)GWW|vmmob)6p)(nVzi{4J zwKGDYJn_+giwX+`n>sCTsyuYVN_Z?gm18A5kdmLb5|%9`mtE$r8_a?bFkJ6?ON?S@fNgv#_O`D{zfS`G_X;az~ z((Ha{NK|B!<_fveCLUmg>U+Ji^h40|lw6(N>@;?;9 zp9$f8A>1Fr?s=+|7d}5V&v^wgowk}bjK&3he%iqFk`S&A;l>bd3E>?fd{YR2JcJ(# z;je`7zl8A1!0bYnm0D=81ADmUc%&BEvDZ2~vdS6uP+f(yfV!Chu4Y4rRmy=XQ*Bz? z%W#@VqZO5obd?%h2|+zC%kOA;nW%uqmWfO2Ynccr0HpP$Oq@}@&}uzSTv}zwjkM}Y zHqI(p8Ekcg>^Z4WN^wpHeH%?5QKx|p&e3b8;6+MhfFbFlI2szb=dYxl;;VCTpWdi= zq%~Fssds=Yq{TwT2jlm&Ry0Vgn^P!@NSET4|8Z&^R7prHBv2jU_(`3|PwG5=QsikaW4ylg-JcdbRv;@`k_j=a!E3EW;o7ROXY~pLn41gAA*q$9_X@ znqE!gh7B7$iltu`iW@8ZIn0e4mV+BM{E5k(NdC0s29ZaaFdK4H&59Kw!6F+=QW-2M zOJyp|h8!Z#WIC3Ft4NW!m~@_Ajg6M;Ro5t%3L6+-X*T4rbbKK(R-d_azzv>UQWSCo zDMk+sA-Q2SjufM40x4F%X%HF3vX@7SN=_riP)d-Z)oCEfjiWMBEcel1mm5F~^svVP z%Z(ehPXU(d***nW;goj4lDM?XT+=S4rd@ConwF|Ea(EOsv{dE|5BaeQHvBI;5X_Ew zNC{9qc|K4*c`g803<7x=P(67JP(2y{NM!MtC<~XU9#|w%7XAb3g2ahPv4Er4ak!*Wg`r|F~oN+`1q)X!)=I=v1bzA z4?Y%=<(07q$}##W{JDG|bNKXJt@$1YAG$LMBH>~1t+c?Q-@>&k?~mZ~&;ZQW)`$5% z7vh_Q0p5T(^2sv_(3SJb z7Y%h4`Yb$%2>w|W33mOkSE0E;5MCY_bR@-~h`;C=6@HQataB+YK-<{oLSY4Zi?o*h zhaS^*1aN`6&cPf#9Q)~KHl{w{q|;;C$AD$?QQ~9jfk1kptVY-QaWPqqwvZmv{s~~O zjX-|i^RGGf$H|#pJo!$Cn0nn_g3@E!A3#?)=@I{$=@aDDM=xYL#N^dy5j~=vhP3CL zbiV3rpa-;f0rPAM9b(Rz0F*yPJfgKb>CJ)rJ@JS}Jqmk&3h6Gs0{A;l`t`unv#|W{ z2TpGo#^f|Vn@SIA>@PR{0r1z)Nwx$>6hqpT|83 zgU<%;0B$yTEz@y-qrpkwFW~xGgRcWdvOKfQ?=IleaDRyx@A_(?4+>+FF(MZFNES#+pkvR&U@=relk?(e66Tva`g)G_osXWhn7mH)>;IX37Y=lxV7yie zUqo$ljUC%1ZCl&AI$HniCHaupzeV#n{h9GsHjXntVUMwCT>1+t!}_%L+!OI;!3$Kr zM?)f&$m@%!-136r{A6*@@?->Gii|JcH>>#Cbx^(SPcF4Sr&Q6b;%n9Fmy8Kkl z_T{PQ_GePpZqMs^a{KlxBE9AC-$VZHeQ!P%$4bXpYV3ljm)L%2S)~2FsgCVMJr8bg z>G|n)xV7y`bluz2-Zjv(r|ZzFO?B$Q`pK1QUi%$ORl@5_q*{6+Rk`uV^CLVpkmV&V zuavrtlJaJ&yuNtx>FT8NT=6(m1SMJK+Fln;Ri`RdH>4cgR|x-1-hBFb$}9JbUnb=Z zbQg-psOidEpwkk5+JWxEqJ;5qRnnfX$|^jOTkhA!TQH}+u((`#<;~)KN+rhj?YXjQ z@}3=s>hs#`d-gxFyC%|qf|NPC=;b6^QB=iBEH2tqR?d2tC|k~?>ECe+mG{PF zdOW<*z8&6`%CD|RYetLIK&0r&%ga&+dv@2TALgoq?OyTjHMY-_@H(ZvTAjF{Jyo(Z zQl%xU#P~kt?YXQZb)YA=>dE-n=TTpH2piGY(n*@z*BdW*Zlt$2iMEk8OYVz-Ke_K3 z`S7%jiYA@Pk^UCQP>Fr6TYsGu8Z;*DN zlr|wkbOt|9ITP@MKbrm@T;`U5hp2#~rX2iUb^i}!n9kZ<@kiNEO_$t-Q!bzcJt$yF zldHd61eaibwebjMS+OfOD{EkqRcu7c%HSfiN{yeO{I$!Uo%|(AeQ{Z#12Y%hxjZSV z@zWK024RM1-OJBPT#AZ*2`M%kW|EGOL+zESGAinb#J+;)uX7cbg_RXgM2gBeR(xgE z=M2$K7a@zuhn2@Aq}UW#PI{VIv4lLXG}6h!xuhsGf5CEzm@8CtFSM2vn+5M7MY%2} z9j8#3!zrw`w2!cDl?q& zj&%fcIR(am*ISX;!jZCKTnfs1=8{m8q8g2m8LW?PkyDfmKC6k{vt0^=G6Q|`^gGnM)*DQ@~IDECEQBAtw< zK7x2mMck*QT<*t`-y?;5s#z0XZ0KfEOr>1R&Bqk_VNy()_kvO`4~k{}-zCKq`Z_7@ zf0Gnb=3Au5kBhaEA1U)AMScrOk-nZ3Q{qliOo_LG7T`TX147E@!Zr7~xnLc|=;$-_ zCrrol^Pi;P^If=z|CVexazPxHm-)ZE;PCpBcUKN+zIo?iI>4+b+p@W&cy*!(hlXP?ph#1E}zc7C01RN%&$W z?!UqJC#S&D?nql?_zau+1ExBg#yESu)bLpm{|!Dj*fQ}!;Pu<_Z8dyW2IYOw0*CGj z@x2c-yMy5;DoV0etmg zVZdQ|-*x1nN)j^3`#12_nsk?h;4()ZrisJKyAgatsqeoy z^7!e&kg0tCKE(1(!|T!37t@x6O!DS~Zz%nHg(Gju5#-%6M0w9T^1LI+dj)($>5tRU z3AVn)j=a6N#}HMrg{Cq!;k7 zEAJcNOCgT)0blYAl&3Wptm|;t(7m1gTzPrf0&PIooPYI_6?GA3KblK5ZsE4+mhd$f zDw%p*bAfG7Te-EM>E=3k$R8w#r{==tWHccQv;B=02#u-tf-dvpV%n{)!PH#17uV~Y z^gaGHM2Su4YARAl*}4 zz-Rh#F-1)U8>o43GjN?B7gM+S*OWg^-4DFOkBh0#`PWRJp}q|Kq8}GiU-z$>o>0#M zzv9Qm)Q|jYrq7g*++}=VCB)QkknZCD1YY5!9}3(*TgHoR&UxLY*JLaVf8r#xLJX0_nM`CxG>A6*qN=VmvU+3*iM0 z=Eu7YeCOXC!k-P{M?#pI4mR-qe-7c79LzbE9#m`~{~ICfeupxBl=D4IoCx7}gz%~m zULV5UAxupO8z}!nAxvAsZ=j4G(x@r%1>he8w;TLz;7{V3?^CA#EAXAT=Jz7;uYtK% z#qT-d9DFqY2ikvw!4rU2LLTQBrk4V94D-E0{4U_7z;g^f7npAg_AJv|fzJZA`CSHl zDey*OphZFCvzn4kLD=#Aj&)0+<(k9 zMa*mTxUz^j3jFZOA^{~5Utc7s7vmq#O+6Ah?#H8K=m3YulZIthewvX@wN=qyK&+d;P#_dZ4s@Eiptt#542pMII*;C$C6fY zkzn;&prx|9m27qM)de_RxUucBwyy3r-VsuBX{CloMdjMIu5I1QD7ip21R@(cYdW+R z3J*9A9{wz69#ekCbGdo8w#l5TExg@EEft$woPP{`m-N}uq5&guj-jk(YVc3V*VtOj zu69*pa2!7JV3xjf2_2Qrf*FdwNrvKRUKWvDRujf&6g`ymy>LvxoNC3-gT6K7#lVR) z2Y>6B207c`z0t&oa**X2REFT$(mvY`Y=8&K3O*B8jasmXLAgwXYlaMo%rf23ItP*E zcyrLPbjbjR7UCV@xJu4(m7L=$ImcCUj;rLD@43IaR*qesIp&Hv&IfA--5jlT(cW2| z$|^az|In&(wcqHJl&kj6{YImt_^RxgBVH^zg)ya~w^DqSMrR31LN6r;+wauqu=*I~ zqK|QcDlBToU0U~s@`uo@2=XoNz#Ys@$G`PjrZO5{r;NHJTAw2(HEQX6roFHt@?rJSTiT=8 zyw_>nP8q{FvW#H~ygy6b-2T>UZ;GBuTjy!2bWvgP_Vxp&genp5Yp**!73s|`dNP>> zeWa5H4y39kA4qPgLp@UC644(`f_6#%K$iD-aw4vpJD)g!Lm(PV-_6fi6nCR4%M@TbRSS!Nh(s3+kahqq4LTix1y>z>#bb9_1d9& z#_-Sd!@R9KWZsiLEBf-Z}PVToD%F4}gdoBs@E_ z;!(PwVSS|pYCKd`A}q4|VHvK%TlDxLKOfP9l!-1h8>1r&IJUX-VD zjp$ZjC7+80T%o|ejp8AXve|+Au?Z~O-X3YSIad=a6UD@5i=K~|E3;ZuCMqFat`|4_ zb1-YP*$c)w^=-s_xsnv+I-L|d1h`b{JZ(}#P(_T@8)PXqHFcz@7Z)<9NrWt<&?ti7 z22yOoAW7t$Pr68sq?Gb=F@{P%T(}|M#iU?vB?TWBSGc|3K?=T2q!X0tBt^Mo5gLWv zZsNO0asTC{h)S1DZ-seeC zo-dLvRO(BlkpB;)xbMrPGnD!Y=_;l6lU6GAbyDQ>P0~80zD)}LXGqcc|3rF`K3tCJ z{lv4BdX^Mp_y?rO=S9*gER2zsY7Gf??#sj|&#R>GfVna$@_U`MRxfNZKaRJdK1MR8 zc|QWjc~EyGZXTl8@PwWu;`Bdf8ll-YWZh^Llk$vMJX6Cd>u5)8zKFGoV+BSaVuvHp ztvtp{sPZQmp?GqKBh)RWZc$rGC}PNzghzci0^Qcc(}Gg&yxwh1WGG?_hbPvp{NSD+ zYlLE&Ioh&f&4^cME#zm+F&_W^=Y)31V<0&L{qLGR=AC6SF|AV9S zWFv6W@C3U3KL^DO_x~wIEM~^xloQqS!$u=EsFLVtjtxgJo)%IYU!gZf&#A4PSP7%=qe&E~B`FKDMQsC2!*U zHSu(Vz;fSDihQ_XNlKG!=JRi)RYofj?U$VejQc%Od{fLJt;OdHDe?(uEmCta3dKbP zq+kP=|I7DuHfgRL6odQBCpIR6IO9j^{XKrl;>|Cgu3(Yx4ZOJDUUw0%X55N08oiZb z5g{k$;58+mV&h2hWXaQlhXHQ_a}GT((t*P)Q$R21x|l@r{VW3`%PVy^Y1DPR7kh+k z2ehUHmX+m_w$V}IS$+ce!U3-Y#k_6!0W$ba2EJ)vaQU9WJmby`_Wp9i7c&w64!#vm zL8PCMhLIVNHw(gS8gI4NG6H~Yo#%!!wPnH+B=X*lkB_gt2bYTSe#wha*ahtJoq`T! zS;FBKM97#j2^+x2_GdZRR}2`IgLEBtfRB6e;az)XqRXHW>|`ylviz8LNj zm~U9#KY(v2_2ADRE02^Rle|LkRqN!yzv1$o>&U|=orFyCTEI7y`hMDxC(j-vW|H@% zA(rp=jy!bDVapfC12dHNTLnJbeiM!$?_%%`rM{nZdz^Nt|zOW+&I`1`#hulNY^;`o>yQvZU_)|Yc5 zL#Fy(48D4u9QZffexGsV%`lvqAS~}Uj=aPX{Y^r0@^x*;v*^Rtwe8xrp=C#l z)|UxuvJ5(-Wl+Rl^t3Qrw63C-Gobu*=R1k`tDrn!lE0aWe*pTB!~ZMbryWdPM;bO+dBwPX)WPq-HOsVLzvHBLFx|n|;+j7(EdL$Aui{=z*K$AgQ>z?)mZi+WFX6h`F&I z^BU)*Q$I8p*w+67;Cr0(?ZCG?_!eN+$(EP8dCgAxKLRHm{4#K_gQ;&xgE8BFcSgEtUEhUMQ0{3$2>cHrMS_(9-5Iryu9Q;dQ8l>5D z9)HU=w)s(i@_>V>Kba0OvAeREC!H;F(z76?&cXb3Ru9a!)FG}Y&&AZgwBL8+zX;f~ z?7%I+He_K}jPgAjfpp3%b1>7-cW@H;RR@#b#VO#QJL$c^e{%3{;1OsK9pdU%;0X@C z6FA}E`++%LE&u0$S2*}l;B^k(2h8zg`M(Lw@nrG80N?6h>XY8%;Fp2-IQVtoM;*-5 zN%uSWPr!W+&dE_YrXZc)NZ>add=jv{G=wFtJYbF|9pb74c$$MNfag2-9l(nnycl?m zgI5A?aPaxSI~?2ue7%F)fzvwHakU-zQ%?F$;Kv<&9q`i*ejjk3gFgbC)~SxGj{_fY z(mw-i15fS?J`cI-@j!Z>dM1GL)hiC>@1mcF@LM4~#=h*qOa5sgJU4`ELioH8?hN5; zLin~2ejtP&bufPFt1mm4<@-(uzZ}B94dLuKZZd)QPYU6(5MCU@YeP60!qW9VyW z3NYUeEv!y<$eDKL^tv>k z>z&BCJ*YSBBv3)u)mF9{Fura9Jz48=1>;w?h@N+*q&4;=zI2&teHTVf#!%m777LeH z1!kLrpJ3I7ZGz+W$dO|mA30IWFJC2!-&)H%l;EmSTgkkED#cc-J9G<^&g(X(9j2>g z&jbv%LQq%P=CE?xhPKsho7-ANmEDm)SZCYbf|SFQsiCF28=2$(WLH~vcc_P$${WR9 z(4g_b)XugZwta^Cm?BEm!8)0nGBl4(X-l@XgsW!KSeCScxUF44&)Y^?mr}vpDZnaw zONwzo1);2lJ{Z!9Fp;9)-{nNQKDRQ&2l?%Bk-CM_{;wDx%npj|jI8i2HG;MrZ{r2a zvBdBXAGH=75F}P0)^Y;|AlfPfCL8(!CLa32HyD{`W2||IFSXo?rLl>=%L=AxiNyFv zwbFP*$5_b~R?^BVI@~s$eX!DW)Hgwpk|(x zJkLs=XC>2!CTPGi_$1cTGym`}FH@^&7Gk|m(YjaG^${2!QxEVgJRRU(t-u9=aQRS z^qI0Wis3^7H)XZH6EwNs#HJ6f)v=xK%x0ok=Zw+Tw1t*8oVqfc;7a#z|Eo@+m09q( ztr3RR|6^MtOc;1~+ZlteaeAzi?%-PjCT>^~u5R?ISFNu1YUkF@n&si+C)u&Nt;;)q z(VWV%IpuT8%PSYopL@Z)3UA}KF0Z*GwwQk$G zvEveN@d{ky9BN!Q)m^%I^Bl6ZCNDj!c3T%F@zRxLvk=jZVs71W%uX-$k1egQJ!7tz zr*z}M)VVb)mdsthxs3;>Zs^!n+RcMhONV5=(z4^vFP!f>t##uie|AlMVH>s_J6Y|m z9mh`CG4F%T6@UKmwtlnWxj80PJ?_5lZ_s^RR}-vt@N@TX!5WDhSbqs)B=c)NgDn!4 z5dPPNu>ZUqRhX|LxoS+F8WW3*jjPdFDgr%YhNy7~SD39vTb+gMEWO|t>kDsaONwYMaFk91!P((yH zxmfQmXP=xCJK5+WWlxUBCeM{*9L%Q|&T}GLuXHR{k2B>KCtA0?Ux5>W2EJhU)sprpDC`#4FEPyrgOMk`+s8 z*Pz~wO%3POG@ZSKd$!;`Z_P3{ZTSVOYJu0BhdY@r_=4*CHBF7xs}?(Pwbd(Xo3M-( z;5l#gl19zba5l4OXk4;-wa5V$DYdKWET#l|ZG@w2XE)U@TT*+rl=JMS#w86)s@EWo zbIz$ju~seC#n3oitVS(-@iKFBW0MrGZb8!;sc0Intgh8nhfK@Er9|eZ@xrDh)qpOp z(YT?0m2Ow66C&NmXa(V4Ri|Z`bktR2ldk)O&4|2^cK#BRr^D~ZnR`~RL4!y`H8w3- zRoi$`gYH9AqG@scY5?@%nl(#SHmpHIH#VKOwR7vX%eS&X2(W9jR&Of8DP^ekFWfY- zfs4{OKi3?{iwS2wB6zf?1W>MA)7nU;zb2#Iit@{xa|d=Bkv!Cl&EzAZpT@tOm+00~ z@`TJ|s&&m=qODr3GrCO|IJ!eGyGOhAa(whQy%Znaq}3Cmw`(?KWNYnODpKGr>Y15`DLuf!HF=}x_^5$%N*IPrDZo+I6*EyAK#qn=UVLcQf0 z&C%N3QM{EmGrkD*Bpt7}V58XTN)eCI4!xpdQBPtFX>Q5#?Z2B8@Ba6ZLgkQKvr!NA zB!!O09i(`B-$M$OwR=hNR_B&&6kh>*Nbwc$5b0FZlQb9gB*hz*Te(rZVV@wy8+SkH z33^MHzEraYA)c<(3#19X#Y>;D1H|~+c$KtRZ}rj_>(7btx_^T- zrpIx?|IrU(0bczmg38AOiKbK0PBV_P%{b07<9LJ~R|SjoxGFeZkE?<+^thtW)^^-q zaHbwt1!w7TRq#$dt_t3z$5la<9#;j`dR!IM=y6q0tH)KrVm+=3mgsR+P^ZUL!BRc0 z3YO_{RZy?TRl#ySt_ms$jJq zR|RYIxGFeLkE;T_zn`Pr3((%A7ix>b0=yRoh}Ytu%)Vx`k2;{AM6nKSFS88#LV5>d zT8sqHhoTsVF)YgZxuh827(+6xvO~GSjxi?6^yoWL{>Rvo-o@Aw6H$x}@ixnjSDvvC zz`(|>Vgib1LhN+$EGUJ6jWHzNYVi!o=)kijP5?00Wmd#kmrU`@$f&|IBZY!UIanFb zh}bj87cT}jM9R7Q9w`Pksvw6R7n3H8e*p|^B#AvR#=MxAB1#Ts##om^fmKE`M9S#K zvm&$WEK&^c*`(#hq@lu?5Mv-CNla$TNHLJXBBr5Wk=b`1DF*UD8EK=@<-|aSD0v&;nGh3WJQJcggl9rbwDC;H(+p8! zQj2H8I7{F~I!L|K(7%e{O2(#%A>ScCHGRSH7fnMsTkuv4Qr_ES;yLy>&Rlt4#{gc0 zzi{AqV%|3V5d-rLc_?g*rW`LW-|HBVGIoP((%WjqAF-&%n9Y{SofC7(QZpwv&! z#K-=0^L@=r%RrJZkL~W}`!n#l!OCbxcPinkxeLb4=DM<`ECcFJQGNBLpa}uoqR_bM#_5} ze;6-Gd+$E*$=J3LhJFjwEnj}Id5I$4_9f*#7vg&n1E?XQ>mhS2(#iL4_(QZGX3mhu z&&T%S=eTh5y#jplv4MCDSqYS9^pml+gL8lx-cCPx!Rcj{n)B`TlYh&n3a^X#$^%It zV-)?kelpv{2DdMHJ}}<(PX8V}wAnDWOMFcHz1)s#_8s+uKLnZ$A$m?7LIpWiRQ@G~)l$g4hzs0rXr!MBxz*b%h z@IAox{>y;(IQSOemmK^F;B<(|dApPSxR`p_zvlB7cXTm{M+DB><%h^O!9UIy7*~|< zVmg;#+vyNj-v?&hEdDoO&qB!i39t>+R}7XnS5bf326`UObLR3aeC8H8nBO?_LfAcD zm+9w)(%tiPncfvjzafPA1HlIJe?ElMx|{l&iy!nhkpJ}%ek+6votGy0PYq#u0=8i^ zF3KEC{&$7&1tGjGgnL8ywh;bY2vc9%2Ilvj5dKjJ9}MAa`vS(jy#M47o(s$_XBze4 zDuF#*bG%a@t{Rx*cfMfE__b%O)BAYqF7IB4eY|y<_wm*(TCkz5Y(x3Nb$XAlN%r{G zbzi>DTx?0Mkyfp;ky^3nFxp1`j`N!Jo2}B+v<+&GHacmt-j$&@It@yNJ{y`64Rtb%f(h>VE2-4@+9)W3)lf;R*$mQ70oRdLZ$#y; zZF^b^$GSC!>WgRzK*IkwN-C@Ih^I9r0(ue{wa4`&te4kgzDIvtPh!}rCC9uEj_XMb zPsztV4F5lRQvRDzlK6{gNa*jozoL4?V3mcDqOwq!rwU_{(Q*2`NUJRHLl{3vv$A7Z z`q#h8&d!Nto8MdoIrs!dD2VArjaZyN6oGT~VnsooUL-5XAAiCKv;3A@a1yuo1&t_} z5G$C-t$n??GfIt!jVQn&qbL!#_W9X;wBgV)Y?I#?X+Bi{B>o~TNvv%?bOd4CvQ&`- zIF4q^knL24Kkka~$AQuHkYA_r8xkwE$9@ZOnqC3q)(jgSXQ#?96>jnH7kso-|2pQ@ z4u2JMONYOPxrgeJo@TZXQEOJ5TS`b$Q6x%bicDo@nk_^uKcC5TENfShR+ueBEMG4p z#xnH^QnWw=DVDd_kj^t(h*cQx4XzieDEJNAu~06?A_R8O88 zRFB1Aq&zo>l*a?rljj17xK$Em5f;@$k|fF^CL$q1g!4x^SHI=CMP1~fMRi#%g=)(4 zh-!`}=IVDS%nxA;(R#WrCW3rJU7%-MvmHEhFU!huN!ysXd1#n(q>)U7A>jr3YtcZj znQnABrvb2xHguq2^xR`(G{wjjKD+L*3w&IdwZRqvBUSjMpK$$M6neI00=0bM1^PdN z&!&;xUY~<&W@GbxOFE1kI@lsK0}h2Ryg*NRwyZ{^kQk-@p%`S{GbrLOdd`Pmq(AFykHf8T76^^W@x`_)Ihfw>q|>+FJ-{+88h#FK8|Yi_iva1hyP>09q*&}DvHO#RfqX8L&bCh%rI4ujp!0f?h-y-~m)aMDi-q)$>afcu>ExqYc#9cG8yy(x=D~iNE#ZVyel%X8xYq3S7qLK>~ak2GWbwjlc~~`UeB))6~a-*Es2) z38c?ZUjqKPlm4|pdO{pUf7MC1QDQ%Z|L-0DpyQ1Rm$Vx^#XnemBz7XA;Joa~@dU`I4WT z-VJ`wk#}VvzlDltvvfJ>w+GTI)hB`Pa?+_(WJ4B|7rp{K;H0yCT+F?OSDkd%_a66h zq&=-b;C~Cq&kgwA!;HYF;I9GWe@TA{_=C8vG58JOZj>isFu(S<;JVo0@xa`FTW)XyxZg=%1pGV9 zA^bdI`D=jr2??=+dG^Y0a2*8?)7Jr0ZU0LqeG~9MLHtzHr%a{^1xPzn__oFK;39-Cfw!7_HC+R)a*vvEMce|h_`u`2YvkcM%FMoclmu&>vEV{JMw*l>+)b#eY5Lh z=*Q5_*Y{l*_GxJAi`L^_mbNYr)^WbAdj>y-n%|m}vr(POF0l6Iv|D%MZFg4$dvJkY zm|zz!@C)Eypx1(1W{U=WfDX1vmrv5uRn3MLIzz1GF$UI?BJ4D`;*bj2I<$TjS8Qu- z*<9P*)#-a$l$d%QL7Q(_Q7%cfwW?*U9dMdhv!Qy!hAw6OFkaBTvF6f^bzN<33YROp zFR9+Vd0VTwcA~kv#n?3+TiSR?Lf4L!-9ZeAPQ6Hs1@_^rEOc=x?o3ZEY|&k;)jWBymiXPDK^oL?=i|AV|ouY zw9!b|*m@auo5^Qv=k4X7ea(OqOX>E;?xc)?)sK%>I{ihF!Ye$3_)Jx?e7;?w(SlO*)fHlaIaiTJo_N zexiHxy>>MnC%E=8ZF+N=xRm>G*S$NjkI`4);p|9np!>%=tV6|ok9;bT+ZR!}VH*62`mTmn0Zyn zDc&YZPh6Fi$nHO($lJ7kvM$B%9=m2Qw&T3WG-x}1tRy))8M%A(y!WIcr8)hl?2ME~ z`wNq5+Ps16;*X_Htcmu&XXlAE6@61uS##$0{cBHF>FmBmDyuItC(@^;B> zVqB{^sP&v!U-q1={%C2mFS``0Szh$c+~f;A(L}U=LMn=OxoFq2DZSPEM@8?K&W8UoYNFq}bLTZRBc9c%G2@i6qb_oXw7K+F*4{Vvz46#hdt<6} z;rvwg^v=59r{>m7?v3}&@$N`Y+`e{udmXuR2R@cmMR)ezxjn0B;-wuD7stJYXkVrm zqD9NZ^2iIVvB{9;HQ;KwdPxL4$ zrt-lP>B=jk(@e&cn-QaXb7gzpg2H0BvD~EH8_rZkn{;mF;?goA{T$hM5bhjDDzwI} z>I#*}?~8uSThQJCZQw+9-+?R9mi=+>z>YFCN>U=|r2|*S(J%3V>^adF4_ujtQGVdc zeDFoQ@___ol=kZq##N&4OqDzTz?Bg-qyJ!h+Vcr1XUy}G8zv{(Bd6%{RPH>m<8&33 z*5>^u^k+*A`8%}V~z4(EAhf1-QaEXHUj3q{)TwXHK-g`^4{HyZsP39Jtw2vzv zkP-X6*B*)IKOa?*zIYiVp2OHNB%QH(9uIw8|@wB?@uhi2mHv^3<4U?}W#% z%PoHI9CATN{X$AF2QH8i8we#S;7(rg2n*P8J zJvT*Eyf3#br#PC-E3QfEc@cBv5N68B<_RjD&oX&ZCb$_*MYb2EBE2&)PS~PjQNKgW z$F)ywpEG^QdmdKrzDNzsQm3Rokb0~puYX-?&h*9SjcIRezdLoediKIwmnQf9X!0p3 zRr-tm2ioVT5evUq^IAXa!mvk^pb<0G0}AO<6aV4gwA0K?R{?*ZIfYT>{vWtI;%TR# zSZK%pNXp8MD*Zq6%4J^Jhre6OVlAz48@NY6;@kdDsS~2g{~tK!=Ay3=t7{uBL7;vS zD2;Q?ZK!G!qfPUYaP2E?;*G^L?kf-S5sFD)KLZemLnez39ibi~H)*pr0-^jX zh*7v*q~{r*pp%vAB}Qg9kYeh)krbKTLW;tFfE4BV5Gl%kJ1NTl5mL|i1Vth5CI;Wf zNg@9eq{T|zOWLZ`1ElDTPm?0Q&yk`r9wJ5j!=&JQgcR{#B%Pt>Ag=cQ12G!?3DU(_ zFea^2>M7EtN_~U0UR&l;SLL6G(FxxrU1fZLqI}O0qtSmriu$}riu(MBbfz|P;qKkb z#K`YeQsnmkEBo%_-|6=hX+sci;$M< zMQ8PHjDOiQQsnQEBLAtR$e-#q zv^t$mit&>G8R`Q)0=zavaZ!dpQPCld4NsQ4SD%gh9Z!HFHqT5Exx*8iv4{mmR{rp0 z;c4^399)gPGT{F61S1t$4yO^h(_q6iTm&7zjxs_=9=%XJWFeuWjnKm333a=u#t3!& zpN=(RG20z&0}L)Jng^p^)ar&K)WbbCaNnkSY|r(+Q_bqJspzh;SID?Rr9?hDcR2Fp zbz(9&6SR8l6|Vdp?>6Em8u6Hsha(NOZa%^aExOSUJTA z#B4vDGP=WIxs);ZJfMlBW%1G&j#&43@Qm2BpUom86e+_InsFMKYGh&14M!H98b4qL zQT{Z}g_*D8iDZ1vf82kmu^eIDW zqnnRUl5tVZpCAREPuh-SG)R}@tCjRTd>w;stidNOF$%kj6y>;;6#3jiigMF-miTc} z+$Xw5HTtle{PVS4KM%9=es@`uA%#$&#OC>hf7 zewnF9J3r9nsY7o=w0v++B%N=5IN}M$>sCIH@phDxUGTQds7Z@kG6oD{-3BI=d_T*; zS%5fcGm~~IZY)IOu>CL?B(RRGkF=?dQghL84@#q&2t!zI=550ZXt<#$P=5^>NE_K3 z4aKx8@?r)*2fhPNzS6%)TV(hQn|cBbYSS2JuknD0JX`1e((v}KblLIX4T*27;jJZL6)x%l2Wh@rE~(yz_@B?`}t)%o&iGN#5tc zHqp(W0T%cPaR6ePzyq#7y!o0AGX2&n4mZ`-~$GLs3E|d4CT+yle)A zu)J7tx_qAD&LnR<`0Tvr3JuG<$dQLj37O<|AhFsNWUj;VKI_QC>q9~&d0z(KQ2IAA zHCLgMSCF|5%R3Kzc0A8Hg1k2H;bUu12+RAtBd_cT^1cebq4aOg^mO?ujv((u z@C~Iu&UNJ3Z;DLq*8;wwly8qC51%s`ak0)+5ZE5M)YE6Xv6Sv9_=Mi}RA~*|1czX+>8!`A0{1dkpu;|0K z5Lyp^SfV-_*2)~DlsPEke}I{g`~s0?;y(uuZNa}^z~8O-i{fX+m7p#7YcTkIpd0|r z2Hyi}1I>!=w?Jr2??{+9nl(J+r1OZXuQ-@LW4;R9?8o8AD*u`Td6aq{n1fn}xcXOn z37UmNhJFrO<&V&~-YGCVS@`VFLfVB+dVzn<`%hGpfH(Saacr8VGswcvoO0mnIf^C3 zrM@mc9qGHB^cvvzIr!{=yopkOH+?PA`4ia6Zw>IDth#`I?xbH4NIym049uUx_Ws)f z>8HvOV*E*L(?1tTFH&CyPCDsd52R03&jRms(ti|4pRQg9rW;!;|2Kj3({PNxQujOQ z1%BJG{Y%s&VEz=h_fHL^&r%h@bQ^2a-w{YJm1T@NCw+AweXd#$e5I3qKLokB6Y0H9 z`VQdh9efq=ZU^58OgFE#JRbzU)xlgYv4KaV-EV==Tt%19HqeZRW#$-a`6&G2Zy2fk&2&#PzT6=NUW+*Pq1S3WI0h`U?EhUVy(cll~oCx8ZMu!N=N+ zM&9j*v!lVwfAJPtCy2EHwaHghwASwE+U(-REjwB?o`YBMLf?`jXhz}sMGP8h_#O*` zb{f9h!l0Rk@4GN4-gjUKBMryc!}nrny$8~=M$AS+rZm2D!;mSB@8U3IO5-~^44cwe zcZXq98f&FOw~S5!eb0rfSq7V{n?=mvy&kbh~WHi!2f2`ICVy;u$y1u4I_llUK5Sq^E z-jY0mF;7G1jumZNc?ul(9LpZqp6qB7!>8k3^t$OGuWjyeyOX2x6?oi>Ugon|=i0Mb zkK3Je!W*T2#>}B}{-aj90q(4~ZfM)u+R@g1)|T$!n_OsrmI2eAHPwwvm#k@8S=KOj z%{k|+s9jbKM@R4#I=Ca~5pymkM*iv5mcO>)iC*#XU)lH~;=K?it zK|73BPU^ci6-m%QBhi%r9@Sscu1d1{63tqbdk^Ar`bK#7CX4W4&JreJHgVnF9F^FO zaz64sb=Rb4)dwe3zU#B8(`HWT&sBTMutGCK*G1it)qib!q^Q7)4%D=(qKK#Np45D% znl^u+>%Q#=cHi5Z*xlUqlkGFQKHdG3?g;}-X+e$0_9bSH?vFf}+new0P9}DGW#2L? z?`p=zuC#jjjAoh+^ggC@%L%kxbf4Rf$)&%3?8d!u>=K`)3Kz6r{opQDGG2^%^t~{4 zn2|Nmel<}{X{uAk_i1#}0P)*#(`X`Usm?bMUf zGXIrg%S0a3ZS&^#aLeRKo3Uk*7&kb$5F=+I%FF&Q0?ifUkJ+kpKHGV!k!H*v21(Oq zKC!*pkmrHP4_@twxyYWY3ybn5c@vZ%PnDHLQdKDx&7IH=BaXJ`oWa&C{F9_stSNf+ag^*4?)|=CQ=(`{oo?uUjStSIMRD zT_`4QQ9L;j8VX6DMu46~kHZ87hDv!bzrb&KxjVA&(DJXV37C-zCrqf^KlRylYUYT( znvSt4H7mDoOoy78)0YJkx2g`+QCOB-8f{lI^ZKG!HpU~*M~h(^hcwmhAw_xcZdkv+ z_-07R?X$BSbobl!olM8mT>ohC?lt);x1ul^nYy|+Usd5MimOz4ZZgYT)_Z9Ap?Y02 z8~|y`h!whixqDgu?q|)s)QcIE^QA87EvbT8S^Z;r{wZ}=O{Aag6502t9r!Md$48Hj zjxHFTJ33lDTCZBcVgj~nFl(VDM%pqY%ZnPD44PErN~*T3h?j}sN9bR09X26L%hy?i z4KvbNYVkHNlck%pW{BoSBd|S$@(vcoP2sR3GGyKFlbr@>#&z}BtF9L{&FZn2Z5ewN z7ipr{M&S-tl-nf?pcpfvpCmgo*iMn1mUH!@57jF0zo>|C(MPoy?H#0xCIB>8L^B18 zMqKowI)P~8U|Yx|244{=RDz00-y^P`WZQ;S!>W`v^H^uhI-tP<#UD}kmz}mVjaf&P zDEi2D@mWl-#lk%4VzWcG+-Nc&KiT1$pck>IelI&zkkdf^cbOf|YGc+>qc!{~2Srdc zw`d}ToMuwADXJ{$`x{A-c?T)@Hj{#nn;fk4R?>@&83zh+8S&Xl^^js4{z_65;wn;T zRO}*!@assI88Z$P_9kL9+HTVISl}a_YRo!NxZ8-af_OXWbYs?W9?p*<#>(H_q^D^u z7#;|8AMyEEC?_q!0wn1gV_JoY=Rsm@`+lCZRH?rs#ZJznq)YUfI#^BD<{b4nM~LxQ zGSW1-uUM!+~bk*1BNx^`-;q%&^C;{vJ8>*)F_RE2X#1w zch%{Z8R2P__9;dvig2_-SvZzBEz~nY@#qgns5>NhEwwH-vM@~yN0vKY^QC}xyiPL$ zG0z;WK#te+12Dq~!~}J;0{KEo3xpKuXv}QG5$HDG3fp`$jV#QDM=Q&-vSu4um`R5t z%k7HFKt<;mftZSqRv`C}7W;D%MvSx^=IH7LNRbnfR0IW9wH0%)$&gdKtqW`9r7O#3 zso044%Dl)4kk;z%JBb=SFVy=%Ohc+?3Wb&gUBe{sqf2ZCJD!>DUE|=q+ zFJ%0=#&am*?;vi0GP#L=oP3CXju;;dJXV_gw6vfSHg~xxcR48exWi7mlkwGfagySN z{yx$wya-A00>8t=-%nbL7o3TI$i#Cun(ZFBu`IAPFBJP^=qY9#-+iX6H@#G>4`6wDsinf#w9Mm0I$*VJ9&uDm?h9v(Q!(8}m+w@BZkwXV7<2``9emlNy!>8|t?K0$j!vcq17vlRU1_U0} zLE%=!$QU&#FN2T$#B#_O1!cS4hd-C^Ao!ZWL_YRC1Np-Fo{NseR4^!n^SuLnHeY!L za7QM2d%)K)NSglYcFXssBM*a`4&qn|=g&YlkS$H3h-zNvQ2xCOg9%f|pzyDVapippe0_-He2>oy36#gZxvkrLMd-Be z;lpS`&o8UgiqJ#QgznWZAYT)DJWD=oO=v3RgcWfH={ygL_#dDIeLk8$-IdzUFfqG` zXQy8cY6F#=Z?piEz7sy;VA^Ef0nB@Kh^c$+B`AF-{2k~!{kWL=d;gm0g`)J#&mA3N za=eO*`;pLKlab#K{cGMI*T=E=adCZ|iosMu{gal!HIO^$mjF? z5Uv7#7x?+<&9l9!Upl`Qb%)*3U{J? z7SbZLN@>{BwMR)KDyWqXmDpk6AX|>4XnoY+wo4V)1 zd-CucB>LJD$2FUdYc^3ss8s71W!C5VpP<>q*TP?0v595acC7W9DD*IDP06J^gI23G zMR2}o$<9bgcArWV_9u20;7m|`ek5M{JUZ{LCZ0%s);q^rNMU5ucA*Rg$8`sz3{{%2Y#&71KJ# zqtW)a@d-1e??*)JR--&VtCB~TugJqCqch;iE` z3BF8g3b%j{RrJF{;A8u5D+qU3u`(HiP-dajoDcP{vvO30(iyOr1C;ShiFVC4p-R zU$6j_YYF=u%t7>ZV9L@VrjJ}Th-(Qi;`$|n$^VLfO?icKWa^_FKN4c<51=mQTEOE@ zdNwM@?NA+JYDBuSkT*uk=cb>G^l^ArEdSI1|2S0vJk3czBal8`)dRoNNpB3KPf#tu z>z(vXf%HkL2YA1eer+IqvicD4FP-$e0_juKgTQHn>6m&XknX7`fj@5NX|(S%f%Iba zL*M}?{gpuaG<6Wz^*i{-K>7@ohqk_0-luHAm>T1^J^L>KuL0N=chYAD(r2pEfq9mg z4)D7cNS`e};Tr5*1o>+N>2p*E@RyzRu0VR3x&}Du&sBQ-xcFwI?{Ly@15P>ko`Adx z89#3N=aBxY!_V>Q;`CT$d&Fh@+S+mw{YF53uKGa$=c!*hn4b=R2;pphZ0JwRu_0U> z!aT>$2Fj}q;dLS09>Uv0_^J>N8%)zU*aqhJ`4A2pME|ps&ac8}9nAX&9L)3s4rV%4 z5o{pN_s6#0LN9bM(^~gX#D1#~9xh-ww=^ z+W475{?7n60WULnKk$i=$JaU2`+&a!d5;?W6W|_kOvxHVve0e#O9_ z0Io6V3xVGS{%HoU0Gf5yGjhMOQ&5W25URd&o@}z`L?=Ydu?0au)VgeZ`fYj);DagZS&1+ukEaxFR&${ z`SwvSi)XaehM6=BpJ9f)q_vd;4bZifMj8@e9K5={rK@cNU{~7?nj)`m)n?J@%hj!L z2H4sT*M%F~x?o4G2leLGy7~6n+=wRtcH$;-OG~T1qGQ95hznNl=xS`c4AR=@chR-A z9t7vB4O?p0^B*30&kir-h=m(!ST{985co}XJ0SlM3Na1+98!L4c-sP8X#hfJFWX0L2rQ+<-=UUv+ zo!s1_eH2ojX~Ei-t*vd^Hr$DI8cbq4QKDp58_s*OxioYdPltn}cU+n@Y-m2(>B~K? z*Tm!dGROC2j_=DHX;Z=9g2J=omDbmuF;}>|VMl#*`&q|59sVtPIy9f0f9I`=0$;U?ED}Ls}H;hg1tiCchi5t_GP!q+v6_%y_5pk9lD=twJ%TF3eTt!E3 zvEm0$89k6tr)J8faSGVAV%$>=?!=ii^oJ?)H|SYPYTchqF{wWcDl2F)2DjrC96NtAW>gru52 ze;|A6Bse@=zjIQ}oW9~z*34Ob|Iw2*E73Qe4i9I-;o+vd%*qpxX znK}K@S&_c%S+D|!-K#3jzI#&gm7eI#Xn%1k3X9j)U2CU&xcb>q*>|6uT3f}``%`Ds ztms?6^NgB$IyQv;?Y6$?U5%Zvcg4RA$!xesDpFmuV%@{u2lIZ&50{q_D5B=>AlGO(A6G*PPH7y|cb^cQS8apeKS}^sEzyC_l{8ThZFNY%@iH;dE8d*QUPdFP>eRhr+I-~QpALUG!t^ULzyfc#vzYwvR3nN2&_2H+baDQ6+sd9f@ACb#v+!w{*U@yHXa4rm;@)++ zy$f-!gm&7(I*e6+h?I|%W*yd<9XhI?yv3b&7HKc zXDs_}fk=s~shGXaN~R`f7azKhY3vV6b-$pmqz*pCM*Wf`duu`Q>F6CR^&raW<`vEf z&S6bX>T5&ID+f<#b;i7skKHU|xv;pysTmxis%q0dGx|8Pb*rRD8L!G@ycMa@Ll0_qb1;GA@j@XtKR z75A0l`;Kr}LLabJ$U^8ckMEgt^@q>nfV3(dj=r~e0AwttVlE$$0+FTi-% zgxt!g%J@HSin&7cHFr6Os!>Ay1RJJ}DMYC4gcvmD>kgPn8n^WRtbt zD3`$MLUb4qIg;sEy%pt>vy6We@KMo%))`{_h0S15GHF+MZV_sYBh2&ksxX(Hr!)Q% z@pY(Fm2rfLbgueR_*~L;x}03PrlJ6Mn7L|9jf2xkTaA`5(yNJ)zL>PZY?h-P>WJ4H zgCy{+A_m{Nq~Kdax>|fiN+qc2%##A%O^SMP)t!zcn@CZqX3~w~>rl##OVOl3RfLJF z=2Z3FMvB5DNl(R*qomE|1O=q`5Z9O!6qXoAm?-SEj9+R_P$+_-CUFanU?qJg3hk%5^L0RO1+PgK>merPQ5_NBUi)XzaU5@yy*z+L%5u;nT$6dyo{B|19Zg#xW)u zVJ|Vt`$bYT@|Q@LE3J`Tf}K&~wdUjm)Mr02%Kvpz@O_i?Y^DB@6dUK?BE3kde5%I7lIHBq`*KCWV}Fr1cn*qz&UIaZH%zInX!h9}lT5p3Y*3cSI&9^x*G z9x#U=j4<-?m=CAeczXPRo`d}KSuP#sEEjCJ$;?zZJkgji{D51jLFT(j8)rm!j z(HE#EwV})n;V2Ua6DZ?u}+Sa<@Pwi}{IE>Q z>YQD&p~akCf`Ka~KJDm*bK~0iV!^>E?>53`8sT{F4CeuP`;jr*2*wNQ*b2s@Bh7&~ z)^G&l5%9yK;pXUyUSQe-qgtfnJvJQa@{MNXZw^b}DUZqmBN^h4PVtr_JHz=Jcs0p6 z4U#p$4T++M`f4%Dty-B)lB{gr03u@O}Y%PV}r{K7N?92cvBOv#^<9+7w3%Nr!ouA zq39w-`L8wf%cPM16H??yeOjJ_F%F*sq_asE4UdrGv*IaIn)^1P2`VwQ&#?M{U+jx#EHMOWb9 zGsZ*yM@b?7cJV&||-YZBU*Q%F8$=n7U4nl=B+0bXc@#8b6$ z6MssKAwJFg1S~Onx0pF0T0YJ3Z6u%8@^ZtN!Do#a^2#)f2}PzKj2U^aN}c-z{+6z;S1l9>n5|H{|Vg4i^2+Uuo;&(^uq{a|rqTsTC& zt?;P2(R=Xc^8EsQyD`Yg zCu7#|h4a1C8(O|kfY0VDWBf4kz5~7nq=iGc9+QjG@+g;q^$3@5Hu%n#)Zjm1d6zr# zqpW#Ai1|6bw9n{otsw}7wSq`M^Czt1`H zyd%hab%^DgiwVru7fmD~Q+?kBzM-@qy~|m7xIC=9k0Nm>f@P<$Bpd_OL(m(&fW$HfP6O&%TMA%msSYCjUbYEmihTmCi2^;q=--~m4_u9vzE zrpLu!;`)G-{-6Fe?>|YFsu%kW5LYMo*G!+NCIh$oadBx67f(mpW+#1)f6e<(miBPd z&qDf6pC_*B{A==`qRs=}?Z?H{#r`$ZPgPrhf9c1eJpMJ)i_{Ik*z+kH;WT;G=%jx&kbau_XW(`xoon4T(8J=7f$w$F(`9A(W~u*1I?ut>A+BQn zHPcJgiNN3YwsS4!#`tdI$Fcb3Mn_|GmHuIrziCPdNB);BPtjQ^3zT_+j8z9sDKW zHy!*nU>kV2QgA-bRegcGE}3_7%aXZgqJ$_kB&V4uFCQIO0Q*% z4dLPto*BZYhwzdRZV2Hf2aiVn^d@No%fmH38;E;D`2V(d{lQUOb$ssjSAW)!C zdl#T2r9eV*Z7HQwl{nbv>QDvr*W zDUQ>D{-K6Wty9N3P)D(&)kdrR5Bz+-@4da3y$jwkgVS-?A$<1x-giIy-rKjkZ};A3 zzt8&YwAfOW|7BnPk9_u7pZ%uKrWlLMO8haR=3ijHiuDToF+%3QVe=BndmwEJz}~}p zkGAK)<~5zq)Xbj``}3Av4f`1KIFw=j{je`$ont53?CWc>&i&J7-;QJZ`P%M>J%;1? zq_!y-dlbj?q_+3LK8yS^Z6Aky3O0t5!gmTbj~SB0{yyx#gCD~=v0sBtk>`EdehcmW$GYLL*6chpZy0p$g-oG=KeiD&5- zm3h%a5lzz~tTjP5{XsxY&`p03P!n|19|Y9fuTNCw?bjzN^Y%MlM3)Zs=?emC_Ujjw znf>}jWoEw=m09(Tn*A~+sGV-=>$Pz95TPQ>^CG8Gl4p~cLVB(0Y4d6gzo*Lc!lrt9 zyjoKiPl@M+O7%2&b*B7vMt$eCSe?<`)tO?{8O5C!61C1~?dnYXc$zw|Wuk^TYRVin z%u&M}HOx^{=BQzgf_c0)FP}iFlwhgosXFdya`P^Ut?AR}L4oH|Gw0LBt=-uV;hh($ z6zkN}`6Y9B+;p?W0`)$ICps%?*0PGOn2ShzhzBZytgEWuwn}tR2>9qa>>0_{juf=6 z8~c>#?>cA*CsY$ADan)X{K*>Hw|z&S+rNbcj6c44`z~ErXdxL-N5FJgVHt|jdsx8-ft!B?(_6~bm&BET*=L{ORvdp zNZoEo-L6rxC9x@Qe1h=CCkX#9K0#<+lzt4fZr3Nos;S@vpCc@Ta)tBa@rLDmuc!nz z44&(y4u>iAI^_^joUKezN{bDHp$$|LI8{ZX`|y9^D02g&fpFP~gFlN^6g5uRV)ary zRxc&Ap=@OC>AB9Fd4Xe#=l!9_Id-Laj%bN6cfw{vzJ+#sBKWM=dY2-44J4H{zm*3eS=q=*w1tGasT1+|4qr%$!s zT5Vyt)D}v`R5Mcli8+JtqrM;<}ODN+=;f;sm55MCEkFSkgchB zo7=g*qbudMcC^^GabcR<-qx0KTiTOx6k=_%F%^p^)dsK=ZC$BkysaVC7GKwuYL2hh zX|1t!saRK6ytSh%$+FXrb>seJXF9Db(Hd{>?vnhLc+xe#E%DVc7i8RS&DvBOGZaTM z$-QvBy?vFmQFk)l$x=2ZI^}m5ej}jL#zRoK!#CU7I5J%fwSNS8b@ZAlhF8vX4mRNXvs@((m=fhJ zeD7#a=*R0ePW|E(M_GV)TPJfzk%f18`qPnkzsOgNoR3pVd_=vXXjgQt7zl>BhOU+zPOYK-ep8=A0-Z| zSB&IYPJ5b;|N12r8-VW*>zV#JJskr6jkHl1ocwsFil0G`^!51>t_8k zWxtO9I-p+B^5cjp`aLE>D5(crC8#T0)9R%I>YHCw3GHAywnI_HZzmB`0(TJ)Y4sBP z_)3<3sDk+IC8DwR5y5wm2oe-g(y^&*|11&dM~Lv}PeOElo{040L^Sf(h~W7K5%qbI zhBTa^jF%4wVDaX?=79rpLnTS;*IEk7=MA}XpV?U@z{p|z!exCG@> zK$OK>6lq#^ghGxCJ^ z_G>3*fij81ni!YQd`fI)M6%d8)=s%!&4jZ;3XIF=wesR{XY!(_2`?_6`S98;%wN(n z8{$q)jO%Vb#P(SL3UwBMKnjU#b3R=5>5r2Ug*2x>I)xD8;+_woeFpINK>K2fE1^*0 zzK{>4eWpGsl(u+li6+I(Bp*_{5l@0tx;*}q0^-J#50~AD>_O>91e*}z&Xo_LUAUkr z+)B-byId@a#JoTK&nrn51ro1Q#akUGtZ|vfKH?*4h(kQ6?UTTg=};8W-l7E0#ltG1 zCwX{Fr~NJw+x>%x^vgsH0g3|(DFh}@C2jDmBw{CUGYs*%G&7h(pAc^QXiC3}LkWOKo$uQ}JUMS`e}S%S7-L zqUFg`Oa#w#V1F-u)h2F0xtR{XB}Dku5#jeB^WleQ2N9~bFde-7j57D%N5ua25V1XH z7jgUjL~MTo*x!et9dRROnlK$hqTgziNW!T1huRk97V0m`Eg)yxus!&RY$9jR5Z7t! z*T@-CB@d##i1ipc5@R^7#8ntN5?vLMxTFEXciM3b5s8gB?!?t-S7H;|m6$+3Ag)2V ziOm=i5?e51h}epmGQ>9Y6Jk4*QN#`m{fG}^<_xh@eP*~M2?0CpE)4aE-KaP5lbBIM zTni-?aUI&a5V#&d{1iqr#82btgm^!W8?bnn`uuS5ZZ*S;{fINWf{&{iUBMwWlPkCb z$CK&E7v&K(M~qDDEz}(;0g_<$|8Rsvg@h8y=n9M|gBB*;tS8~#qMy#n^wZfiJ;@fQ z23%zpMF|o26Krz*gh{pfX%DBK+`4e;@dD0SAQ)T7BO1mU@`#2ZfsD2>L=X)>?&R{Q z7AB$#MTqD^6+~A*9X6;5ES%ZCfa&N$cM{Qs7822gDv9VqRYY{5yNKvQi-;|1!VG7g z<619|dP|7tLbzUwLIu}v`H)2o5nX5*5nTvXlMh?e5z&QEMR_#5hlnnOs>xUIe4F%;P3AP z_ZA;kC*=DZGMjY14gTYC4=$W#a0ud0?p?rak-aP@|^YC-WQ;Fs0`;EmX_x=g^ zF2OIJ1K-^kh?x4y*kJ;`mGH}@{q|UVGWM8&?-2ZQX}{MkzNoHGw&VMDj^&$yPG{;X zV;^0<)4&2tShfIu7;a@OuOY?0zYW7Lj175y6lrgk?^pN>Xq)gH26QVd+pNBW6`SuD O@H>YM$!Gk@SNtFKFbDYn literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar new file mode 100644 index 0000000000000000000000000000000000000000..33ec662464ab34a1a32e63535168c82695517963 GIT binary patch literal 45796 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 0000000000000000000000000000000000000000..be4fc74df19b07087e504553274075539d203504 GIT binary patch literal 15508 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 Xij@l_an$Iiq&$BD9nvZdXo>q@zr<9I literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 0000000000000000000000000000000000000000..c11e06b141d9fa5dfb02611404f9f718e8cec087 GIT binary patch literal 454916 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Ν7dZmhw_a>vzUAA2GwsQU3d*Anjw#O9 zieq1z^Qhw3m$vO7*_Zyf2(|yp>su_$zI0ar=j(Qu1VvPVs)K$;!8EcjT^+ztRc0`Y zn|*1R%=wOe+qpjS`o=RH%()41&BZALy#&e%6*ILswIJ{ou$OCK3zjWKbi^|7INJbhxApRqmWbboapi~GT3 zEWWt=iM>P2QTK*d)BNg)eOwxrRnM($#5OPg|LxXVg>H9hQM?A4!hSnF6Y0OgyV>wW^ehe}E{4hR zdK}yL@^iqQIrL{QM21#Uk#VBK?f3o#cq@biKaBTZA^Q4pj^v4I+VO1YfD-o8Fl46l z!G7U2_@S%jy9e;hNCGj8aWcPr=CtBx^PWMV^eY*U@OYhU-t!g@{XU=P_CH^?c)aGK z&*i;l@kZ;<79kOmKAhs~bNjO;;C%#gaZ=81fA&k@eNluU%OQQ_D=p_Q3+d1HboF9% zsCTXGwtuAlY|XryocG$l7teb*f4;Z`dm%?l*GbeL-#yXl~9nGq7517$<0t5C@^Qt^^Z#e@^R{d08XfCgPHzGSnqcW(!(UNOxdr# z-e8s?=cv04=EY*aTI}IjX8aaxLx7(bXq&tJ=xlS$jF1=DQvVYkV5jMhdM<>A?%R;Iih)&>MrN{X7 z%eT-3G|I=mjJ@Y0z`lfb0DA6_+LulT1TNbNUVDS2!Hvk6eqm<5x{uGk#|iF;|Tu7(3v`)IceiE0%9UwAN!UDY*^ z`AFfB#!cqVop*s}2yo=R_qNsR2>o%BJJk+tD}NVeZf^$VuwF2?rw6RayQkE8~m*Gg7c~WI^(xeQhP*dhn8(!kNGSAuZ+?9Nadt zpsKF={@XfliItVDuh^ID$bacp)n3)Xk(bwNzE+r|kM`Dq3B!@(_VligY#+XVB!Bqh zBXv*LgUj z?a7zo#Sx@`*MINssQ<{!ruy6Jdh)k>dke-?@<8mB!ssc<=tyMzq}IDeDvEJ*2L0D( z7VVFewUrFxIG!v{tK^dO&U7+yAbs-nm5C+S7nWDIEm+~q_@#Fdg`)iIK&-;EPW{CC|KNdwv$6AYqJx(j*XjJZ`m9DT4a_w^wcoEQ-A3B;n=K_{ZYNA;<)YKd?_+Xy|h)A?p-4b ziX*5av6-H9@vG^2eWcf7Bz8RUQgpI<=@xRkQDaoJGVefZPlmCpcW}m@eXV*QzbJNR zjCOo@B&IrghBtm?1olY(kG*#RjH|fM#b+OqRx8O`OE!MV@=BILeqc++HiD3#=UTF5 zENt_3;+15<%JO3^%ODX0@(W~Qz$GLh4Q)+Ia!Et(H4e0-wQE6XOGqx)CP^FGq&01l zCLz7G+ay&|Zux)ToSCz8Mq0DTCQbkG*sD3;%y)kCJagvpJ2MY|X(TA3i5C+IoU7=B z(0ridp}~?v^}%nSekk&6N8o&(V0o zHxzxCr6DqsA3fN9ux@(%q22Z0J`svNa5M)c=9K1!AB)iCC)*Dm?!Gz}Y7}R&87+HD815I9 z&!2SAgF{Acc07vQ^kJt<$IlntGjgT)>d?gfZ3%2G!jh6DFuJt-IKR`mC&gmj^0n+n zy>se9c5_zC?s#@fU3+$muOquf)+Mv?;|^eE@}{+l@+q;yyK0_oD|zYY zq$R<5BeGp6KV6yVPJA&Djkm{tKi*dIgLrh04`*vKPr8T1tfBhw-=MscYgj@efWHCp zrYv(=ZVO6JL?4u=XGT+JXa-{8<_%|r4>d5l*lCBV*ba$ka`~Wag?8UxhgQh9Gr4>{ z;u>ffeoMHmf|Jg}XKQ_-xfLgP4}JYDy47&~{h@gUujj0gzHCu`7LPww6FkXKAFSsS z!+V((fmi|KaxJJT?uRm|CYBqz4|%=X;XKhDbLlNJ3k z>(mSN(Nkp!U-Z;S{vh)5Pe3Bwx8p#%DSL1fO`U8aHw6LFVPsE0oCrbXD zt@`D!e@sVY-27C*HfM_ zd(C1oKX@V=uH{2z4_3;ruBOTyMjh?XS~1w~e`~j|wc3Y0K}GbHq?7wHUzR_4wpQ#r zG7H~*A*Q*Z%8C;~#{U7dSdn(8Y@PB`?rgpIJUFaitnOhkclpVd(%fKfe%<|5r+kUm zhPHk=c7I*sxsfGX-5K2QDcKpapMj`K^(PD6ZzyerF!uAmwXHcH=r& zHZ8e##CK@#h<|YPkEfQsku2R_9lm9IAQmdWUcE=eZIV=k}uRxJcV)} z^p?B-Q#dO(?zEx~^B>*}1CAFchN zSY*Wafdl+|+ukF-{`!9I@%!M>-6fHkyPI-O29C^))$pCYT9mWI{Xg$ZIXJseV%W(B--xy=(n3VJ^3`>;i)&A z6IbUA_hsZ8^6U}$cQx}ZjQlvW8#_DilzB3TxiagQgCj%zugV<4^)EsLD+cI}oH{f# z@T$Cq`+tP)Zn;~$HL~XB;5=z3gy+!T5okHGV@;<%)y)2FiR|C{3;iekL-kFw z(Xw9}nN(%FPf6pRH_H8XDW~&PP_&=)$L?zuWdd)4WmP+#4J1BZpLePu@tOWVL7RDK zSw<=LX@R9B0?+;?_;7T!JL6A0&uXKPD_k6yDhREc-toSCQhqi)nzJ$-*-Pas;k z^GnbA-g*H2@ju6&*`FJ!9Q@qKyd(a{pWgquk%fmpH&S)z^ibk{e{}x{W=|FCXmx8d`FB{fqFx$^l+~^5}yDUz1m0jD%5+dat#4U-By7Z1eu!d9yv@ zkK%nO^!qTHs2w^||2S&L?fah^S#ap7k%fcN#PCr3{-;K&u&Ffax79a2EK?knDb_8X z6F;^beBTY84$iyRoAwbt-zsIlcv|*Bs$YNQt1gt#wn)K zKX)qn*WWm$$1jsk=9EqA{cvxv?9;t}*Si;Q`qg;5+_Gcu$b>_ye>|=1jU6F;9qo)$ z0!N&*`^xxKv2|kG0pBd}R!ovCuXB`zV9@ zSc_^e>ErajTC0qAdR?Fl{h~-+BKzU}4+mp~?kLU~S#cznEk|-i?>dtEWU|T_$>|)* zYR2bmLrfjwC;QA!o6o<==lzL2N5q`JN^CDj*+=UW!PukhPeu2zzDH5pBV+g4oZi&u z(3?7faSQux)0_9~5@@6M++B3WUl>3u;q)KT-bB&fTp%Ca8^t0M#>2kYl-B)6MD(+} zu9mF=dgPTO-^hYX)$w_Wp2W9CLc`_p&iKo)YfIi7)ho~Y8-X-pFFaZE&3<_n>Qxm| zB}6U8qW%_+McH?DN{(&;&-m1F=jbv!HYrx9zBtHI<6}PEzFB7WE z!2uO>HL`yI|AVgCILuY|-O{IZj(N>8djF|s5A&WtZSoExS+H<3Hw*ar|7 zUg4J~c$HU~7^ENU;UN(&IL+&Hzbj(&sR>_}j3?{(j4z*1E?a;T%=4UBDRR9)ovsj2 zxsGQ?WS4OkqDb~(nbV{Du)d@yt4r=r&JDkq3~nzA*I^dK`|NN|WAwAby73#NQ-f){ zMefwyMU|S1Dm52XYA&kOTtJl?vwb<2MooGxlnS=U%4~#PSA5UDzi&$o_S{@3TV;BWePWu^hd zMWyqV5jm%f%<_kevFYP6R{4eULs*S77iSloQ$}X_aqhHaCWB>muC!#LRaN;eGSbx- zGe4G%Q^r)>r_DTE7~dP6GhON86xG6DGfsxQTQWI7Ae~(E+2w+HeeuA)oc-DNXFU)c z3LL;Q+)#Yyj^crF#hLl9%@JH!-*frb=`Bs*cdoKd7kAcGZI0ohzPNv1Xn)TA*$-q5 z1rG!sMC|=~Ym=|O`r5d{F!N`t4CC&7+55BZ4?YkWg8Usi3FC>sDf`aRvhO+{*_(C7 zzc1Lvi2oaB+Wq-U|7*N&dY@{=JTWRq)8U`aJ27w^n*O^k#Y8D*xV8+&`Z5 zziq@ZftCLH;=A_c?hoCc^Fa1c)`8%IfsY}FR}}Xlz`GjV*nI7^hCCcrau?ce`4{oV zb%XrtUu`(m@!GhpK5vsl`h98LAphPW|2nrd;@S+SJ})MHd-yjcs44G0I5eaj5Fv); zb-BxOfw1Dcnv9#qSLe;P2|9M;s?#hhZ9b2SQP2E};yY0@2I}*6%D+wHeEu_!Yi93+ z5aK$XdN!mJ3;S(63r)qIXSkubA2kez->i~wmVngyQ9gYCA^wCKz9 zdHep>-zegz4c`;SyT4z??X~fhdsGXBy}~OOMb=)t%kVcYAEus}GSmnEn1QKnGz83I zcZ^SX{r%FP$#9I{@()P=xb}u-llT6h^k+47OwjVrlK!bzYnJ7oE&bV)I40Zj&yoIY zCLEJv`G>6gLzaK8^k>uTm|V+0EdBWyJ0@)T=Slxm*Cx;M&zJrYeLFhu-ux+${;5Z> z!1A9U{ZmcK1k1lr`Y&_k7h3)i3s01Mb{!ov(ef{n{*BrjUtxRWTWp0_Z23=;{;B+& zWcg2){_Ns7X0qjfiS*}d&M}u*{!^s?lA!jVBK@ziu=eGSLag5$@;PRzC2yMaPu1^f zmj84M&yf60S{%+F^5##8^xx?EmstKYrGKhE%(VPVr9X#;jw!YLXG#Af+FQ)B{G%2w zlYDlC9aARus^_2k(g(zBku=%^et&U`2m3{f2M5G54~ABj2WN>19-J-y6Z){)@OzIR zdvHj6*MoD#*F88a{=|dx#21Fs!?Ybsqnj zqTYi`#X=9BC8m3DR0KS@Ox*20OH9<+cQzQiPKkUIv#pgYEnK{+Ec~SD0*%Pj#EZ zyr17wtyDNJaX{24TrP1?lq*~zah8ZE%sxbsACXs>eFmP__7jyJ$3G;fzt8ZQKAzY1 zn!@Y@6#2vAxWatr^Sria6lR-V4BKDt ze0M~7d>+DogfjwYKO+R|b1CHZD;|dr{y&6%C;h==ycu2%?dP3y@JbQxdf-xo6NgRt zLHa{J`IN_S+;DM!le$hQ2Hp^uaZN#@++0DwG>8Jax%GUB5fq6e3a}oXn^}QwV zROOzaJMslll=*QQHq-x0V%W=&AL0LrAtG($+eeiB+q4m$Y^Ndb8DQqeX5NQ*GJN{$ za(Eh;@mL1C^eaM~ra!`!;Xv*r%0qdSE4f=?Gako?adXlS8}ZM^`!@V}A@pQLa;{SjZ54|$g=`?qN$ zT>KZM2=@qV<~M>8euO)L{m&6h@+?{2LVBuJBrgQFzk7U120%;tqv(D%`2?oeE=<9~u5#3g4t~zrwdD zJfQH63g4~p%?e|#PKLKq;av)^P#Ei_(!WLF`xI_fcu?V(!n+l2P}kk z;N$3>z1@BKlu~3u1D)Htx_TkU2orI3a}4>B#>aM6Wr8%=KJ^2TzqStt&y49KV=<7u_pxe^lCLW?EADx07m#G&I39Jg^8__)*|?@_6CNNstm$_vSzC{E zanD?ZZv(dykOx6-*wVG76Z`pL`@ePFTe^DJ_H9cVpuHCyx=uK`|xRK}ZZn(X-eM?uxRcW``ziMf^Eex+(oX)4_ zs<%vqc^a~7w~oW*G~XK~uh8RxbhX*Tn$uKKk) zasm(g=#E17LglR6RJl*5<%Xt4@;se`l#6^nr=Zhh8QAF%NQcy$!P^w^b| zfv(X!p2KXG$4}r<<+4)puCREV7o9W)Z<@v9d}?$I9yY`9gxdz*Sn2q_#oGlQ$DZ2g zbi8Kqxb8GhlVBrS(mZGJz6ah|`SQCKZ+*6R-x3|}0~YTo@WzUtxlbA+avHo6Cra|K zmUpuy?``moz)c&?tF?IC&-WQkf~|RTEFRB);oP}4nm5tn4P!zkqDind@8`H?bPz3R zPJ%b6u4!rBw{UIp+6o;t4o%hNF>LXk01wk6uF>+CHd9_cBA0Mksc=7S@%q3UtDa)Y z!6T37El(Xo9;SXgyu;wVFa{4(Hy+;26EQbv@N{}>EZ(G|vFqP;s{PX<4uYrif^Pb{ z1w0fz*0vpU2t2MWX`^|ymOS!qG3o*HmgX}2^fmF1rewB{brUkLkvAx#W!Ul#fQM;0 z*QDcpH$!=4(=rRUD?{EFGUWYphP>+OnZ<8shP|@TJ~V3a40!F}ZOnl8=ip@$ZrRMtc=v$!R0iRem13@5S5ENtrJa8_%*w2MKMkJQ zUZs=gi)JRTDMQ`?@P5`vtIcz;2?f@Rfsb1@XB?~u|-aLV{lqaIo zzsl){k;mp-^ZpgU2Jae+w_tH99hVrqGK<#=-Vr4aT^Tpr0*m)Hc)A`iA9eix71w6I1g}WdD|7)| z-YJW>06bkDcon<6V-~LwJRL4xu`cgvi`NRC&S$(5UEU`w-g-kGUUe=HOLU%eY&3Xy z)w#SoEZ%1DYT(B5#VgF^t+seifft1vd9-!@Ey1;!e=mbq2{-b}3?7GaMy z2k&izcj-BJ`G|;?$9K4npB-+A!DBqr@fH}ox#!?rWAHd0O((C_;LSe=Z@t0ecsZTC z%?9uCbMSTR44&E~c5089WdB+SM9?`VCuNyp6iL|`$7(862 z<^9CqEj}jbMQ(G9-q5(<-5S(U3CuLH3skMbMRUX-UrUXTW|2L zIR|gE!TaDjc)JYVht9z}Xz;E*2k!}kS9=cLGX}5j9K2%&ul^jouN%CEbMU@n@EXs- z`-#D8GI)IFu%D;R+u(h~aPTRQiLec4aVsjxo9uuoqj|K!OKSHIATydZfUS9$Hhxd% z8eO@#YDrX@ci*3P*CZLByFYKWSSY3?bHleJC(isd>^G9rw@<_lf{$+(;csuB${o2* zgqw3)eDS(?E_Uq9ZFw>7Yp-h$Vb@L{_D!mYSEie1&{vWAbqk@$+C$J~*H;TB64EE>oy%i`s za5Qh`z7qnfWO&=lTLzWitZ6i`=Z{;5G-z4cE{0-bCCvvgSB;XR6Ivm5BW)F|?f5bGy0Q z9Iv|NRn2jEr`!dLY2t1;&Yq>YE91{{FUjQbzwH+Dxz}cSY%XHJ9e$@S{|wxIev11y z(IlUrfIWsM$0kGtC1FQ0@_l8#-dHbAJnj|cFZIq1XYHul5lqewHzdQe_aDTHw&BLKdy4`-#?dW03e%LD;TM@c2&> zVGo`x&gh$A`|w4^UwQBp&w8*AvxA@Y_)o*BBq`$)g{eUqoPC%*_+6xjK{8o>%nS^9 zaF*ES!P(*?3bT&*G5g-CFzbXLvyPi!)37`z;@iEiEB`1kzeRjWVb*DWi};+vtiwFp zjo)@MK5QKL?ch9xS%>)T;1q@V;PczTTVQL$Z^Jl;s10$g2C#`aFQg4|nFg?lIq$0t zu~8hN9GLT@r5N{?)2?yS>Br>S0$`laAsY=pGDGGECg(sAet2?T!;i_ZTH2UAV|vNo z47(JQBZm~`+)NmgKJtF}BS=w-NtO`ZG0CId*;s|)9-}|vBf~+a%WyC$Eion$C7!A< zCR-&&BBg&+;SzRi)-A{ z*mdWcZJWE4in^tfegRMF`~RW3@vqS-f|wUzDW@I`S$nLHC#0MEKuF|y7_^J~AV`Pv zt+7%E)qRpAN@>WtPtg0Mm8ym@b!?L4cOt@vhFCN#URYfvvT#UcUswO-tF92);ha^u z{)xUK|0Mqu-&Ef;-*jIoP6Q|f8DC@wAE!Et%ohUixy;M(B%SXv8n)e0UMR!1o#qem zGkNQP8|k48-w8BN;b-z52S(HC8qK>DB$M|H7&xJJ{ZGTs7;kHFsH+;AAKd-o|+ByC+`tIwCZ5)6J;jS+hqokA1 z^F)pUtZ8vYi)TY5j~7R$_I{+-AAP)6M8DlzvLhP4c?VC9N!DhUJEuzEnQrkl54AgM zg%o<``J$1~>Z}-60k1vCzlD2`TrXD%cON}e5}x^3Q}9I5g3#RTlcIcDtWvJu1&*9K z&NH-XfBw`J-_0M-Slyy~ct3w}K01{qo@3IC*7w z-@x!d@GTJ)6@y@eYI*L^mqx<1e_B7`^#|)KPh`&vf8*%SnzucE;@HoAd0+7LaHann zM}ViiQR=3Y=LDTOUW~JJkXD?f^POH_*|Z(&cVw5(bx+SZb9@t41LaEVJ7hDZzmex! zY-x9@t6c`U<;w+WY_)o?V?= ziu=!-oXCK%xe#<`~ zZZz)ax<$-`{bGR!2gL7dQPMv9&H)4Cr0G=W2JSwLdT;Xh=ZJ-nN0H1(obxN!8Hib6 zoM-2lnwW9sJbNQ-Z8)!el?Jehso$s#_f+FpPn%5U#o3?7f~8y_Ek#F;;bQt-bu;ymBj>8B z)RrQRTLAd&x)UzG(oeVjMcNG>((dn2{p+?J!kA?uX9|t-kl5KdB~=y`8%0H*Sk$qz zd-KK}i|*R7sJ`_)UaRs$_AO2q?Z4n#_D!hTd~WdwNW(^x&$Koi|I^%vpUK+{jK|0| z9P`oexiNXWfZ1kfqvaif19{qP1kf_*rmr8swaH5WY~V*d%4k2fANrbJe~AR$tT?o^ zpUsHfl8jIvPjhCc7r!iFKljk&+_3uuW4ds{PT+8H> z{l4w(I90N4d)dJ5?N9Qo%k57N_mP`u`8d|Lgi6EeX68oc)=jB{QGI8L-8b!IM7d z%K9oMob;Xc&(A*T==+NDcB#W0>33!d_8kq%94N#50B0MJ8?NT^Z{S&ystR5la$g*B zpGV&ydU?wQ>1OQMlDq(-x;htiZ|&T?b7R+e3cG8^<(=DlyB6)ZYthcW?#&lY+Fd(t zUvx*;)~?>}&I>ElO?Ts})r~i_Hf?BW{2-p~Ezqjy?ilFn+R&M3@7)2Hj^6IB+c#|N zZogyewjF)lopkHP7Kw;aU-W{MC0=l{%jmQ);~Q~Ts&@u0F1#5Urnf0A(8j!0XY5@C z|FN}9Gan77moe6viO!jlQG~0_ATEqJ?#g6VAd~Y8(T8}CT9;1Tc%L?x=nJp?3*B*n zGspWsH!yoO{{}qh-r^Hpf4_wTlAj7TVEG57Kl@*f30nSH(w{}`m@M&sReUf+M!zaY zykW$T^9g1jEPx*FvmXC|_^by9J!cjK1Ul%3KhLE2nF^WV`4HaUDoo191R^maB{BNL5@T^t zVr~|2KJz4N*>O)dO(H$Lvn0~V-0jYtQ!#x~+tYeR^5?mMEZSkO_7fbesg-l@3)`A@ z;-z8h?H6$3CGFOp)oHi(#AFSV$I`$I(XW}x*%)<1PSd37M+%yCW0b42$Kj|t@jhvV z?T~}g|AHAFAs)wLiRR5S$1?=14ae*>d+;-P$AHb(8=5(368LNKz6s2^3~jW$8{lB_ zz6U%Ok8Oy_`zdf7KW((UKZ65#+Hl_u?MF9#{inEQJBaxLX{Zy=c2pb9dmav^Jn}xA z!Q9gGm^g`RVTO#$jB9#N#>7b@FO<oR0;*C3PH z;6S|`&et$sSU!*8hv^#E9K@VVB@m}S7&r2mzxU#2@}2{a?&L8X&D&`4ju||bk>*`* z@m>ax@u56&G;fK;`zCl%xRJ-=)4bWZHskkGLmu7J@q&0S>Tq#OTHYjshs(6Q3WLY@ zbh>bt7(Bj8HP4<)YXt8b@YhDy7ke&k3Ie;%C~(cAjeJk)`@4{F%^JYgJPaGVH?(*5 zsj0MgolCnCAIxVumv+)=SX_OUMfjrO(8&C#n8$f6Q9g+4ul75$NSvb*oAP7gY}6Mi zk0&_OHuCHzM&?I?<$FL31GSnf{f%vj;xb+d1&HUTpU@5ZZBgpn1pXfkWGe5|!;k2cF(D z^wFnx+OuR#V{>BereH?-U5(45$Nq-`X$=;e_q(LF;?jm(Jd8R)pHexUQ7-);z;8XWlS zJ%<`XC&STKl7Z+@GOF}@s*Z}d4BH^pDekSM9bX|jRYgiL4N7KIEwH2MM6my$CJ+&;A{NBd)n{Yln_7m1){OC zO)ORCt9%jNhuqGOKAoH!i@LLk+|8gMR(ns`eZE>Jjt+Z*#pAdBlumhNn;t_9LW7Tu zREfx$VBw?_{-`fnw&|6-%I`US@1FXa6A^^GdnAemgkc^=j6$`MGrq#rXF|ThlM`1w zIx-wx{A@>0QUCO3BWL`Dk&`*6H=M~9WG9c)#eWjl5ncxir=AE$&z`bl&fKYD9lqx$ z_wGM(7@-DZEs64&lOHdijra=Q3JS*e6RCKX`N}?lxNnl_$a3@eH)t*u&CjA#6LfJZ z_2N|O#i`Vb+DjL3D%I1#jBh3tFAmpi#g#Ej*_X*IWxDV5*-g}jJ*6uA#-4>uKZ80| z3xGWjzq;c4c$)pLHO2RhOCE;++Hg6$uJ|73`~HUFyKe~>-&2>jLjG+jzGqzWqgpuZ z8>ReR`-1xe_xm6ACC(==&3JFJ<*R&YEbhPU0_4RZZ=C&2 zDl^7YC!$7NIgB#u>rLmA$EIB7w;}g>E!POzxoqX&PZ`dUb06@O@d+>Xix~V_fR4dA z*B*XA`tu=lOu+IFS~yGcS&v3+GCCEG)<5TK-|Nz=$vB*r$0gzGnAe z%=sH*w*W?if9Jtjg6BMF6Ts}w^B$Zdp7P+3c-Vt;#oZnp7H9RqPYONzj`!T+LhIb( zh;?r9M9&%k_a4}0$m8Av-gAp5S?3l{w$3fSM1(x|7l?n+iG}UMXn!H{ixf7Hoa3LN zFzX2C`1Sc4tP`B${~6LtJ{uR#@t;UCkgTix%d5$#iX9X|v zhr}U;S?1h3V3)%65{Jc`u(jbD!Rs2pCVt7ne`w+VVd2Lu{96`2U|{N0Qa4E(hBu%A zZ2E68F#R`Jc%6l>wJ`HV8{U7J2C#`)F4_ zI?r>NGp`d~r zt>`4WU+uhP89t^%L>PM{RKO<2bf1)WP+^ug?`QhL5GupFLY+HWt=2?lt2GfM5>(-b zFu6v8#7c}k3?#JXPT`g%L@~M}0lBXGMF9eD_oC+zVl z-6Cil;n>@USjuAo1s%3D^&?d{*O35U>SEeTg{YEXY`U_vWsR+L0Lpf2LSv6Og;U zgljC!@NfI(&b8G7@{>HxkOvZONn-KHb3UO7H}~=g!up-JI|oWNZo!?ZESXOd%N;2g zU-wACzLt&Ht|84)XYXAZ_`mI8Z@)%MVJLj-QS4r*-OR_(aCII**Fn`Q7u%1X$3s7M zqa69jr5x4c<~pPvwUm>2;2P`P1=OcT2BfBp{!7-{Cg3H<_Z;6DG<@gqJ)sR=d(!+n z{+hg2;H2Xv|8nl1<{$7gdB=eJ=%I|}eHGZ`RRP?nNw9UeM=T!qF4%1Fw7id7yq|){ zevvj>-hFT|!!3me)2xl=u}^05*1&`BXKggE4Gt!ceX7Sa3ATbi8-KyEy~iP2tSs{SkQUGLV;tHL6U)?aYw(Cuw+Q98q+F-67^3dBp#QpUGPQUKDQRF&xeNJ6xN*R`9A64^_wI{kg^4 z1>RJ}qbx1&8H@KAc=#{FHPw*l|E;kFVRyT6Ws!9d}FQlaeXf! z_ao(wLSSN?zPfC>Bc80;}h`2r{=hGe@(4Udvl^d zh7p%xI5L7`rXSCm%&SP*uv~SI_vEw;C!#Xccux@5Rq{F@?~bT-V6Hh2?%I2#Am*#g zIvMXNPTg~_uQJ{<@#Jt~LW^@J*JrsxJVV7fwfg*GLX=lk|L-4(vOS5pv0|(QGw=0k zb0&E;!nofXoHGIOn0zYUvmK>9oN&^ccvgpu5^U2s=7ceF94oqQ$Q?J;)v8vExOvF> zv**Z*{inV%oS538bL0{?N9NrVn3w-;)Tf!liOW@f&AW%_g9>TsPMFS)_MJU`r1Omg zQr-R;q?#%AA4%%+Vl)QfQ)#Rjk3r|d!B|S}+md?QxcLi&Se7;ig zOy&95bu1qm1B;@(j}Pl_;`+93{w^+YUtHq8xWs*NiTnLn;#O_U_*S_wrg9BCj8*u( z*VSlK1_uJ;k--kIHVbi4SA6e2tPYP$R#Xdu?Z|Rho7d?T%kjj~lv@GW#!Bew^O0L( z#J5(-mAmVIm{MOm?>y-B#PCsDX(I$=yQ`_PrQqQ6lx&`CQ15@_RQuf{Zvi1k>4?KXUsaw|4zkF?+ zvZJ_9n+sY0qgp8JdH5O6)td8puFSmHD&?lMH*S>qe5=f7BY1uJ&7i*GIQr~6rwq&y zt{3|)9I$ZE!dVv1ws4Mk4dJm0J0{2S4@v*H_QoucH$J%*4qG@+-p^*iF?p7MzJ&`c zJi)?+7LJG)jQpZL#P52rU+nSVfY|K8L2;u8XNeDaa5fafb=)}@ks~H~a7g?=W8NZw zS*ss-a9F(V!Fl3OJvd){(Sr-bCp~zA81&#mvB`rY;!Shn67`4r2io|=Wbq{rzC?W7 zgQtiA51uMEcbpTS~m56`WlQMAhiJ9WN9$YH^%!6l%FL-cNJmSG+ z;!Y1P7VAB@Tr_y_B=N^6A3Cv^sLyd&VLtBE=h&w(A5-dcY*n~I;-I)$;aZ8aM6JSn zMySs*--C0+B?`x-e@I{pO&NZL#JS>!3bTpiSrFe;n9l^yf*4k~R^oi|C51aAE)b6^ z%vV*Be}dSfuoIs`u~}huhl=p=WsQ*^)R&lR;b|70XyGgi{~U6)p}c?605Wc%8yVtNLflHb)zLo*W3rOnP2LxUUAk7u!F?=0-ba0k(sd~w z>uD(}3(GUyqVz*zN%A;h7!Mug`!7`(`Y{q?;fwj~$46=s zBhw_Fs_`ukEDf4OK^Wc6ilhq)%H9{noT&)3%hdi{ax{ zjZq#_3L|${ZM_4J5NC<z9r}66vdDMdB2j#K^QQm7M zQe~aOP_ST0x(=yGI&P>VMqWso;e<@kPRx_F*tMiB<+{-OVWNRzoa@{Fju5ii@JC!&64UHS{GMW+uW07)-d0?a*gJ-S-hWu zQR}i&@|IXUVsvF(qvg%8c-(grT@=^ov}5??$(P50H@Ylmj7G>Y1-#t+dmCV^bbQ_7 zMG>K!;iip_-*a#<<@Lj(Uz1?#_&s6q&VW~I@U*=B7Ox6pu8uKyn=Rg>;OVj^UCTo^ z+!H^J@y5z$)(Yf|SwnegqPE+VC6~okqIp>(dsGW6^dh1}URupu6mmw-m}a zjhbZm*}Q=adB?%S5Xm*^!p%iu&GJphYtNAP74X)%p{CMkr=uV*vv9jI~O!01nIiX=qJHDf_mD7 z>t*<{K1cBTQ}9rgToaw-=&{X)3-g4$5PpX(UL|DxKB_zc~u4vQ#WaO zwFa-`9K1GzhpCmc^5O=M>VE0smo#{o8cNF>G_9na1Z=8!Z|`dZ}-@V@qadR8?19wbVJJ>fQA% zUtmTU`j%IVD@CBi-~8gp5vg~n<1(jm@XUt?|Ne*KO!4F?S52ESb5_~xIhW0yfBB;7 zE0*5Y(6qc|<*F+`@WE^AR$ssNhMR5?6^E0{=iql4e)I5KfZrng7UQ=Bzbo;(8ov+W zSBGB%eogo-$FBvymH1tU-}U&d!|z7?ZozLoejmXvj$bE!ci^`Pzb*J-L!sq;`1Rwr z3%`5u8^mu9e*5ri!4|Nsc&W8)Xsc^kvtiBJHeO?Q*rp9@n_8P1)*-R*yP*Tvv3@tV5p8ufKUb5q004VYh4eh$X`qQdfC43ya= zgP}kbvULz2FEkn^9hN7<5G_^I=t;4;mSJxw|*EMcX@gbJMDcst$ zysqJv4Q(xKmcegrTHD~D7N%wc17^(W=VHWMhQs_~k{L&tcTSq+J+Y-5*2xUReUt&b zs;((``YFmd4Z`p9e)}F1~?%K+LVSYpP7}=~`RAaoT z#&}VU@uC{z`=rK*CZ^MAWBF5p&ZKkd<9|Q3y2BXq7Xwuj%qLm#Z8$7 zzHXez-nR$_+4;}TV%NSXds=Z`>7yOSFC()p_g@|(pFYI` zP=>l{j~SSwjo$)h*pBfDufJdVbH2bae(BG6YRvmn;rhk>Nwa!Z>oi-S$MjIXIQwz!ZR&gYT;QHj#{|P!sQm8ZQ%+F&#~~O7QW2IPJUFn z*r_jbEj-V~PW_qh;>Tq9FL1F_UYBDVR(L2wUBgWt>=$pcnQ{$uITdF8^`ZX0q%h_C zuvhID6=wK8F<(5YFvIhq{@txG%hQJ)mODInrdaO5C1Rlm&k$2Q7|pZ?&lW$RU>HaK zrQ+)ze3|$og_(am&+&IX{-t8S2hS4QJp8$0y~0lVazulNUnu5za6}Y)@C5M-z6fCG z>=Omz?>u;-ctv3+e)HrUaf)9ie%r$ji`@#de(?NCfCyCE`FrIIPo%l@=+dcky;x>jytJV%Vy=N1|DWQg4Y8?9E7NEBzhL3dTKJ%ax$dY9<#kxN z)xuX{!U{w`-e*}vUcyYSzscsmvEc1I`De}}UM;_q>EEBy%} zqLkC^teN{aI%_?CBxV8KJC)ApCTES_zf0*9-mP>BvH40ZdG|VNl>U31IbZ)roi$qj zUT3Y*zsFfS^$$90fd1X;{Fjdl5$FB;oV9)bgKBTI18VQJ2b>9I|B%uRMW*+YKj554 zwC08eu{Qdh^J|9 zbI$GcV>0as@fOr~+P#hrvVVsV$B6d}F-%)k4u7L6hc&7kR;hAmRpoHADu*joIW((s zSgy*UNtHuPl|zdvhuc&+V4iOY!@EJ1!;PvO)~Ry1NtMHOsvK6Ua;Q<|@Bvj0SF3Wk zN|i&MDu;Si4!5duz$E8phIfrBhYzZ9XjA2YN{%Wa{HWZ6w69g=fC*<=4h^atR;Y4V z1`>HoRX!mxA>vwuw~RvoTye&ffJB7cgtPSM(M_KmBUu|vfPvwrKUNWum-2WQS`E1 z+NnV4++-?wnU1c;tLbQqOR0CcERS-R$CWojwQH1{qt5BXW|Uf&%TD=7r7qXqQ0bx@ zwTn~x`e_$)D>2v2*+@*m)b?}~VQ(U)NOaa)h*?g$Ab7LdK1?y-qg2$igS~Ya+}&cP z#;}QHB$GINZ-?Owty0Tr)aHBCfn`LnC0|4P*3PcY?(HlfY;Bm_+%EU#lOa2qi}Hyr zYm#+wl&h>U(zRi8SNm2YmMqpWRdDGMTe^-ausTJK)2eo<7wdIw?du_}K?cuKq>gw> zPuNJ#mZVIKa&fYkf@RejhszyE#o-?3pe-TX0{jWIySep@7U4PHDDGwMJr#YW;HgO55D%p zbHJoA{l*yGx$fzj?LAGu$s zSH_CFuIprsZrIV)YYEa`qjQfwV7+TCV%_oRUbt4a1WvCd)uVZzG@<1R$FEuu z8eKeegXOp<8#WF5x|8IU^CzgTF|6_M(2bURX)AA`c^DQ+o_4PcIQ>qIH4oiR50Cq# zZ^+WDlpng$lIK@m2hn+bIYo2BwRvrrl;J#+Ha>M>^EQAtS(9L=kpf6b6Lk|FOuGvo!snLS7040(|Zd6#6!E6I>oo*}O? zL*Bv+c}p_nU7aDXHbY(vJQT5O($&+|;APV8ek4QQ7Vt7@pZ9_Hm>av)JI8MCr{;Ov z4gEg44EO3ZQ4G&-Y&7I)Kbx0G!&`@Y^*f7Vo&k^VB*y0>_%YlFeweQD;4LzE({PPfy=&eEZ=Z`&WiSzLCT|dt`)6i^GP*oygO}9qTguL*1FIBZ zv6ra3=jauQa6@@gQx4r4(DEkd=Sej=^dcNJxqL%S&Kw8Pf4qk8^s)8WGSfjr zS7VgQm0H~_6ey|rZMxBI%QrQvT&}2 z!xql7aK42LEIh%*EV2N4zB+uCNdP@1jh*;Ubg>ivA{VoN7r=RGn(y2{Nt`h9i#klp z3@nhJoL`}F=2L?5JTzj;V>_6IUvK2j`2~9-JeJJsA6Ssg57>+lT!Af$j)O zJlWm9jPaT1pCn#H`bl9OqmIni3_jQV|H#7T{$}+5l;wZW!UGoOx2D?getyfZ4e`|$ zzSP3+repDcwJ_L}_m39-u7RmT^O}Ll|3eFZ&cdIx@LmhM9c{Q%9+sV5L%h;Oj{h|l zuC#FK*?0Ixc1Rrzj!96Aa$hQ*zZNCN8hQooEAfXm1|n=<{R`CE_EMz-aD~zVzyJgy zgdYu@l($UD!W@1Cy0*oi=q699ViO+Pik^S)5j^)Kby=zn+^~$wuIEZOvTc zft$IyE7wxav7)=wSqM@Kv!2CQy_Bn06E!whJWV%uz0+_+zIX!gEI2A&YQaxAc$WK= zo4ItSourC_u?{!NT`k+C+{Yx-(aSXRvs*77%5)%ifBn|WxIp$RSsr6wzK$)gJmOIJ zIPui5cwu#w$ZFWu+t<~9`Kl{Kb~tBMu79Gh$Un(H#W&SA%{Sdw>M!@Pr&70OmGH5v zUF5@`Obw@N$Y?bTM$5B#QxQ?7R-1J4E(4EEzBcK2*MO(fPHsA0eTKZ|40+dO$Xk~o@74@?@eFyl zXUN+Oo;i1#F8_9d$Ns7|>3F-r%cOh{ftN}7J`Eo0v^MGL)pxA;X&$-{Zk?cvAA;AY zg&BTpaINbyy%*p~Y=aPVU*z*dc@g~3UGn7DE{t}gaAO~lc|sohFO0L9uTOyY0^GpVOCg&(&Iron{Y>%#VtB zp%cmF@+6a>@$rtY zCQfw-guMu1^W>`LMA@dck=#Y$j{3xkjy;J7JBAalbO?EdQFK$J%sGRqY!grXiXa3> zI?t~Xn|OXz^eeSIndqHpN7a{oB3ga#fO$rjD{nL_7;(gZH%G=c{#2d2*Oe`r?ois*RlS6|O!L@)e$( zxZ=@~;ppOLJ9>)xr#~Ax<1dVy%sIW`Ot!#jS0Z_wF8-6aj_^8IIQ2w0diK=lP*M3< zrtS%6Es4ra zy8XyNeEXS!!`r8|R>r|Ke`|3bYfJfViZ34 zt&u5WDE|D&3^BAjao^Am$N!rn$Etp3BpCf2oQYK#dwhB73@$!uOurA(=8ODT*hm|` za_x-{H1~SbAueU9qE5z{BW0UdBSM3ZjZ_Kd@}v{~s4rT!>6N?6?m2z$?)sV&A(Z;= zk*GL4s$5Yvac`+kI2jpLs)Z-BPiM;-{$9$I>H5uEds0p0#T_dyEQZK zCqIOME8JK(pEH>!9Bq*&@3dTy6OJB5IL2u~IN54_xOi7x-t9Pt>b=D~B;#%7A7)SA zqYNkQ98ze58Dzvyo@912PBMD!y~W9qSE+@;zER3^Pcy?|Q8*y%FJ7z9YjiHgBR^`$ z@9@gsdOoKwnR5HQa__oOa-Z_b_3LBU&Nm-8^JLU3_tZEzd(BH2uxZ0}PjelQBQ`Jg zTR0$&;eHmXV*-|c(85_3&bDxlg+o$4Gv6^G%Rkq`Vaex1<(RPLpJ(BG$!8%rCSRD} zmUA6*$jF}nW(Rh9a6rU8I4EKsoF%F~I9r(Cl5-sxyXUxudyC+BTi0-Jk$?1HtOI*+ zo_NlK^F8M%aov?`Yufn4MC%--B6l5<9InIunI5D|JjpsoX|i>W(j{W2hd)K!=D|}% zod-`7mwE7XF~Nfi#m{tPW%v>C6!M1@z6`i7`k=yW*m>^KT?(@f^4z5kh1vKO`GcZa zVK!t%{w%?7`zfzq;%qTnVLmWL*z%}IVb-}Ke@Ofi`A2?-#JS@83bT&!+@-H8%$Fd~ zUHU_XS*MEp`R{tJ(Mj;M;kx9@8o(xg-ol@^@b6jpQwC<)?=>*xrJf~6{wB+Rqk(z< z%?9TED=dtqMc2@OiHjWhoO{!T{+xr-hS(^6xsDo!XDNh6V280zi6u)>iV1Gc&6U=v zbxAm0O8={zeVa>b)ww??WR`mv>#dxJ4%ax7Q9MUz5^U+=^( ze2tQi_0a|7VG?UG?FL6Dwlt>BV}g5Jx!+A2?vKIdI_u-KAy0;b`xsx|#}_o^!ApjJ znC=Ll^@V&yS@`Fw_0AH7QMnK$;V)7c>!%W9a!~T43S-?=;xdJ?E-P`l!kGM%c(%eQ z42dfgMkYy&^<61{y26OO#F$%?{+B6?iBX9w6`qPnj&prheoozslfoxRJ2YZ7eD`-;Wu2ao+q zZ8VSXdQ;xhmOPz~A&VDynjl=TZ)X-b&S!k z#X9m~R1&B^VwXavzOdhKpGR^U>&R>m(4Cd_gY}A-07dGWAA%PJA`ex}UFZG>T${WQ z`q2!BJXS+3@2eJXDtJ-2k;k@4^Ef6m<<%JSatz*Ki`NX^RJc(d=1Dyeb-LcRMeqKtV>Ld8bUt=`cRi3}Q5m4C2XY-WzPUEuoS?o(t}oFODIZR> zRmpYlSZYw8(9sjAD(ZIh4dOj>W5Wq?HsYs7M@=nt2}Z}rj?W5erJUfpz7wxVSt?$+EyD>% zw;|q>jcZ3^Bq-O{sk@QV#=t@V?r%;M$h60M_8wvC8CLvWUuD+Gcu%o=|KVM}%6QMj zlf#J#Esk`Z;u)T_QY+-egeZ?z|L-4(vOS5pv0{}A^kMEZF9&xO#C(;PoQn5!CsH|{ z%Eh3}#ehe0&G7=62IRbv+R?ceRN6Gmn^fBNxM_3BBwOlvwD$yJuOtxD_=AY4<3r5} zCtoMT_8dXJmN_Nv`E%l|gwJ99X3xq5o$-9z+2{Vcg9`d&hp&oZ8Y{FqZ7rVbXLjVwH~ z`7y?9D)e|#H8;_d=fn=h1HF02@GZ#y5k9JFb}0qgnZWjSORal7t9#f^i(^Nm}~8#idqd>A@2 z=P!4SSMKuSyWv4`4@>C zBY&yG^v}i|4Rx6Q+JggP*n@-OiyoXMKIy^P;yw?~5j`Fp5;u8pu4wS!u;<&M08Vh8 z>haGPP}^}0#?Im&jY%gQK_*`I;6m{~Jvbsh>A@4leI8sSer`@eqdw}rB^anrOc5^` z{yxmuKJCHN#KRsu-Q7#VxqpVZ)#G0xYCU+SxYUD7MZO2m691|v$Ygw?g6EcN;}d1_ zeDV}77f*ToXN!+{@MN*wgDb>M9y~{IeMTD}G*v1*_!5ze`b4J+{HTNVFDM^kKK|6f zdPCuIi38##h1mt64%U|x<}*qitj87RGg;)%7P}RWOPnLND9q-bI#{=O?#~rX3bPA9 z9jq#ao$&I+bcOl)p$=A1;fTZq;`^u%j6YxXMg9rmFBIl8SmZAhM-*n4uLx({J+3gH zxg!5Wv0Gs_%|%eknP%h{b(+E!MwYpT{y%pS?-%c?Blb0ePo1on4b1yru<++Be9*!J z7QWrW%olAazfJ?##MKs_ZDHn{Hsl-0mpWdYYY(p#A_}|o7NsM#+SxNAe511l8;(1A zrQvl#Y$9(x!iLTJxRzUbo3oZw`eAkd^#UhZ!5?xiRdx+|w<_JF8PWO8@x^BaSm+Lg7UUmnmGO@EnD!6-J@U`;p1= zeq@fsS124+7?~ygQK_Z>QiW$Jj6_TSnF?R2Fe;_wU#0L|g|Ak4s=^;o7;7TurzG1i*N3-oHAyDHJQctS172g_lREOmxs1K939RpQ7fg;NJ{I1Z_J zQ}Is*Yb4Tka!z=WEGB8p(?Y!4?l14^YwM}+?$a88ow%)fam}q=z1wy`8_%o%hf{Ud zblut2yQ8ZC+JS2s9|nU^4Rye-PRMNPlqZkS7t+Xn&$@ui(%rK3inKmeX?@apEV(kR z&yuu0)#-e$s7dRyG_B9#bUur(O6!w0a~7w~oW*G~r#fvORHw~@Uq3xXS?kTl*HP$` z&Yp(XbWc5khU-`j?r3jMV>_m|(m#|jaGFy2@O!zcf%Q1@v1#b=-Y(tRO*h%7viULY zH5*#5^XU6i4XnX58&}Jj640<3uBpa}ZJFsquG65tAIg*N%=E8ZfAS~jIJ57}ei#k= zap?BA#;>kkvv@bdeXGkt-%DNdTt-vgU%(yRAlGQ#r!C$O!O(FaS@Q-h-WmASlAugb z*>_mHD&Rg%f~|S27LViFxWUummg53mZk&R^p)q(%EO{Jfv+t&jmRDl&n&A=CB-ol4 zuy~vY7%N|XgnP{RJqF(0W61kI7H|iNw9UfvEOT^cRf7N-F1zYXO9K@z|%5F*4MeXf%3HJhex|H zr=|UDeatsze`O`7w#9p%Ou=?1}~HJ zHWiK?t`GHIKP!yW6W~SBz_jA}gZKsUWBc$!L=;usHOD49?)rHkkL}^B7VqoeVHhsR zV>p_3#Nz$bkcXzh<$c291<`0Q9Ll3CEpL~_%Lh+~%g0#rIxXH3@T!zNwyT=gZ1FaN z7gf9*gU9!ZnJ@bc9^JLPsTS`kgNH}i<-LPzQ{Kzq>Ga~!b9vvlcwaZ<;ZbpUU$b~W zG324jy1b_?-cP~P`G+dz^7dQ2k}1wy49f#m$K~}{yp7sccQ^# zKg7(JC&1JBQe^OETfC=?a8bqFaBbdm1`kP3%i~!fIvu!7%loFmn|co3_Y5AVXLP>U z@%yR4!?aXdUJ!xl_)(`ioxDi~ujCxO3WJB~r?m2x7(C9ErVF>x;9+_zEpMH{i=KnG z(cqPxgV$&9%Fn^uXYg1C>C*9-!K*k2?f=N!D}4Bn*%k98t|pEfUpx6Ej;(X2?r zXT{|G5|w0t4WBZaM;pAPcHa>_x1Kc4-lLlIyPgSC4Mpi?;6*dpFOLOaoC$NaxKadK z{LL?pJVSlw6Vexd=2Q-zxn=P0e<;orPo6UErWrG5mCc@W(`9q#U%sgNilsMQdDRC# zcx_!n)AE*;t5#pX_6AY@|F!on@NpgW+3@T|tJTHU>JrCJWM?JIwtSbbu|r67T}!?y zmYg^ti6l$1CCe8@k`pC3j-5DH0vHH1Kw1I`yrv&*ZJN9dG)4{$5DEpk4Fw9kn3lH* zfd(6R+bus@zUP_C**RmavXLD=z88;uH0POl&VR0F_M9{GpZ}BnYi8n@jbkp3`8XEg zSb}2(j#W6W#&IoCEV9M|Kx3CArs+HrK^*p8zY$1WUuaomPu zAC5b5yc5UWIPSr52*>8Oruy{_cxG;^X>Mw3u4&rbwz;L5c*CaphPIZ5^$m5cDC6d~ z<}I~t>l$v9=QUee8|}EYH*Bl}Zry?_$(8tqnx@va%{3eAt+2Y9^>uA{clB|$v^2;^ zcBHY6Ni=V6XyNm<#8OJ##)QF?V9vF0$*XH@s9UG6+1$|FP}7R*H*Km#wl>zQY$%+{ z*5)>OUfRaA;qX=_$Ojt)T|c#cX(8_V2A!tG_rmlwEv@UM49aiVShxAcX4Qr$L|c7R z3jo@?wY6bGb1N!(bK90ZeS7xav4K=viJa76q!<- zds#^lA5<^T=4(qNiswjic@7^hFDd3rStR%J>3P$q<$LfXKAlG<@mc=z$z?n* z;A7k6v6=XbuRE8is|xv0dwDS*StBKUahrO{T!u`U$G?}(=ijLd_;=bu{w-gGzv0WX zBA3gzvC`~F>0*TBP3Oy8-VDCtMXulrab7%+f6J=)w|vQ@3cl4wXD-bV!B9DtH}GLM zGILq}%;l5Cq!2TO_s_|ZiUL(dsFrLN_x}%$MSQc%&siJB@jShZ%$B)6Z-iNXl5L_L z*HHc+3-gQPFMw0|2nc_CP{y+EH?n&vNi=2hZ`a zO0Uwxs{ZFXc%Fwj@`RxMZ`%7Yi5GZS^@oMxpRE4QHLYLs;h?CsF!#M%YV}{*|C*^W ze0g=fktb-}vwx@#j7~OMF;k zmA^7^*oVt~YoY^Kskd3jGtGclEY@hu{#6)UD87&W$nQbKTx0up8goqM8r!#9*K;0i zzJo7yuzc3QwRGhFn!nN75x?T#mmT~C2Oo8?y~djI4mn#>$Jojld zj(CNGXF0gQ!T*VCjN|p(r_ng#Z#wvM4*ryb-|OIe9K6H9n;d+NgXcTg*b8JHnLm5t zhuB^NPW&(I9NH28or6E`;HMn?UI%lI#yHCBa&WVQ-{xT2>NbwoU*cfdnKgm&uNyLa z;_o~7Zyo$s4t~nP?{)BigSR-i#=(3THjeq>JcDt>R&nH-W&T{u=ur1(5D!i<;NWg` zMX+0an-1Ql=0SqDYu-N1`=DAA8{DPl#e*Nx_VKn05vQCT+CE;Nnr{jAX#04*>RB?_ zrPh7~cj`5yoq7%FHX*8c{b4mf8N?!kM&fs>Im6&RYF;&XpSJ6Fx0;^}KBDGFgAWVQ zPX0q`&2ex@t$_~SDFm`Af_Lb((8GFv%=fE(uYw;CVn5^YV|tK28UtAn!6UHsPX9eZ zJWBt4LLf*4->vt>e3#xA6Om6a{Ex8z5B&%9{+In~pQ+$p*r8`QKGq$hkH&q5{-9dx z9(+(es|F7UagyQ4%!~Bz72+lO_Y3iL`Uiy=rGE&2=-23WTB+L!m6gx%&AOe|=yqDA z+o?{sQ@w7dTHQ_!x}DbPc3Q97={ns`8+1Eu((SZSw^OrjrzYJ_Yjr!d>ULVK+v#fE zPH)rgbd_$WYjitZtJ~=&-A?aFtyxDCis1FSo$w)Bw$lx|own+B!uL?wPSv`d61ttP z#KmyI6}q05>w3cEGpa-cZ`S3(S6PW~(Re8$C%EtDqRzd028X&jhRiZvEcC=O-pnjB z>eXSiUx(GAsLbAN6&2XJZ(sM|P(?+@!0uhWa*Il}F4$hKhqbIK(6?AG6`ESA=Y@^6 zP|uC@Ez=t#lFMpUy4DgsCyXnNt)M!!JkJg3NO8QSc^=1Jm}dt{S=N=QMR^{}UXtev zglM z25sn&tE)|J6mR`dA9GSCQ(+@h*#Jrd3?$_JlUiNQM$v`vn+jExO_6WCSx`2YZMYJd zvJHW@u=V7ygCgJ_Z5hWXXxfF>(pu<%v51NKV6pX0qpfV}K-C33CTM1@zIVA(Ib($T zg@EtXq)ld^W_Fqc&m9X*jAi1KwP13sltpyan81#~!M^T0DGO<{>Fq02aEujUemIQil*w6(Eroc)$T<JmzTKVf}>*D4~!#9G`guID$HA zI4Z=;DVitG<*mm@q5_LY8FVi19pLf%o^k1Tw}WTuh}?9%{ovuh=hE@+&rsgGGUUAv zJib>MmoD8u&QRV{8S*}zA@46TsChhiOhVuS4L*8hHynoD)_x%ic{|p}fdoEqO z{WL>)XEWseM~1xr%8(bz&Fucj$&go&A@7n5d6#F%D+3Qj_FTI5n3o}s`&wr*ZmiCb zcWs8eh75V@GUQzcUMBT&6L^{2zr7jqhQYhUYmM~d?h)`Fvv}rr#vSh~^8DkZ;myId zrmZQa3cPwto{4jLLuq)exYqn;QOtAT9YF;$Keyswx-lI1+~up+Mih1`!m4mEP4e)Q zCx4gi`fmr1d)Sl5pUrf<=%x5>rg;m-;Z-3~lP(u376p~UT4+IgWw;jQli zi0bZKd|`@s$Kb+FeAr{p*f-R>>pZh&NxNfk`{Etld+?$4e5=k8>Xo}5Yx}pXZ@|+3 zw`0Nc?tQz4dbiy<)ZNzE(=jlJkZl9K-P_x`dOLRP**iGY+sQC|pM6UfMebhIX^*jQ z_4zsL6er7dim@CKiv$X@1?JAZb&CAC2#3OvP%%%!S&?uFPV%z&oR}vUokX(vo1Yiu z4_;mlpMUalr%cMnGmePnUCJeZJQewQQzLoPxc(1M7kuu@kL2fN2`0_;fA;$z<0tC) zTR-;tyv)|tO&KF$do2am)>ZO>!*c;K3pjOMK<+Qb=pGy)Je_dAF*-hLa;==fe3$21 zIfGfJTq|cVYm{r{{5Z$Mil6IXwZ9oImCy2AD`&1({7DX;>|vE&frr^9Av{5u>s9^> zJ5ZqQI&zuFZPDepo_%4r|Q%3ZT9^G-iIemWlR-=$IbY3SH@o z&lTl9oF{U9c#`;qez;ZgCW{|x%<^#U*Vi;=egi1)=QU>ga4nWu`=R)S;(b1O`C`Au ztUs<5GiyH-&JiuX_yTd2#-M|LiCCgB(=Wuz;0lddpM}9Y7tA=u+iOR- zHYno6zi!Cz$^S9q=&tA_{?T&&kBU|^K; zR%&^eqnGlQ>a_}Zk%A}@L}odL2IuRw3h0DPGT5N!^53S{DqOACDpc#W3iU$m?}jx9 z&E#VZ0_!D+wE}>T^?jIMtqqr4{l0OM6g_! z2Zh3=A~;=_XO=Dxmc+~Ql+Uq&jaX>*7s%b8X^ zCsaUd4M7>`se#l z^}m19do5_}-^pwq-#vc!Q+Z>~Cxx(j69cDfrm#v{~4D~-ZJp`+-O`n-bV27-*f4BtswC^(ztZI zTQcNr&oJFx8S(})hHtgWzxP!!Q&%>ap~lp1P_l+ zo=exSe&yuP@Z4|rcnuo!8~s|W8Ogy3;V?%zUre159KVb|A-cngmsjL)Jh z19^NNVxDc@kHH&7775L!MXh`r44?n(b9i2mJgN+Qn$uC*9 z`pTu?WwOUcex*#%`zC)2c3uv^cHL5Zg{P&qBS}7_!_wFZG3#)0X>-o(+&Jy7;oWsK zt2}pL&hS~=6h54s-~3n-5A>BKBYE+Fw3&A}xvW`PwZm)7tW5brEd0rt znn)s?n3VYDus`)pI`zeg`1lgb0%fpS7h?`+p-z+s%9z{v@#p$iNjq`{@v6aaqv#1d zR3-5PDC>z=&m3aysG69R$h}+a%$d&XD(?tDfu47D{6o*zI#jG-vF0ZwzTuQM zRo7y+s=e8%+HUu1J5^SM*=0T2pRy%cg%rfj`;Lv<4k<~#T6-*6CElG33uEhVp0otm zBkPU!6`6anb8=!LvggN-^;db;Ayp5YCtw>A{U{VycKHg*$_9T_)-f1Q%#f`(P4`Il z(!klMfZlI1Fn?!HaZjkdrKhg_13mY(|9#IF+f!C2m9@T9d&be8w9Y5WDtDfQ4aAel zY#e#97X}dq8-7QURaFlhD?Sr0C>TA0I)$}Fu}GF0^#F^BS#eeR2<$B)-m|8N4f7Q%5dK{P+~(@5fb7G{khRf??Ha&FLW056^${ zRG{o*ub_Uv$&~*0sc$8tC-Zd;Z%h2()WXx#dX6MZPJVUx(T1{-zd7)(+CV(%wR6N+ z%^WBFkx?W4-yP|%pAwLz+K+!R)~$&oUI|8$cPsin0RdBj68OVF` z_VC#f?wa)5Fk-_x?r?I(k-)4E!J20T_gA#Cy7aQqOV0!g!bmGR@<4L&ksM(31>lmA zoXXsIE?PbioppS1{K2 zkAE6#kAFVR%ku-YEUt%53-x#H!=>oF>k${Q0RsoGGZg zJX;J(UiR5&ICeZznLk>3dditV!L-pzj<3Is#N+*Qcea=2Om8?HP6j?&xf3Q~Q2xrD z2j3-f)mcq%S^L4>_V$&yGFT8A6}b1aD+^G!myS-6r4^N>C~bCS>8Sd3P&tUkc|B7J zXe+IkoX(M9;+&Z1>D+U|R^5e?i`B5`OBpO>&*#Es>>ACFKh*z0j4jcFk0+mzEhS{R z&Apw4USWRyIMQXsqXX*)QX@LPy*^X4f&Kq|$>2$hAJygZE+`)EY{(sBR5|l}Y>gUI z{_WILJ*g4pUr(KRzJCoT&>XxRUpnQ)$Jmp{>1_wv9~UNLe6GSVwv5asp!qVN zUPk(SOjW-P@-MHq?D_p($ctO~EBEK`yzGYBa@YFhUNGCP+x&9(oR6JTyPX#JWXjQoLjuVCa+Ka-7sN0qj8e}{91n+H=j@Y+4p-Cawk%!aa?EIR-9Pn z@4ZlY!@TB%@^+!iw;6q=ws`n(^#1GzA`fOg6n;4L2z$=?*4r0Qz6&MS?&JHV+`A4( z?$3H4{9x#z@$;J5m_E^dVviNq`}@g+>d!9c%~Iao%Jyzu@m;;r!Yu;*?vJfG6s~>x zh=uue)Q^J>4mmh1{s`Bzij@mH@mUUzI5^wEQ3vNZIM=~>4$gP*BnMA+aDmJ}hb-j^ zocNf73nib!rgDW&e365TC7-v9a>Y)3iGweZd=C4{UE;(~5%*c`#kE(veK;s?@!^nY z^5L+!+K02m93PH|A|K8czqY=ybM4wc`*4oZ!lS4TnMuhgBIq#VmDeifSJH+eYjNE z`xFH*OOxk|pCQf$jdb2!SBP)>a9o`5;WF`*50{IFeR!tW>%$ddix1BdZ}Z{VqRfZq zh^P-w6R&%HlliL@FZ=LZVec~(z{;m5eev_f13tV!?DFA-BGvaPf00=2i@!|VkN(CW z4yjxVw^w5hkK6}~dYO#p&r4A-B-UxnF^9HhuhE#rqOIAv8rMo35hWTc`Pt$(=ns^~ zpHteJ{jtU>K1X~*<83lNSA1S$4zESQJn^)~d^Dx4*&`bBXTK;oN!m)Ld_EG<*6e_e z|AfQ^qFZBCo|tIWm}3fU&DLwopF`T3y;5V=V-eO4#x*XN@g?3`LXH_l!Arz{qyI5| zzPc0zr--El+HvjL90$9$Y_pyCe>WGy=k@p;={e$m@{o%Edk25T!GG=GV-EhLgFoot z!w$Z~!95Ocw=mZlUT0zEzt+K5TbO*z^>~i_G7qWpaz4{I##`0rt^Ld0r`E9L-mdy_ zE;6|a7v=83K_3{?loGSu$Y=i~f1ZxVjG>Ibp8htq<}SBeO?2k&()<4OtGV&qy-GhS zcZae)JL5Jr-#TMJ+03=EOdsiCIi5_fLZ`?6%ltL#^lpVe1L@`Kc+T}QUX}y-X(b*f zKB2EKCvUf|52VZMW}uu>F7iEF%Xu0;_kVKh=TTH}5am2VAMqQ>?@)Sex$SB#C-I+a zIlOOKpByi8hlF7N%-t!(Khy6L;x+o<|Azi{)Dz@VPK zzYqC`&wOzFFzv?jtOqvvpMmnSo`N;0{gWha(zr~=FV`5AFXLBejJ1yvuhh6oW2^~f zf8`oT8IL~_qY@>?T2qPVX?&H&OEkvXPZ^I+F8KfwW38yfZ`T-&Ch;{I&(s)eLM4B$ z#?>056G?up#T}q zm6@;)nQvnx7O8GYGdh!8L7IX~L_Zb))@|Pbo2x0Sw=i6L!{Bz=>97X2-vW>TqqqKm z4THqUgEWV!P7?#&-8xj|48gVgw##5+HMg;|7dCTiyK1_+21NaC=3^VQ{~Cso0HCy} zyMAwH$F8P=M}KV zcrU;j-%Xf*Y=YkNci8`FqLX)q{7`W2M^duN>abz#FR{e8So{79WGvu8BFO&AYq&PF)Ztyax=NG`sq#Ri#ne~G$;Ek0o zb)e0?%x3rucn2{iyaVSPf5SM?9=rd}`< zdc1EryjJi`y>L7?@?La!H-l%|t-#{_rNi50@yIvw{>0(!w|KafJ>DY@?@{pL2xI-> z*7JCG;@mFpXTa;xJlrZC?^cIbf`=Sa4s>mgx6a{JfM@FE5{tLo;VrOuQ!L(0hqv5H zm%2BmUR++i#pAc(bi7uJM?JZ8ye^A}E|!)zWbsgyX?ce&9!}Hp9q$}s(J_Bgx}i^pe?bor~W zc$MSumRr2J z)z%LghEeG_*4Vt4(V5QRS=%_nqYqxc34ald&}aaB!=pai?vCC)MxkxVimDZ>maSg0 zVj1j5S5+;s{;piP9BApXWtrNHKE{q|*^F)$8^qrXQxhdxo>P8rKlVr&>0c8aKKav= z;)ltKllkyt$-J+xT1DLt#^ucmpE{CU68{MFYx>to_+h`Fh}=d5Kq$oYa*tHeBpKQf#*FH7e9 zYs3D$Pil%idkAu(1A+3gWbWeN%tOhQBJaUN$vq+z|9G-rMAk-{B2p9K#H+FDa8rQi zDoqw%JL=(4BXFL0;FzeS_SY0>sZATDHUkgVNnlQRlrhBF33H}m4|p+CPiK0~PVbs2 z(CG@FjfL*2es?k&UphSLY;JZl&T~Y6Y59J{elt{d?`!!%gy+9InH#@p_((EvuxZA< zuSJ88CIj)}WN>jT8GJ8sKF(i1^`pB#l*~SPX8NJm@&mt~{-3vn&t4j8I}-|gAQ?EB z7;c*J=xdSudvT5{zlkgN5(jbq`l-CQI1+0_>8gUCMhnH2M#tgg67gGTjzo@8b1({> zq!8*Cnn|J;`Xb_VSe9DF2I3!jh1H5Wt(yehMru7#v+TiRQxcz(nv~g6OC)~W)M2VN z56PI*Ud$9J_l@`|Nrw`HGbWvlMn8QvkU!~cwqTi`Kn()DX)3F(M&r z>zy+Orbo_3@}p-XInlFOB2;$k@D0NUsuTU-?JY_M?>SHn=H8|mzc>XQE%7jpC!iVm zFpei+BJyDzPoT9P#=-iVEbFfZC3ovDoAq~}TYs`g$r#pK|FaJqW4%pDOiKihGHyvC zEPcwJG)~*}pBPKB(V`1A@g5G~ShdRB*Rf|+|Ba5sPRKjFNyW!bFegGJpN%BMLvuE~ z@YxqIK4jte_}NwAsg``dT& zE=rzYiaWL`KL9N%?A0{-E$ox|rQ}g)vCivHT_Omrrwp?lzVg8yVYp(SQ5WSC~yCX{P@xSxwuPGDX6-wdiKF%B^YH?3xr3qp;_rrmx=o>Dp3xek8d#_Tk#lXx99qQC^vav6%XL!C3C77%}>T zy@|kMlut&sjP1A!trB}()|$$Ppr)xTH}BO2&`7O1&bFF5!YjMC^`EG`E8H|c!LqRo zvV3|3g-#Yq30=rI$9pC34^WRv{p4R%q`Ig`by1OO9Mz|bo0$$|rY`1f35@rN#ojwb zC%#o>7ZwH!^9rMd!J0xEL`7GdWY#BU1Um5%wdcHEM-?WTqeiS#XU6%FZ%E+u;@Bwc^ zW#LzL<5uCMR*kRM(4j};Prpcf8ResU5l09+d;PV>oO7X`%%?Rbhk8gK_2Hm+w-1MWdv$RS z?c03uS)$#CBVv;eXNzlmI4YLVR;am~(;XLtM>tieT(0<*ACyDR-@MQ6~K3pK4 z_u-iM3m+~NPx^3?xYWYbBl<7jH{faFUwrs7@l_wbT>OO(mx>Si@O1G`AD$sPeE15n z#)so#p%0e{+a7s9l#BoL?gf5Ro+*Cl!xiF7K0Hf&#)mHz@Au)^V%Uf0h+BQQQZ)GR zR1rXXG3aR=LA1~RLj4i9OFUV8U1Rp~Aa?ey9S&}H@Ky)g zb0W#gdNdOUpNp#DrXeC}l(*FO6XG3RJ!^sA=CPtZQ01X~nLhGU&G0TEWcmna zJusiw>+p8^NEcBu991LbM0L9Jbh>;xXS(dixotXq_zQ@UKPeaa<9$S4O#4B`x9dH_ z5zcyJImn~_)6MjI^mu~!eB#|&&*?Um?-{))Kf_T;ln;WHf+O#~}cyD}Y!lJXBS z9Px+gBcAz~fyym{&vfSzLmu0o@v@y8bUQEBxJlz>8iOSJ0rY(&f3?PoG)7~~_@x>f zy&WVX`G}P9m;jX+onK;9qQuu|yint7HD01|wZ>>%$*<8EomFB~l9Y!|EODL2b2YBl zc$UWK6p}wj<24%3*0@n)R@Qmx?QnTCbTd3<5l=(I3t7LkvmVCgrOHE!htRsAfn83h zt<&KNsNYTf2ZveLxvlojMwm0+)twS514(Y`vI4Pey2VnA;fiUaBI2cy3N%b;X(;h} z)98WjUD7734%G6&s^4uiLXpCn@cIP z7!4NqHQj>(jkdXa2P`Wi2fA6giTpV#E%n{EZ{CZBQ7z|PqF{4(_rT`<4joBEy_nWJ z`wia&X@=B{NnIeJbA=bCFKO!X`UV?ziBy+axm-YDrfKk|?t#71COrD>`tCig+oXl} zx@}Mls@c4uZO1@=+oG=SZToh#Z6D~^-CdDZTjrvEOU2T(%0CzNTQ)betg2|JscpJl zD{Z81S9SO5p;H2H*p$dOWSWrFa4AFVp;89e!=wzbhsacb9v)SI8XCQGGb}m*OEBCx z!=W9ZVpGGQjH}uJR^f)=KM+UqQD_d zdP>;$Mktd{}{aLY_;dc24LPt z$g-dgUk-fZDzFHa;dnii_XBynA8&Se%fVwfc}&Of);heaEgtV_!@JVq)m!P3V|d)V z!_Hr;#pCU6c!dtH3%n}CGk+KwJRX0iY`Q69*_5m!^_9VKEq?VO}gK9c!$BO zL>SX$I)?W}hxZxqO#S6rygzez&wyvzBhTVJ?(kj&FOD##i=oC#_dcB4<^3^uQ#B7m zgU8$L@P1>-<9Ke$af8Dvh2lUQVN4gdp2uszxt;FS;FE||{l?;zjl;`FAx*oLkHagqcxp5-isK+j5DXa2W(z78gfik%Y zHdwCKkjAi<_GhEU#>XGvx>4DD7nhA*TsC@f+33Y(qeBC|okQ`((u~01;yVTx*RG#v zx4=(>TsF$_<^1>G=Sx8qj^|ezXdQn7Y}NDCPg#KZ-q1PaI=a$wCC0I@d73>E|wTC3=$*r z5>v?e%sFC{Bi{#dZ%Pdjnc0Sx-?x>R)K~Sib7J_{auyK9Grq-qn4HXTw zHLEH%H(a->qWPS;3%Ab4tU>v4-!#Ho@Ew1T9MWpondBCJBEWuLw{+2xDv?#UcVMV{ zc;SX+B9fcEAtzWEC<>MYFAYo$Obc8Vm;o(RzSv@hPXzddpoq6mM(#SWNM^UC~u|9d=E0`I2B7!aQ}G4P-P3%=Fu+fSn_TK*OZCZy$l}Lx?mWQ-7!iz=K7NuM;i^Wczh=u>`a+deWQ26CCitrtjh46@W@=5 zpl45YtJoq|LGQA$CtfbjMzh-cdP@)X@J+D2FJ7K?wk&Y4CtgKNJzwgEw)a)zjc@X3 z5PFd%@w`!38XYN)XOD&}!=pxXRh%yJ^on`ysuM}1QQbE=(bOY)8L~7{mRJ$zSr*}oZ*b;^qi+0A(?iXb>{o+IIeKQj)%0=(oL`>$=*ebNs zQ!#Fe;!UO)C=1|4IbDjh*qNKiN(2%Q9E;0xMMM~y)_8w@3cAes1z&sg)dCSOFPpCH zx6V(*%a=eiSV+xIrQN&hq5IzVr~l`ZtJ<&3``%6M_kE%N*~gEmw{mf|IuI}4lZZ(T zVz$ivJw1uJ`i(t~xX9VKkhMw8;`r2=&{~f5$oQ$A{mmHKfE;SE#ymY))h>@56TMA6 zvGP=1)#%olJ$i0yFr-Sh%a8WMmg(gmmw!9tU(-UyS2b26+lZ;h8mr$)ZPOsK{qAJB zSd70BZL1Y`X#CHTaS=I^eWV?8%mTWTBT=)K- zC9-yd$Ro?y*%w6YcXjMXt=LrFn{^%Y4xoM9W+@jrDpwlN9cbx?d-6`R#SitUFr`ON zj-%^iG+@7|0Yi=BYgUs=C~u|hIb|6#nc zNBh-bma9zLhg7*CGCI+UMb5c#;@P!5_Z=%v6y24xZ1TL^(a=0tY&|AUOfP?=KXmMt zWca7JZe-dpt$m!N<=wRP87cqtbfuer$!Xxe2uAE_0Tq&eI_vBelHGj#)%}W1 z4R&7tG_LADVXnABU-8RV#!Fersy;_nDrF;wDXV-opOa62$|kSBd}ZNJl6ADXdoSuZ zoH&HPf!QbbA4|l}L<>qso;pwr|Ec{sqXB5hcftyA&M7eh)2SL)h(NChP)VCT*w&Dp!o+BQkX21C^`sd$nv-#AE$4rB&cgX%!gvpl20$ zYjv#u^!}SRF$bH@gtAJd+-Skwqt|2ClarWM>KkqEJBU2+Z{T2Tcw1lWw&-yG@s7S= zys>}rX=Oe5OQ*i~in8PTl~aNEmtP6TR~|1r5SSYt>DV8bd)esar#t#K^p_n7&n*~L zp*%aiKXxWoaD_}WR=^a32P3C>1uO#3{rRbmzQ%rYx2iT3m4zd*xcUV~A8Wqq6nFJt zYoFea(QlD>Egr{s&Dk|+AjaM#k#_`;?O_4)Avi0bZK+`Ff9*S@aq^AvW+ z;KI(m1Ko?ERex~@f{E@xpof@Fv2AEqcNK=)H~Td>ZVl04d<&qJL7y@>;?Gy^9>}OE zzUMsw2)`w__@0`)EyesKGZDG`oM0T)O7unv2`chVL|)togI_A;?LQp8KlA|9;Mbkc z<^Z(N3Jsm}_?Fm63gtl5S7;=8VsivJrY zsQAzJF>WVLF2sflaU&2uKi%m5R98H_DYy7QP2Q&B0~4x;N=t6Nlq>uHer&yg{$Gc` zwZ-BawRsySSkJcngp}{~+w1i#PHkSJ>S+^c$GDY$eg?JLv8K3d+k`FE+Wn)}FSnui z_Jr&oEf=7F?2@w2-+J#`-RC~*uY-DQy}{y7sL$DT+wYctpX>`?`3Ax#(jV+`=PrMq zFStC2_q%Ud>v1?|`1cm(*H}LeifM9r)!kVmYJ{%J*K3phP`*4xC!iS4Rz7Lm( z`#5>xxwF3=)|j*a>i1SF9y8E__Ard2UDkO%Tq|*LIXQLww(duMl7K;kY>J z!)4+$o&M%d4C zcc`@{^f~X#{Q&am->ml)XxH{sJ7LF@;azG?2>p8EHA-J67o7}2a$g1Z_aHjeWMatS zLqcx5-k$(+m~UQxjrQ5UC}$&m$YH&3e+HkNc71)1-p2v)5%O+PbNk%4pqv;!A7tp) z(r;7w3!;;Ti6NBvnt?=2`Pu)Oze@VZms?J`KLhe7>!(rg3xV{XCLiVdQ~HQ}27a(t z*I&EdHv#fwzTht)556ofOvJ=O>@!e#mhXS*_7 z#zWrKjE5Xquh^VKwmTL@EF$kV)gIh0LZ%Cz%rAV1lKIJ{kHKpO{deeg+@aeM{(2pb zOJu(t(*8uR<9Ne;I=0eBzCNM-Uu&P^Sg;TELLdES719e<>orm6WD+MdUZ^qlr(it< zQ7JMWon7L&8e_i-iP70){7Q|dYkZ}~s3aMWKaxL7Qd9*r*f4H_>-rJTrZV+(bB0y z_jJK(VgEok_ji!nOJE6yj!YNP(K|4f;ae$D#kuxlrNFg!?CGrU9qixLVOhuZV(Op< zzQ!^u>x)P%cQRMsh|KYl#L9+kR?oy&v6n z1-r@b*IHQrZ--n7JLd03D#rcI&@txs!obvTg+Ijlov`qn1%x!gEJOJ{6xMl^mLJ|4|I7uILLf-qYi_lg^f z_dSO<49xceCl_KMO?l;bq;}M5fg^1@23BHj>eR%x$>g84N z>~a`+)Dy9JTSLOPUxeXZ?eLxk53d%UGrV$#$8Q*THS?U|xi)RD2M>?no-@4H5Mt+V zKX|1c3-1N`{FK9c9K8B5c+WVz?}LX|4$m2Rf8y}Uv;6yp7~Z=a9=}21)y8v%hu1n^ zIr#0?{(fP2n;hOX=&)n)c%Rwz@*H^iMhN0iEa|o)j6CCB#7n7(W0*PLYEf)0N}f;MwC#I^KLNs?VsN!E4VT-G9lDSBJqWlXO1{UMA)J5AZT6FIEp^ z#QPX{ndI+3z{@0mEhU+??^9`bSK|gU_Yj-mSL9`@y-S;bd0(Q*#Y~WL;2T$u!EY)6 zzxl8akcV4Uf@MkLeiR8C+z`d)ne*NcVW(c6dLt(xogT?>UDT#&?%0#4}wE zABM+oL3X;!!DIQz!_ejNTwAsE;IZAvL-lyPosPUGz^m3g)`v;=I*0dt@Zy@s{21OU zhxZ#x9>0ef-VBF#HNNAR_JI1I$AgNZue`0`#SzbPs9v7JfYv~hT}ooVX%vT=A% zTRdzbk~ZCEEFNyDw7eHB9=c*$-pdvbRi2jjV~dB=w7g$gy!bf0Fd|L8l#RnHv3TX< z@G2}G+bUhVEw^|T4$7h>#`5Ur$mE-UZTfDjB@E)^x_ynCc z-KQ-cK23W(_HB;q#yu0qzI*&Z&`%>_a&A<+lZP3d1vF1czIPK@?oL}lJO@m zpZUS$!Wi_Qiu0Rlppo>xeHC1+|XuJ@#lKlDNF=1JH$uJb_dKd5zN(9kj_=rD}w!P~*zfR8Xg3>_9RV zrbhiO==IDx*)vt@She?kN!FS{_scp{dPU4ZdtX)u_q54rj5gJDmMnQ;d&!cM$){tH zrjyC%jgIJ2gpu=tWor(Hh% zin5ur=FFYHaPg95E3RDqwzpqfQ`aC$pX^_A1&(qYvv5@6Sb$?8jwLvj<5-2`Z8)yM zQHvviV=a#LI5y&F#<3YkD~>HVZp3j5jt(4MIJV>H!O@3fFOHh#rncsqrp;|oPiI}F za7(knbu}C78rCZY<7>9GHnwd}#kVxnZQ0z^dZUq1x1qkRd0nfJK4dp-T+^1QXyn>N+TI)cvsX67={1ig1S){6`SkxKr|0K*J48DLo&>go(s z^4H0dm~)v`^6EC!c*Od~wz|fKx^=Q5w`^v$h%I~i_Uyf5k5KkzaW_Ge>R?aoM0H<5 z*%yaT_I&)Oe;@ejXX8tPXR?FUHwVhzR~@Y_895X`7>DBQ8d_(*6qZsWi9k7Z+Y04f zukPY$a^wn&$)n-3Q8B5Ex|*@_)sj(`sDg&!nHt^=(fF&-=c6UoR9Gf*F^&Z$N!hV- z${t(tr+sp%%{W$Gn`B9eh99r$1m_wI^SS93HU2{pYBR-JP=9@0vz9+9yR!`|JP zHpPzhSH-c*LY%O7SNA}C#iFW}@qPW+)V@2uEM6)1xQQ>Ts+t>b-Me?!RdGzWb#}(z zvAk>9itSam2n81|>|DJXDosN@`*v@GkEzSvp|(NH-SuL-==ehDt1R5HXJ35b-Z!bW zB9mVXoe)@KY#SWv=yaO?&Nok2Lxyp;9kqp zS)+7%#xGAa6b(nSqLFBJG#br`=0@|*HO+b<`bi9Rf1$=OelXOssD(M9_Okok0V&VZ zklUvFU0ogxz`_7@`u>pFef9+8r2MwH8w z@u}{h;@M<&yg{4=@z=*B2TyizfrDcXE_85_gNq$pBJRPvy5i8*}W>7K+dN_(g(iK#U7v_U1!ATp}h}nD%FXY27!} zpZcy3UoJ*`xKw=7ho_5o`S1*Jn-56LBA&FS31jn)oj*jQx}L zWw~~RlyV%@mwG|tW{HF1FE!?vLVc;D8uL+u_GLff!&%}z8rRDBh`3i{c;IJ?9*z0v zOMR)EHLj32N37GBKLfNc`*w{v22fvWj>f#_s4q25;|hrPs1Wyb8xWd%S$yp}rLDBd7R9;!_&)XRat%EFRZbrC%a`fpFuf-}7Sw;1hq#!JLCN zj`3eG06y_&9sEBW{J4YPZ(-^u-DhFSyTidd9n9~k#*x3#0Qkf;4z6(O!5cNAa4@$if{;U$0YJY+DIp520&ZkjdhI6^}H`8wuVgNqvlMcfVc4@hYNApYl zpE!N+u7OWpJ$&-$W^B{x!k77gFVlrzf%qUMOZgi_KEs1O>gPVVL(A{h`Mp`|C&6cb zrruE_eCi9a9*J+#K14`-myQn-Lyj!xEm|+957#n$yDo3LT8}{cuC2Td4RTO zp2g>V>gi)azAP`~%kti;^Ns7SA`h7P&jpt0K@RghUb?bfz^^9HN;eG5@-e*`XqPDc zU8>%xpTzrz^}C9GwbnBxI?b+^<)mrDC?oMOG6_dQMaX40@EnK<|t)ESMx7BUmp#{l6wLi77 zB|D~ChSGD9Y$|QoS4(9LE51&tZ1_Wb7f?;dDDX&;V<~Z1*DF;HOFia|Y|yUXyQB8b zq3)W20jL(q_1LVFzS`a)g&J=PTe_k0GNjd6lnG8Wyfn(o zrR`d|rDa2N8*~IZ-@K98m1)&CR;0DPdeJcLMZ>h%>pkPm-MxEG=~K94n%1)L22l%R zwB-P5hv>o63bF=H8Tv*;#yNwkyviF$eXg87I z8F?d)yzd}_&#uOqOa8%;$9-!m3<yFMx-~anBifT@G(vWbAa;I=p+q!{fN;j66Qi+WC7Dyb_OrKH#)qN;8kfJ z?|s8t>+sHi$8;!<9K&;UGm;jM!-C;)efqEKWo`9qiWcUQyu9KGclEp(6rR9Cc;^8zc?^TOeIu0*s@$mUFt-L6NnEK=I zb-MCSwRrd}mzGy)@#5p~R$08Vad?duuY4TdR*T0rO;?T{i&rrYZ`k6^8i)6g#hX12 z?{SOAXN+|DJ8JPN$KgF^@#c=hd&%O>8;AEDi^tE1CV%YP9AAxl6+Hi(mWtuMZ1cX2 a&eSx<^A(0k^7@UuI2wWDfpLtd`+os(TFJ%$ literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 0000000000000000000000000000000000000000..136a7ad1cc4065b27d860631922a15c7cd1741d1 GIT binary patch literal 24248 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..f4ddab2ae05d5d44d4a2b49e9cf0ba7500b9a488 GIT binary patch literal 50834 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 Sibh6XV-$jb_A;cA&i@0Z`gGd> literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 0000000000000000000000000000000000000000..140192865e312ac41d87ad880ec3b80e38036801 GIT binary patch literal 8652 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 SK>73L5oh7xWn~1a?EVD?0w!w! literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..a3d7380c34c037b6093a15713d8e90e88978a4b2 GIT binary patch literal 270228 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

GUExHSAVmQL2RzU7I|V*>f`$a|M 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a new file mode 100644 index 0000000000000000000000000000000000000000..ac246b29c0550e92f5532d43c689e4a5e95a3e5b GIT binary patch literal 49310 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 DRf8#F literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..bfc21b106d7ef3c6335a7077896c31c12f3555b4 GIT binary patch literal 94644 zcmeFa31C&l`8GcHW+fnoMMVj46M}?23xt4M7Pu^e#DKV=Nl0!;B+JdcNl08UAYef2 zUYAxaE>&Dw0mZ5n5wzCY)&^UU zWuBRLwzJL5Nj|eQP*!<%!VHh|$e5KrD<^ACMs|kBlP*=(-|U$)C6}2qYqk}mBtZzV zPKd#^$N!g=BEED6&y*EZ*99Gd zW&UnVGlwdf6->6EuEt;OYp~-fVQoWIZKG32=e&W^H8sB424A^OSlTadC=E1pOOW|; zneX{cuw7ajTuYtJ6qc^>Wm2-lXUi;Bl}tg!8Wz^Ps$dyh^_4Xg)Ra@O#FtlIKF`;5 zVP#c=Z%I`!R9;o)TTzF)sjF_Ps$JtSD5&<81{^92P|ADa6(HRU{N<=SJL!S|>dZ$) zK`CmzI-EjhbAD}EpvB*vy#>BnUjVV^Ej-uPVkNw!VQrDG{yg8BBA>q-%aS@oMW|;x zEtYIvdDDuE3hUPS0uFJ0W5x2SE4%Yc(}K#<+NGs_huu711#6PcO%^HbmeiG%Ru^W@ z$}VhNZRgNdSjASlx|+ow2#KYuOuNolXwp5BDD?SM`S%1W^3~Ke_}C{LIdxPQed|sd zsiMs__=1iIc0Gm^1kqV>g{6Vgn(k6pHDRT0>RJAVvdI^=%`u)-q1kx@bpSRRo|RQ} zZx)%tclR1^lP zno7%Bme!Sbw-|u1u`$P{X?OL@NDZbf#H_STfEb3{$KJW*NtB41fk0mgV`!t;O%8YRb*n{`5w{d)o1ZIg6~ zZ56ClteUZkRB?_I8cfmq5!q;-mdrlMS%Bv?)?mbvCq?MNp+XQ11*2t!z5oOq#dY6@ zq171G=x)gE0YPQTF%(e7b4Szs<^~x0>jFH1QCO||LASKhIMb^zGRFceT#KwJ5et>! z`Aw{34n>VYZ)sI^V?drWAx2&)mNCE<2I|UuvJ2|Ea0o2~g{W+o2G>xqA`o)wwghY& zN*kyutuAU_R9jY8gMy)SUZ6=f8v3|0Xg3B{^1AtfKwY4ytjRuu%cg2y%pf)!gC#Ui z>nk~aF!N^Il|i_n1;sV1edWbp_UqpDjo&Kiy1M!sx&Y?&`^WHuv$zH)RprxZo2h%bucKVH~5+@tKy~#UvVWy z1z$iE7tdR=D8IOHe$k4BMf3CK^$-+S@p4gu2OCPu);0!l;R9UX>c%z26*v`v3HYje z3YZ-;Mqbg<>7@+~fvVMwIOSQ9>?}53&Fo=@E3#E zN0dkiX^#nFtwTRptatE3#GM8|96%3;@Xv(sFNN^0hwwiR;olG8j~M(gr1v+2XZmit zEQKIHGK8N1{vrIPLN^@!Cj;Rh;l~FUcCIXCa)Uc($#*2zwO&XYf}6 zKTYxRsLQtj_=w`ifd3k7SjEK8L4bWGp!mh$e~B>1E$T0(ArAUC4C7k`c#db9ZwAk> z=C4=wEcRg--$cRORjV7Ts>_3`)&*DPFPXmzm-o|fek-r4n*Nh!?{c3y8nU|!!!_KSyS)}6qB zAD)Rtc}1SQ^Oi626wD}?GR4D(d{x!HfM@0G={f1sGp1)` zHm#wuv1YYr+O*ob;&p*ie{p$L>6%(RKd34TdZziHprAO2`zKu32hS=jO`nxM6@PPP z^6#818P4=fTUH6%rs`70sIFR#5v{hOYK>>!5`^)T1>s_EV|Dd(nw9w*&qCWktDm+s z3w#i{tZnd2TU0Q2hBdCvSQnguadk%cadn0sS7(^x>WtvJ8I@&KGs+ur7gAPPm~n9p^=iWzGBKi;tah1}vHR`q|JO?WL&e>0AE29Fn>ox!q- zHOJ3ev`BUdA0En=&=YY(m)$})cee5sc|{B6uP9!cHDkrHWlIVc<}Es} z82w+HSVgURglcK*9oCgbxo2A4|8yP(kb!W$y@zkSidrtOpfL0VN&_u|W01I|O}Is? z@EkjKBCg_iw93E7W+y&V+!gI{cP2&+^Cq=z%6A`3d@A$&WsmxKVi8 z8w;Bfo6=wOFG$>@;<<--N3>mM#fiTC1}l^kJsfF_Jm{$$wd>g5j~){qPl@nsZ`^M4 z+e?t1-?On~{occgxknEr?rq(ZzrH9bzlrw17PoXYB_@cZeT&AnBIMfJ#T0X0BD%9F zW^ntY=G;+f{+D-GHE+m|eruB7-LZ8yW2QBiJdKiJnrU4JtGv;j<$|0WnZKp^V6*td zl^orf7@OFZdfya96~uF`{u9izCYh}P^29^ znCK-&`=L(cBF1~7_hiXGmw#-D=bbsHRc*`|RaG**#FhM5<4%8uS0o(qSFX=Zs%%P= zc6W3&370svJ$LLTgvi~!%hHInzaQ+}o8j$gowU!g?%eC&6C;i-NjivJyI5ukZ5#8G z_HAnslP7qG9o%|DbZ4e}10=(m#UywT6L;|7Hsn8ML;h*|60gOL#)QVFnfuypTk_pM zW+>J>{preWRh6xyD>tTXi}$A?ED~~$B#MRp%E~SN^x;*Nufv0?%1|G4t}3@B?y9Uz zpI2Gp^7!|n9qmor6YY)nK5$Lmu99sRJ@2VxI;{2Wjfs0l?P486vM+J(w2!-%MSDHX zrOl|#ogc{h5EEQ~$t~Rf=fUw0G+*v@ed3-txHHkcZ}*6{0@TXj&ZOAeZ?Hl+vBPi9 zpTFXum|oPr^RJ>f=ituDMA^djltj;1_^zj=v;{Tn8TXIY&%WK|7lS&Z6AI^_`R;}D zliwNCiF=^rR@q8+mfZ4mYnNzU_PbHZdH%Ux*ts_NU1K^+mi=yW@_v8vm?P4IBb7Px zj+8(vULL)3^Lr|H zmUv_fNb~MJ{OQfD*Z3D4TPRSEB4x2}n-8@aNNC-5UBdOFlRaJjaWToRdRKB@y-3b0 zWoaE-7E|nnJ6CL?P^=#y%oJQzB4Iq!wt9Qk3%RYPTc(1?za5cb`SD*B#$Y9ZV)s6)*i3= zjYwmh2GQCq(qh_Eyt{ViNRMJVQoJHrThaSxcL&DKS%2F!8ci)wpA~OlNUXl`A=MfgH5tpN8(Bh;a#5w2Ob^`PYqq@op)#Nc1ST zu>Zp#%4FP$Zh`+Ywj@z$ZejhWOh{ZHN=6Y&*8MjY4{mHs*dm;U{2jv)CEQmJ9ex7t zo8w$@?zpJ<==hlU*!Z~k`1nEb3GsvDhQtpYYxu&a1bHK_-Q-#{LcE&Kz_|#dL+Zxc z{F$VKl{qM%D~LsWN{M5r;N7_p=L!K+c~gG^>0;jZ<2Ya7=^l=`LYzzr;VGm`gh(RI z6=DqONFij7U_YLGp%AB&o+rd4Qaq^OvlQY?BL&!WQrPi12JNy*@n;Tct~3>5ln`f- zhaMuSFCfhoVjk&fLd+*!Dzhvj!4;V~WKjszKC&dlY#~;VBK-?V&lKV!Qe>LXcEvIw zE+_Q}QB0aAL^dTLZ^e|k-274RA~z-GP#~~ zvJlsj!inoi;r}*L`28hPIDZQ%@_9QcoR6ecpt$TK2cf(X>o>VKyDmX<_)a=_H%{fU zJq(QucbtuCJ%f_CH@PZ+`=$y@_+bh@F*0~WvkwnKfV{~i0Y@l6w7W>k;Zz&WdWMxZ z;>t}io1?cxUGG-FXw|YH&~OI|9FRE;1xELfz-Zx-0Lxyba{Y(|zIs#i=BOLH!e}mi1W+Vc7;o+48HDoDA!9ekY>B=;strw~gag!T-+diz z(jgCMxlDVCN*jY{9y1{yxd|6oQII(u&;DZUXCxvvA#Uj)_X)0HuHo)cu2Wq}Q7JC= zF+496F5b|%-O;XicY=GU%MC6YXC*?Ca$qOD12h2x@xzKf2U>x%$*bgZg?Js5cE3{e zDCLEC2<`&K3F~B1jKX|5MVu>0G0^)#2P58X9$~fJG_h!aa9Ng{Y|99<+@8YEv^yDg z&mjSpuWb9uE;QXY(U8$EdmN$Zo{Y-X>B_#+3*PClTh;>&Z{i^{^VewL$-dSL-e%b4 z^#kuU15Z~W%O%v`pTcfYKk&xk;!FE0`+6_=n*qE2;58d~2+AW|{@S3#4NQ+CwETW# z;IVJ>2#5D;*!8DAreloM{>r<%UhvL_-T5*#=bzC0-E83L3(|1;`x@-b3k8iDiubO8 zm#mD!;eFCiyoo3@?eF+L@MgoVKluw9coX`-yRM&j`wTo>%gH00zd!0H-e8>jw7--3 zz#9#_{`h;Lfj6ZOyfv`n#Z~ALTE9Ow@Nk-y2mO5oKb#Z%mPCl(z;20V4Eke)&GBUh z8gZ){|FoQVzr+t>`*>=sz+9xB$0rc!c+|cQyXQbTo@P*hgLv|7K~1@yvgi4{IeS?d zv*u*Vr7@pBXHS&MWb8S6k1^*F&)NImJxlKr6j675b{?}E3gn!n*CdNj|B1Dp%qW(# z@LIJBGz!ndZZ>#6C%X+ih7@(giLdA&XcVp@9|JA1WpQGc9j1Pmcp3bawk%HGKxme; z?0yF3YArx|zqZ4Sf0Fnk_*-mQocNm^rv4N@ZZu{N#)%WU3j_L7MH2W2?Kp8_f3LZ~k)e$Ft=+I9RjJwd#|JI?OBK`ut!O;KPp`Rv(K)1!v zpJa!b{tS@{{&8CtC#Kn9>NCWd;9s<5abmt5ranuo0RMYi7AG#V!_?0b)!>iXvN+Lb zhpC?}Hi4gx0n$3+#FrfUIr4_lYv{l3(4QeV3(s%p_d4`vi64O9Xz1T|=+6-!g6B=9 zPX7-MeV+Ii_(u$Vj2&kF3*;=kmuy*_7-NU2pD(6@=gc>aKg$kNzd+0b-#v>mPAqlk z7l~EiyJu0x37$GO+}FilM*2p)VHY;EN1>jYD55t_FXFq2KJ#mx(*TZ!+}vIrKj9 z4e&P_`ez;bHR3h!KQZ(_a_FnXufcz4=)22;{;w5y9W4H0=v{W0`Wi6|{83vLCr-1& z)Ypm0;G^};DB4e!Ltifnz>hTaOC0*3SOq@S(EA+vM$riVOhdokp8r0-{sJ^ zh)2O+ZRmG8^jC?O!QXA@dA>CH??HdBp??efc7uP{fp?8Of13JFpnt}&?=EYW-?g&r zUN`h7*kS57h%w-QYRlrp>2{d<>qIvA_iS05IL8iCzga8;|Di356BpTG>aQ1-;QwXI z;zYe2rhco~06s0QyMJ$U=x-2T0e`ijf5@T#l6V^YZHE3uhyG^q1MrU+`nMhWTg7j| zzhLP9=+NITj)HGD^l^5W`Tw#w1^lmUS)B0LVe0P^>EJ)IWpQGT9j5*su?YMTTNWpZ z>@f9T6|2F=@{w(SLc|6T<&mmATgcT48AZnCb(X=a|Jq^Vf&ybsn^S zbBO*>2>#j-{m(-3^UDzasgU&l8WNw+M0n`*KMT=+F9h$Pksp^`7uK`V_z?cY5PozB zKOuyl5yIz&@JmDZRU!OZgC7Q;>J6SRFxG>A2-Jh$aMbV3;9o%)w~>;66#OLkw?gr+ zgTEd8NX2)6=QTO882|6!I}zr62l)itBz_;)j9Nb)JXfl;Dt$J1Oc9bVQfTi5&ugr7 zrN0>b44l*PSW4p6fnNZgFF0tw5qv#(jej%v>kR%8@Vq9``WL`I3SQ&A37*%CTK@s~ zCk+0d;5*?j9v8~=Mxje^<$<=(0MBbW&Cdt_ZNt74{6QnVX7G<1<##*y?o|{v6nA|7*cd z038~Lc!Gg93jA3HKN0)|;L{ZTT=3U`*Zz6IKLB3$my5ygG5C7$ z>rfur|1IGE4gFMw_W*cQw~hA=@H}YGRVUAaFGX0Vw;%j9;B|WK;PD8IlQCp{y$k*- zgi&Nx`#CPFQ0&>#);bhC@9A|J3LdvuYf!jc!MRid%Ma`YCeFne8G12>b1lXf>rQHX z$8p_B_u>*`eauX~-i6C{Ou1g~!lfsMe3rc=#ktOAmR|3Y>8#pWx@x)5$HcMIb*{6S zWvAo>!*6C(B{hh7TCSZeJ4dI>1x$wh z9G&h=r@wRTbe;arvD0<>JI7Af=`R*@t0hh|oepQD+bKIe&Pdlu&vLq)k*?EbV>Nup zNY{zaayp&CMP_n+6`QdcgR99bh12bf?jg(RcZNM^&2l=PVK0}P72>(QU~X23=b3im zI^WrPWf;4InNNEeU3Q3PnYt|4Q5-RB%n;A)m2~VvW(<2NU3Q3PS-K+Fxg0U<#6vu@ zM>TdkGlspKZgxnW+Ux1qAssPv;}>&H_bwC*zu2kC+F<01otosHTY6WPCD=rywA|j9 zg&UTjsaR6S_AG|xi=CRj*r`c12YX8;<^Fk2jEM<%(ASQz>Lnw^@ySl9c-y55T8 zzHAn2L%&$pJCHTz*3w$cj`<&7*K0q!u~zot+0FmJ!rq>lI8G~jdjj{ev^NLKC{OSn zPO_FMj@lLNPfp15Z}w;I&5_Gr({{PB><&vo<)YT@>v!zp5?70h5kuRzug@L3y{W1> zjZ6PLp6lGndI2Jr=wv{}L>Y9?HOSReBJYod4-Cna5b+ zZaHSHQ6BheV@TatG!*6)P8~)X8 z3H7THT3r8N+cx|ltN)-aA@BiZft0P=@PjO{dTT;(HA0Jn%m)`l#(0N%Px0REJr(#T zNc?D#-aaXzBPq|Hkr3nG@89B&t8eX!Y27>~_8x0VZrt5F>f`TrwS8RgY8#X=DUjDz zh2Nlr#{wJLKE@BS;QqEM{2&XuwtkEsWDR*+s~U2*ii8~vM-OokrRD2TnX2V0mku*O zNzz}B)V#iHQo@0x^O2i_{*(N363(x`6E%LY{*?MV>SOO278sOpejx6iTR{&7;_n$2 z1P|{zQEn{dDEO5ual+Ta$=+C4q)3axT`39slNS3YqeNL-L+dk9qTRJJ-pHwi9*wxE zQktXUG9Kfzd@cVb7_qu!o^lcEbSaG$L)!nI`BpnVzef)<#zi%%E*J2 ztGFH#w;|E#o+M@6=~{84!dRXh)-uVkwBnvJ!~@kOQDe~G<56R5BhBzw`V=taZoNBS@D z|I~jWde5zB-CVG*%VdzW#aj(oCVx*#@y2zz&Yh%M=c}FLTsfyQ2kBg_jV%dSYO&rn z*<+KC*HcwqN46hM%1DUy=lQoJ#i!(X)8&Hb*@2t{e}HW@w$rMWG?alg5=41q>FpYn z%rUQZkLF_}@A4;N5xT%QyZ5jg>2~X*LhN0VXWhq0M9;1<$u56NLNw%wvNvcsmXbq0 zQp#BiCwOCJjEidgN~1!v*JUO;+wk?TUis5Sb$0(x`)2gC$aoaJ9Q| zhOla@TUI7zY5w?>A)ZQqvNztd!*A6r7r|%3KQsSVsoXICRzBk-dgZRG?R-Ydd@h!w zmL7eujX*&h>Sm<(9`9rsBUU7}PxPew|C;3S`2Bg_iJqPQm@d~<)~No}7;_X^gmK6k zMPywUu%0@vv-(?tLUXmJ!4sadba_ldjy$qFx@D7XS!nDjGIqLul9&03LvD^F3A8ue z!u+`i?F)@HRmNfoMaz8T$ohH}>E`)y#zqe?>p5-LbXiKCWMXl11#SY+hV3b=`iK)J zwx8$8@&6lT(u^{R_dLfkIoB$aZ`S9i7V6(K#Cwu##j%2m{3m&j*drt>9@AG{)~fnw zYkht9Dton}Uap>xR}1egCiJfxtM8=2aSy1xX`-@WW!P=41w`{l5^AE;|gIW zgl^2wkOwH|K5zjjRG3)96$dylUjqMO=(5)Cy=cwf;C7#Kt=vm$9qKD;9V+I`a6Smp z#*ko+2j`=RD3`S}2Nnu){)oW-(342_S@VlHDP#)yzghE9$Y+rMyINxkel~ebcsi35 z{8^-*$W1Xg!2&b5aR7HQDe`+RDdbB?-^AP&Qpi`3LVf`$7VE4ch5Ry7$S)^-NA0`; zd4-a%A^lK@T2jdCNMY|MMZVXOLf%XYc?&7>-%1Mk22#j3lEROzq>yhTh5QE64=_iQ z6!P0iA-{tZetwk{@_R`~3Tv+5t7=UJ>g^%QF}dhr((eel9)$JzIC)gc6Qr+WK{P4k zyGYS8c9VWj$X%K#e~x^T5YLl-Ux=4TA>U8>f?A_7)|$H}-mn&;Qx6CsJXk|Piiv7J zB89x2GzD|BNPmSnw4{*#j5HMszDYl_))3Gx0Is?z*H{uK#@rK z?@1?PZW!s?LVQXJoIjIda?f8#e<;Lfq>%rM6wdscbh;GDOrVKMCYm%|UJwZJ1FYj# za=D%b@rIJm#JX)#w5yRye-i0TQ~@cRm%B_Oy|Lu?3o(u~8%0ElLYY7c{pqARLQEt@ zAx%~CX{2+JMbfvhQ;m{yoeVp{EK;=Jxk`Qp>Df?`qHyz+JfAcd{eu+kdZCgpBF$H8 zV&22rOeHTQorkrRq`$=cG$p@~)Qg>KNIQhMOvx`NU5K4)NI%5RHA?OyU5o|#q`$$= zHA-GhicTrl=b%ypO5R9{M%PS=cGg0A9@Z?8q8)A^Mf=~VWLgt?ZaXru>}{1wtmu%QF#AJKo5T&_V{WzFSexwTXNGOC(% zzuKuB`nSm=-aAVFOQru6>E-Bxr07H+k)qrVDfwYi^oKtw`4J`WBt?7gQu5D~{2!#q zhuolTdd?Iq!{$pD0!ulSCRe%=LaRPSMmTU#;F!1 zmpjV?pF3uAFx;r**O5ZLi4^0-4N88alFRi~7%%Qn@-Hj-oun8q?o;ynmHca@7#AK< z@<)|?2PyjhQ%b&5$#;>W|39bX&nx*0q$v0ON`64eUm->LzoF#cS8}e~Vm-)R(@}0e zQS!G*Q6KM-LjFr7{}n0f<+n=yk&+)GMg9Cy$^WF}M@Ugme^>G@(klQ#igb^XqCFiW zt;R13KcpK&3VAGPEv|P+|AzLfc5+)*jc|@QRYZO1cS` zSfrh3@1&@=?~`u95K0Pr&PAvEEz&l$f6~{i4Q`mvcgeqiB2#wnlcF9!Al-%`m-KxU zh0=dadLxQ}6#d{&N`8d&CS-;5T{K}O|2yd|C<4-7AWKSql=L?A2U6g3V;%A_q_9g+ z{9saCtR<4(fjQ8mxUM{z6!|_y$w!fPU_4jyu}VIU6!@u1F4y}3=XCN&XNrfEZ#qG^XehcaS*gu36*DrUHqWtes`mc~~$Nd2*(%(*s^Xo&T`>px% z1G#DRBD(XYage%cjE@X-2!Ql)8UpF~aZAXVqzMDZ;&?8xPEc4#C=IgyIy(Zk`WT6T zxs~9F3UX*4LQo?;-PtQ6ur?w}`qhZC|Kk#Z!ypJc##5O!8H zv=S7h5(%i8*CYiRZR{cly@WkEGFX(HeXxML_h&p+0gj3c&~*M131~hV8LdFkR3mX7 z(d?rYp^&}gWMz#}&?uZppnETXaSCv3WPm6)`&fcd&kZV*6|g5VV6$WqHKbXMSD-18 zftt-~ssc5e)dU5b8X0Wwr8-doo*o&X={)ih;`}59ii$rzbw5P`PL2%Fta~=fo^?M> z0i&#sPflkj!0C|zetu3f6fpdVB&X)UkD&ua(7hFDmV(TT4AN|)s1RBAW*eQQU@`th zlGEPX=xha;eY^nYD8QWK1$c%6oEsTnUzKx~f;=-a$lgow90hoGWPp9;F;79}Mh4k? z9t#v;{_z5wuK?#o252_%aA)@g3KrLmku-6$EOBAr=!}aL@6Y%TyBQMV5qle&Thw^P2B`1zLDK zL6Gb>b~x)Q;@aC53*iC`XhrhhiP_f=P(^qpn=Fh&C0RH ze*KMuMg`aq8K9X!Tt9G3*?-Ij2pbe; zYh;+L7JbM8RAI`&)9RVmDddfjA@|kpH!H|ZkwKc(ukXpbPo~!^&@GXH=4kgpSKyaF zqIpx?=GZMU*GIQSZN=0TpSleC9zOdKqTiqh}4GMN!WUywR zv$}}xb6-+`Hy$s*n-$3jd@XssXdlc;5k-?h%*}6RLK97A>L4IZ6km~$kf1Tw% z1$l2|kmdy&dv>@Bwy!DZ`y+!k%T-^>n{D9%1-l*RrEDavKGng2s$ZY#nA+RNI@m%I zzHRLZl-*>_T}#+&?ZK4rqBUwIykzakmGBDQox+}WxC9W{&DK|#$YZn>3H#)0J5lk7 z+E@2c`5H%5;2qaDsXuDXy{gzDrx{899mp#lv*tii|9kR}TXUModtKmRzY3K6deRrH zIVKfP;9aDW|D1M+_j|>sy1_q*QUhhYdE|k^xew$yhoRydc$cMk&QW0e+Z4|^1+?F- zc+MH1{&mIwoOC~?2Pt}(dN}zPrT+(c*e66;>G7R9?N3*9GAQkHl%DUrD^Om1cg_4& zlES{4@~1F|NXgfe2kth--=g??75|{(cPgImeu?{<;`uI@@!wJWhf2?Pu1uHjTB&zO zTYNkydA<{+p6@m4Kc+bBnU@tt16^O&naJ?d>YDcZ$L zl*8@~^1JXZS@9n#{!_&tB?S)WcUJ7iG(u3u8%rMbl&Sdh$fMpbS9}F|}nAY>SffTO<|FTKkE*k6HVOx(}dym3}An z-@I?nPV6_okNR{RQ5)JF*^+o_^W zpv2)`l=S~5^3UNNui_shk9toTY&;Q2vWuUC^ty>BChA2(5sbTBz=fJe`7??@m( z3bYk;FZnb9%^3+wk(^VE;_m)>V4|9%JY4OQk83TM%DJ$ENk_>ja<1zM}cXGiB0puI4z(bLF&IG-}Kl zB0o<~mz8rZ$CFg$M=*4b2CfjOttS4-FAoT=I5{nq)9bE4*u zZ;-BH5K&)GY*ur&aWi-p^;b*R<;n0I@~yH6N z+Fb;}NufsISC*9=S?sQKC4v%nn8M&%&NsI13p?=iB zPWv%TnT5l<26n8=&?6M@`P^>25z06m-uGZv5DEr96mLjgH=b^<;qa1Rm){S(%MCnz zvk(ri7ItzB3Be4_-yQ?+RAn0u?>n&TPyHsq30)uT+dRVIod&!9wFE`R%A*Pr^0_jdc6 z)d$`v*!3rW7aMr;8Vi`=@>d1B{^W1BfhVugdcivYJ2dGYM`(MFL8H?3E3ff-!8-|d z{b_%z47@W`>f!vYhFyQk?;8f5yvFP$e|!6hchtbcDO(=l@;7v0|MIsCcDnquKjH9- zVb`Dfc+kMp_Tlh$!%nBC+>j)+e*bLXp$o_(99|R}pH5GiNfL_Zg`M^nMJbPPcq?Jo zpZwir;33#6-lP4*J8aSwHc17c*X!1MKi zw+?n_T0M?XyaNW_nm+K}f?a>czY!P&w7*q-;Ejh}fAGo;ytRGcHNY-c=}i*q?=uEo zO&@r#!VZ^|J&sVk_`+^~>-xYO1-t(Ed$EC6-v?e*Kk*(n@Pd8dy#TxZjQ9UG@EZHT zI{|}tfA9)nmk1m;e(Uf>()-c^0z#p0P}fAV)O?6kkv z^nrJ2Kk>F3c-QuUw-a{#Y0rN#@HX^;7mbr;fAAKN;#IsW|!KbPW3axV{mJ^4%MOuSoQ$2k)`|31oy zIEW{|(Onnt75jtoJKg#l-P!3L5B}q@{$|gdDY-eBnX_cT^ZDQCzGt*dCT6DaAdrUF zkH~q%-{|HSRzg2=(c_C2Jp}R-7c$y(x!rPOuyl>j@lg#iJ>aW0zp`No@HGubjJ%?y z(@Pr~0#&OU8+<{_#?I38ia_a_s@jUW?zpx@`fmO)t1Vh|9z%^7RoQv0!7%3Mx%FiT z#Zh>Pv(3{o!7TQ4d7W#IL}&&Lz5`-l^@1|NmNr`5q*gO%Je3X$As-**}M;gCHL!aoth zKO4dyF!*7JPfAfDX*MG45iAEN)8!81Mz-9Bh9w_Q;Z@{>aJoEoMN>KB3MrCkwz z!{OgW;Ms>b43l32p2If#GY`(#B`;L@TaNx;=l1ZLUn5E^^=4g%0s@}l+pbq!qAUH>93GEP9zzKZ+!;LDaOa0q}U0c zslU?Y{3sN^q$jPNpM>HE^Q74ML8wffWQOy5P?iJMTcCc%1@b@ z_Bz=N=U1?@>~x(U!OF7Jbvn!M%~|O>z2$f1EVe@# ze^s?F;8{6)dQSTEjOiH}IoUI3T$q*Vsi+HhaAhc_O>3xZtXYi@dDPYwuM3p=i_5D@ z*VNVp8>-5Jo@qXQ;RAx=AaWT%^_*2$nm#LiD*oooS`nWo?6J+MVaibGY?AHojjF?G+P7cDdH#lQymR z-ICJbX)bMkI0+xZnK-h`{ls&-x%Gb2*qyub)*ra$flm@#c}*A0bFF8{)%1tmMZ50l zYV>?>_qP0)AB*JujnD1=dDlqKEenq97HPjY$d4BsSs=IB-;>}yw#4PNK9u8G&(Gqx ztA`S!e2bzl?N{L)fVMZ9^9az`JYI+5 z5^)bN_uw}F%4l+@aPeRHn}*EwcQ>;k$`uk^>RUUbAutnRH|{m$0m^#>z7yqr1m|nZ z$6a7}pCZn;9{X{g_6YKr`!bRg%9BWOGsXJ{&I2DqI$KR;Pr&xA&bR;^Ne72f$ zK37dKKSNC^KU+;9&sE!cBl9`5FHlp&hpH*!cs2`>%+x&6eD(SoH+b^3287EfM<(Ht ze0O{SDISNcB*km-OG!tmZNBGQpKzxWt0_lgSVNkmUK`+9W)1nVYMXC>2g!TntakY< zyM=rTw)rDnB!qlDlqy6kc|2>}OnSPUy)H8+UoU{aQR#0bMaAAm3MV3|V_Bw*hoc%l zE|87i9JeL*`k1!ptx?;sL^hz8$i88%TtxNC7JwR#BqbD>eXz#W7DS**;((AV?J%m!GdQ4R`;zA@R1iipxsnc}o4l-%=SUP_ z=z+Qjd%%D5p|hJ<(r+r=} zD})x-p`kAV%kbyf)hatHHu46%yEJ3a^&xhDh8^2y=y3xCvW+Rl3^Wv$Kl35m8YtW1 zz4)1S=fLi6WSDj+a(U1$G~J(}A}>*TlZ2+5fd;A5m2DZu;qdZcx6lMq;ZVG-2A=E- zz2MygyZQaV`;~zw`%*7>e}r9s%6T#xpY|6~yN*e7yM= z0k=Q?o((%)ekpz6o!3viZ3Z64Mjqkn<178d`>BC&@1uU=rJ&Jif7ANF%Yvar_(-6YqW4JqH=jA2XFT z@e=UbpxD>cAZHM9c91=bC_~R5a?T>k%*o8MB%eQv=$k8LO7<+GyO{NeXA!LqV(t!K z6^6bE?C~P7hv5GQQ;B%8?yk_zV{9phafWB3bK&xokA(K41@QvZ4SqW)zs|ynB>z0< zFJ#!_e~j=U)o`dk44z+i;z^V|9y5w);C~37_?*gf5Ab*qKz%0oB;F6fyo+$Q;y(sI3_l%zC;}Jb$CEVE zpN#Mtgew)l5PTed?6lOcLYQB_(*CUnzsunH<)U@SFK%+AJ$Dlths=RUo?j5E!B406 z2ZSHMPvZ?o+1zaK{DKa@o`nB0{wnZmfS;)NM(~TkYdya>^R!{lFT?QbD?BMP|J)U5 z67q|2OY;08%P(NhlOpx}a?174AgEyj{rEjf$5-@HZPgr$XK7;D?B>8$53xcYv?3BI9qI;O;;Ah!Q7?ec<2J0_eZ% z&<~Tl0CBLkjyUlvhkk_k1Ne8e8u9G(tB9j(PhiBrUA@WT!Lc!&N} zkqJJ{(4XPZj~0u;=NkIu4*eLh8hrOuvN*BUp&uu%1i!_If1N|0EN%mTuc7~{LqA^b zRwTcgCtZpYPdoGz6UaOh`?uYg}-=pSmy2BC{6>ev_g9szYBU9tVH7p?}(;_lZ}) zbNZyl|A9llM!X09Wkdg4hrUYu6+F+uI{s0Ieytdar!pTI`cw2%8bpY~3%-fq;=yq`n3KvhyE(@Q}E9i`d>Tr*N8uXA7!7D;zXB2f31keh3i;D zKTJMJwNi@`8$>dAkD;IJ&|fF!f}d*W3mp2*VmbKkb2P389s27dgz&+CVm489%qU3Q<26Tfi8 zzg2t;{$GZk*DEIfDedhx8z=thh#wzveG@N+$S2sAH&M7n9P8jMpdTr3dHu$e78vMOI4-xY#4U-dt&zcz%wDH=npoXlE2&)2k~4)b9-LpDq_ zIpG!4X;=6HHO{yN)xOd|UlGHiah`E#)|SZG#~1j^G4nQzF5sh_@k%idxjHN?$|=y| z5AVSITGT?BuRMIxOB&V|VV1Q~MN52^>^$F^BA-8edX`16YHQN*@|N1N`9Vj!SmNte zEx~+UXSzk0ejV05PPtxES5}HC+(FKu?$xN!=VP7pVN-(&_Xg@}`l`9*Wu>(!l%lex za%TpqFy@t`(aY|Dx!auTUCyNE*OsoXMm6?mfQ6MU;j5U=vE?r<^@oW@?L1$F?od5( zW!d13zu+FFj&03uf}x#UUgP) zb;P3wL3`bYbA<^Ox}@S+uUs60)gQ*1kqj(dkz(f(mJGy~V&@8$3@k*EVkbP-n^vT5DPS@$} zOgmktyEE-{o&L_$>4q-X(dn}Ij4GL_)8#5CLq1EV%W^g4I$bX8G39o;PJd_F={o(L zWvA=(H``9v>2J23uG8Oaoi5i|8TrZ9>1H|o&DQB=IsKij)6H`FJ6orl<@9&9ovzd0 z*><{4e`nk2I{nSD({=irW2fu%H%F(-^<9R)IXYc77*np(<+?9JK1Zj^hGfchx?B%t z%I$QW{?4(}b^1HUPS@#gM!KD_)8UMCJ7uTG8R%)bg@%7Vrb8^Lp;ya zp0m3+Vrb8^Lp*0UkPfmVnK9VjEk%guS$5(fp4&rMc8KTp7{<1GiLSH%T-X(1P@=}R0g^pls<)pbF8WgrF1{ML;U4ZPC zTUu4!7|?f1T#YBswCc*-I+=%D9N0qVWrZc?qQoy2*UdoreX+RixGx3#VsYL7rp0wW zJO%n6Us%UX{8tv$5xAEHbvb*Yy~Da(gFW>pjEQev+$=tEdpcU%nmvKnn@a+dywRNr zf(zPqjBz#RH@iM@Cns-A>~fE@!lg#|fsL`rt~F)2q60lgk6ol{UxyAAbuEw0uBe*c2d)VDRe z1H-zaR1QK@4Tm0|vNb8XGhUXU_A7C(g`3c9<#>Oq&Tromu`e_~Tbo^h{cWyRSId6n zmi41+e|zhflHyY)dAE;Yy~iL2uI60Syzq2v*pBkG%GN#2D$9+n+nNvfzt_B>9t#Q? zW8a`=7sA~hC8m@}B(n_TZJChv%md55J66v)TGBs{L;YoqTV>`lYPn~rMc!V-zJz97 z7TxWtf9-7pYQQY3T)SMX{O6AGq_9jwYn`>m+Vd~a9&E5%LbnHObKh&u3xsRc-MX$l zG2WA~ls0jC&O2v#Sm)6qt36$$w_{9^+R>>K9&V7Hk3*MqK3k7$)kdSk`HcI4$; zkI0w#OKYw|Z*+Nfww90G(Y&+%4@r}}M`U~3(c%vtZrK@3yYfiz%XsUM-tgtm5`@1Y zrgJb_v^9R!Z~RWuhUSdM*v^y0B)L#`N6V3>KaBY(ZNxjVNb^YPB=4u|>DQ6+T*Cww^KPq%!S`qII4FTKz`o;8(kj5_RR)+n*KIlq2uQmgDE{T&Zc$_DjzCOj zqBvagxU41NNo&pU?0_ez>bq1KFPMN#zwTYu03(yQ@UK2 zCQh67PLgUVY3*r98z?2vpr!C{M_>*{ajTs?*Rs9g*ckFwJGkq!SWyxP*P&H ziCxG+&DeKkoA4kfpURy07vwfGM_lyn_O^M4ce$QOY+l~XeBV?lK8f<&mDIXB_ixh* z4xDyD`?9&E?YWNqv^w2sqKM|Dh0J-K62>d21Cslz*F0(n;I(2nfXAsw?*6FPEI<2yDaoHJ?M!F=x= z*=D1?ukU)m`xL%;mx#BqY^^aOv7L4Nr2nu#pPH!UU6a!1U=jM=sO6pb(W(%od_*pD z$27E$y9$miayQ>tc}th8bxTsrWO3xq)_DBAr*#Pa-rG8K^0@XBCy#7T1ovp`h{?(A zr%8D_{@&ht_T-fI3lZAhdJKObYTbLd^SWaTU0W9=xi~u=H%GI4Y1s>!HQL|?PT<#qOq4I4WC@FQGEJn>#q;Hk0hLQTGH6`%$c)2 zQ|6wzV9|Mb1@lFEbNciC=3TPgTRp)wv8p4_o37BKC$8=oJh7xBapL72J#F0+mm9X@ zCobtoow&H;2bB{hF2LW@C(i4bGBMw5g>SCb zsEKI^=OLWedg8r4_m)aIqEk<)$evyzt49@ofv;mmk;YemeD?|l+nBYA3CB_Qxk^9CM67w zADS2+AD@sI8z0MK$dK5Rhk}odA3AiX_w@MKgxCa6bi$C66Jxm)FIvxj!PH~7wc`Oo zE`%hJn;j$?e|y{hAil@82$lror|E63Of+I=G9ZRI0GGz|q9%a&- z_V^)vP70W*!0PDDO3GtKVHZhv_kTo)Hbp%EEKIAkqOI*SkWRSL>n@Ne8xe4BET)hk zJp($cQXS)wTXuLb-NMbiI}mjUL}1MSP~g8MvBFl4(=ZzJcaIG$Qk4IOP{nvZTvbxh<_{oDCy~#Ey)I4 zf|*OC$!NcdPawrCrV~k5qp6ajcW^^X*7M1v<#35K(^^Z;Dfis4k{_Q;Aw{K+Crwwg z*%6PcD#R6NdZg$aGf1mpLW=gl4KRtHO^QY`n-uNhOeH^y)Q^=Tq(iXkhBRQUO=tUG zr1-^3zfAFkq+^7*K=CU{hob!|UM_F;p#3U-HR(*WU&U9FqO;YIHXv)HzzdQ#K|~6? z7Sd*{^(STfB}Kn)B}Jp&K#F!OXWv84RV4ggY8$Bst9D4&V|Fwt>ic%mR($f56!m=% z=|+4%niTc@HPTI(O-YLUew}m+X5W&c{^hK`HX)uQkNW2-9PU!Qn{=8GTnWU^^Bif6 z5PL~)!fZ&Te?{@HD*g9JZ^4o`rT>xQ+m)WHnyBYyydoN_ib!w6o&}^6vEeBx>h}ZE zJB0WRX@Z)q5BbOB@5DD!Nwb9b6Y1U7OgZBHmHbyQ`?&7by8W(kHPDn>5E-ox}7B z$-ir@{$je^B$yjSTtIpvhBnfjXvd_dqAQc`Mmr|W#4KaQuTgrrD&QGwbrqK@HBydz zHIpK}7SdJ6=r3Z#)tjO=V>_sHgxz@xGdD6!jGy*FKP6Uy!pa{w7Rueiny;|t z4IInP*8+v*9XQs>I$w(v*22iJaDK86^j*DYmMpe&73AW`Ak8Wuq{LdPu$BxQ3q!w! zwM=217a5l6DvM2R4<@sBzJe@_3=(H&`xuJQi1nLv`(3UOiw2Gu>qNXjA+CrF(X0;U zSNeOQ!diJ8ur5|u7aa$zOBL271IMy^*JTQ8)xfdr@+wwXmk%6^^&rc>RAH4whIJC+ z>w{gvc^_A%KvzcwYBmnL;Cu?JeBfC2u(U>DRSX=9-9Q#xmBPXaC=Igy-T<3E+E{B9 z))kRqnPUh~U*;H6qadq~A7q_^tc?uP^w_S|dWGd5I99x_iJ-y?3>?eOSEIseI1X6r z6joDYSZ1xV%bT^@q9B`(ALLaE^2*2{!`A9G3hU~DW7&h;wF+zfalqQ3uv!O>HCDH_ z>lD_;fn(XNZL`AKG;l1tyslSRTLzAmt$p08u-XQWW&3!8!rFEmu)d_QZX7t)T z>mG%5_rS62e0^16eP!TSc9XqNVck1$EIVIcQ&{&$hIJ~+NFS{TC@b-ZNzZMqwAqD(kWWZ+2vrF>p3hUv4V7YL}Z*r&>+N!)zmFz*UefRb6z1c%`LGQ5&dsi*#UFBY3>k2~iA;+(M zs%Tz{tZ2;E5shM!Sg$Co18C;FYLiPZglj5-1)0;abR)+8+>VG%h+8_yeS&M4YdBs5 zpXy4AN^wnfodQ#=3=ysq5pcVsF_R#{J=Dd)DB%~@-v0^j$v0Pmlmk=6_vM=nsmJMG z(gzi-02R>x9Hin0cvFK)toWhzTC3tsJl-e&BkQ$NMLXW8D7}151O7qq3BOdEA|1rz zW~F~i(GL~<2vh)HZaxIOByZ{f8n=veT4EKm6rlmm~C+sSjIH1e&W+@Xq( z*_l5+UMJ;abozfkdDuOvcs?d4&rNY?_bTa+@ft?azbML0Yp9Qpvh-&wnoIf<^dV5b ziUSX!fh{pFHx-jnRl# zPKtV44_fh4_(2}_FM`tkr{rNjB*vntq=+{UwBl!oPl|K`pkrb873x8EQ;teLKpuFX zk|G{o-4b^==vee-x%mm|V=j2wd6j+@dEitldK)P7cP}X8Jxuy*yx9OH-pg^Y{|(9m zbQa3sE%Lzoko+LLb|sH^ZafWOydj{25pNagYp8!EuT}hd(29@nx&<`h1H8#o^4k>s z0p;)G^#o|eEZ{3X9%)ser*UJZirFY9(j06;1Ilz(D!N+HT1Br^bc>?5DSE%6kAu>$ z-JtaARr2`#oILzG0y?(C+AM|Xa1#{wuTb7N5xM7}oslNOZ_<%y7o@S+2#<6a-hhz~ z$D2>mNthu(nt~CCbTZz6lBQu)Ax%X)BE{H{LwYh^tC6A%a!FCv^GHv^bOzE)v^UZW zyhbC%(6oYdFlGplV(3~$ItJqi=}@#Q(j>gOCLN7-K2&m4(g}DYN;(a1JW0_e? zyapppM!O>&hkinO0@@$xSkw#YC=5NMr=km!V(9$2qVFl%q3DN-hTW>&9nlf(=4>*I zD{`_4+KSxP5k8<+)Yk6#YJSW-Ii*6*S3#Z0NhfG8Xr;2f$ayKK8#(y|btC7Yz(@H} z8q|%PM*^SZ=#Mrf=XszF$@v{PXJ#KwFb%2ebt_e*tX;wX5daRH*qjm1>*T zE3BO#IS&DKF6SMf4aj*0Xd7~V0m@ju_ea^w_x&EyX8DR)zSl>amGAM<2ITwuRMJ-Y z%3Z#%M_tPI^r&qphPgsgLj6Z=HU{c63(CAH-lq`mlUOD&JFMY(OiM-v^TKqvw);Qq33o zrkXFbQ+=#wx2#h6L4tE=_pGd1`F=N#{0lg7kiLl1JLya4h@=P9w&JhKDwo?oE}$Hh zzK~Ql76!Tx^qsH=&#R_6?T&=8WczU&@>E2;1&xPsF|NylZHMi|#Crw}Yo=^umW}?) z_Q16DaTpCE0UbE>NQJ<(`!uEZt@Yz!tJ97fuiBylj8>HOMLdj^@}OO+>>L)a?al;i zraJ`E*SfB*| zr@bqIjiWll;{zvgAWhOh0}W;ZPGb{%B@Vfi3df0Ki(GX~peylZ=jy|#CK7Ew%5 z4nz@$imED9C8a8%C?#UHo&;_+(!Am=#|IkU3>WOjHv$~n(kouR6*y5<{^VMR9sKyN2hN0Vm&Pa8 z%2D{fZpint#z!5V;+MZa8S-7RB30f?9XemWGT^G+bbaNmzqrQ7bDQFqzpnsiQh(2A zd~&ZCh3_|peEB%2YG1k6jKX&ra3qp7o-wpXH zKAWmP(G^DFs{+oX{_fEDMAsOF?>R{_ixBbSn+cprc{c#3>JOJB5kJ0LfHS$i z>;+Eoq05T+@f`%tgzs;_DLzz@h#y~Wm05YO15WW_b5y=fhJ0Vu_*8lP^7n`#->Vv* z>i>Rx#|`-kaS>PL6aG!;)ZjJ*P)<$CTLYY`zZ(Mh zwixm~r19Mt!1rxKzBe_#&j;|mZ^(BwPBK;AF9z@}2hODadNsbS0em|R`F^VLg#!3q zGUS_9lPYgx0AB%c=vo=#y&g1bd`$s-UBH>t-+qlR62N!Zkncl{uO)zQ3NDT&`C9{= z>Mzj%z8ehr9@O}@2k`ARZp7Um}3-UEoaGcRmWC+P5cwZwYWFdeJ_zHn*$Y7Hp$u#|-U*o$YfNwW&CiV9-jqlC?zTX=1O^1@9%6nG;pADQz{%+Rz z?hfE<0}f4+A>Q^lr19+t;5!Q3rVO^s_P7`WeX6{>0{G?uXHwoqjqjcSzAi(){TkoB z0epvnQ}<`R*xve^4W&<&_r3tWBH*TG=}gYHmv7OA6yN;;eAU32)Zd*N--8<8A#CT! z69y;pe&Fz*Ax9B2MT>m{piLJz>Gg01)5iY}ap&PyuVcKhNy5Vy%;{(pufC(QO;+rG!C>-tg*TtGT z+M}_S<;z>)*uI~>Q2i34qbGIJ#d<*UrtRGUsoT5jV&T!#6L5|iL9)1r^?0M5fEV(@ z@I-vg!pSVWt|pz#Vw+W%`Pd4b%grjjh&%zw6P_IIU1r(3A-eM1V)4sJ)NELNFuRv zQ)Bt!@@w$Bw35He7RmNPyJTZ4u)S@K+@meJE!5NzYmTd3I1+1$MiMLA6ZV)px||keO&#%Yv?Ih`-cVJ)c1=TQ{i3pljT_fh z*H+bS2;ux!5a-~DzH~>(3{iFa$i2Q&eH?owxWx}H+bBL?I}cq{lUuW||AhEW%e(yQ znu9~x;?M8tp#!Tf7%r}%|GiGf|K4HxD!j7h(f*@zo*2p!)c&D;t8#~lQQiXKov&)J zW?Ie2`uw+w26Bof4ex86eej9a)&csNgD1MKlS5X~O)nM?%!Yr!-hzB9ceu67vX2jD z*(Z->6|WdRvAeYaTEP6;InjaRgSo|%k7O5SznG16ZsFk2qpMyXW?V;q9^!I`_x1k; zdC#7IWN7K73|n&@?{C>}IcuwE->pA-G3%PV*Nf@hb^-K|1>u4ZhmYU-!Qk=T(|?$Q z96fa`+a5ZWUHskQ6RmY~PTZPxI_shnyK4)M4-O))dxnYGa||Bx?t(5N0zXOF_?zzd zVoGl1B)vfu0cQFIX|YSn6}2ILdYii=XD8m0-Yl;m%O?YFOgR92|BbKnWGlM_YtgPQ zcVB<`v}>}=abFXIo;wwIy49fRN4FQBJN0OBIIEXdU(|fUrAG12?n~8| z;DGt4JZ886IiX$4Fidc(0G0a%tf!);+Zd0^`yJPK*^n8{N99tF&xSE8FB3X%0-^~S zL6d}52AhP|htpo%NC}(XPuK;7!%Zaaqz{l?fmV^!sy1*?b2a%h9o#zYm@O~V#MIz37+{b`xK)hGH$Ni^vT%2MeeteT~ zYG3aqL)gn#51cB;3>Qy6?}*Pf;5PX19Yvg8-UGnZB97%%eTaN7VA1ROG;k^%NlEdJ z`1}Vr8>!?|{gr%F8^ZD49r~|=)JIS zG3Od%lUDY5i#gpsI2&dU>i1mOpnZwvvX)2;!&FTZ&ShVs1g1o!4CWDO&s)snA8`2? zSj_4Yk-A=qnaum$IkuAnjyw+QIDl;wo0#6oaha#jTv~ZW*fh1|pco~Ew~BHs{5Xl4 zxaj*#g}N%YHmG8veL%Y%r*#5L!};WsT2tzi&sjnb%Q{2GVmbUWV{b=$q!y%P1RKv{ zp$4uFM@`OaIUGTbX#04DMx12UP536rPq5-VQi!mQ+ldExN)yweUdv$*a5|mJJ1qyD z?^_<6+GnkcQ~NyzoGyyvCPQ4z#VHQ*c_<}`>WkuL#P>0U zDw2<2(Q*F(4(6z6w5r{RJAegk*@>0NG(>Jv0d4&(wspQ+faCtGC#6v{Obw?ukyMb+ z{7iJ|Lg>zvGi%86U?D@28gc<^>|>)LbCSQ(=6GXE6tf9irSV8xdW@7^|Ixb(HE0@2 zskl=kVGT?TdV5-UDn0FLl4sq4kU9<6s5`XO9E?tU4PiF1BYD!rR450X@JR%06@mSK z;0ZsCaG{p|OmdrDaHix(PyaR2i;|c;>y_j-@w4bLmEM0{$+O;5n^@;qmstPCx;z<| zXXT_S2kEn|nQ7rklHVj8Cu#cQ-pP*JWf#E5r|Y!+c{#4v!n7c|J>iED=H-f~3@r+} zB`(1>>zv^sggJ(y!aqkC|H<%c2+Y&M?;~8Sg+~zPDazCQtXeEMpT};n$lR5lDK|0E zrbK%t+{E)siC&zXS2^T)q>0%x1(80zCTIGU==8}oIiasar%$cPd3(K9)L2ZYYMBZ% zq_hi6SsreSgzzvh(j7`fx_a{DfvPzjF*cVCpBSumk};B>Np1=__PpO zl-K7JV&$MB?7{0n%ueJh^FCV8?PqFn`QA1Cn+u#tdADkOya`a4zXMosDt0nVX$OuYAzpbF5qf+47&seo>@RZ7 m!J2%}V^QY-Hm%ozQ~ilyC9h&b=X)Et>kvo2Iany<%l|LyzP(of literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a new file mode 100644 index 0000000000000000000000000000000000000000..cbd3dc6d89e548b22c96385f7ae16b897f125835 GIT binary patch literal 17976 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 TPd(oY1fvCcv?m`9;I#L@14oJa literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..e6938ca404c8661dc2f3a7d8724e034938c278a2 GIT binary patch literal 462866 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

%c>z=X<4_CUTj&nlU67l$~>iBoUhERP|0S- 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 UKyCv*Yf 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 T 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 ZG2XO0b;89?xkYbvPY>S}U`viGq_>TYp literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar new file mode 100644 index 0000000000000000000000000000000000000000..5f4cbb09a35db7bd1263e87cc917964bb96b72ea GIT binary patch literal 15528 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar new file mode 100644 index 0000000000000000000000000000000000000000..6086a112c33e17fba5220e34092655dcc0f9c4f1 GIT binary patch literal 455248 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

gNpm`kO_>v@;4A%zvRJ&lYun-_ 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

pYk?J zId=z(^LoSf+F|s*a$QXMjQJ;LQ);}CT(&2@Y)^XGp7gRk=_R)(<=smojb|32=Z(-X z;03!9oN=KxrZj#eT^$aTEhhOG;@JAE*$~p0=Y^%|{G}Z8FIY!1-$qu=m;Vyyi{?-+ zEMMoRiSlKwtP|VZ&W8@^Xs&F`Z8z<^Jy|;gsnuCK$4Rrb`lK=TiR3#?CKA4Tf;!at z?1PSrEjv}8_4bjtE-tk`wam!QX(HwB!+Fv*;Xo;~@~rM{S$89BB6`)d(Rk!UbWkrR zosYL&(^8*}az)ag1X3rYzeXyD|0Vp^X6+-p`MY5=zOOvB27d!t49aifm_iMVC3VG7 zrE!3BCz8JnO8h&KKVb)5k+tVWZV!)mVHJNn{e{VWd1^Jsh#jGZY<--OdUK4oXDPcB}sb}g>G7`_}~;!~0Hw_-;4#n%5a=uqnalNVDKYMMirIL&ImY}|7%ZtHL#(kC62p;89)?aU?F z>U)k^@0v@c_fobqpDYCUmnOXz`s{Zp`no@y4osbnbItv~m5xi1mrJ4JQryQ%Q7_6h zeA~rbYm^@8l)gp=#eA11c8Iz5(R29JL2)*A4n`GpzTs@lEVpwxUCV~EYjTHnzC)8c zxjdd$rzUr4a+fAg;&Q4#!zF3*WbOQ9P43ptcWd$#O`f93J(_-xCdW84$}gV2R85Y# z9aH(HY4S;2PR}=no21DnYw=IkFJA+oIc18xa@1n7CL^@%#8E~%d`12&5@&T9{RK8>ug7!ba1(& zuiTMWXgS+Zo~v-=)3rQX$C~cQQ(Dgc1J9)#`8itNDPpV|6nr0@>)`V=Kbt@2Ir2(J zUg^kZX!(#I-V8@RQ_I;V_S{TIe!lu|_XhA3)fd30s8s=cs=7FUPg7?F@KhBE;M3Kw zt=`TUW^w%}fX`IV1aO&pEP&5ay90Qdx<7!=R<{OlQr#H9X87RsXi6J=c`f+b6)EI8e3|%ZzCwruK@F$ zZ5`r6z_-b`~054Nr0bH#X2k>%L9l$HpX#u=ay%uLk zo{Ok!)V~Jswd(Hzc$NBM0AHu>58&(7<^Z0nRtIp6st@3KSe{2hXL{$W@d131det&s zjKIS7#{qn?dMbb~QJ)LoO9S(kBlyy649G86s{;64>fHfcrRTv)3?u5@YHUEhKplyS zl<}`qKMde{wLgFts?P*)gSsbx8&zKbH>s5YyhvRdz|DFtsl*_n=BVO;yhZ)S|8_8b zSE%O#_)7Ix0oHbR{&q7dIETf>M(dOA~6vY8h?uSAH6E@i<-WQM;tLp+7`@aPE2~`u2k5$tR_TpQj zCK=2+0QZN81g;;ievS7dv)r*r>N@<_TqP{y42uvwfr=7w!wUdOu_`%SU`Td`Yqmnj4$hClcHy+ ze>RwPtVz)`)wd09)woRkrNLf$&QhN?*b9G}`XhtA{5e~_-(bE5Cq!7N6Mdf@LxOl ziw=I!!8;th$-(b)@OvG+)WKI;nEQiZYP9c&FZ7WY|8fVPYGLxN| z%{=#Oy*UnvUwdtnX}|I2hewZO<$OOx!PCc8-uE>6f4#bT^moQz3q|RBXlY zSRNUk_DB4t(jW0-IrqbbUXk;Aop{mvc9X~V0eK1f=ST<3FVjsP`L%{G{w$x=cdn7o zvgOdn_g~`Qyz3ZWzCRe>O8P_Zg*@VVKF0~@@1h*>sW5WQgZvUBM;2Mr{K3j0^{_=;IS0DR_8 z;$OXV@cL5XL#8|cr-11%_eJm(@SldshAiLYbDk0P@V!HR(#VCc^&;Px-{fDB~qBd$l(^>zPkFg|%2mzr>=@QD1Yq8#z-#F6po;t@BY zheyccI8OWbY&x0G+Pdw^)BT}~;{~=xvz4!45Jxni;B|QGr z;2)dk=3mV7^n%IPfA;b#`V*7in4DS3>;B2a?}z68ziP_;cTIWz2XlPLl+OW!A2xW4 z!HASDzncyIV}tSX($577g_hrJ@W%|^YVZRFZ#Vek2H#=uCk(#L;6E{VhrtgTJZSJI z4Sv7Dxam54WTuV}>>D+{)!^L*Z!`GQ2ID4Z{$~vCH+YZ18x8)f!S6Bna|Wjk{=C80 z8@$)x4F-R~;2RD8GlSn}Fg_YOzP$#2$>8+{|GB|E2LFY@D4aU}`wY$){D{GQ20vdBE_NuV<@9||kS&~U_2$MPc{sgXD*wfda z^E&$b%V_YD;MyG$W?e@|I+NW!h~CzWeOa}G-qwyGws+%}bjQNA?HxA;0$bRzwtj0% zcE2Pl(0<EugB^h{>D|_Dj&PV&_z}Cx>xGJ<~P944^ zpu}6ZLGRw>MYd(bO8-GHKArVu6_&u2`bi4py)TG+jU{iV~;DnPK@`sib6hRn+DQY1cd6K9)*Fx+xx1$|Hd5KTVXvJJS;~o zAA<)a?7@IY?ybGOm6RfgThn0=O^DEcVvO8=Tuc~Pk;Xjz;52micOZq>0?k{ohWB%6 z*VYw%EuCAi$V_uzzr9#ZLwfVFJ`{Vivf+EPWiAfg<*GJx zm#f;)U9M_Fce$z!-Q_AY(ieqpe|1sl_E#5$ZUHtwG@SXNnKM5$bLNF+&b-jfnHQQl z^FlKxG-{*!qoq^FwLjY2&=NAII<$z)sSdpnbE-oN$(%W%rDV>W&|)%YPG~uqGbgm5 zVBfcpx5AvN(C27QRp^5>r-~cN@ugfXYc>(s=ib|TaeMa$!(5J!eM5R(`=%c3d04-x zyQi~m00!!7@q+J9rB*aAUemI?ZgWklF|{<+kh(HepIV-}sBv*>X=AGHlGf_#m8~^% zR<>5pNv*o1bbYd%HP^Rjx?=@ zC#LEe)CC|>x6$P#Pfm93(RkM%vaymXBR;Ag&7mY-Kk z6%V_H>iY#^6<#yt&URrR*xWMz`|649&#SJD(mPw#y0b6W>`b>QtSKr zKDs6;Vy_nIqihXQyu8|@kFqt#jyHJ;G3ej$hgd!gol_Asl?(BsV;>#+gT%4#itabD zAP>!b-S4G^_#?a@Iy`g-<<$2LhxZtGQ$?Aj?=gq>EM&|* zT)aMq$G-nuyz3oaO$e{f;c*YcT>36>c%31G3UE~p-WMHS12Fq{#7VjOu)`Y+(Z@X%5hcGo?*m>S%5W5Y?GEoS zFuKfqC%k%xw;K7$vM)|}=Q+G5z{_<%;tuZ+c(X(qj-u~HB*IQd2?TsL#R-r1$>uG9 zAeX*}9bON3EHmOn-!6yu5^M@~3kgTzz2D&t;lW#)gSXz{Jr7>4ah< z@T$N|<_Px+L=;rN94rM--VLPVHfVQ_qmMQzxx(cbrmb%fyc9i*lYIF-u+7_3oLk=^ zhxaUaQ*-D;_j^F!i({;XoFJ2MzvA$?CLL7zPST6+@_@e8;N`j>=q?ZN?hD~{IJ_sp zyWbBr8^1*kuXSwhwG(Td`_=}Y#GPv8oVF!acBxMABrnL5^XWKYKHxFat_!@q=9~xN zoq-cuA9>fJ?28i_-*r5fcsx~_`+aqu;mP$}lWwU1OXl)gC+4^2;Qe{>o&ztRa8nqB zYRDsgUEt-T?+Nfa^Uzl|Ilpk*^5pFSFQ53mnkTPeN`CrwftOGIaqr1hdE`sgDf#Ie z0Iw|%eb0e6m$Ab9!cdjY(B%JZx<@(Xuop1c?G z_@JUH;=A~TUVG*S`0&{vkKbMH4P^7mEFQn1!ux^4s{xPKQy)Y=?`sb4GK)uDqHmwW zYp}xQXI*%oaCoaNeXK7EZ_wd&TD&5Qcca7Wv3N|6=)1<@4Ol$pm+&rkc-t)=s#-p8 zhQr%w@lciVc~czTec<8Mrt`VP;=PWWW8b$u7H^!z`<26c(h7IH#rwX)dm6kX8Tn zz02VZSUh}+ecp73w+lR`llg*Atj}YGGjKn^llz8GqR%^ohtK9cY4OOHa`lwMd(PtF zljHODI=olFljjnj2%mSq!+RCHD#)3RGcDdWhnE6L(u-HCuaCCJb~TD+wr@LsieSC7Dp<0U2KZ`laE zDHd<}2)vZVTQLH!#^S9Uf!AR1t{H*1!s1;!0pgP~d!9#|clPgpsdNF(4^T@L)*ZiN-;}0eEya{VtSMc!e_lD(t}c!2!pgHtyS0SA zye9K_NmD`7j(d`~s0!-adry0ptTR4%&ls-Us`b7j*HK;5+fF0U3;RZwQypDSb#yt^ z(dAU%l;u?AEz_Yp0CF#68or<-JE6q!J6MI^iRdUkP8~^HCypHx)?!5`wCG++l;X&N z`nt)t?u^|T&9L&`BwNJPrBK`BQA-PIxfCgH~E&uliz>B`le`odJ(rp zSgh&05{`9Tg+3~ATwlqa-_BY>5J%NA@Tt~wQAZwgaNNNK4ldODf{Qk;FEYo94_0GR zWdR&hw8anyq<&>pVq&U59Sq_1@L(FQ~-}r zpAX=KT7>vfWfDKmx1Vb;^NjQDry0y*#C^gG4d!FR`S!2iVqVYU%YDMXZ!jMT&bQx% zqd3l2W*?6@;w}L=60deJ+bQBGXZuSW=LfTYK^*1mcM?a;{!MYjjH|c`U>4`Zbg%7~ zINNJ~OiP-1jpdM0Ug6DSOql0t8afC03Q3^zkJn?zAl-K45mjatMdn?`BS;#fGgjmA z2BVRqF*>=m92IYk(TT3{B!kh}r14~f8JXjpZzk5I+M?Do*IcYCYGxLTXP2y{t<@bK zp=CpGQkG|p+rFVA-9!6bfBp+D$QprWFY=5fVGHUTUfR=oJPk+9m1*DDyJqvc^qMZr z8^Tnguo*DgMij=X_DmOQG&a9pY8G~2Vwo|^h0jRyUyuYZx?akc^=G_Ykr!^nR4qO2 zYoSiJKh-6hV0wj^iHF+0hg!Z@ha01ZTbzd*oX>e%n~VpFVW5BpieNzE-3DEFXh3^Z z(G#m$yV!}JzUrj!%S)r$Y;~lL5A0jGHSgCD9N%e$_|etim*k0Yc*SY=1^l&nD}bkZ zBK?=|bGrNSvw1zheD{kJeFN~Yc@F@K4swOZeiEDaAaEH8#tDzvX7io^<~Kx~@O}yp z^29xb6FXcv|0np{yr+TFIc%*s{$TTFAR`;#Cr)H8uQyK~*MC|i%5V(RH>N1~?F-|j z!CRV#zQ;p&tW!x|QcW>3xeXp1@8Y+T`G?Pw+K(STKfde2w}@Anb9h7GF&y&P=Onz0!{dIo5-vHyWB;HX?ruvTZ?o|DJlMQ_mOef+!b24x zzfP}{*?jvuXc26L%W&t<~Z}yy8zdw*CZ`3C^cmDjm`vmteW0msz z1Sev>JnXyK+>E_7wFG|-KYqu)#oHrC#ui4B?7JJcB;NGIHl9VA#$L%CA!9EOst2mn zN70K|8Uw!M)_vGbYTxi4b-w8ZJj{o~a_{7RzBN7R^`m`#Skhp2|IM@e2YAx4Zhi8C zmf34LS+9Tg&Hc0MTaULNth4uIY3l0eK3S@|H+1xD>P(+3bv@M`Cred-Z{{SZN_WgY zIZ3>^|ALObjcJyQO#|IMCm1zL+s*y!X0OK@ARD_+H0vCte!3eLFKJlW+PJ2r;d1oj z_hR;G_u8!k=`|f)?Hl{yvvy;5dfl4N?)LQ?Fw4HXgML`h;?3;q({Gv%>$U5jR^jYe zyYG_z)!rIYb(6R4EVwg%SL|+dlVJyyw#nN@=+4S-O?TE?T(?g?gb=X*>Pr^pSMtw* zv)4sbP#)FtCSPe(eac+VZ#?^x?z8l)caTLe?mU{)@NPM${(Zu&1`*YGh;(Cz5Ix%rJ z?Vi31Eq*@zJ&ZTHrMz{l(67QeRsxA<-8X^CDD5&5sPr_Ghklq=9;e_BkEqkI9*AWX zb^4>H89lhTmj0-J=zbgoqA`?fjJo*o_S;;D=4Jl?76X#iQoODW-4)|?p;+secs)Aa zvL+|ivx0f(f!4VdYM^ay`CBb>&v)TkGl$(?f&`PBThmsr3OY|3dO6kDTDYUN$L}#Z z_Kp=VY?()|*Q0qmPn-99GT5PH-@ojAe=~b5%uDsH?zMpZ0UimyH}EKG$95XuLE`wF z(Xrxg^BRDcQed3$b^wznZWm5OMn5^D}LueYU`T{ z-YRnq4j%677}^B9lo@Uz>s4S46!pYJ#7VtRSL5I>u@ z0-lvd#&Cq^wv)Gmmoz-PJ?*wH9|TXrMO1x#F7IKB$Je2R>$XFm1n(n|i<5kD+o6k* zsBuOA$XA86tdlQ#Fe*3->-wq{; zJ<;cDJCrXC#}{~3DD=bLPutZ@?)*)g7gbR|aL*8TrZ0e%%M88edX)RbWB243_KJ_| zedY^QtofkXYn?nDN7%l^o9-X3RCn$h*Hn5qI$`WV#)M~u2Y267uy4j$`(LWkmNISI zcRx~+oS|b=F1yexXji+r%e*SKv{&tqB-;jp*L&gd?>n=-Y)aawSy#v}6L&67%+{PRtbt~1zu7Y4 z7MuCSw^HlfzB7Jj>@M9|u=#4e-KvD^AAc;B4fwFF|3eG2CKAL^2gmeY3(OqP#T4qLz`s;mKgV%-bJX1IZ1(U*XJ zhX!l0F|5FAOf(?&`YN((gtn%aZ_03$-IHgTG3Wo=Ru*0X2$)j%9XY(mM;TLyr*+fc zoQ??jWWDu$5clB`FXD@40~{Iz+jf%(jf6CUS|*u0&<%|gPFZC*M) z=Qi(I;0y)E3GZQG^2A*RATs*N`Dbu$^A-SfqTRf&OjJL|- z;ne53eJ))PJ_)%vxxa3oO9~0Cwr-H{c(nUmuE960S(M=@yxBFu2|;hz=W_A9YR_2U zjr&{<;=2jwkNuy8z2-RfKV*&lD~$bP++^?_Rw_cU*9H{<$hzc;go zJs{;xl}$3I=U99hiFa`S#;7?!-x|*fVALF7ZBLrx-}yD!{p=d;ZBKNCmF)dSY~^!bvqZ@wzFjI0ZT>EPtkxwi8ID<7?vY z`TC|Ob)B1+5Ay^rBviVW81@?A9nDR~*+a8?t$XmnJW#-p-~i zfub1bdGbt!Oo0kW0!1)~#9wjWDtaBhh18qaLG_0+l=&)N6MX;KeN=oeiQ~JA?jiha zUIQ>*Wxm5}Q@cCx*XFGQw%@nHV_&{ANh@W~g0}!3_?+qfF{YR0;&J@!KCcqf2gL3X>LQQdxliI}^UA=ZKY0vCcpQkc zc_~XDYC=A*-Qm?(Jn9mC3msmA#p7)jp4->PwZ^L;XZ#pX;Z4W69lxEHKKh68c3C`} zhVu4UJn83S_-?q5Sv=ND!oq#p;-QM*^V~kU=fHafa&b})+&;Od5UFok1w(i|;{Igh z`n!>F%>r-~o^J=$3nQp}=Hpb&ou6-?+;iTI@%!Y)p=0&lEz!dhV)eI1U%tJh(X!#mRm-+4-1O7ovZp4GSv@?xYWgGKMwbs)Buf{ePtG(gUi$zt;L-+=j zM^Sa~{;3qMNqOg3_9PNhu}QIt*yPwbIKx*jR)Awc9G}1JKNXKdy@&a!Kh`Nd{OpQj z6Z`T_8J#v%|85DDII;iz3C0u7J6+zHZ(q_^*hj#)!POJ+Ug-q=6TZ2AHaefE7tbB zeOI>dGb`IL)p_$KwN88g5Ief*GRDV)#fy&h^#*_H`*4}z;kBgQkHFz`C{A>^?Y}VI+1_P3%1Ej{#esbhijiw$*UiU%qTq=oiP=2AtEy$JaFIe zlw>5CSrnW3i324s$JFfu@YnbO$R;O;f8=S1s*)?QR;U_tFfw!8!RSnV{fq|>oW4o3 zXY4xgak+BF0|$OI@L%RSt|1y}iZ|0nAPEbB>?)%8V4;m-|1ys!n(MYJ#%+J3ym)cl zfJ&_#PGQlj!9{IlPd{2R>-Rqp8v~sq_;dS~qL%7MChPbtued#PPgn6GRdK~YQqIBI zu_bmzy!f%7BJcWloXvtR-J@-( z(YDlRTWYi|b<)=@;M=9cd$R`rRskMs!zO8|n1yr8j$rwT*b&(ED~54AakF)>Z}xa} zuzn;C!?`kPqm@g5hUqJgT5sqDc6J4?9k5hna~awA%=c(@6U4d}7`1c;fVS z)G_~<(^6bgjDljPg>8ou%@4M9PgDo*i|e?Dv^e$|eBHvV(H{V2ne|*m1?5pKXBqTd z)RD)uoN@PD%#p{nocZIqxFg4U9SA?$Pf*~<3mshK;9>`lad1NGpC!Sgr4vlwSS?Tb z^0AJ*M9cYJ@LY)_AE)IkL!KL_xED7a??ntPBEc*#F<60r-pYUWx%^20N7ar1j;Z$r za9mv*zy+!$fD6^U04`Ez2XL_}4&X6r*lHBUkUu{U;IZnt04`Dc19+Ue(8BC9I>%t9 zKZ5j+wd4_4q8yQioR*&wm=nexqx}K-Y3efpJXPHjz^ALe06s&l4B#^r_d*sI!OD&0 z0eqII=wEs^l}oKCe$2%x8vk#O^Sd&j@Xo zdJN_>!8u~r8O&#Z>knUPF!PV=4__3(MXEf2i&Y|k$Eg2CeltES^OK?p^^(C!jmIk4 zo1A5O5*GNCJ;+&xCq>7pzr|4;`|Q3b07v3o4&LhEw1ZbTnEepqsPA0@a3r?-7>O^m zqw=m_|cZWA;&bqydwpPr?#Fd_n)wEWnlEBf$ULOXJye~ZReu#gf0dWDIhK>b( zN9j*D%|w1$qrpw)h&F5`>8s`XniQG8ed>=(qLq^mRA@&+hAn6<|9#B zey+iD42F%GmRB2GW-xB1=EIilc>8d3*orlzH)D0&rtThW)3LO#r@LdTKQR!Z#r^BO zC6hPWzF4*=hcEhXm!$G~TDq*SN9IL(*h^2gpWAe9=h?5_)Ulyu z9ebxcdmDQ*16#f9LI1X1d>VPXJdH)QukBxl)4HCXz7Eb|G^xayrY}$5v?+~6w!P_% zR)YP-r@gEVh}IyKZRAb z!& z9Y4<5O$iA{;jMLeZQxDG!DIKnt#1H;bpmmsPu5Nlf3E!?GWyB+X82Q|xW@oiVr)#D z$apV#F8N+kl+{75=yQ3c;N>b;=NWyxmaYuERoJokbi*q}EuUYZq<0QP79o`fqPU6QluJCC0Z0jqtcqpd#mo;xT{1c&}PK+8~7S;>cW3b^dW4Rv2%J#iPx77%yeK z77xvKpXb_DtN`!Be6biOr||Y|QYiWv3dyOAlySo25$}f;B_z}lCzyijM?RqoM9C9%$>T85P_qbkDnF4aR_T}?xa$dq{P;R!+*+_L*f zGBS6@&I56vSWD#P1*&RzK?%dV1eDAo#_x*lJGQ8qWe3!Z%%b=eSFeui9B82(hUFra zB?qIGg$E-uinYB(G#NdJw9JSc)amup^NzEt@JjcnVa2Fn#i(J$sA0uPH>}XFmk!uT z#^|DPx&pc)xI*m;3gYpiqIeMn@%WfAV>sV^?AWnIG)GUM2EczM`fnN9<_XLxD+Ka> z6{yV=<2mKuy5ewh6Q?S&s%p)szk>K@lE$6-UT-=ctIJnT^7drAHEziE^iX3^dmM@Ut@YW2* zXN-drPIw7NKGwk{4j!kk=X=j{;~e>TwZ`Nx+r6|cSz+)#jVGzA3}$(Wsmbcy22&qx zP38u0R80@yn3@#8afMk=zT@6JzvBzlIP9dX4h3+L`auB0HYb3`sK)|0p*|D9W7Vzz zE>SxJc%14F;PL83X_V?XW!ERZ7&wC7kZ(cGc2SqXPXeRPo4tD$SoP5WE>W8duF&%FN7<5;!(UuJwj)W9X|s{y5s6^AnFd=Drl0=oAB$dU z@)ua=Gmh-Xq@4X-iB_c+7~H@k^srwgiVhsjmm~N|<1gXuA#PD>FORtBVROVmMQ3?^ zK|Jd4a4a$YI)1=9emFw4=IiiK2$BZta3HTV7^j+7%Of75%XmD`*m7KA@VN$y?TFZ( zgxQXW?FkB*)`!k6t$&Weh?K_F2ID4aEVd&_gV8~%uSa3ja@Q6Ho$p#c-N-L87>Uz- z{LylDlpgQ8MgBHcIjmAJ$lSPjVBuQqpy(TREbqQ0y<{D{eV=9N^)M~L#^7Rc(%Q3h zWB2C94eeNMFl#zu?I0z@X6#c(tC1C3Gg*TVW785aGV$$Pj4y(REr+B7`(4q)(a_M_)J+=~9oMie&@t@pnQb8F7NrLkw{KatrLLo=6&tgAdFkg> zXRl?JvT$vf{X?i}MyO>*P3W4~qZT0P)Eq9@gq&|kuWQE!iZlr_1)TS&vln-1MPEzj z+jK6gQzUhCCH^qV$fJ<^4{y#Q@0U(WgHN&N<3Fr9ACSP~Oosg^TUgtVSWnZ1-a9C3 z3i9Sm%{AQ=b$oTcg}cEkwI<@#F{ECO*S@Zg;Gi8o@!I_ue?j&8DcW$(@0hr_Ir%#r zZQc;@R3YIgyhj|~Zr~(-;)HjV6ThcG5E;1=Ki1vsaGwTF;wMh7VSH@fi@+s9!cllP zJG{fdtvPs?JMnYZT$lKz9eoRMT{4HhS&qIoV9`OkoS)_J)`sw|#x)T6_pK8k*L~w! z1~!lTf>tm<<0RbIfXNdVW;gPC5Q_0b6;(UhjpQl^zk$@&N8Ys@5I0U_^}sxrc+kFN zpOA2r`^E=|JPG$n@K6=0zSN+JU$m+$Is?H1sq6-_a%q-Jb1jGJaUBh35R#c;_=-s zyqym3C5wkgz~}Wlyu;un;m2?pzUXVmxt)$u41i1gaBF-X+rl<)DtMCKaTf1g4zJ4M zVJO|#$M2M_uNk~H_%VJX*<0)d4@uEHw$~&b({XO=d&1(4WN-0|#bf(3OyBbskHhX^ zyq7E<^CyfqZ1K>f4doRh(7R?rq{T^ZIU1jmu zqzvPAS-j*3ye$^5+~P4W`TU6+0x#Gv8g$ZrrGkMPcDfIpAo<~Iw# zQFyTP$e>}Gx1GnF>UkG=n_axIoks}^x3zx8_3B!6!7mRlD!~4t#hV{!`bg8gO|$fB z8gW>3?0@O--D{J(Gv^MTbJNvLZD-MbqNOQ*WGvUKc)bp1XX>+f^UmS(Gv!TOb>pzV z-d^eBo+fWyj?SFxa_D_F+B1t-e&}cu!XM&PSJ-q)(}boHJ2pEy5Sw!b&%Nnl6PsAG z3AK(_c{;M!o)NgVO<#L)Q&Oj64q`t=$3B-1uGL}3K8@I`Wbt6Ex#T8yZINtv!MLtt z&iOHoH~;&_qvOh0Gc2_gc^N~_M%#7lV$HjT&o7N^EFao2DAp+C)pf-x#^@D9B8qE} zj6ZNFQ&9e|nRv@HnTrr!ta(S5x3);u<|G@2r#sS;9D2rRJ+(zW{`Xr>z2feDmp)Qd z{bGX3u}?d9qtRm1U1CvA&<0pY#Q>%F^ych2MStx3I4N~F1AqnDaU)7NiNTU(e` zeXrw9gImsCoLq8BZDD04%iWHjzN8MvrksAxc{49Yy7mqw2M@vG=-lsB-je+CmRn2z zI&yB6*12J0*`Z6ocnOTt4qb|~Lt7sB>XuuF9#KAH?4iq&>d@to6&`w*X3&DD>y|B> zl1*RjLTGi_+{(R1O0-2KpUFg9nm37sk(au6oQ;n6W*W888MV1(K+chI{Nj} zAzzL+K30KpthO#mOYLf$*K-5eg_E~5>kVYr9QOvYtfPx#yo}w+HOIT|2iqj#*p@N+ zMzBc;Uz5bv#q$%<<@S*s&poi?Q+g8P!?+z!d@6CBxVvytKlzrOg?AR*6~8++gpGQm z3vd&^@ps>R=DUy`kA6GP#*e5YzqM&bPG^2P*fu|&w4`vIIJVK9yt+ZM>Uea|62&;K z(7LzmEWWeouEM(uhT`|c?!~=WXY_yT+qfCW6NVjs3|+eMzxG7pZ@&ZBhBeRGi0cvM zYiq`K?(wA8E_=tT!%o+^*>o*MUj4z=G|KlrBDw)LZ1pMAcIy9Hn62>N0kiCRE~0|+ zsFw5IdM@h7V_ME<%X2YD9(QnogA4WbESH`ubmT=^&gaf^MUK2!%XyDHSM12gIQqvp z@`QuOYCgX|o*V1POSGKj(sLz_e4K;FYkv0qKi-i~&~kp4JvYITmuh*bh|!}Jygw5i zJW2D}-{rYUTAmaLTO{6ZzVkij$px_ok#fGXJvZ6WKSj&4&)5|8Yg3-s=NW?~%D)-R zZ%hn5o!>T?`e+;WcmPM$-T;oNp#YAn?f@=OO9Hr1T^hhesv>}k)z|s~!*F67|Ud9;XHac)aQk;0bDR0GFz{0X$J919*}e7r>L%>sDVHET2@y!d&-g zox$uwqOI8Vz&z(YAzondBiQxi+yE|9B>{X^z}AkoVb4cR=4gFqtG@~0q}mg}pfhct~QwOJg&QRxxswL(N-;GFyCpDqQz=lfImk4I}~O0CDgYKuF(9k>MI8G9mRE* zJ{91PQ@0z;chaQjcy*(}d<~wH+Z1?6F%rhn~%y-D7=p;44V7@aZ z!L~0F;7?HvCO;vDT&as4%=Hn(QLYnbJcxfLLL7;|>EJyMzT3eW2g9t+chuM5BTs*= zgJFK=JM#Hn6UTL;*vBu9m}4R0$hVTG%R0K%Rbs%iHAr-OYa=Ay=dDl0<5I|{ZSu-n zbhB4($mctq{z)9^&+-;UWO!eq9JGg<)@zO%Jbzx7f)~T7rX1HZeY~F6QC`6#!kxt< zc$eTv-U1xSE2O{S(Vyu*>iQh|K~vK}#?1zwZ*Ysjvkkt&;28$v z;nCq;XmG2+GY!7VU_3Nh{}O{yxHMjBaFxMV8;ruK<;x77gG@VK+eyn}$?V%m!$*7h ztHum*`#1+9@f?gFUL{^vXU)Y=JaW6qQuzOt57rd%Lr<|(>>DbT~R3~Xb z$7@A*Z@O=jgzj^XPP8w|m10lm1z;yv{Bx&Or0tzc(`n`+GKYo>qc`K3GRoR!3qzMPTb}N~t;;T5=BGHv4MCY~O$Upg zzhD`>&0Xm0!G=D48%*)j*ZAw7b$6tjyz+&7?cT6nmoh`indQDLS6*wO6lYp%jMMkRn_$UId)sy`Js!Q%?n-ZY+mSMXY)cAJDV4}*jc!>??qvj z!=rYy-k;eV>Iyw!jg_O@g=gpC*p6C^65n zd5A5U{Xz|RyYEv=D37Rq+AV+iX4qcN_kxzeOw}8GD=Z%A@^Q4h-4uCxgUJ!Uqthai zoG&Q}Wm&qtGuL}c*-kk zUZu~xKXG&3=@M;|1J`h-^7AL$?hxZf+A|n@K?S35z#_wtP=HmT>!+Qoi z)=kC9HD7UfT(_=4NH_}b6ArH#7}Zwa2~XCKll&V1FITwB9eu97u%x%f;n5Bl%@f~A zxUSvv3*fQNEKYdtI)YOWkjTiDa1Y@eDt!CssSr#B7AMzy10FW73cOAs;V8V%Iy}y? zoRWigx5L{DUWvs6)GmX+cDRp0aKDl9AmLu;@ET&d!$s34pl?+O?>>aXaK&*QZ3&Bh za(*{>#lR42$9_7tZN*7CZgcdJm&?wZ_mbhtb}Tz#~U&WBfpOlinN-vD^|=zA(peetngUx5T2mM@*)!+Gj!9hYA@co4jN^5syTyc9YJm*$a<0r2t(_X+TF<=6ce=xS%!(f# z0iXB3IJfifSu5Oe7Viaz_nZ|jikPqOYYy*4D_j&YpZAc%d(G0v^hkQ|aCjxiWXTuW zSPQSm;Y|TA2|wPqN%#qGCC=^i)>!&rqV4k*I=suklYHj)TJ*7AXzObQZz=p3E>3;k zbcgq#rEetr{D&M>IcVgl zWQOE(as+*47O#8+-Ykn(F#_*0i^seTOGm54OO3!=ZSl?-f!Aa4&K-fb-Quy15f;Du zEFRxmVY~+|-i#4=4_myMBk-QIc;}D6d)DI3vUu?J>xej2FTmqLemIPam?NM0n0Vs2 z1%>zuX=DHkk4Nw_Lj5{!ezO3Jhj|tK9qswApIK8oFYkRxAK;78npaV#PN&_wwos2Y z#|P})J~3ZljXH-jEee}vHARwp7gW_xIj9c5KK7E~DT5aePsz}NewDspfQ)<>v4#Ix@Qw$t>7sWY`7Bz_>ff84MLA zHnCsCnYeSzUB!174He!~aButru@AADQH9^JPB*aQ z%I1WL>mr)Y0tVf8rBVZL+NQECn{^TO3^0{=E~0|+sFpJUo{Kv2n3nUVcrND1<66!P z^<3PM7if7lK?Uk>P5juth@sW|7gl`r9*Y4SRUZuCm>LY=xatq!0`;OqMIVp6{%s3K z)Y!nf4-xd5el#E-r)~}4F;2fxLfv5GjQ>Q~nmvN>83pFC-c!(E<|%F4K5Q`akhX2N z8_YbTZQCY;nMYiQtrbUcw0&A207qh&vG|Ud^>cB=Y~P6^Mi+|jXj_Hgd{+U?HbA1> zYgbLH@X`@QBL}D2pY4PMB3sKNJejU&3F1PG#@ad@rzMr@p+BzE`rxl^t>BOU+Mns; zb<8*Ns1K%ro-GV2?i!<=e;NJJ8K5y5-5R6Or!g{FW7M5BKE+^mMjWTD3&-!cL{`Aw zfgZ~T`ZC5M#9Ksb`9S-|tYL?yqz76yV1cmB?P5D(n4Ud>xBAx!SVPEGZY$dRZ(O+n z8@S!b-Q0*UQm4-`V0zRhZ_bimUh)Gxd!J`@e{}AoQ}`E&1(f-MS*d`yB^r)?E&^1;5Zjvi^H3Oi&F3tCp>0| zt*;g!DI^?)_veNuqE+CDjDB+d1)Q_*5d8w$tp<D!#S__+! zx2npi2Zr}gUQ)ZAT4GJZ+tvN?mzz}my^(wOp1xo!efMsSl&cEvA=AD&&K+5>mrUE{ zwVNw8SKf2z_VP_Lu$sy605OzF8P^CozqO!g z#};*7#~JS{$h?KNzc=bFlVM6fvi7+im+E*?UX8a@@fgw?vZf z>tc)}m2W01d7G*%J8+&pKQ~!$=q0R?G4;TCo1zC($-SA0hyL~6 z@<%F?$^H_(X2?$TFaGWq9*5_J2hRbkvgr}C21ZP?&fD}KzwlCI2G6SikG10}WvOVxc^%e7D7Z6zSL|-g!te3A@V*QGX~J}Uez$Jy@#wenjdk7Q(P5{V=cYrl zg&mUN`tn;-q7?dE_g$<0srxi7%$nviz}YyVPctA#pC)itFZwhCa`b5exA}phPctA# zpC)j&-wb`40Xh0K1M&h#UZ~~!eEo%vyhzJ=FFaS|$cwd{`Rci1wcmu#G{+SBFs=Bo z&vbVHqt7vbW9t0@99KO7T%fKC;6l|Dz(uMyfQ!`^q_VFgc;xj@8O*ZAKGy#O%yYq8 zEq(+oF0LCbE}|x=#sDr==LhgaH8FrEso%@RI7Tqv{wD!kqP`Kp|w%2^__-Pxgxf za3p@v!FM_MCI_b-e652QIrtI>+kMFF6P{_wiOU_FeHOgb$HgTof%%ub-w6bU zZdx@B4Q}Q)rZ;nMy)8P)zX)OD zNPn#t{w}Vkz6+JQokt{cFOT!R_bRV{44C?O-x)rSlr#N|H}4nah`J6B2R%QSZT{#C zum2(nGSeA_5tr6;zDdt4(hFxtXej*bW|XQm!!A9#)(GT0gF&CQV+ob<8g=h)uX939&m^K^pKA-%3> zPT$G)ty_L>_d2JDwx-tyI^n%;`lI^P+c);E*}N{jrVF!Juwh5;$%S4}T7!4GaBZ%c zhK%z@9Yc1udjL^e+%KK)IlAKYY(C8MVJ0nY-`L)3&n={^o;vhfdk64xO@B9Xe(2ID7xS9G6*X%#ye1 ztTaX~J1dRID)lm2WR-aFvP!$MI6W*V~!{$8)TqYzO zg?G2ZI~>BxI6Uru@C5wCiN5RLVTb!P0AJJMgval-&3hhzcSoG?{tF)Di7Um2S7h{) zbH>}|asJX8c5)jhGKRr(h_xFi%AL>WK`PgfcprGH^%dS9k-5B=z-!2ZH>)^5UIx6S zdFXozytX`eNp$Gv6TeRI@(K5`5PdHpE|SNL)-ZTa#gt-xor@puTPc1A6hJ%JAW zN+6aQ<}rCln)+M(Y#!&2@OttXj`056;T;CA%J2}p&-;YKOQIqx`lw6v-Qn=6EFO!O z@c10s@mm0%q=V1C@K!p!F7TK>rUOOC=Ph)28Ss+uBaeL1SA%mq-21_k^kVqK=S_Eb zPk|@tW!+Bnxx9lG4_O(?J7n>28p=Ct@$C5zZn$V7`SD{s!{S$J@i?v%#!Ff})}h0A zRThs!FTz7r6z$NgTL9h|c?rN_uSB0&o-_$ClC^{xbK; zHyT^2t(jY$@7U6y_kk&38DeRjj~xj)22%vf=X9O|!u^goRs=t9@Z3%3JW|~> z!>kU^HPjF5HRUrHSt@DrES(j`iZc6SSR=h)@afF{mof`D`V(nh&?Oelk!Ize$1#f4 z++NTeYl*bgwFyH(f`dJ;4;1V>ynpYOnyX4H z&pJ51a@v6jmGnt&M}x7PoaFW|4VS2wwtR3Hg$E;27hpVSysA3*N&Jodg%{_Gzc=U5 zOZV*iYH`K%mc4qF`@yd!w@37P@v9#BIq^VR}zk6XsOc;^m?t$d? z%E2m(Sv}HKiBwZQONW%a?a-#(+dnv5s=o1y5BW<@WKK+5c z_e?(v`wB#|9Lb@*_lO_EdgqOU@kt*Y0vjCy8yx~09RfS~LtuEjbnv~J%T>YiM8>|@ zu5!k4R>>&N@#yxdCSFWgk2d2k%SIl5318ct@e}uRoYYO;mK~>qC3{n1^0vCMSlu3f zZ_z3%# z{Z`w8^`Mi5B;mF6ThfRL54IESB)#nT@)_8*Yn3bO#cf2cr zqiSOS$JCktj;rMXT%g_^z=dj702iq<1Grcv0(guXwmMa~4)xCic&xhC!d&;c)nKNN zauxsu}*d)Ps1{;5ZGL z!E!=5rs5{|t76&?}a!#pC~Ldvi7 z^i9Kc^NDfYQXHqf3+vPv+)2#AQn+ZVmrjoNGCom^|LXW%V8&B1F01i{1|u^yP8pmu zSjKnD4Mw8%c! z=pUShmF`%S`*QJiFJIWcp(BlDZEv!}s@pWswX7eLxn$T_wq@__O>e-AuDk}1bFEC< z*qa&H>Wvj*s#f2I4GTNg)^Ba;#Hg~5yu~ZUhXc+Sb?)%iaJ@dgv9BNNoa#}yH4FiZ zx|$hYIR=>_L5?3a-)nhqrlD5^8X$L;58SBqdEl6IeGKa7SA@d(ub=*55^9PTDy2+|U_kb3+%ZtqxtN_U$t2o$l}k zz2A=0-vST49;FUE@WvO-clK(Kv zL%gAXK%bucv2xu-@Kz6#C-ITTf4?2VZzsQJ;-cnctiyXB{40cnqwxL%=eEB4fJ-bM zzx8x4;Ait50M5mG*5T~|PU0s{^gRX-Ti?^b_$2yHc%Oui&0{=r@rE4UtH4$Gi4%SO z@UZoz0QmhBC%pH-!{)UCP^UQIp_&oktw6?h2?1B#~b_y1;A5L*K*T<&)mm^5nH*;5nag?+@Y4Mn*~*WAvW`j}sR8 zUYLy^?{6u7W#A#peD@qY`5d8|sqY1OEEh!%?-lTPJ$VdAc)!KDt?xCEcs+S6Yr=cp z;l(lND?D<9_l(0U0WS$Z>SOU2-aee$;m!h2(!qMZ@Yt5Kc?}k?$l~pEc&ova^fI2J zug~H2Sn*>x!n@Al-3Q)M_%R(Q5{?FDEeGpjm1M0LU|1q52vBL6&BC732?*hw0KiS&^KW5&?F5Fcc;ZeQ#6#f%i^KQ z70TOV@tEIX`S+N`LlZ2N_q4@h(@ga7niziKo&)b1JcHuol=sHw%|xb+rxN3Y$0K+d z@vlYXn+4z~JkM4FwtoGd!Gv!s0gH$^RaJAWzw_tUB$Kss@?X2IhZ$?l!xdYJf~NcS z4Kx08%)mOWsdxsWzSLyia zKb|#)XTRZDV-yUcqwzo-d)LRxPl07dc9cEZyrTlf@7oZA1HAZa+iu?$c{y5MzfEnM z6py~F+KL;ZE&KlG$nPTmGf8C@EvSd>LbGS5;e}JEQ|W~hzo}sG)S&*BNOSSptX)Ux zBmfsZZSJ9fR=x&N1S)jb! zEdD~$_7kuU8t3Lk3 z=e~2<8T*s_V&DJW$Npy4duQG8`CtCmXTSQ}S3ffG;aC6npP!9In#a%kQ5ZFe%UFjH+M9C{lmYmN)42K=-?^$eE$Q?t4LE@MT9eZb{D7~E32 zct_=_2M4uP#9Ua;B+qKs_jv48uzOH*^tpF`lTBa1yyDD);zc#&`H1?(y%X&q%u_sS z3^8g9F=`AkY7Fsa7(;lkm=1Z%W{*`kJ=QV!%IxL3Zo)aTX1xCfGu~e}w#gffKOX%_ zOMeB~)iG2^|B^cYklj_jux1X64^H zoqxCOge^w>goxS2Sy$_DLazVUb89a(R2 ztT|G{w+*UTozr?HMi&;HatyV9dM@ z;J6;|hAQo1=*9Sj)lm~e5AF{GxJZ31fQy}Z++*~-f)4svphnV&aX9wh` ztAYSNL%oc6h~vK6-xq)*?Hj%tz?0MxU?c(!ODw!AXtd z>NVsaPx5(8O$;`DLPjD zIga8uUjI1(I1+!{!S^}%4hIi7xXZ!p!xl&VR|~+AxZc5+TbT9*7h0J7atE`YMI8A| zySNHq=6hnHXE%_5@(P2gH&JKC;c>izSjOQSlxic!@qQem=u6ne<07x$FwyAQ4NP0$ z;b|E6XE>DeKGJT1_lrCX$t&T}u0it<81Dz|4wjkYd(H6~9C>{qj?*C5e0Dk!*PD6h zNXNOrOwTMH5l`x4_^mv8eIF{?V&Vf~G5s$yu*l zqaR1(83v;hNn;dttxxO`&Nnz| zims-kYzQ#hSq~2`>04_L$zu$;v7_V4^j62SffJpNmQb~88Gws38`J&$&R{>r6_37t zQF=pqWBWkblQ>tfN1=UVT3ZO{-Hvsf7h;GWk=EQ0y8$lv=^77Yhcb=YYubA@r9&sA z>!INlYkM%59xx`*K=!@VCId%X2_UcQdax)gEe7g0t!vttPMcHD8^iz0X?}rJEL^vq z)&R>p7Pb#~W&ysvK)M5&g8bpV;COy-dxyQn?C9WrNDklLH3iozFES#ZeN3}r`w=z1{^Mz|{b(Am>|>er2s|OaxBH|Tf%TM% zkM)GQ#sC+-Ig9b8JEWal$9L&lIeY#Te0=dgU>EQJusD7j>0Zar<~<9HPl)gE+1Bpg z@Ym)I1DARt{a5s{&S&$A0a7`5-+`aan+3q{qBzm_m+-K8+`AK>O5aKRKJD1)S@P~qou19+l?IwgLn4g`435G*CZIJssalu@6!2ONFE zdlyK|FH~W*abp5{_ZKr@?E;gIA2f(zZN!UEt-T?_uy(!~pSB z_>qTEN1r#{;nji%m70gsP+qgen=}G%mBkxryuZuhO&LMo7K=C1c>j>a8)>}%0gE@% zc>i9D$9$Cg=H}lM7LQ~1VZ3K7o;}|0>U-Ye(MCk{QFjbKaW8@QK6yF9Q%>O>;Gq*! zeb2g3cs#;8Bl@NzGnxh9C_G~q(A(aRjVrK}!W-EI%&o13bpTyk;{A=SO_7LbqRvWR zFN3Nn(E<8vC`?94$*xL5_5Dbe)y~5sa-D4Hn+icvJjvQDnzW#rXTRo3g7goPt#tgrC_T->k}a z3=H0LKGtc-EJ!p(TC!u+42$*4z74Pkza)uew~~b2J?V|fc^6jAPj1Sff|*XvO;)bu zCKk!LRaG;REBg9+E=j_8yrUy|Lrv%0dF!g)qda)Q1sxY(jN#gWu1&pbaqQ3ZbPsUt ziUF8h_a`stfZzHJo01pw&DIM0XW!gEyT0{}2lq64c1PdF&hEZ7{R6PKpS_}P*`mf3 zYZlkcUa@3J>%!)`maFu_Var!E1d07O&-Sk9?49kDg3*!X(UIjhE_{Jv=a;6QYLw=d zV=TwHRrU8~PJ*g*$L#J69X*>m()9pMeWF=s zMUhJVbT=$s(y+3%aZO9Z<#@JxH}wp3uiZM3UenRlz7g-A3)XJzPOn?j+1h> zz24Scd$ewUDF7=9-svA_Kdq=I9C`hZEX=Ph_Y$K*&qY*F9(8a`^OX^JeH`!F z5WrEzy==tAP@79>g)_QZzZic_CkcP{ zT`+Fs!AphIQ@t%kAIA2J@wfk>eeXA@U z<1hN$b~gJ3cR?;r?uXmXehs`|ix6Zv<IGGObe^Or+sspD;BDt#x^Bjw23|1#2#&8j~Z{kDNSte9dmpw?3DLz)_+-%I+-ou zq@}w8=WliE-3ne#IgTujZS0j6=2w0haJD`fQ9*gs!7a{@RP*l(O` zQf-&W;K(+0M*tVt^KB{ETg6 z`onb6*7}R9q1Y?N9CNF9ElsiB zu&qlYvpLnZ3$g6W|KFRpR@U2%TV%3|FT*j`$|6XV!U zp=-s@<_!R|%!|XLryZXMo3{_R!V~Gg!n@7zMD!d^BrN*L`6is(&-C-a?Rm6oFGhk^ zQ;~6^!)^cmF?g$lgku=**CG0PagC&jYFhD*XoC{A*U*Kg)4}%P4fvtS=DUaS?nnaB zk6|*seD^ftXY-zgr?f8_j_`P&Y~BkN5A8pn=e9#%v3R`aqR-{MX7NU9*Onj>5vP++W#D}Xa&eN+ZoBr+!21gkf-I*zB3&7|{<@HMZC6J(`iZ(X$SVAA)UK_WoBzD> zJ$UcK`QyiB>U0&k;_JVRN4z=Hk(MEUReX-###)Lut7LIob6a*SH`4Nq&!Mt+(6}yc z&Ft*$8EtTmHaJHcoTClSli1)4ykJIZZRR%xlAp&a{Bln(J{dZSqWMhc z-q#8j!?783qB^8XrWMMcPs;}y9&E45UaOuwq8@~t2@o8VN41<8?YXE5%3}_WYd#a> zxws=QaP$?ZkD2(D;er_2r*~QLWqWv207n(=v&C_Y`Pu-E>-KF{jy1If=;M*sKWSm^ zHG4+@mjuR;IVW;yKt4uY6u=2J$6&^PBIW=NAwG-}^OWuDn+;|ja?F}GdX)2Kv3-4= z!OS!6726!(7X<3&ZhJb{m@~s=dsvQuY8vK_(S~#y8qKAST(^%gHqEv|6cu8P(P-Bg zWR20@))*yLV`-nmkW}L-M$SYWcl)}zqZ{*KmZjHs)3ngErr~L(FghCKQc{sEi@xd=zm;r1s?Muz9ZyEaeWpXAB=X$bG*h^yT{kz!*W9<&LE ziIC1ezO#4YXZI(h0GOYAFCRDV)#b=C)L$+Ydyn& zH@3gOuTBT(_n+LS?$I{%_hWRvK-Z1|K~;#~j_qp3v;#YCnRqxdL0vHJ zU}U-~FFdk3zT{VtqFuxDlb1ZwQueJ!FRLk@@%tapl79Z7ox}617R-6*uJ+qw<>i}F zk0jd)U%pedR<*GQ=JlE{7bkf{z3bq(!ANo_v-?9sgAWZC4t{iaL6nl+AEM6hcB5yXG@f9`3k z`_PPry1N#16%Kjp4#rgSVC+b7^weZ@I5Ku(^ZmoAQk za%pB)CYd;xIpwCx#L}CJE9Nv6=oAF)78nE1J|c1?p_rS4k1~#h*!7PwEYa5#sM8J> zB1Pp1H5|FJq6vS`^j13D&^CKV&kluM2n(BMG~JK9kXZ^<{;rV>L-ujxT`IVOcPWY= z=PlT~J$gKEe@ToO9Vp!&MNY?>O9nm7r3(-@U6dm&4-MBx&3c0~utVV@rsCc$+nR6R z7yWW%raJtMLF{LL_=UmP%(4Sfz24%Op|8FC|FZWkfKeUyx%lkam9$z(Xpz8x5n?3- z77rT<1C|{p)*A_ABLjYupa-&7h{qy?EjeI|mn|G@Q^#qX#OWoelae&K7l_?DEfm>x zQs+?@oTN8NlNPsmJNFjaBvn%X>-&9kX3owTY4KX%HvNZz)tqnUJHL6JIrI3PnZQKx z`YxHf2S=7h1E?dxxvuZZUnFYemHb8{vj4@`odWUtZgSV7#t5f8<5W{T$vD)#ZO-AN zO>&Pv2Rk=9ZI6xwMO%EZ|MMfzPkQY0BOwuszYve(+(kEpru`j{4i+7(4SoB}qtT-s z@mKq=!~KWaoAwVD#rBHXU3>33Q(b&!U(@~-@xh|q$J*k7q1at*Nb!5sYun&wgYvIRrPIq&pdivBg0OH z*><4hz))?$=|kO&!Kd0)3R}lcA#3-vlV=_kC z>G}m?yGO1OUm2RXuQe`)q?;^((WT|!d{6hDB#U(`(7X%v&aDfXO&QI*+A^DK+B2I2 z9huFtE}4xVZ&2p!bNi0uHD<~uZ(55eozi${N7d2Rq8E=%S{#};BHM-1Gv)E__#ek( zZS8G;*w$L~qqf-Y0M6cIo^%h1nM1Xa@1ndDt5`xJh`&Mcnk;i!ZVQS}#vYNUYsQji zYz7-6P3z8z0BT@tk=qVcupJVy#Iixz3hjER2CYzFdt%vI#5LGF{JQX31vj0C&Q%A( zbIVTh9{M`Xy4CRfo$$Q8SF@H&U$!W}Y-@X_Ds+mWK2pmkhW9cnf{l5Mj{~3K^)~V-fW2Z~vf!OJh+(G2! z!S?umK1tC}@JWh(ek4<%U2U`5)gK`ow}t(5d%SUYS-j{=Y}K!P^&3Gx^Lvn!Nzdu&FVcOt_-Qr(ar?^v3up&-te7A&m4Gmq-?luT4zJ`cP5;Xv0H|4 zPlo%K_di}FUUy;-9gD?x4IQn`c-7t0)lI?CqR-S$JdJW6^q0HyVVtGg=C-0P^Pj$h z912v(r}j*{DA%$0Z1J_y?Qrp#y`SFea-;S0T;755`d!Cf+k5E1u3DXEqr-Zw+xb17 z+^bvdGqUA-X{6|&D~- zuseXix9^7QpM~aCpY7kx@@45h(*KqI!DG(rffBS(&i-TJd1Y>1JkE9~lx&BTD_bK6 zZ)h3k$Hm-`x_a@^iSMb(V^Ox@pjvHEW`J9TPWXd z^Tv3)mCLu=yfNQylhoVo(|o%n&~~?te!Gb?lh5!So_xc(adqEtUqHSg&mNb5S2Eus z$d9wTuHvHI5O1#RhdJ${&jd@`2gLKQwN6zzACTb{_o-Yo9`E|2gv_T zm8`j0IB(hw;aT)|1X_;F#)i`$ZestoNcL}?eCL!iRNF8ME&H74qzc=8N(%R!QSNt3 zIi06NqWzT9_+XPL5qJ|Ut=M)n82?~x&gr`N$NK*qZRWv|Ybu=i!N*oK1Wrfhw49MW zX}rOH@(nl6?f37h9XgpY=Z0^`?r%G~QMHWWlbLgto?^>b)%eu1Oi^*VtJx_HoLifL zcaQiG!nyirbz9Pf@h+S_Cv=!|0EH3Hxb(YNUMd zQzP?^I8Pnk_omDpKZ70?TfAMh z6Hbc-x~%{FoXDSmnsrB`JbPW%tDB3y$~W7*e{kPyk2^8E4~2do#^TjOM{1u!?YMj2 zGb0NQJ~MLFU@Sg7)b`LbBNf#137SD|zTMoYO2G4}%J>XCK2%m42 zvR@yTeUQpmUw%D2F@%=z6TfU*|IGDsPnA5@-0+>#OrZ!Wy?@`k2XFe7c)Q%OZO_PrgDZbFt>in~!uV?19j643xM>fR@Tp?!#J0(iZBuC8 zdrl7_CVW-~kGXxJL$4Yw4C3+BDYm!4@+VL0Jo?s;oq46Ijs^wZ1Lu&+l4-I>6qqM_ zJ+aTCZ%`Y5qW`0{;nU)%I1@P&JQ65j$c%-q=|4mn)HXJ&_L4qs|Es0Kc&FC{OVBTh z*2FU(+xJ+gG2a`-xg#r%-`C|80D0Dat-p8xJ);!TwZiH|u*0wLLm^ug&dEeG0v)BN(@^-*$P^?i~Vc^zQo$ z&N}%)v=VOr5$#P3?af8<(Y;YDHeoy*Xq?ir?}&(fa>sSDRX~rteB>J$aH%*kFWwXX z)<}4`w5_x4CD_$PuZ`-J=X_Tnjo2qo)_k*Ho`HH*fm8`mjj^cH%&{o@&Th%kE$ADc zy6zlZW;RZ0%vWC^WT^2mpYFg+K7G4to$nEenY-k>X;LXh$@6C{e`2Jp0$1;%y?3Ol z;?4Q!XU)2+Xg6@A)Jcfa+Qh?&>mn~Eo*Y>mbGCl+vH6V!k=m`L@q&Tf`1{0ALFC1) zf!^#$O>aqjLh1g2U9i70lpT4YSC8pa*963S*{75_#axZ-AI5k-G&vT+OhSZz zKgKH|@w>m^rmEbRst=7Uj)F7&Gmm9QXwQvj54iSz#D!P*BJsk=+6HJ4OtE~(aBQmwg& zsx@Z&az4$P)Y>RzY>|~&54)yt=icBxZ0lZM*xwu}+*zB`R=5-H75I&Wi5lOUEf=D(=%}9xjaUkItK} zRB?)FVXzq|L*5U1?UsKLZ(P^Ozs^d-sfO3aZM8WYT+$y( z>lXR<9{Jb3tsd8AIJG&A(zl0ylY$y@9)v?((g6`-SbmrLEEfnXysyEyX?%6wY@48K zH?BI(veM?$xES@!FE6|oHDjPQXS@8{FwW;c{kW$0P6#8e+J(yOZ@mb4 zR=a<}ab&w$Qz+xOa=dXgpMkc~aYVDg6ML`?7n&A*nL2OZ+4>tp{IubF!g%-h%ecKV zzH*Ogp|F?x<)X;i3wId)#^saLGgF3o;lF2KY8yQU%wl&Ca@i#M}Y$+G;z*8O42KU?~XZcT%{>dg~g5{qt{g-<3 z^DY0Vg(pfryN<4zX!#dN|9b6>ud@B|EwsWbwEQPY|73nnviv7Ye|B+PGuiULO#1UR z=bFnb|0&XcaY*}5k^a|PSo?B^A(kJ9e6E>l$(ttqll6O=<$t+_r%V0@Ee>ZB`SYhp z`mgu=i!A>c(mz=rW?25k(w{>^*A!d+Go}9#?JZ_n{xJ)eNItv5t|<}w)$`B&>VsmI zxL0BN^E-@nKJ18`hc6ccK0IA?`*4xC(}!n>CLb;qi+y;ei1~0#WczT5xZiu0 zn5c7at}}2zG>8Ttz5+@*I`w>;l#7WzJXic1m5h}MVE2db`|y16mp;5ee8z{b6p#Dx zRq`yiq`ZaVE}wsesPW-SafJ^rl4pM<@4s670?&aq0Wn*A*M}F2VIN*1KJCLxg?aWG zcG(cUKL09lyANM0-s8j9i83F4mx%cA_2R78Rx*FzE&jI;&k-kl_&wqeefS2k--oNk z79Xzh?NbsEwc=eq|2k3P!}TJH`cEge@eaNy_;=JFVz%iH>i>@w{< zahbyGLliifB2!`Z8F-f4zo_)M{$cS$BYix}?VAd-4^ZGl#9u1RcRtT@JEkz(^a3YW zJgqR_=>_=E>LG>s4li&fh=jsRCC(S`Rd}AnQ2}KRnSQ>b3!I5!iNf^~7l=~d{e|L` z%1;i-3$WSfu)=)j6*yDH`xWLptH7BqdK6wSagkW7up9pwV!6V62NgKQVyVJ>=M*?I zMXAEaC60+4h53#ta7sj$Do;RQA+T)h8RDOM$o2o<7XG@0hb^3Z_qq3f%JMh&nq_#8 zS^k3--eTbn3$L~?zpK%P``pxM0Gr`0v@rLt(T4tfZnPO|pB$E3Wx38}4ni!Fv^UF$#Z#_I`J&fO56`0?Pf2yT_#SKiqGS zn7$a?orhF>9#(tr4!QR+9rR~@Ur+mwg?OLBeXuEifwGxT#6`+3S2pvD?zym8E|X{@ zzNN};QtnJY-S1SkmR}Fd`|+5I$Y<4em%vk%dz|jb7erC!#~Ij6|8Iz4FGYSt{wIcr zw2^PzJDK)JX(K$@PD9@3fSDf~c^~4*@aeD1;V>}cu@rXk7lk-Oe}pT;fxJnShw>;@ za=Aw|<8hoAHzyp}h<_&DzmZQ1v70vBzYLq@{sUr!%f39rsZ#b3Y=-kEv?2c`*yO)T z8}SIEy^;A!8}is*(SJSd=iPj#yvtO4+h{|MtY=?P^&RP!_5IJ(epHCZBJz-aS?;iz zFO+i~-BAzLE3C_XlES(4M|@d6(*C#89e4xXAtwQwa{6dPP8IEK>bqQ2R*6xFOo#Jch3{5)jl%aRe5b;3h1V(E zt#F&d2wciT<0s|!D14K`8x>xu@Fs;($t8cY!Z$0tMd4KnBT-WREedZ{c(uYPJn7%A zFcL3uhr-(x?o{|*g|XR>4F5ibZ&SEm;X4!_Q217b?^pPCg)vtr!&{;74uzL1jP+9K z->mS13b!acsBojgyA-Zdc(=mK6yBq7gTi|iZc=!k!l*PdeO(H#MWK)TyKF2iukPBs zzP@`~=a$WzaRy0p`!nTLr`)|g&@A_^t?D~%xZ`{5x{ms;c6suoyJMPmtsTG~;C?4} ze{ajJv$HGFmn0@5*1UOr4I*j_PZH|l?MT7K6} zU|hF`-rg;}YjCoJ&ox=1$-3zB>$`fr5B}wLe99T6V^iyTyViI2v1*T!uPZbw?geZc zkYM0AI(4J_1l4U?zp85k9w0ib>h~&HYmapC&SQmd9k&#a$3w2$)U~M-`}<)#z%|{Q zx_VdlZAloQy%#BvN4TzO-_~=>W}F+^BfWuI)U|&bL4D3ETp)aV|)LqeteDJ(zRK*)gM8&blr;w$%Wn?3odM4UpwHIF%ybvAyb1>k=EVQn^2q~TpNf<|sXVT^CZ*5fls=WI ze3qunoTVuUUjyul=Nx ze&s6{>vccc)y*YFzOKV~%^O7H6>qz`uXo$k6sa?|#s5n0zRGowuX7E|SGnZ|k?sx2 zSGaab77t%Co@?^e?K!FUkjB<4+jBPhr5Aal7*tVDZ~MPwpP1Pg4`b-;+b8B_U~NL` zB4Y90fcu~(!PdNAIevLNAbkB8ynnEGXTU2TgZCwi7X}`S_rEM&1#s>d@;+wqt_K$U zDWlV|$L7IfEP1^auL-;bS{Q6C@4XhU4;~l}dPehjPP17aKZi$!$4bh(+Ts;q9%9lM zylED%0=(E5yf+c38Ez|hW2NJV7H^mT>cJrx*0qaJ=U~ca}YePF=?ZD)s{T+?l9^B^Ooic z{PZ>PPp71}uXO`5ubww3qh;9g_JfD%InSixeLqckCDYOiw<}HFXVT>TpEP-um!}uM z?P>D9m?rQ41FzM~E&NDc(*6BC1v@3A_cE1nCw$f%p2eh=eX;Z9{>*F zhgXFt0S~WS&m3RqrneC;EDQ43eslfEyG7a8`E#5QWF`voHGI$SKyf+Mal&iztZ1F;s z$$VixXx<$b4>K*Y-_CF&29NJXGym3tr_+Jr^W-hGc?<3_mXDtO`U zv3M_m$M7hx(BN&dc;7VSu|KBEZH>kI9(b)v-eiM!y~SIwD4CAS3?B7(%yhJXcSOlU zSH=rB&*HrSo~{SXM;*U^!L=zbbak>`p$p*gPFuVM;OX+ftJvcmw|Mp7>2UFi^>~LZ zUJH0SpYclccptKOYYlmL)phuP~3d(&9Y>UJP#J z(boC57}sY0y#!u4+{i02cxXO-yq|-o(>wb-yf+Nqob&K<5fLqq?{FPIJKQ3J$9SgV zEiia<&%?Xk;Bh>fN?wb>n|~hOT7$>&aw>Tn4c?XK;q5SZSDlAhthEXYgvy!#i&9YR|*_y1}bE5AS;hul_u|pBuaegU5Fc`+3^D0p9xzhk){!2-|QL zccPN~m>n=>G>+ zNA5^WobeIZ-$`7)bs}~Wd}^zRe0%Fu?#y*E(v;mCXsc<<#?GDD%`dbC+H2aw*u67= z{gcX~SydEsse=KLlQ?-*%N3puB_HTQmpy~LzQ2u1> z@0XFEhrgNmlTJk%LmTEdwl`KZ9$Mz^_sE#;iO++}Q_Ft&5IK{BN^LjwuKV2B6W$#tUZYr6PdGuTWhyw%-XZ{#oyg?kM(+sdqmi!jdCt+ zlyhmLoJ$+!yaOBM$OdM7JLPaXLmSLyjO$D2-xe8VIw7z*Trj>$#y%1Jdis?bPV;bR zl4{qVR6Bc^vLExy#+C$9cI|j&PlY^fI4ohjsv~LIKjG7$48JM=p@G>m_G3rAZHP-WfKAMKUu}pPwl<}}oF^^DxVMycm77inlWPlraZZP9G#q4x z%nwY?fg&7ua$dv1WLPzAOr9~lGNimKcRB@g#*YNhx+Btp4PbM0;TQ7ja%-k z^MASkSEz8Cj?m8Y6t_J!e7~~3)&oyZ30^7{)_2|AzI|gK@AN*0808_OX1XRdCC5I1 z&(%*KQ*|8)qrNE;$1tg~ZXO(0zp1|K-c?&Rb}3bLOE>)@p4|8UL$%}Ix>E%)JHWC| zJ|40TS)Wo!H}A2K$oEKS7w>V94i{Q)r7o)XJV}()l=YsYcSt)`4Q6WCFv+h*L;%gP zs9SVZWrfJV(UpB&{a4<&SY+m9-I(o63=}w%oGF2+foXxu1I0KWARlCWpCJOA@GLN2 z3&5$(OYkC@?=u><-!Wb&!}gu#Pw+E&Yk=$Np$y*(G|%8?@}2@l^XeJRn*)-``y3cL zERywg)Z+b5!_VaX8-OYANDAKL7VlZ$C-Kup$8P`*ro1Kq7L7KVcMlv)-XMU^OLBEO z_}({pLn-7j43jquz`lewS{|oI$A7n!JBalXndgwKk1#KbR)(pTTQQL*5No*i9$Bd(!0n z6?nI&5$?=Ldf|4a;Bl=UMe3Qu;GIIHSO^#XSP$6e8^#Y&@=X5(xBj4uCCi;WWR?6z z-Q*2|R}FXa7>?#0!nMhxjxFyek9AV>K49@)29NO}4^_hBZMS&eHh7e)<#k%TpBUjX zKAN|};+-|*A&WfTVvC2NiWfglfM|KMEMC;$;W8yJX7HHqRPrhe9@o24@v03Ty6Gu- z)KS*?jBayEUYo&Vd!8!Xgu!DsIu&ow;Bicoig(c9Vc3w8cgWyPJrD1Q!NV}ZlgDe; zM{S0|qyCLH`qExwd;^(xy>X-F(S~zE-(Q7HYtjI==DBN(JT3dGEeo-B_*Q3uUVZH% z_bAZVTdy(R&Ow+E-Wp>eN;>fzPv^+Px)xWpcuqv(L}6@d@B4b4*i*eC_U+!HZL!Gh z+jxphqB^tGJz)aRbaS9-sNG#Jq|md^6^w*eW;9|Y@P-5Yo4@DC&2pu1*Rg{|kr_`m zgiaPL2+z$tB}%6?mdiD~;E}T@c%D}Euin3mXKL*~hE=`j?*4-#!QsbdIde zb`YoO)eq#p9$GN-HwWIpDJ;W#2ZjeiuZx%{8w4X<%`=ETKN6|_i`ogVK2lqLGIL(! z8^?axwB@Oj$A9^o2Scw$%AIc<0iN=mVlSmUGwAGzLY%9EwBlTy@AU>srfplhEwgm4 zcaqN86C1E1C|6tGB%3Myojl`WQ@dLwFRk8PTD`lpdUt8{?j2dZlTFO{*6(7nVRrvu zHqu;Ux%EQUSlG?e=0~{j?eN@O*nhL!;ThYGW1na2RgS-nZ?W5R`a2Tqa6S7z-ARB8 z*JAn%%pQavJA&Wau@CGT$MO$~wZ{EiyJ+!YM=bK;p!h>AO4{e%+;3oILVwMl1g zoc(z$TFSZlVszvfE|vh~H>Y}TJc522=OV~EMH{@or;UCd$L5&Qcjt&P$d?#>EIDTk zVG<({i8*MwkU8WV=BE7_(&L zY@tyq61#h;Buk`hy(sGw3p=)VZ(P4^;eFc{*0x;0%T<2VzRB&V{g-^#z5!L7&o3SY zY1nx3+17^h05rGaXYw`z<8kr~$9^FbAaZSvv( z>(ZFh`YR;pb}ihH!S=?KHxth|)1r;`vw0r?&urT???K$C(?l7kz-xmi$C#Lgkm+DP z-Ho3)hf)DRce+s))62GO6@DhK+Tbx9&0{&4yjFmia^p}|^JZDRgdvY*o{BeU@Q|dG zyn_ah@z?U~vG^hI4#8g=oqzUNyc%uqUu#d0^(Ad{ES`rpyGaW(cxc?#ZQIy>Z;;O2}>FWDF%K|mV;zigm*F7h_xMT+PcHb;&YS=Z&7?tzv#sYbE<7Fw&ZVZoW0){=n9DoHSXpwPaw|)=%*K%dMXn2=u;2w_bN#uSfMVPD0GZ zEWom%eyJO~EIj0%B#XM)94L)!3-^Zm+;KnW0A4oc020q}{2$K8=>Kmx53r{HiK5`^ zp;;e0Ry5-iI2X3CJaj4mz1cw7gj0bt&iu?%uI{fWZI}AY(SCQvVDGVz%z+Zj6L8i6 zx#4Ls{|=rnsjA?mq4%Ys_XYG0Vpld_l#a%>O^J&js;hHh_vX%x+t+tpps@S4UD>&% zw`<|H`xb8R>)v?rq}{je?uGYsZSLyr?!34{y>!>#xU&A1mWFlB_3y^By$Ko?-5mpc zUF$mI?Y-OJ($U-9b@#gU-R<{m-mWf{JvcwBcb{gFlW_%;>a`n!j z#RWJ++w?A_5n7+q;*P;9;6Jv;Y5Jq$)H238N6|fJGKO%q8N`JV#~ta+4y1FYA^H$+ zQv=hD8}HNRGJWBPT1{<{eL(-r9FV}=D{|xER zqIOM&_=SoOhRWzyWr=?<;>URfvkw+T5BE=f{z17Ii;MFV zUsRZRN}a&ZD$G1Aa6+O3wlx8?`5F;&)`81G;p~uSlu8A9gW5cpe1i{Ka0{ zB?udKF?8XW4!Se`&Qyire?9#%2xx&FiMeAU@?}1OFXuauDdagAkVuS0I*GA3Ir|CYm_kJkJoYHXOIp?8eXJ9S1gFacJtKiQ})y z`zA2wGqln2Zh?cz`vLG+Jhmey?-#&r_-Ui%{Usd8(}w$SXg|8?>%YJ?+d|A4NJAZY zwx!x=-g9s;<&pQ^H0GC{!{kYu7G}t}!nmgQWK5pa^FkRNmd(2ZyxTPib}HV{H0Av= z1@H5at;>+XU5`xS_X*U|;hYWgh2`@kewecH%mK{Hlml@JgmEK}`TGEVChuAB=uRHP z(Y*B*@3_HZ8EM|l7VjnS7$3?bNAnh2yl;XRgBy7)KFynjYcqboFyzra6)%K$qYf9h zq~uL9c(_c-D>Ha}SEmYhvBBf(RP*flw0iKq0e@|DeX-}$rXa92MuBS{ZRC4G-`|6b zYtjI==3(gAy{^5pPfe%2<$T&T*DOkVKJA-s!{X_-EW{TM2S?_|#5~SriPAw_f2H4@ zN#Z<}*pS;O&cy=J(zZBf+eVIlXk>mgR2qzlxuKK)m^hS(p8C+pqGQJFgcgJvefum?$-0oY=mR zg~HW>sg`qm3j$=Yws-J*V1C*%jCmpeerRNb5*=;Y%Y^V!MZ)8JQm2JgkZyBp*+R_`o%Fi`Er(PdAtc>MOC z(kZWG!;^?Xc<{-Q3K2aU%Aa)7i3MUM8(zMzbmy4|cGp&&j3VS+BQZ1}4D%3T6t0e* z4dkyp8xG{3nz;Olk>S{)qa8g3{g)q&o^|r0r?SqhJDVxUPMn~Na|+i{UWf9ho{YrK zowj4n+^Jw4-ud$f_8mEdP(zK)@zO>&KVCW)4dlHZ5{&PMlJP7Flza$r-yqYG;pOq~ z(0nSIpM}XL=+boRrRmg5)2Wv-zozF!^ylbU=l`r*$ z{dZl2yg2BOv(un5V?1>tX2g}lD5JjKb|HCe%4L2Va&OjhjiBAjRUG^&!+G+R2IeTl zj~&qhe-@x?aQ?NAAC&%l2wfAj{6iMbkbG8T*JN1!nHJ8naM;4xQXUJ-HQAPbL@YAm z%X#*hKJ17IK8$&PW9-Ix_8<6ghWMHfXNo`f;Vki49}bHreK=bT`fx;?(*r-5fOBv9 z&oj=q&NGf$=NV75&ND8s&ND8w&NH55oo77RI?wnr5jNrzz}^l2tg{w&0HgiI$S+dZ zKysd+`xX7_p#7tZtlNMY820w+WKwZd#Hc^>fzh54ZHJmSwO z%nDxMgvIYG%rfU*0=pHil{g|^gRKqM30~CzHt~xV{u2xTk%gbK@b6i8zk#V=N&O^k z7~X&eu<5_a!1P~d;WZY%!NSZJZFv6`8o(xIxoAVoyw|1_Sgv1S@gNGv$P!oosrWsv zzEtrw>YUG|?z~Q9p*v3%K_p`2FLLLkBG;<(H{b0}XgJ`P(jPpQ6a81gE`~qj8-e^d zY^O@`(27o?`*rS1mf>SML`1M>LK$pgO!rB72NY&`^M0l;0--XztJQg=m1ogpW)pYi)?(1pT+}S(e9RaD`yZW{#R&)*Ea3OtIpy#uBJv`KMjB;Gn zdG9E<)?OU_sE%b!o))NXpl54)cdyirl}8I&9$YPy5CXGAu(cW>-kuN|2&@Mnru zHUW8SOt{A44F9%o>|9+bAV0xV4tY@FrUVv{eCHOLaAPlzCam3lw|m4?{U+S0%98mc zvD~48@%4@x>}y_+?Hf`Yf%f(lga6we0{2_D9EK`jJ&@g3X*cs>G+f;W(Q{C>%ft2q z==0DI-zY~ucu7a~(0LBY2QKMk9>m6)cM)}~kpanxqyK{Swh4IA@m>FvLwcEICFO@giC$M>4aV}GyK z;Awf+f<&G+YrxYo=%%lkUncK%@Y2~s;S1sP*6(t#=v1#G0b7T~ev`hY_e$`X2ij;q zoA*D!Yttmysd#UKcY7MV+al@7`&01Nq#-W{>s0B4+nFZs&r|Tqk#JqsjMgN~oc&7IHKqTyF|=8@`(QxKa;lrycpcbV>p`k_qaBBE#Ors9;%MV z`;x`m0p3)_qbx1&a~AJO@bF)TYp!cPZt zS{~acllOJ-bUNs+d3^Rw-VY2Os*cB-W%2keKK{$}n(Lo7FBg4a&0}9(himhS3?9^( zQt}oUJjzWa?|OrW%aptpgU2yWDtT)S9=iD{c^eJhr1S807(5IsQp!7E@c3TR@xxGp z>%yLS8oXvc7|Q5NIQw`%L?Stu=c$Eq;^JExpG7MKnXw3BES(AAcEg6<8?`=I<&BO7S47IH%gzE}<9h7%R)mkvuodD|g=Yc?ZThGK(!|@5t?wwqt9(G&DDC06o8I_Q9WqL=Rp*!+#>fe*>b4?xyi`}J zS~23~A?wfXBQNxy{^D?aYO~If%e)+!w=*~|_uHsXGlt_=s{ER_ljz+FY3Xj5?k@M8 zJr2_Ooj6k6{xPJQDRzz|_qFGGzAn4nsFS*em@?XXf{ibu=0HZSbrDSxOMY)X_@=dGWVrr?n}$u@5C~@27EN{hmjb61JPaI9TWsq&G zhOWF2xkW~NtCif~KBWG=l={jA=RvPOuJwiYZ!6pZw+qb!9apuQzpU{7+r}-|tV0~^ zUTEAdX1Q}PtW5_lSnjfXa6O)QvhHZph6_{U;(b!rq6PW|7cTpDDf|At8T&#H1s_Iz z>Xx=^FT=3>_Wm=+3q9)8Aiwdz8iD>I)rOSwr6j$36u-zoFi2wq=)H>9sP zj>ej~fjPqUW5>cl3x_P6Vc|>*XNhkjJXT@XWLf@U>EEWkF-zo+Pqu|47S56PvsrLW zj^&?g;XDgZuyDSGqv9`&{Gv|8Gd}EyAs-HkULOvLwLY97>U}sJn^&-PY@6JFwRHt;i!1coVY~&`6~kl#ANY#AHGa{ z(1)jp0Uw?!*7@)>(cr_Ei}^l0UFreo(hcDBfq&DJGH?ut8RGjsTrB?5hi8h<_;Aek zEhscH#JxWMLf;-%0j!+Y`TQq|VU!1*SS-}(__V@&+^N&?h{AkKsngM?aGAs*@jivC zCC(6y3iBDEPDiB=XNe+(+oXS3WGGxFaklusC@;o`O(f5U_^!fyCU`!?mldv-I9Gf@ z;SP!O#2+ZkS5<*CK@2JE#wTC&D$MRs0Y1X4GV+5u6LT#*&B7BcoMGW#L9RBG_hSuU z6Mx&nUo$XuL|!s5`OjPUQx-m8;QCY!sAED? ze6u@W99iL>byIu`!h(BbrTglP+#$qG#5W3YC+!wj2PJ~ZN_IDSUkrBfY9$BvvHW-+ zbt;P2Bzdf-#i%SS&q%Y<5ouI9BCy#Fa1a>d9RV&^Hq=a{Jl3~fM%J^e7!MugJ9897=PYI>_G6zO!1j+14`ZIa<-8I|$;;Xwhc6CDAY5clEKGh)kVYw_p zl=o_hR9Po6)GJt$ob}#8#54ES>E>|OoRm?~jxXZfw zT6=1{`?PvdCvK};RCQ-p@0M+ErE9dh5BgX4cJ*%Ss!I%r)l8Er2?QzAIfe>SS0{pO z=U3d*(Q%l*(HO)6R zlr_}WRF$o2xVfsVbydUas2c)6Hxc4XW8F`khCMO*V!G)7KDM?i7JWa12*G`-W?>-B69+n0~V1GklD;;hoUg z@+K+&vrp22J~ld!`0vx(3IS`wz75SY7LV_E_H(q+yuB8$1BA_*1Y7eqSiDp4Ls!T% zn%8RaegQ_c$4bguZ1ITErSXiGH{IfKA5L^tJfqW&VVEypo&sL)vD~p5A;%W*^74=S z8jY2XuUotrB6K_4w9)Z<77nJoet7h25^Np6r!C%D@Tv`-mbcI1RbcGZF$Qm=#d`ug z_FuKp^3Wak#qTNb#>!{b4>KJcGe)#9*jnCCK_X9^Q{d?|(oJ8Vv3TDEubm1)%4iwr zHv8l)fl^MrCK-M@<)1qb6_2kjM5z^QKt5r@)ITd07VUKX7fz zdmcQU4(5lJ_fHn@j1eyH*Swc4-dQ7Dwnv(G#NtIUPH%!6^AC@J$9u}+-40$1ZseiL zdc0k@Hq+4$p3Xm1F^?Cwcn85_Iw=oT$K%~(@ty)t*Moe6x7gwxHsq17(@Xhg{Eis% z&Zn0*Z19kkDdn9qc(_c-J7e%Lb&!&G*5GkUAyqm!$)xjz`JIXvHF%gpNy&>DJnk8k zN?wJ*!xTS~;0 zRZ&rC{9U>fJNr~tT${Guo1LZ?Mvh4ROC6Wl<%4J6JNOSj5oZf0 zPq}v5^cgctX3f50?))nkR$jg2uDXV0%`0xa=3Vc;p=RaHt8cmO4pDX}v1~SeSKv1f zzXkX$#BULPi}AY#zw7XO4}LZH)#2BG-!lA~@mqo4P59l6-x~aG#qSRM*5da*{MzvA z#P1&bHsH4jKWr|vtPj6_{C42?0Dgn`?Z$5}e$ChtwgoS>=5?(#&8ya}THVTP>=xUw zZgoRTL){uA7Jj$Xu3OQ7DN4(6>s1Y{4K-_U z@5+_6i0V!C>r{M*WpE0&G%TyByJKBzGn-}bTN+l^xu}_`S;v4GbNYE0F_+;mznEmk zQRbbSW_eHJl67ljhT%TS0KT!N&dox~Qf@745M>W9UDr_K%69#MYh8S6!>Z=SJJ!`V zt&^GO-h=qTeN-GhHx*AzK1dG3X}GCw)g7&FnIbal>YG;spiI}SX}Ga<4KloW-7TAY zHgCCaGXsYC9o1)KvvNtD@sc{@C3VJ2>WuG@IwP8xPPdKy@BTL;u)zfM8G`w8C>sdm zMMNMdCS;0y3<)`^!5kDfY38mL6WRL~p%6R&nHlWb7i3N=%qgBUaSmOw=$#p6*L!+4 zJJ!=9>^4s>oJ;qdnV03nLb>dpP0yP}mkDM3o6j!k^yqB-ot9g2xg<|7;G9ZkVLARz zoivYx$@BU5vIYD*83EUm!b&~)~^bBfqC&6$x&cOKUzGI`*R$cb@G zms3)}zomtFWgL2iXHCjR@=LMajGn8=oHaRj)@2h!Zjcc~@^doFB05h3S&Z+01H-(y z5EWUDp;OC9ZwvmH#>l6SvjCK#&e}%}%o&#t12b&b1ccw;k^Y=7aE&AV8BdLQe==N0 z98mJ<7Q_y%8nadhF|(>M$Hv@`USrlAoN()5R+Jz{>VE%-g>yX2Gz5_nKR?gH6D*u> z;i!ctdf1g;;9)nug%+M<;mH=h%)@T_rg+$uH`T(^EPT0zr(3wl!ZR#fY~h&}j#;?G z!lf3TW#KXl&$jR!3t!=3H$Tcf?ADjL7M|x}xBkrc@RPFq7kJn$uPeoaMt!HwVZw(U z@fw>c&zyVnw8E^v0o30Y6{h?E_O1P6g&BT8%ok56%q2%tT< z$LBv)+~~v8#5F!#CSpE3TSR;~EY5})x{hz5_?8b}CXV~?B=Jcfo-7_x*p1&5vDN3F zBkuC~mx~*G{xMOauv>o$L|9?QDS#EGf95MvnSfX*exNY<6P+u?F4Skv@eosovRC1k zBzB|@BQB+(&fLp}JmP09{7DOc*ur})yw$>YS-8Q%S6jHm!qW{*oy2SdGrqsTPa9%W zr&gxV@_*jKpS17+3v=C38_MgjaEpbnwXoJhqzvBApEkVy4GT*dVy**fL;PI}|CNQG zweZI+Y@W|Td4rb!Mho9*;YJHzW#LH{mX*&)&(C#YU^D!`weVkB_=tr+X5oh{+-Knq z3*T&E>RM{U_^@BA4Kb!)Jwt3HPwJHNby3`|&RIdnCkpIrbZ>FG-1%f@tGjmL+^cxo z74L3WH`2MsT?27?Tpdd%E<}uSy4^K%XT7`D;~+5$=-#PxM>n`@^v({YTX?_HEyN}) z)#N?ku2DKW-8o<9{q7pAv&UU)bauOIr_P|e2I%Zk=fQkXh&JB8*InCp9#Q+G?N|G- zJ?u^>J3~rG6q(*n{(yTvjdLIB6)_wkLO72J0jh8w7vccz-xJ~>?I+y5TpWO>h(932 z)3hJO`W|hNpP`));xO$k?s>irCew}(Z$kS-yVuo4cD4y|oOquQ!?ac9aOzb#tWxE0 zqbi3MRSvhSa=1p7Lz60pWvUz+R5>)Na%fiNaF;3v%=0Z~c(xK)+I8dVOrsdBhU zmBUI^4ppig-lfXnI#mwWs&c4NZ4Exgi5P>uFqTPPbv+hJ{*n=okC=0cSl(nHjdhk6V}Sga5D17Zn-1cC>>d@a@Y!A zmYdS1)HGKk*5K5+s$RBBI~6J2n@lw?)6vs>H63knNd+&DG0RC81aDTG zh$#kql#-fuus0BcyI0KA95%6xWCDlrZ8MyqU1~Xv+K7+3u#5<{=c{Yq+}X9!yPXAu zZ4MI~+vPreGGsS%Q9g}J8)RJ^Be@c zAM1B)>FXh_P6p3Xq^@{UU)V^_ri4t4a&fblf@Rejs=jT*(M-J)aTWkn#Xe_7H;mv&1^5$bZl&G-?pu% zYrrgWidMdE&8lxQAAIeH=YUCL`i(o1I@zY98_24zL|41ir5?kNTJV-A_by%ald)29 z9xGDXYmA8TvBBZ-b{KFSD`-!X+=wdLvfJ9b`^MmpZsl|?-MD3am(qmyhuqS&t+Taz zvlX9~u6x=$2S&T2eB|Dtei_T}yQz~gx@B8euO&!(jm|y#jFAL7%N*5Bs7`_BAuF+w z9dheSe}werr+(M^I4g>N_6-T1hkjw`FtISWX^WjV)}v_1N&47vgpc<~`fu`_R2*GalIAzLV!NHl zJ#hOj$$rf{q!BIGIsVfXqR|zWW1mdeH0YcfTAXo|CoIjw&`9#M zPkAuuM>oww*VD&a0N%O`eOJ;CU1`bFL2;hNI(c;Gu{;ld7Js1TUR-_kC&dHi4H;`@9#t zC%xDu-!pc5KQ+hSZs_;X6}VTYiDG!3W4$3y``NsB3f>yrtKV4^^EvSNPGWrChaba@ z;)f|4U%tM9m+w@#Rp7@k$>W^OV*JefpM*@|p3da)wV8_dG$uN^cP@Dg&ck~NdImaN zuJ~(tvv6&O`#ta&Z_1-iKq}tP4cr_hcsaK{k`-Idh)0lZmy)r)z zTR7Xo5ew&7IM>2?7M|c?7FiHIUmZTnB#54p#%}y4df1JBfrr_@3yMMyyZ28LUo!HG zdQ3|VERdg^U!ig5Q$j-PQBYn0@-me_!wXbHywl&Ju+_92Re?jvw=Xc+XMs#)po`0^yXXcyq8tj6}=)!B|U%Q>@Z~!K_RNAJ&Vx-k;uTf9mCZ ztPuQnT$n5xtex{k9-Fg90rUSYA+q!1PMY8{tB{KHt zYuNtEgAYZ3(@%AauBxmM8FgEF`?~tCym7I}%*(nl+nE?Ba3(oZ0#gIi0+$DhozejN zD>bWb6ajX)3j+9)p5c@Y+3cUt@IAnHgf?tfX*%&UrLG0me)QMZQ1$Zh+JNuius|6t zgX!coUa8U?2Zu7X(eiBGR78|%)h3m^E5Kv3uT3i6_2B8WlbecHni_rBl8K!Aqxn4}-@#txc+W^*t+onujig zS0^arC*aj(k&p4>$72NyS@(OpYsF;dyw+!JDdhlMEiZV7_p_2_ECkaGBpaTzj7T2jD@C)ib($ z?RoCo@{l$PQAYD<2aS2|58%coO@gg?c<=Ulhis)W&t0{2X$5F7Z+*_z0k=Qt?f0+* zJI@{*nI9AL!Y32UvfcL;f=QEWrB#66R$ zWCKqCiy{P9I?uBb8+e{o?2FYrsp!pEN5vNcr9A&=qCBH19&a59&n#)*HS~$yy9Pe7 zy{2fe|Iv{QF@(P%5gvGSBvUluZ~b~vHWYoc4?xxB_u zWA)CG2RFpU&jP_%W61`FF3ORwCnhL1^TN%81mc<3IJmR@!9cZp>XXZK)7J($;p*tw zK>o_J;XwYWiOZiD8ICPF+R;?Ux~yCx;UqB9p!Z>f9lCd z?A+tBKlfxXmK)oL zbhNb zIrZ+vc;v?n`5k`wn=j-vCR1*oU+#SuOYSp%xsE=T?LzZ`^G-&+@=lS1v)`ECTyyQy zT+8E#&5s=m2gQpR@Uc)`6SVw87S6D6riHUC9G3E#`K}3D{@E6eNIoAb*F-G;91G`4 zJ`2G$x#BR=qYc+GAM;^Hyx)g|;%*-fi54Hu5ZCx{rntg~v&3aS92Wm!Oh9mtk)Qf7 z)`ERFNBo%&=laf7;@T_M*R%RaDIb4hVOFc-Jc#?Il(q!vgrOU*2AAgFt z%ZI0m8Xuk}uJGZ@#RMPD7r)ezmElLlXOTao@MXZY(Sr)JVdptaI~8UfN!godX2S`V?t!{VAXM;?%nF zi(IedV~unHc}?p4qB>VEwzyH9&jj~2`osNx+HijoHrHC8q78X69QZT7ypJzv%7d2- z{}9~~KI;qlh_Z0zsx{9dg;BW>CE*k(j5Sn=F*zvtF@>>qDshRzSeuo&RAEg1Njyto z6o$lQ3L}#w#u~4bf4Rblyu_GWlm1sIjEPZ+%N3rANRD%jR(@99izOs^+>Txf^G*+P zeKzxanC-pYeFI#r9OWrL)x|f5V|!o;Zp)_8ehA9%sJch86zbJR* zv-@r<1i3EhOG#QEoih)N@Z1wL=*Vw)drf&MSFN#L*V~8BGS_r(az9~Q?K|{`3%@k>8=#$;D$X5w4bNguJS&Y()?fGP>?J%WB~`fn~V5 zyYJD*_pDnd7s=Lb>e|#PPt{4njlJTwZFkphzuOJVcSKKJ2Xs;!`nx(s{ieDtn>VAv z$W_v}eJanT({d^+e=9$49MudMjf1}l@OkLRf3&0f==Tl2nX@%q7I z|56*x<2&D!ci57r(=lZ6Vi3@wg~8VHwphHq@OawbX?g5Rnc>EQ{=J8^Jigma9>+G! zLv6IYMv%zU<`>{;Kf3AbcU!y>@a`HzuK?W(pS;yrM7>=LH~ehgAA?t)2JfHKsS$-isRIZcQ6c$&N)r{FC?M(R4o z=vQMs`4B1zR3Wizp<7?r|F_R4IfM0Nwg>3e%KE{2MNEJq^~_Jeivf{`D(0V?2o0;;e40%}w?~ui70&gnZD39^i^7dN1Ht@<7 zkKt%ukHs4@c&K6??1`n4hc@+i^L!gwrYJ-QNR7zf}!Q*&0RXW-X9)@ly zc?pBZdXq}tpuxjXEhX=u!NU;Gm|PvNg8o8vPhMkld^jGJzHMN>5D%Pd733z4YVC;}Xio%1k<_8+Zgh1Ws!k+V z%!i?I(9sjEDClAa2$W}>YU?TV?mx66P~O%v z@zij9LbEGfr+B(At<(;AAudW|m4E$HQL;Nex3N&=0)3eK%*(+Yd5wYc%TBlTbjOo9 zp3KFN%*CKja@C1EnFi#%k=oI@7gAa^%$sD|c6(`a%Oq3kd$jii8()qirfrWPrmhb) zDBOIV(75{u^0mY*aW@BDPKLbunAkrU*I`*dD8(%$U)?En>sCOl zJR1~wr;vxy&qH$~RDxO)eRRYT$vV^C^VR-UMXw(FYGTs7vXhs~yvTi(8Zgu3wOMmm zX1Y9*5~_QeRqke2vc8O!BW`@mJT=ql=2B-5Q~8~^Ok?}UkW&mVnNNAhr<(rY+{;f7 z$ET~>(bhB7t2^^{2Iu8|8}Xen9KTXMJ@a-Fy<0y^UWvY)(B-p?XCSxHEe}%{i_b;| zp4r?+#%wC|d6G3Z-jn0StrT$^f^WR1#ETuTOLq>(`J~7g;z<)CuN0awvD%*1{my)9 zkG&d?E@H0I?{`rjMK{rxR8lUfq+C)-xulZvPN<}K$1Yc(ksbR(-_%+gF}BRgw7@o2 zz&kG1iak5@hTNu$C6@~#}JVDLiY*65ELG-%!n z-I)uQyUH(jS>gR{7e(#^ez}P6z_{gJ>~gm1AkuuxxZ}owsy194W&H{6a~|WMFLjxx z_YprQO;XE9-9D7*2*FO^=V^5zr5#eMt7Y6;T}6iMHYr=BcN3qMSH=}zvwWGK<4JQ2 z_i4lQ8_%&;HX4^)GrgOYTv@(-ZhCc?hFxyV^-|Ypwt+bt;Kz=IgBA{1I75^|9;>ix zGA#d0>Ca+!O{V3aW#O=evn?F4aE^s@Eu3fJ2^P+m@niGgntaPYYT=2J&)1x5CR+Xl zBG1TQ>N5SSF-H@`4D9!PI4HjC!y$3hhcm>}KAb7``EZtZz6j&P^OD}{^UoH|J{<9V zLlne`&c#0eT;F*k7(0uf8k0^ql1zNnhx2{sg>YYsr+xkt#XcV{5Wg}fp-~_8J`;?8 zKui%Y8vX&y*dF%bY2q;-zTDea!o7dGxYOrfB&vOQhM42S#Uj^-XNrH(6J#ceH?HXoiXxIUvz02(W0K75(TM}4AG8Gh8o`X$PX zn2$eovHn5fQi+4&Wrf)Vp)S@J6y`HZU93M)n9pQ^lPMlnxJ}|Lu}xt%_teE&=es{! ztWcO;0P12bRoD$LN5mB7>xa5n5rv}?=ZV)*9~ghW>I<9+;_C|Y87y$}#h)n5E?)u8 zy!!)%`OFnK6UD;{vuQ4Xa?Ug(zo^?3u`sgCGxYzJhj_nuOI@+A8GPzyy<}kC|Gb4i zW#I!B9^j5s_Qn zHP}d-t6v&fBg6*s)*@`!ypL4~%|KIE{zkzYg`{-w0x z{~p@#N7e|&U-A&nBD%M^=WawGzfWOy2Z|AI86VhE4&+`%f5?^bgWToBkSlpem*l~g z{ z{O7(XeD0lcg#jeSVyg6?uP`!6;spw05lUk0dm{PBWQmbziOUpTsBnqG6$;N*xKd#h zy1XBmEbm9=NPM-zF@=#?(jS#t`Y%yoiDf!nbJXhiC6rQT^yA;Nn z$c5?5$zvS2Ej_k(ry7Z&f+oFI_igFz(%auBwc1=iYJ6?)@aw=ypVl6EAGXG?*}PsV zc6Hc-6$OeeX;8+v8DYzf@vS&PEPNn!^ew64A>H+1E?iBLNia_du)=`X*!LulK(X%7 z2ce7+FM3fLPD8P7vQ9a%e0h(%W&Ks@>Hj5D#dAecEBX0!`Z}4L`TzoKf1fOIWR$|m zgE?G>WW1>WD1$W;X*;)r=2=L8yjWU{@z(Hgw99Nazb`WWQ~lz@@2fS#otspNf<| zsXP{6lhS8#N}tM9K37+z^jVV9XHhDjMc1bENtro|QfAJgl$leRG7l1a{{mEw5V46*=bwSFc#S+u^?1W1$bGu6bUgDeud0M|a3Gn)eZl_Y*L597xu@L5p`5 ze$^x>6H@j)7Ow)hPm^G4UW>)!__od9>2OPN0WU93A>i;Byv3G0jv%=kSC-u+|9`x}cl0prW)7`)F}ykhXsUH6QR-+qgi0B^6y zO6Kzxi%0!Ujvcho^3b*Sr6U&w)v8Ibb-A(sYo>QCJkag+jFxAQ3H!j)GDz0f*|>r7 zwCRUOyD_(={cOF=?_{T^&sYhiIX)xWq>{HkP2OwZ)oWp}Q^}j1lU}$x!AnQp3u(%m zhJj={>D`(p?b-te7^kPfi=lyO!S%cG3*pE1;U|bFs=8;6Pj=n)^FSWk!>?Mr zuY-r-xFC<=Xx@|3F*Yc)Xyk`s^9%YaBCaz6+FM+4ii$~An{m|ll-H?Yz z#p8X=;{Du^hbrsw4qLomfT!~hRm|h#=z2!DBrlkG9U2l@_lL zJRR;tgU5b|nJ-U+r}L%2;LWml&lusNih1GMyk`v_lAe;s^FeevaG8?#O@lY}JiH$m zJWkW-e6i#A3xkL0sg%4B0@LxMZgnbolMG(bd3a?857SU7)CZ&)}7whqu?@u?$kB<4J>8b{^g{25k&G zdv5|C*HLDRS1)R{7F(^wj-AMMOO|bUmEdLFHt*)(K-MDuB#_O6li{hvHSI@>V7sq@Y z3vn#LQGsIxj!GO?;kXt@4URe-F&qsz*5Fu=qX|bdj_YyUgyR+*Z8$n{Y{SuuV<(P1 zIBvtS7ss7A-i70C9Ph?)5XYw0#=3R&cxG;`Zfb08s&3rWx~aK|c>Tt@`qt+9b@jC^ zDC4Hqrp-02YwK^6=hd5A8qBygH*BZ{ZrO}0$(8tq>c*DVP1PIfjIi43b+xT{d-ZTO zH`mKYcBHYENi=P$Z|3v0#8OJ_hM2~bpwE?X$*XOsuU)II*;Lr` z*>G?oTbo+td0j)RbMdBDnZ4MG))raN1YTcV>l7U_HHUULnVy4Jw$@hznz+WnO^q9z zdc{|FnLmwD3zEMf=EzX-D64~2ywfJEMx=$f>+4mT2Hy=+*EF}Rl`<&5enai18=IUq zL?K%18k+&o-YqTl>zi6o(VJQ~@9x{Z=Z@XX5Zs^WdR`787nk#1T+VxOIq${gyzkI* zUTHJf8D#$-`)k=&N)s^j=?jaz43QV|<)@2WEV|-*7v8RE9t281BA4$6A{gN7Y$%Nn zuz8`W`I(m%Omh zmrX9>c@7`jE{n{@UwqxU)VV5`54D%&^N}@Fz!$e^Q|2>d>H_|~WFh}fTg1Q97xQoN z68sHbmKM59zKs>8hYHIOk~M=bb6GR_iWi#27vijF7XKEN^KWs*q!PZ>hG#F$5dJ_h zmO1cYH#B=$_Uz@8#iRf;h4;_Np%N@0ViloU(plX9KR6cg?Jh%SZD_~y)-HRkn+bp7I&O8zS#(8iU)!`x(%aj}!%To*g(=UF)4 z!UYzdV&SPScFK2&iyisXEIi%9ms@Mbrot>gb^{l`;)g^y=EsNp{G-B5--rJA1%(~{W#ZEwJX5^SgJ+1_ zJ-AS`E6n=v;r?mx#Lp6C9vl_ZJ^cBw%7+W#c)$60zcC|lPJVL4cRYBK_@5p;S$xcc zBjO>2o%}2igP!9>_=#Ts!M9j6e-&UAoGS}K( zZCuZJw1pPF#KQ7f1J}}#|6Be>D@XjAgv0$`Sv)h5x68pSJM(EX+9??I^Fy!c7*w(!#XgtsSqQVqw{t6@l?@YBGG{ zA6odU7XGY-pSJM(EIeT0%@(e|2d4B3f2e#=Mj*oRm>7#L&D+Nn{s(;C%IEvlVXsdlGOl$2l-zrEdqLnS5c1G{$i$}KCM^}*(XJ*;VU0zJ$15}}F3dT!WQ zOZDtX&qBR1BDuWQN!M7UXN7Uau@O}3EYPz<+7ldiah}UDm*$y)QkHRLVp*QcG8g4} z0(mVaHQX?3L7p2SzZ!dpa7SYP(VJmyX11Ojc2ES|qs`+O3Qf8ITUrnu&{i^0A1t=IX_Vzn73g$9mkF9)v+rJR zRn8dUULoMSHEEI=sFD=S1l-}EkNmbchDZ`pRB73<#RM9v?2**hM=<-1o1 zJ{=xGrCy-~_!Cqoc(wBI@F*|7?pKlUG!L(4lBZ(|0*N?=X&xSJJv`clXid{sCF1zp z>%*aw8V(EbN`mIfvw7?Ap(w}TQ3jpOyBR!w~xeJRR& zBt_o)!Q;D?cFEHHixlNOog(j3Df0d%Mc(t^rP6LEQ zcU`h}`+17;&Zfxw_Y`^mnIbQcncDr4ks>cAMc$MYd6%WgD*_Kic3raeSdb!*dt9e7 zZmdd?cWsKi`V@IAC{ z^XB1N-PROS4qlxhPsiE3p(MN(T&sVxDCPz54x<8@pIdP--3ShR^77Pc0}4A0VdXfO zCVBYDlfTPm{kMU~{p`u(&t@`S_!4|OQ@lmv@XC>>PM3=nw7l6kH`8qZiTP%_OUB`C zF?eMLkBctwQ}4PS@D8~s(FVB)GkL!Nuf@oSZV&q4^=lDT#pA8%RSSAkSkt>=Rb|RH zu@B|R)ZIOhXJLs(s3EQKMEuzZ|Gpsqz9?;C>wKF2pXA!eiwh%%U}vXn@Q$)UdD6LU zdvtMQS;yYqon3=vcMO)*tefbf!LD5wN>Wc}?}ZZ8ySsDe-mdNoC2r@^&I=_9?|c_P zRCj0Dg(>14gNr-yagRM??@;f~^URtd?T*21W!t-V<74ajR-Gl(Eq5K(_itWTkLCYY zW6|@jy*r0`JMJ9nZtd)89~eYP$3SoQw$`rR_U*g(3=Z{nG7R5n-;srpyOwmCW9&P9 ze$HCO$#Sh?Btt|(zT9+y`Ez%zB7ZJ|fnX?*&y!$UC|H1#tTa9+X32#op>+P{XNCEL zmzBZipRCNOld|!QBf?pia2X&^MRwM-P}X#=0mRb4;adEecciR^C^JqEfUxH_uvTN=_IQ7eAeW8IgR-)&-HQ| zvrf5QPGi<6*UNcvhKn73riGoo&Ty%GmgjmoeZ9kMtyO8*8S$g66$kUVb+&V1Vy{T%rDn7X*;S+kL!iB9aSej zQxtpnSt8SeCy9Sk54R3~viPyWEDzUzeNAEJ*N5_IJF09SuE)~rKOBCpc)v$pw%DgI z>yPWj^!g76XNYD`e2%z6VbH;!A}SPS`ngygT%s`RGuNLlxPFJvj_hMx|HCy1+VT9q z^aG}h7vhYC|CfcoZQ&CZ{woXrnS~Epc$bAuyRXdOYAc>Lf3#!#Tnp1in0Aae*N3V##d_qpLl_V6Jv!FZxlza zC&BB3;3Dxt`k42R(#Jf13H?g^p^q0D-d6raY94-tTCcE7tyjQ&Jwyn9nOd)afl8s8Z_{>V&h`8`dE- zk&krC9B+o2$ylLFPiPS4eHOLh|Jaa>f)> z#^y|s4Euj`mR!%q_wL@#8JJpU5}A{Cu)l}^7CpuJWMyg8xoGS;W~7psI)`Yotf|#= zLgjR6B9s$R)&w)VITNhpXg=GlqfVip<&ai?yb*{N}+p}n)so{3vM zLwkNR&}M(svwn#QMU{qUI#Gq0Q-eB4uB&is(k*48DbyTwfcI5@0=g1 z{*QHvuNh7L2bt018^|AeI!}x>pNHYub^Lv!>%`%cXU?Ck@N^tQ^f{Kid3bHWH}Zp{ za#{v|&v=fXX6ar8r$?RB)ADRy2_7K%45(c)dCS1#v!iy&cpJdOf7d1BwSdHDN$ryH zZb^~1EyZ+qrpOyekvE(oZ-0usL*S)SFYf`5&(_){tG^F}mrDB{0gsOf+9i{B0z5oE zxh`41`n8om&9lGX<5g(P@BEvPg6_*qtPZ>b5Q0Y{xsMCw@foTXhgn}I@g^Qc7@tR3 z2J-k!#5|k4SHT-a7yBs{`n>^OH z=Goun>%bdCymq=h?CT zVg9Z6+K@V##$Fq@U?*lDY}qZvmv~xkI~?bOIxLSJ7jq89mo{b0&5Y6x8{S_>(~2_( zHVinn>7qL##~41R!@-B*3!5H~>|toE!K%*UlDV=F#1A&rL-%T6D=PMHi#bIgXI$6 zkFp+r{mel&hf@=iVwrb~9T_utUFqF{((tLG9U}S?>@L0(PsfoZULHg(6gid;i*`6R z4}E9L{kUReO^(t)dL~XaZwVfy{!pyQB=}*{}EJq4r$Gu0#ZHI&;Ppv&3FBk8L2Zgr%w?JA3?2+|G zdyCAy*fBXa5!nl)NBhfNYmrV5Tp(a868$I;b?o%z6cr8rq^Nx`8k;Fwak}b}?4`c5 zVFCT$xNqT(p8TFbTXRos+Xs5?ZTnWw7uph5C>`s4iS~@5J!!2^6qW8c0h@>?;^{cD zA}E8i>itccOYIK!Icp)zhLC0eFygkidU_@V%>{pMb6cu-;RqDK5(9l zhfWl};mcXhmXI|KE0%1F=qvFfO{~@4*n%F`Cu+C+Fx)MIZvP`SzG&QS=a9Cd zIZpZ`qgwiJEa`8a5|AaEPyWGJw>lJqUD!E!@o>&{g|lKuVjItdGeV`8jHZ`{M#H7~ zqZy@BMl(xij252`53d;(KlewUy7$4tQ*nQ!y}hdEsdnHyd~@Nf%X;ee z;MoH1p7i@5VuLE~P<-ZL-<%J@x@QRYSGcsQ@Y2ys&iHeJNGm*Yf4uB)1~B>paKT7M zX=XGNE$<7@IaU^Zs^1yut8llTc>rATtJmaMz52)TbqCX8lVeZBPr%}6dPdc;o<1>L zdhCO7d?bS0`{K(EfAW}b$>h<%lHm8m2*WcmZrmBBr1=+`!sQS>A#-xMVW$g zm%}25CCreFe-5Gr~DoZO$3sKti(!x>a*TKm_ILhmp ziceW>opL%uhT+q*6%#(4c}`g6T`0L&1q;8F!BX~oE~v+@(d_7h{U5~G5ykkE&vM7vv9j)@P0}s+@T- zvf3F_etGKYp2UdqFQ?AD*uR>o<`nrb&Q=e~QFg@1$DiIjyz}UFaf70Z^Y9a0YjANM zzN>f7V!4E4v0S@Rwyd(dV^!xk+a3K0&BM#_rBhCRj6H#z+?JsEabYsX=W-ll%Sde! znlJOoWhBqXH0QTL{^j+CeZM~nc~K*O#oqj#mmN`4?i#P$3uf!J!z*|9`Pe-*+i8(k z?u6Q@6f(41hZDEmAMo9fDKq-z>a2Cn$wc}UCl0lH7+*`O^Y1#8c3<%Rzyoh(!!vnb zWx2KcOPsiQey^`K|MpFp`TMG~`sCmB6Sg}V)d|3_@uso$eA>^v-}!-SB6S+Yb=qyg ziBbOE3zav_ZB8g}7rK0#&}VA$hYyACOTRz#K-z=BhXN0?=bUf7eIDhzP;$*azE8@% z>rm*vwEKe(1Rfkeuc?jc6YVGFSaH3#pG>I!%yMp(^6qwQ@z&a8UdOu4ffHE@;K4SvX|jbPILdAe$nZ{ z0kP48gQCWR)5KyA4vA?VjL8QN4vW|M;a)lJ_x3Fh&J>^b;4E>(gR{ls9z03h>%o)7 z?H-&XdObKIws>%^Xz<`Xais_6ixLmE*RM?xeoy>VF^I{7ggg8D8x8EkOyIR1Tqw-_ zihP)*$@0X{6leVjX+AMaeAk1c;GnB{ zH_-lx^fSaO3U|o(OmRYC4zGFsEb(cD`DjYpvma8JKl^$9Nz!&Q+w0#b;SSZA}9V^7XGq@|JK4sE&K@!f6&5* zEPRKBdo0{$V6Hd3&cMunjfJl=F!`A4aUJ=VAJY-#~u5lfTS1XFVtJUn@Dh zZ&{xlFEWROVE@eAA;eGVcM0(Zeei!re;euvaw#W5zY}xY^byZ>t!xk8Pno@#Q>NdC z{KIEH!n|I!8_Tl}Sm%Ex%FBB4S10ySlDJXfA{D<}VN|}1U!gG8KT5n(;c|tsE|mS1 z>mX%3{z!~Ulo;zxC0?NL6$)1y?JH44vG80$hMf4;(1 z3ZoNAevQI&6s}bm>sV!cox)2Lu2(p!FglHtKSSZw3ghOG*Ec9U50x;%b)Ir-DXe)L z7{ZPsExo(2Nr!9Bwb?benh4^CQO*`OYDuCe3Jd8Hmvi}}+OfzbnM)$wK)rO(4Uik0 zV2xxVz*s5i2~^qPwk&3Nk}P6%oVj*#j4RX%N;@X8c+aqftE463D$dCR;+(~OV+eE> z_?Z#rqDnLT-1@N>Sf*xZ7a5jIIAxmynA-v+U9>9=>-NcAUDgk7uim+HkKC4KH5Hn$ zADL%^Bo?W*q6wWzt|Cpq3ek_{f3@4T!v<@@3N8%U-Y~dLb~>zs?Kc1Fqn0JJ?LTkDEnjPkBD`$o#Ms8(-cZ?C;;`9DLhb#vLH$Be~YYypJl(+EqP_9|# z;C$f?{;CP0Kln0fvB>YdBZTnCLWf5_`RphG{vcYq*YRA5|L&S%J_lXzM9IIJ$M+z6ayKTQ7eNFqXVZi}yc(JG3zPT3*!RO+&=iF?iHd!+$s3A@J6W z!Fv;7Chzm$Z5f02eTz30-;MCt?>e2omn~i$ct>1TqTN1g@qPi`SpDEHEnZ;|`x7aWqYc&#O3kI)8Utynb}-En~>*uy`-0k8P8Bqs99Lcufe?PUnx$|7QNK zLMNE4N$_?4a&Tf~N2~)+%OG8!hb&$bcw^}s@KwW<_o+!^uj96Pzf6%=fkK$&)oI!C z4yMRE1)kaelF6Ho#qz1}4yMTaK6t5=V}8W>mch25OP0Tfz~i?9?UM0+1YVaW!B57k z&P}bn9|o^31$jS8QQnHY)a2cnBJVhOskGaa{M2~6z)Pi`Uji?cdPyrttsiU#Z>)5w z53TQIHp8>v9l)4yGtN2w^8Q7Wi&w$RfUn)6LLs66WjJ^}dAOy;sKr|c94Ns^02F}g$UIm`67Yv0i z?>iQ+1w36Z9M849lNN6)c)Hzk4BmgYcsmUq`C8sbE#5wZhg;d@J#6tF1uu#))*o&? zmv<-5&GJ4AUXSA8R&jZ^TD$^0p z;OKg>d36Sl--wg(S_~fb<&yEb3?8~zQr?ikLscf_9Wr=0P0D-R;Nf#>QrI~k3ad<5T51+4-=C8}(@p(I0Ife`#K948m9Wr=J3?A<({+?*}ICxdY z4;hA0={VMyyjRefeuHOi?KF=*c>Oy3t7wD<4d81Y_1bo|_wLq;Z51oZS5z)rRk30j z>`9lGR~Ua+u3QeZblGxe!@0NCYkQ6z)6i>c66?j^4O1f}T%1vSPe1lc8R=gg9zOB& z6XM75k`vkRBk`=SS5{I7gmGC5f~OA0E24i6J)8d3Sg}7sf#CZ>4dUl7`3}cVh{{z` zH*R%9pXiO0JFDg~)~=ycKaR)ZC!&>=9mi_=@{xAoNM5g4kTx2C{!5j*!oNc-2#$zo z|7z$MMf0G2P%z>zriP5z5mgd>F@M8hM<+n$LCjC&J!1{iLCzOdR*D4-e|R`+L7L3@ z*M_}$pVSz6{vhOp2Ykgv@ys&+?1S-@BI|*J@!cX2{dl}zgw})_LsBE*`0J6XV55)c zPMR#da@5D8X5a#G|4~s&EwHK3R+~Obtp*;f6W_exC}W7zWBSaA-S5UsJDut^JKSrg zLboe;HWIk2>OJvrbm{PL+)9D4u@e%#4F?Wcz+Q<3DZ-p1mZ{dM4oeK-_mC zHrzP#(KkZb_uw2?eiK*jA@<|^%~M%XaX8X|(v|x^g%*lBnjMGY72@~MAPF6%24NVw zNdeR^G?YXy^hU(#pe(f$>x+KqHC8L?w00779I5?84YLQ1PK|v|YE-66ZIS3PU5AO< zJSbyMyD?Lx+_&N4If`5;cT!A7*`J_-pzLQ9~&A$B2Zi zt#{2Fm=QV~$_}3mWrWYBi9peF!wah{I^rk)e;ZkcoG_t z58-$cCLJHb@g!R7Asno~$+G^cQF6Qf(pi7^+Vv-Ul#F4$^*?|AQP$hk*z}nH2;(YZ zLFrTWq;cA&|M*yvwKiR#k@v6^!_uy51ocd%#X7vo2u&AOl;TCL*DgVFoShYz9GKi< zYyWsV@Ewlc*YVf;tH8y`K)oa}Jk_nOr%+;yM%i*)Jbq-@2i+U73xUTZ`V~j5d$Q@q2{w_8-rV9_gQtyCjiMKX9}Fqm0u6!I5<6nX(P0 zt2S^#X5V$=%*pdhWNbm>SGIntrcjE7LF*Q*X~7$s83UT92?d z=6js-$w-&6?RTM7B5%rCbMhgmaVpErdvy^sQ_GLBt)`9e%I=Q-T~w&Ls8BVI3e?4oO$Sm_8*{e@#`{E>`%ck` zZ&m5Jx&GX&+;FbHI@e#00e5WWsN~8b{K}ynzbI7a?>{vDqWt8tuF`_w@0YUF0{H6u z+gE4i-(8*6Aph1If1U6q88VUlM~yW3#%CydG{3d7M`{WNlOgwf^Va6g8$Rrw{Nk6s zF)_LPQls57IJwYDLrr*nt$`wvp`=llKjeR3X8v6@S?lHB3DpPR@U`QY(3<=^52fE1 zx*QR_uPM$v`ZcvzGOrAeo#57;xu((2D zjv;ye3^89}jv0CWOfgMijuF%^`i&|df9hti8gL*Vo@VT#bRQc>b#GIp@+3!3J5c6q-eD)t= z&WTZPgm@+j$9}|c%JpN?w~9W5)zL>MmD)16D)?v#h}W%|fZ6~nuPkm)0w z^}u{yufp5tBV9zva8!+y6ISUiQ0emNoawS3XSS;J;V&Xa{-j*wkM|LI5#{?C-=_8t zM>y+^>hn5cEEXODTw{NgvE2P@Y%H;xzGmV2cbr0;3HsaB5*LCl1>5vxR zYdfGIRK00^>-K^E)+Jrt9ecO8ZX0Od)m@TQYv!V!OUcrtNM4o|Dha?6~8Db8YGQb=xWq>(QCIZwT=>#|fq&$a7<>a5M;4I>+8(SDH0<8vb(BV4C>B$>Q@04)qqPV;^aZ1P6&AXhmC?*|qy3;|oTF!);Dmn>cz zA_~Uf9kX~t;6=yav0lymJr3THF?bJHysOg2)=$ABuSed4;Ps3lkL#<=bkBhI;21nS z!g_eap+p}eozKN|Y)ez#0r1!dwbS+YJV++*Iq>*Spq-ZY3B}XlC&AM)7^csk0xt|4 zP{fzPJE_j;X&&ujFDeMG)0~tmAo|tdAEX>N;&=q zcy%er`)!K6YcQy#BJZ9Qd0$GAmzkSdx*JmDJqBLW81-@p9Y^6p$MJf!5daQRFBJh&EjR_gP-QH+&bOwTD(Kx zl_HGkG9AtPg2j6lJY9d82Jf#d-gDsT_Q*1LPguN@;6)L}bTQPp>E4TTv%If@H%;*{ zG`PH77Vme4JdWqO95-0JLMRVJ5yo_J>$$vooSW%h1)eT1%cJG-H^t=Dfv59_F6;7U zTfD8{>3X?j9NtcYN4Yv(Ti!l{hc1zn_o%@`6(!|8Y4C8Gl=rN`D;$USqQM(azvAl# zZ{|4ierWJ!jl=te!HbT=`<=ln8i$vSLh5!a9*0+G@Yq(#+KqZ+T3*RGysHe}oN;(s zzl{BP?l`=yhCDtKB+K7UgU4|}^Vr7%IJDab-bsvM+UZl?117Hujk<7*=N$6E>(|%! zq0$;OfUo5ZLf>Hb9#`EU`d0b|%T}yd3UfPfZ>?_-;Q(dm8{}a`@UICttLaB%ocu#u zGE=Z#nX5(9&W8QI(gN5Y2#rLBvr7AqJNx^?_AdALFPc7Z<3N#I3F|L*){#cAp7s}` z+TO>X;M!5yd>5CFUR*kQap~yArK3Xwy`4kRGHFs^ud0%kyq@_EY~x9e-ygBAXA!+VP=#3}@QU=K88F`iE0;ePT0k z;!>Yy?+m^PdHDgk@1RbG>ur`9@&e$`^x%MapC(KH?Cb8dT_c}0eKY3 z>i6Rx-^YlVXRfD+D$J_o`iWKWwd4Hx5)I%J7h9O~%-W4L-_CcfnV3{%Rbx4Xd^Y2^ z0ETDcL5(hF)ew=I zt!Vjm+Yyuark->j&HXZ;bP7z*dA;pfq-66>6&0dpZ|}}7Y{xXv+p%}3d$6RWrD1(* zV{`TG%S-A@no8L+~c?X^pnRFsRf+C2k9-NTF5FBhRn>FYE6xxPGqf&UWU zG~aaJrM{WaN9F4+=K6$>-wE<~Q>Eyx1CMleUpl_?7RWQ_58nys-i^cL@%f$iv3B~L z1u%JQfO$V_r+Ir2U}p0$uuh9yeZI}&Jr118UOKEf1@w!*Q_ACqltvXGS5W$@TnlF1t~csO-=_PgOBM6yk^({*OQ8%{&UxWATm`jkG( z)vv?9gz>aN1NfT9cf-NXgqhX1dN-_CUa_(=#dpIe=F0@r*!TH`Y>U_|Dxrhf&=V~d zXTxc2eZ7STdiX}z))y^KJ6q&C&=V~urp_<*MBDnR@a8vp)DIoWf@sz#tdEZ5N7F}x zrNL3H#VStcxjM$Yw(@u!X;k%1jy3j(UWP1<6~$IWd6tGZ%=mHNyt4kD!eDWvkzwt9 zUy*sBAE{u7wsNQa^nOuP-7h}W);Bx0qFD6Kk40oIwf#afJtxLaQM}C*eMLUJFegiq zRy;FfX)#~y{-aS@u8;^q>l*LTPeZRcJLhYUzMdnZ#YHn5o30CE(c%hd2@9#^>1g`y zeDL1)fBJuaqO$GstRLLecJJr=pMT=0^L8%IR{5gEyJHclP0W_Lucs$AU%k0U5f?fe z6|y#|WgMM08yd`!9vMH)waFPl8<0bd)`+V!>$JWN z-PUuW=lJV!SyS5j>pe$lOSWHX!*}!rpdEY)J@oH?Ca!y|r$W}QA9-XsJNx{I{l1F* zh!LB}dy}eT-T}0k+a%>8N5zgdbURx5p`NVMZ1ICVPMD)pPmW^`GI5VMC1@%>(c|=t z_;I#)Rp0$btA>NHPO0zUDV}>XbTo1tmVjmbYQ_r5aQYA99UHY@8D_bPl+8#dH$+-L z+F_A%Zk%|2P0zhY^J95;Wh|S#AagXZ09IU&isLhiAMOtvy(J#}Ij$R-K1>U>+;e~< z%}OH|mc2aS^Q#Bl$T4IGbx<>x;`y4s2abxO zQ~iPB1M#vbQbV5;(Iv&S+sgE@AI6=qqbr>9rz2(Yd@Zi|KwO;QjvRr}n}_`i(?$zU z(-!YrTjHezt=AnaqNcak60c*2w^#Naa{HmXpAC&}XUB>(Q9Ak|^bOzKqsP+DP8Y1- zs$->h)5>S4_){|+J^d-Cf%`%jv8Vf-knGcGXJ<)v)3Mk0Ic#dP^ZI9SRsV5)#VmEj zuU;E3Wk*)kIkFNdYdK8W$!F6!`Shl&^ZKjT7XK_>OFO*xppJvFgZS&4dt%?wSmaDN zr*P!y{rT{p-j^}zgSLDpECXkp5+h(85OWuurnO*({bn>mi>V_|?WZ3dZQB>X&KI*` zEBI1rSJhX#ViX^fp&#!nU4`GPWuqb*>7Okv1$RnI!MF!qOTk;JBK@cL-L#Q8*mx$8 zRw(6$bM79!9y_3%z>jC&Xj|U_TO!`@iR_W8 zGeHr>aY*j0umGhf7&*P~<HVRsBJ?%XrbT?P&Ni@Om_ zbT|p`G337;fM0SK+8JLqdNcH@AX0WEt&c6uFl$= z&rdQFk;~5s+EK+sZJH3HQtw3MMYS;ag;L(WL&5t3_d_Lq?fGmJV9K5AmD_Yaa?SF0 zDY=3BxNXGw*C#(A=ytjuEi{q(EP)K|*5SmMWvI))>pHm!z=jEK0>JjsZU;^-#O4c8 zEf79G-KhRln?JlUGk(y*dO;&@`(*XIVJg!jmjK*}^#%j#xO?!g&_Xw{U?hA0HkZS0KKs+9!yBfVf0FZ?u=( z8^MG9;$aUCNZXfM8uv!H$rGO@8ay~8$~`#UvfUaM0Z)8}c#|1ZE`S-_?|E>Rv~`(? z&$ev0PO|oLm@Mw{T%RL#;}h3M#EqW#Tyd=j=ZQHUoGX4&t=Unx^9UK*hZi@L5OZ$4Ng^{G-BrfZ^T=Ur?A2p0v%X zZME{pjC(2Qy&mc$o-Fn$J|86Vu&7{%!h9g)UJExX%m;bywNRii?|Dq-itR>ya_s`w zv};Ga-on>dxYWWkEF82jJ|(-3^8eLE%#RTNWZ~~y_$3P`#%AaGr>*#p8kn|F4;z^2 zJ!oLYvma^4_-z`%CvGz^`7H)!{IwQ#=JuRG#&aH6JL0!mJHmdJx!qZFLZ9=#+#4X9 z{#LceK%26$+6mj94DWK*hS0AgUhU}ZWTKNHNba$~{_aPonoJBid`QS_Q+pLa4)e|H zuTehx7v*fA4>_zC?$zLt)26QPQF}TdK1ALv%GN5vi;3a$L56+}{Z=P`est0xF@!Q- zGm(fcKl?xPS4toGvdby=YC!&E{WPdOB9Q(wlDtW-=_Aw&^*-Z6%2=8MIYfDSBTkR?GKpgfFIE_PRj?lXs1zBG&MxtMg|T;q z#OQ1?ex<@Q6uw+xRFaIxAIYDi@G6DpDvU~$@$(eEQsD&(BT~jMRQPIzixj>_;i$qG zWF&uV=qm#<((dd$2uW%VE<$TtXHFu6_8@9Q#wtZ+*_hA2? z-PmzKS@Co?jF7QhY1Z35v}cT1ZCcQ{fHwa6V9s-Ie`0fr=1vv5y9+i9`v8&eBq@YRN?Sx-c4xs|!P24s$x z#8%dKj1!0LEIftMh6t@tDx&wa4|I27zlnivV^q7oZ# z=vrm-GjS;kE18PB@dklX^4F)HmP4Ssx)A5J z9Rh!qJ;>hO+m*3nCrsCywrShtY>m>1y-={_2@rR&@S3@89vaxxeS7!7U^i{XHnUgJ zNNsZ`Z0L6Oz+~+<#5v)$yV^U|S^E$+&2Z243EFwNb1t_B8B2z{Z%BP-CpIVWH0L?{ zgg7Q}!DPd+d7Yg)%zZlE?sCeD25U=}CAH?eEU7i$Kk|({(EHJCSFoG>F|LXA{({IA zv19&vBx3Ae4i%$+H8f28Vt7N0Ukft=_2c}67=fO#=A3Z#3y}yne;vG`>X+f%K#U2A zK<_WY*x~I4Uyo=BCe!f@8{Vjx^9x`Hs?pyLc6J+)-3LReIqD}y`*&b{vO7yw%_o&V z=n`cy56_f%%=D~L=JUCBh?Y*<=L{+Q1bjTAyDq5Cehp!!JnkPi7VifZZy1>G2ij?Q zFIv2>12<_Be9il$#VbU{`TVb)F2}%Q1dCGATJo7t-=54fi z*Pz3W#p9i3*2@dvWosdbL$RdWf-v&5JBgQ59mgDsUkynesDwT9U0$wWR{de$EDKAzLq{RCec&X&?-@!{I zf6WD{weQnOcvs;D()SRX;n(D)JNub70`tB^lZ)9PWx&_24ujt`0Dk*nA0Q96s>rf< z)br=KOCHnFyfe7Sl=qCm!;tRszH9M*VWdl0THXs5FNp6i<%nmx96mIU--OI`mxIUh zk%ytn<=OUY>%e2Xk%#JWc{?n5Pl8vac&rbd?sXRLhu}pOkNMHON{jb9Lmt12X&&_+ z&2n6Y?>V|XpbqHrpt9)UwSX5zJj;=7@csqoro16T-Xw$f_ZII_@O1rQD0I_3YVn>l z(#6o_^8Vc7y$BxbjrpToUET*Qp0+be9)<>&*K6@;XS5Pw5cm)QpcpP4d!DCw`Yq#YF zuVfrvoxz(k4zI=F%^io=W$^fHlPrHj2CsA+-XViGe;nT91`nU2lcxKO!NVtNm&d-% zab3ITqS%LzKM2ZUn39h7vdJq%BT)ZQJI$jHUcU}skIeITMmx>JODJ{nTobXbPTq3E zGHiuBSN35qUz(~;UOyY&*so=?*aTaK1+mF;^?sU2Kb6p9akR%up}pbg_MGU6ey&Yw z5w-Wd+=jLIz*P!A2rPP|pL6ul+WW%oZGA8Gi1~#h2k|#J3jHeRNBE+!8OZ~7KYzdR z-lJ);AN?%y-=;zX#nG(VcqSZ%{zFFm*uAj|XdO|bAnR;26fG`~g+5Gle?0osWwSpR zUmSrRRDO12H8hjnAAhd=Mwx%6A+2Y=?@&B&;85IuIQ^)jk8@@tt{!n}n&nNC{L<-8 z*(e#dRRy(=?m7BsEEKz}=mXG+2|bBad|3@MV(qlkS?<&bQ=#USt|`AtL)(UADol-f zT+r{CbE0RO)U|5s`=YEhjqa0m=I9qO2W@?6?cC!gqaoZ_-C0oa(zb$%6Y*yvp~e&O z7v$d;Bfg>o@e>hkMbRk_|Moxc*obuO)22a}O_a9vA?48~sjJx5H$R5EsuaF_knY=>FN;|8skP=a^GfEGfX*}@b*TtFDIl1{$E}4GWj9Epq z=ggbGaB*41vK5!Fy7KC4t842;;ZyyqXW=NuF$YH}jzu^Y*Rb*&rf zx3sjbt-n!)t*_qFTHVr8zrLxZnRzFVWn=m>F%?Gb{EeGiWc<4N=332NSHHTt7Q%Sl znj2a-Fv5}1+{{#XzHwuXtRrauZ(=TEjnIIHW4*{Q5V>73Gr%wnbp}|L`r29z9rJ zPxO5J=il;uVn=1tSNe2cl4*T}_M4m%w^zDCR4sj$5w0>z%uJ zx*WNJV)AJ4Y*+c&3_nLpb_6^!jL>H4&DIT#RGBNm6#Cn6k%~ z{3(xIYBi3P*G8GwG;!%D_Rb1sN2y`Q5rdkUj@}iKz+D+F4xWv2^!dG$UuR6xBb8Gw zCoGjRICT?zTXhpb8JIrXiWY+p^l&e)NL3X_^N~Q~`(f!hgX1AB$Epz-J2LFqh3Ql5 zVt+*x`z=HXdv|sZL{}^+Um4xokB#oTqsyYDa?hLSvhwoz(Uv`Xc3u(1v|DFq^ycMV z%T{bFzePB3@#4-^tDxF6)U$V22YgIn_71fUVh*ntn@2|%LvLmA_T774P z8FWKnp|N#vsJ*kVtfhL>>iU+}^~=jzHf~&3+fd!OLGBLU+*0Qyo@1`j{fWP*gmqB~ z>!K3Y#eKcrfqlL77&EcGz4);}J3c9$j~Q5gP|yzRjZCeL39ZuS#|Q0daN^MdxvN=f zYt-lOtGiGdO?&}2(wI=5vvr2y^Ch?($J^D4GwYEbug*75S3!n$x8tNHfACPoec}7l z9|%2|_E7NQz$4J$s?P84%gn!{CaXUG4yQ)H{PI`6`n7L>pS%pInb73>XmT0J%?g`+ z)2WAvn<(bT2JLp@#HiEW3!$;Z@@cmPCzcuATb(q%{4$iT9K9%EUoVBb*t|I@et5h3F>{)cu7T!}!5a$)YyqgxbsOcl)J0S5vM- z^}E_E8ij>X=;Zw&wfpQz$WJaK`F&=NS**YDWTeuL#`iNwb6uR{p>out`riiTY>gND zEgTU420n)`#|5nTpoP;c9Fo`bXT)(KD?Z)AVGC!->)AyemtnH*Ad?exTlMVkj_h>aecDfMa+*Jp`^p7?Ar z!-FS@EDuKg;zO=>0qlAGQxA?)M8HfS?E@w3Ih>W|kT`CyIcJ03ho z{H+JimFwIS@}`LgJ@NCTjfzBksmCsm50(e6@bDMNJx&w+g(BS(KVAH%ie&$!&Do!# zJxM9XLA|LjE8HZpUwlqsjw#fe`fG*xs6m^vPkC^fpv@o3tC8^`@u0%+z)u&u73QNa z^`<%$E|EAxT&FO92557(R$-0-)SFtYFz-3)P0docMB+(elEQ43JpW|z@900w4<9$E zH}$FqM_e1deB7bl)E7MQdE!}x`7@X2&lew6*hwGvKf<-6p3kcqz$gBWg*gYS9pgW* z0es@mSoptL_z4R?W?kuVgNpEmJY-BcPY7uNApWPpeTLt zu7OWp9encWW_GA_;mdr$m+8VULA)Q6rTh&dpW*%<=jYzPUCHlO`Q57Yl;E>JQ~#&| zKJ|uJkHj}AA0i~aOU3(%AxD<;7Nwulhie(WO_jIJS&u-QuPwX|4RTGp26pR z>gr`dzAP`~%kti;@{Q}RAP<=N&jgm~K@RghUb?bfz^@|DNH++~@-e-cXqPbkold<| zPl@*r>$j4AmC{R@rEpB)ISMaRc(%ew^eSG5%97WwP#BFTF)BmG7b&duc%lk}B;(P! zB!88{#R{V`Wc(6^wH^;DP4W>bg|Ah3zQWZC<7Sfb&}dQ~CWR%g zRk&2)I)y6~u2*;=D&f5Jc!uyf8R`y(c1ZUSjfpnx?bz9CD~C`gV-xJh8thJ~r?I!g zQX`R}SVmpDdz(#mRy+4}cWT3~nB;}U!?6-=<`Q;j|7_gTQM+xs5+nni{i?Nn*)i2K z9DNtbrt*e)wN%@1-5AD?gcr=PT)Lt9GNja69D|%_cxkAYi`$iw zOY{1sR%i)yzJ0^9E0d~mtVn8)^`f!bi^gi-{$}s)o#*IP*dv?Lws41117pnPFlvUV zA=C&mhEEy#Rs+X5L#w>X9Zuw~^X4F{0^|Uz&d1PwGh&e6W{wo{M%L%ffSN!q$r(sh z#8`u<8RgjVerI$|{%@JK72E|3|6QF5K0o2H!*zajw#VXKkMJg!g=Zgiev8FBg7AF? zkI!Lr8!TQ4FrN*z)ADQ`jipI=i!6Cnzztd$e4TEg#pC;}jw4;C`(HRmlv^*fUCL)# z?KJOA1em;&0IWmpwCwLAz~sdN_G=P+E$=4?H+jQ|Xw#A4X?Y`-Jnl!sXISm@CEvE> zy$)W9Cc)Rdmn>d(S|W~g&HDt-&HPOUZwm>^Y2JH*P2RR7ykU#?dGPR9?m8{6%i=8v zjh*fqi+2xrcr16FmdEE>Gk;HkSKzV|^?Xd#i;kjAT~wj#^!c;k@tq=|VyL^qXK3v- z?`caOdF?2(cFYqU9=&D$B*35P*+65qs2P`Ub*7&-q*Y}7VivrOo#Hw(L7s6 zBX00GENCA0J2K0`4;eatD7MR+X7Q$hr_)V0c)!KDDKBcsBVVWchQ+G{FN!dhgV$>w zzbl&Zwt&~5c$o(8Z!O+a;OYEj8@!KOyd&W0dd4l~ru(qP`<}sL`|JF1EHU#JhC+kR zAG)l|YqNMw;OTVH#av#@;vE2w>9Jn&4IZBb%ybWfr`wIcH#&c_E#47B9{I_5FBm*@ zous^%4IZi}Derp*52s0auN%C=ad>fqhtHTv<%Jsh JpdI7s{y&&XOM(CZ literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a new file mode 100644 index 0000000000000000000000000000000000000000..d607932aee1c7f8175740699b6b119dd53733c54 GIT binary patch literal 24256 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 CPo$Ut literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..084248d905060bc196c4ae9ca9976bc1ecc0b53f GIT binary patch literal 50778 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 SqLES87(NitUWPEj`F{Xl*=$Jw literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a new file mode 100644 index 0000000000000000000000000000000000000000..84e168ea2e3a1453c33527fcc6d1d30d52ea487d GIT binary patch literal 8652 zcmeHMYiu0V6~40%ds*US<0Oy=amU^yY-)R%b!=m3N|V^0I3xiRQ%EUoypIX%;Kycn zL!F9>g_u&&6a^_%P!XwBQYj#Qgh!B95G$24 zyE{8c<&^eERdKXu&pnSh_s)HtbMLfnOy<+sJHof<^^oW>diplp)_3czx^767`(M|) zy1JbQM#Dmgg+gd+>M?Xd2!)H@5JKUK86j#|u+sf0F=C~+O^y{wcO@q??lNVYt-?@x ztUr}ZKkTp$QHK2!$+X*oJWWWI&0xCD1ngF8a=Ueqb~ZDTP3El(*t{j10;znsV5Rp= zB*!M>Q+6*^`(}f#Ck!Lu`tR*UwMf69NM&r=*P3;ZlqVr34oG6Eai+;1{+;bQGVg`6$CAesRcKJsCIp3+=?5cL( z+}f{b?Ui?$%8goh=<=ukxGZAjxg(Vhy>Yw$<0t&T-zVBXoI6%&)D!0OTQ7Vd&W2E* zF6$H`ust{=+E%6>NFA!gbUb}loOM(pbei52&Rz^{l6uj1I&A)Wb>lW_E=0uI3$K0r z+KXGn`Mz07w4P5-SDgjTiL2Q+a*!uATbeM9Ru!tc*UKpGsSW z!c@MX_jYy}iCa7OCpr)0GRdN~Uhj=>h$nPPjjlwG9?M(fRvv9MC5M zVijlxXoEdL6z3NWp645+{ZeHBy&L=@=l^dm{Y($;9~KY%W+V?-%Y?~w67Ob0qqBY)ZYMXMtko8RY3i>fz;D)GupcsQ~~v( zx;54iv2dT6N99`ONWCGqc7rXA}ufo^{%z;jM3Q2w?+;P&@d_`~o@f9wP0 zZ#T+re{X{48c?A6Rv-87Cn}epIFEnp7pEs$6?d#1$M;Lj(yzK1AO5250=K`DuJ*BAs(lZmOn(ND@D{Mdf&rL%v}!!- zah*i%Q>i?U;w;ouNu#I9)0Ze%)aA?k5<+Vw`MF+3zImjy>J!1g%+*f%QAafMC8LG2C@BExQr7cK49u~X<7%Ap=S&vxx zg2ikFNBIJ-_?-M@_f-B`G8Fo)-Yd9MpPFyF*>Yg7nYS#*qsoZ*up_clBIFO0$pnJ; zC(LmSQsg)Tq{wl0J9Hl@a+^HqjY52v6!s-h9}*?rAMoBF?ojq!7)iy8qzLFwgSIpZ z@iOUZC#U+75R9+%lO;vHkC39C5-IB8yrh55H&V_n-wOPFuG|Vy>x!YNOR(xX_zF#Z z?p5u(|F`>z8Fa6LfK%uIb>}xngLdx3+?X~*j?rB}t_?ec3vmWzu1f_fpSu$Rx4*aH zk8_Xy_^k5BdExe#1;e?eK(#Lef!kjIPLw~kOZnrxb^H4aOhh?z?8tH+y8U&-AMMz_ zFi`nBj57VPF2Vx5U`dwjKkA6Q6F@4Jv!y~DhTXN~b8o^9InBKH6LVqE%4=jE(SGp#T&rnRbDnkWe#iFDALM3pxZ^mATa0Bg(-?i# zhg*vd!)G>>p2Smrc|Sp)nx320(SS>^fA-W-y$SaoE%KSSs?Ri*zMorf+TShowpJ&r z(c6Buyy;_~Y)jS*y<~e^eCm?)$6V%tFLD`$S9%SYyVToucxDA&>eXfsy*nwq)X58P{*`@?AEzF<#O)52$R0=K_uC|EE3u^(thS^~QLRlrAp3Y5P`A#nRU2?g!s+yzzs zo<*7dSQjA#rX)-DA9ci^0Nr`S4>_yj6jv$KLJ~UCWZh2 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..eaeda2da13ddadad812e73f52238a671286a0c70 GIT binary patch literal 270236 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

Lx z(r`uN7|uc5^7)?hxP7@--pv`|k$2C4sK;{47YO;8b`qSNlNG?|6Sn<$QHYmDq+uR> zuF;9|m?&t5d+TQjIl1qWd(*Gd{25!7<=+XHdaY~WDntJUMZhJUfc3#ngr%NJ?~m!P z)|p&eaxeKVxRjUl2zxJkRQMMdUx%vA6w1zU-sOW^_=xz z^T|KF2*BPs1z+?R)9@C=m;<(n+ zR{)|DJY^JK0~k79m4?T3DZEZx>v+3B43)l(9=w}?$NJ9nu~$}j2XL+9Jqd#CN*R^D z2f@(O*8)6Mer#U~uM5{Y-ifo|J>|h`*YMb@E4=S`@LmBP@3}H6eJ_Bar*9+h)cs(- z72X@TX1djUmd~Xrr;Nh;6&TEiii>icO33n~|2we2N-D2ykUN(-`7@9^1j{}v49j?# zPUb7ywgul8J-F?$K^|;xdlk=-1Lw%2AZrLU0ykD{j zeJ+e^PM%j2T6{yI;K=B)_r=DUd8fAK6de!uLpw6*!R~^pMfC;v%7zh!6(P~z;_Sxp zN&k`?>Ye#-=17h?)_P~un3iScY^mCEcl~$jPfzeg4WB&KGq5C4KdR$zxA^9bN|u-z zftP#4*uiJeSxZKB_^x=PdsK45QT3G&oWy#ZQEsk(0Wr<`Wu_8mv6@fsn78AHnc(ST zc-!`2JXwxUoLKc}_nYG<_>OEDaVC&;0p7zc315>56g-yxRr;%${9S(Wp6z4xi^RM( zQGaI_-=1ZxPb40J)-Ao`k=U?ap5mIR2BU-ToSAKzb7uCJCANTS@scsroSE_tCK{S%hMF@|p5u@->}?z~)SQ{}VOxZ~ zvtx#uGdsTQD~4-nqYt$Uj^VRjC+*~WpZ%Wa8b8>x;8C0~Ou0|=G!_F6=giX;iN1+* zWTxLSx<-fcgXhebK$!g##~IFK0 zJ=}Nzt}>K=SP^hZf89f?F>5LK{QiWTBeT=A=g3v-TIJJQYkmwG6Jd6)xLOo%5GTFy zT0G#Zko-#QQ*V!pEp}pZ3-2m?@kM9J51qS2?Af-3g6~k{DrGot+@-;iLA1#>z%5Bk zoALcn7}jw=2Dh1Xt$8qMmH}zrUw)qNf61GcxP!Lu2XY-In zZBM3|0(`ZCk9Qlis`2q>*Z+0unwH5a_9} z$|$@$z|iqB8lFDC-UB%u?-kHYzcQEt3d8xZF84ZU_Gii{xyQlK?R>y$pqTln+aKZrA_yrv@I=Q6)u3Aux?A2h#)s@C|n0*A{q(Rk3n2Td7u z$##A-UNg70bAI6bdj4hn>fgEPybs8s+@4=wh?;1h<}bcKFwyn>0eR-hC^KY^6leU) z@6;ush5hc1ES#k>&eG(*xn;`E>0NWJU6V#6vQ>U-K%V>VGfTR{9R^O=mtPd%R|51i z;iE^Vl-Bkp#M$kf;Z7+n?7b~9e*I^+PnuEG`@#-m#>G7;yeU&6PLcmrUu36ITGl%a zaTMb`qpdrP(m6fGw7a+5Ui{4+QYO;;i!JgrcmGaf#_3*P^LTu*Vb*qePEMqG-zHR1I;*B=a4*C=Q(K97xWl2uj)NK@y6=;ujh)ne$cExJSBoB>Ib(bf7A8Yz_37N zeSIQ>^JuC&t5dT=0i3pzyX&shMMs@8X-3sdG3B{C8S!pa(A;YNpf6jTYQxy;>wnTG zpPnzn3MKRTJMmOrrs%hQw-;yn7UMlC@I_d;Zb{-Bh9#xh=2+|N0GDhUws>O1cU9mI zS?7o6Ke6Mj?nsy1m1{(v*do3pfv*e5?_HoI#M*~ndoaWaLP4CwvvtRfT}EW<7N+OO zrdda4nE!i6RQUdUOY&HL&G04T8+>7&qrY-9Pt-4;dur9bCVx0kJTCP}CWe#srxu*r zwl!0ZbM%8t_G#-k)ka1g;aO9Yrrs}WlK2{h>A8{w8yxVHP}wU1pCy!c~l zAI{O$Ir|*tTg%RLbyXcKe!b>Oy5heemq}b_;0~V^TE#(Iw8pLRj_`Hlnh@E zD-B0Z$8fFWPLX$QG}_}oTHtXWE{#4jV)>2n$n&l^hUfIV<8$sbrFc%i+kdoowCoJ~b7UySF zHabT=TPs}G5zL(BK5ik>vq)Ic{SP@IpDg_qgQA2&_f-VV_gq%K#sM%me}f?9DB=jh1fo= z_F`AA5~uJquZgGdwR>@_O`7|fL`L~ldx$gbLK(nvKmfAb#o=Y4biFKK+z?N-ai6#+ zJcN}GA`pklJ7;g>HnUBIqH>L+&MoITIc)zSYzR&q-$wQiKWlU(y9$H(e-rSYLVG4gHB~onfrc+Nh^TBg^rqTrtl58kB;vp)-AG5-j zTIDhJ>@LI&KNhVlPd^p~T-*4OIhLcJh4@j=X%}_7(P?&$ih&iz)%x6Cs1tfS9OUV= z$U$Cq+jRT5t0k+U+aEDH?bYq&s`ZW+E32yiZmv5nEuz8o`|O@tvp6fd)h%$KD+RPrr~@| z$7=x|!xN8T6zd=b<|jc)ZUF@BiRh$4df_bwe4D!VKV7$6Ko5arUb4 z_#9iuJ8+itczqEL3>gJa`k&g4gLu-vJGe^8xHM2x@caYE_b1*+ z?6>6j%}AcAJQ80Cm2Vs;yKowDWGdbyUYPn;Dmxv(>Bd>b{0gT0UL@Sj;=JgJPICm# zVx|sf<>AZL7fuhn_SXYr0=cClPSxa&TCzM7sr`9Z;gXX#9ga;pb-6jmEaeH$`0C^G z>A{|tr{^Cph!~My^@SpD_Z3YK^_Z8<2l^q#=b!h@${WKrx zLMd(XiL-n1YWNO$q&*yotc`4H+)|3Kg610I5K`_Kwf2i5Jz3m8P=7-`HBiANuh$1_ zvX0dLJx?tN<(it!us-SiRpWsxLG*Kdh5N1V}&QD z;EnR~1bI(x7~P*6^!GfGFs2rDk`u<;^2uYNshPgvQ-9lcDZU@;dt81&wybMwV#4;) z&dNlj-U##En^5=_eaw|(hC0_8%P@go2A8@v;?K8(4A!-|@e71J!%8DN zTSZZ~=9VuM@*K0J;cUe*L!E=o^f>oJAI+KH!QaTFeAI^2XUCKud`>pyojI11GC~aX z%}g6w_z(UjrrUq;H!t1!;b`s{>f-3{n6Pt+D}KY$?O!a`1QcS)`@{@^lr#a<&g-pf zj>Ut&SxL>YWB3irI7rrdmIQTuEsnQ{V?Age>;hQsmFApZ8K&V2ihxU+b8}@#KLN|| zypz0c-UE@|oxiB}HGbFc-0Ya06N=ev;h>JBF(FvGJB zP}f&N!ZMU!;Gs=Ro-K>Iz)xE=+YEJo)D~pt?*IE@|%~`6)MB-)(0}2fzv!XA>Y<_=GXHs0>xU4{4D%Q3q+HmT{EzRlncuMFp?LAD4UsKPDBrk4F$5Z0# zo!W8c1k(3Qsr*Tv07dyhDkX|To~mY*kG6RVo8^TJ;ZVkHsTFZ-mudhd&cbVKwGNaQ zq;s0N^lhe6cXb=z!?Z(yw_;sVe4|zIcqrRYJUtv`Vl8c}ygVM+=HE9gcIX;Z-T!7AN~SB`!(7s0Zge~=v87{loC zvR*2~I!nX4t?QdkLx}i{hcdLJYhZP}a?mBP$|$^rVCZ;n1CQ;Fcub4JWAoAR5}-M+ zR7RBx`!F3Zqv0`K3Qym2OpJrD9lWrNN?#hZj+cu?N*Fw*PuD+x9<-jmu^`wVDWlT2 z6AT@%1b8aHNUEK_r*N&~%>;oi&NeE2kAtJ*m1*f?|E==-ZCvYk)MuB2r;Nh;CKx*2 zN)3B2;)04_*OoDBFxO3Xf|99q%O#Z!Clr-c=sF za^NjeU~pA^xy*z2wuYzcpX)q$Jin)S2t0l(NKaobDv2sTj<+g(%^tibfj89shXVat4TX62@DXnD3 zsOiziVFs9cBw!Yp`!>9s6MDrzJ-;_(`pmIHTYBid&i?Ye++zjP-|ZQf2%IjM{)b-r zsW-j+(*tIHuhDT{$M#ru@5+w4ju*$TjIFFV(GBe=bfxD}TYkLYNG>$L!;X%{`)K2L zY>8z~-Lzv{?Ejn`R)1rnb9~^8Q6S$@iyjGCa?xWGcN~oQU%oH)+f!llGdu2z{p-ma z6Tt~M7h?42`lz+Xa#)Po{A}pKFEA&XS-n2!*s*7ln)}TK({qnc%p2W5Vx+&<5FF}y zi*t-uJG+AYp+KnA*Xt_@z1EoXn^$vcCNx)eT@JlJ-zB5QK1+ni6~9uoA-~ai{?*LIK^~&2;X1C=}ntcbF8mW&M>`S@C=sS)&286-VmH% zwQ$e+>(}R;30!m>-vlr&zO!f4hTWNAyYkKircZwF-rp~)Zar1LGdC*V$;&cxkDfPm z&gra3DV|>3mdY9!5iB$D)r9rFuP-*IO=fO;x_tZhZ+Igo`fAodDDb6NVQ(~v?=*$7 zGrlX6N#FhniL8Nqe_)`%SCAmvqU(o)2&oBN5sO;_ji1qV7LuXH1Wrotp zD?hqJ>D<}(PPK(NQaXnFUojkOCM5c5XC5RwLM1Si&Yk!i-=xt;Sf*$2Hw!3_C8%Z4 zxohU5d|Q%uPum!rkvWDscHIQ~+aIEFw?fcaa{ez%Zv#G1wn%aG<6MtSo2ZlGz= z9N(xDRyt>pB0T5sl#jylyo^?hZV`08_l>e1)?E zH&w1likAf8V6?V4a~8C>&6!&!f{`_60mV3)yYypZRLU0`$zR;MyrK0LsfVnMr`9y5 z)6ICR(AH8~C(JSwm1dTfY{(BLo<(_yMK?m}8pS~hHt6>dSnat?+v)+v>L^D=FzV8% z_p;P{C_B!@c}6YQd_|a8a_&Z#ZPP!+(z(E$O*t^xrpV_UneQ~tpo>XgIbBpfsDA{X zZOISMYv2}5mpGKGr9UEhfG!&Jm*~zijBn6I_(I&r5F%p>35BhFj1h@Lek=LF*+(~O z7?06KIJPyW>!a&>RMl`487x4jF1Y!wS~1v5RSdU}UPU}UPVE@%A#0k{rVjR1_w;|3 zj)eW7GHN=`{$F3iaL)_-0@h*9=V`&R`@(Eo)3DC4pHxQS#lX<Xp0w}e^D*CRvl4xMOYnvIs93RvyYlu=stMVYCw6Su@pP>0_CgeBKwjZamH2XgYTHVa;n${rXV;5r!hXRm)x))T%x!6%G8I4603g(&&0=1WHd`wzrwddmbI znkL`!d=~3gV|J`J2P@aFVC8y+y>iWAPCp-f=zAMZ=1hC_DBeg7_3TI#ZeLP8xp#@V zIKi*|am9GzXlldHj&^S-nX%IJi5+*(X2yqe=T4b)dDRzU-#WGIR}&(Q$v|jZ#yE5^ z`DSt}zW;Kn`kB{;4fwF8e7tX^`HMc^wEw5in0BOZo;kzJ7VFjHSljk5%epMvT(N%F z`kUX|{9f>kG4YUK4IS<~IxT?$89o>|Ry7Cy- z$OT<_r?+PheO?5tWPIOu(D@~`sP13@nH9)swav9 zcKVki{qj`opn0Mzd;dPH<%hqT^H6Ul_YmI}&gn7sU`-!kdQUAZ=*m958|!$;A>LEBdcXy>JbrX5w4o_V2a%Qx^=o<^^ZnAF+i&bjAMXSe^1Zy3IAnM)k%FK+4?iEr5CWd~BHs`E}t%?kA@sx8%> zeh_`s*o?nMYCp0p-N$BxUF7N)0^pSQK9m^|{!~u!t640wgFLZ(BKm_LWQ<)SP-Z>2 z$I0i`@64S$qw0a!w_koOlN)_46D*jxefNaj-FtD@MnnHqEOI%m>PX+7?6+SX$zDJp z{j3MFQP~glKo4?WBna6NR^K99k}ra`xrez6?C;mg;QmAGZ7+;ozkbj9tjnn3`iE{~ zs=suLc|Xo{J>Ko#}|54 zS=k*c?WA7T zJNAo?MsK)iHIz4|{%?dY$bGNxQZv&R#C!ce?dvpu0$wP0zIn2*679J_^k#4M`AYt* z^U`NxoRwx>OnHjrV~4D%VYAZnW1!Inm5urc;6}G z=kqyfIKy|$*>qrHqASEWgLlli=)fFlmLD}*j-k#=>9~?$Q^$p6ylt3PeJ)L!Yd|Ld zK3M9ws9PZYmY{RRIZC(`hVp#&tPJUU6akm?ZVye}gEI90sv_W$J_O77CgO)Wvv1*A z8Txy5T0d5vaOwXhEW@7`;q#5(S#(g)BaC5i>HjN17Z_7XScc)H4l4znjeH5&+D1op z0M!yo$Dq^{N@1nxr|ROVJDMBi(OT85O#+aLDDR#smo|fVx~77(qers!RF)3Oz1PlG zPN`j8XH!lww54EE2~t5s{8l2*X_J?uqmgI#sBbU%q1U1wiuA3P%l62#y0+7WKi6Z_ zGtH(u#gZ$Q@9FYvuM^}?HH;p*7s~T}7;Y|U_^+mm%_VoxMTPzgx+RA3AYI6xpgY|# zUZz`wwI}W|^w9yBArOjTci>1N7v7JtG!zjMqh7jcT1>hruGsJ_9cd@goAzAX8yRZ zs;onYb?r@@Ew?!tA6sdMTfkdr>yqZV36d7-`FrARo z=MR*jp{wE~{WRoGgE0ozY&%RJ)5$!jI*&_(@1xFDAfVNyR~MH+e)abilpF`Kp}t>x zHeKAj`E$#{!hG;IJ|1OawS6Ge#Z@MLhf}MDn`gR~-W#0%Xt#XQexyFfJc#G#S=cAQ z)k=O%G9lg=EcWf5v4P*6{h9dgZ23{S0;B#6dX;j>9;YTv?w^?T%ilrQrSw2K&;s!- zy=~~^g*+y zYhiuXW^?lun*!-2Cf5GG;o_-$*{0Bv%A$O{6cGqdF}Egay8Hw3OSZn#hhsl^S)^|( z^CI7~gdS$$){aQ&_Cs~O*&UZ%U6Js8BLAX0E6*u;~*xxe~U*5l!O85_%S z%Z9>!|H$A#K_J}2b$b3T>Yc{-Ou09_!T&|yp2mBPJueqmnlCMsr9Wm7L;B48aNglz z8+=zFPqpOavW)N9ogI30B()ntQy1(h21*|Ebf^1P-P@6n-`{<1!-SmJ@#hk&?j7Ix zN}utE>}wyd|7jm@{#5?J@V(9(R_$BG_c>p$&%*EcCiU*7lyH6nHNLX^V*ekEXa!Fp z6R-W`M|@=~D}6QNYUMkTiXOXC(tlnT>b(N{h@sboZ1*?8^8H0jcf?r*vgFyrIA*AI zVhOw%o^wFHzsT^McS*xh%`ro*8#(6_{SJP3mKejoYX?Dxr5!L@AHEo zO+W7CINwEs>kL-*VORXLs`bg-x^}$QWLS$&&Z0Fx5tOw3Is~!Es1#>E*`GVP-u*S- zp}*aWFbw`jSEJUlQ@zww-70r8U@fUwe2Ed}Fk}lp;V*kVM0JDBjF5lyR^fenx&sB>CFO4)2&-*X*v8$C6&~;BeZ0mLo z;_7$N?diG2_Lgfz|iqt0$v$-#A8^6w+7cb9^biBgQ4Sf01y8HkL^g|9l^DZ z*8)7YH)RxF7Z^HTr-sLoQ{hpcq~mQo3*J9^@V0Asj9=lM!8OyZW;^$trTqQ?8O9rh zrJ-D>xRO8gqvhHYSV`r@egEgOJ}ZYD*TP(%6%z-R>13IJZ5w|7`u}6^UEu2|?z7=N z7hNo0kY!_pFXC7dARjB{_<|9^A+jWnFS3nd8{z;7k|lu*vVE{*BZJ)t48-Qr7;sVt zNMd4=LI|k^QHxusX-FILHf`-Bqz<{1l%%F1O>jaJHROGHpJ!(NyEEf+VyEQ$ef{#~ zFYVd=&;OZcW@l$-W@l$-@;!I?&u6=FQtU$$kwaDx`PMxy^n5m_;nbhc_>2h&$4Z=r zIv39=YP`UGm;;$_1V4oL#DjQVOJ$25)AQ2s?bjMSN$th^qiXXk^#a~pKea3It_nOy zJ@MqUBab&tJ92MH3FcOwf;WZ#)br(`*!{%EKN@@_s9B0J>Q67KeCpuwiqkSjIDTMB zmLtFU%u)C9<4xcH+E}dUcwcepixZc=cink-E*v$TzMo$7gJWmn-F8mB1$zq59I+Rl z>X|l3o-s#8nNjf#LlZD29(?67%&?=LiTE6|BbNF*>wTdf6EW##o+ICdmt^n6IhH(j zzj|8ao4lLM+fV)ODX3e0r0BKcvmbx5=>DPy_Ku9plns5W__`NAd%UQ4a><`RnfS)j zSd;OorcN_5U@pEg_%>EXeE+w~ju)G!NxoBk?_v6Vuw?Y{v7@Ja<5|4%dkpVL=VafP zeQYGz{uox69Cf@*rNk1f>&)1fVWu1zHU7du{kFN}!Eg6W%LX&Qr{2Am4&L)>V`)$` zNxfwc>b`!MX*$WgH~rzUGw}AD?-rlmRPSLJtS++U5GAr+c|M6HX z^)JUpr@nh^Z0g&`My2o;HucX@x-DFF(;Wwjvwa5{GfD9mhR#Ha&%R62d;H6>nb#gk z_S|;x!b|m=%p#1N2>(Y#ey{#C^38RUo0 zpY9V>Qhl5BvH(d?!q1a}Fs#wFA3k5Y{G|#Xjn~tKn}opUNn5y{HtR{! z{{S1`^RXNkVOeh11Js+vh&}Zco_?99cX)cQr}O!Z;Wyxi?+tf)_K$k{r#$`hp8n_1 z$*11~mYy&_%D;Gc)}gq8^Ql-T|9g9XJFhnPMvFo&*2^q zPusYk5Cos$9+~7B?$Pi%%sndnm$B#f`rVmX^`igJa*qb~7q|z{ zkGKavzfq-~d6vA)>zsp@?J>Ti0;R&&au54_?#~K>rQE~+8txJAEoT4c+{2%WZ_2zw z1Aj63;m&a0-aG?QPKcgPB>kOBc%s?4Ja7AP<$u&Xtt>x8*bb!l&ntE2`9j*-#Ib~0 zj18A1EZumGSRRN7Uke=U_I5k?c>T#|Kd)R1-R5hHyYGL5uhZju8hq_=BOl`>@w*kr zZ)^R z7G*E}QOm?pN9LaSH#^VVG5N+brU%vU+i}H>58U|Djq_S+KG-+Zw_yh6QA}m`E}9!2 zJ&yH3l83OG%Z)$ZFa>LYaP^PMMd8{Xi*oqG`0AS`ydFC((K_+alnqyIn8Fz-ReyPI zI5{wOd2B&fZ04E8*~uTgZ|K&6SbEH%SaneSz>V?4*KfG8XYZo=mi-@`d2r^2O!i7M zi=*(D4znFpITS}hT9O&$L`o0{(`8Lm52 zmc73TqcUrnc8tetlEHnGRhw9^gcER77|ym7-~N^^-7%62CSP;KH6=?*mg;tY@e+QO zTiU2mjEyU$*$ap68aN9xc;0;oX}5v%cglH{wU!L;y@qMP86_XwnP}MCRQw$@5$=oE ztejqM$3mqynPaU-Ia8(51!%t-MVUM0N4n^8I(J3MVh$&u0K>)PO8>9eCVNY_;9 zvr}di!Ir>zJ~x@M9bNOQV{guT@ajR{Y`h)v%OBdDPP+W2^-|h_&M19 zBUfS1{L3~0pMg3Zy(HM|=%wM>pu7g0G4!L@i!hFVij90c=GvcZ6H`wqeY`V=J24y^ zNqd8`PYC|S=*$xp$Z!8{be04a$Y1}7y$Jmm!E@yQOs5Zz_7sgqsGn!>yeBG_nlF`c6h4>Y$q>h!{Y*b* zF6{5u^9*iMFXV83;Z%n@CZQT3`ED+BKJm+Gd0GXEaSoBt@oI;kPU9$ykUmzQO6$1E zSJT$KjOIOlqpmOF*t6W{p7&DOC6PPxO1x3u6J?9d`!&22WS*lt9#w;~CE8!rGVQMn zog2Id;*I*fLmcGw)KP?IxJS{e{G$p?L9fD#7gdKf>gN&8yGM8ODt~ZS{&2&ye2YVu zc(EU+tX1n(YoI{l&H7m&zR=*YSNJ9v|GV?#*;!ey7~A1ZZt1#4In;G8Fi)OyUpP;| z&K=@dnmeOhexku-Z^z(ebjRl8b;n|Iz2g>Ux5yP4&(8Vz4A$FEpu>#pK%Fe^SWISj z-15f*t}55hl1cf(Vnun5=HIjKiQlh&g?8QuMp$Q3crUS4*ocj?7u}k?pXg2uH|n_k zgBUhx!S2B^%LNfRz7h^Lj`gY7h?V0$54YE{*|-mTxQC##To94-V1I#q9{a5Gpu3#M zV>q_s_XX&U*hGZy({Ql)9<}(`3KqWSacuLw0X<**_z-9F9RMHeNTxGe$-?&?9NT>C z(<4qq;&&7dHs5nr{Md>XKDIAxKKA9N;3gt`$Khb}yKZ?;?-yRf~_U ze2Jf|$0r>7;4k0#zQ^Nx9el*``tm72_%;BC|1eHRp-hD?LLB8fkFO4yPVP%SB?#XR zkM9lWtVczJ?}Hv+27D=i7(YHm2;av%zB(k>7}!OG?;{>xn-xDkWeDF>9^X9h<;%~1 z=JBnu_@-NYU-tM~z{j?!h+N<2J-&8}k54TUzwdf{Ye6tk$gmf_Z+Uz@79XE-gzqPY zFJU;gfWSUqn3W{q&ST-{{E9YC(wPAJKFT576#VhJ)nSuxCmX&D+$ejY52_>m!?3v3 zz#VbRiK!CGTu}^$svS4#%YfTgggM`E+=z|gGQNzPoGT84A0v}~mY$8sAG%yd!Z$I@l#vdSPmHeH$? zm99^ZPLD~Slg2BN%J-xz)AQ1$m2=b8={f1?>5>^M(#zAOGg{LXmCMpg(-)>MNS~V? zTREySUO7LVPRHx2((gzoDrconOV3ExrnBji%8S#ZE6+=3(&H+xPPeD4D?gBKODEHq zSEw$LUYTx8zcc-n^uqM&^s4m4ba7=-I#ySczBK**^rH0H=?Rq=rR&m(84J?yN|&b> zrz_H@r_V}{Pp8sT)5*#S>1pXn=`+$L>2c{x(w|IEt$ZL|JY#lxOy$SZpGZ%u{KL3s zJC`!ghIgXMJc$4|fhFwYvxR+nwy+P+7WUcMlJ7mTYqv{Z#>ekd|?Wqw`&9P*{uoc=SN^1C7fBasbApP?bZ_Q7kYMd99WVF zF0wS@(NSPYB6ydj(SEU~zuVIrJ$<34H+g!qr?+_eC7z!3^hKV&*wdGI`chAC_4H+) zzTDH%v0_O=jaZEw5^B__t-mKyaFkGAmq$*CU{$0j`)W_W%+oLT^!IxD8c%LPhaclou1z1>D``wji+Dh={=sl&eN~+^y@vn z*VET~`UX$m=;>ioPq`<88$A0aPw(^eeox=*>03PgMo%B`^sSzLlc(S8>DxSgyQlw= zr+?7X2R;23PrudEcX;}3o_@Qh-{I*W^7NgazRT0^^z^$t{ccacCwv}@!!ka&Gptdy zzAOArNb7fn?R%~72pSEe)^87_gwc9R&F4pm*4xARWVOCJoNq$w?+xdh(E4Q_Q}DEj=eMZS4UqP{M6AW2ETUn_XlM$?V$PI5uD-Z zYr^>_w0&JL+p*6N8Xf(Dpv}=Q3a)na3j;pmQ#9X#V4I`Q4eoaIIpI4Kjh`2M&as~s z9CY;lfX~1Y|MkI(j=ntjzN6n7@R>Bimj=If^kh)VfFU~kqF|DvcLddr{(;~;M;{$r zVaI<-FwW5z1ydaT+~8bCuL|ZmdP}g-(OZK{9erbP zm7~8qSm)^JV2h*o20I*mS+LvDd(_$iQTlHU9(U|F1_vEI8~m-KZx4<*`c1)i9erHz zBS#+}{L<0K28pDdezSsdNB>|j&C&lTnCa+Sf(snID`;`_Z9$u(Zw{_<^nu_yNAC-6 zbo8acZH|6Ru-nmVgHJg6jNl1JuM3`W^y$G@9Q~Z&MMpn7_`ahL20wB1lHga4eoatZ zWT)Tzf{BiPRgiM@D}r}8dRcIxqt^tNIC?{{%F)jcIvo9u;08x84nFAUlY-rjo>Tos zQGPo!IN;dN2)^j(rw9M!=#{~@9Q~5u2abMi@H0ohGKdx1>2q6fnxkJHR5|+kpx)8n z8NAccM+J)=y&|~W(Z>W`j=n1BbM(gG7DwM1eAv<3f{#0Tb?~^OFANSkdM5a?qpt|Q z>FC|T4;}ri;OCBha}X=B(`PZJDYW&bV49=X2lb9VQ@_(!ophaiC671C%{_dJsFd~A zabMr6EuCVytTPvxE?XBJx2)~7w3WGzjghUbcc9Z^gxcrnR@ke0Bah8}mbYd*hRr$K zlC%7;wEe7f{B&%Js8@E_XR@f*Vrbi7o#U!?H%6Wouj^{F!iBoB+rmP(NojV`Rtmw` zbiI{EO84yRExpM;$5opY%5t?S!MfKZY!(o zXs^DeqbCY!b!WE~qa{|1R@=u`$~E;`v1!WLip7Lfv;x^|p;m9UlYaHu2)44{%9pEc zFIJvd-PLDBY*qhFk^g0mf6LI)*Kgesm-Np$e}3falK$D5Or*ASS@bQ|J=$WquO6`O z&V|-#ud=dETh2bwmDV}5+4tN+i>hTq6cOI#>()#82a<+yOvuq1D*f!)Y%Z3pdme$tc)E~GlEaQ8f@KL5%Hmn3; zX^Sy0LsSbb>b12MU7fbNvVXI!Hak97J5gQc@GNm6z6h0~9b`vNwBK%|(MB1m5|+4T z`m|XHz$$rd*C?CVu9AOkx2Q~aT*CygT_pqCZgTfpZr1g)UGsz<6)`q2ylEUqDP|nU ze4$4d$cBa$gyq;A*5|fkct<#n_MPS!oIA?3urXx2*mtAtp6`UC_KA%QTO*ERo}>w@ z92*#AWXsiRciFCC>1aDfca-faWtr_36~wlyl&rR!l)RQ(Sa;fPR_X0HM`gU_9MzYW zn?SN>l(H>UFWFn z>A9Qg$aBqe?pC4hg2Niob(VVHc8wZxj%&Wq!d8%j%$v}8^SV_)TMSVX(RPg5X|}7W z7j36JnL26-T0pC=uwA1jr0p8Ea4biwv1q%74M58=Y{T1bRxM{chYfMpQ7S9TwJmJ> z+KyrC*mkrkZQI#;j&q&m>B)7?cV(T2KN}uCblHwk)68+r7o63yv9Mut&T-3^y`x7R z8yY^d*pAV|t?inpGK(HR9ble&BWhFINUJ4dIfso`+bwG5*{A2=OQLC+JL*?nuam(l3Zur{Z@LAGv%tsqOVA#m$G1+omEiHW8O&)J-x9E|}c8#8E zY}e>v&34Ump{)j}jm(oM;e(xxiyq1x*L>c?XCE6WPg|B-)Jb4F=DS6##|0ajr&e$t zd@OAAU~V~DPXV@Tp2Ukfscc~MfbsT6dh2;r`D(>Uq zlG0Pa)f+zZnnLl(F-$5f?iEu0PaT~E?WTie>@yVfaE(5u4QGXA4h`Z z!*RYR8^`yx`EarZxY#%{M2>M7UbmGVUt0lOkB7r2IC=TF#c24|i1o+>bpRN0#K{^T+PC7r>nf&!7xB)>_9n46ny557$)y z*X-f0DS+dgZFaaEfdZ#cXrpj0HXFy0DEV-=dN|(q`EVR_Z1ZtsNBj)aGYDiK95@q;BNJBw-vyB%){ML0QY$h#}P33&f|Fx$B{7kaNqK9cNf6@)WiL8 z0bCK@r`qYVy8w>wp>5oK1#stkxIG1M%RLEZSkz}@8G9w>mj&%-@b0Qabe z`$PfUArH5&0FLju?ezOp0o;#0+#>~WalGfX`94zsSLxv%Er8>Dahvb61#nFsj_r?p z*KLi5`+Nc11`l_j0PZ#q_hbRw$2{B@3gG_C!~J;y9N)*=>GE^|+&4YkUlzc<=HZ?x zfa806JKVo6fIGv(Jy!t7_xd*97YpE;JlvNG;NI)u{;mM-dJp$P0o<(~?tc}){fUSB zY60969_}9t;J)bL4i~`vvxoay0o+eK+&2o~iZG7Az8>E!fScmsjuybp@o+B{z%BJ~ z-zk8*+QWUX0B*B~d$|DaP7n951#l00xE~b24STqMD}eiZ5BF*T+{+&BM+I>I>EV7{ z05`hSy}mywfIG{>yIF8fJ z$G6DC@tf#;xT`(fxB|F-4_96Qx68v-6u^DL!%ZxJ`+|q#nrQjX;{^{_SpfGP4>!30 z?q?ouY5`nnnR|V!3gD_dT&e(Wj)$u*fLrY0Y75}5@^I%Az~wv~`%m(v^Bo>8T>$r> zhpR7u<2U^U(q1^6mGTtfj| z#=~*$p?vYX#KSEpfVvaTSvYJCo4 z=Yl@Hlc}~a=!&knWpg^Y@722;CV_(1rG7PW9QP+BUS;-E&7LRr+s-wm#(+r_)J#R% zMF(p+m}prp<}|DqUW}=zI>w@zvk}#t`rCgiHU+25be3E^PbWqAE9K;LgOj_($4MD? zE^xf=C&RHUrym=~>n|e5^>AQ0+-MAo;eq@W*ofgqy$PGm*I;beDG|Plq1k+G79Z0< z`1qBr&9}hVuu~#@mqN4o)>wRum+*Dt*yd|AHtduLUk5asuifH9Ga}^USD@sR>(hc` zh9@F?x5B~3Ei<~{Xrt`LX5&^s7jD|+_>&&44Z0n!;686~yv~$0*amrEgkf>}3v4*W zoN*40;^0*3Y(8VWjty0^n$dvgTaJxs2fk2#jR-9bH612Zzs~M~r!VKhb*;a;qic)I zc7i(jBz5+@^XH-FrkuRaUOYwx7|wT6gXxAxw@$8nYkK+c_{{;6tf=-xO58)F*Q|6N7bL z7M5hkrFLc~Wv8jxjFZ{HA+Y2IM~VhZZn)!y8QBuG(q*!BdbaXrtktoQGZS;o4()%W z`Ic+~Ym@BEo&ko^PjIf}WOnaROmQT4ljlP>{Ot|1v0_W9!!**YnMQW#xspeQli9M= zX<qHP4b4K zc{_6Js+y-ITlO~+DeJ#*(fv$tj+ zRLJ0|qJe9se!i*X2-nextCWsm-s_PM|J6wF@)J*PY1uO6&!5a*GUjOP{Do)!uPI-9 z^7F67;|v4#%=@Q2J`%LyC^g~C*xcqz;@{?+*&`o*y0UZXU#(t}9UO`6t2V5}$LCFL zfse+2IEENCPs|o)Ps>iuPT%?LNUCjAYOjh>-N7cfl%^QQ&Y|5S!S3pvqmIW$1+R^Y zJ^Wf};@eMtjk8?8RkL&dYokUzqU_gK-QP6zyH8cd=6<~CdxzrhdSdcVo-BPW9(?0a zY0apb8>W_Grto+s7>O;Ilf6)da`w*n`RBKsJ*dughl=%%--p&~R3`DdCxhc}aW9fk zrKD&q+oXimZV9Kfqdkchnk{-=P$`FX4HDVeo^|oMeaohh7HJu1jqO_(uiLwK=3kJ5jVhp+VTl?orRMn370^Y^&? zrtxc7Ie(99H;v)YZW_s=Q_`RgRwIYaGlX@MsHO5xZn<>*D1YRtzSt# z#=8Q4pLOgL!}$;3tm0$06Bs|ve?b2{{|a2sSB=gqQGutW|1$c0N}n8zBG?H1v!79f zI{WqLv*QzVzF;rCa;ZE^5^s?a&vJE#Xq7 zTRM6f(CUu9>z8fpyk3qk+t5o*!fo#9*s!6ycX@{i0a01l)wOB$)?9apS=fb9hnuN$ zF`|WC%80l!E+J?|$9gofGe|S8Ez0MUI37HiFS#ZuuLX5pBidOil+6y*>`-NM%v{Q_ z(_a-bDDP_8$yav1Ublt*`TRgTOCj1Du%|n5bZ6;D_XWm1ZQNOk(w%us;z7KMAKX*M zo$(BLE;4w;m-Z@d%7zgxKk&;%13Z#=~32b)_TQxv{7Fe1cTf|7kf4J zMty#?Z!`Aa`gyp&d!T<-mz6`+18?N2vS;L`vH_+KW=8c~B~$v&Dqo)9h#cy1(ko@lc2>xsrN=jJo%Jba=>W!$&_B>(^3_*Ulq7&d7s@E+oQA;P>#!ENX~ z+wwgR^JxkjG2D3nWU<+Nz0gzGM1-#i4)(M1ZBTe$q_8nA!gmFZZN9sqH)0bJzRTfY z^F0J51vhStm+<9qZ1a5;`Z8=H!pC^qe9u^XtaF9$LpZkiDxu)k4Mq5Nz{Td{`z1Nw zF|Y~WLpZkiRzqoon~3o3g@euahQ&7yHsL#fW1DXelsX|ZII5q+X7i1~NlN^9orUkK zIJWtofl>=M5sBXmaIpDmEk2gd!uKkUZN8Ta#P0_l-vWz|<)-i@;NRxs{5w-&7m@g} zp>D@-wZ+GBRrpdKUoH5UE+WFm_kK2Cuf<2a@NsTrJAMnm$F_wCR3#U9e7Auw1q(N} z0)_7~;P4;bzyAn=JHMDh79D?^DmjPi;%w-?=@0|2?k;#R>GgEHrD#CR?ZFl3Z_^r$05A(V9Ta8Y%TdTF!GqmGAn44gl+IJ@FV z-LhAJ?9MrtBIe5pM z!&6&_b9B{ftxZ=xUq6zVIrhl(yQU8n*HkR7=|f0wO$0-E$Z%Tgl!2Pfv6}B33(o!_ zw!b^}Kvg0=`e^Lo_l#7(9vs?%wBp9Z=O$~c;V=}YR{3!0vcvHa{bjb6_UeOpT>xAP37?@A(o{;Zxv z>+_S>G_6^PxTtF*wo}^wVJ$Kznb_~bIx`ZMN|A70V%J`z`k+~EX~7^&OE^!li!V`a zdzMX$vBhC$ITp1ON-W zIZ%7fqwMmX;n^!ad!^#54N-OrfbpB`;U_CR+a+2~?6+~lpX%YGD@Xqcyz_VQe!ou2 zv!@ha6w8#3hWSn4U4_e6t?*HPuJ-V?fiN%+$I#+)uV9oi^vJc!T>IHrO-u{VEEdk9 zsoglQvx`4B{BCcI!k?>w<~QFw&+La{+}PIO`q1w&I_>(@Ce_8Nq)^(Iu)B=T zJXL}G{&7d28XPdX4!dipB{ulbSxtOlIhcc%Lry4El2zE*Xm z>7KKNo&EX%D-12UCUjGM1?Uv$(=O;sGfO6+>uFhU_{fhnz?OBZ-m5Kb9h*AVH?L<; zU9;(xll{u>zHYU~_3Cx&yEm=sN4JIQEQvbv5DU{Eq6|<$s(R* zhgaR*g1BmzRSdah-KOr&{%+G{$&g$Zt{VkFwqsqdfQ%DV)itEjrn0_ulX{jD`Wh8p-sa-raotxN;-TTHDu$KH#u) zRbI^kZgL))&vw+M?(d)@bPBQ*s|MzK$~?Ubf0^$o)3FhkpaSu6v{BB*R*LOpxO!mx za3w65)cwXiZUG0^0G;=W2=5O{3pTdW8?jOP(FA8a*bd^;0&&#WVza}=Evdr5PKoe+ z0GiFW4SaQQBVP$N;TyoQ&9?_S<02w_{cy1P9syqpZseo8@ZE!Bo9`&}6gCmz+XV-k z?@QogSwcP>hJ2sFvCTIEJ%vp~_&x;(o9`PSse~K(_;e!idk)7oANyZx;U*${&%nXv z`!V<=etdcnKAxY=$MMwp_`c!s{o3LiZ}I)q<7)?>#0jP_U%iH7JAPwOAWMGX(~!iE z?La$zT~K&#BErqJZf(Aa;A;bj>Bpxb;XBLYOCi(aKNLBZ_N3gG><4B36OnNJe#Df5zi`1blLz6EA#!?eXm^aK3-(@qN`g z-)f8R2yl$Il#@?`4^E-T@egspW0;i?$8-~s^Y}hM_I3LX!fgPE`R{COavs0(_`U%? zKtmC}UwC{IQ3y!BVi_-dV@

hT&!CgCU!aJLAuJ_;Ic|F||WEmHz8Jz`c$FydEB# zurXZbN1m&s9S#G&&*B(I5jkYpVB_j>9_Jt~B7!rIKe?__Frc%oX_6tQ|Z4R zVF7A=Z*UH-NWQ-74-O}$#~)=6(Z;Q`b@I&< zYJ&UYj|DZD6xn@%;TT!F?Z^>6awC_&tU)et8pp3x7s6Zp}#XGi-9)jKUK{pJKULMqH_Eh$B z?0bGo_qCcHSLl^PE>991HA59Ox7?XvuQ8caziR1lF)YoICG3sGNJ2<*@vYl~n&&rH z4DE3GxHH3(mOsAz_5(AYYVMi1Z1Td-Dk0jqoKb?m$KC@sadX#^YG&o zeqzYUr`kw3p3mhkSNNztVaXZ^$Md;(j`*_M-_#=Ecs>_DQQ@x&AyLfe#PNJCev-mR zsmR`hNVxuzdgMMfiXPBo#PYPo)w`Rzh9)&JZv1F$oKCew9ET* zrgsJI2bsSsrS$SZ+LhW~5$rR3UCKT&_=3mxf~WtJ!Rz=<3cl;vUp02N8QE|9OV6IL z+8X2-2b~b+S@!Er_3Y>ncv5sOL7x3B}XxudsJcN@~B+4PwzYp3Z?q+<2U zQnfmHFc&(eWAEYsM)t3^tcL@Zp2xVuj@~7kt`DFt>}I#6$E`bSREGw7F2lZD_(zAT z>%wjl+r{Y;1;6Tx?Pa_=I=8OcoXc(8#GcQV^>l(qbTMu0-NN2ih3UsAN(^(f`&;Rb zJ|}dps6N>!0O=$)0AofNCw!t0i?yA1dvIV*fDSMac+r8NI0prEa9Qtp>_q*IL zH2&dF`G;c`?)+|^Wfu7uepR!6o+-ng`JDVLy~)q|r40Nj?iy?;8z;_`EdMg`fN9K_gbBp zy!O_u8}%zj`A~|4d^WzZV8+gGlba{MRb{#SCgrg(uiQF$Jm>8@_HL)hTX>V?>p<1F zg&T{|gO0rJT19M$MQNs(?QT>Pa(=`A=lfWZtlzCNz`I=IX&F(uGz`e$M zrv@7_+^Da>#=1-RkkwVY89ODyhg;I&8w4NYLO%KxzUy#o^F0K8H8v69y9N$+{5UrS z!zLf&C46__*yej3dO0=`;ky+MHs1*Nh$9~kL%v6FZ1YiJ8j1+tJ~-HXrK5G<3;9^4 zN&NVLYxB*6!m>t0`2GqGHeVz7Bz`O#h3|Vfw)vJpNx@A-_+Em8&DRD#hRgVoSNML7 zW1FuRO1}7w0B7^{Sn;c{_)dp^o9{L#U9gKt{KmuG<{JQC3LwUh`BmaK7dZTf`HyX{ zeAo9pxZ8Ytt@yDn5k9`7xA{h()WI$y@mu8aJ!+*N(?|H&H*E8z(6*};GJ~Vq?(scm z@l7^3=4*}#;68zk(gMDG*Mohc3>Ri4g>bvPaE~I~416%1`J^J}!9G!&?8AB#x3 ze9Gf11&Hw@-&xp%?^(mguqZv?8&pU7hhcI1JN)2Wb7FcGxKrsPoC;4F^byv=Bdc46 z%Y4B+08=Q-keD+ik>JWODSjVe3g_`nF~Tl~XqtDTVHmTa51dav#&r)P zZ}kyg6LhOFt}|-x%EentvtJ+C9gcAwwRLb8`^-K#d|}O`W$eM?c+}Di$D~fe(U{EH z+2rxtiua=*t!CR3=r@c#mdZXcl2koi_4B^abo@xB=F=mOWIjFenM?^rH@>fD;=II{ z_VyIDrrLw*$(tYOOCG>TOiQBga&FveYcMa_sY05m0-wm1P55~`4Gp`=~nYv$ac2@5%{l!~-`)>(qV&`}E$7;^*-@iGP z%{?1CyMErQ$Aa1s{RmmJV>5f+idz%MZ;O9y`}m=c?YgBYakzf&{Y}3-64X>?b-&zM z_(nL`$sWCiq5T6jGwTi)9W9wT_VDPL?>n44Q2y+>GaC-q&CDLIo%zcnJ9fplHBO)W z@-4e+wg%hw{8wq}2^4J&wfBs~8}AuOAU%_rCq|0Pk+!M&)*f{Y_AdJNG5UM=bYN3K zHL$QJ;4_(dWhc;?nq5!eT6E&KEVCcKV=^xvi*2jf`meACT^uJeHCxH?%FfjzrKd6c zj-L4AiRV9aO!ueehDTv6w9XAP5Axdo>PS$_^qpZ+KdAfp;a{jUZWz98ptCAAvnczH zqrvgAq`o>Y96Vz&uFwqu(tXGFi-wxF$7h~~@yv0g-(5{*hwC%Dn|^j==1sAgvBNdE;2HbN)PDq0i-h8h&dYYbaX!{FC+5V{ax> zgWF4o5^u&*(kIM*)?k1>QbW_hB;$QEaKHV4wj9RQUU*S*=A@(l@@nGs#Hcf>&Ity0 z6=7U=MtxiU!(BDI{&nZWI|p~gKl15av5$1^3ignZJ-pL#KSfB5igfykwA^sA8tVFZZW!n$UVh->(in zcyrC>n(d#N_KF(89Lr`@Z+y}5Gh)f(X9mP3kDnD39iJBCF~(lsaxPM_4ri^uk^lD1 z-#Zp8c_q9j>QFwElH(BOC)gZmn8RREarRDp55E^9rZYLRjo!=OqHN_sIimjQrzUbd zIp!y5cxvXh#9(mVm_wPGIq0Xxck7wNEgv7L%?yqt_hHTg%v(@AxMS1kkBwF($!Ge< zuK4&!T_$sLXa96{9^|=EjRLRR#u4?@<$VBko`)W1pKL8!`ciw*(#ah~IGW5}bvBPq zkf_{AE)HJ1J$P>9wnoWI1m}PPz?z}ih<8zI@nF#nEjPqes#V^MSRBIDQT%$W zcWP*GmyGf*eHPa=TW;n_NM;Z4&Bj~R*`RLBp}95lYWC-r6Q&VMV}+LpoW2EpxvUmA4d8`L)bD*5womrQ(d+|JWgNfk@&YkclW zhFW5L-7)yL@TK`<^ZxBvN&TB9f5ozT^nXy(_^ZUvzE)EFVl1^+`#uz#`^K@7nLwhP z9Bp&1CWiYy;puTe(wDBgj*dO4ZUmT%y2#c(3H78Q&|RX>18wl#%fJ1lL}q`mEUI z)PlySCHy|Y#p`4j2){pY?fQF!b^)lCY^b13JKDqR?+@5cWg9yVE1whVLoY5nzejLg z^!EwNLcD%qEouU9QC$3KVp4m)S90y;Dtz{@X^B#XI^Qd~c=p`m8ABS{u-n4-N-ln) z!bi_)cCQBcCwcfu3O^8%@+mM9zE^Vj_4f#TmeCR&QRjOl7tg1*NcbMfwNF*yN2n-e z=!@SQxOn~jL4@MSmPit4c)IwM;_nF|sqlyg{QkhjS9|ta&#oUv1e8FJvg`jG72ZPv zP(99}g7E4*e4WBaS1G!3^p!wQu*;uT_~`u85xK(Gd-!^VkMetTr1@ug_*oub# zUt@^kT@^_JJ>+hD=O}!XYI7nmjuPlKa`E#NenE(`dzFZv@8Rc%NFF3Gvd86X@a*sO z?C{)6tG)QI_VAZ`_{$YOy2~#2@M}E$ z8ikL_hczDl3T2NRuTXtb)OihJ!4;7SM+v++V*L}zRjMAP&XPZ--YiAdMDPI*|AAnk zF>C%0L|_~xf_4wz9^kc<5{=h(wjZ_V`XeQ(dQ%lD;OmGK93?QSxgC2}pX}b^xPY9| zS?2P4tUIu0E9OyboOejx^Oq`nNw5!l5#9$w*vQw5jo)9{jZE7A0h`pXUcR8l5et3e=Z(JO1ApJZN;*oE7-$Y1rsGzg!%A&FDJ*jlnC9 zy(#$LMrWO0fmn~j&BgfZ^UDU49er`|4x{s2D=^FE0>{2AXmjiKan;Iq(07zd6sQJvY*7!xySL+x@Hqk#b+=#lz24QIQB?H}^oBI{{TA4CSO`p}Wo^OoXdbY0KxTI@9OlCGM z9aeMa+J(KCT}y_+m;oE1v8B61nL~#rGw?#v#ro>V!ZfK7AZqx>dVa3Rh~`HwQJ*}* zY`x#t_&Jsf{I2Zo=vvv=w=VpKk)Jj7cavFtJh`&_2CRYIyH$@vInlVH`&!G6>&Fit zmvwI-{=J*lVQ|gn{+_mut-TvNy5!ZpjtJAYd2L7M_0IJ{xR>U-H>mMCi#PT~BZ0t& zaYQBsG=sX}jH$Y+a>k)+_%S0PBwg6q*_~70eC8hxL!3X9Mu()cCWa6ZvaV|QX%iFTP(ACw@C0${bHVzvu!=0y( z+q%0qSwp-SL2)t&HD1hvgl-ng%3O!-BT_LAY+3h~?p|X>sxIjY)3~{(yYqUbcdb{W zp7fos+79vibz7$DBWA49p9DcWiZr@+aepV?F>=3Gw-?GjrrUjG59mG-;#iMVJ*ey3 zvX5)M>=S0J6YOjU5XbgL**@JjL7nwU*?x_u&Yp_0PwDXpWe@5067d6Yr@bBfD#VZN zh>-8o+8^CnUzI^`X$Uu3w5)eJ+ZZ@`w1U@c+!rS$Dvs2iz|v zANG9G;JycYrpHy-S3LnYZ_he`>BOE9o==KUSF*6e?WSi}AlO>F^`o4=lY2t~83i8G8Q}7`E zQGBP}$DyVK<*t0zMeKbp} zLdNjX101C_kp~|Z!oF<|A}wP*eH$p7wwjvOx1G!z8XmqEtHI%$?8b<1i`oaiC9L61 zOQE3MvN&d%&Z13>ySK+Q0C58wtKA(=PCx{dR$EFVI4;A%*i+ z-d2O}HEciFhC(fg-;4>{6gJF6Pg)nYsZcw^#?ZUf;yA&i+8(~EG&$5HwuOvVZq^q& zY=z|Y7Ftj6$I#e3@dHvm@)^PwjPFC*GQNA%s!^73C@K@jJZPP0upYWjG@3!G4wLgB z_Wy%90aOWF4;#ePEgU#k!X56t;!ZrtG zEjF94&En%5KH<9s$2Q+;=)KrPB!1iBVDqg3UkYxFAKiry%|?gsIq0mvMT8H{1BY+G z;$wfa@I8fNJASW2Z^I@cd}wAme0#xH2{*=XEH>eL0mn99BNVwdFsU{h_pe~Haf_j( zXfPt-{tI+FT@G03Tn?Lr`xcIEz8)y-4-^r;H{oFOJqwt zB7A26Wb?gX@i89?-vu7uBjDR6WCll-<6LdNqu^t^jPYapT=-Uce5r(Prvaiw;DtHQt(OovE3|u(uXS7el_^|g$#S)yT#+H1YZVr z#t(-f-@{(~UI1STb`d#W&Xr}yZ?Sd0RRBx;{>tNf6@2;bOZM&Bd~M)s1P|kv!X|v* z_V`xAz~>SXIp2Tw_;y?Is|Hy3-t_p^7U27($G6wwtF`#1AOe7f_hJrw`=E<3T*?{1 z+2^|teC=@O`JRJ~IOd=E9$z^MQRY(-;hW>}aj>!EXYPfs)#GabUrNXfj_M+huMT`t z4y6r_@$2&VxTZPtm59Wz-Q#Pt_;|ld{BH92c7o5YXJA&c#p7E8KDj^m94LGr^Y|VD zUyI@3PU80wkFN)ODcE^Ecs{~+z~g%veEF`&=RCfh7T+9;@36;LiW|8Rb`go+S3SN* zExvgGOZ?;=fRqP|alq>&0vaVh_4r-@A8|b2`PhW-w1k_V+rY>BTSWLq183*w!xmoy zz`{4nouMK>XUs?c`^!u^Lw+(#u{VRN|2kiW^#^TFbd~tZN%hTNj`2LT_*KYAGw)oES z_#Oct%MB5U-xM6!@$0epmI6#1&%eRr`$B>E&GYzj7T+?9?{bgtg#z(g>G2I%d@C$I z)<1Uo9WB7u>+ua*d~FurPLJ=^0(`f5d^;_^l@{N_9^XiT^!vESx7*@dZSno3$2SHS ziRGgR%u4>;td@P4Lv0a5t;#ckQ-BuueRUThC z23AP=eZb542l+4oCx<~A4~ zC;xsaiMj(4&e6{`l`%f~P;$2ZR;fXK7jet3x|@P(j$2;WvkxQi^*Hei#x~!6pwz4m z*f?~4P3*CI@Fh$9BlwnyUvH?dG|GqXI1tn(?vLM>+!Naq?5W9Cs}a$~_^Joxq!}L_ zZ+*yF8}RpG)jPRF&pRcO1nvgj>r6AA8OK7g%`HOoB5brX=3Ha#YV1X5 z--L~JJodm|8r+G!2<;!oM*BI~IA_TL>_uq*qA1u?{~ET4Z%puA&;Ao*XS~%&Xo8K< ze>5&y^G){bcssAga$LQ>gD<^jc|$t*W~8}eLuYp{d(HJ5@8(T-0j`D+XiGH0LiOD1 z4({cO&Uio%rFQk8SgKjOFTs=|P;?ipc3RoTh05T_{>=#0rQXXlcj6U>e!me8FOUHp znnXocgRTC4Z9@-h`0kmLf8<{{4W8HPgseJU=ZC5@be&dqrmhpHGl!O;j|J6EP=<@n zyjBK<`KK(U^?0>T`>N@1{B7P*S@Sul9(3<&L_Ng%L{Ciqya*@NBSfCWwvCK{N>ty` zPR+O9VT`0y`CUp5yNv@=*dAa~GAm0R=i?-sp9>7{)sx{ehR+VyF5RR)=QD}j-gpKe zT^8tTPCwM!JiZ3wj-3+WV;kA#`;x`SxCoz=D-yp(*jUDh2;T-c*nD3F0m}iFn~az6 z?ZGkANch-RItQDG@a=|!&G#LPk9lAC@OswayA^uA_+j{f!^d``q#sLj;rly}Zy$7) zaU#S~zKG3^-y1OKvQYP*3E%gC3RYVT`cGwuS!G0+q>;-q;>;|h9cJg(yXE&TbUwb%tJB)2} zNZ1bJN+S3c^wL=B_5=5hjNd(eh5qiWyfrx97B7CSDZV4S_vSy@`6RyVynkfkzA?3I zZ|$v__~z(&^IArqAKM+@6MUpKyE0raiQmG${$Ujge*8HR#Xa2r;oGt>DR{td%h-n> zNislHWX*e`FQC}j9&_=<3eWpZi`@NMWBZJJk(7q_F!ORu-Kmk4?KNBYZP|GWr=Pvp zetNeBAjb+%ztYoLeu)r&qbS%@--eC%0*~4Lx(9m^x?$K&DAW&xn)dU8r+e)mwFsHp z29j5(YD}P2(W=T&Phb`f7CmvH3ahb%p@G^v+7+sC(W2Tix}{_WCbE__qYe1kY9 zUj`fH0JcFM7@>{ZE^Kz)n}Or0)V-WL=KwaoM`k=3F86-jI}zkB!(D`7QvAAi83;b6 zP3l*0@~G6;+p(n^Gr63!40!sbe~ID_m0OIWQKQK_dv<*2a@>Sd(?}pTX&Qc zy*OjqKK1oBXP@ZYHuqqxrn6t%-Z;iNTY}6OHMp!h8L*qF_(`FR{@- z%S-mNd>MNY+QWKZ-^^~6Z#_t_;=Rsp49;@ejp;@?`afT{hTnbBeS=fmqh436VddPs z;TpexgHF00Z|*!<|AzV4LBp*cj&V3O*7K~QS(w3@ zQgGw7C59XCSl&a-<8pWJ!Eqxt5#d`72b+)Yy6B&LcD>&R-RAoSblz_w(jM3d2b*s< z_;^o|kGvAU-8i=Seg>WQqloa`4F{WVpA|orJi@mh$K=akqp&Y?P#x(X+PHlVo869h z0FI~9jyMe5bJ$LUf0lm?m*>T}fiINZP>zP04wEYV*tkbQ@Jt@udGp+tDPcQe4xZ;T znc3Fwe6DmnXWj*{P)_~~->x%5*pA@4lnaJq$43|4z4fk}%62W@8vDqSZNa^I&ZPv} z5Dj?yp`YtHtCzf2`E6YJ9RC1kVLF-o9@O;AUn0MYdLBiwCCqV=uwHlVa;Iwy>v7l4 zyDt*fHu7nF=?U$CgRqGZ|4-N=e3|O+v+ch!c49eay#HdUb47M7BAC5~B^h)5e{F&ykR%IhG|WrX%Cd>eqX`Ffz| z<72sI^YJ4B;bXjnZ@0(yM+Nxq_V_rSR`~2T)RP_`+l<7CFkH&#vDxuUS$wP&Bz|AT zG0#`h=@A^WE)WsE7vNy?Wx$t#8?Ogz4dMGY9FvbW3foVEJTO8Vx1VA|TPtUr1Frpd zDs8+RaPpppbsxj!`7>^I+if3|ECVtkhkhHc9p~|ufUp-_*jKb(Px*VYHs0*H7o75Y znn4}Wu#Gnc{qDIh+%?d&eeCkY>!&5go>Tm0d`{78O^MS-DpFStG;N+bs$}WPk=j&x zi1yqwD@STDBXI5+^uZj8=FW^EA>yg%WD+%U91D`;V>mbc7bFt#AfbJ8k*H2gNSuu$BzB?*`=TULJ^BlhNziNk_hH0Mln0o4zl%1a+p0>c z=Zpn%X;cml6{NE6`=QIN*kWPHrZJpP&=$5Kd6}7STd=Y3#=ehuZ!}}$eZu>m^Z!I` zob~>Ak$#K}(Ti2X1Wo>jde{H8?QgiN(S)DydxrI+WXs=de?96CCY4MGS>|36nbe@L$KC^_A2y%zr18&G6I)cM;+9%Vy3K zv_(MJ3l3#-SGQiOQ9V_ktZbf_x$u;qzvnUX);sjGG3xx*f%L)RB}@BL)wkyE>Zx2b zA)P$3syg0!Ywp3GUmnxX%?-n&TCdvHdoWgAy8Md%%P?CBsivi*UQpSML(avaxKC z5(e%Wx+Q;j_O}v)_eWCY^T;u&-e09c2f2&21Iu-twFFSC@O7e|P|lZnc;4xeuy4TS zEAzs4tsHylx{Oiyh?RG2Bpi$B;>Rg`)HZZ$HTD&_c;5MuaNbwf&X!{&oafcG^NB7J z&g<&hC#m>kLWtc;=k=-d@KMa^h4Z+&eC%Y+MLj6)~#51Syoyyfl*ZgHC^u5?+DgEDK z@VxTuE4j<)JX4NEeF%FI;`fV!J@vo97KL9Pe8sbW-?3K&zwqp6l3M;J24|DZ2>JO; zK&N@wI8WbujLz%AdHQ4?KYjj_gFiBMtxpZ^q-P`K+hcT|?|59lPkMH?i&(KlFOx9$ zlQp9T8bKWS0Y@}^^!y;Os)JSCH*D_4Fk6__SNXaP1*A2*hMr2QyASK`6^t&<6g2m(Cj8|*u znOA4M-5s04AoZwV9pUV{UJOHS+t|CVb1UAD{RT(Oig6>@eLeT+oTPgd74B#1d!sC)-HBrUsQiFJt4mUo-gfk27|IM~A641(lQGbz}4Lx@&(?u35`}vNX z-pq5e@|bT5uRF7v=Pk6E%vH#&^HOA0r-Lw^91)pS+)r-yvy?|*vXpWSA1aW*W*&{- zt3EZ>0U|69DZDM%7H`Bx;WvED|JB%t;YNKaHWrP{p&p@AwO+@$}hJ(#l4l+qUwyuQlIUL)3M~w|T zC6ay&$L6cE;>Y?=_`ZWw_%B)a4&JA{$n^~5LgY4XJBKv%&)u_;0t9c z3YE_Z30&pS?>890d2oIY5jjNjZat>2J#h`U0`KkT%{%q6_xtpi+ptfU{RYLYS8Urc z5FeU*uxRPmt}1F>HBz0q68#7AJTLLf!KHk7Z0p!%ldl`wy086#rUwq3b{Nm#Z?)8o z{!UPXQF)n_7!g>UiQ%^-6MJ+&dKM=0+ehaqJu^IgXu?3>&_ho?+!Q|=RF`Kn&t5ig zd(*ED|Dbt#OKk40CnvZ3$Fa%TpB+QGwg%OeeTl_aY`&u3e%gP}P;u*(+b%kI*Fe$I zDWgiW>}h_`i!=Hp!u4#DtygZJIaE0mt1CT}K>tD<8_%lT#r;1HbyU)9)yQw9IIhKaxD%CI8GiXU27krCj#GBJ>P<7H6lM~B%kf7x zTS^j?c#={?DS;F#DJn`POG=U@G$fOwMvaQ&h8R71bP4<3%YF~K(dC|Fdi*Z>(9Mu` zle|e>4}JgFVINo5)UIP$f<(f;7uUagold?+PpRi$e^=2E27v;{686ow;n}qf%d`{M z@L~DQGEa-^JKvf;#B-CYdKg34|!&SdMIMzOy~;Bx#G=xFLv=*9Sug2 z$yhl@sF`0JL10kv@{WO(0}DHQN!7AGyKVy}fmd@+wyZaPq(=jRhJHgM#}M~&De_A; zbgb=F^QtfF4Zm&%%${T&Un{M{Wtq!>^voN z{8~B1agzLEcR_?#Un8B|V&m+5lgHiZb8$0|jkdCp?d)VI+Yn_fiJp_e~NW1MVLn^%)9n8=r=&ld|!=?7;X%&1)F^yS3$R*spR;* z9*%u1V#8s0obzz)&>4mZ!=?0Mv*Y(;L?#6{#*gum_}zkIJARKqXI&#Aao7t78+RBw z&sRjk-2(?Z+%ZrjUD#HTa1Y?v=6e--EjAJ1`y3o>zFH{daN~KfH6?ss!m-Ua2Fe(? zi3s0waIpF2L1B83kF71?`yP&MKK4cAJKvXpv-uWSd~A&g-+y|18St@u6p{F`zP0&U zEIzi@gl`=D+woggAbuQIYx6C$_+(rb&p+ky@moKM6XPiP;Cv6q`CDrVFe1369`5b} ze4Pd-_vLQr86m@7;=r|`?DJR+r5$!&H@lCf-|$I1o`c>4jEK1Zv4^XJAzyysyD2-| zFF=v}%+{h@kNqCsJn*s2C<3z*_O&T&0(gW9BiY2)@c_(7WF#PlD)ok|}~3Z4cL zsTz1hRj%U4`-SHKQz-k;9$-J3h#WG{+PJU6;}J2!CWmOo<$&(+d@Y7nhL-Z-M0GN|uxFGSeX-`?%efNt zpuCj30Bb}SwWhKU_HaB#<)WgRS8~VA`s?&rJ{%mMlE50~$4AE(P7AiOS0~ZBXJlq- z@}}yY4-85lPWkY{X+SA^thIXQOSC}PH}l1tj8F9Tk)1m- z@x1ilg9DG}64|lGM+b99&NvTi(5D_8xCd*{k5%(+#cER7j_I%EG9$^0=G+|I8-I+k zC_a#Twxs5HoWYLVQ|M39>%i+cC%5XA++(d*ZPM|`4euB@{i0;HXy&{1D(jO|=gpaS zVa>GVJ93ZjObkAcHQ#66bkWdc^!wBt)azi!YOdcj$)rsVY4c8mG`{uQK>z&M-ws>^ zEqKRIj*NqkVCIhw*Qpu3Mzy|w(+`dtRd$azmZqEEz1mVTR$$AFtBk`V_;6WgCXN z;3MByA%??^^Pvg4ZKxaQpe8YxY)#(4@kM&nkmNh!M}|ufCs{{5navGd!#LeAJB-l} zH|0w!=9N>DKa3r6l8Ix7-2M&SpT+W2i_}h9%h!L!{;#NBkyfSPPwcNEUg`$jGSOK6 z=IgH_zBYuEg-1N#SRyz6V^n_}pVPENF{940L@u7}k#OvgYmZWbs6uN-v(2l8Z=)h9 zv}Sa~8pV{p3auF(;q{u*lfoeMn$o*1Jv>x=`PYRhj-!{(>9>c zn$pqv+D{^kzg|N+;;2U-lNP3AEbQ&mZV7yq?dITF;dgY*`7vkKLGov`NAsHqW~=8$ zwt1KnITow|`$#WV&t7Pnp=VC__bta>g!ytMHsa}zW4}7F7oq(+Y_u~C*}t~~dlA|n z!A3iCBFBEAX%PzT|B8)vmP8y2HiEqf?d34i&iGZ}{;i{8g!XqEdl!zmChKa?ex;|c zHF%vK6N7D@{bRK5KM_#j#++9{xFFZ&dcl!Ph+d_dNaIJ^gi0m-+bH72nig zJT49)I{mAH8AfNBSrMdy1xDBDR~@_$x(MUE*|FCK_j~pO#$FF>1!i{pvV*S+*lrh5 zX@JIc6d&YoX-G$d+1Sg7forhvNOuA1V{5#ScF=>{^l`J9?MQ1NSlHdyygt{<#WOqA zI+uo64>()B5uP~^%^roeuCrUYZ|vQ&Zo{>->M>)+Ck6{~7|y1R=v=k@hJ(`J-54VR za~g<`8cXDO6qkHxj3Q#F9i3a3Z|qVtL#P3DmYWx~KCpDNM^;t~#mYZOf+&12(u^4B zK3sj`k?Y3Z&Hd{(ZZJljjOf*p9>NxNIaDXH)nBGv!5M~bj~Q(4=#A-{#HqddS3?N>l-BN&V(P*Pw4+O{ilpMe&S{khh`C-gGmkCusFzJD;4`05dyNv! zq*myxQ-ZNjR|*T4BFSaNQWYoo{f(fI%DU91FZ*KC=e*eHOLVzb)~ee~ak#VYh{K)t zS{Vvs-sf~LrH+BPEVrmrs@|jf7pqoj|7DlyZ#2p-H}iM^*A5){*m5gdW5R`d#^@|J z>AssdxbNW}_)_k#H1S;s3~}$*eLiLA++$5ycD3oV2cGe+YB%5G0yoRpS#A;EWcF-3 zkbgDy#0xK52IM0T?JSRIXSv33Q`pnJ5_`H+s=CeoT62ED)xn9l6z%Q!fmB@=g~NI_ zUpU0Y5h;cjUuw>OnK}OzCf(Xh`lGXx@rbi>$;hNRKq0q`43r96ZuT&(Z~ z2`#L_l_$ql*XF;27bO3az6+nI?qdDJ`q~X76Gt6Iw`vcu ze5EYLmXD7ed^X<#@Ue_1AN>kn2aaRL4Lda-6U$H$i64qOhi@79SSFE=@e;mmIJWur zK(E6lB76gIu;bTd#gApQ@O=`;Hs3SQ8Lo)%JqQPzuixSu1Do)D3CA|yH;fHCCDQzS z4w}t(8~AvhJYO7!d_Tak&36cLgUse5e-}0p;wW)|Y`#6< zOTnG-tH36F{Px7=<9c-Y^2>C%+k9UDpX3+fg>Q++cNO%#u!~6iF7f!jWW|sD4Z_Fw zCioBETfPB>;fe@fyT|tfD}Kxm!sm}UP2vJH3Yo!C^~apP0Y2tarl0+Oi3OYTz;5h?j&CJf=VX{qUiauk2u?2=I#7kF@j4 z4&cf6Q3eUYbMI%1=fHFCXWM1rF+PG` z>@MhtU?26#dBvO?I#Mv@qI$sFGTwqVW5-eI5XuZLUCM~X+^$H@u%NY zyc2Rl#M=u+_k2ejXXd!1DnNp9NiH)p!(V)q@kYJC5$Aoh|B?N&bg;N{9j}^EkFA~a z*JA(ahUV4WW9#1x<1CgmR#&cFy{=_d;8YDMZOo|A3x=2HjWJz$emdJ?2{d?^9^~tx zm!Px697pq{F{eA4Gw!@chHa$8xw>sdycF$|#vSb0W+WcvY5rEnC;UXTJCr(gn1BOK zk!Ax7t<=k6=O@pfp_};^wGNNTE+i!g+X8mG=rLIE9Z^w+ilxC^DCTb|NtWQ5-j+%!KGCX+XOO@pwjCsb7&Z#hN-Wa@{+vdtGwu zEt@f`YUY`?i(X-1tutx3yCB=TrFR`3ys&(0^pZ&B&|`Z2&UtFrSbl?d9`=njKF}6< zWZ%5=*0W{8lVcSselGagujY+in3vY8cFy1WfiG1S7pBg>d}e>q?!Ena-SHFE-ogIp z{;Dl>`Q{dH@1k@pJwIKo*4R9{F;Y3CuVsT*UcRC7j@PzDlF9XxHb;3=j9U2;t&H@= z%Kzi|^&5V1T$z4Q{LO0^yEQsFug@!ul@+GPGF(T{vO7Y1^^7$~`IYhXgue5X z-?CdC>fN>}juUvs-m?kw#sE3Zgbb})X?@)_$VV*SyH<6e2?`rjS@ z$F8YQ>9t8y*PmDZ%i~d){yww@sqiq}VSNow(dCnz;Un>kHSBAPHGF04(we1nBz|I- zRe!tP7fKek`_N6ZD2}#-E}OI=OQ(R??hDK7dkv+G2}*12hV8zvyuRl!<3qAU4T$Z& zu)MzakmZ}Ef$hGqJWIfUxIQLqukS(J?~7p2#Uiek3CkC$^a%WC2^SF8&xGYUBX6f4 zxq!HSCTudwKZlqhkAz0XSdNZyvEs)PZ{QnrWKuAOc8D#hok z_7)x$F?N_z^NDkiucFxuq@jlop%HE7!EPt46lA$kJBV768`G^}6uhq=C08VOE5GHa536ui2wpRuZM<&qEW?Ea&z*Ps7VsE1;xSx;w+YWSUO#w#D?);| z0S0#X{tI~ghKOhPhxUNC@kW6W3|Oh}llt9IHXiSPXSj$r1WLlkevXaD{?#Ke6B6vt z!obEG1+WU35szh*;C&6xHr}&fk}wkzyyszHFmm+@tO6}-W4Z{u-ZD;r(`glxQB7M}DI zVWjT*Bp&k;sR(%8>Pi35j*9g&zO{^4ao*xg`lruBj`xx9`=1EKcrcw9Hu-k(=q|rGj@Kp_KliwwB8mMJqcHkU-yZ4xU?#u&tC_NNY(o50ab!_{ zyrCBA&YIu#jp!NM9cze$cYPp@iqOxTjDBY1=#!Zie)5S-TQIOJd|(vbZ3Qf z6~)e*KV6t0$H^@YEFa z>!YdiTV7j#U<+@FYg2L8GHq!sMeMI1zd%X;$8pIwRS0`LDfhm`aH8$=nLNx)RH>PX zs%N+tWK3u;NSu2?y7Skc*E>BuDP3GgT%JDb@0-C{GVuk=n%Vyy+qA4Hn41wlgZYhX zo9y|Gzj$BZrbB+j+FM0QzEU(X_eZm(B+h#kD))&P?w)1Dh_5;tG9SQ-KotlCt^4ZRxrF_uV zVXYKUw)1Gi@_|db%5^?%kV*slz~K}rR_Pna+qEk3$13|Egk$}( zCW*8$uZIQu*z9u)F|{rd20Hn94u74)w>x|fc-A*{P@HS}m}7sy;lJSUkAtWC6cqdD z&pGzrH1f5YMZ$`Iy^Uy)RfhMxeQMoB34;iowE7a9BM%6?erehK1T zYV5W9B9G_93DKT=99X~e9doYkMkCKR%|5%k=b^`O|Iv{ADDN|d=lkdRxKD-nV(%M{ zdo}llMu0UO(AwgU0kpP+h5&f}e{Bn{F`Um8J%4V2Y?8uU~xwR zAgr#Pv0!+0S5tN;zh=5dkfW z(3utW4DkBSwnZHo1&np~2w7{3846KpsE?0fJAma zM3n)rt6YZwD#sxciiA$6QT?UFB%N;)lRfV$(WFk=Pi^H+n9 zqK~iS@X=L}N23*@%A7R<#}?EY@L6U|17irYX%3+U)ZtIY==V^^$MI?ERi5_*^e76I zC#jpUgarI$o4w=`$WRV^8TEH-e`(HdCHh`7R#9%oG^)**2JrX|C2EX4%qd?|o7UEfs{;$=!phcxjmiQ+_H-;HZ#u>U z2RK?=B&Vs2<;aU2vzTKQ%8xnhd}qP1iIgvY@|3aEUD8UyYYS1-aHY^$?8OZ4%1M#< z4%jnaoK6m(g~GG_z20C`6My;5*!{`tNJ(19PT>;BCRPjmJ8Y^{tTLb-}>K>j%>aGgVeV z7rc++*~a@8m?X@EB>nclz{aab;UM7~0z1L`BA#u$pMzn2EF^f3!obE`3Oq?adwk>{ zA!p+y0gx0h=n~)O@NDB{fJZsTm*JG~y@Y2QuNrvtS4i;w1qL?WZYz8vU?+IL!LyCG zGzZ=<9lS>@yipdO%ri*-%K(q*DWtSH?9ds&AHOL_jm+~tZo`;Je&0;=|A#j4d=sAG(Oo&BZ$^0nr+&<7i>vc5Cbh|l z8Wn9E8;GhgljEErH^jSW^D#z4+p69%WqCJk%fziQ2bdo@iE)X$4i;hLfl}iZj=MbB zRQUKL#m!05EH8bqH(54KnTU?@kxX~#C7Y9Nk&k$LCZ*@7^G^1e`TC>^&%`pUFL;Cq zGcXo1ELDKt;i=doU&1)c(1RzfvqYi|w?S5~1!d4r9-i26-@zNxu~W(XHR*q5h#V9NH-{Oot1dg?#l_{dq0z46~Ke=8QLA9mr#fBH)IgY#P_pIFl} z{r)4%7LC4kL(AOfKKzT+#Ln?|A02(i3m;?X$0YV4Fb`3NMQ|#xvaFS<|p?3+kKTiDJ3dLEPhGu;vaZ*E$H6znX$4^10SQ z1gXT(1;jC+aQIo12E;L+u)SUfk@Q7aQwGFyZNu_stMp*Ks_ATbP&(H|*u*iQa0tix z>oORJfnz}9RNsmiP0D_p+m-?{A%!YpM>HV(pKm~e4BR&1D*Uwp(xMzbIj-==t8vbg`)iqD6Z4^2k1hy z|F$sD$^VPP|G?pY0-ku37CE6ob(ZJh0_=8N7OA76 z#&lX+z`&eQQ!?-X$-c`iXH-YgH zwx@~1uao>_>KE&N5_RGvFwW9Q9r#xny@~p4eMdX}=>|`K`R!Auza{T6XAzX^{ftrQ z57Hj`e(LC0KWy|zjIP2vM}IT4kK5)}JSZ1U8~+$+^7D**z4o7LRsMu=8YlBQ0~vN+ zb*xP0bWE*$>DUa+eU5;W^#xNhl$7LlrH+uZ_oXo+6kfq3BldR^r*l+i&ckDH6O^a5mnnU>Kex6m`M770))_ z!{B#72~m!;8Op}vxY1IWC81c}2;O~ow(+&VI@ctgpHXheB zJSJd9j_lt;*?5h>OTjD&Wsmb518?JTUx3}3lkmL=IUBFr3LnEM;XCEvaoq~jS4i+U zCuQStoJZaV+ggH`fO|W98~~{hFzE7rx$oV^+h>K3@e#bFgU54dCt7$CJ~^jL^65gz zWqWUzIR0{cN!}YW)u>Po1_UIJ+2dbkRBP5$FsoOavc9UB$lv~M>B4;rnv*#;;{VZ zbmKA?mR^BX7gD&hm6@ez1xMqe4gM=z^d1*WQ*c zw9Z+jo9^C7dH%_Q{JfI|dD}BMWwm?WO}F3lRqWUGc4Ng!Eo5+#YX5d5xWDd)?w;&z zW-)K)-Zh zIi?Vnmy$$Fa7-a=U#Rfv1RzvuGEXBTTg1C^SiUenvpi&<5=}^-_|2Fmurecmsc);l zsb%2l9!*!c&-ZR{>^mI38$9Lfq1dO~4PA)%4+sODy!5HeM<%^0bPU#H%ycumAJ!Z- z=G1e|qNDT0qus1Y>Bi=jI9%>@y(h~f-OW-n*Qy`JH+{bw>%$S#jq|Qsjz^>a~1s?M!@t6k$uNlwG-}0qCh-c(KD(8IjW!UujI_b zO3wIA_DW9Hu_xzrW8|NwjhCo8IiBw6y#h5Q>eKGL_4C$G=*5}kY8FRM9X~lo*RdyW zGwWU79&=YOPJTG%&b$|pezC%{J`CH-SEeOcABODEXOIIgkt@-!0>g7FI3|{cvM9BX7fyq{Az~}e<)UU*V>{=bqtD~W~7f_ z7^^fjcE%-Ra1tI!l%-dy0)zjmuENK!>M8_^ufk`o^ulno!6xzqs`mhVWGWlP{qid=g4X>aSWD z*!2z1a1uPb{^D8|=4ZjX2hYsQLh?mk0|Ohc8+b{WF?@FYbrX2vrJzX1pt|{Bh;~$) zpa79E#@j8L>=f-lZh_b*0c5%kfZLAI*MVV6V?E3iv|*>=hR8oZDLh zU5Mdqf}%VzIajv|x{!*8|G`KdhEAD%OC#)Sm$Rpa@o@k0KCrm%(Pr)Y`e0kTuDw-F z``}sjy&7X-b@>xTMb1>Wb%u*PQ@4bb8+9hgTdKd{tsS4BrhGEUtu+#v*FE!xsBIl;n{WGa>&_u3v=Lo zz`^Ub@E9%$AIJ4=yrtmz9SKQ%*|)R9*8@Dpm5O;(@K^`ic&m*aG(}R!?*?b%@f<`+ zKc)x#dIJGx zy)Q&RN!jY;FKa9HD{`x+w_Mk&H9}+3oG`fO`mZQjtl~wzD|C& zTzTc!$yZ=T_uRu7tZ&Ot)wVs*#e3to-;LYAQrqwPJZ=Mv;de+XhEsrE#@e^MgYWN; zzgcj&L+uc(ZNtvOBD(REn>gg!(v*uSxoB5jL+r%1*tV`KN*2^Cn6thAa^A#l#&S>2 ziKh>&Ebo2ou93YhZ9nK5){E1BZd<Cu*5pIliu>Tx>1N#LrOcl{&OUB_x+pn3JzAN>(*3>Z$G!gD|>I^;~f_yUTVLt zXwRKBv7@6>`)c0k^O)+O;SH(7v0tC;9NC|L?atoC{j;yVw`NG+;{K{@Ki{>prl4=_4YUWe<{GZ857$Ub018%CyLC%Qd(kCCd_g6)S!CA~Le z{=1DgM5?+EjVg=2iBGY7J5SzJ@4V>nVBCMVw|`c3-=T$1MNU;m@4tQ7wpiKr{#oAG z^~LF;XCl)JC&y0Bj{UsP!|K9om4CC#s;h{UnMc05YWtyr%8wt3Hq6%e@RjEJJf&ps z?*3V+57iVO@sfql6dg`9AinMNF*2o~Z*PB9^{$#&-?eQIckMvx%$~8g<|KTg&&1%G zQ}4X){#lJWZ@s#*sF!)?C(Zj;7ON+({6KTnGb0a2+qU2RV%tq+*ioCTY1_juAjvQ1 z^ZofnbkUaHKQDT)=ou6;hlix|R4!}Tw7q8VvE-(vUhWp2J^hm2vYygAEA;%ryu4)Q znS3Y&18xQ_%umOEeRBOhh|MMVIv(hH9N~_X>Kr_K=3_Oda1toPT=c~Du4vagaGKWO z`O#A&nTM}=3RqDPiN*;RKAIu@QR-1x45_eGEcRo;Z}bKWBl&`v9D-2 zTG{q^f3%yih*x#bea}mkZA*K~7K|z{Z{O2DG1a1eclKAM{!oc8WX8*fBIVm)o+v-i z{*Df>{Jn|S+HdH1^zH*t;}WlRRJJ|PQ{Ktn{hi~m-SgGX7H}{3l&`Y4hH-5b>2rGIyE5T8^bAi}mGLDV_IVtq8lE1Lo}ki~p|3eQx;)mN zDBs@hmCtMcO1pPzRKeEARg89Pq}%3}sTe(acex5-iwfZZ^_x^7e66ENh46s-MI1Wc zlbMycB~zZBlOCqOcy&gZgzS6A^E&2s?CkhzM_%XL&YhiK?fj`Z4OYsT3F+bK-KM0e ze|*fs{L_{++xv%gv$VPV--|0)+HCJ1-i@2}l7%Xb@{vYZ^Xmnv6i%C1SuBlQoUCrU z|L$|{R=duRAS{=EXVX2K_Vf?hA3qVB`0%0f3HR09aqu>jRD09;N4>Hu(t~*Z+U1DX zk&&CmRG!xtpHh9Y?zZo2zGrjMX1ZCt**g(SMoYU7J*-M(44j;teH)fHoV@6^=k6L+ z_r$Ne-<$Ws^E(5a;AvFl&3y^rjlXU2=7PQ7+3f8dxh1l9@s{Y`y<1{?zq2L2cjVT* zy^FV=z4@b?^Y=1sS>AgmhurqT1&8`;7I_z3(O2+5!HL*AjvTs3rR8?mr;mCM1pO{Ij`b9ectY?4ToL#6*K#yN%gkyJpE`#L;U_{`@MsOr$!dWPV~fTn_>?X z?BojO+MUt+BM;=?&gbnr^Y71lfKOl9`6bqkw@1sn``?u+Pft!?k*-%E@Ghu6`E+;E zN;jN>Gw~P4&r82~JbvEKj*qUKtK$4n_ejKd@n**NW1IK%58pis@&4$RJ^drQM{nKJ zKl&g;$JpN6eTB&<`lGVu`3*n6R8 z+3gP>^6rn^w`6X`ktOMZ6NBE7f1>dG=!r<#wLAZ2=MQ#{y}da7=<)o@OYlyY^<9Pc z$+zmA$WPvWD3#{BWe6TVl$TCD9=rQMO=BO+QJxCeaI8qBT@1Hk79iio%eJ+9WzV&D zBOm2=q!JHyOiV28c%`GTY(DZQQ6i-kc8VZh)u;P@T2Ofw{2t%;oz1&dE{Y)+>34Fp zSC_Ud-F|dDQkm$BOey>x?J9b8Y83WHO22!28BP+Yw~$rd`Y?(Dthp~t?>rbS9c|8Y zh^J5X*4+IIT>(P_Z z`OWR;+)=aOlc%b^*%Rw(N1yZ2^u7Iinxa!L?7Md6sJa{1E&tN8I}Z2XUUb#?yKADS zqS4VW9qzxg>7%`q*8ZQaTc3)&=TqPY^<2|-xPOT(C(6xA7+NWO&~!d#RwD1FWJ$y44~;^K+ep5L@4iGB1PkIJ)-&M?%dOjBY0sq$8&iXo(Lq zHCY^O<{>5|kMzz+w6xDjpWi+myG{}wee-ZKNnyk4rgz@9_O?lBjj3D8Dg>c6bEM%w ze~rnPJOf7W=SeL1)T!zib4;v!diwGHyQ^o`9l-CnwK!2keZ_L7i^}6~j}6+NI{Ks8 z?~7$0GX)h@z1P4=%*%7mG0#(DYLu@~@_B(Uo;a2`IAoIV-%mMS$>)3Tg3h^VO){#X zIgTxc-507o<@9e0R8;lwwJd)*wiuRA_~RvP2S;H~|2QV0Y2a96*!>VC-znmukrw(l z@cvoiCw+N$Y;xdzw3M&*`o1)~O@I``@q7m<>4a-mUCAEFZu}>+yj4u`B z6fHm9k)Q6dvBvQ8okv4Eu<8FyM}DTlKZdb1O*7>|=`qaGhQm9{zn}K^kcg^T+`vf; zDHWElQuslx4pNe?VknKm@)s+4jyr0)SRRxf!&?c<&sOrmSElWQuR_~%&9f%H)qrA{ zsSo4Xv#AVUwPRnc{7d=})&3J7Vz{*-j8~)NcllB^{*#ukbL8uk{6t@>&VSPKX-7V- zD4o|(357M{Zkze4*FHrJ9u2|s6FLd}zy}yGA$BOHar#M&itR=y6 z^ji-99f$vc!~e|T{}Vi4XBQObj{e)R9}Y{}GYxq^a*5%YlHBJt)$j}p_jS!SJiiz2 z>yrDym}hx*&(+4BX~6r8+d}TgdN&(h%a8Xy6v8X<{>Je9a(Vyoo;+((fc!}Cbg$okwKvi5yJ3c1eBOnQ{2Yg0Xyo<#sq>l)-=y59y|sqd z;jQ;>F?^M>$M+!<3u@{T3=c+XZNc>?*ugiwrLMWNxpwXKe5_s9Qrp?SS{Mi)K%>yqzfgE8Q0q7dfy*rFR`)d(&ny3U6`y~ z*t(W*+P- z12dd}-PszLnb(3_uLCpj3X7zIv$d5+2r{N+*SD|i4;*zl`*OF-!a|8keOrU4QrcMBh3CwQ{Jpuv8eS%=xY8^|Yg`a06T?h4|eag4oy#x(N_PQAV>C_>&&FFaa zO5k4Xm(U!120C#%sRQSF$^oZ{`W~~N^@Dm&IB~D%{WHuHx8hDc>fN3?gFo>hFetba zJ0MT}BcAsO>X82&^&U^1o5%D?BH@^Bv#BGT*HcG0c!o>@{(OQuK`@f2;8ZV<2wAys6!sF!b^Ni@3Uoo zVmeYkNgeO47&_BsJoUXMzhJQ$>!xU}d2d&;UV=aO>G^hskLkzwz-xuW_AAZXDVNai zk>TchEP+2SQokGb0#Zk~l8|Tk^T8)RZr&F4EO(N4NhlkSLf8#EcN_)S?|k*nbgj~A{r%V)zhvG z3mH{ihb(A1u;LDh=vq-MLtcSDMW({UgGon#twSFA;cAf25u^C}i*J0arEp`JcWT$Fd zoo`tC7g*}rP*vTopnSkva!^i!cvjxn^k*#*{ z_E~sLAHn1IZ{u-~a!dK<3-cv3!3xA6YO z!7B#dD=-t1@V(&RrGWP=gcx7uFA3kT9lST->F;4LB+#cEypzC__c05?f;R&B!+yUf z5vgqXZy4l4@kJrPbYu94D|ozj-o_h`J|^owA&GCfgSQlTl71IMSnz5cyb9pi=c@_c zdmX$c;MD_%;hSyYUE|;_!K6kR?1d!#-sj*w0=!}f5$`=v6249cuM2n+19>c@;QE%b>-obko zV9cLF629L!cp2a&Aw;|dP!hh;cwl@Pc2Ym^y492Zp&eBTb zm~rO&24Cch!1Rf(2P@DY7>D)d{PVnb;j9?0FX}#oRdHTdZ{b4hTxfhv-BMh>lFz)a zn0m`fKFOWMnZwU@;r?T+=X~H$taAI2nvIc-krTKnsr1excN~gN*ft@aE}XEvW=vm8 zSF&q#7gxG2?#eq6JMZ&{@-BGxSA)GF4S7fNFBp6@e!<|rac$nK4`3BP*W}A8q-)xK zbG+on1lBT7N*|o}OS3LNqt=d%QDLrrs-WS4m5bG#NZMWTyhuf~FVgVx%3sOZ$EAqf z5xlR4gt{4N5LWjMTJTcS*yd%;g;?KLIDb%m1S{qza_v=)b$;em@s6d6f+OcNz0`Cy z-0O9JMNgcQdGXMo#MPP73HN2rnlNa@h{V2|yu|pMj@|UV%(9!X7XE1>t94j7Sy`XU zgZ0F{xO=KSiq)TS?1Pw?c&d6_(Fad-VhPf$Ols^7;NcDwYdTzh$Xo6!Qu~<)H_jWfbvQu0_Fr0D8~{#h|lA zF_a`>{|2eO|8(C46@@+BclvHv@&v@QdBW}oEBPtD2r4LxV%Py4mPY|+5%+|K?T0J8 z3SWk)9Z(D1f*bnvo9=Z_izX3)2Iw;=i`~q|#+W!!W z_M@OiAOycKJi{{r@$ZK&MEL>;Q=aX<5!?yqR|Yb%T-SPi^ZM1DYV2>h%=KDk*3_;M z4W^p`hPhfbM6I0a>1P;W+E&jk>M_vpRATLNbAE(O06TMwb!+NcH!NC*tB8Q_Oz1I~ z{*0sS!nJp_E>ttc{sf_n|EUeJ80KwRO%s_M#T`aw%9HPu_v`Xo^6&9QqVoGFnWWnr zy!UsCvFG>7yLOoFlvn2X{8Hp68ysYR^_`-QXFD{C7g9|fFRu(b?*ZmJqWg*D(RqNV zx_gH>CDZWpKiL;7a}onyX)rU9<;A*|!Rrl%M%@?f+W7A~WZ}Hmke&Zt15>=ZfrHH1 zM~mgP296OzHLUKx(La6Q7Q=Y{w~9xroF#|%rZuk=I=?Y#qA?HIL^~3)muk13PL6qr zZdgW;RG!q2>R0?_TiTZ6H!gM*l;;*lPS+ij&?IuVfwl3NXDKVhZ-lfJ%5LAkj({>B zp96(YK$VY$&>w)Z@jAhGK?w=o$6#RN^;>u}ryTK~fU@y^4xZnMkl-DJfsI#)KuP#m zV+r0-JllA@lU>rBn368v!n2K63_OO1@nsDsct6FnjmPolI+zJb_a<1DR}O9EbpU3(c_cE*By^-v+!7>3SK$f+u?f{ z4D+Cn;GGL|JA4`7$@^dpEO-|iyp#cW34FJJK?kc;EgtXG?X z`_9@lVp629urmK>B<+<|sNNCxTrJ)_X7fijkJ|FDTevIhJDVdXVx^0>{Ouv`P}{o& zJ-#Nd47;wd*LGO)(7CY_1?77VRsUwwygRTX@qt5sU&H;k*t=fMo$Eu7-HrXWy}zzs zS9t7+U;qBrycZIeJOJqpHG6B~-;0##ojhMT9{HSp`ttF&&-Ju(Ec0(%%?J-W7mn=-(X1MZ;n8i=d~Y$H zg=l}BFwn{0=QskYq+U1yb`AZ6Lhbts>pj>6>; z>MRidCvCp=*44TJhX7bH3K~WXwpwZ!#44~vM6xE&pWJx*|EukkLh>&sN9L+{WXWrQk6vg4gQcZ355lQAp~{W*FFb zKL=hh%osj~OYpYinc-u+NnGRAt)BD`?WlG^0V1PKk=I~&CUxd3kZXcsJ4f0kjF($y za<1-f0f$aMNp78qotEl832ht5AtPSrAIy0Mb>{S$)2ko`I{i5+*XqpRk5P_7Ke=i^ zZP&PI4C=a(lZN+2vHy9==Ce?v#Y=Y`N~k-xO4HnvSyj#Pwg~FOA?aTp*Y%;8$~kG# z1uuo_;*!hq(nGM@xP+sHe;Acqf19qA+a52TKLYjgN7Okc{QbjZoYFA;g+r0D+rSl? z-P>h7(T=j75s8|P|XD=;9Uv>8!rVs$`Oxl1+NXyHr|8acR&dV-U=Alc-6qGfEn=^F2UQ0XB#gGCR_M! zgPe`m20Y>rk0qnv9l*1Vmjc7`K}gzTe**&>FJs~Hdl0;*@JxTu98y#VJbqU~lp}o| zivFg^fGF3kp7amxs9u1w+ilOo@J!lmTw7R;z%wo!SE9d6C&od-hDWao7RUHth<=io zPPSYZ;`<|IqklxMV@+n|bU_Ix0bt{i2g<$v^LhabL(E{g+~+R-^4wwAIj*ML~(lDpi76I!trqZPo{>R z%8%@u=T-db=y&^{PJO(;Ao+2Oo+L4+{qJV(y6SNB#)h^y?y?;eNlrg!#ufeX!8K6# z)%>n6eqJ(-G-_nH&M_&|-J925e&e82>{KdRJ!4US{F-X0`ym}p0p9nLe`7pdRF;1# z8EI3ez8u48d6lUH_?@0ATEKI~Mzrm~^P-LS*9__#RDL2e6eo&IQfJBN+2%ORV&!if z&p(xl<)12w@_av;i`VVu)ZyoEiEW+VhI?|4jK|1R9`1T+Q}5I(eI71`o``!4|GoXG z)V+B3BTvSM-h zJK;kjy}dt~^i;v0$*SIAjxRv{D`=VPvW)3N`g63+S>^_$=jm7b22#pugKTFh`=WTrc6M^u zKKoh8D}14WZS8RQ!W`S$VUuC1H67r&ZS5jQ-mdW&e$|@wL&H*^t@Cc*#IDgOKgz+g zYbe@}aqP$VNPOV=BR26KTl&B{Ap<36J&O!O`%Yn?ldpF8g${4GVJP3?*slUl{}^)i z9kx66`;7f$Wnbuh(Xs!sv2RoM39rww|AE8**vMa{DHvXm%6r(MZS((}Yzqp$+z(J6XO0de>ZB;dZ0@^Huen7{|A7D1ZAk`-+U;B zLGT{N^C&1GiN{N* zv78mWdV|NjPC6fW-RepIz*>d>3Ov9nBUW6yeL{)Iuez^SyXsw78-A>9DEh(k+o}~p7y7^K_s3Il^!f`@k6VXl6Q5Gg zoao|c!pO=KnU5Wbm5)`}=O`&j>*Gkv)Zy)0B9%K2GBkNdYgdg#8k+RHW%;TI&R5^t z_Ci}~dSnllS?-yX9&6&lF@mFQh4XcKYed|a@Y!+dy$w@o{Btv&(s8)j)DKJYfH>x$iz_jcmWt*%<`A|o zRDEbE|8*-x+|oaNKT}|m2p;jo`Moe6Yx{sW<`A|Yru^&jMOd2$#QD6iJZp=9IOY(x zA2`Mkwzpen4DT4nJ!`{&IK~im&sI!8JkvC6KUT%3$roV@B_N(@8kQd)SmKFin1=1y zdkHA!B^~=@V2LN5SsHd<=Gfb<1InML?xkV9$(+M6lS!5frZ)RswC9`V7)K*?A=)=V z(VlH?-ec^}pKgY^5an+d20Hn@P;}3b@_wz)Ko_F@-wFer{MVrw^2(%7@GvH`2q(GOmwARRv}W^9!O{tD{7ldE-nY0D_gimh zZSQEU#W;!t#*!G|YTk5fU?w!I69R{r@3e6hy{m2J08MKPjt`vM(qbY7rg2pbjyzn< zbTFZE9qQpC1>cB6`f%!=9xhs}Qv`!l#z4nU%c!&fk`@v!NCD!6O%Y5UTo{D=@^#Bq zz%Bn_G|(Xo)hH5EU-`%(H4a&|HRC)-M7bSJfJ{LLv@`8JK62wZ_D94|wSu z$Z;NiciaQRnug;^ETI!AGj0SO|6X(&^ES-UNm1iLD6E)w6SH*xD}iyNi^*3RIXI#m zaWDj>+*KQW0d@Fu8Fe^XM*R}cTT2~HKNLdo$nDtT`Zt_t#V@I$@Y zoO6covD{$zSTiv^ENAIYjp3IX`zGl0SINPhl7qW6?GfHZ)PWyLhj}I)kS^!LzGS|! z7k?W}x-2v}m~g+IIKX}D<7p~;TLnXSs7cu}mzeKAi)~O6zQhk6~Y;|1B2b#rRKGiH%!AG0j(*Jz3Tl*h!7VF>(B}ld?2NLFc z{c9T+WPL0oRUW@Z3^{n!#^RB|x`oVdhw@Z~P%Il*4d+9V)Hkmm)vw^OEV1zpT6lCT zc&qVj_B{{8U%GZ@x8LW1X> zDb-_zkMCLVq)jYo#&f+_2$+#0yUq#UKHycroax7URq%E@;oAkgY~kY_*>?Ip3%sPk z8*kx#(ZTyM@XBB>1XdB->Nei1R(#ohknl0R@b9NzJ_bA49v2ckz9$>+q=lD+u;86^ z@KV5AEnv_E@8=F47vDl!Czq%c0<%<;Yba9+R@ju|j57q+^X<33j@1-)YlQ zGiIIPxbHosDwzH{uy>B6^e8c>JLywNF?41PzlBFegV|` zpjJTf>^APN$U%;|-^vFqkE+0Ll zd<<3w#md2X@p1fA;r96FKTe|}jCzw@uVa_y?M>uz4_fgN z#fvppJ7;07c~aOAFvxgPxY~Bn+{U?c7~ab-uR+Kzs}nKu$_L|&fY+rjyl#n(iLjT> zsSO(}T+#qEZ9VI{xpQo$2Fz7+7tK#!eO+C>ABu%@=gq0T+N2dyLOW)xeTH#XDXkMq zC%R53$^bL$$Ty(F#Y+%log8y7t6g+;BcqEzUspGOF(2nFSu*$1#w94~{`W5>w2RI^ z$2vl`RRhv{W>NJU;wKmo$MnPU`D&dszdcPXFaqKjKflp{3jH+-_rNfsTBLz3$N0nY z2_99b=z07`RLkEOK;xKySbm7dqKu^Rhp91S@+^TOs^vyb6XyiN?uV)M|Fq>c)Cfjm zR%lVxeu|)Fyvgt^KO$&V>yQwe+|i(`D4UdzSLhwr}=Ze zQuD$!pY(V}07>)Z-j#;e__I8=Zv*=ayt_jDJH1bb_>}i-h@a}cYYK>3u)MpXc#R$N(Sf zHd*_CbokEpc-CUTPxdYf@s(alyv{$t zm%%V_PRS;o?_?9_lx*U8PBwAfs!cr4$tKPz*%b3wc?Ohi-D+UV@Tp4HH;Sp%58x@B7HF{KT2FI0uL24?Z!s{?g(5jXWDtoRiBlRRqf) zo>o?5c!JQqYQ>QOk*{>@=Q#ZP9R5a!-|FxmcKA;@{Ffa5+YbM44*x5M&tps25W_#p z;iou!t;1jC@GBjDlf&~2Um^Op-{HUD@Xt7WpTqye;rksP4RoLAUzx+ta`*)fzs%v+ zIQ$NW|ER-1;_zQ``2XYZuR8p%9G+(#2{Aqs9DbI=&v*C_I6Tkl5hC904*#ITKjH9d zn#l|d$P{Jm;`c47t)FU5-mP4>cFFS9W=cxk@iCCCUAJbdpNy?Tm3 zOfOxxqBWQewZs>;cC<9Eba6v7pn_pdoP@y_+gf`X$plz&X=k$8> zAn=q|7Lqu&3wm*7M{7INpgnNY*xb>vs&ykK{4(vW9UV>z8C%ZFB1#uYS(&^+Tzk?ne`oD#g1F} zz16iTN3-TO=dzGlSqZP6ajC1fCvnAYVe1XeEgJ{sCFBZv5uf^H|IMmbc?uHQCw6=L|3vSDUEL@tj z^5Y*iQW1xdn$ZkWH4rihq+ZMbQ*n)32>tkKUk!`Z`f4T~E>&)Dq!>2du(u|o%QfSH z+4z!cLyX#iDE`hCBV%nx5EFY7f-%dvIR)<*sMe$~9VoK_ zr6J^k>0w_iG|L(?jw zDCR7~g`H|$i89fX#7tpRx(zV3;vCEpANv z0$D}-jV7Him{Uz23k6j=A@KF&F%hED=@yetx04ws~F?<+q!?WQc4V z`JHC3+U6JO-g2rhbn;LoIqQ&ekXYQQX}~{bS~iN;rO!{C)Z!lj!}P_bmAb z@IxKL332Keriyvxn| zS#I9X)#m+NW8M!k;cUt+GwydMVkEu96kIA}mPOJStx zpp4ts;XJsvkS23*6r8a z_UQ}RCjDdfrkwv{BC08zLqJ-df7F`mv2+55Q$RN*7>{YEmB@*qJ8juLu$tee5#Z9V zY(bP(Yj#`JIm~Y5_p@?E%@@cOGrwn-+XLwm{&5M_qsuNL&F}2CL4PBcz3$m&x3xON z*#+#@OHK*D^Ojx0G|+RrJ=L0JrzW>!p23;RR`q(BJx?Q{I;(#iL~ZfSmcgV~`^Q45 z!eRQoIlR&9sk2*3e=NIgxWgHeF-7Fmj?VUJQ$zXqj|>j@2*yzhKG4>+o!-v+UJ=ZQ$21T;RN)Fw;@<@R z9w;HfLz5ze_ag8r5HaF0T!M!tUkL9F@XtdD2_Bk`A-w-8)@x9Rmw*yHG_gW>Pr}b3 zFcT6yG}S_QJH`g-M|r_}7|(nk65r>+WQ*^9$k^%kAn+u#Lg zqV4a;a>za7$bCGA+`l<;2Xe?oU~c>SS@4_#6rvre#F2Y42i|)fxi9CCYjWhC2cON~ zTO7IXfX|j+?sMc`2cIn;{JkUhA35Y+cI4j3A@_Snj(j$M$D`o0)0qWfHaXsTXUlP2 zW43g8zauv~2i{gkZd?wz2OPOl@cf>IBp*EO$W6|H_X9_c>nXFvmj#0z-&r~2co&;3 zH#>*iyB)cj9CFtXsvW?z2cA!_;G_KK z0-yEq&VrFG_dFU>ymvxK{AHKSUsRhsgYy+8R4Keis%C+W>61t6T*B1Py2HsO~u7R5goonc(7@qYd*QD9RHF#`?29)qHoTiBF zi3rvtH5#5iN3h0dMTjr<@6*%vL%lmf_QTYD4>Z#DqrF2R`!U`>h4|s#zlHcBb@m*M zn7tx6dvCBQESS$DSe0_F;dT5*c{2>J!*7?WOfQ$$g#z(OTq9^xwsXJ3_HKIeBMay+ zVNF*((t}A-0mU^xJX1%AeL1e-7b1VX!*gvvi79s$^4liIey79lb@)0k-cv0^UQJN3Qj`THtRykDX0IZV!Cf_^X&8G2i7^V+j~D}chE;}w{V9FHkzv&k zxHdGi?G~C$&iZJW7!KwV14w%|dZh>lW3XXh88os(AcLW{nT#OXX8y?bVkDcIyoYVA znhxa5BvSwr*Gyzi@ydj?8bzmBFnfM|{gWt9BRqVF>ET2%(`B7=v) zq$KUp_?<`{^FJ(0qnQ7iLLKu`@XCv#;$)p0tv2&obIiO}jpxD0i`JTXtvWNWHP_5* zrOmw7JTtFVZ|1e;!x7z~VpHKppjEibjrn=Te3CJrY~q6kfQnDj#OEC*J_z)9;+2~C zl$rQcn)o1cDn93%_>@5SEzffW*BMw-8F=%#=B={MTAAV^JmPH({qNcz<3(<>3X&`{ zIYH?|OJ}Mhu=IytQ1Ls&=dAD~ylkIS2?-wC(>C6C^tPUa8Sxkv!Nat72#+#s za|sC^rq4roF9MI{AMqG2!E47e<168N9?y0f3f@|n+u{2;@Y-NTJUse%AH=hb*AG71 znB&8a+)y}@G>4VKp#Bf$S;99mhujYwxpQ*J{eO-e`vuwj^s+iAObd^N8;@k|vlPH5d@I~r=kmPjU529`dX~69u4ZIzM z>GaN2(KAIzC8mXUV^OI-A+z+xWIBTTL7sWNs9L4z;UTySB+uLh(xgtNJlK0LZvGf< zZUNb8ZUMRcWIXm-X2_ADh{1u3zB^Cf1cKW?a05sRH-PXyJ#EJPRdx8Q>i&<9*TmD_ zjr!b5eWqvf#$?JX<=K@L>ReVGTe-)ir#FtAaQd4}c+*Dht+)9%ZKNL8cXE{7+G1}1 zDEgzff4KK@WV!w0h>i!suToU!)Lb`_ly3deEx}DB_F1!4hikURoEt>mz88dP8}mz8 za^&sOihMj&AL$ZM%WC<2$KI|*=)TagXX_!L7)nyRz6+P~bU)a!AFS%L9v>n+@)^US zAYr_LV{c)5cPwt;y&$YVm-_y(^bd&pE5ms1*xbN-L5R1)hZyBQ@!?GF2?_hhR#`yV z_FFPUtY;=eWjhlST~wbKyJ{%P(;x1~3*xTpzSYK_Z<1$Z?l63(;s<#jgDyn81HwQj zf6(E-?C{?PPycsAjllbV6}k}JpArT-`QJJGAHdUn8Po{mhY?@`9(OR3F+}(7Jt1?9 zJlokk6LXOxf3?H682Kh8Kf>GS*mpZT&&;F|+rK|;)^}D zwS*Xc4uR;#gEe^9j&3klp4&HmKrY**B6QB-5-#d;#9=&O07}VXe@VL|OLH0Q;s}>> zok?)yWcV7Cf!B~o(CM=o;X#+%x+ulE1*KMvvDsdm0U*anchnJL878Db?X*U~s=X={ z55|kK-Cz<571pk;TjShfVv^Bpli*9S9<}T6eI_&uHi@Vm4ElBxyi%4*ykBG@blxw* zQnloK{Y@q&d0vwC_@GnNF}A|~Rbq-ht1W?s>JsvBugu||J zEu=YclsV+zLmp#Y%0F~o`K{9at&Ig)NpELLwLrPEwX1V#t}L#v`4(F@Qx9-&XYT=) zeA|*`L%8BfkD|!k;>J_UQs>bDxIwlYVC8$M^J7+fjO}2k#ql+Cwax%rxisZZUC4;n z`Ij^f!|Wv#H4n_c_PE50V3;R4F2QeviuK$TP%L((b@Kr{GcOAX-lZ_G@qP@3?ukdY zg0~LOHr|ckDJLX&AAx}_$MF`{vqB(oPk6TRy1_$}GvO~=IP{lgmH3+v_ck8S zmA)4CLK2TC%x%1dz)M1iczn--R|+}&`|r0H0dE2?B=MNw;H|dOh3zcClQx9p7tZ&! z37C;1%k#JG@ZDp@ca)K1zF6jj?^WQ{5WtXx?!zhp78OLGDpy)5-#k2!N zKuD}UdSpl*&jN4DeGBpUlvu(}9$6~O@!!0D^>kN-8@2T`R>5uyxnU6r2T; z!3`kGx?+<#nlhp9SlclF7Ly^NTTF)Myv0O%{1}-41^0E@{a=hDugd7#RxTZedt3@t zuRqs4F8Z#Gf%l23{=T|@WY9F;rNNO6+m~9{(R|RfM&597q;}PB<%SpIqeiB?mR0sm zE4gk-$sU{Rrus$|`pdgnhNgK>3d16I*0?vbWWU|zx42>DKj9Logj;C}PBp5#JluO} z+*?*oTDPned~a;%c9j#y^@vjeMqAD)XR6A5HorI?SECvjSHt})66T!;bsDNvx+PMX zceF*_#-hiM4r~c-V@c+?jitckAw8CsFa`+y8T%-Nvzrfa2(%>bAQ!W2qa^TfL8^+J|7x7SR8T`&a^W zmjD0z?q3Oq|8)1QObE^Ou(ss;TkV6e_6&$;X@%eSxq&5~c$QY!zSOZVckIg@`|})o zEGDoh+gVzi(_&rR2*t4~bZvcN^@*;jPvo(@!6)*Ipy-}$9gbaH4_%1%8-;;R{thV0 z*FkYC>p|#3w0~F_=;Z$nit-Jr6J02K2nIh ztTUt;d7gty5gnf*PuAIKeuUR*?AgxbSQ6WHLUezJvFDdN0w}WAWwzpry@SSnt>VXe z++!p}_uq8*V-EjQ|xY zWDBc0BghW~gw*IlS_OP6$K00-gWB-i@R*GSz1nA(vIm; zZ!lN>aZC^>O2nKS&~G4rH)}Xb@$0a=)B`34ZS3#`(nJ) zg=Mxq7RSCS-BlR98amx!$(S0G<9EQjR47-1u{n-Q5Rd(3j^*)N<5=88>hIR>5*UDE znZdhUlz$kDQ~cC`=ciRtgCFX1ba_O71TP75;;Hxmk2ncL1|nVpZQ3^K^~M~A%74Uz zko3QiI{532Jil@O&KKY)T;Kpg#p5dK2Cu}zErEH-WhTDBQ|SfwRg{M(c=Qri1pfTr z_PzzauByy;pGO`|`Z!HWNogBS&Phv}wB@8N5EQRTPIKtHAt}nE+O%ny)26h?wrE;w zr_hR3L5oyGKt*AkqKJ*OGxQFff-s6BcW$CGR$<2a_!$%&8ho7*9p?XEdwqMay>dbk zxidP~uU%RDTi>_->#_G&BR1b8Z5ebf+xpF)Xg-&~M9~-|pC=gXz1ibwP zq{d5MP^w?uf--3?{FiuiwZOYxSWUmr1%z(-+}FK;*xN3spp0*lJDz2*gC zL8f2$!a^T2FbJw}%|@U=Y`-}uAoO2w_5T0CGuHmN#!C5a3bF4%nhj@;RaK#(sYBQ- zIO@=q!Z9v?^NZm~`{3AL5t5(mWe70wnt>NX81Wca@Ypvo@$Le@5Kf4Cq>XSUUb~S$ z=1cHCh-(w?6!qqi; zt%bKAJbq3+61)u--YMY4p~d^b-%P=iKDm^UeQrMELW0M+Y-auOyc6OO?;JS6y9avs z@738n0I*(!1n-2UcL@YJQGzdZ#I-YKx>ZOw1v%5@7o?>7jD>eU@K!@EB-!Ngkx zyf~DI$1hI7d&$Bp#egl#DF_c^$uaF4P%$IQCv24dinIpWz(W#sS_Q?=5y-!8vczjvK&t1oZ}*oKL1jH7)JNQ8pccqij07^J}1HoL|%7o>$Y^w(9bB0Qra6r~_kkfI0^TpFpNu9a#fZ z>j!upa;_oKOmCtrQ@3NY&QNN=MVk5*g_1_K1r>n7Y2D$O89j@u|`DxC~0DrF2qItHi zA@r=)1mrWF_XPL`hjUJRyz`tR0e+SvYsB63>ztoxxm&(^higXs_(^X~xT|05TpWH>VD z^QHj5!08C^^Q?1g<~uiNxtrb`=XTAz^?#1)zp{Q@KJGlO<*rSKy-A<`d~QwLuMAxM z`P`aDt3Kvgy!pk$`r_!YPZ4$cq{(0CGq`#+=hi%p=asKKdy2F@{#ZZ11mbtoX^a1r z)@M(Swnnu{4X)X~@!Xp6{NU2W_){!?mc_r>;xD)O4Hn;L@gK7IPh0#Ei~ownKV$JP zTD;or$0*Nad|L{!eDxN8iN$wXe6PjtwfNgC{yvL;*y8`M#sA3S?Q?2WA6gfH`RD#q zLgdf4_>9Hd=hVE*k{`7A&szL3i~qXCf6wBFEk0Tzxpkkb@kHHG}HU|!3sjZbgvvGkq zYDeT?9PY!5$>I3#opEDCq?C!N{YuOb%Vf5Gc)Egjdo+ z#CVwz#HutaJ{Y8Gj1g%P_9sU8N@k6Z2$k3)kINyJaS#q-su#zrPUIM2nw3L!WC4@8 zLWV_?*oDIF6){?07Om)wj09OdSGuiWY4pxVs2{%$efzgpt)|I15Xi^bnh5i{oLuAH zaKoJLrRsDk})?035w0z)AFp{W{5&JB93hNP~#(;Hr`z1 zYviOBzdch=Kb0~U_$`?c_!^GDaVyxekh3(wr-F$VSbe7z<)z_-04%oiLSJbSoji$X zZrpx&IP3O}!ub4TcVfi3I#;_L4xV$v?k;`m(PuxNKKmkJ=<&ONJp23fr)fW~{aWqU zX@53-#7k+OUo4E*qun#=C9B`ZEcL-rTz8V&uV{@_H)|b zuKhmk@6!Gr?eEk6e(m3+{R7&E_vdqUFnK`L6Dmj5)6M_&=juGp`*4@zJVE~xj`Jk_ zPhziI`k%rd`WSSH(#J%AQu=9z!oO69N$U#K6eL^)N}rJ$JxX9 zYxMoQQs2LfzJJT~xjS!y(rew149%XuBbh&gi5)3+UeqKay-}I>-C_oM?S0|>%K%^K z+#Lq%zM8qGmJw`x#u%G!nF@0H;3(pP2lE*5{hye^0Pe4gbuf<=-~07>B?$Xq9us54 zo@j>9>s+rLrHVX-z_B<6f^=&O=g!_)&4_4xniY=gf9{Pg_daD_Sw(&26;_cBcwwn@ zY70w^uie55W@ltnjWd+N{v0igV}F*8uEnoO^e;xa-|~%WA7o?PIP+um6_XixPR&RZ z7M}g!QGiAqW@8}8XI9~;W|uFZp^X#PgO0ggI!Objs=|}_bo7m%6qqkw+VPs zUUa)WyuY*XvM9JbV-Tsd=s%;crCvDKincQ$=85zYoSDD9&@;;`ded-W>V0^WbT6^= zK01otYD@3VQS|=O();u%dUsoT-1C~YLm`M2+2`*3%_w;PYT-RRir&kX-j_#7cRIqE z2Y8AGae-Uxk>rni1e$u!gD-S{ue9`D97T_7oJ_p@D0+8UdbIx*O811N$GyM{)$_kt zdbA%G!h6Zmn*u$)S3*)R_PIOUW1tY;|3bJ~UfQV(>2+CpbHNuX$BmXA?c9a%?zi;P zqv-vUrMGw#y>k__x4fnR$F@ON7371>1`Y(-H%y%+eX1V zruD>9y90V`mxWkHx~D9>y`$jK-e}g#`$y5k1ipaYhey#n-_rZ&D0(X`J)Xx@=y};> z>3te{h3?z?Expf;qW4*?C-wIr^uEFh&?NPDRO_*yK-vL*kGgXIh~D2L91uAX{X2Nm zYA(?9@d|r1n}x-Vdn3GS;BXsMKY(Qeo=3CMIXIs`xS9kHLu&!OgVS(657HJAJ$~L6 zJa-3^fg4k)M&s{=7b0vyQoa(YX;CdN<&7&J!>)rhZ?&}iY|d3xFR6=A>cqx4vEtCg5@&)p zQFUy2RdM+gPDtf!P@Kf0dT)_vaikJ#G+I;~orH_>vdQDdDy%=B$HRIOdOgqM$pSPK zXpQ);jeZ^ve-Amg&ZI);??{`&{!9oX+i4wvO+g5~Ness+;-kd#c(w%iDm4bmAXk69 z^KmVA`3cSg0e-UcSb&c?PY3vk&d)XPrZ>eY(TxV5Zk`V`Rr7B7&T`JzJRkB97seR$ z|Ks^P3sE1ek~%ofU0SZ|ht(cZ=sf0z$;Av3Rb{5u$vt#b0glTP*&1i@)9C4_o{b7SA&) zg_u6iwiF^CGJZ(Ov(GFW0ZC9+-cEy?6 zuE>QYP> zew+~BH_~i4_K%z4NZczl4xjH4b?Ep`rs3Fqk}e3}=PaC%;Jq0ECf*U?4Iqqo?8gfp zOz8o<$HDX677{#|)B||?&?d5tBp&l6cw2F8=8tKzpD84Gn-O53wh%JpwU~l;hwidegL?{)u)z0lhs;NE0#WW z+MzdqhZsMF&Kx*C&oMZb4R{{KFc6gtV2ygp-qIFw!jk}*GPq%S4R`G10mz`vCoxA_%!F+w(N#238 zcFGf>#6FxJv=4iM?#s`|c{q&6-CO0%q2~S~oHWyBojBBVv?w!HotyK~JnAnIVtOw( z;M5!ATq33OwLVJRvv8W!c{)uvPp9lXMVV-$vyrmodm;@bgLNCnC2%}b%0JaePUeY^ zdNNPb(F6JVl+!TjL?r3%)5<-1iRqq`bD%$hy!U3E;W6RJa4giBk6w-Qf3E%@&i@IX zpp-hYG#lE8Q-Z>iGO@-f^H)Ku1@10tZcIH4%o9tXL7y&vblJ*}=!#fg@@|&d-sIq+=lDOU`az{ur8B79+?w5Ii{g+pseAY1GnX8GGLx6a$xk)QPDNAl&V&g>)k3901H8-Y}lNvYaETJ6r9CkCV3kKyGIQu^}1*yP^a zZTUH=$exeok0|Uf4Bb~!`c!#;Nkh?KDbjUy9~~-fC?6aH-br@ru;_4^it+WKjV0rs z8q@HJ6U{GPpGf>B^7E(Dq2$vg(QlRM`2RZOK5?NLyNCF&=8jfpDt8t)jLj5f!Z?#D zIvAhMbezQaQzZ@6gSYJL+!=W;l)PteN51^c-D^9u_pA*k?|D}!@ll-CRNN36C~b%j zhUUK)oHHZQf4+L+h)|cw9WQP8_Q05iF@v2u?|ElG^_ z%M!w!o|np98pBgKFBQ#n_VWa!d8sk#UEq7*o*xxEUWxa~EoG=i&e}SdPo;3GmT{U^ zJ@zDaPtpn>W(u*T2l8{{xg+1qA8P(kUozX7PsA%T=k$H4wRG^RzCDoL(bt{LJ&f>F z)uomB$oWqF3xl7@hKI)%eZKW4gSm&fYcck(JnAGXbLF|cyFv|P2h-TEc+6mV?y+4r z?5=E1kl#xl3D@wp8XqyTh}>gDtzlvyLKWeax9vdSdVCP^2>Vg&`;TZ$qKv^F!C~ zesZWX8-CBzeRs5mzxn0eceIv%LsBVLsYH_hI24NilX}K@KT;{kn{PZ^i9CHF?=+VW z%uQyot8UX&=?|RqS>=PE>Gjxy z7~MRBq&MgWanIqP-0WHK_qD{5ml#--kFn%tkAw1ZOCC&(=Su}c?6KzwmfY+i5r3j3 z=dZm_Jj*?Z@BR>rMg%?9pxo@i68~&VZm;vl+4cgad`zk_D1x3}P;T}FiH|*94Sn`< zXnI@VJp}Ca_{2SigZdZwB$1_d7UM% zQ~6owY1MgGyolgbtziD^mHzXd76vp7ir_0Qs6X3~5)T7P21T6nRezAx%X;S6e!`Hm zU&%fxG1rmeei{-e?S=c zsjdBm0&mpj!cy4O-4`_zIj1^={2CQhc4WU-PFGU+;WO^D7jO z=U+Z#jQyH1ux1?ig`>n)ZMe3F!);qJ5UiG!Vz5`n+GU{KJ#j3vwWo)NkLeg&)DiJ| zta$`r9GQ_ zwqoG|SAVIIbiGsdwrjk4LLK9paU9uldfArlwVM`i?R6G)Z@9E)d+Yj^_3O7ft?Sov zm+gR3dK$F<=$`O43R5X;tT>j|aRy+vHw>id1aL{~BR*S$M(_%irgQ02{ z3m>?~(H(E9ZgR)5%HGK59ATH>52zXwT={O4VL**zQ`ODxc!%t*T-NG1afYY09vWzl zg;%$@<1ySbIYItXw+$|9(|Z}C;pVV+H5#tT@XIdJV_!&TA;X(BF63;RxCb(+dbvIa z4tndsbMNEr^gG-=?aG?nv%$+c-SNIM{2=^@^2;43PakV^cy3Y|*7DTSzXD^A^fAE4 z-}x{m2QdG{gQ`=8a&4s#{XIII`6*kd_1@;@GyHa4Zz#X2C)AtLgU@z{^~7I8;vuR^ zXCL`>j`KWu#OJRyF&U-^fB~NTLY?+SeH6O1mry(MUZ6s_7r8Nn}FkbIKIC5#e z=;jSEUu!!~&@5?7bxo(Q&20+i+kfc;QOwsrAW*v?pdt8!%?#{K;}!D8Ll@xMq_Adc z;8QQ6d0US%(s^)fd(Nbnf{vXo`;$VFF5f?X5jAT;3ZE~;XMDb^bmY-g1@KzI3kEK| z>(!PX-|Kl)&?Irt#01i9Lb_}dm~IK2q|3J0EXO;w44xvvyB3^TjzvZ}7%q74$F+&K z6MO$RGRjf_DhlCf;4(YvF_h?_LC$cwNA&LKw@-FG|7t3a(AON5E50 zNbtUl028mz$R92}ydUA(#5)PT4o*n$P9ea=+i&3Ui&gR`eeq%e0C+;K;S1is!8!+(r#VvT8XJz8u4u&!z!P{!#oiy;+rU>4x79Qti@jFFG zus>|!odRALl=%EjhZ8)mw_$X-zu!WJ_>2ol{_eH#n(^|+p+r1>@eAG~7Tzv2T(yu3 zN&X(T@VbB}??(-k1@EMVcQ^0~-H%^bdWWEwkVN52IZj*Y_90#TSLI+nCEW@{fT~w7 zJjc*%qXlm~F3jg(zflhMWdv`og-5|6$c3m!s<-g&1|G|sf~$iQyfzDO5d^0p7ZSV{ z3-1u{@L%E8!xud6L2Z_|3G=&kcT+(^tmrBW?;!(^zb%5t`FF%ixzU^(fwxCr)1!>8 z4|=HD9K%S(cn~?>Aw(S#eaQp)OQ6>d*NAI$n^n3j7w-k|Ji2MD<9x=5D0pn+OuZ)% zncuNOqQ_6yYu9erJeP+>g1qx0N3+4HneEg(^LddN3M6@ZU(Z4Bc-zs){u}!0mp}8R z^XiK;(czaD%o*fZa#Qm3v8VEfQl-Zko;v!z z!{aiOl=b3de{$zl)#K{VJ{eo`jn$uPtsFdnoZrzpaiFMS9Bfh?UGLs`b3VeccUS-% zjHZVU61U`V>UdH8&jvVFA5Oh6LxxXBY4xjB5-xs?8vR=p(#vsyzN2{Bu>w zSp&|2W|hJ#mAv%u@n=t8&vKtBpHAHuz58{aeim{^_aB~|q4hR;Xo^a!F;jeqXyXF+ zpzc-NgHpUHe7?&+@i zW@6@#yYCDvg3jUJ>^a>$2Jeir@$)?jWo~tCxGL?`(TZgU^N++sP07s0e)TrDuIio9 z_on{Z4YOepFVA)MR&9u-Qpc5Se$~cB{kP^*@ru*Y36oBQF(aTXSG6$?xtnIul63V) z@{c%m{Y`P_rAR!jV!Q8b?C7|q;}-8l>WEi+PrfxCNmOlJef{2iv$Hqf=iHOu8840( zFX5exXNpi$u1%Ep$E4Vi{{Hg5v5P`)WS%17kHC7jssEmNVf1z~w$NUm!eqxq> zOzF3K`s~U06v1d@5Wm6~;wpmCx}bcL!kg`B`8CU+2u2%&`jb^ZiuK7l3`5TPTm|P6 zM<;!Xpr;;;&z`$a5!hIQa()r{L>pvKK2@dXhw+QYC)y-^8N;V5{bimCzi51-O){v@ z)q>`C^|`(>u4tnS>end!CQpk`n@_Y+2KAGce$rRQRRnvN2lZ!I^7Aa7J$;`dI9aB} zXI1}wsm1%xzT3a=hMaHR<8Tw57hm20pZAw{iZ;YP_(FWz-VaAPuX*n2?V9IYOFn&n z4PJ;ke-KSmYiodF^KoI0<}sTA$hi3v@!A=Rw3s90WIfs1)hKN zoEV15T*-DNpYD7^>vJ5PHa*$l#vdcYX(cNTif01)G7novU%ML*KS|y20;USdi&N*F2C^Fg+1@=*s@72 zj`4?I3t52D-RoL+EW)}BD7&dFUhf3}SIN^`Hg8_6lJ(76japqIBu z@@X?5Y-2Qlp)%Y0T>GXPv+v#R=vviVZK?$avRuou#If>QHf`F{?Eq`xwPKqy%ycRo zb~((NcXe=010TZO`gYepA<2%Ozu2&Cd(T!~SdaBJT>!mKV6nTIYXK*oFB1gqyYftIa+4jP|mb z2Ww9TnYIgdxbkY)^EMeNWZbD!rFv zv)levBcHq<)u?phg`3^`QGJywCtu~b;lwF>yWZOm;cP#+#~?1%TA+pWOWgZWy~fv@ zi*TmHd{uYh&ud!Cvn|-{1WYvPZokzC2m;MgK%%1Ph9oF3%mCru zs~rdow3eRv%YWYk%HEsrhpKm5-gzrnzw#qP`SJ%s&1RsGAgI0YTI2mU7WVkd=+Kp}Fz;0Jv0b4&N&w!9%kU!22!m z_}&n&7*6ok;hMkU3{wP#-#bErhu1ZLHx@tYOqY1fm*DNfwTZVH4AT`7ygme&<*fxC zafnw2CwL#lwTVaD3;T;gf_Do7OuX5^V;aO`dn9-d;M&B?q0!1COi1uPhX51rUIPzR z>EV49*Ct*T1HNb)Jrcaf5Mts@L#41CWd2w`lE0^MZQ?x)yk!UzLUt8>8-Go_g#eNJ z!7n$#<8Oh9R|-K&A-I1ef2YBkc&iP(NstNN7=W30O%PmB0Ivv2Cf;@fk6(I%$8}LA z-T?@Bzl5Z`whits=y}g9ltpizmF`VQSDq`=X12^q_g>&Z)g$JQw8+9c2qo(AzL_?& zZVQj+q_h)2li;nf@a_ee??=GHe}$KXFL<&)o7~fTfyd`g zNbc`3tGvGenAG14C<`9Mc|FEJgY&%I^97j( z9|4YmniO%0ta;&hm<=kluAv5Uzr97L+aRuUFo|QFwFqGPeAg?G9_^w+e6CxBflnTv zDISsMZw2G?-R8XVZuml!t1$vT$TCELnRJ0(tvgKMhWaA~fsp~PW2<}Z{Om=~7ID-X zeuR3TqN+VCL&E$`D#Ob*7k)Ko=BWFgq!_}-$KBC58o3$?b7~V zgKHCSJ9yqcA$fDwA;83>kub_%;aMyKqgs6dY+k+#X(NqKs}293XP=6qO?I)%;Fe z0=;%PK6m_`V!C|xm^Zii#Rcdlly{4Jss1uelKnd|8<7sUBK24F_&c$!+h6i~rnv@9 zjq_5k_IKiuvsF^w?*!NT=8qODOS!uiwfxWw@mR#^uXij*5YZNaW48c_%Eo4nBcZpI;k_)=k3N#7P5H=cZfJSeqE%9j*%xcI^ryMXZ^|Cxxs{ zbY?t`)rmjD>cr=Ux_d+Cots;etLQuD9c6tL{o%w_xwB6>bCwTAaFy5{tuG#2w<}a1 z8i>{x4Mr0$4B;9fzaAPcjy(0{;?Pr}#2q=wtGiy-sk>kxmc-l*%q%EYGYfvO>z>`= zpGHE?oJ$5_>KlPe;R*tv3voXA^q04JCGm>K|A6dUWu}5a%+KV8!M?43%TG>zzArPa=Q$i#1TZ!whr=?xrUFAJ1bLQ3N7adLaF3(0Y@x<*}%moS265ZWJF|eom-<;p2nC`$>F!iMHr>C>A z`Jr23n7VadCX!*<7|wY=^w;%%Gwa+&ja#$f%nNvf$}nGId?u7>SG~fb%t_1)sZV`V z%}t0WLYM>M;(i=ub+5jYjWzPBtJk?LnQ6yc{)kGO??QKPJn?bG>DeSeXv+Km^`Azq zL>q2A9L-D^3?Evobfm^Yhc3XqbDvPIrgdljM6v4kEHC`Up^J_#%O-Y?uOC0i`9V={ zeo!`Zp}POf6YDlo|I*;}#0PTZe>K#El<(~0J_BD@WpaDJp-glCc&vX*gn#=|I zDX4nTIWL+h$xU1wQtd`}?|1a`C3l}YAFzf!KN-R2MmJ`4@Ts@}Pen|{C~Fkn{?*XoMcHZJz8q&TP274&ho_)v4uBb_L-Y%J<8ak%2=GKdT?Yq3`wb{ z`-i(CxqEgYja_?lk4_7g6;J+0lbM!8W5(IQI+(EZ>UV$rSQt-Xed>Jt9iMWa?6H`E z_l102s`S<|w|4hV*$_SCzB!RYj5QYTWGML~-3D$`Z{j%I>tO!e7-ml6Du4Ivj^w&` zr*p~OXU<=D?}qHjY#4Xn{l?q0fA1}y`{iFXbzM~c^i^GZ|9;(e7~uZ=UB}1NqtVWZ zXCG}f+{o{`VrzCsF|74&f78{M-nE-Vp}k#OAbMOnfojCW)#YD)*KthKr!xN%SDdR7 zl>1+dROH;0pghQNE=n+jJzJkR_arEq(+(j- z{sCd&lRskd4}<6HM!N~;x_r%&pVV@W)pPF4vzGi<7C#iaR*PQ;p7A*@P~pVY zdUG@WEn42Cl_R4Go7z%{;-nQIo}5_#QgkN%lXb#aP-^w5SO8@&hGTu z?Hr=ouolP0>UGc1Q{f#w+j3hrukVp?cO0w}2X1m-(e>BT1fA}N`5F^ij43N`#i4N> zJ@4$$bbIt=C<14WcqydY!pY8fto3 zbAd@GJPB8pwIZg$sRX!GdnCR(EL5+x^w-lP?ual`Q?GDED#{)nSYyvXW+iw=wi_EK zrs4=tw>qH0(_?9U&n&=P70jxEt-Gzen-!~atVIGS+BjBLiM{zU>PAVF?Tz!A^!2rC z)oueSX-1XA;wxSaq!l` zf0KK*6X&@s(fpa@yQtUf&etnz!H_IoWb*9agj;c@CH=H(W8%DYFLTEUs~5ZNI`b80IDAA=>D18&F5m02c0HfxGIwl{{8)x#{tSBw zthGH<8CY8in^3z5X5H{Qagr^TYM>{FP-oNLr;E*L+IzDxIsfJ|Z(;)%c-9 z)jHM9x_rRPQXlhZa`0I{G4jYCL~5Nr(+y)FpY_6YtF*kHKJvxi2^x z<&@!Ot*4K2Y=R#~;Z(kW!`~{Vqv{JdDe{QVejR;eMd6_870x>P29Bx+6n+}R1qbo$ z{HSsuKS)yHsPY2mcJc`PBz@H5{qV!ctjeFOMf3$1c*N!Wrr*m3 zV6Jp8*ueYa{puCOPk`OjTN-BbZHc5&wuAllc%&rQzK$v{w3mQ-w~gktKxEy}j+96v ziY9k-AzIkNLTN!qN{t4zkdUpT*TRle7|~c3R?!Dvk0#VjBL@DTPS&u23a}|o)7xkGc8w2L%rei0gqIIbB#s$D7k z4mcC<0Qf?9D-dqtWeq%jSre0Z+u=;S=fU%PL5O;!9Gr=_A9!^LWB!OEcpt{KiT4l+ z_;!Q|NqIkr02A*p@L~uf9-1i+@3Xiz@g~Ct1XYg&?=uK7@g6bo*fvW39>KMVR|h<{ z=|Y0{Fak`x0RxY}DS~$j*Crm%Y^y?;kl;Oo02A+&fyZ(S9>Gk!w*YUQfWa5M-&%O5 zfyZ=Nf4KDUWbb6&bJ9b=o9AAtzk)XfiJJKInZKU`Z(#wv`4(Ob zc#=QXx8SX^@a960Er3TmqM5%s;59>!`6I62y~D!04T6P`3rTsoN3)5SHS)(kj^NpI zjJ^xOg#rd&@a#E8dw|FL%KS}(6TJJa{KbmgJ_A$~2_C;q&HNnzUK|?4tA-Q2|6}2; z0v_LKA?lI7X5k$+${UAV@VL$&|GoC=3E*{s7ZSYZExacTyabd5ZyX9_;??0n%n6v* zBRd9qW_eEmZxO;--dZ@pn{DCUJ_=r)g;$4%Sny^Vc#AB&QuK`uLoOucU1;IufOiFy zn7=wW$zRsOdkA=&1PngJiq>0rPXMnO65`dv3En=9C-G`a-RBA_ideTK+R%9|dJCW@ zd8b_TKBe`T4yg%xd(@TthkA5}podpGC!&X-H(wa7L)J`_{PWQ3!aZrk^(Ao3Lky1h z7I+>l!-N3Na}bjJ**5>uv(RQ0&_myVHh*u60ng@tfpJ=1qqabenWVWvV_H0!@ z>^rHd6QOw1@pLcuH$It-E4vyN2PMASrEH=ee+T%g4Zi%GwXx&dj!w^vU0Qq>)*7d# z&J5iK`&XB98|@+O$7p}6!QQ!bnR{}+wSu-w*JhPFI$qCaE6Ow}ZP!}o&K2O^&A>SU z%h{#H8Ls{>Q`VGenNQ^72mU2ryN9WSGN=0^nfgr8aNL2V>}pubuD$`5vScPS91lkk ziv7KpVt?y=YrAyqJf+E>!=A}C;IwhNVfmwHXF>_u zeEoD>>z2ENcu}USe;m@eI5Q>{Qx;#>KJKm{_Yr9`*Q?531!DAdMT{hiGFSAEn#aV8 zx!}6@bnkcjzLWiC>0`qaBA5MU@6W@hOTxG2@I}L^5cBgN8mmM*AMq) zxNpLJ5AIpGpTqqQj`PbW!X@CiPhbYF6OQwyd*L`Q`tr@ao434cv(wVPcujlD;*K>P zZI>BLXS-t3Ei2M(%RE`j<*OF0>Cm#yw)Ev4i&tH#r0L}g*R(HP29=I^(=Ux6RV>|sz|9GH*p_aX(a)RLE~ZAk%K7Ey6K%Lbc}(S}&QoE}#V6WygZli^@`*Ovpxo_9hz4!8LAm+m$@;6Z+<`$QXU@Q&4c=N#pr7E(QLQ-8M4;EFa|lM2~rSz~;w zTH&}Sx&Lgt{osXK&fgR6C$Jj65XjyB%i z0sb84Ce61i`80I~67|_8RN(!QGo0M=oa=Cnj}Y-WcE%vL{%f35ntvz4DlpCP1PLQ(4#I+wSv0bsW_ zr>GAxraA@Rp@gZf~%1l^+i9f{aWqUX@9o%Q`%Se6Z+~ofq#h(Z`M9;y~10hebx){Sx)+^ zw10*6S#E}RX@9-;v)bRJ{nuu@RBu+Hi6Oq3N~siR7%dIe9$H~;%W4Ix2GI&r6A?^% zp-R+0m{qN}QekWcM?_XLGW^hOY&?yIuz=?_X*(Pzry2)h2U{-IsEsY zgRv0sITjMUpICS&0VeGl+jzly*}{uMAY~+`T+6vt!q-ACCy8o2vS&fTEXQf2dkWzx zxOzBAm*-xw9P{8v2O;476{3tTW9f1Kk`GXzN%Z7gET%)6i64VK>dO5idfZDLx4_H# zXQ4OW(j!ZKsCx7a^iCJKHb=IDEC-6F$_hM>o8@^J?ZUTyV%+%`g_wUKR+cp{>#Fw<{@ z1cOdsbMx@#rvCn+9z-(S5)E%z8`%;~BqMPh)fSI{gJ73Ol0v*L8BQirajS+0)(j2x zry>a1G%E(9Nwr;Atc(n#LLHGo4QLj^bY)_TD-yyj;bb@sj%;O4z_bpUkdYCQYa)?r zHGW-Wu$RI24@ZV0p`qcyqzkn;Oa#+95KFRB96HTZFe?TVk$5W6n&CvBOSd*MFtkl7 zW_@%Z5|<)^hXAW0Bgxj0STr6^Mu!HOM55P4;@hG<5y3=6GABA2jwe@2(Nplch%||g z7>c<}HpF_v$q1`WaPlX@lAQQRcsSNN81C*DsY8j@LEXp*j-Y{%K9rDV zvwOhm#JWh51!@lu_Vzoy0x_-IB2IO#4=1ke80wKaXBbW3ibEK*Ya`)asbInz2GQHD zrTkigPod1?+A{I{e^g$$vm0Z>jt?Q3OVye40 zTs>q>aPHi;DD&LbP`6}>GaGgl-_Y98=JWY5#W~KWDpd+ns%VPD7c{6K0+p(i*y=kYs_O1ULgG8OZH{#Ip`K8h&d!#O z70sP%TGy^`U)$Q$a#TcTl;f#7K7^hScGxD8sKnt!cuPc8_eQ#hw{&ifhX(+}BmGB5 zP!Kys)7q8Q;bbx%?H*1>AP^Hd@{tmpwnPUv4>|E^F-`?p|8_m)tHYxkfJ?<49=#Uu zeYj>ze4!eFPgjD=r;5}rftAQ-BNIxI*@7nD|rGTYz`FafQl{!g^sBjq(+wDg)^Q zLZ8A1)TwFsNvbjpE>_FZ;K`o!lhvgbekK@S>4Ez^@DSi8(5=BW6E(RV@M#E7)A03x zix6h}5WfpBep2Uz?*woT;8KlOp$j*44@diZ6PvatHZ^y&Zo+g^)iV_DjSf{wm#Y%= zrtSre_2K#j-J2X-r{Iu=w2@7T?VE;^(f&;w#y#l&=yaWl9axkG5)~B~K*N~BuxxVK zz3{@m$VdvnAausoqO^ffw?I{3$gop)Hl$-fDA5bkqZ@T}I-mMl9lbb>y1rgVH>!$W z?|^PRY5*@eDn^EM9hf_Vx~>is;YheU+Bpyz=)tbS2C;-Q*4boawe?Udn$`xJR;^nR z4Aq1#xF8rB8i++PnFlXlT-{h(U0030-J*t?jSK37n}^~-%m=EfD%m$Y&>gI*8XW4} zj-{is7kh)jp+qv;lL%HtfM7&tVmKCyM-qvpYr?e)Yv<#?v4Q_f7D%{0ShczjwA=c_ zOwk|h?(7*F+#KB!Z0SHaB;n4s;r{+=lJ&%fmxhMoXppLv4S*AnaxfXJS`oUi#_3lz z+Y>eDS2daYRgLLaHFm#38tGRx(ZQbn;a*c(L#d!muV(t$)U=h~IFFm=o!TeH4t?ef<3ohut^)~{aO5o&K*v8ofj&d|vC zcH2SMTMfr|Z?J0UJr!Uaxo7NLcA+?Ft&<50y*wU{?@;XSs<3?YcW*zrbFcWL%gS~( z?Vs-7SF$(1t#B?dqYs`{vQO>3`H^UwD*yIBt8$wz?-8}H_Ay`EX!}?HEkEDicKccC z@RYn6M|_*ACPl9CAMstyaKWMJ1qSk8V=z-kQt|(z`Ij%Nxiez5PsEmE)>gH3^$Qvn zE?V5Uq^UX7(%Qy2+hNJ_DL+>(Um(pZ(U7kasjqzeG) za$z{jaD&ek7YuLlYnGEWOO!1amR!7zV_BPK-Egn{|Uoih7f(M%CoPc8=i* ze~qw(q`Q2ZXQ}T#Eqqb`!WYG8S_A@Fyp(S~f}#3qtZW7Dw5|%L7OkA*pX!_8o9Un9 zJKa~BSMHndqvTlUm5)v7_vfRx75k_8{D8{P0cdh4MuW3Z#c1Gq4Y$CbT%r{F?ZP}~ z_vOzA;PcaAq#(>51)Ovr;>b-p8>)f5khRZk4)-}|Lru&;%CUHv9DAzp)=1JF$v}t( z#V|^_`ACQ%Bxz9|amZe=Q`r1225`R&2ZzS|qb{6Lq9a~G!Qys89be(0YeNBLbZETs z>NK6y2f|l_?qP$3FZBk0F)r4T$tn+>pK=>#=q^TtEjH;4j=o5zXn~C#@n7Z-)i)2ldox)O#ChZUC3sn!(M(jTKuR|&}HIx59nk; zaY)>MFTYnUezP@ICVsDjuHEI53V8X|Vqlr_8dZ<{sOq7QvTDUG1KlbESpIVe+wE~T z=o%5n_Aq0C{C2tfZJjaY#@LK$XB2-s*1Xlxy+x_^@ju`CSH4Qj$k}St zob8R{>Lg0!F5d=MHN%EiR5N$Ou2(^9=45|^Khb@lc*y<}n-kfuLfw`99`<3>Nw~?% zMJ`*%;0gmx^cLUyAr*!6BS#SmnU9w#mo;I!+AzhYN0_1nxiB@mZt#<}Qv}4WO?aX7 z<5Xy=)L{`)KH3dZ3hivPwy37e4s9aMf@%=G1d@whid?;p(qwX6(M{75Pr9Em;BhEW zn*MnT5-!8Vv}js!^x4)nzYW+3uV5w~=hZ(yg+$le2{k>N$xdF1rnmcsVe8dD>p*v} zLBi*LoR0dZ&F?#)le!aZD!g3NnRL&B&US{!6YO$LCUhgI($3+8HgAK+9UDUva0Nb+E7{t|%Hs!^oA zW{~jn)C~1h8XRzMb34%i^>P}1lA_JPxIB#N|1bc2_W3F3!0f}6X(r@54FIPz16Kg% zn!QNlYe)>o@i&816MI|MjDRsUJEsFKlAEFIgz0xn>*~kU@^BM2la`0{>FV6kn%mg- zR6Vy&^?|9Z4^o}f=1yvJC!#iI2H|_E%^4vk`W~v`JH~xfncS?u61lG$kbmf8<#{8x z7kXLGvb-4m&`8g+kc4hV=w=Ch2chr8)LCoGUVo9A9GO{nI~>D}pmK z*COqh_coyv$O?lgnlm}KNZeg;x)<#W@v7wA%MeF8wmlu`y!kFgWH$Nk0G-KK zM(`N?ZUoFJ{Qi8Wveee#~dJ^Ig5J=MgOmU zpX+keNU8-7kM>I)Ie)y*l}Ljpr)fi+Cw2i}?$Q*hyWB8)+BDIIQX`;HMv@`neXg$= z06w*??^-ZdyJsz!_p$yV4W6V90bYu$3>WWH{Sp2=T)cZqcrpsd@=->@6Rh1xe;re` zp?Wd_H?7juncVJ9S&ws!`Dn*Ut>vWFaw2LiGPvGTmBm?(Ciw1?J7;9L^;Ghhnm1b& zzn~7xdVI>rl*fJZRK<$YwPgyb$-j&85d+2gvit+jZTi1wTwS_r!26XAu8iWCdtzB{*em>cR!stt7{J7;9(brd3#V;!3+C!TaaW5DCQ z8Vc{|l;C1oW64KT9i^e1gDo0qz0RwlTnI+Pwjeq|1$;aCS5Zd0BN@I%Ly^9M$nPR> zl|jPiPLa-gN2d&(O6tr(yW!=4nXgG#E}c&kX&j*|bof|wgH{@*BR_M8fv|DjJ1Y&K z%d}&^0}1RM@ea_j{was8Q9R(GyB&1WF%kbxcXS>H-DRNhI&Z%D=xZil(+}AFyycjU z$kaYA#nsDijm3|A>B#R9T<9J#!gO7TT;l}O{`Uj2`^zJs%cM~}4?4U4_JYo66tgr( z<_nEtb7%MPW>={=mPWC#c8T*SGoD;N*3*5(j;`iv6lYWPoHYu0uJ2Fw_Dg44gB~6o z){R4t3dRR5m`epao^ezNs9+e!+b{PSK>Q;0G5B}7aYb^l&VaoA^49>KF%jVRbvMlX zXQ-zE^GQ6%6?qQU%~JmeM4^TMr6Gl%hpFsM_`K!fxFYoj6NI0K=i_+LuHC}3yf!=& zxDE?{Cc-owIj%_Yc8zg)cv^wwxA6b#n+f`iW#OsU)4S9oxL(N~+RU;g2v=RN-LnO!?~K6(gx?%B7k zEeq5%J{dT#=;fkw7dPj>P;@v@SahhU=yzvM-}zS~AC9f;x~uEVv!>nl+d$EQFSky6 z8T_U^4V^gBc0<`KNAmZNKI*TTa&Z5YLqGa*>oYGMdO`(b%VT>B@VI14U*SmJ0X|;2 zt!zrep+`sd1aEt|`N+%iz-6DRJp4jITV>yaT`Jhu#kk70*uF+Qk~!Mm)Q6KB2bcMM z2X9gj9-dO54oq2kSM$`DKhSqy^Y117XnR-J!+pW7FL&*Gy>1y&KUuerIghrh5#~R- zYHC~E$X(6(ZT^>4Ft{_ek2%Ep3J$jVZdc7$mG2C+>>PP8rh*4z!L0{&?t48ZTx2;^ zQ(ySfTPZESg!;W7kBm7FUNVFgRBl>o&0pi)*h;X;))G+bWGVmLd*PYETk?11-Rl1f zA8++N{mipgOw@^CnlW#1R%jyucI?nwMEw?RyfpQ&W(nh=@yP9rpng~rc%Gc(6Ph#z z(6T_qRLxZ?NFN#vf?}>Xmp+)BM}MAD^XVgf4Sl4SGC?z?BFcwJbE%Khm_|G9YuwTw z-y@%>71wclMYgbY-0i!HRr-9h0i|l8G*b8Xql$77U8-5ByndgN&dV_E;$&I^RYVIe6*QuHpI>9(iJ?sbATV;AIbu#wW zyMd;EKm1~Jxi8X37yOonzo+qU==gsnJX^^-P} z`8=y^mZ3jG^%gyxP0UdwDm7|>&BRe6qYjlAAdDw25(i4k?@NG8A+y za}?{su;>Dv)Qx5*^@#8y%}?qPVbZO&GB9);zE-q)6cuZ5K)K-#O=pVub!h-nIL`36 z1|Y-7qT}s5lZG6~k1~7R&4{q+{snYhULwHk!qPW1t^*CpcA^|+P_dpK!e!HK0^Ng% zBOTkGj&$C9{|MxA!KVLt^9><0ldofh$;@vZ=+>vR63EN%^Avv*Gt=pflw){WX((t3kKQD;!|2e4n)Vnbj*3zprE|-#=UYWJN}v zwbce&F?ADwIh!F zFjI;nKkmc_5?ivi4mLD4W^ElTL7s4~budWDbG8otmo*H2NNUgd%R?jIVZmIu?gnh8 zU4}kt;d%1lbAZ{zjw@7OF+un|dGG{$Ecx0Mrkyqq zXMlN*3^S$R4+7>?Waxhjn9H2O`@on(w_MXt+(`~h0=D6g^TC*gKMqHaoo)i3Ll%Qw zI{Rb4MJ&y_XC8fq8PK*4f@iwXFUM0P@;*-Y&6=?GnYU=l`y12Vkml9E7{}UQH*fP2o^}0x;(EV!y*OySDs@Za{$kK%apGY>rA!=F{3gdiL76#w|zm$ zqYmuHCRiMNtZPaI9YRve{uUM|E_B?nV2dnxF1j>tiT;52*@QtS`)mA(#S40xSiI&* z5{aBkIxyox$ro;(M;|+x^XX#+t)dV6N;Q4#QN;oVV#-Onh4i6ph@J>$7ZFA#7t@DO zOX*ikfWZX?m%2e6y3v%_zpPMK8bDAk`uC#@rsTIl#CPEWXoV>M9Q(`nH|TK z6RdyA%eJCppLhV5O;-!L7Z67}1jUign=hHj9II)J=gs$G(3yPE4aH^RN88*ojki57 zzdJ2{FztUo zAiMsq2VFbj*#FE}rF`GRWsl2eKxg_VP_BCwA)DU|pj(DG^23BGj{Im#+se-;Xlt5# z(r%1zge+`m$okoxHytCdYfCGqS2dj<&SB3?RPq zb~@9P>?HSFc-qoF510$6;|kSRO%Oh9Y2Sj+1=Vqd)`2_XXR5yk;&Ouq|DU*F;%BRW z0sL7vu2B8P4HJK=94KRVb)555kAY}QI|GG($wYvEd8#sy{tQ(I_>hIaFb!Xt_RbpG z+OD$jT=1{4VA|S-(qLzBtk(Q#Yoq($7JREk&nfX94@}$I%ZO(i&{p;Zz}V@F{gLoq zz=r{IIw1TV!1%fJKLD^1Fx!Cmp8~!JVNREXX}TXz`eaw%t<95P%$!frfmM%-CC=qT$bX;~@IpwD&TUt-|3%8;KQIk4 z)k4-?&4DL3BX8%Znvog#p5r^9`UXl>lUg+Ohv?!oc! zTIw{L6LKT8_0C`72F%g7EJ*zLRsnvM$Rt~XpREsb(RS@TwE*}^c`Efs8U5z!4S1t6v13%u%2MbT-kJGAXwGvs>=yu?Xv!R0R5FE){`fu460O7E)v=EN3H{M)KUhUooat6TLvJmF(7= zkuQfct(W!mQH#qod?9>l18d>&=-+?S@p0|nru~o72maIWH^Tt-%S!483Q84!GM(kqN26wICS?(wdl?L*9IG^wg9J`q8cDi?83-|u z#3W%*G?%V{u#}V4NypihEi1A!0&WPvADD^9p>`~tTB#49fFHFJYI;n9X>_!e*j>`F ztR1z+u-9BVPb$`MOYz{0OMZs`SagG$&Tt@I z*Z`J)y@&1=(8+3G(J*)iE)>yqe+N3&KjmOs(V^QMWiI^(&{aZU(jh30bl!Y@nA)<* zw+(bA-)Zl_@A549eZt~LzI2)7`x59bbXKK1k{34(W zIq0;1uY3<%{LH*Tevjb7@Q<0q-vr$n16clkgzbJGz?ykK;@F?f*eAd5;j+j1gP@y? zIInvZ5jMXsfvz2Kq5sJ5{_DDK!#I=?0R(bQSSb0~Vw_SZk{ zC!ND+gj9n%M%a0Xy9AdXM#Nh+zFfl}fo~j*w4X45_|ErAO%#oipECe_J_-Gp1yiB; z24M1bT#tY>XrwY4|hc`=mdz@ZD+nv(#3=KezDLrQy$3 zw*wBiaYa(!Hhiy(V|fFf_6VrYq~RxtQPyO~7xB{lSVyqEpR?#WvHzn7rcu^7;(zCX z&6CcgA^sGM_%M9t#3!Z80q;Y&Ov6h6{{ms|+llAqCxI|Lfx8g67GX{n#BT*Wj4&s4 z!q)@lWLU4^yOr3UHZ*`CHZSIY3>o{Kpm!^7e zzG;5aw0+XFePWxoor&%QF>O1-yn6>h9sXk+1?6XKN85dUxKn$exNTBj-JXY<-+FPb z7^PLPD_*kCF)Y&n+;yEgw`5OHa6aH7T}slLrgYYfeJrh2Zg ztEnrteD!axi@!hg_G@pyCV7IN!)f2^CGzyNF-ecM7xWb#;B(#nxs}&3->SZx$b!K1J?_M)cZ5uw6;`GN=Fc?!6c?W!R=f+fDOP?`Wm+WO|v^~GCWly-T?r~L~ zD&5WKE%ZUxN*`OJHu~?=CzU|gK^Q`cs*Cuwgh9Vf$FHXk zp{}Hl_^aqcFTI*R;=Aah5Iyw4Z!>++<{N@ zMsOXHItNXm+zT%t$IB~Vc#YGDY|F*1X)P{4^iq)v-6|Kkq?aK*9rwSwbGM`RoVr8z z6u#(Dx$vdY&^Yd+-Ma{vr!4-K`8XHW_IP9mu*W0r28gsMN-iu>IM)RbvOXyd3$<`W zMdiZL77~LgO-R&@u*6^(r`a6E%=COcM!A{{Qwhn_g(nJKLMW_ zIhEF8;D1RU_}AeR|69TpO1%w#GpAV0p`@cy>aQUz-~N(6=hM_hGSz`fn}jhW3P4Ab zS|NRm0+7f&$oAwsC#ECx3yx&g5GDngk7P7K2(M$MWpbR~QAe&L-60oB1<0SH(>Qs5 z84@z>JRJ!!k21qoprRkL6KYzHDCTY4(*X85a7;IYi`tQ%9780e&~bOsPZ+#>ul zU#VC4q)WZ$EoG9wSku81_aRh(;lT(K?m(FQOc8fVLy*F8ri|AB%!V$Z>2z{Mep?J+ z`8Rv$UISgo!kgf31Z*?o`RE{QC(0{*1wQNPAzU`yg+R7LVA7c)kQk} z`SNtB$rlTSxJ>*GfR1(VbzXj@7#oJ4W5jgI;gxSb=(6G0XYn($T_*WPvgG%e#n1HD zO#HqJx^{120ej0k1(jyX%lVQn6Tec>UFM+E{=NLRSp0a~k}ea!?V!u1U;T~6&#ac2 z_0&IiIx6s`LoHUNBD_djL9>^Yow zQ_FRc`htb0b)TD%ayPC>HX{b4b)WsM)mGO^YGPLyvsR0Pt!3 zo{7S<{FIT_=_!| z9NiLZ=|DIn;m)?<{{Cu`^~8pkhKAxeJzcf30dN9R4km+DD?%66bPq@SdlPsWVoh^L zYYmD;^JQ;zs49^R_gq^g=$h^YjrHOB1>JacB5|F9LzHUeGy&7v!5*s{$pSjBHqM^v~742U!r6(wi98j8 ziOnyGM3*oVkMpY6k0Q|nc0x^G0pCu(3Z28KD>lnI0BBY>?;g+@6_|7;>{YKxXV;CP zyBKNgd_Oh@zYa}j>gE%mvz_7LRjEyoA59{3j?_$?1Sn=_1dOuyIzUkR8S9xg;PQT|@QoZt*R z2$(F{hlsxs@G!#c6NEnknEG#nhH2a81Z2{G1@Kl2-Us;ofP=W0{yD(3w;B2$17?^P zPh%Yf%!$mvZvm#GNBm5^h;vbxfvI#3;Ey4EFD~-01k5o3v!cMc>*E96k>1XsL}$1+ z97~3iQT^QvOsZq4-l@Y{um$OJPwAhrz@es!r2cS)=PMa_guHVZMHm z&b}UJsf60|dOY*iJnz{olc)D=mdO-fr%yYZWpd@&Ec?us$+j-toUp*n*F7BO=7{p7 zn-Y%xXg#Fu>}=^+(cHPFb?y50wXIDpozcN)64Jtgz_;o}w(5|1U7sA!S{I3Li}plX zM`F=-r-R z%)uv(F)+?VYNCTZ{lmR5Bu$WUC$YU|I2rAqNPcM28m+TWG+VdyRlSi|WUx0f*b|K; zmJTFxe|Ffhd})K1RPFkvwaZ)Acdl%xS-*O9N2tAN#i~y9x|*Y>V6nYm3VyfkE@S6B z4in4R%*L{&T)L)91@Gx9*$L|j-VJD9&QsI+@YSK|K3~f{M=FBnhi=6G?jwyQO^5P* zJK>Web)?IApWtXaDdvV!c;}GVXgl(`^xh*&N-itC>By4W<|A`eppBLr(zloGY}!9P zw)}{5yMNN>)KRs_wrgf%oc6SKU^y`h3a2l ze7LCSmB|PEhl_nPuOlVtRFE9}>dhDXicb6c{KFLmlg_Oi;WOKOa=Z8iVrxe58GY4R2O07(?cKmP|oqxIX90|=aW-bwBzQ5U9+?w+T*x+P1n58hR4kdyLXWb?VbxS zbCa4?&Ghb(E@=7q3X4=9`kSyu*U5!-NrbI+QBIC}i~zX0sCJY*GwZEXP6TXlXIxJBY_@v0me^fIk`d zUc$il!zVt*cuY-6`awrsr++_S@_j(ZKTH_uo}!Og;`{WG=^OM>r!*aqp0{X8M>XBQ z*ip~@jc5kK@WrBSj-2J=>oJJpRGUY?*ikj9?}}|3?I-p(6kcXybo~J7PzjUhqnjZ~ z#v^A`tNGLtyMPMnPdv>fknS4NK^KC!j!Zg+bcbAQDli#ADT9upt^5%bhUHCD-D8* z{CXMixSIjn@|}eaW0%*E??yoSnvS>r_03eCt3149jl(3{G=aXRS}noUlK&w)ZZf(ztVT$w?9jM zf3)~v8XQx;DcG@OBVRk{z*5Q^bl7F=e^-ERg~r?7ZUAC$ zRR*y9rxCXKje_n~#Bp4*9q8!)0GB<^e~8Y`a(LZO5MlFs4RjQO{LDN~e$Er{@o-PJ zZy>E(vN-D};QuJAUg`<>$rL^3dphYRy`#)`M@5J|Pb`7ea`I(35#AC})i}^o9Zn|W z(eB}7gwv|W*|o}>E#1JU;tr3FSoFNva=Qg{{kYSDc{t5JjK;%Zxf_e^<2yK|CC7I* zCARax)+TL{k;7X_X}&QH$m#Vb5B_>hpo=qCBK9{Y?Q|#YbSW$4f2N(z?)~oJHP|;T zd!!idoZkO#+wO9cW*qjs+%g!$#@E>?rwcdZ#9(J{B!T-6vE)$P`97;^;+|i>cMF=0 z3e{KRZb(7M95qyhQ;Swk_090j^w05~?kmkJ_s#cFWyA!cd{~c^{Vf52X)YJVBYo<0 z*kIo+i<4ox4*@P%+~|w41fL6?SMjLA9Q}2~dmT*>sp%VUc>wTnGV{0!z&727ux3?z zXb9GM=)MTLObS4grsG0O_t(xE=m7XPd9BsqW6||lX~@LOk8yNdp6rbV=`w9J{y*ZR BHuC@g literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a new file mode 100644 index 0000000000000000000000000000000000000000..97b9b3b1e58ebc8ec4ee3d4dbda79d74b743cc2a GIT binary patch literal 94644 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 literal 0 HcmV?d00001 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a new file mode 100644 index 0000000000000000000000000000000000000000..1488a250db4e53a541400ff40441203db9f3c48d GIT binary patch literal 462942 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�zH)zb7)RXC{=c4~u(<-~{ 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

GxLU~?*j!lR)5Ila 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 H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Write data to the driver. + * + * @param type HCI packet type. + * @param len Number of bytes to write + * @param pData Pointer to the data to write. + * @return the actual number of data bytes written, + * + * @note type parameter allows the driver layer to prepend the data with a + * header on the same write transaction. + * @note mbed os wrapper of hciDrvWrite + */ +uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData); + +/** + * Start the hci reset sequence. + * @note stable wrapper around hciCoreResetStart. + * @note definition provided in mbed OS. + */ +void hci_mbed_os_start_reset_sequence(void); + +/** + * Handle hci messages during the reset sequence. + * @param msg: The HCI message to handle. + * @note stable wrapper of hciCoreResetSequence. + * @note definition provided in mbed os. + */ +void hci_mbed_os_handle_reset_sequence(uint8_t* msg); + +/** + * Signal to the stack that the reset sequence is done. + * @note shall be called from mbed OS when the reset sequence has been done. + */ +void hci_mbed_os_signal_reset_sequence_done(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_MBED_OS_ADAPTATION_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h new file mode 100644 index 00000000000..45c601c81f8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h @@ -0,0 +1,44 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WSF_MBED_OS_ADAPTATION_H_ +#define WSF_MBED_OS_ADAPTATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrap core_util_critical_section_enter + */ +void wsf_mbed_os_critical_section_enter(void); + +/** + * Wrap core_util_critical_section_exit + */ +void wsf_mbed_os_critical_section_exit(void); + +/** + * Signal an event insertion in the Cordio stack to ble API. + */ +void wsf_mbed_ble_signal_event(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MBED_OS_ADAPTATION_H_ */ From ecebb727bd40111f3730fd828ecfbdfa07f4e27d Mon Sep 17 00:00:00 2001 From: ARM IT Date: Tue, 26 Sep 2017 17:09:13 -0500 Subject: [PATCH 27/29] Merging changes from ATParser towards parser unification --- platform/ATCmdParser.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ platform/ATCmdParser.h | 10 ++++++++++ 2 files changed, 51 insertions(+) diff --git a/platform/ATCmdParser.cpp b/platform/ATCmdParser.cpp index 6200f1fa4b6..3e5ee2cde2a 100644 --- a/platform/ATCmdParser.cpp +++ b/platform/ATCmdParser.cpp @@ -380,3 +380,44 @@ void ATCmdParser::abort() { _aborted = true; } + +bool ATCmdParser::process_oob() +{ + if (!_fh->readable()) { + return false; + } + + int i = 0; + while (true) { + // Receive next character + int c = getc(); + if (c < 0) { + return false; + } + _buffer[i++] = c; + _buffer[i] = 0; + + // Check for oob data + struct oob *oob = _oobs; + while ( oob ) { + if (i == (int)oob->len && memcmp( + oob->prefix, _buffer, oob->len) == 0) { + debug_if(_dbg_on, "AT! %s\r\n", oob->prefix); + oob->cb(); + return true; + } + oob = oob->next; + } + + // Clear the buffer when we hit a newline or ran out of space + // running out of space usually means we ran into binary data + if (i+1 >= _buffer_size || + strcmp(&_buffer[i-_output_delim_size], _output_delimiter) == 0) { + + debug_if(_dbg_on, "AT< %s", _buffer); + i = 0; + } + } +} + + diff --git a/platform/ATCmdParser.h b/platform/ATCmdParser.h index 03b1ef6b2ac..7a2e7f5e98b 100644 --- a/platform/ATCmdParser.h +++ b/platform/ATCmdParser.h @@ -288,6 +288,16 @@ class ATCmdParser : private NonCopyable * recv operation. */ void abort(); + + /** + * Process out-of-band data + * + * Process out-of-band data in the receive buffer. This function + * returns immediately if there is no data to process. + * + * @return true if oob data processed, false otherwise + */ + bool process_oob(void); }; } //namespace mbed From 0b70eba1b052cac523e05198ec5718de5b3ee3fb Mon Sep 17 00:00:00 2001 From: ARM IT Date: Tue, 26 Sep 2017 17:09:13 -0500 Subject: [PATCH 28/29] Merging changes from ATParser towards parser unification --- platform/ATCmdParser.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ platform/ATCmdParser.h | 10 ++++++++++ 2 files changed, 51 insertions(+) diff --git a/platform/ATCmdParser.cpp b/platform/ATCmdParser.cpp index 6200f1fa4b6..3e5ee2cde2a 100644 --- a/platform/ATCmdParser.cpp +++ b/platform/ATCmdParser.cpp @@ -380,3 +380,44 @@ void ATCmdParser::abort() { _aborted = true; } + +bool ATCmdParser::process_oob() +{ + if (!_fh->readable()) { + return false; + } + + int i = 0; + while (true) { + // Receive next character + int c = getc(); + if (c < 0) { + return false; + } + _buffer[i++] = c; + _buffer[i] = 0; + + // Check for oob data + struct oob *oob = _oobs; + while ( oob ) { + if (i == (int)oob->len && memcmp( + oob->prefix, _buffer, oob->len) == 0) { + debug_if(_dbg_on, "AT! %s\r\n", oob->prefix); + oob->cb(); + return true; + } + oob = oob->next; + } + + // Clear the buffer when we hit a newline or ran out of space + // running out of space usually means we ran into binary data + if (i+1 >= _buffer_size || + strcmp(&_buffer[i-_output_delim_size], _output_delimiter) == 0) { + + debug_if(_dbg_on, "AT< %s", _buffer); + i = 0; + } + } +} + + diff --git a/platform/ATCmdParser.h b/platform/ATCmdParser.h index 03b1ef6b2ac..7a2e7f5e98b 100644 --- a/platform/ATCmdParser.h +++ b/platform/ATCmdParser.h @@ -288,6 +288,16 @@ class ATCmdParser : private NonCopyable * recv operation. */ void abort(); + + /** + * Process out-of-band data + * + * Process out-of-band data in the receive buffer. This function + * returns immediately if there is no data to process. + * + * @return true if oob data processed, false otherwise + */ + bool process_oob(void); }; } //namespace mbed From 5b59b7fca355bdf31566b35ad18e41e5273b6655 Mon Sep 17 00:00:00 2001 From: Senthil Ramakrishnan Date: Wed, 27 Sep 2017 10:36:08 -0500 Subject: [PATCH 29/29] Merging changes from ATParser towards parser unification --- platform/ATCmdParser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ATCmdParser.h b/platform/ATCmdParser.h index 7a2e7f5e98b..1201a6055f5 100644 --- a/platform/ATCmdParser.h +++ b/platform/ATCmdParser.h @@ -289,7 +289,7 @@ class ATCmdParser : private NonCopyable */ void abort(); - /** + /** * Process out-of-band data * * Process out-of-band data in the receive buffer. This function