diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c index b04311f5f..420f8d699 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c @@ -23,11 +23,15 @@ #include "sys_arch.h" #include "lwip/udp.h" #include "lwip/opt.h" +#include +#include "lwip/sys.h" /******************************************************************************* * Definitions ******************************************************************************/ +#define UDP_BUF_SIZE 65536 + /******************************************************************************* * Prototypes ******************************************************************************/ @@ -42,14 +46,6 @@ char udp_socket_ip[] = {192, 168, 250, 252}; /******************************************************************************* * Code ******************************************************************************/ - -#include -#include "lwip/sys.h" - -#define LWIP_UDP_TASK_STACK 4096 -#define LWIP_UDP_TASK_PRIO 25 -#define UDP_BUF_SIZE 1024 - static void udp_recv_demo(void *arg) { lw_print("udp_recv_demo start.\n"); @@ -94,8 +90,8 @@ static void udp_recv_demo(void *arg) { memset(recv_buf, 0, UDP_BUF_SIZE); recv_len = recvfrom(socket_fd, recv_buf, UDP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len); - lw_print("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); - lw_print("Receive data : %s\n\n", recv_buf); + lw_pr_info("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); + lw_pr_info("Receive data : %s\n\n", recv_buf); sendto(socket_fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len); } @@ -108,13 +104,6 @@ static void udp_recv_demo(void *arg) } } -static void udp_recv_demo_thread(void* param) -{ - ETH_BSP_Config(); - lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("udp_recv_demo", udp_recv_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO); -} - void udp_socket_recv_run(int argc, char *argv[]) { int result = 0; @@ -127,7 +116,9 @@ void udp_socket_recv_run(int argc, char *argv[]) sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]); } - sys_thread_new("udp socket send", udp_recv_demo_thread, NULL, 4096, 15); + ETH_BSP_Config(); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); + sys_thread_new("udp_recv_demo", udp_recv_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), @@ -182,13 +173,6 @@ __exit: return; } -static void udp_send_demo_thread(void* param) -{ - ETH_BSP_Config(); - lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("udp_send_demo", udp_send_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO); -} - void udp_socket_send_run(int argc, char *argv[]) { int result = 0; @@ -201,7 +185,9 @@ void udp_socket_send_run(int argc, char *argv[]) sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]); } - sys_thread_new("udp socket send", udp_send_demo_thread, NULL, 4096, 15); + ETH_BSP_Config(); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); + sys_thread_new("udp_send_demo", udp_send_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), diff --git a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c index 9e948c81f..f9c2741b5 100755 --- a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c +++ b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c @@ -31,6 +31,8 @@ #define TCP_LOCAL_PORT 4840 #define UA_URL_SIZE 100 +#define UA_STACK_SIZE 4096 +#define UA_TASK_PRIO 25 /******************************************************************************* * Prototypes @@ -91,7 +93,7 @@ void test_sh_ua_connect(void) int result = 0; pthread_t th_id; pthread_attr_t attr; - sys_thread_new("ua test", test_ua_connect_thr, NULL, 4096, 15); + sys_thread_new("ua test", test_ua_connect_thr, NULL, UA_STACK_SIZE, UA_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), @@ -148,7 +150,7 @@ void *test_sh_ua_brower_objects(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); - sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); + sys_thread_new("ua object", test_ua_browser_objects, NULL, UA_STACK_SIZE, UA_TASK_PRIO); return NULL; } @@ -202,7 +204,7 @@ void *test_sh_ua_get_info(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); - sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); + sys_thread_new("ua object", test_ua_browser_objects, NULL, UA_STACK_SIZE, UA_TASK_PRIO); return NULL; } diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig index 910b833f8..19095bd47 100644 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig @@ -11,6 +11,14 @@ menuconfig BSP_USING_LWIP bool "Using LwIP device" default n select RESOURCES_LWIP +menuconfig BSP_USING_GPIO +bool "Using GPIO device " +default y +select RESOURCES_PIN + +if BSP_USING_GPIO +source "$BSP_DIR/third_party_driver/gpio/Kconfig" +endif menuconfig BSP_USING_I2C bool "Using I2C device" @@ -20,3 +28,14 @@ select RESOURCES_I2C if BSP_USING_I2C source "$BSP_DIR/third_party_driver/i2c/Kconfig" endif + +menuconfig BSP_USING_ADC +bool "Using ADC device" +default y +select RESOURCES_ADC + +menuconfig BSP_USING_SPI +bool "Using SPI device" +default y +select RESOURCES_SPI + diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile index e71e7eb3d..008906504 100644 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile @@ -12,4 +12,12 @@ ifeq ($(CONFIG_BSP_USING_I2C),y) SRC_DIR += i2c endif +ifeq ($(CONFIG_BSP_USING_ADC),y) + SRC_DIR += adc +endif + +ifeq ($(CONFIG_BSP_USING_SPI),y) + SRC_DIR += spi +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/Makefile new file mode 100755 index 000000000..b602cc180 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := fsl_adc.c adc_interrupt.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c new file mode 100755 index 000000000..ebc2c1f3c --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/adc_interrupt.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file adc_interrupt.c + * @brief Demo for ADC function + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.1.18 + */ + +#include "fsl_debug_console.h" +#include "board.h" +#include "fsl_adc.h" +#include "fsl_common.h" + +#include "pin_mux.h" +#include "clock_config.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +#define DEMO_ADC_BASE ADC1 +#define DEMO_ADC_IRQn ADC1_IRQn +//#define DEMO_ADC_USER_CHANNEL 0U +#define DEMO_ADC_USER_CHANNEL 3U +#define DEMO_ADC_CHANNEL_GROUP 0U +#define EXAMPLE_ADC_IRQHandler ADC1_IRQHandler + +#define adc_print KPrintf + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +volatile bool g_AdcConversionDoneFlag; +volatile uint32_t g_AdcConversionValue; +volatile uint32_t g_AdcInterruptCounter; +const uint32_t g_Adc_12bitFullRange = 4096U; + +/******************************************************************************* + * Code + ******************************************************************************/ + +//#define ADC_BUS_NAME_1 "adc1" +//#define ADC_DRV_NAME_1 "adc1_drv" +//#define ADC_1_DEVICE_NAME_0 "adc1_dev0" +// +//static struct Bus *adc_bus = NONE; /* I2C bus handle */ +// +//void AdcInit(const char *bus_name, const char *dev_name, const char *drv_name) +//{ +// /* find I2C device and get I2C handle */ +// adc_bus = BusFind(bus_name); +// if (NONE == adc_bus){ +// i2c_print("%s can't find %s bus!\n", __func__, bus_name); +// } +// else{ +// i2c_print("%s find %s bus!\n", __func__, bus_name); +// } +// +// adc_bus->owner_haldev = BusFindDevice(adc_bus, dev_name); +// adc_bus->owner_driver = BusFindDriver(adc_bus, drv_name); +// +// if(adc_bus->match(adc_bus->owner_driver, adc_bus->owner_haldev)){ +// i2c_print("i2c match drv %s %p dev %s %p error\n", drv_name, adc_bus->owner_driver, dev_name, adc_bus->owner_haldev); +// } +// else{ +// i2c_print("HS3000Init successfully!write %p read %p\n", +// adc_bus->owner_haldev->dev_done->write, +// adc_bus->owner_haldev->dev_done->read); +// } +//} +// +//void TestAdcInit(void) +//{ +// AdcInit(ADC_BUS_NAME_1, ADC_1_DEVICE_NAME_0, ADC_DRV_NAME_1); /* init sensor */ +//} + +void EXAMPLE_ADC_IRQHandler(int vector, void *param) +{ + g_AdcConversionDoneFlag = true; + /* Read conversion result to clear the conversion completed flag. */ + g_AdcConversionValue = ADC_GetChannelConversionValue(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP); + g_AdcInterruptCounter++; +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} + +DECLARE_HW_IRQ(ADC1_IRQn, EXAMPLE_ADC_IRQHandler, NONE); + +/*! + * @brief Main function + */ +int test_adc(void) +{ + int cnt = 3; + adc_config_t adcConfigStrcut; + adc_channel_config_t adcChannelConfigStruct; + +// TestAdcInit(); + + EnableIRQ(DEMO_ADC_IRQn); + + adc_print("\r\nADC interrupt Example.\r\n"); + + /* + * config->enableAsynchronousClockOutput = true; + * config->enableOverWrite = false; + * config->enableContinuousConversion = false; + * config->enableHighSpeed = false; + * config->enableLowPower = false; + * config->enableLongSample = false; + * config->referenceVoltageSource = kADC_ReferenceVoltageSourceVref; + * config->samplePeriodMode = kADC_SamplePeriod2or12Clocks; + * config->clockSource = kADC_ClockSourceAD; + * config->clockDriver = kADC_ClockDriver1; + * config->resolution = kADC_Resolution12Bit; + */ + ADC_GetDefaultConfig(&adcConfigStrcut); + ADC_Init(DEMO_ADC_BASE, &adcConfigStrcut); +#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) + ADC_EnableHardwareTrigger(DEMO_ADC_BASE, false); +#endif + + /* Do auto hardware calibration. */ + if (kStatus_Success == ADC_DoAutoCalibration(DEMO_ADC_BASE)) + { + adc_print("ADC_DoAntoCalibration() Done.\r\n"); + } + else + { + adc_print("ADC_DoAutoCalibration() Failed.\r\n"); + } + + /* Configure the user channel and interrupt. */ + adcChannelConfigStruct.channelNumber = DEMO_ADC_USER_CHANNEL; + adcChannelConfigStruct.enableInterruptOnConversionCompleted = true; + g_AdcInterruptCounter = 0U; /* Clear the interrupt counter. */ + + adc_print("ADC Full Range: %d\r\n", g_Adc_12bitFullRange); + while (cnt --) + { + adc_print("Press any key to get user channel's ADC value.\r\n"); + getchar(); + g_AdcConversionDoneFlag = false; + /* + When in software trigger mode, each conversion would be launched once calling the "ADC16_ChannelConfigure()" + function, which works like writing a conversion command and executing it. For another channel's conversion, + just to change the "channelNumber" field in channel configuration structure, and call the function + "ADC_ChannelConfigure()"" again. + Also, the "enableInterruptOnConversionCompleted" inside the channel configuration structure is a parameter + for + the conversion command. It takes affect just for the current conversion. If the interrupt is still required + for the following conversion, it is necessary to assert the "enableInterruptOnConversionCompleted" every + time + for each command. + */ + ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adcChannelConfigStruct); + while (g_AdcConversionDoneFlag == false) + { + } + adc_print("ADC Value: %d\r\n", g_AdcConversionValue); + adc_print("ADC Interrupt Counter: %d\r\n", g_AdcInterruptCounter); + } +} + +SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), + adc, test_adc, ADC test ); + diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/fsl_adc.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/fsl_adc.c new file mode 100755 index 000000000..d9b5b6ff1 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/fsl_adc.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_adc.h" + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.adc_12b1msps_sar" +#endif + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief Get instance number for ADC module. + * + * @param base ADC peripheral base address + */ +static uint32_t ADC_GetInstance(ADC_Type *base); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/*! @brief Pointers to ADC bases for each instance. */ +static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +/*! @brief Pointers to ADC clocks for each instance. */ +static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/******************************************************************************* + * Code + ******************************************************************************/ +static uint32_t ADC_GetInstance(ADC_Type *base) +{ + uint32_t instance; + + /* Find the instance index from base address mappings. */ + for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++) + { + if (s_adcBases[instance] == base) + { + break; + } + } + + assert(instance < ARRAY_SIZE(s_adcBases)); + + return instance; +} + +/*! + * brief Initialize the ADC module. + * + * param base ADC peripheral base address. + * param config Pointer to "adc_config_t" structure. + */ +void ADC_Init(ADC_Type *base, const adc_config_t *config) +{ + assert(NULL != config); + + uint32_t tmp32; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Enable the clock. */ + CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + /* ADCx_CFG */ + tmp32 = base->CFG & (ADC_CFG_AVGS_MASK | ADC_CFG_ADTRG_MASK); /* Reserve AVGS and ADTRG bits. */ + tmp32 |= ADC_CFG_REFSEL(config->referenceVoltageSource) | ADC_CFG_ADSTS(config->samplePeriodMode) | + ADC_CFG_ADICLK(config->clockSource) | ADC_CFG_ADIV(config->clockDriver) | ADC_CFG_MODE(config->resolution); + if (config->enableOverWrite) + { + tmp32 |= ADC_CFG_OVWREN_MASK; + } + if (config->enableLongSample) + { + tmp32 |= ADC_CFG_ADLSMP_MASK; + } + if (config->enableLowPower) + { + tmp32 |= ADC_CFG_ADLPC_MASK; + } + if (config->enableHighSpeed) + { + tmp32 |= ADC_CFG_ADHSC_MASK; + } + base->CFG = tmp32; + + /* ADCx_GC */ + tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK); + if (config->enableContinuousConversion) + { + tmp32 |= ADC_GC_ADCO_MASK; + } + if (config->enableAsynchronousClockOutput) + { + tmp32 |= ADC_GC_ADACKEN_MASK; + } + base->GC = tmp32; +} + +/*! + * brief De-initializes the ADC module. + * + * param base ADC peripheral base address. + */ +void ADC_Deinit(ADC_Type *base) +{ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Disable the clock. */ + CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +/*! + * brief Gets an available pre-defined settings for the converter's configuration. + * + * This function initializes the converter configuration structure with available settings. The default values are: + * code + * config->enableAsynchronousClockOutput = true; + * config->enableOverWrite = false; + * config->enableContinuousConversion = false; + * config->enableHighSpeed = false; + * config->enableLowPower = false; + * config->enableLongSample = false; + * config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0; + * config->samplePeriodMode = kADC_SamplePeriod2or12Clocks; + * config->clockSource = kADC_ClockSourceAD; + * config->clockDriver = kADC_ClockDriver1; + * config->resolution = kADC_Resolution12Bit; + * endcode + * param base ADC peripheral base address. + * param config Pointer to the configuration structure. + */ +void ADC_GetDefaultConfig(adc_config_t *config) +{ + assert(NULL != config); + + /* Initializes the configure structure to zero. */ + memset(config, 0, sizeof(*config)); + + config->enableAsynchronousClockOutput = true; + config->enableOverWrite = false; + config->enableContinuousConversion = false; + config->enableHighSpeed = false; + config->enableLowPower = false; + config->enableLongSample = false; + config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0; + config->samplePeriodMode = kADC_SamplePeriod2or12Clocks; + config->clockSource = kADC_ClockSourceAD; + config->clockDriver = kADC_ClockDriver1; + config->resolution = kADC_Resolution12Bit; +} + +/*! + * brief Configures the conversion channel. + * + * 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 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. The channel group 0 is used for both software and + * hardware + * trigger modes. 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 appropriate 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. 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 ADC peripheral base address. + * param channelGroup Channel group index. + * param config Pointer to the "adc_channel_config_t" structure for the conversion channel. + */ +void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config) +{ + assert(NULL != config); + assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT); + + uint32_t tmp32; + + tmp32 = ADC_HC_ADCH(config->channelNumber); + if (config->enableInterruptOnConversionCompleted) + { + tmp32 |= ADC_HC_AIEN_MASK; + } + base->HC[channelGroup] = tmp32; +} + +/* + *To complete calibration, the user must follow the below procedure: + * 1. Configure ADC_CFG with actual operating values for maximum accuracy. + * 2. Configure the ADC_GC values along with CAL bit. + * 3. Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. + * 4. When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. + */ +/*! + * brief Automates the hardware calibration. + * + * This auto calibration helps to adjust the plus/minus side gain automatically. + * Execute the calibration before using the converter. Note that the software trigger should be used + * during calibration. + * + * param base ADC peripheral base address. + * + * return Execution status. + * retval kStatus_Success Calibration is done successfully. + * retval kStatus_Fail Calibration has failed. + */ +status_t ADC_DoAutoCalibration(ADC_Type *base) +{ + status_t status = kStatus_Success; +#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) + bool bHWTrigger = false; + + /* The calibration would be failed when in hardwar mode. + * Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/ + if (0U != (ADC_CFG_ADTRG_MASK & base->CFG)) + { + bHWTrigger = true; + ADC_EnableHardwareTrigger(base, false); + } +#endif + + /* Clear the CALF and launch the calibration. */ + base->GS = ADC_GS_CALF_MASK; /* Clear the CALF. */ + base->GC |= ADC_GC_CAL_MASK; /* Launch the calibration. */ + + /* Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. */ + while (0U != (base->GC & ADC_GC_CAL_MASK)) + { + /* Check the CALF when the calibration is active. */ + if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag)) + { + status = kStatus_Fail; + break; + } + } + + /* When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. */ + if (0U == ADC_GetChannelStatusFlags(base, 0U)) /* Check the COCO[0] bit status. */ + { + status = kStatus_Fail; + } + if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag)) /* Check the CALF status. */ + { + status = kStatus_Fail; + } + + /* Clear conversion done flag. */ + ADC_GetChannelConversionValue(base, 0U); + +#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) + /* Restore original trigger mode. */ + if (true == bHWTrigger) + { + ADC_EnableHardwareTrigger(base, true); + } +#endif + + return status; +} + +/*! + * brief Set user defined offset. + * + * param base ADC peripheral base address. + * param config Pointer to "adc_offest_config_t" structure. + */ +void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config) +{ + assert(NULL != config); + + uint32_t tmp32; + + tmp32 = ADC_OFS_OFS(config->offsetValue); + if (config->enableSigned) + { + tmp32 |= ADC_OFS_SIGN_MASK; + } + base->OFS = tmp32; +} + +/*! + * brief Configures the hardware compare mode. + * + * 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 "adc_hardware_compare_mode_t" or the appopriate + * reference + * manual for more information. + * + * param base ADC peripheral base address. + * param Pointer to "adc_hardware_compare_config_t" structure. + * + */ +void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config) +{ + uint32_t tmp32; + + tmp32 = base->GC & ~(ADC_GC_ACFE_MASK | ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK); + if (NULL == config) /* Pass "NULL" to disable the feature. */ + { + base->GC = tmp32; + return; + } + /* Enable the feature. */ + tmp32 |= ADC_GC_ACFE_MASK; + + /* Select the hardware compare working mode. */ + switch (config->hardwareCompareMode) + { + case kADC_HardwareCompareMode0: + break; + case kADC_HardwareCompareMode1: + tmp32 |= ADC_GC_ACFGT_MASK; + break; + case kADC_HardwareCompareMode2: + tmp32 |= ADC_GC_ACREN_MASK; + break; + case kADC_HardwareCompareMode3: + tmp32 |= ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK; + break; + default: + break; + } + base->GC = tmp32; + + /* Load the compare values. */ + tmp32 = ADC_CV_CV1(config->value1) | ADC_CV_CV2(config->value2); + base->CV = tmp32; +} + +/*! + * brief Configures the hardware average mode. + * + * 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 ADC peripheral base address. + * param mode Setting the hardware average mode. See "adc_hardware_average_mode_t". + */ +void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode) +{ + uint32_t tmp32; + + if (mode == kADC_HardwareAverageDiasable) + { + base->GC &= ~ADC_GC_AVGE_MASK; + } + else + { + tmp32 = base->CFG & ~ADC_CFG_AVGS_MASK; + tmp32 |= ADC_CFG_AVGS(mode); + base->CFG = tmp32; + base->GC |= ADC_GC_AVGE_MASK; /* Enable the hardware compare. */ + } +} + +/*! + * brief Clears the converter's status falgs. + * + * param base ADC peripheral base address. + * param mask Mask value for the cleared flags. See "adc_status_flags_t". + */ +void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask) +{ + uint32_t tmp32 = 0; + + if (0U != (mask & kADC_CalibrationFailedFlag)) + { + tmp32 |= ADC_GS_CALF_MASK; + } + if (0U != (mask & kADC_ConversionActiveFlag)) + { + tmp32 |= ADC_GS_ADACT_MASK; + } + base->GS = tmp32; +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/fsl_adc.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/fsl_adc.h new file mode 100755 index 000000000..be4829cb4 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/adc/fsl_adc.h @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_ADC_H_ +#define _FSL_ADC_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup adc_12b1msps_sar + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief ADC driver version */ +#define FSL_ADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2. */ + +/*! + * @brief Converter's status flags. + */ +typedef enum _adc_status_flags +{ + kADC_ConversionActiveFlag = ADC_GS_ADACT_MASK, /*!< Conversion is active,not support w1c. */ + kADC_CalibrationFailedFlag = ADC_GS_CALF_MASK, /*!< Calibration is failed,support w1c. */ + kADC_AsynchronousWakeupInterruptFlag = + ADC_GS_AWKST_MASK, /*!< Asynchronous wakeup interrupt occurred, support w1c. */ +} adc_status_flags_t; + +/*! + * @brief Reference voltage source. + */ +typedef enum _adc_reference_voltage_source +{ + kADC_ReferenceVoltageSourceAlt0 = 0U, /*!< For external pins pair of VrefH and VrefL. */ +} adc_reference_voltage_source_t; + +/*! + * @brief Sample time duration. + */ +typedef enum _adc_sample_period_mode +{ + /* This group of enumeration is for internal use which is related to register setting. */ + kADC_SamplePeriod2or12Clocks = 0U, /*!< Long sample 12 clocks or short sample 2 clocks. */ + kADC_SamplePeriod4or16Clocks = 1U, /*!< Long sample 16 clocks or short sample 4 clocks. */ + kADC_SamplePeriod6or20Clocks = 2U, /*!< Long sample 20 clocks or short sample 6 clocks. */ + kADC_SamplePeriod8or24Clocks = 3U, /*!< Long sample 24 clocks or short sample 8 clocks. */ + /* This group of enumeration is for a public user. */ + /* For long sample mode. */ + kADC_SamplePeriodLong12Clcoks = kADC_SamplePeriod2or12Clocks, /*!< Long sample 12 clocks. */ + kADC_SamplePeriodLong16Clcoks = kADC_SamplePeriod4or16Clocks, /*!< Long sample 16 clocks. */ + kADC_SamplePeriodLong20Clcoks = kADC_SamplePeriod6or20Clocks, /*!< Long sample 20 clocks. */ + kADC_SamplePeriodLong24Clcoks = kADC_SamplePeriod8or24Clocks, /*!< Long sample 24 clocks. */ + /* For short sample mode. */ + kADC_SamplePeriodShort2Clocks = kADC_SamplePeriod2or12Clocks, /*!< Short sample 2 clocks. */ + kADC_SamplePeriodShort4Clocks = kADC_SamplePeriod4or16Clocks, /*!< Short sample 4 clocks. */ + kADC_SamplePeriodShort6Clocks = kADC_SamplePeriod6or20Clocks, /*!< Short sample 6 clocks. */ + kADC_SamplePeriodShort8Clocks = kADC_SamplePeriod8or24Clocks, /*!< Short sample 8 clocks. */ +} adc_sample_period_mode_t; + +/*! + * @brief Clock source. + */ +typedef enum _adc_clock_source +{ + kADC_ClockSourceIPG = 0U, /*!< Select IPG clock to generate ADCK. */ + kADC_ClockSourceIPGDiv2 = 1U, /*!< Select IPG clock divided by 2 to generate ADCK. */ +#if !(defined(FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE) && FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE) + kADC_ClockSourceALT = 2U, /*!< Select alternate clock to generate ADCK. */ +#endif + kADC_ClockSourceAD = 3U, /*!< Select Asynchronous clock to generate ADCK. */ +} adc_clock_source_t; + +/*! + * @brief Clock divider for the converter. + */ +typedef enum _adc_clock_drvier +{ + kADC_ClockDriver1 = 0U, /*!< For divider 1 from the input clock to the module. */ + kADC_ClockDriver2 = 1U, /*!< For divider 2 from the input clock to the module. */ + kADC_ClockDriver4 = 2U, /*!< For divider 4 from the input clock to the module. */ + kADC_ClockDriver8 = 3U, /*!< For divider 8 from the input clock to the module. */ +} adc_clock_driver_t; + +/*! + * @brief Converter's resolution. + */ +typedef enum _adc_resolution +{ + kADC_Resolution8Bit = 0U, /*!< Single End 8-bit resolution. */ + kADC_Resolution10Bit = 1U, /*!< Single End 10-bit resolution. */ + kADC_Resolution12Bit = 2U, /*!< Single End 12-bit resolution. */ +} adc_resolution_t; + +/*! + * @brief Converter hardware compare mode. + */ +typedef enum _adc_hardware_compare_mode +{ + kADC_HardwareCompareMode0 = 0U, /*!< Compare true if the result is less than the value1. */ + kADC_HardwareCompareMode1 = 1U, /*!< Compare true if the result is greater than or equal to value1. */ + kADC_HardwareCompareMode2 = 2U, /*!< Value1 <= Value2, compare true if the result is less than value1 Or + the result is Greater than value2. + Value1 > Value2, compare true if the result is less than value1 And the + result is greater than value2*/ + kADC_HardwareCompareMode3 = 3U, /*!< Value1 <= Value2, compare true if the result is greater than or equal + to value1 And the result is less than or equal to value2. + Value1 > Value2, compare true if the result is greater than or equal to + value1 Or the result is less than or equal to value2. */ +} adc_hardware_compare_mode_t; + +/*! + * @brief Converter hardware average mode. + */ +typedef enum _adc_hardware_average_mode +{ + kADC_HardwareAverageCount4 = 0U, /*!< For hardware average with 4 samples. */ + kADC_HardwareAverageCount8 = 1U, /*!< For hardware average with 8 samples. */ + kADC_HardwareAverageCount16 = 2U, /*!< For hardware average with 16 samples. */ + kADC_HardwareAverageCount32 = 3U, /*!< For hardware average with 32 samples. */ + kADC_HardwareAverageDiasable = 4U, /*!< Disable the hardware average function. */ +} adc_hardware_average_mode_t; + +/*! + * @brief Converter configuration. + */ +typedef struct _adc_config +{ + bool enableOverWrite; /*!< Enable the overwriting. */ + bool enableContinuousConversion; /*!< Enable the continuous conversion mode. */ + bool enableHighSpeed; /*!< Enable the high-speed mode. */ + bool enableLowPower; /*!< Enable the low power mode. */ + bool enableLongSample; /*!< Enable the long sample mode. */ + bool enableAsynchronousClockOutput; /*!< Enable the asynchronous clock output. */ + adc_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */ + adc_sample_period_mode_t samplePeriodMode; /*!< Select the sample period in long sample mode or short mode. */ + adc_clock_source_t clockSource; /*!< Select the input clock source to generate the internal clock ADCK. */ + adc_clock_driver_t clockDriver; /*!< Select the divide ratio used by the ADC to generate the internal clock ADCK. */ + adc_resolution_t resolution; /*!< Select the ADC resolution mode. */ +} adc_config_t; + +/*! + * @brief Converter Offset configuration. + */ +typedef struct _adc_offest_config +{ + bool enableSigned; /*!< if false,The offset value is added with the raw result. + if true,The offset value is subtracted from the raw converted value. */ + uint32_t offsetValue; /*!< User configurable offset value(0-4095). */ +} adc_offest_config_t; + +/*! + * @brief ADC hardware compare configuration. + * + * In kADC_HardwareCompareMode0, compare true if the result is less than the value1. + * In kADC_HardwareCompareMode1, compare true if the result is greater than or equal to value1. + * In kADC_HardwareCompareMode2, Value1 <= Value2, compare true if the result is less than value1 Or the result is + * Greater than value2. + * Value1 > Value2, compare true if the result is less than value1 And the result is + * Greater than value2. + * In kADC_HardwareCompareMode3, Value1 <= Value2, compare true if the result is greater than or equal to value1 And the + * result is less than or equal to value2. + * Value1 > Value2, compare true if the result is greater than or equal to value1 Or the + * result is less than or equal to value2. + */ +typedef struct _adc_hardware_compare_config +{ + adc_hardware_compare_mode_t hardwareCompareMode; /*!< Select the hardware compare mode. + See "adc_hardware_compare_mode_t". */ + uint16_t value1; /*!< Setting value1(0-4095) for hardware compare mode. */ + uint16_t value2; /*!< Setting value2(0-4095) for hardware compare mode. */ +} adc_hardware_compare_config_t; + +/*! + * @brief ADC channel conversion configuration. + */ +typedef struct _adc_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 an interrupt request once the conversion is completed. */ +} adc_channel_config_t; +/******************************************************************************* + * API + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name Initialization + * @{ + */ + +/*! + * @brief Initialize the ADC module. + * + * @param base ADC peripheral base address. + * @param config Pointer to "adc_config_t" structure. + */ +void ADC_Init(ADC_Type *base, const adc_config_t *config); + +/*! + * @brief De-initializes the ADC module. + * + * @param base ADC peripheral base address. + */ +void ADC_Deinit(ADC_Type *base); + +/*! + * @brief Gets an available pre-defined settings for the converter's configuration. + * + * This function initializes the converter configuration structure with available settings. The default values are: + * @code + * config->enableAsynchronousClockOutput = true; + * config->enableOverWrite = false; + * config->enableContinuousConversion = false; + * config->enableHighSpeed = false; + * config->enableLowPower = false; + * config->enableLongSample = false; + * config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0; + * config->samplePeriodMode = kADC_SamplePeriod2or12Clocks; + * config->clockSource = kADC_ClockSourceAD; + * config->clockDriver = kADC_ClockDriver1; + * config->resolution = kADC_Resolution12Bit; + * @endcode + * @param base ADC peripheral base address. + * @param config Pointer to the configuration structure. + */ +void ADC_GetDefaultConfig(adc_config_t *config); + +/*! + * @brief Configures the conversion channel. + * + * 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 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. The channel group 0 is used for both software and + * hardware + * trigger modes. 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 appropriate 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. 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 ADC peripheral base address. + * @param channelGroup Channel group index. + * @param config Pointer to the "adc_channel_config_t" structure for the conversion channel. + */ +void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config); + +/*! + * @brief Gets the conversion value. + * + * @param base ADC peripheral base address. + * @param channelGroup Channel group index. + * + * @return Conversion value. + */ +static inline uint32_t ADC_GetChannelConversionValue(ADC_Type *base, uint32_t channelGroup) +{ + assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT); + + return base->R[channelGroup]; +} + +/*! + * @brief Gets the status flags of channel. + * + * A conversion is completed when the result of the conversion is transferred into the data + * result registers. (provided the compare function & hardware averaging is disabled), this is + * indicated by the setting of COCOn. If hardware averaging is enabled, COCOn sets only, + * if the last of the selected number of conversions is complete. If the compare function is + * enabled, COCOn sets and conversion result data is transferred only if the compare + * condition is true. If both hardware averaging and compare functions are enabled, then + * COCOn sets only if the last of the selected number of conversions is complete and the + * compare condition is true. + * + * @param base ADC peripheral base address. + * @param channelGroup Channel group index. + * + * @return Status flags of channel.return 0 means COCO flag is 0,return 1 means COCOflag is 1. + */ +static inline uint32_t ADC_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup) +{ + assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT); + + /* If flag is set,return 1,otherwise, return 0. */ + return (((base->HS) & (1U << channelGroup)) >> channelGroup); +} + +/*! + * @brief Automates the hardware calibration. + * + * This auto calibration helps to adjust the plus/minus side gain automatically. + * Execute the calibration before using the converter. Note that the software trigger should be used + * during calibration. + * + * @param base ADC peripheral base address. + * + * @return Execution status. + * @retval kStatus_Success Calibration is done successfully. + * @retval kStatus_Fail Calibration has failed. + */ +status_t ADC_DoAutoCalibration(ADC_Type *base); + +/*! + * @brief Set user defined offset. + * + * @param base ADC peripheral base address. + * @param config Pointer to "adc_offest_config_t" structure. + */ +void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config); + +/*! + * @brief Enables generating the DMA trigger when the conversion is complete. + * + * @param base ADC peripheral base address. + * @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled. + */ +static inline void ADC_EnableDMA(ADC_Type *base, bool enable) +{ + if (enable) + { + base->GC |= ADC_GC_DMAEN_MASK; + } + else + { + base->GC &= ~ADC_GC_DMAEN_MASK; + } +} + +/*! + * @brief Enables the hardware trigger mode. + * + * @param base ADC peripheral base address. + * @param enable Switcher of the trigger mode. "true" means hardware tirgger mode,"false" means software mode. + */ +#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) +static inline void ADC_EnableHardwareTrigger(ADC_Type *base, bool enable) +{ + if (enable) + { + base->CFG |= ADC_CFG_ADTRG_MASK; + } + else + { + base->CFG &= ~ADC_CFG_ADTRG_MASK; + } +} +#endif + +/*! + * @brief Configures the hardware compare mode. + * + * 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 "adc_hardware_compare_mode_t" or the appopriate + * reference + * manual for more information. + * + * @param base ADC peripheral base address. + * @param Pointer to "adc_hardware_compare_config_t" structure. + * + */ +void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config); + +/*! + * @brief Configures the hardware average mode. + * + * 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 ADC peripheral base address. + * @param mode Setting the hardware average mode. See "adc_hardware_average_mode_t". + */ +void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode); + +/*! + * @brief Gets the converter's status flags. + * + * @param base ADC peripheral base address. + * + * @return Flags' mask if indicated flags are asserted. See "adc_status_flags_t". + */ +static inline uint32_t ADC_GetStatusFlags(ADC_Type *base) +{ + return base->GS; +} + +/*! + * @brief Clears the converter's status falgs. + * + * @param base ADC peripheral base address. + * @param mask Mask value for the cleared flags. See "adc_status_flags_t". + */ +void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask); + +#if defined(__cplusplus) +} +#endif + +#endif /* _FSL_ADC_H_ */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c index 7ed420d66..d04c8adb3 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c @@ -78,7 +78,6 @@ * Definitions ******************************************************************************/ - /******************************************************************************* * Code ******************************************************************************/ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Kconfig b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Kconfig new file mode 100755 index 000000000..f284f60e3 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Kconfig @@ -0,0 +1,12 @@ + +config PIN_BUS_NAME + string "pin bus name" + default "pin" + +config PIN_DRIVER_NAME + string "pin driver name" + default "pin_drv" + +config PIN_DEVICE_NAME + string "pin device name" + default "pin_dev" diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Makefile index 2776af734..a69677383 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Makefile +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := fsl_gpio.c +SRC_FILES := connect_gpio.c fsl_gpio.c include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/connect_gpio.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/connect_gpio.c new file mode 100755 index 000000000..fdc55b4d9 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/gpio/connect_gpio.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2020 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-06 balanceTWK first version + * 2019-04-23 WillianChan Fix GPIO serial number disorder +*/ + +/** +* @file connect_gpio.c +* @brief support gpio function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: connect_gpio.c +Description: support gpio configure and register to bus framework +Others: take RT-Thread v4.0.2/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: add bus driver framework support for gpio +*************************************************/ + +#include +#include + +#define STM32_PIN_NUMBERS 100 // [48, 64, 100, 144] + +#define ITEM_NUM(items) sizeof(items)/sizeof(items[0]) + +struct PinIndex +{ + int index; + GPIO_Type *gpio; + uint32_t pin; +}; + +struct PinIrq +{ + uint8 port_source; + uint8 pin_source; + enum IRQn irq_exti_channel; + uint32 exti_line; +}; + +static const struct PinIndex pins[] = { + {0, GPIO1, 0}, + {1, GPIO1, 1}, + {2, GPIO1, 2}, + {3, GPIO1, 3}, + {4, GPIO1, 4}, + {5, GPIO1, 5}, + {6, GPIO1, 6}, + {7, GPIO1, 7}, + {8, GPIO1, 8}, + {9, GPIO1, 9}, + {10, GPIO1, 10}, + {11, GPIO1, 11}, + {12, GPIO1, 12}, + {13, GPIO1, 13}, + {14, GPIO1, 14}, + {15, GPIO1, 15}, + {16, GPIO2, 0}, + {17, GPIO2, 1}, + {18, GPIO2, 2}, + {19, GPIO2, 3}, + {20, GPIO2, 4}, + {21, GPIO2, 5}, + {22, GPIO2, 6}, + {23, GPIO2, 7}, + {24, GPIO2, 8}, + {25, GPIO2, 9}, + {26, GPIO2, 10}, + {27, GPIO2, 11}, + {28, GPIO2, 12}, + {29, GPIO2, 13}, + {30, GPIO2, 14}, + {31, GPIO2, 15}, + {32, GPIO3, 0}, + {33, GPIO3, 1}, + {34, GPIO3, 2}, + {35, GPIO3, 3}, + {36, GPIO3, 4}, + {37, GPIO3, 5}, + {38, GPIO3, 6}, + {39, GPIO3, 7}, + {40, GPIO3, 8}, + {41, GPIO3, 9}, + {42, GPIO3, 10}, + {43, GPIO3, 11}, + {44, GPIO3, 12}, + {45, GPIO3, 13}, + {46, GPIO3, 14}, + {47, GPIO3, 15}, + {-1, 0u, -1} +}; + +struct PinIrqHdr pin_irq_hdr_tab[] = {}; + +const struct PinIndex *GetPin(uint8_t pin) +{ + const struct PinIndex *index; + + if (pin < ITEM_NUM(pins)){ + index = &pins[pin]; + if (index->index == -1) + index = NONE; + } + else{ + index = NONE; + } + + return index; +} + +static int32 GpioConfigMode(int mode, const struct PinIndex* index) +{ + gpio_pin_config_t gpio_config; + NULL_PARAM_CHECK(index); + + switch (mode) + { + case GPIO_CFG_OUTPUT: + gpio_config.direction = kGPIO_DigitalOutput; + gpio_config.interruptMode = kGPIO_NoIntmode; + break; + case GPIO_CFG_INPUT: + gpio_config.direction = kGPIO_DigitalInput; + gpio_config.interruptMode = kGPIO_NoIntmode; + break; + case GPIO_CFG_INPUT_PULLUP: + gpio_config.direction = kGPIO_DigitalInput; + gpio_config.interruptMode = kGPIO_IntRisingEdge; + break; + case GPIO_CFG_INPUT_PULLDOWN: + gpio_config.direction = kGPIO_DigitalInput; + gpio_config.interruptMode = kGPIO_IntFallingEdge; + break; + case GPIO_CFG_OUTPUT_OD: + gpio_config.direction = kGPIO_DigitalOutput; + break; + default: + break; + } + GPIO_PinInit(index->gpio, index->pin, &gpio_config); + return EOK; +} + +static __inline int32 Bit2Bitnum(uint32 bit) +{ + for (int i = 0; i < 32; i++){ + if ((1UL << i) == bit){ + return i; + } + } + return -1; +} + +static __inline int32 Bitno2Bit(uint32 bitno) +{ + if (bitno <= 32) { + return 1UL << bitno; + } + else { + return 0; + } +} +static const struct PinIrq *GetPinIrq(uint16_t pin) +{ + static struct PinIrq irq; + const struct PinIndex* index = GetPin(pin); + + if (index == NONE) { + return NONE; + } + + irq.exti_line = index->pin; + irq.pin_source = Bit2Bitnum(index->pin); + irq.port_source = ((uint32_t)index->gpio - GPIO1_BASE) / (GPIO2_BASE - GPIO1_BASE); + switch (irq.pin_source) + { + case 0 : + irq.irq_exti_channel = GPIO1_INT0_IRQn; + break; + case 1 : + irq.irq_exti_channel = GPIO1_INT1_IRQn; + break; + case 2 : + irq.irq_exti_channel = GPIO1_INT2_IRQn; + break; + case 3 : + irq.irq_exti_channel = GPIO1_INT3_IRQn; + break; + case 4 : + irq.irq_exti_channel = GPIO1_INT4_IRQn; + break; + case 5 : + irq.irq_exti_channel = GPIO1_INT5_IRQn; + break; + case 6 : + irq.irq_exti_channel = GPIO1_INT6_IRQn; + break; + case 7 : + irq.irq_exti_channel = GPIO1_INT7_IRQn; + break; + default : + return NONE; + } + + return &irq; +}; +static int32 GpioIrqRegister(int32 pin, int32 mode, void (*hdr)(void *args), void *args) +{ + const struct PinIndex* index = GetPin(pin); + int32 irqindex = -1; + + irqindex = Bit2Bitnum(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_hdr_tab)) { + return -ENONESYS; + } + + x_base level = CriticalAreaLock(); + if (pin_irq_hdr_tab[irqindex].pin == pin && + pin_irq_hdr_tab[irqindex].hdr == hdr && + pin_irq_hdr_tab[irqindex].mode == mode && + pin_irq_hdr_tab[irqindex].args == args + ) + { + CriticalAreaUnLock(level); + return EOK; + } + if (pin_irq_hdr_tab[irqindex].pin != -1) { + CriticalAreaUnLock(level); + return -EDEV_BUSY; + } + pin_irq_hdr_tab[irqindex].pin = pin; + pin_irq_hdr_tab[irqindex].hdr = hdr; + pin_irq_hdr_tab[irqindex].mode = mode; + pin_irq_hdr_tab[irqindex].args = args; + CriticalAreaUnLock(level); + + return EOK; +} + +static uint32 GpioIrqFree(int32 pin) +{ + const struct PinIndex* index = GetPin(pin); + int32 irqindex = -1; + + irqindex = Bit2Bitnum(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_hdr_tab)) { + return -ENONESYS; + } + + x_base level = CriticalAreaLock(); + if (pin_irq_hdr_tab[irqindex].pin == -1){ + CriticalAreaUnLock(level); + return EOK; + } + pin_irq_hdr_tab[irqindex].pin = -1; + pin_irq_hdr_tab[irqindex].hdr = NONE; + pin_irq_hdr_tab[irqindex].mode = 0; + pin_irq_hdr_tab[irqindex].args = NONE; + CriticalAreaUnLock(level); + + return EOK; +} + +static int32 GpioIrqEnable(x_base pin) +{ + const struct PinIndex* index = GetPin(pin); + int32 irqindex = -1; + const struct PinIrq *irq; + gpio_pin_config_t gpio_config; + + irqindex = Bit2Bitnum(index->pin); + if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_hdr_tab)){ + return -ENONESYS; + } + x_base level = CriticalAreaLock(); + if (pin_irq_hdr_tab[irqindex].pin == -1) { + CriticalAreaUnLock(level); + return -ENONESYS; + } + + irq = GetPinIrq(pin); + if (irq == NONE){ + CriticalAreaUnLock(level); + return -ENONESYS; + } + + switch (pin_irq_hdr_tab[irqindex].mode) + { + case GPIO_IRQ_EDGE_RISING: + gpio_config.direction = kGPIO_DigitalInput; + gpio_config.interruptMode = kGPIO_IntRisingEdge; + break; + case GPIO_IRQ_EDGE_FALLING: + gpio_config.direction = kGPIO_DigitalInput; + gpio_config.interruptMode = kGPIO_IntFallingEdge; + break; + case GPIO_IRQ_EDGE_BOTH: + gpio_config.direction = kGPIO_DigitalInput; + gpio_config.interruptMode = kGPIO_IntRisingOrFallingEdge; + break; + } + + GPIO_PinInit(index->gpio, index->pin, &gpio_config); + GPIO_PortEnableInterrupts(index->gpio, index->pin); + CriticalAreaUnLock(level); + return EOK; +} + +static int32 GpioIrqDisable(x_base pin) +{ + const struct PinIndex* index = GetPin(pin); + const struct PinIrq *irq; + + irq = GetPinIrq(index->pin); + NULL_PARAM_CHECK(irq); + + GPIO_PortDisableInterrupts(index->gpio, index->pin); + return EOK; +} + +static uint32 Stm32PinConfigure(struct PinParam *param) +{ + NULL_PARAM_CHECK(param); + int ret = EOK; + + const struct PinIndex *index = GetPin(param->pin); + switch(param->cmd) + { + case GPIO_CONFIG_MODE: + GpioConfigMode(param->mode, index); + break; + case GPIO_IRQ_REGISTER: + ret = GpioIrqRegister(param->pin,param->irq_set.irq_mode,param->irq_set.hdr,param->irq_set.args); + break; + case GPIO_IRQ_FREE: + ret = GpioIrqFree(param->pin); + break; + case GPIO_IRQ_ENABLE: + ret = GpioIrqEnable(param->pin); + break; + case GPIO_IRQ_DISABLE: + ret = GpioIrqDisable(param->pin); + break; + default: + ret = -EINVALED; + break; + } + + return ret; +} + +static uint32 Stm32PinInit(void) +{ + static x_bool pin_init_flag = RET_FALSE; + + if (!pin_init_flag) { + pin_init_flag = RET_TRUE; + } + + return EOK; +} + +static uint32 Stm32GpioDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + struct PinParam *param; + + switch (configure_info->configure_cmd) + { + case OPE_INT: + ret = Stm32PinInit(); + break; + case OPE_CFG: + param = (struct PinParam *)configure_info->private_data; + ret = Stm32PinConfigure(param); + break; + default: + break; + } + + return ret; +} + +uint32 Stm32PinWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(write_param); + struct PinStat *pinstat = (struct PinStat *)write_param->buffer; + const struct PinIndex* index = GetPin(pinstat->pin); + NULL_PARAM_CHECK(index); + + if (GPIO_LOW == pinstat->val) { + GPIO_PinWrite(index->gpio, index->pin, 0); + } else { + GPIO_PinWrite(index->gpio, index->pin, 1); + } + return EOK; +} + +uint32 Stm32PinRead(void *dev, struct BusBlockReadParam *read_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(read_param); + struct PinStat *pinstat = (struct PinStat *)read_param->buffer; + const struct PinIndex* index = GetPin(pinstat->pin); + NULL_PARAM_CHECK(index); + + if(GPIO_PinRead(index->gpio, index->pin) == GPIO_LOW) { + pinstat->val = GPIO_LOW; + } else { + pinstat->val = GPIO_HIGH; + } + return pinstat->val; +} + +static const struct PinDevDone dev_done = +{ + .open = NONE, + .close = NONE, + .write = Stm32PinWrite, + .read = Stm32PinRead, +}; + +int Stm32HwGpioInit(void) +{ + x_err_t ret = EOK; + + static struct PinBus pin; + + ret = PinBusInit(&pin, PIN_BUS_NAME); + if (ret != EOK) { + KPrintf("gpio bus init error %d\n", ret); + return ERROR; + } + + static struct PinDriver drv; + drv.configure = &Stm32GpioDrvConfigure; + + ret = PinDriverInit(&drv, PIN_DRIVER_NAME, NONE); + if (ret != EOK) { + KPrintf("pin driver init error %d\n", ret); + return ERROR; + } + ret = PinDriverAttachToBus(PIN_DRIVER_NAME, PIN_BUS_NAME); + if (ret != EOK) { + KPrintf("pin driver attach error %d\n", ret); + return ERROR; + } + + static struct PinHardwareDevice dev; + dev.dev_done = &dev_done; + + ret = PinDeviceRegister(&dev, NONE, PIN_DEVICE_NAME); + if (ret != EOK) { + KPrintf("pin device register error %d\n", ret); + return ERROR; + } + ret = PinDeviceAttachToBus(PIN_DEVICE_NAME, PIN_BUS_NAME); + if (ret != EOK) { + KPrintf("pin device register error %d\n", ret); + return ERROR; + } + + return ret; +} + +static __inline void PinIrqHdr(int irqno) +{ + const struct PinIndex* index = GetPin(irqno); + const struct PinIrq *irq; + + irq = GetPinIrq(index->pin); + NULL_PARAM_CHECK(irq); + + GPIO_ClearPinsInterruptFlags(index->gpio, index->pin); + + if (pin_irq_hdr_tab[irqno].hdr){ + pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args); + } +} + +void EXTI0_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(0); +} +DECLARE_HW_IRQ(GPIO1_INT0_IRQn, EXTI0_IRQHandler, NONE); + +void EXTI1_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(1); +} +DECLARE_HW_IRQ(GPIO1_INT1_IRQn, EXTI1_IRQHandler, NONE); + +void EXTI2_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(2); +} +DECLARE_HW_IRQ(GPIO1_INT2_IRQn, EXTI2_IRQHandler, NONE); + +void EXTI3_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(3); +} +DECLARE_HW_IRQ(GPIO1_INT3_IRQn, EXTI3_IRQHandler, NONE); + +void EXTI4_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(4); +} +DECLARE_HW_IRQ(GPIO1_INT4_IRQn, EXTI4_IRQHandler, NONE); + +void EXTI5_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(5); +} +DECLARE_HW_IRQ(GPIO1_INT5_IRQn, EXTI5_IRQHandler, NONE); + +void EXTI6_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(6); +} +DECLARE_HW_IRQ(GPIO1_INT6_IRQn, EXTI6_IRQHandler, NONE); + +void EXTI7_IRQHandler(int irq_num, void *arg) +{ + PinIrqHdr(7); +} +DECLARE_HW_IRQ(GPIO1_INT7_IRQn, EXTI7_IRQHandler, NONE); + diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/Makefile index 09f3be8df..3f937865d 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/Makefile +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := i2c_EEPROM.c i2c_EEPROM_test.c fsl_lpi2c.c i2c_RTC_RX8010.c i2c_RTC_RX8010_test.c +SRC_FILES := connect_i2c.c i2c_eeprom.c i2c_eeprom_test.c fsl_lpi2c.c i2c_rtc_rx8010.c i2c_rtc_rx8010_test.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c new file mode 100755 index 000000000..c89d01e9e --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2020 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + */ + +/** +* @file connect_i2c.c +* @brief support stm32f407-st-discovery-board i2c function and register to bus framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +/************************************************* +File name: connect_i2c.c +Description: support stm32f407-st-discovery-board i2c configure and i2c bus register function +Others: take RT-Thread v4.0.2/components/drivers/i2c/i2c-bit-ops.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-25 +Author: AIIT XUOS Lab +Modification: +1. support stm32f407-st-discovery-board i2c bit configure, write and read +2. support stm32f407-st-discovery-board i2c bus device and driver register +*************************************************/ + +#include +#include "connect_i2c.h" +#include "bus_serial.h" +#include "i2c_rtc_rx8010.h" +#include "i2c_eeprom.h" + +#ifndef BSP_USING_I2C1 +#define BSP_USING_I2C1 +#endif + +static uint32 I2cWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) +{ + int32 ret; + + if(i2c_dev->i2c_dev_addr == I2C_RTC_ADDR){ + ret = rx8010_set_time(msg->buf); + } else if(i2c_dev->i2c_dev_addr == I2C_EEPROM_ADDR) { + ret = eeprom_write(msg->buf); + } + + return ret; +} + +static uint32 I2cReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) +{ + int32 ret; + + if(i2c_dev->i2c_dev_addr == I2C_RTC_ADDR){ + ret = rx8010_get_time(); + } else if(i2c_dev->i2c_dev_addr == I2C_EEPROM_ADDR) { + ret = eeprom_read(msg->buf); + } + return ret; +} + +static uint32 I2cInit(struct I2cDriver *i2c_drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(i2c_drv); + + struct I2cHardwareDevice *i2c_dev = (struct I2cHardwareDevice *)i2c_drv->driver.owner_bus->owner_haldev; + + if (configure_info->private_data) { + i2c_dev->i2c_dev_addr = *((uint16 *)configure_info->private_data); + return EOK; + } + + KPrintf("I2cInit need set i2c dev addr\n"); + return ERROR; +} + +static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + struct I2cDriver *i2c_drv = (struct I2cDriver *)drv; + + switch (configure_info->configure_cmd) + { + case OPE_INT: + ret = I2cInit(i2c_drv, configure_info); + break; + default: + break; + } + + return ret; +} + +/*manage the i2c device operations*/ +static const struct I2cDevDone i2c_dev_done = +{ + .dev_open = NONE, + .dev_close = NONE, + .dev_write = I2cWriteData, + .dev_read = I2cReadData, +}; + +/*Init i2c bus*/ +static int BoardI2cBusInit(struct I2cBus *i2c_bus, struct I2cDriver *i2c_driver) +{ + x_err_t ret = EOK; + + /*Init the i2c bus */ + i2c_bus->private_data = (void *)NULL; + ret = I2cBusInit(i2c_bus, I2C_BUS_NAME_1); + if (EOK != ret) { + KPrintf("board_i2c_init I2cBusInit error %d\n", ret); + return ERROR; + } + + /*Init the i2c driver*/ + i2c_driver->private_data = (void *)NULL; + ret = I2cDriverInit(i2c_driver, I2C_DRV_NAME_1); + if (EOK != ret) { + KPrintf("board_i2c_init I2cDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the i2c driver to the i2c bus*/ + ret = I2cDriverAttachToBus(I2C_DRV_NAME_1, I2C_BUS_NAME_1); + if (EOK != ret) { + KPrintf("board_i2c_init I2cDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the i2c device to the i2c bus*/ +static int BoardI2cDevBend(void) +{ + x_err_t ret = EOK; + static struct I2cHardwareDevice i2c_device0; + memset(&i2c_device0, 0, sizeof(struct I2cHardwareDevice)); + + i2c_device0.i2c_dev_done = &i2c_dev_done; + + ret = I2cDeviceRegister(&i2c_device0, NONE, I2C_1_DEVICE_NAME_0); + if (EOK != ret) { + KPrintf("board_i2c_init I2cDeviceInit device %s error %d\n", I2C_1_DEVICE_NAME_0, ret); + return ERROR; + } + + ret = I2cDeviceAttachToBus(I2C_1_DEVICE_NAME_0, I2C_BUS_NAME_1); + if (EOK != ret) { + KPrintf("board_i2c_init I2cDeviceAttachToBus device %s error %d\n", I2C_1_DEVICE_NAME_0, ret); + return ERROR; + } + + return ret; +} + +/*BOARD I2C INIT*/ +int Stm32HwI2cInit(void) +{ + static int init_flag = 0; + x_err_t ret = EOK; + + if(init_flag) + { + return ret; + } + init_flag = 1; + + static struct I2cBus i2c_bus; + memset(&i2c_bus, 0, sizeof(struct I2cBus)); + static struct I2cDriver i2c_driver; + memset(&i2c_driver, 0, sizeof(struct I2cDriver)); + +#ifdef BSP_USING_I2C1 + i2c_driver.configure = I2cDrvConfigure; + + ret = BoardI2cBusInit(&i2c_bus, &i2c_driver); + if (EOK != ret) { + KPrintf("board_i2c_Init error ret %u\n", ret); + return ERROR; + } + + ret = BoardI2cDevBend(); + if (EOK != ret) { + KPrintf("board_i2c_Init error ret %u\n", ret); + return ERROR; + } +#endif + + return ret; +} diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom.c similarity index 83% rename from Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM.c rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom.c index c118b2e53..55b3b8395 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom.c @@ -34,7 +34,7 @@ #include "fsl_common.h" #include "fsl_lpi2c.h" -#include "i2c_EEPROM.h" +#include "i2c_eeprom.h" /////////////////////////////EEPROM INIT///////////////////////////////////////// @@ -51,11 +51,11 @@ void I2C_EEPROM_Init() * masterConfig.sdaGlitchFilterWidth_ns = 0; * masterConfig.sclGlitchFilterWidth_ns = 0; */ - LPI2C_MasterGetDefaultConfig ( &masterConfig ); + LPI2C_MasterGetDefaultConfig(&masterConfig); /* Change the default baudrate configuration */ masterConfig.baudRate_Hz = I2C_EEPROM_BAUDRATE; /* Initialize the LPI2C master peripheral */ - LPI2C_MasterInit ( I2C_EEPROM_BASE, &masterConfig, I2C_EEPROM_CLOCK_FREQ ); + LPI2C_MasterInit(I2C_EEPROM_BASE, &masterConfig, I2C_EEPROM_CLOCK_FREQ); } //struct _lpi2c_master_transfer @@ -71,36 +71,36 @@ void I2C_EEPROM_Init() // size_t dataSize; /*!< Number of bytes to transfer. */ //}; -status_t I2C_EEPROM_Write ( LPI2C_Type* base,uint32_t subAdd,uint8_t* dataBuff,uint16_t dataLen ) +status_t I2C_EEPROM_Write(LPI2C_Type* base, uint32_t subAdd, uint8_t* dataBuff, uint16_t dataLen) { // lpi2c_master_transfer_t *xfer = &(handle->xfer); lpi2c_master_transfer_t xfer; status_t status; - xfer.slaveAddress = ( 0xA0>>1 ); + xfer.slaveAddress =(0xA0 >> 1); xfer.direction = kLPI2C_Write; xfer.subaddress = subAdd; xfer.subaddressSize = 0x01; xfer.data = dataBuff; xfer.dataSize = dataLen; xfer.flags = kLPI2C_TransferDefaultFlag; - status = LPI2C_MasterTransferBlocking ( base, &xfer ); + status = LPI2C_MasterTransferBlocking(base, &xfer); return status; } -uint32_t I2C_EEPROM_Read ( LPI2C_Type* base,uint32_t subAdd,uint8_t* dataBuffer, uint16_t dataLen ) +uint32_t I2C_EEPROM_Read(LPI2C_Type* base, uint32_t subAdd, uint8_t* dataBuffer, uint16_t dataLen) { lpi2c_master_transfer_t masterXfer = {0}; status_t reVal = kStatus_Fail; - masterXfer.slaveAddress = ( 0XA0>>1 ); + masterXfer.slaveAddress =(0XA0>>1); masterXfer.direction = kLPI2C_Read; masterXfer.subaddress = subAdd; masterXfer.subaddressSize = 0x01; masterXfer.data = dataBuffer; masterXfer.dataSize = dataLen; masterXfer.flags = kLPI2C_TransferDefaultFlag; - reVal = LPI2C_MasterTransferBlocking ( base, &masterXfer ); + reVal = LPI2C_MasterTransferBlocking(base, &masterXfer); - if ( reVal != kStatus_Success ) + if(reVal != kStatus_Success) { return 1; } @@ -108,5 +108,3 @@ uint32_t I2C_EEPROM_Read ( LPI2C_Type* base,uint32_t subAdd,uint8_t* dataBuffer, return 0; } -///////////////////////////////////////////////////////////////// - diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom.h similarity index 88% rename from Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM.h rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom.h index 13533d417..759b98195 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM.h +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom.h @@ -1,4 +1,3 @@ - #ifndef __I2C_EEPROM_H_ #define __I2C_EEPROM_H_ @@ -22,4 +21,7 @@ void I2C_EEPROM_Init ( void ); status_t I2C_EEPROM_Write ( LPI2C_Type* base,uint32_t subAdd,uint8_t* dataBuff,uint16_t dataLen ); uint32_t I2C_EEPROM_Read ( LPI2C_Type* base,uint32_t subAdd,uint8_t* dataBuff, uint16_t dataLen ); +int eeprom_read(uint8_t *dat); +int eeprom_write(uint8_t *dat); + #endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM_test.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom_test.c similarity index 63% rename from Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM_test.c rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom_test.c index 2a46d8e17..c3383f48c 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_EEPROM_test.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_eeprom_test.c @@ -34,13 +34,18 @@ #include "board.h" #include "fsl_debug_console.h" +#include "fsl_iomuxc.h" + #include "fsl_gpio.h" +#include "connect_i2c.h" #include "fsl_lpi2c.h" -#include "i2c_EEPROM.h" +#include "i2c_eeprom.h" #include "pin_mux.h" #include "clock_config.h" +#include +#include /******************************************************************************* * Definitions @@ -48,76 +53,83 @@ #define i2c_print KPrintf +#define EE_I2C_BUS_NAME I2C_BUS_NAME_1 /* I2C bus name */ +#define EE_I2C_DEV_NAME I2C_1_DEVICE_NAME_0 /* I2C device name */ +#define EE_I2C_DRV_NAME I2C_DRV_NAME_1 /* I2C driver name */ + /******************************************************************************* * Prototypes ******************************************************************************/ /*! * @brief delay a while. */ -void I2C_EEPROM_TEST ( void ); +void I2C_EEPROM_TEST(void); /******************************************************************************* * Variables ******************************************************************************/ -/* The PIN status */ -volatile bool g_pinSet = false; + /******************************************************************************* * Code ******************************************************************************/ +int eeprom_read(uint8_t *dat) +{ + uint32_t ret; + ret = I2C_EEPROM_Read(I2C_EEPROM_BASE, 0, dat, 8); + return ret; +} + + +int eeprom_write(uint8_t *dat) +{ + uint32_t ret; + ret = I2C_EEPROM_Write(I2C_EEPROM_BASE, 0, dat, 8); + return ret; +} + /*! * @brief I2C_EEPROM_TEST: Write and Read */ -void I2C_EEPROM_TEST() +void I2C_EEPROM_TEST(void) { - uint8_t dataBuff[8] = {0}; + uint8_t dat[8] = {0}; - // read eeprom - if ( !I2C_EEPROM_Read ( I2C_EEPROM_BASE, 0, dataBuff, 8 ) ) + if(!I2C_EEPROM_Read(I2C_EEPROM_BASE, 0, dat, 8)) { - i2c_print ( "Read from EEPROM Success!!! dataBuff = %d , %d , %d , %d , %d , %d , %d , %d\r\n", - dataBuff[0], dataBuff[1], dataBuff[2], dataBuff[3], dataBuff[4], dataBuff[5], dataBuff[6], dataBuff[7] ); + i2c_print("Read from EEPROM %d %d %d %d %d %d %d %d\r\n", + dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]); } - //set data - for ( uint8_t i = 0; i < 8; i++ ) + for(uint8_t i = 0; i < 8; i++) { - dataBuff[i] = 8 - i; + dat[i] = 1; } - //write data - if ( !I2C_EEPROM_Write ( I2C_EEPROM_BASE, 0, dataBuff, 8 ) ) + if(!I2C_EEPROM_Write(I2C_EEPROM_BASE, 0, dat, 8)) { - i2c_print ( "Write to EEPROM Success!!! dataBuff = %d , %d , %d , %d , %d , %d , %d , %d\r\n", - dataBuff[0], dataBuff[1], dataBuff[2], dataBuff[3], dataBuff[4], dataBuff[5], dataBuff[6], dataBuff[7] ); + i2c_print("Write to EEPROM %d %d %d %d %d %d %d %d\r\n", + dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]); } - //clear data - memset ( dataBuff, 0, 8 ); - - //read data - if ( !I2C_EEPROM_Read ( I2C_EEPROM_BASE, 0, dataBuff, 8 ) ) + memset(dat, 0, 8); + if(!I2C_EEPROM_Read(I2C_EEPROM_BASE, 0, dat, 8)) { - i2c_print ( "Read from EEPROM Success!!! dataBuff = %d , %d , %d , %d , %d , %d , %d , %d\r\n", - dataBuff[0], dataBuff[1], dataBuff[2], dataBuff[3], dataBuff[4], dataBuff[5], dataBuff[6], dataBuff[7] ); + i2c_print("Read from EEPROM %d %d %d %d %d %d %d %d\r\n", + dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]); } } - -/*! - * @brief Main function - */ -int test_i2c ( void ) +int test_eerpom(void) { + Stm32HwI2cInit(); BOARD_InitI2C1Pins(); - - /* Print a note to terminal. */ - i2c_print ( "\r\n I2C_EEPROM example start ... \r\n" ); I2C_EEPROM_Init(); I2C_EEPROM_TEST(); + return 0; } -SHELL_EXPORT_CMD ( SHELL_CMD_PERMISSION ( 0 ) | SHELL_CMD_TYPE ( SHELL_TYPE_CMD_MAIN ) | SHELL_CMD_PARAM_NUM ( 0 ), - I2cEE, test_i2c, i2c eeprom ); +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)| SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)| SHELL_CMD_PARAM_NUM(0), + eeprom, test_eerpom, i2c eeprom); diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010.c similarity index 96% rename from Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010.c rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010.c index 8f91dc034..d11ddb7ba 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010.c @@ -43,7 +43,7 @@ #include "fsl_common.h" #include "fsl_debug_console.h" #include "fsl_lpi2c.h" -#include "i2c_RTC_RX8010.h" +#include "i2c_rtc_rx8010.h" /////////////////////////////EEPROM INIT///////////////////////////////////////// diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010.h similarity index 72% rename from Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010.h rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010.h index 3f9a2a94d..95cfc52e4 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010.h +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010.h @@ -1,5 +1,7 @@ -#include "fsl_common.h" +#ifndef __I2C_RTC_RX8010_H_ +#define __I2C_RTC_RX8010_H_ +#include "fsl_common.h" /* Macros for the touch touch controller. */ #define I2C_BASE LPI2C1 @@ -9,15 +11,17 @@ /* Clock divider for master lpi2c clock source */ #define LPI2C_CLOCK_SOURCE_DIVIDER (5U) - #define I2C_CLOCK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U)) #define I2C_BAUDRATE 100000U +#define I2C_RTC_ADDR 0x32 +#define I2C_EEPROM_ADDR 0x0 - -void I2C_Init(void); +void I2C_Init(void); status_t I2C_Write(LPI2C_Type *base,uint32_t subAdd,uint8_t *dataBuff,uint16_t dataLen); uint32_t I2C_Read(LPI2C_Type *base,uint32_t subAdd,uint8_t* dataBuff, uint16_t dataLen); +int rx8010_set_time(uint8_t* asc_date); +int rx8010_get_time(void); - +#endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010_test.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010_test.c similarity index 78% rename from Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010_test.c rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010_test.c index f821ac396..32c04c847 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_RTC_RX8010_test.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/i2c_rtc_rx8010_test.c @@ -36,7 +36,7 @@ #include "fsl_debug_console.h" #include "fsl_lpi2c.h" -#include "i2c_RTC_RX8010.h" +#include "i2c_rtc_rx8010.h" #include "pin_mux.h" #include "clock_config.h" @@ -95,6 +95,9 @@ #define BCD_DATA_LEN 20 +// change BIN format to BCD format +#define TO_BCD(_n) (((_n / 10) << 4) | (_n % 10)) + /******************************************************************************* * Prototypes ******************************************************************************/ @@ -133,12 +136,6 @@ uint8_t bcd2bin(uint8_t data) return ret; } -// change BIN format to BCD format -uint8_t bin2bcd(uint8_t dataH, uint8_t dataL) -{ - return (dataH << 4) | dataL; -} - // 8010 initialization int rx8010_init(void) { @@ -202,91 +199,29 @@ int rx8010_init(void) return err; } - // check format and get BCD format date like 2018-06-21 16:29:30 int get_bcd_date(uint8_t* date, uint8_t* bcd_date) { - uint8_t tempBuff[BCD_DATA_LEN] = {0}; - uint8_t temp = 0; - int j = 0; + int i; + int temp_date[6]; - if(( date[0] != '2') - ||(date[1] != '0') - ||(date[4] != '-') - ||(date[7] != '-') - ||(date[10] != ' ') - ||(date[13] != ':') - ||(date[16] != ':')) + if(sscanf(date, "20%2d-%2d-%2d %2d:%2d:%2d", + &temp_date[5], + &temp_date[4], + &temp_date[3], + &temp_date[2], + &temp_date[1], + &temp_date[0]) == EOF) { + rtc_print("i2c %s failed\n", __func__); return -1; } - for(int i = 0; i < BCD_DATA_LEN - 1; i++) + for(i = 0; i < 6; i++) { - if((date[i] >= '0') && (date[i] <= '9')) - { - tempBuff[j] = date[i] - '0'; - j++; - } + bcd_date[i] = TO_BCD(temp_date[i]); } - if(j != 14) - { - return -1; - } - - // year - bcd_date[5] = bin2bcd(tempBuff[2], tempBuff[3]); - - // month - temp = tempBuff[4] * 10 + tempBuff[5]; - - if((temp < 1) || (temp > 12)) - { - return -1; - } - - bcd_date[4] = bin2bcd(tempBuff[4], tempBuff[5]); - - // day - temp = tempBuff[6] * 10 + tempBuff[7]; - - if((temp < 1)||(temp > 31)) - { - return -1; - } - - bcd_date[3] = bin2bcd(tempBuff[6], tempBuff[7]); - - // hour - temp = tempBuff[8] * 10 + tempBuff[9]; - - if((temp < 1)||(temp > 24)) - { - return -1; - } - - bcd_date[2] = bin2bcd(tempBuff[8], tempBuff[9]); - - // minute - temp = tempBuff[10] * 10 + tempBuff[11]; - - if((temp < 1)||(temp > 59)) - { - return -1; - } - - bcd_date[1] = bin2bcd(tempBuff[10], tempBuff[11]); - - // second - temp = tempBuff[12] * 10 + tempBuff[13]; - - if(( temp < 1)||(temp > 59)) - { - return -1; - } - - bcd_date[0] = bin2bcd(tempBuff[12], tempBuff[13]); return 0; } @@ -330,7 +265,7 @@ int rx8010_get_time(void) dateRsul[5] = bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f); dateRsul[6] = bcd2bin(date[RX8010_YEAR - RX8010_SEC]); dateRsul[3] = date[RX8010_WDAY - RX8010_SEC] & 0x7f; - rtc_print("\r\n Read datetime from RX8010: 20%d%d-%d%d-%d%d %d%d:%d%d:%d%d \r\n", + rtc_print("RX8010 Time: 20%d%d-%d%d-%d%d %d%d:%d%d:%d%d\r\n", dateRsul[6]/10, dateRsul[6]%10, dateRsul[5]/10, dateRsul[5]%10, dateRsul[4]/10, dateRsul[4]%10, dateRsul[2]/10, dateRsul[2]%10, dateRsul[1]/10, dateRsul[1]%10, dateRsul[0]/10, dateRsul[0]%10); return 0; @@ -344,13 +279,15 @@ void test_rtc_rx8010(int argc, char *argv[]) if(argc == 2) { - rx8010_set_time(argv[1]); + if(rx8010_set_time(argv[1]) == 0) + { + rx8010_get_time(); + } } else { rx8010_get_time(); } - } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)| SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)| SHELL_CMD_PARAM_NUM(3), diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/MIMXRT1052_features.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/MIMXRT1052_features.h index 7ccb74015..f78522df6 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/MIMXRT1052_features.h +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/MIMXRT1052_features.h @@ -144,6 +144,8 @@ #define FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE (0) /* @brief Remove ALT Clock selection feature. */ #define FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE (1) +/* @brief Conversion control count (related to number of registers HCn and Rn). */ +#define FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT (8) /* ADC_ETC module features */ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_ethernet.h index fa18d0e83..7876dfe6e 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_ethernet.h @@ -63,8 +63,6 @@ /* Exported functions ------------------------------------------------------- */ -void enet_delay(void); - #ifdef __cplusplus } #endif diff --git a/Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_gpio.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_gpio.h similarity index 100% rename from Ubiquitous/XiUOS/board/stm32f407-st-discovery/third_party_driver/include/connect_gpio.h rename to Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_gpio.h diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_i2c.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_i2c.h new file mode 100755 index 000000000..0ffbc7dbd --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_i2c.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_i2c.h +* @brief define stm32f407-st-discovery-board i2c function and struct +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-25 +*/ + +#ifndef CONNECT_I2C_H +#define CONNECT_I2C_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +int Stm32HwI2cInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile new file mode 100755 index 000000000..ec7e13636 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := fsl_lpspi.c lpspi_interrupt.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_lpspi.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_lpspi.c new file mode 100755 index 000000000..82c1270ed --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_lpspi.c @@ -0,0 +1,2099 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_lpspi.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.lpspi" +#endif + +/*! + * @brief Default watermark values. + * + * The default watermarks are set to zero. + */ +enum _lpspi_default_watermarks +{ + kLpspiDefaultTxWatermark = 0, + kLpspiDefaultRxWatermark = 0, +}; + +/*! @brief Typedef for master interrupt handler. */ +typedef void (*lpspi_master_isr_t)(LPSPI_Type *base, lpspi_master_handle_t *handle); + +/*! @brief Typedef for slave interrupt handler. */ +typedef void (*lpspi_slave_isr_t)(LPSPI_Type *base, lpspi_slave_handle_t *handle); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! + * @brief Get instance number for LPSPI module. + * + * @param base LPSPI peripheral base address. + * @return Return the value of LPSPI instance. + */ +uint32_t LPSPI_GetInstance(LPSPI_Type *base); + +/*! + * @brief Configures the LPSPI peripheral chip select polarity. + * + * This function takes in the desired peripheral chip select (Pcs) and it's corresponding desired polarity and + * configures the Pcs signal to operate with the desired characteristic. + * + * @param base LPSPI peripheral address. + * @param pcs The particular peripheral chip select (parameter value is of type lpspi_which_pcs_t) for which we wish to + * apply the active high or active low characteristic. + * @param activeLowOrHigh The setting for either "active high, inactive low (0)" or "active low, inactive high(1)" of + * type lpspi_pcs_polarity_config_t. + */ +static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base, + lpspi_which_pcs_t pcs, + lpspi_pcs_polarity_config_t activeLowOrHigh); + +/*! + * @brief Combine the write data for 1 byte to 4 bytes. + * This is not a public API. + */ +static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint32_t bytesEachWrite, bool isByteSwap); + +/*! + * @brief Separate the read data for 1 byte to 4 bytes. + * This is not a public API. + */ +static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap); + +/*! + * @brief Master fill up the TX FIFO with data. + * This is not a public API. + */ +static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_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. + */ +static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle); + +/*! + * @brief Slave fill up the TX FIFO with data. + * This is not a public API. + */ +static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_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. + */ +static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle); + +/*! + * @brief LPSPI common interrupt handler. + * + * @param handle pointer to s_lpspiHandle which stores the transfer state. + */ +static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/ +static const uint8_t s_baudratePrescaler[] = {1, 2, 4, 8, 16, 32, 64, 128}; + +/*! @brief Pointers to lpspi bases for each instance. */ +static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS; + +/*! @brief Pointers to lpspi IRQ number for each instance. */ +static const IRQn_Type s_lpspiIRQ[] = LPSPI_IRQS; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +/*! @brief Pointers to lpspi clocks for each instance. */ +static const clock_ip_name_t s_lpspiClocks[] = LPSPI_CLOCKS; + +#if defined(LPSPI_PERIPH_CLOCKS) +static const clock_ip_name_t s_LpspiPeriphClocks[] = LPSPI_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/*! @brief Pointers to lpspi handles for each instance. */ +static void *s_lpspiHandle[ARRAY_SIZE(s_lpspiBases)] = {NULL}; + +/*! @brief Pointer to master IRQ handler for each instance. */ +static lpspi_master_isr_t s_lpspiMasterIsr; +/*! @brief Pointer to slave IRQ handler for each instance. */ +static lpspi_slave_isr_t s_lpspiSlaveIsr; +/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ +volatile uint8_t g_lpspiDummyData[ARRAY_SIZE(s_lpspiBases)] = {0}; +/********************************************************************************************************************** + * Code + *********************************************************************************************************************/ +uint32_t LPSPI_GetInstance(LPSPI_Type *base) +{ + uint8_t instance = 0; + + /* Find the instance index from base address mappings. */ + for (instance = 0; instance < ARRAY_SIZE(s_lpspiBases); instance++) + { + if (s_lpspiBases[instance] == base) + { + break; + } + } + + assert(instance < ARRAY_SIZE(s_lpspiBases)); + + return instance; +} + +/*! + * brief Set up the dummy data. + * + * param base LPSPI peripheral address. + * param dummyData Data to be transferred when tx buffer is NULL. + * Note: + * This API has no effect when LPSPI in slave interrupt mode, because driver + * will set the TXMSK bit to 1 if txData is NULL, no data is loaded from transmit + * FIFO and output pin is tristated. + */ +void LPSPI_SetDummyData(LPSPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = LPSPI_GetInstance(base); + g_lpspiDummyData[instance] = dummyData; +} + +/*! + * brief Initializes the LPSPI master. + * + * param base LPSPI peripheral address. + * param masterConfig Pointer to structure lpspi_master_config_t. + * param srcClock_Hz Module source input clock in Hertz + */ +void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz) +{ + assert(masterConfig); + + uint32_t tcrPrescaleValue = 0; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPSPI_GetInstance(base); + /* Enable LPSPI clock */ + CLOCK_EnableClock(s_lpspiClocks[instance]); + +#if defined(LPSPI_PERIPH_CLOCKS) + CLOCK_EnableClock(s_LpspiPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Set LPSPI to master */ + LPSPI_SetMasterSlaveMode(base, kLPSPI_Master); + + /* Set specific PCS to active high or low */ + LPSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); + + /* Set Configuration Register 1 related setting.*/ + base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK | LPSPI_CFGR1_NOSTALL_MASK)) | + LPSPI_CFGR1_OUTCFG(masterConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(masterConfig->pinCfg) | + LPSPI_CFGR1_NOSTALL(0); + + /* Set baudrate and delay times*/ + LPSPI_MasterSetBaudRate(base, masterConfig->baudRate, srcClock_Hz, &tcrPrescaleValue); + + /* Set default watermarks */ + LPSPI_SetFifoWatermarks(base, kLpspiDefaultTxWatermark, kLpspiDefaultRxWatermark); + + /* Set Transmit Command Register*/ + base->TCR = LPSPI_TCR_CPOL(masterConfig->cpol) | LPSPI_TCR_CPHA(masterConfig->cpha) | + LPSPI_TCR_LSBF(masterConfig->direction) | LPSPI_TCR_FRAMESZ(masterConfig->bitsPerFrame - 1) | + LPSPI_TCR_PRESCALE(tcrPrescaleValue) | LPSPI_TCR_PCS(masterConfig->whichPcs); + + LPSPI_Enable(base, true); + + LPSPI_MasterSetDelayTimes(base, masterConfig->pcsToSckDelayInNanoSec, kLPSPI_PcsToSck, srcClock_Hz); + LPSPI_MasterSetDelayTimes(base, masterConfig->lastSckToPcsDelayInNanoSec, kLPSPI_LastSckToPcs, srcClock_Hz); + LPSPI_MasterSetDelayTimes(base, masterConfig->betweenTransferDelayInNanoSec, kLPSPI_BetweenTransfer, srcClock_Hz); + + LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA); +} + +/*! + * brief Sets the lpspi_master_config_t structure to default values. + * + * This API initializes the configuration structure for LPSPI_MasterInit(). + * The initialized structure can remain unchanged in LPSPI_MasterInit(), or can be modified + * before calling the LPSPI_MasterInit(). + * Example: + * code + * lpspi_master_config_t masterConfig; + * LPSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to lpspi_master_config_t structure + */ +void LPSPI_MasterGetDefaultConfig(lpspi_master_config_t *masterConfig) +{ + assert(masterConfig); + + /* Initializes the configure structure to zero. */ + memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->baudRate = 500000; + masterConfig->bitsPerFrame = 8; + masterConfig->cpol = kLPSPI_ClockPolarityActiveHigh; + masterConfig->cpha = kLPSPI_ClockPhaseFirstEdge; + masterConfig->direction = kLPSPI_MsbFirst; + + masterConfig->pcsToSckDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2; + masterConfig->lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2; + masterConfig->betweenTransferDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2; + + masterConfig->whichPcs = kLPSPI_Pcs0; + masterConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow; + + masterConfig->pinCfg = kLPSPI_SdiInSdoOut; + masterConfig->dataOutConfig = kLpspiDataOutRetained; +} + +/*! + * brief LPSPI slave configuration. + * + * param base LPSPI peripheral address. + * param slaveConfig Pointer to a structure lpspi_slave_config_t. + */ +void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig) +{ + assert(slaveConfig); + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPSPI_GetInstance(base); + /* Enable LPSPI clock */ + CLOCK_EnableClock(s_lpspiClocks[instance]); + +#if defined(LPSPI_PERIPH_CLOCKS) + CLOCK_EnableClock(s_LpspiPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + LPSPI_SetMasterSlaveMode(base, kLPSPI_Slave); + + LPSPI_SetOnePcsPolarity(base, slaveConfig->whichPcs, slaveConfig->pcsActiveHighOrLow); + + base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK)) | + LPSPI_CFGR1_OUTCFG(slaveConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(slaveConfig->pinCfg); + + LPSPI_SetFifoWatermarks(base, kLpspiDefaultTxWatermark, kLpspiDefaultRxWatermark); + + base->TCR = LPSPI_TCR_CPOL(slaveConfig->cpol) | LPSPI_TCR_CPHA(slaveConfig->cpha) | + LPSPI_TCR_LSBF(slaveConfig->direction) | LPSPI_TCR_FRAMESZ(slaveConfig->bitsPerFrame - 1); + + /* This operation will set the dummy data for edma transfer, no effect in interrupt way. */ + LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA); + + LPSPI_Enable(base, true); +} + +/*! + * brief Sets the lpspi_slave_config_t structure to default values. + * + * This API initializes the configuration structure for LPSPI_SlaveInit(). + * The initialized structure can remain unchanged in LPSPI_SlaveInit() or can be modified + * before calling the LPSPI_SlaveInit(). + * Example: + * code + * lpspi_slave_config_t slaveConfig; + * LPSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig pointer to lpspi_slave_config_t structure. + */ +void LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t *slaveConfig) +{ + assert(slaveConfig); + + /* Initializes the configure structure to zero. */ + memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->bitsPerFrame = 8; /*!< Bits per frame, minimum 8, maximum 4096.*/ + slaveConfig->cpol = kLPSPI_ClockPolarityActiveHigh; /*!< Clock polarity. */ + slaveConfig->cpha = kLPSPI_ClockPhaseFirstEdge; /*!< Clock phase. */ + slaveConfig->direction = kLPSPI_MsbFirst; /*!< MSB or LSB data shift direction. */ + + slaveConfig->whichPcs = kLPSPI_Pcs0; /*!< Desired Peripheral Chip Select (pcs) */ + slaveConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow; /*!< Desired PCS active high or low */ + + slaveConfig->pinCfg = kLPSPI_SdiInSdoOut; + slaveConfig->dataOutConfig = kLpspiDataOutRetained; +} + +/*! + * brief Restores the LPSPI peripheral to reset state. Note that this function + * sets all registers to reset state. As a result, the LPSPI module can't work after calling + * this API. + * param base LPSPI peripheral address. + */ +void LPSPI_Reset(LPSPI_Type *base) +{ + /* Reset all internal logic and registers, except the Control Register. Remains set until cleared by software.*/ + base->CR |= LPSPI_CR_RST_MASK; + + /* Software reset doesn't reset the CR, so manual reset the FIFOs */ + base->CR |= LPSPI_CR_RRF_MASK | LPSPI_CR_RTF_MASK; + + /* Master logic is not reset and module is disabled.*/ + base->CR = 0x00U; +} + +/*! + * brief De-initializes the LPSPI peripheral. Call this API to disable the LPSPI clock. + * param base LPSPI peripheral address. + */ +void LPSPI_Deinit(LPSPI_Type *base) +{ + /* Reset to default value */ + LPSPI_Reset(base); + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPSPI_GetInstance(base); + /* Enable LPSPI clock */ + CLOCK_DisableClock(s_lpspiClocks[instance]); + +#if defined(LPSPI_PERIPH_CLOCKS) + CLOCK_DisableClock(s_LpspiPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base, + lpspi_which_pcs_t pcs, + lpspi_pcs_polarity_config_t activeLowOrHigh) +{ + uint32_t cfgr1Value = 0; + /* Clear the PCS polarity bit */ + cfgr1Value = base->CFGR1 & ~(1U << (LPSPI_CFGR1_PCSPOL_SHIFT + pcs)); + + /* Configure the PCS polarity bit according to the activeLowOrHigh setting */ + base->CFGR1 = cfgr1Value | ((uint32_t)activeLowOrHigh << (LPSPI_CFGR1_PCSPOL_SHIFT + pcs)); +} + +/*! + * brief Sets the LPSPI baud rate in bits per second. + * + * This function takes in the desired bitsPerSec (baud rate) and calculates the nearest + * possible baud rate without exceeding the desired baud rate and returns the + * calculated baud rate in bits-per-second. It requires the caller to provide + * the frequency of the module source clock (in Hertz). Note that the baud rate + * does not go into effect until the Transmit Control Register (TCR) is programmed + * with the prescale value. Hence, this function returns the prescale tcrPrescaleValue + * parameter for later programming in the TCR. The higher level + * peripheral driver should alert the user of an out of range baud rate input. + * + * Note that the LPSPI module must first be disabled before configuring this. + * Note that the LPSPI module must be configured for master mode before configuring this. + * + * param base LPSPI peripheral address. + * param baudRate_Bps The desired baud rate in bits per second. + * param srcClock_Hz Module source input clock in Hertz. + * param tcrPrescaleValue The TCR prescale value needed to program the TCR. + * return The actual calculated baud rate. This function may also return a "0" if the + * LPSPI is not configured for master mode or if the LPSPI module is not disabled. + */ + +uint32_t LPSPI_MasterSetBaudRate(LPSPI_Type *base, + uint32_t baudRate_Bps, + uint32_t srcClock_Hz, + uint32_t *tcrPrescaleValue) +{ + assert(tcrPrescaleValue); + + /* For master mode configuration only, if slave mode detected, return 0. + * Also, the LPSPI module needs to be disabled first, if enabled, return 0 + */ + if ((!LPSPI_IsMaster(base)) || (base->CR & LPSPI_CR_MEN_MASK)) + { + return 0; + } + + uint32_t prescaler, bestPrescaler; + uint32_t scaler, bestScaler; + uint32_t realBaudrate, bestBaudrate; + uint32_t diff, min_diff; + uint32_t desiredBaudrate = baudRate_Bps; + + /* find combination of prescaler and scaler resulting in baudrate closest to the + * requested value + */ + min_diff = 0xFFFFFFFFU; + + /* Set to maximum divisor value bit settings so that if baud rate passed in is less + * than the minimum possible baud rate, then the SPI will be configured to the lowest + * possible baud rate + */ + bestPrescaler = 7; + bestScaler = 255; + + bestBaudrate = 0; /* required to avoid compilation warning */ + + /* In all for loops, if min_diff = 0, the exit for loop*/ + for (prescaler = 0; (prescaler < 8) && min_diff; prescaler++) + { + for (scaler = 0; (scaler < 256) && min_diff; scaler++) + { + realBaudrate = (srcClock_Hz / (s_baudratePrescaler[prescaler] * (scaler + 2U))); + + /* calculate the baud rate difference based on the conditional statement + * that states that the calculated baud rate must not exceed the desired baud rate + */ + if (desiredBaudrate >= realBaudrate) + { + diff = desiredBaudrate - realBaudrate; + if (min_diff > diff) + { + /* a better match found */ + min_diff = diff; + bestPrescaler = prescaler; + bestScaler = scaler; + bestBaudrate = realBaudrate; + } + } + } + } + + /* Write the best baud rate scalar to the CCR. + * Note, no need to check for error since we've already checked to make sure the module is + * disabled and in master mode. Also, there is a limit on the maximum divider so we will not + * exceed this. + */ + base->CCR = (base->CCR & ~LPSPI_CCR_SCKDIV_MASK) | LPSPI_CCR_SCKDIV(bestScaler); + + /* return the best prescaler value for user to use later */ + *tcrPrescaleValue = bestPrescaler; + + /* return the actual calculated baud rate */ + return bestBaudrate; +} + +/*! + * brief Manually configures a specific LPSPI delay parameter (module must be disabled to + * change the delay values). + * + * This function configures the following: + * SCK to PCS delay, or + * PCS to SCK delay, or + * The configurations must occur between the transfer delay. + * + * The delay names are available in type lpspi_delay_type_t. + * + * The user passes the desired delay along with the delay value. + * This allows the user to directly set the delay values if they have + * pre-calculated them or if they simply wish to manually increment the value. + * + * Note that the LPSPI module must first be disabled before configuring this. + * Note that the LPSPI module must be configured for master mode before configuring this. + * + * param base LPSPI peripheral address. + * param scaler The 8-bit delay value 0x00 to 0xFF (255). + * param whichDelay The desired delay to configure, must be of type lpspi_delay_type_t. + */ +void LPSPI_MasterSetDelayScaler(LPSPI_Type *base, uint32_t scaler, lpspi_delay_type_t whichDelay) +{ + /*These settings are only relevant in master mode */ + switch (whichDelay) + { + case kLPSPI_PcsToSck: + base->CCR = (base->CCR & (~LPSPI_CCR_PCSSCK_MASK)) | LPSPI_CCR_PCSSCK(scaler); + + break; + case kLPSPI_LastSckToPcs: + base->CCR = (base->CCR & (~LPSPI_CCR_SCKPCS_MASK)) | LPSPI_CCR_SCKPCS(scaler); + + break; + case kLPSPI_BetweenTransfer: + base->CCR = (base->CCR & (~LPSPI_CCR_DBT_MASK)) | LPSPI_CCR_DBT(scaler); + + break; + default: + assert(false); + break; + } +} + +/*! + * brief Calculates the delay based on the desired delay input in nanoseconds (module must be + * disabled to change the delay values). + * + * This function calculates the values for the following: + * SCK to PCS delay, or + * PCS to SCK delay, or + * The configurations must occur between the transfer delay. + * + * The delay names are available in type lpspi_delay_type_t. + * + * The user passes the desired delay and the desired delay value in + * nano-seconds. The function calculates the value needed for the desired delay parameter + * and returns the actual calculated delay because 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. It is up to the higher level + * peripheral driver to alert the user of an out of range delay input. + * + * Note that the LPSPI module must be configured for master mode before configuring this. And note that + * the delayTime = LPSPI_clockSource / (PRESCALE * Delay_scaler). + * + * param base LPSPI peripheral address. + * param delayTimeInNanoSec The desired delay value in nano-seconds. + * param whichDelay The desired delay to configuration, which must be of type lpspi_delay_type_t. + * param srcClock_Hz Module source input clock in Hertz. + * return actual Calculated delay value in nano-seconds. + */ +uint32_t LPSPI_MasterSetDelayTimes(LPSPI_Type *base, + uint32_t delayTimeInNanoSec, + lpspi_delay_type_t whichDelay, + uint32_t srcClock_Hz) +{ + uint64_t realDelay, bestDelay; + uint32_t scaler, bestScaler; + uint32_t diff, min_diff; + uint64_t initialDelayNanoSec; + uint32_t clockDividedPrescaler; + + /* For delay between transfer, an additional scaler value is needed */ + uint32_t additionalScaler = 0; + + /*As the RM note, the LPSPI baud rate clock is itself divided by the PRESCALE setting, which can vary between + * transfers.*/ + clockDividedPrescaler = + srcClock_Hz / s_baudratePrescaler[(base->TCR & LPSPI_TCR_PRESCALE_MASK) >> LPSPI_TCR_PRESCALE_SHIFT]; + + /* Find combination of prescaler and scaler resulting in the delay closest to the requested value.*/ + min_diff = 0xFFFFFFFFU; + + /* Initialize scaler to max value to generate the max delay */ + bestScaler = 0xFFU; + + /* Calculate the initial (min) delay and maximum possible delay based on the specific delay as + * the delay divisors are slightly different based on which delay we are configuring. + */ + if (whichDelay == kLPSPI_BetweenTransfer) + { + /* First calculate the initial, default delay, note min delay is 2 clock cycles. Due to large size of + calculated values (uint64_t), we need to break up the calculation into several steps to ensure + accurate calculated results + */ + initialDelayNanoSec = 1000000000U; + initialDelayNanoSec *= 2U; + initialDelayNanoSec /= clockDividedPrescaler; + + /* Calculate the maximum delay */ + bestDelay = 1000000000U; + bestDelay *= 257U; /* based on DBT+2, or 255 + 2 */ + bestDelay /= clockDividedPrescaler; + + additionalScaler = 1U; + } + else + { + /* First calculate the initial, default delay, min delay is 1 clock cycle. Due to large size of calculated + values (uint64_t), we need to break up the calculation into several steps to ensure accurate calculated + results. + */ + initialDelayNanoSec = 1000000000U; + initialDelayNanoSec /= clockDividedPrescaler; + + /* Calculate the maximum delay */ + bestDelay = 1000000000U; + bestDelay *= 256U; /* based on SCKPCS+1 or PCSSCK+1, or 255 + 1 */ + bestDelay /= clockDividedPrescaler; + + additionalScaler = 0; + } + + /* If the initial, default delay is already greater than the desired delay, then + * set the delay to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ + if (initialDelayNanoSec >= delayTimeInNanoSec) + { + LPSPI_MasterSetDelayScaler(base, 0, whichDelay); + return initialDelayNanoSec; + } + + /* If min_diff = 0, the exit for loop */ + for (scaler = 0; (scaler < 256U) && min_diff; scaler++) + { + /* Calculate the real delay value as we cycle through the scaler values. + Due to large size of calculated values (uint64_t), we need to break up the + calculation into several steps to ensure accurate calculated results + */ + realDelay = 1000000000U; + realDelay *= (scaler + 1 + additionalScaler); + realDelay /= clockDividedPrescaler; + + /* calculate the delay difference based on the conditional statement + * that states that the calculated delay must not be less then the desired delay + */ + if (realDelay >= delayTimeInNanoSec) + { + diff = realDelay - delayTimeInNanoSec; + if (min_diff > diff) + { + /* a better match found */ + min_diff = diff; + bestScaler = scaler; + bestDelay = realDelay; + } + } + } + + /* write the best scaler value for the delay */ + LPSPI_MasterSetDelayScaler(base, bestScaler, whichDelay); + + /* return the actual calculated delay value (in ns) */ + return bestDelay; +} + +/*Transactional APIs -- Master*/ + +/*! + * brief Initializes the LPSPI master handle. + * + * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a + * specified LPSPI instance, call this API once to get the initialized handle. + + * param base LPSPI peripheral address. + * param handle LPSPI handle pointer to lpspi_master_handle_t. + * param callback DSPI callback. + * param userData callback function parameter. + */ +void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base, + lpspi_master_handle_t *handle, + lpspi_master_transfer_callback_t callback, + void *userData) +{ + assert(handle); + + /* Zero the handle. */ + memset(handle, 0, sizeof(*handle)); + + s_lpspiHandle[LPSPI_GetInstance(base)] = handle; + + /* Set irq handler. */ + s_lpspiMasterIsr = LPSPI_MasterTransferHandleIRQ; + + handle->callback = callback; + handle->userData = userData; +} + +/*! + * brief Check the argument for transfer . + * + * param transfer the transfer struct to be used. + * param bitPerFrame The bit size of one frame. + * param bytePerFrame The byte size of one frame. + * return Return true for right and false for wrong. + */ +bool LPSPI_CheckTransferArgument(lpspi_transfer_t *transfer, uint32_t bitsPerFrame, uint32_t bytesPerFrame) +{ + assert(transfer); + + /* If the transfer count is zero, then return immediately.*/ + if (transfer->dataSize == 0) + { + return false; + } + + /* If both send buffer and receive buffer is null */ + if ((!(transfer->txData)) && (!(transfer->rxData))) + { + return false; + } + + /*The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4 . + *For bytesPerFrame greater than 4 situation: + *the transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4 , + *otherwise , the transfer data size can be integer multiples of bytesPerFrame. + */ + if (bytesPerFrame <= 4) + { + if ((transfer->dataSize % bytesPerFrame) != 0) + { + return false; + } + } + else + { + if ((bytesPerFrame % 4U) != 0) + { + if (transfer->dataSize != bytesPerFrame) + { + return false; + } + } + else + { + if ((transfer->dataSize % bytesPerFrame) != 0) + { + return false; + } + } + } + + return true; +} + +/*! + * brief LPSPI master transfer data using a polling method. + * + * This function transfers data using a polling method. This is a blocking function, which does not return until all + * transfers have been + * completed. + * + * Note: + * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. + * For bytesPerFrame greater than 4: + * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4. + * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. + * + * param base LPSPI peripheral address. + * param transfer pointer to lpspi_transfer_t structure. + * return status of status_t. + */ +status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer) +{ + assert(transfer); + + uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1; + uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8; + uint32_t temp = 0U; + uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)]; + + if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame)) + { + return kStatus_InvalidArgument; + } + + /* Check that LPSPI is not busy.*/ + if (LPSPI_GetStatusFlags(base) & kLPSPI_ModuleBusyFlag) + { + return kStatus_LPSPI_Busy; + } + + uint8_t *txData = transfer->txData; + uint8_t *rxData = transfer->rxData; + uint32_t txRemainingByteCount = transfer->dataSize; + uint32_t rxRemainingByteCount = transfer->dataSize; + + uint8_t bytesEachWrite; + uint8_t bytesEachRead; + + uint32_t readData = 0; + uint32_t wordToSend = + ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24); + + /*The TX and RX FIFO sizes are always the same*/ + uint32_t fifoSize = LPSPI_GetRxFifoSize(base); + + uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT; + + bool isPcsContinuous = (bool)(transfer->configFlags & kLPSPI_MasterPcsContinuous); + bool isRxMask = false; + bool isByteSwap = (bool)(transfer->configFlags & kLPSPI_MasterByteSwap); + + LPSPI_FlushFifo(base, true, true); + LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag); + + if (!rxData) + { + isRxMask = true; + } + + LPSPI_Enable(base, false); + base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK); + /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */ + temp = base->CFGR1; + temp &= LPSPI_CFGR1_PINCFG_MASK; + if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) + { + if (!txData) + { + base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK; + } + /* The 3-wire mode can't send and receive data at the same time. */ + if ((txData) && (rxData)) + { + return kStatus_InvalidArgument; + } + } + LPSPI_Enable(base, true); + + base->TCR = + (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) | + LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_PCS(whichPcs); + + if (bytesPerFrame <= 4) + { + bytesEachWrite = bytesPerFrame; + bytesEachRead = bytesPerFrame; + } + else + { + bytesEachWrite = 4; + bytesEachRead = 4; + } + + /*Write the TX data until txRemainingByteCount is equal to 0 */ + while (txRemainingByteCount > 0) + { + if (txRemainingByteCount < bytesEachWrite) + { + bytesEachWrite = txRemainingByteCount; + } + + /*Wait until TX FIFO is not full*/ + while (LPSPI_GetTxFifoCount(base) == fifoSize) + { + } + + if (txData) + { + wordToSend = LPSPI_CombineWriteData(txData, bytesEachWrite, isByteSwap); + txData += bytesEachWrite; + } + + LPSPI_WriteData(base, wordToSend); + txRemainingByteCount -= bytesEachWrite; + + /*Check whether there is RX data in RX FIFO . Read out the RX data so that the RX FIFO would not overrun.*/ + if (rxData) + { + while (LPSPI_GetRxFifoCount(base)) + { + readData = LPSPI_ReadData(base); + if (rxRemainingByteCount < bytesEachRead) + { + bytesEachRead = rxRemainingByteCount; + } + + LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap); + rxData += bytesEachRead; + + rxRemainingByteCount -= bytesEachRead; + } + } + } + + /* After write all the data in TX FIFO , should write the TCR_CONTC to 0 to de-assert the PCS. Note that TCR + * register also use the TX FIFO. + */ + while ((LPSPI_GetTxFifoCount(base) == fifoSize)) + { + } + base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK)); + + /*Read out the RX data in FIFO*/ + if (rxData) + { + while (rxRemainingByteCount > 0) + { + while (LPSPI_GetRxFifoCount(base)) + { + readData = LPSPI_ReadData(base); + + if (rxRemainingByteCount < bytesEachRead) + { + bytesEachRead = rxRemainingByteCount; + } + + LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap); + rxData += bytesEachRead; + + rxRemainingByteCount -= bytesEachRead; + } + } + } + else + { + /* If no RX buffer, then transfer is not complete until transfer complete flag sets */ + while (!(LPSPI_GetStatusFlags(base) & kLPSPI_TransferCompleteFlag)) + { + } + } + + return kStatus_Success; +} + +/*! + * brief LPSPI master transfer data using an interrupt method. + * + * This function transfers data using an interrupt method. This is a non-blocking function, which returns right away. + * When all data + * is transferred, the callback function is called. + * + * Note: + * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. + * For bytesPerFrame greater than 4: + * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4. + * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + * param transfer pointer to lpspi_transfer_t structure. + * return status of status_t. + */ +status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer) +{ + assert(handle); + assert(transfer); + + uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1; + uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8; + uint32_t temp = 0U; + uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)]; + + if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame)) + { + return kStatus_InvalidArgument; + } + + /* Check that we're not busy.*/ + if (handle->state == kLPSPI_Busy) + { + return kStatus_LPSPI_Busy; + } + + handle->state = kLPSPI_Busy; + + bool isRxMask = false; + + uint8_t txWatermark; + + uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT; + + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->txRemainingByteCount = transfer->dataSize; + handle->rxRemainingByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; + + handle->writeTcrInIsr = false; + + handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3) / 4); + handle->readRegRemainingTimes = handle->writeRegRemainingTimes; + + handle->txBuffIfNull = + ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24); + + /*The TX and RX FIFO sizes are always the same*/ + handle->fifoSize = LPSPI_GetRxFifoSize(base); + + handle->isPcsContinuous = (bool)(transfer->configFlags & kLPSPI_MasterPcsContinuous); + handle->isByteSwap = (bool)(transfer->configFlags & kLPSPI_MasterByteSwap); + + /*Set the RX and TX watermarks to reduce the ISR times.*/ + if (handle->fifoSize > 1) + { + txWatermark = 1; + handle->rxWatermark = handle->fifoSize - 2; + } + else + { + txWatermark = 0; + handle->rxWatermark = 0; + } + + LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark); + + LPSPI_Enable(base, false); + /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */ + base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK); + /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */ + temp = base->CFGR1; + temp &= LPSPI_CFGR1_PINCFG_MASK; + if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) + { + if (!handle->txData) + { + base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK; + } + /* The 3-wire mode can't send and receive data at the same time. */ + if ((handle->txData) && (handle->rxData)) + { + return kStatus_InvalidArgument; + } + } + LPSPI_Enable(base, true); + + /*Flush FIFO , clear status , disable all the inerrupts.*/ + LPSPI_FlushFifo(base, true, true); + LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag); + LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable); + + /* If there is not rxData , can mask the receive data (receive data is not stored in receive FIFO). + * For master transfer , we'd better not masked the transmit data in TCR since the transfer flow is hard to + * controlled by software.*/ + if (handle->rxData == NULL) + { + isRxMask = true; + handle->rxRemainingByteCount = 0; + } + + base->TCR = + (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) | + LPSPI_TCR_CONT(handle->isPcsContinuous) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | + LPSPI_TCR_PCS(whichPcs); + + /*Calculate the bytes for write/read the TX/RX register each time*/ + if (bytesPerFrame <= 4) + { + handle->bytesEachWrite = bytesPerFrame; + handle->bytesEachRead = bytesPerFrame; + } + else + { + handle->bytesEachWrite = 4; + handle->bytesEachRead = 4; + } + + /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX , + * and you should also enable the INTMUX interupt in your application. + */ + EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]); + + /*TCR is also shared the FIFO , so wait for TCR written.*/ + while (LPSPI_GetTxFifoCount(base) != 0) + { + } + /*Fill up the TX data in FIFO */ + LPSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ + if (handle->rxData) + { + /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there + *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark. + */ + if ((handle->readRegRemainingTimes) <= handle->rxWatermark) + { + base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->readRegRemainingTimes - 1); + } + + LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable); + } + else + { + LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable); + } + + return kStatus_Success; +} + +static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle) +{ + assert(handle); + + uint32_t wordToSend = 0; + + /* Make sure the difference in remaining TX and RX byte counts does not exceed FIFO depth + * and that the number of TX FIFO entries does not exceed the FIFO depth. + * But no need to make the protection if there is no rxData. + */ + while ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)) && + (((handle->readRegRemainingTimes - handle->writeRegRemainingTimes) < handle->fifoSize) || + (handle->rxData == NULL))) + { + if (handle->txRemainingByteCount < handle->bytesEachWrite) + { + handle->bytesEachWrite = handle->txRemainingByteCount; + } + + if (handle->txData) + { + wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap); + handle->txData += handle->bytesEachWrite; + } + else + { + wordToSend = handle->txBuffIfNull; + } + + /*Write the word to TX register*/ + LPSPI_WriteData(base, wordToSend); + + /*Decrease the write TX register times.*/ + --handle->writeRegRemainingTimes; + + /*Decrease the remaining TX byte count.*/ + handle->txRemainingByteCount -= handle->bytesEachWrite; + + if (handle->txRemainingByteCount == 0) + { + /* If PCS is continuous, update TCR to de-assert PCS */ + if (handle->isPcsContinuous) + { + /* Only write to the TCR if the FIFO has room */ + if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize))) + { + base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK)); + handle->writeTcrInIsr = false; + } + /* Else, set a global flag to tell the ISR to do write to the TCR */ + else + { + handle->writeTcrInIsr = true; + } + } + break; + } + } +} + +static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle) +{ + assert(handle); + + /* Disable interrupt requests*/ + LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable); + + handle->state = kLPSPI_Idle; + + if (handle->callback) + { + handle->callback(base, handle, kStatus_Success, handle->userData); + } +} + +/*! + * brief Gets the master transfer remaining bytes. + * + * This function gets the master transfer remaining bytes. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + * param count Number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ +status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count) +{ + assert(handle); + + if (!count) + { + return kStatus_InvalidArgument; + } + + /* Catch when there is not an active transfer. */ + if (handle->state != kLPSPI_Busy) + { + *count = 0; + return kStatus_NoTransferInProgress; + } + + size_t remainingByte; + + if (handle->rxData) + { + remainingByte = handle->rxRemainingByteCount; + } + else + { + remainingByte = handle->txRemainingByteCount; + } + + *count = handle->totalByteCount - remainingByte; + + return kStatus_Success; +} + +/*! + * brief LPSPI master abort transfer which uses an interrupt method. + * + * This function aborts a transfer which uses an interrupt method. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + */ +void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle) +{ + assert(handle); + + /* Disable interrupt requests*/ + LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable); + + LPSPI_Reset(base); + + handle->state = kLPSPI_Idle; + handle->txRemainingByteCount = 0; + handle->rxRemainingByteCount = 0; +} + +/*! + * brief LPSPI Master IRQ handler function. + * + * This function processes the LPSPI transmit and receive IRQ. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + */ +void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle) +{ + assert(handle); + + uint32_t readData; + + if (handle->rxData != NULL) + { + if (handle->rxRemainingByteCount) + { + /* First, disable the interrupts to avoid potentially triggering another interrupt + * while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll + * re-enable the interrupts based on the LPSPI state after reading out the FIFO. + */ + LPSPI_DisableInterrupts(base, kLPSPI_RxInterruptEnable); + + while ((LPSPI_GetRxFifoCount(base)) && (handle->rxRemainingByteCount)) + { + /*Read out the data*/ + readData = LPSPI_ReadData(base); + + /*Decrease the read RX register times.*/ + --handle->readRegRemainingTimes; + + if (handle->rxRemainingByteCount < handle->bytesEachRead) + { + handle->bytesEachRead = handle->rxRemainingByteCount; + } + + LPSPI_SeparateReadData(handle->rxData, readData, handle->bytesEachRead, handle->isByteSwap); + handle->rxData += handle->bytesEachRead; + + /*Decrease the remaining RX byte count.*/ + handle->rxRemainingByteCount -= handle->bytesEachRead; + } + + /* Re-enable the interrupts only if rxCount indicates there is more data to receive, + * else we may get a spurious interrupt. + * */ + if (handle->rxRemainingByteCount) + { + /* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */ + LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable); + } + } + + /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there + *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark. + */ + if ((handle->readRegRemainingTimes) <= (handle->rxWatermark)) + { + base->FCR = + (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | + LPSPI_FCR_RXWATER((handle->readRegRemainingTimes > 1) ? (handle->readRegRemainingTimes - 1U) : (0U)); + } + } + + if (handle->txRemainingByteCount) + { + LPSPI_MasterTransferFillUpTxFifo(base, handle); + } + else + { + if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize))) + { + if ((handle->isPcsContinuous) && (handle->writeTcrInIsr)) + { + base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK)); + handle->writeTcrInIsr = false; + } + } + } + + if ((handle->txRemainingByteCount == 0) && (handle->rxRemainingByteCount == 0) && (!handle->writeTcrInIsr)) + { + /* If no RX buffer, then transfer is not complete until transfer complete flag sets */ + if (handle->rxData == NULL) + { + if (LPSPI_GetStatusFlags(base) & kLPSPI_TransferCompleteFlag) + { + /* Complete the transfer and disable the interrupts */ + LPSPI_MasterTransferComplete(base, handle); + } + else + { + LPSPI_EnableInterrupts(base, kLPSPI_TransferCompleteInterruptEnable); + LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable); + } + } + else + { + /* Complete the transfer and disable the interrupts */ + LPSPI_MasterTransferComplete(base, handle); + } + } +} + +/*Transactional APIs -- Slave*/ +/*! + * brief Initializes the LPSPI slave handle. + * + * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a + * specified LPSPI instance, call this API once to get the initialized handle. + * + * param base LPSPI peripheral address. + * param handle LPSPI handle pointer to lpspi_slave_handle_t. + * param callback DSPI callback. + * param userData callback function parameter. + */ +void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base, + lpspi_slave_handle_t *handle, + lpspi_slave_transfer_callback_t callback, + void *userData) +{ + assert(handle); + + /* Zero the handle. */ + memset(handle, 0, sizeof(*handle)); + + s_lpspiHandle[LPSPI_GetInstance(base)] = handle; + + /* Set irq handler. */ + s_lpspiSlaveIsr = LPSPI_SlaveTransferHandleIRQ; + + handle->callback = callback; + handle->userData = userData; +} + +/*! + * brief LPSPI slave transfer data using an interrupt method. + * + * This function transfer data using an interrupt method. This is a non-blocking function, which returns right away. + * When all data + * is transferred, the callback function is called. + * + * Note: + * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. + * For bytesPerFrame greater than 4: + * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4. + * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + * param transfer pointer to lpspi_transfer_t structure. + * return status of status_t. + */ +status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer) +{ + assert(handle); + assert(transfer); + + uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1; + uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8; + uint32_t temp = 0U; + + if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame)) + { + return kStatus_InvalidArgument; + } + + /* Check that we're not busy.*/ + if (handle->state == kLPSPI_Busy) + { + return kStatus_LPSPI_Busy; + } + handle->state = kLPSPI_Busy; + + bool isRxMask = false; + bool isTxMask = false; + + uint32_t whichPcs = (transfer->configFlags & LPSPI_SLAVE_PCS_MASK) >> LPSPI_SLAVE_PCS_SHIFT; + + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->txRemainingByteCount = transfer->dataSize; + handle->rxRemainingByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; + + handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3) / 4); + handle->readRegRemainingTimes = handle->writeRegRemainingTimes; + + /*The TX and RX FIFO sizes are always the same*/ + handle->fifoSize = LPSPI_GetRxFifoSize(base); + + handle->isByteSwap = (bool)(transfer->configFlags & kLPSPI_SlaveByteSwap); + + /*Set the RX and TX watermarks to reduce the ISR times.*/ + uint8_t txWatermark; + if (handle->fifoSize > 1) + { + txWatermark = 1; + handle->rxWatermark = handle->fifoSize - 2; + } + else + { + txWatermark = 0; + handle->rxWatermark = 0; + } + LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark); + + /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */ + temp = base->CFGR1; + temp &= LPSPI_CFGR1_PINCFG_MASK; + if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) + { + if (!handle->txData) + { + LPSPI_Enable(base, false); + base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK; + LPSPI_Enable(base, true); + } + /* The 3-wire mode can't send and receive data at the same time. */ + if ((handle->txData) && (handle->rxData)) + { + return kStatus_InvalidArgument; + } + } + + /*Flush FIFO , clear status , disable all the inerrupts.*/ + LPSPI_FlushFifo(base, true, true); + LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag); + LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable); + + /*If there is not rxData , can mask the receive data (receive data is not stored in receive FIFO).*/ + if (handle->rxData == NULL) + { + isRxMask = true; + handle->rxRemainingByteCount = 0; + } + + /*If there is not txData , can mask the transmit data (no data is loaded from transmit FIFO and output pin + * is tristated). + */ + if (handle->txData == NULL) + { + isTxMask = true; + handle->txRemainingByteCount = 0; + } + + base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | + LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) | + LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_TXMSK(isTxMask) | + LPSPI_TCR_PCS(whichPcs); + + /*Calculate the bytes for write/read the TX/RX register each time*/ + if (bytesPerFrame <= 4) + { + handle->bytesEachWrite = bytesPerFrame; + handle->bytesEachRead = bytesPerFrame; + } + else + { + handle->bytesEachWrite = 4; + handle->bytesEachRead = 4; + } + + /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX , + * and you should also enable the INTMUX interupt in your application. + */ + EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]); + + /*TCR is also shared the FIFO , so wait for TCR written.*/ + while (LPSPI_GetTxFifoCount(base) != 0) + { + } + + /*Fill up the TX data in FIFO */ + if (handle->txData) + { + LPSPI_SlaveTransferFillUpTxFifo(base, handle); + } + + /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ + if (handle->rxData) + { + /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there + *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark. + */ + if ((handle->readRegRemainingTimes) <= handle->rxWatermark) + { + base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->readRegRemainingTimes - 1); + } + + LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable); + } + else + { + LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable); + } + + if (handle->rxData) + { + /* RX FIFO overflow request enable */ + LPSPI_EnableInterrupts(base, kLPSPI_ReceiveErrorInterruptEnable); + } + if (handle->txData) + { + /* TX FIFO underflow request enable */ + LPSPI_EnableInterrupts(base, kLPSPI_TransmitErrorInterruptEnable); + } + + return kStatus_Success; +} + +static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle) +{ + assert(handle); + + uint32_t wordToSend = 0; + + while (LPSPI_GetTxFifoCount(base) < (handle->fifoSize)) + { + if (handle->txRemainingByteCount < handle->bytesEachWrite) + { + handle->bytesEachWrite = handle->txRemainingByteCount; + } + + wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap); + handle->txData += handle->bytesEachWrite; + + /*Decrease the remaining TX byte count.*/ + handle->txRemainingByteCount -= handle->bytesEachWrite; + + /*Write the word to TX register*/ + LPSPI_WriteData(base, wordToSend); + + if (handle->txRemainingByteCount == 0) + { + break; + } + } +} + +static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle) +{ + assert(handle); + + status_t status = 0; + + /* Disable interrupt requests*/ + LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable); + + if (handle->state == kLPSPI_Error) + { + status = kStatus_LPSPI_Error; + } + else + { + status = kStatus_Success; + } + + handle->state = kLPSPI_Idle; + + if (handle->callback) + { + handle->callback(base, handle, status, handle->userData); + } +} + +/*! + * brief Gets the slave transfer remaining bytes. + * + * This function gets the slave transfer remaining bytes. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + * param count Number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ +status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count) +{ + assert(handle); + + if (!count) + { + return kStatus_InvalidArgument; + } + + /* Catch when there is not an active transfer. */ + if (handle->state != kLPSPI_Busy) + { + *count = 0; + return kStatus_NoTransferInProgress; + } + + size_t remainingByte; + + if (handle->rxData) + { + remainingByte = handle->rxRemainingByteCount; + } + else + { + remainingByte = handle->txRemainingByteCount; + } + + *count = handle->totalByteCount - remainingByte; + + return kStatus_Success; +} + +/*! + * brief LPSPI slave aborts a transfer which uses an interrupt method. + * + * This function aborts a transfer which uses an interrupt method. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + */ +void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle) +{ + assert(handle); + + /* Disable interrupt requests*/ + LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable); + + LPSPI_Reset(base); + + handle->state = kLPSPI_Idle; + handle->txRemainingByteCount = 0; + handle->rxRemainingByteCount = 0; +} + +/*! + * brief LPSPI Slave IRQ handler function. + * + * This function processes the LPSPI transmit and receives an IRQ. + * + * param base LPSPI peripheral address. + * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + */ +void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle) +{ + assert(handle); + + uint32_t readData; /* variable to store word read from RX FIFO */ + uint32_t wordToSend; /* variable to store word to write to TX FIFO */ + + if (handle->rxData != NULL) + { + if (handle->rxRemainingByteCount > 0) + { + while (LPSPI_GetRxFifoCount(base)) + { + /*Read out the data*/ + readData = LPSPI_ReadData(base); + + /*Decrease the read RX register times.*/ + --handle->readRegRemainingTimes; + + if (handle->rxRemainingByteCount < handle->bytesEachRead) + { + handle->bytesEachRead = handle->rxRemainingByteCount; + } + + LPSPI_SeparateReadData(handle->rxData, readData, handle->bytesEachRead, handle->isByteSwap); + handle->rxData += handle->bytesEachRead; + + /*Decrease the remaining RX byte count.*/ + handle->rxRemainingByteCount -= handle->bytesEachRead; + + if ((handle->txRemainingByteCount > 0) && (handle->txData != NULL)) + { + if (handle->txRemainingByteCount < handle->bytesEachWrite) + { + handle->bytesEachWrite = handle->txRemainingByteCount; + } + + wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap); + handle->txData += handle->bytesEachWrite; + + /*Decrease the remaining TX byte count.*/ + handle->txRemainingByteCount -= handle->bytesEachWrite; + + /*Write the word to TX register*/ + LPSPI_WriteData(base, wordToSend); + } + + if (handle->rxRemainingByteCount == 0) + { + break; + } + } + } + + /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there + *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark. + */ + if ((handle->readRegRemainingTimes) <= (handle->rxWatermark)) + { + base->FCR = + (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | + LPSPI_FCR_RXWATER((handle->readRegRemainingTimes > 1) ? (handle->readRegRemainingTimes - 1U) : (0U)); + } + } + else if ((handle->txRemainingByteCount) && (handle->txData != NULL)) + { + LPSPI_SlaveTransferFillUpTxFifo(base, handle); + } + else + { + __NOP(); + } + + if ((handle->txRemainingByteCount == 0) && (handle->rxRemainingByteCount == 0)) + { + /* If no RX buffer, then transfer is not complete until transfer complete flag sets and the TX FIFO empty*/ + if (handle->rxData == NULL) + { + if ((LPSPI_GetStatusFlags(base) & kLPSPI_FrameCompleteFlag) && (LPSPI_GetTxFifoCount(base) == 0)) + { + /* Complete the transfer and disable the interrupts */ + LPSPI_SlaveTransferComplete(base, handle); + } + else + { + LPSPI_ClearStatusFlags(base, kLPSPI_FrameCompleteFlag); + LPSPI_EnableInterrupts(base, kLPSPI_FrameCompleteInterruptEnable); + LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable); + } + } + else + { + /* Complete the transfer and disable the interrupts */ + LPSPI_SlaveTransferComplete(base, handle); + } + } + + /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ + if ((LPSPI_GetStatusFlags(base) & kLPSPI_TransmitErrorFlag) && (base->IER & LPSPI_IER_TEIE_MASK)) + { + LPSPI_ClearStatusFlags(base, kLPSPI_TransmitErrorFlag); + /* Change state to error and clear flag */ + if (handle->txData) + { + handle->state = kLPSPI_Error; + } + handle->errorCount++; + } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ + if ((LPSPI_GetStatusFlags(base) & kLPSPI_ReceiveErrorFlag) && (base->IER & LPSPI_IER_REIE_MASK)) + { + LPSPI_ClearStatusFlags(base, kLPSPI_ReceiveErrorFlag); + /* Change state to error and clear flag */ + if (handle->txData) + { + handle->state = kLPSPI_Error; + } + handle->errorCount++; + } +} + +static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint32_t bytesEachWrite, bool isByteSwap) +{ + assert(txData); + + uint32_t wordToSend = 0; + + switch (bytesEachWrite) + { + case 1: + wordToSend = *txData; + ++txData; + break; + + case 2: + if (!isByteSwap) + { + wordToSend = *txData; + ++txData; + wordToSend |= (unsigned)(*txData) << 8U; + ++txData; + } + else + { + wordToSend = (unsigned)(*txData) << 8U; + ++txData; + wordToSend |= *txData; + ++txData; + } + + break; + + case 3: + if (!isByteSwap) + { + wordToSend = *txData; + ++txData; + wordToSend |= (unsigned)(*txData) << 8U; + ++txData; + wordToSend |= (unsigned)(*txData) << 16U; + ++txData; + } + else + { + wordToSend = (unsigned)(*txData) << 16U; + ++txData; + wordToSend |= (unsigned)(*txData) << 8U; + ++txData; + wordToSend |= *txData; + ++txData; + } + break; + + case 4: + if (!isByteSwap) + { + wordToSend = *txData; + ++txData; + wordToSend |= (unsigned)(*txData) << 8U; + ++txData; + wordToSend |= (unsigned)(*txData) << 16U; + ++txData; + wordToSend |= (unsigned)(*txData) << 24U; + ++txData; + } + else + { + wordToSend = (unsigned)(*txData) << 24U; + ++txData; + wordToSend |= (unsigned)(*txData) << 16U; + ++txData; + wordToSend |= (unsigned)(*txData) << 8U; + ++txData; + wordToSend |= *txData; + ++txData; + } + break; + + default: + assert(false); + break; + } + return wordToSend; +} + +static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap) +{ + assert(rxData); + + switch (bytesEachRead) + { + case 1: + *rxData = readData; + ++rxData; + break; + + case 2: + if (!isByteSwap) + { + *rxData = readData; + ++rxData; + *rxData = readData >> 8; + ++rxData; + } + else + { + *rxData = readData >> 8; + ++rxData; + *rxData = readData; + ++rxData; + } + break; + + case 3: + if (!isByteSwap) + { + *rxData = readData; + ++rxData; + *rxData = readData >> 8; + ++rxData; + *rxData = readData >> 16; + ++rxData; + } + else + { + *rxData = readData >> 16; + ++rxData; + *rxData = readData >> 8; + ++rxData; + *rxData = readData; + ++rxData; + } + break; + + case 4: + if (!isByteSwap) + { + *rxData = readData; + ++rxData; + *rxData = readData >> 8; + ++rxData; + *rxData = readData >> 16; + ++rxData; + *rxData = readData >> 24; + ++rxData; + } + else + { + *rxData = readData >> 24; + ++rxData; + *rxData = readData >> 16; + ++rxData; + *rxData = readData >> 8; + ++rxData; + *rxData = readData; + ++rxData; + } + break; + + default: + assert(false); + break; + } +} + +static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param) +{ + if (LPSPI_IsMaster(base)) + { + s_lpspiMasterIsr(base, (lpspi_master_handle_t *)param); + } + else + { + s_lpspiSlaveIsr(base, (lpspi_slave_handle_t *)param); + } +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} + +#if defined(LPSPI0) +void LPSPI0_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[0]); + LPSPI_CommonIRQHandler(LPSPI0, s_lpspiHandle[0]); +} +#endif + +#if defined(LPSPI1) +void LPSPI1_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[1]); + LPSPI_CommonIRQHandler(LPSPI1, s_lpspiHandle[1]); +} +#endif + +#if defined(LPSPI2) +void LPSPI2_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[2]); + LPSPI_CommonIRQHandler(LPSPI2, s_lpspiHandle[2]); +} +#endif + +#if defined(LPSPI3) +void LPSPI3_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[3]); + LPSPI_CommonIRQHandler(LPSPI3, s_lpspiHandle[3]); +} +#endif + +#if defined(LPSPI4) +void LPSPI4_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[4]); + LPSPI_CommonIRQHandler(LPSPI4, s_lpspiHandle[4]); +} +#endif + +#if defined(LPSPI5) +void LPSPI5_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[5]); + LPSPI_CommonIRQHandler(LPSPI5, s_lpspiHandle[5]); +} +#endif + +#if defined(DMA__LPSPI0) +void DMA_SPI0_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI0)]); + LPSPI_CommonIRQHandler(DMA__LPSPI0, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI0)]); +} +#endif + +#if defined(DMA__LPSPI1) +void DMA_SPI1_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI1)]); + LPSPI_CommonIRQHandler(DMA__LPSPI1, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI1)]); +} +#endif +#if defined(DMA__LPSPI2) +void DMA_SPI2_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI2)]); + LPSPI_CommonIRQHandler(DMA__LPSPI2, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI2)]); +} +#endif + +#if defined(DMA__LPSPI3) +void DMA_SPI3_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI3)]); + LPSPI_CommonIRQHandler(DMA__LPSPI3, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI3)]); +} +#endif + +#if defined(ADMA__LPSPI0) +void ADMA_SPI0_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI0)]); + LPSPI_CommonIRQHandler(ADMA__LPSPI0, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI0)]); +} +#endif + +#if defined(ADMA__LPSPI1) +void ADMA_SPI1_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI1)]); + LPSPI_CommonIRQHandler(ADMA__LPSPI1, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI1)]); +} +#endif +#if defined(ADMA__LPSPI2) +void ADMA_SPI2_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI2)]); + LPSPI_CommonIRQHandler(ADMA__LPSPI2, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI2)]); +} +#endif + +#if defined(ADMA__LPSPI3) +void ADMA_SPI3_INT_DriverIRQHandler(void) +{ + assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI3)]); + LPSPI_CommonIRQHandler(ADMA__LPSPI3, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI3)]); +} +#endif diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_lpspi.h b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_lpspi.h new file mode 100755 index 000000000..b3b9c0925 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/fsl_lpspi.h @@ -0,0 +1,1109 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _FSL_LPSPI_H_ +#define _FSL_LPSPI_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup lpspi_driver + * @{ + */ + +/********************************************************************************************************************** + * Definitions + *********************************************************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief LPSPI driver version 2.0.3. */ +#define FSL_LPSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) +/*@}*/ + +#ifndef LPSPI_DUMMY_DATA +/*! @brief LPSPI dummy data if no Tx data.*/ +#define LPSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for tx if there is not txData. */ +#endif + +/*! @brief Global variable for dummy data value setting. */ +extern volatile uint8_t g_lpspiDummyData[]; + +/*! @brief Status for the LPSPI driver.*/ +enum _lpspi_status +{ + kStatus_LPSPI_Busy = MAKE_STATUS(kStatusGroup_LPSPI, 0), /*!< LPSPI transfer is busy.*/ + kStatus_LPSPI_Error = MAKE_STATUS(kStatusGroup_LPSPI, 1), /*!< LPSPI driver error. */ + kStatus_LPSPI_Idle = MAKE_STATUS(kStatusGroup_LPSPI, 2), /*!< LPSPI is idle.*/ + kStatus_LPSPI_OutOfRange = MAKE_STATUS(kStatusGroup_LPSPI, 3) /*!< LPSPI transfer out Of range. */ +}; + +/*! @brief LPSPI status flags in SPIx_SR register.*/ +enum _lpspi_flags +{ + kLPSPI_TxDataRequestFlag = LPSPI_SR_TDF_MASK, /*!< Transmit data flag */ + kLPSPI_RxDataReadyFlag = LPSPI_SR_RDF_MASK, /*!< Receive data flag */ + kLPSPI_WordCompleteFlag = LPSPI_SR_WCF_MASK, /*!< Word Complete flag */ + kLPSPI_FrameCompleteFlag = LPSPI_SR_FCF_MASK, /*!< Frame Complete flag */ + kLPSPI_TransferCompleteFlag = LPSPI_SR_TCF_MASK, /*!< Transfer Complete flag */ + kLPSPI_TransmitErrorFlag = LPSPI_SR_TEF_MASK, /*!< Transmit Error flag (FIFO underrun) */ + kLPSPI_ReceiveErrorFlag = LPSPI_SR_REF_MASK, /*!< Receive Error flag (FIFO overrun) */ + kLPSPI_DataMatchFlag = LPSPI_SR_DMF_MASK, /*!< Data Match flag */ + kLPSPI_ModuleBusyFlag = LPSPI_SR_MBF_MASK, /*!< Module Busy flag */ + kLPSPI_AllStatusFlag = (LPSPI_SR_TDF_MASK | LPSPI_SR_RDF_MASK | LPSPI_SR_WCF_MASK | LPSPI_SR_FCF_MASK | + LPSPI_SR_TCF_MASK | LPSPI_SR_TEF_MASK | LPSPI_SR_REF_MASK | LPSPI_SR_DMF_MASK | + LPSPI_SR_MBF_MASK) /*!< Used for clearing all w1c status flags */ +}; + +/*! @brief LPSPI interrupt source.*/ +enum _lpspi_interrupt_enable +{ + kLPSPI_TxInterruptEnable = LPSPI_IER_TDIE_MASK, /*!< Transmit data interrupt enable */ + kLPSPI_RxInterruptEnable = LPSPI_IER_RDIE_MASK, /*!< Receive data interrupt enable */ + kLPSPI_WordCompleteInterruptEnable = LPSPI_IER_WCIE_MASK, /*!< Word complete interrupt enable */ + kLPSPI_FrameCompleteInterruptEnable = LPSPI_IER_FCIE_MASK, /*!< Frame complete interrupt enable */ + kLPSPI_TransferCompleteInterruptEnable = LPSPI_IER_TCIE_MASK, /*!< Transfer complete interrupt enable */ + kLPSPI_TransmitErrorInterruptEnable = LPSPI_IER_TEIE_MASK, /*!< Transmit error interrupt enable(FIFO underrun)*/ + kLPSPI_ReceiveErrorInterruptEnable = LPSPI_IER_REIE_MASK, /*!< Receive Error interrupt enable (FIFO overrun) */ + kLPSPI_DataMatchInterruptEnable = LPSPI_IER_DMIE_MASK, /*!< Data Match interrupt enable */ + kLPSPI_AllInterruptEnable = + (LPSPI_IER_TDIE_MASK | LPSPI_IER_RDIE_MASK | LPSPI_IER_WCIE_MASK | LPSPI_IER_FCIE_MASK | LPSPI_IER_TCIE_MASK | + LPSPI_IER_TEIE_MASK | LPSPI_IER_REIE_MASK | LPSPI_IER_DMIE_MASK) /*!< All above interrupts enable.*/ +}; + +/*! @brief LPSPI DMA source.*/ +enum _lpspi_dma_enable +{ + kLPSPI_TxDmaEnable = LPSPI_DER_TDDE_MASK, /*!< Transmit data DMA enable */ + kLPSPI_RxDmaEnable = LPSPI_DER_RDDE_MASK /*!< Receive data DMA enable */ +}; + +/*! @brief LPSPI master or slave mode configuration.*/ +typedef enum _lpspi_master_slave_mode +{ + kLPSPI_Master = 1U, /*!< LPSPI peripheral operates in master mode.*/ + kLPSPI_Slave = 0U /*!< LPSPI peripheral operates in slave mode.*/ +} lpspi_master_slave_mode_t; + +/*! @brief LPSPI Peripheral Chip Select (PCS) configuration (which PCS to configure).*/ +typedef enum _lpspi_which_pcs_config +{ + kLPSPI_Pcs0 = 0U, /*!< PCS[0] */ + kLPSPI_Pcs1 = 1U, /*!< PCS[1] */ + kLPSPI_Pcs2 = 2U, /*!< PCS[2] */ + kLPSPI_Pcs3 = 3U /*!< PCS[3] */ +} lpspi_which_pcs_t; + +/*! @brief LPSPI Peripheral Chip Select (PCS) Polarity configuration.*/ +typedef enum _lpspi_pcs_polarity_config +{ + kLPSPI_PcsActiveHigh = 1U, /*!< PCS Active High (idles low) */ + kLPSPI_PcsActiveLow = 0U /*!< PCS Active Low (idles high) */ +} lpspi_pcs_polarity_config_t; + +/*! @brief LPSPI Peripheral Chip Select (PCS) Polarity.*/ +enum _lpspi_pcs_polarity +{ + kLPSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kLPSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kLPSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kLPSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kLPSPI_PcsAllActiveLow = 0xFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ +}; + +/*! @brief LPSPI clock polarity configuration.*/ +typedef enum _lpspi_clock_polarity +{ + kLPSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high LPSPI clock (idles low)*/ + kLPSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low LPSPI clock (idles high)*/ +} lpspi_clock_polarity_t; + +/*! @brief LPSPI clock phase configuration.*/ +typedef enum _lpspi_clock_phase +{ + kLPSPI_ClockPhaseFirstEdge = 0U, /*!< CPHA=0. Data is captured on the leading edge of the SCK and changed on the + following edge.*/ + kLPSPI_ClockPhaseSecondEdge = 1U /*!< CPHA=1. Data is changed on the leading edge of the SCK and captured on the + following edge.*/ +} lpspi_clock_phase_t; + +/*! @brief LPSPI data shifter direction options.*/ +typedef enum _lpspi_shift_direction +{ + kLPSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ + kLPSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ +} lpspi_shift_direction_t; + +/*! @brief LPSPI Host Request select configuration. */ +typedef enum _lpspi_host_request_select +{ + kLPSPI_HostReqExtPin = 0U, /*!< Host Request is an ext pin. */ + kLPSPI_HostReqInternalTrigger = 1U /*!< Host Request is an internal trigger. */ +} lpspi_host_request_select_t; + +/*! @brief LPSPI Match configuration options. */ +typedef enum _lpspi_match_config +{ + kLPSI_MatchDisabled = 0x0U, /*!< LPSPI Match Disabled. */ + kLPSI_1stWordEqualsM0orM1 = 0x2U, /*!< LPSPI Match Enabled. */ + kLPSI_AnyWordEqualsM0orM1 = 0x3U, /*!< LPSPI Match Enabled. */ + kLPSI_1stWordEqualsM0and2ndWordEqualsM1 = 0x4U, /*!< LPSPI Match Enabled. */ + kLPSI_AnyWordEqualsM0andNxtWordEqualsM1 = 0x5U, /*!< LPSPI Match Enabled. */ + kLPSI_1stWordAndM1EqualsM0andM1 = 0x6U, /*!< LPSPI Match Enabled. */ + kLPSI_AnyWordAndM1EqualsM0andM1 = 0x7U, /*!< LPSPI Match Enabled. */ +} lpspi_match_config_t; + +/*! @brief LPSPI pin (SDO and SDI) configuration. */ +typedef enum _lpspi_pin_config +{ + kLPSPI_SdiInSdoOut = 0U, /*!< LPSPI SDI input, SDO output. */ + kLPSPI_SdiInSdiOut = 1U, /*!< LPSPI SDI input, SDI output. */ + kLPSPI_SdoInSdoOut = 2U, /*!< LPSPI SDO input, SDO output. */ + kLPSPI_SdoInSdiOut = 3U /*!< LPSPI SDO input, SDI output. */ +} lpspi_pin_config_t; + +/*! @brief LPSPI data output configuration. */ +typedef enum _lpspi_data_out_config +{ + kLpspiDataOutRetained = 0U, /*!< Data out retains last value when chip select is de-asserted */ + kLpspiDataOutTristate = 1U /*!< Data out is tristated when chip select is de-asserted */ +} lpspi_data_out_config_t; + +/*! @brief LPSPI transfer width configuration. */ +typedef enum _lpspi_transfer_width +{ + kLPSPI_SingleBitXfer = 0U, /*!< 1-bit shift at a time, data out on SDO, in on SDI (normal mode) */ + kLPSPI_TwoBitXfer = 1U, /*!< 2-bits shift out on SDO/SDI and in on SDO/SDI */ + kLPSPI_FourBitXfer = 2U /*!< 4-bits shift out on SDO/SDI/PCS[3:2] and in on SDO/SDI/PCS[3:2] */ +} lpspi_transfer_width_t; + +/*! @brief LPSPI delay type selection.*/ +typedef enum _lpspi_delay_type +{ + kLPSPI_PcsToSck = 1U, /*!< PCS-to-SCK delay. */ + kLPSPI_LastSckToPcs, /*!< Last SCK edge to PCS delay. */ + kLPSPI_BetweenTransfer /*!< Delay between transfers. */ +} lpspi_delay_type_t; + +#define LPSPI_MASTER_PCS_SHIFT (4U) /*!< LPSPI master PCS shift macro , internal used. */ +#define LPSPI_MASTER_PCS_MASK (0xF0U) /*!< LPSPI master PCS shift macro , internal used. */ + +/*! @brief Use this enumeration for LPSPI master transfer configFlags. */ +enum _lpspi_transfer_config_flag_for_master +{ + kLPSPI_MasterPcs0 = 0U << LPSPI_MASTER_PCS_SHIFT, /*!< LPSPI master transfer use PCS0 signal */ + kLPSPI_MasterPcs1 = 1U << LPSPI_MASTER_PCS_SHIFT, /*!< LPSPI master transfer use PCS1 signal */ + kLPSPI_MasterPcs2 = 2U << LPSPI_MASTER_PCS_SHIFT, /*!< LPSPI master transfer use PCS2 signal */ + kLPSPI_MasterPcs3 = 3U << LPSPI_MASTER_PCS_SHIFT, /*!< LPSPI master transfer use PCS3 signal */ + + kLPSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous */ + + kLPSPI_MasterByteSwap = + 1U << 22 /*!< Is master swap the byte. + * For example, when want to send data 1 2 3 4 5 6 7 8 (suppose you set + * lpspi_shift_direction_t to MSB). + * 1. If you set bitPerFrame = 8 , no matter the kLPSPI_MasterByteSwapyou flag is used + * or not, the waveform is 1 2 3 4 5 6 7 8. + * 2. If you set bitPerFrame = 16 : + * (1) the waveform is 2 1 4 3 6 5 8 7 if you do not use the kLPSPI_MasterByteSwap flag. + * (2) the waveform is 1 2 3 4 5 6 7 8 if you use the kLPSPI_MasterByteSwap flag. + * 3. If you set bitPerFrame = 32 : + * (1) the waveform is 4 3 2 1 8 7 6 5 if you do not use the kLPSPI_MasterByteSwap flag. + * (2) the waveform is 1 2 3 4 5 6 7 8 if you use the kLPSPI_MasterByteSwap flag. + */ +}; + +#define LPSPI_SLAVE_PCS_SHIFT (4U) /*!< LPSPI slave PCS shift macro , internal used. */ +#define LPSPI_SLAVE_PCS_MASK (0xF0U) /*!< LPSPI slave PCS shift macro , internal used. */ + +/*! @brief Use this enumeration for LPSPI slave transfer configFlags. */ +enum _lpspi_transfer_config_flag_for_slave +{ + kLPSPI_SlavePcs0 = 0U << LPSPI_SLAVE_PCS_SHIFT, /*!< LPSPI slave transfer use PCS0 signal */ + kLPSPI_SlavePcs1 = 1U << LPSPI_SLAVE_PCS_SHIFT, /*!< LPSPI slave transfer use PCS1 signal */ + kLPSPI_SlavePcs2 = 2U << LPSPI_SLAVE_PCS_SHIFT, /*!< LPSPI slave transfer use PCS2 signal */ + kLPSPI_SlavePcs3 = 3U << LPSPI_SLAVE_PCS_SHIFT, /*!< LPSPI slave transfer use PCS3 signal */ + + kLPSPI_SlaveByteSwap = + 1U << 22 /*!< Is slave swap the byte. + * For example, when want to send data 1 2 3 4 5 6 7 8 (suppose you set + * lpspi_shift_direction_t to MSB). + * 1. If you set bitPerFrame = 8 , no matter the kLPSPI_SlaveByteSwap flag is used + * or not, the waveform is 1 2 3 4 5 6 7 8. + * 2. If you set bitPerFrame = 16 : + * (1) the waveform is 2 1 4 3 6 5 8 7 if you do not use the kLPSPI_SlaveByteSwap flag. + * (2) the waveform is 1 2 3 4 5 6 7 8 if you use the kLPSPI_SlaveByteSwap flag. + * 3. If you set bitPerFrame = 32 : + * (1) the waveform is 4 3 2 1 8 7 6 5 if you do not use the kLPSPI_SlaveByteSwap flag. + * (2) the waveform is 1 2 3 4 5 6 7 8 if you use the kLPSPI_SlaveByteSwap flag. + */ +}; + +/*! @brief LPSPI transfer state, which is used for LPSPI transactional API state machine. */ +enum _lpspi_transfer_state +{ + kLPSPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver. */ + kLPSPI_Busy, /*!< Transfer queue is not finished. */ + kLPSPI_Error /*!< Transfer error. */ +}; + +/*! @brief LPSPI master configuration structure.*/ +typedef struct _lpspi_master_config +{ + uint32_t baudRate; /*!< Baud Rate for LPSPI. */ + uint32_t bitsPerFrame; /*!< Bits per frame, minimum 8, maximum 4096.*/ + lpspi_clock_polarity_t cpol; /*!< Clock polarity. */ + lpspi_clock_phase_t cpha; /*!< Clock phase. */ + lpspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ + + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds, setting to 0 sets the minimum delay. + It sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time in nanoseconds, setting to 0 sets the minimum + delay. It sets the boundary value if out of range.*/ + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time with nanoseconds, setting to 0 sets the + minimum delay. It sets the boundary value if out of range.*/ + + lpspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (PCS). */ + lpspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low */ + + lpspi_pin_config_t pinCfg; /*!< Configures which pins are used for input and output data + *during single bit transfers.*/ + + lpspi_data_out_config_t dataOutConfig; /*!< Configures if the output data is tristated + * between accesses (LPSPI_PCS is negated). */ +} lpspi_master_config_t; + +/*! @brief LPSPI slave configuration structure.*/ +typedef struct _lpspi_slave_config +{ + uint32_t bitsPerFrame; /*!< Bits per frame, minimum 8, maximum 4096.*/ + lpspi_clock_polarity_t cpol; /*!< Clock polarity. */ + lpspi_clock_phase_t cpha; /*!< Clock phase. */ + lpspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ + + lpspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs) */ + lpspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low */ + + lpspi_pin_config_t pinCfg; /*!< Configures which pins are used for input and output data + *during single bit transfers.*/ + + lpspi_data_out_config_t dataOutConfig; /*!< Configures if the output data is tristated + * between accesses (LPSPI_PCS is negated). */ +} lpspi_slave_config_t; + +/*! + * @brief Forward declaration of the _lpspi_master_handle typedefs. + */ +typedef struct _lpspi_master_handle lpspi_master_handle_t; + +/*! + * @brief Forward declaration of the _lpspi_slave_handle typedefs. + */ +typedef struct _lpspi_slave_handle lpspi_slave_handle_t; + +/*! + * @brief Master completion callback function pointer type. + * + * @param base LPSPI peripheral address. + * @param handle Pointer to the handle for the LPSPI master. + * @param status Success or error code describing whether the transfer is completed. + * @param userData Arbitrary pointer-dataSized value passed from the application. + */ +typedef void (*lpspi_master_transfer_callback_t)(LPSPI_Type *base, + lpspi_master_handle_t *handle, + status_t status, + void *userData); + +/*! + * @brief Slave completion callback function pointer type. + * + * @param base LPSPI peripheral address. + * @param handle Pointer to the handle for the LPSPI slave. + * @param status Success or error code describing whether the transfer is completed. + * @param userData Arbitrary pointer-dataSized value passed from the application. + */ +typedef void (*lpspi_slave_transfer_callback_t)(LPSPI_Type *base, + lpspi_slave_handle_t *handle, + status_t status, + void *userData); + +/*! @brief LPSPI master/slave transfer structure.*/ +typedef struct _lpspi_transfer +{ + uint8_t *txData; /*!< Send buffer. */ + uint8_t *rxData; /*!< Receive buffer. */ + volatile size_t dataSize; /*!< Transfer bytes. */ + + uint32_t configFlags; /*!< Transfer transfer configuration flags. Set from _lpspi_transfer_config_flag_for_master if + the transfer is used for master or _lpspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ +} lpspi_transfer_t; + +/*! @brief LPSPI master transfer handle structure used for transactional API. */ +struct _lpspi_master_handle +{ + volatile bool isPcsContinuous; /*!< Is PCS continuous in transfer. */ + volatile bool writeTcrInIsr; /*!< A flag that whether should write TCR in ISR. */ + + volatile bool isByteSwap; /*!< A flag that whether should byte swap. */ + + volatile uint8_t fifoSize; /*!< FIFO dataSize. */ + + volatile uint8_t rxWatermark; /*!< Rx watermark. */ + + volatile uint8_t bytesEachWrite; /*!< Bytes for each write TDR. */ + volatile uint8_t bytesEachRead; /*!< Bytes for each read RDR. */ + + uint8_t *volatile txData; /*!< Send buffer. */ + uint8_t *volatile rxData; /*!< Receive buffer. */ + volatile size_t txRemainingByteCount; /*!< Number of bytes remaining to send.*/ + volatile size_t rxRemainingByteCount; /*!< Number of bytes remaining to receive.*/ + + volatile uint32_t writeRegRemainingTimes; /*!< Write TDR register remaining times. */ + volatile uint32_t readRegRemainingTimes; /*!< Read RDR register remaining times. */ + + uint32_t totalByteCount; /*!< Number of transfer bytes*/ + + uint32_t txBuffIfNull; /*!< Used if the txData is NULL. */ + + volatile uint8_t state; /*!< LPSPI transfer state , _lpspi_transfer_state.*/ + + lpspi_master_transfer_callback_t callback; /*!< Completion callback. */ + void *userData; /*!< Callback user data. */ +}; + +/*! @brief LPSPI slave transfer handle structure used for transactional API. */ +struct _lpspi_slave_handle +{ + volatile bool isByteSwap; /*!< A flag that whether should byte swap. */ + + volatile uint8_t fifoSize; /*!< FIFO dataSize. */ + + volatile uint8_t rxWatermark; /*!< Rx watermark. */ + + volatile uint8_t bytesEachWrite; /*!< Bytes for each write TDR. */ + volatile uint8_t bytesEachRead; /*!< Bytes for each read RDR. */ + + uint8_t *volatile txData; /*!< Send buffer. */ + uint8_t *volatile rxData; /*!< Receive buffer. */ + + volatile size_t txRemainingByteCount; /*!< Number of bytes remaining to send.*/ + volatile size_t rxRemainingByteCount; /*!< Number of bytes remaining to receive.*/ + + volatile uint32_t writeRegRemainingTimes; /*!< Write TDR register remaining times. */ + volatile uint32_t readRegRemainingTimes; /*!< Read RDR register remaining times. */ + + uint32_t totalByteCount; /*!< Number of transfer bytes*/ + + volatile uint8_t state; /*!< LPSPI transfer state , _lpspi_transfer_state.*/ + + volatile uint32_t errorCount; /*!< Error count for slave transfer.*/ + + lpspi_slave_transfer_callback_t callback; /*!< Completion callback. */ + void *userData; /*!< Callback user data. */ +}; + +/********************************************************************************************************************** + * API + *********************************************************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /*_cplusplus*/ + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initializes the LPSPI master. + * + * @param base LPSPI peripheral address. + * @param masterConfig Pointer to structure lpspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz + */ +void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz); + +/*! + * @brief Sets the lpspi_master_config_t structure to default values. + * + * This API initializes the configuration structure for LPSPI_MasterInit(). + * The initialized structure can remain unchanged in LPSPI_MasterInit(), or can be modified + * before calling the LPSPI_MasterInit(). + * Example: + * @code + * lpspi_master_config_t masterConfig; + * LPSPI_MasterGetDefaultConfig(&masterConfig); + * @endcode + * @param masterConfig pointer to lpspi_master_config_t structure + */ +void LPSPI_MasterGetDefaultConfig(lpspi_master_config_t *masterConfig); + +/*! + * @brief LPSPI slave configuration. + * + * @param base LPSPI peripheral address. + * @param slaveConfig Pointer to a structure lpspi_slave_config_t. + */ +void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig); + +/*! + * @brief Sets the lpspi_slave_config_t structure to default values. + * + * This API initializes the configuration structure for LPSPI_SlaveInit(). + * The initialized structure can remain unchanged in LPSPI_SlaveInit() or can be modified + * before calling the LPSPI_SlaveInit(). + * Example: + * @code + * lpspi_slave_config_t slaveConfig; + * LPSPI_SlaveGetDefaultConfig(&slaveConfig); + * @endcode + * @param slaveConfig pointer to lpspi_slave_config_t structure. + */ +void LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t *slaveConfig); + +/*! + * @brief De-initializes the LPSPI peripheral. Call this API to disable the LPSPI clock. + * @param base LPSPI peripheral address. + */ +void LPSPI_Deinit(LPSPI_Type *base); + +/*! + * @brief Restores the LPSPI peripheral to reset state. Note that this function + * sets all registers to reset state. As a result, the LPSPI module can't work after calling + * this API. + * @param base LPSPI peripheral address. + */ +void LPSPI_Reset(LPSPI_Type *base); + +/*! + * @brief Enables the LPSPI peripheral and sets the MCR MDIS to 0. + * + * @param base LPSPI peripheral address. + * @param enable Pass true to enable module, false to disable module. + */ +static inline void LPSPI_Enable(LPSPI_Type *base, bool enable) +{ + if (enable) + { + base->CR |= LPSPI_CR_MEN_MASK; + } + else + { + base->CR &= ~LPSPI_CR_MEN_MASK; + } +} + +/*! + *@} + */ + +/*! + * @name Status + * @{ + */ + +/*! + * @brief Gets the LPSPI status flag state. + * @param base LPSPI peripheral address. + * @return The LPSPI status(in SR register). + */ +static inline uint32_t LPSPI_GetStatusFlags(LPSPI_Type *base) +{ + return (base->SR); +} + +/*! + * @brief Gets the LPSPI Tx FIFO size. + * @param base LPSPI peripheral address. + * @return The LPSPI Tx FIFO size. + */ +static inline uint32_t LPSPI_GetTxFifoSize(LPSPI_Type *base) +{ + return (1U << ((base->PARAM & LPSPI_PARAM_TXFIFO_MASK) >> LPSPI_PARAM_TXFIFO_SHIFT)); +} + +/*! + * @brief Gets the LPSPI Rx FIFO size. + * @param base LPSPI peripheral address. + * @return The LPSPI Rx FIFO size. + */ +static inline uint32_t LPSPI_GetRxFifoSize(LPSPI_Type *base) +{ + return (1U << ((base->PARAM & LPSPI_PARAM_RXFIFO_MASK) >> LPSPI_PARAM_RXFIFO_SHIFT)); +} + +/*! + * @brief Gets the LPSPI Tx FIFO count. + * @param base LPSPI peripheral address. + * @return The number of words in the transmit FIFO. + */ +static inline uint32_t LPSPI_GetTxFifoCount(LPSPI_Type *base) +{ + return ((base->FSR & LPSPI_FSR_TXCOUNT_MASK) >> LPSPI_FSR_TXCOUNT_SHIFT); +} + +/*! + * @brief Gets the LPSPI Rx FIFO count. + * @param base LPSPI peripheral address. + * @return The number of words in the receive FIFO. + */ +static inline uint32_t LPSPI_GetRxFifoCount(LPSPI_Type *base) +{ + return ((base->FSR & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT); +} + +/*! + * @brief Clears the LPSPI status flag. + * + * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the + * desired status flag bit to clear. The list of status flags is defined in the _lpspi_flags. + * Example usage: + * @code + * LPSPI_ClearStatusFlags(base, kLPSPI_TxDataRequestFlag|kLPSPI_RxDataReadyFlag); + * @endcode + * + * @param base LPSPI peripheral address. + * @param statusFlags The status flag used from type _lpspi_flags. + */ +static inline void LPSPI_ClearStatusFlags(LPSPI_Type *base, uint32_t statusFlags) +{ + base->SR = statusFlags; /*!< The status flags are cleared by writing 1 (w1c).*/ +} + +/*! + *@} + */ + +/*! + * @name Interrupts + * @{ + */ + +/*! + * @brief Enables the LPSPI interrupts. + * + * This function configures the various interrupt masks of the LPSPI. The parameters are base and an interrupt mask. + * Note that, for Tx fill and Rx FIFO drain requests, enabling the interrupt request disables the DMA request. + * + * @code + * LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable ); + * @endcode + * + * @param base LPSPI peripheral address. + * @param mask The interrupt mask; Use the enum _lpspi_interrupt_enable. + */ +static inline void LPSPI_EnableInterrupts(LPSPI_Type *base, uint32_t mask) +{ + base->IER |= mask; +} + +/*! + * @brief Disables the LPSPI interrupts. + * + * @code + * LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable ); + * @endcode + * + * @param base LPSPI peripheral address. + * @param mask The interrupt mask; Use the enum _lpspi_interrupt_enable. + */ +static inline void LPSPI_DisableInterrupts(LPSPI_Type *base, uint32_t mask) +{ + base->IER &= ~mask; +} + +/*! + *@} + */ + +/*! + * @name DMA Control + * @{ + */ + +/*! + * @brief Enables the LPSPI DMA request. + * + * This function configures the Rx and Tx DMA mask of the LPSPI. The parameters are base and a DMA mask. + * @code + * LPSPI_EnableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable); + * @endcode + * + * @param base LPSPI peripheral address. + * @param mask The interrupt mask; Use the enum _lpspi_dma_enable. + */ +static inline void LPSPI_EnableDMA(LPSPI_Type *base, uint32_t mask) +{ + base->DER |= mask; +} + +/*! + * @brief Disables the LPSPI DMA request. + * + * This function configures the Rx and Tx DMA mask of the LPSPI. The parameters are base and a DMA mask. + * @code + * SPI_DisableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable); + * @endcode + * + * @param base LPSPI peripheral address. + * @param mask The interrupt mask; Use the enum _lpspi_dma_enable. + */ +static inline void LPSPI_DisableDMA(LPSPI_Type *base, uint32_t mask) +{ + base->DER &= ~mask; +} + +/*! + * @brief Gets the LPSPI Transmit Data Register address for a DMA operation. + * + * This function gets the LPSPI Transmit Data Register address because this value is needed + * for the DMA operation. + * This function can be used for either master or slave mode. + * + * @param base LPSPI peripheral address. + * @return The LPSPI Transmit Data Register address. + */ +static inline uint32_t LPSPI_GetTxRegisterAddress(LPSPI_Type *base) +{ + return (uint32_t) & (base->TDR); +} + +/*! + * @brief Gets the LPSPI Receive Data Register address for a DMA operation. + * + * This function gets the LPSPI Receive Data Register address because this value is needed + * for the DMA operation. + * This function can be used for either master or slave mode. + * + * @param base LPSPI peripheral address. + * @return The LPSPI Receive Data Register address. + */ +static inline uint32_t LPSPI_GetRxRegisterAddress(LPSPI_Type *base) +{ + return (uint32_t) & (base->RDR); +} + +/*! + *@} + */ + +/*! + * @name Bus Operations + * @{ + */ + +/*! + * @brief Check the argument for transfer . + * + * @param transfer the transfer struct to be used. + * @param bitPerFrame The bit size of one frame. + * @param bytePerFrame The byte size of one frame. + * @return Return true for right and false for wrong. + */ +bool LPSPI_CheckTransferArgument(lpspi_transfer_t *transfer, uint32_t bitsPerFrame, uint32_t bytesPerFrame); + +/*! + * @brief Configures the LPSPI for either master or slave. + * + * Note that the CFGR1 should only be written when the LPSPI is disabled (LPSPIx_CR_MEN = 0). + * + * @param base LPSPI peripheral address. + * @param mode Mode setting (master or slave) of type lpspi_master_slave_mode_t. + */ +static inline void LPSPI_SetMasterSlaveMode(LPSPI_Type *base, lpspi_master_slave_mode_t mode) +{ + base->CFGR1 = (base->CFGR1 & (~LPSPI_CFGR1_MASTER_MASK)) | LPSPI_CFGR1_MASTER(mode); +} + +/*! + * @brief Returns whether the LPSPI module is in master mode. + * + * @param base LPSPI peripheral address. + * @return Returns true if the module is in master mode or false if the module is in slave mode. + */ +static inline bool LPSPI_IsMaster(LPSPI_Type *base) +{ + return (bool)((base->CFGR1) & LPSPI_CFGR1_MASTER_MASK); +} + +/*! + * @brief Flushes the LPSPI FIFOs. + * + * @param base LPSPI 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. + */ +static inline void LPSPI_FlushFifo(LPSPI_Type *base, bool flushTxFifo, bool flushRxFifo) +{ + base->CR |= ((uint32_t)flushTxFifo << LPSPI_CR_RTF_SHIFT) | ((uint32_t)flushRxFifo << LPSPI_CR_RRF_SHIFT); +} + +/*! + * @brief Sets the transmit and receive FIFO watermark values. + * + * This function allows the user to set the receive and transmit FIFO watermarks. The function + * does not compare the watermark settings to the FIFO size. The FIFO watermark should not be + * equal to or greater than the FIFO size. It is up to the higher level driver to make this check. + * + * @param base LPSPI peripheral address. + * @param txWater The TX FIFO watermark value. Writing a value equal or greater than the FIFO size is truncated. + * @param rxWater The RX FIFO watermark value. Writing a value equal or greater than the FIFO size is truncated. + */ +static inline void LPSPI_SetFifoWatermarks(LPSPI_Type *base, uint32_t txWater, uint32_t rxWater) +{ + base->FCR = LPSPI_FCR_TXWATER(txWater) | LPSPI_FCR_RXWATER(rxWater); +} + +/*! + * @brief Configures all LPSPI peripheral chip select polarities simultaneously. + * + * Note that the CFGR1 should only be written when the LPSPI is disabled (LPSPIx_CR_MEN = 0). + * + * This is an example: PCS0 and PCS1 set to active low and other PCSs set to active high. Note that the number of + * PCS is device-specific. + * @code + * LPSPI_SetAllPcsPolarity(base, kLPSPI_Pcs0ActiveLow | kLPSPI_Pcs1ActiveLow); + * @endcode + * + * @param base LPSPI peripheral address. + * @param mask The PCS polarity mask; Use the enum _lpspi_pcs_polarity. + */ +static inline void LPSPI_SetAllPcsPolarity(LPSPI_Type *base, uint32_t mask) +{ + base->CFGR1 = (base->CFGR1 & ~LPSPI_CFGR1_PCSPOL_MASK) | LPSPI_CFGR1_PCSPOL(~mask); +} + +/*! + * @brief Configures the frame size. + * + * The minimum frame size is 8-bits and the maximum frame size is 4096-bits. If the frame size is less than or equal + * to 32-bits, the word size and frame size are identical. If the frame size is greater than 32-bits, the word + * size is 32-bits for each word except the last (the last word contains the remainder bits if the frame size is not + * divisible by 32). The minimum word size is 2-bits. A frame size of 33-bits (or similar) is not supported. + * + * Note 1: The transmit command register should be initialized before enabling the LPSPI in slave mode, although + * the command register does not update until after the LPSPI is enabled. After it is enabled, the transmit command + * register + * should only be changed if the LPSPI is idle. + * + * Note 2: The transmit and command FIFO is a combined FIFO that includes both transmit data and command words. That + * means the TCR register should be written to when the Tx FIFO is not full. + * + * @param base LPSPI peripheral address. + * @param frameSize The frame size in number of bits. + */ +static inline void LPSPI_SetFrameSize(LPSPI_Type *base, uint32_t frameSize) +{ + base->TCR = (base->TCR & ~LPSPI_TCR_FRAMESZ_MASK) | LPSPI_TCR_FRAMESZ(frameSize - 1); +} + +/*! + * @brief Sets the LPSPI baud rate in bits per second. + * + * This function takes in the desired bitsPerSec (baud rate) and calculates the nearest + * possible baud rate without exceeding the desired baud rate and returns the + * calculated baud rate in bits-per-second. It requires the caller to provide + * the frequency of the module source clock (in Hertz). Note that the baud rate + * does not go into effect until the Transmit Control Register (TCR) is programmed + * with the prescale value. Hence, this function returns the prescale tcrPrescaleValue + * parameter for later programming in the TCR. The higher level + * peripheral driver should alert the user of an out of range baud rate input. + * + * Note that the LPSPI module must first be disabled before configuring this. + * Note that the LPSPI module must be configured for master mode before configuring this. + * + * @param base LPSPI peripheral address. + * @param baudRate_Bps The desired baud rate in bits per second. + * @param srcClock_Hz Module source input clock in Hertz. + * @param tcrPrescaleValue The TCR prescale value needed to program the TCR. + * @return The actual calculated baud rate. This function may also return a "0" if the + * LPSPI is not configured for master mode or if the LPSPI module is not disabled. + */ + +uint32_t LPSPI_MasterSetBaudRate(LPSPI_Type *base, + uint32_t baudRate_Bps, + uint32_t srcClock_Hz, + uint32_t *tcrPrescaleValue); + +/*! + * @brief Manually configures a specific LPSPI delay parameter (module must be disabled to + * change the delay values). + * + * This function configures the following: + * SCK to PCS delay, or + * PCS to SCK delay, or + * The configurations must occur between the transfer delay. + * + * The delay names are available in type lpspi_delay_type_t. + * + * The user passes the desired delay along with the delay value. + * This allows the user to directly set the delay values if they have + * pre-calculated them or if they simply wish to manually increment the value. + * + * Note that the LPSPI module must first be disabled before configuring this. + * Note that the LPSPI module must be configured for master mode before configuring this. + * + * @param base LPSPI peripheral address. + * @param scaler The 8-bit delay value 0x00 to 0xFF (255). + * @param whichDelay The desired delay to configure, must be of type lpspi_delay_type_t. + */ +void LPSPI_MasterSetDelayScaler(LPSPI_Type *base, uint32_t scaler, lpspi_delay_type_t whichDelay); + +/*! + * @brief Calculates the delay based on the desired delay input in nanoseconds (module must be + * disabled to change the delay values). + * + * This function calculates the values for the following: + * SCK to PCS delay, or + * PCS to SCK delay, or + * The configurations must occur between the transfer delay. + * + * The delay names are available in type lpspi_delay_type_t. + * + * The user passes the desired delay and the desired delay value in + * nano-seconds. The function calculates the value needed for the desired delay parameter + * and returns the actual calculated delay because 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. It is up to the higher level + * peripheral driver to alert the user of an out of range delay input. + * + * Note that the LPSPI module must be configured for master mode before configuring this. And note that + * the delayTime = LPSPI_clockSource / (PRESCALE * Delay_scaler). + * + * @param base LPSPI peripheral address. + * @param delayTimeInNanoSec The desired delay value in nano-seconds. + * @param whichDelay The desired delay to configuration, which must be of type lpspi_delay_type_t. + * @param srcClock_Hz Module source input clock in Hertz. + * @return actual Calculated delay value in nano-seconds. + */ +uint32_t LPSPI_MasterSetDelayTimes(LPSPI_Type *base, + uint32_t delayTimeInNanoSec, + lpspi_delay_type_t whichDelay, + uint32_t srcClock_Hz); + +/*! + * @brief Writes data into the transmit data buffer. + * + * This function writes data passed in by the user to the Transmit Data Register (TDR). + * The user can pass up to 32-bits of data to load into the TDR. If the frame size exceeds 32-bits, + * the user has to manage sending the data one 32-bit word at a time. + * Any writes to the TDR result in an immediate push to the transmit FIFO. + * This function can be used for either master or slave modes. + * + * @param base LPSPI peripheral address. + * @param data The data word to be sent. + */ +static inline void LPSPI_WriteData(LPSPI_Type *base, uint32_t data) +{ + base->TDR = data; +} + +/*! + * @brief Reads data from the data buffer. + * + * This function reads the data from the Receive Data Register (RDR). + * This function can be used for either master or slave mode. + * + * @param base LPSPI peripheral address. + * @return The data read from the data buffer. + */ +static inline uint32_t LPSPI_ReadData(LPSPI_Type *base) +{ + return (base->RDR); +} + +/*! + * @brief Set up the dummy data. + * + * @param base LPSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + * Note: + * This API has no effect when LPSPI in slave interrupt mode, because driver + * will set the TXMSK bit to 1 if txData is NULL, no data is loaded from transmit + * FIFO and output pin is tristated. + */ +void LPSPI_SetDummyData(LPSPI_Type *base, uint8_t dummyData); + +/*! + *@} + */ + +/*! + * @name Transactional + * @{ + */ +/*Transactional APIs*/ + +/*! + * @brief Initializes the LPSPI master handle. + * + * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a + * specified LPSPI instance, call this API once to get the initialized handle. + + * @param base LPSPI peripheral address. + * @param handle LPSPI handle pointer to lpspi_master_handle_t. + * @param callback DSPI callback. + * @param userData callback function parameter. + */ +void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base, + lpspi_master_handle_t *handle, + lpspi_master_transfer_callback_t callback, + void *userData); + +/*! + * @brief LPSPI master transfer data using a polling method. + * + * This function transfers data using a polling method. This is a blocking function, which does not return until all + * transfers have been + * completed. + * + * Note: + * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. + * For bytesPerFrame greater than 4: + * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4. + * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. + * + * @param base LPSPI peripheral address. + * @param transfer pointer to lpspi_transfer_t structure. + * @return status of status_t. + */ +status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer); + +/*! + * @brief LPSPI master transfer data using an interrupt method. + * + * This function transfers data using an interrupt method. This is a non-blocking function, which returns right away. + * When all data + * is transferred, the callback function is called. + * + * Note: + * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. + * For bytesPerFrame greater than 4: + * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4. + * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + * @param transfer pointer to lpspi_transfer_t structure. + * @return status of status_t. + */ +status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer); + +/*! + * @brief Gets the master transfer remaining bytes. + * + * This function gets the master transfer remaining bytes. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + * @param count Number of bytes transferred so far by the non-blocking transaction. + * @return status of status_t. + */ +status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count); + +/*! + * @brief LPSPI master abort transfer which uses an interrupt method. + * + * This function aborts a transfer which uses an interrupt method. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + */ +void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle); + +/*! + * @brief LPSPI Master IRQ handler function. + * + * This function processes the LPSPI transmit and receive IRQ. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_master_handle_t structure which stores the transfer state. + */ +void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle); + +/*! + * @brief Initializes the LPSPI slave handle. + * + * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a + * specified LPSPI instance, call this API once to get the initialized handle. + * + * @param base LPSPI peripheral address. + * @param handle LPSPI handle pointer to lpspi_slave_handle_t. + * @param callback DSPI callback. + * @param userData callback function parameter. + */ +void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base, + lpspi_slave_handle_t *handle, + lpspi_slave_transfer_callback_t callback, + void *userData); + +/*! + * @brief LPSPI slave transfer data using an interrupt method. + * + * This function transfer data using an interrupt method. This is a non-blocking function, which returns right away. + * When all data + * is transferred, the callback function is called. + * + * Note: + * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4. + * For bytesPerFrame greater than 4: + * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4. + * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + * @param transfer pointer to lpspi_transfer_t structure. + * @return status of status_t. + */ +status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer); + +/*! + * @brief Gets the slave transfer remaining bytes. + * + * This function gets the slave transfer remaining bytes. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + * @param count Number of bytes transferred so far by the non-blocking transaction. + * @return status of status_t. + */ +status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count); + +/*! + * @brief LPSPI slave aborts a transfer which uses an interrupt method. + * + * This function aborts a transfer which uses an interrupt method. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + */ +void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle); + +/*! + * @brief LPSPI Slave IRQ handler function. + * + * This function processes the LPSPI transmit and receives an IRQ. + * + * @param base LPSPI peripheral address. + * @param handle pointer to lpspi_slave_handle_t structure which stores the transfer state. + */ +void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle); + +/*! + *@} + */ + +#if defined(__cplusplus) +} +#endif /*_cplusplus*/ + /*! + *@} + */ + +#endif /*_FSL_LPSPI_H_*/ diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c new file mode 100755 index 000000000..7e6458220 --- /dev/null +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/spi/lpspi_interrupt.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2013 - 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file lpspi_interrupt.c + * @brief Demo for SPI function + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.1.18 + */ + +#include "fsl_device_registers.h" +#include "fsl_debug_console.h" +#include "fsl_lpspi.h" +#include "board.h" + +#include "fsl_common.h" +#include "pin_mux.h" +#if ((defined FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT)) +#include "fsl_intmux.h" +#endif +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Master related */ +#define EXAMPLE_LPSPI_MASTER_BASEADDR (LPSPI3) +#define EXAMPLE_LPSPI_MASTER_IRQN (LPSPI3_IRQn) +#define EXAMPLE_LPSPI_MASTER_IRQHandler (LPSPI3_IRQHandler) + +#define EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT (kLPSPI_Pcs0) +#define EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER (kLPSPI_MasterPcs0) + +/* Slave related */ +#define EXAMPLE_LPSPI_SLAVE_BASEADDR (LPSPI1) +#define EXAMPLE_LPSPI_SLAVE_IRQN (LPSPI1_IRQn) +#define EXAMPLE_LPSPI_SLAVE_IRQHandler (LPSPI1_IRQHandler) + +#define EXAMPLE_LPSPI_SLAVE_PCS_FOR_INIT (kLPSPI_Pcs0) +#define EXAMPLE_LPSPI_SLAVE_PCS_FOR_TRANSFER (kLPSPI_SlavePcs0) + +/* Select USB1 PLL PFD0 (720 MHz) as lpspi clock source */ +#define EXAMPLE_LPSPI_CLOCK_SOURCE_SELECT (1U) +/* Clock divider for master lpspi clock source */ +#define EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER (7U) + +#define EXAMPLE_LPSPI_CLOCK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER + 1U)) + +#define EXAMPLE_LPSPI_MASTER_CLOCK_FREQ EXAMPLE_LPSPI_CLOCK_FREQ +#define EXAMPLE_LPSPI_SLAVE_CLOCK_FREQ EXAMPLE_LPSPI_CLOCK_FREQ + +#define TRANSFER_SIZE (512U) /*! Transfer dataSize .*/ +#define TRANSFER_BAUDRATE (500000U) /*! Transfer baudrate - 500k */ + + +#define spi_print KPrintf + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/* LPSPI user callback */ +void LPSPI_SlaveUserCallback(LPSPI_Type *base, lpspi_slave_handle_t *handle, status_t status, void *userData); +void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData); + +/******************************************************************************* + * Variables + ******************************************************************************/ +uint8_t masterRxData[TRANSFER_SIZE] = {0}; +uint8_t masterTxData[TRANSFER_SIZE] = {0}; +uint8_t slaveRxData[TRANSFER_SIZE] = {0}; +uint8_t slaveTxData[TRANSFER_SIZE] = {0}; + +volatile uint32_t slaveTxCount; +volatile uint32_t slaveRxCount; +uint8_t g_slaveRxWatermark; +uint8_t g_slaveFifoSize; + +volatile uint32_t masterTxCount; +volatile uint32_t masterRxCount; +uint8_t g_masterRxWatermark; +uint8_t g_masterFifoSize; + +volatile bool isSlaveTransferCompleted = false; +volatile bool isMasterTransferCompleted = false; + +/******************************************************************************* + * Code + ******************************************************************************/ +void LPSPI_SlaveUserCallback(LPSPI_Type *base, lpspi_slave_handle_t *handle, status_t status, void *userData) +{ + if (status == kStatus_Success) + { + spi_print("This is LPSPI slave transfer completed callback. \r\n"); + spi_print("It's a successful transfer. \r\n\r\n"); + } + else if (status == kStatus_LPSPI_Error) + { + spi_print("This is LPSPI slave transfer completed callback. \r\n"); + spi_print("Error occurred in this transfer. \r\n\r\n"); + } + else + { + __NOP(); + } + + isSlaveTransferCompleted = true; +} + +void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData) +{ + isMasterTransferCompleted = true; +} + +void EXAMPLE_LPSPI_SLAVE_IRQHandler(int vector, void *param) +{ + if (slaveRxCount < TRANSFER_SIZE) + { + while (LPSPI_GetRxFifoCount(EXAMPLE_LPSPI_SLAVE_BASEADDR)) + { + slaveRxData[slaveRxCount] = LPSPI_ReadData(EXAMPLE_LPSPI_SLAVE_BASEADDR); + slaveRxCount++; + + if (slaveTxCount < TRANSFER_SIZE) + { + LPSPI_WriteData(EXAMPLE_LPSPI_SLAVE_BASEADDR, slaveTxData[slaveTxCount]); + slaveTxCount++; + } + if (slaveRxCount == TRANSFER_SIZE) + { + break; + } + } + } + + /*Update rxWatermark. There isn't RX interrupt for the last datas if the RX count is not greater than rxWatermark.*/ + if ((TRANSFER_SIZE - slaveRxCount) <= g_slaveRxWatermark) + { + EXAMPLE_LPSPI_SLAVE_BASEADDR->FCR = + (EXAMPLE_LPSPI_SLAVE_BASEADDR->FCR & (~LPSPI_FCR_RXWATER_MASK)) | + LPSPI_FCR_RXWATER(((TRANSFER_SIZE - slaveRxCount) > 1) ? ((TRANSFER_SIZE - slaveRxCount) - 1U) : (0U)); + } + + /* Check if remaining receive byte count matches user request */ + if ((slaveRxCount == TRANSFER_SIZE) && (slaveTxCount == TRANSFER_SIZE)) + { + isSlaveTransferCompleted = true; + /* Disable interrupt requests */ + LPSPI_DisableInterrupts(EXAMPLE_LPSPI_SLAVE_BASEADDR, kLPSPI_RxInterruptEnable); + } +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} + +DECLARE_HW_IRQ(EXAMPLE_LPSPI_SLAVE_IRQN, EXAMPLE_LPSPI_SLAVE_IRQHandler, NONE); + +void EXAMPLE_LPSPI_MASTER_IRQHandler(int vector, void *param) +{ + if (masterRxCount < TRANSFER_SIZE) + { + /* First, disable the interrupts to avoid potentially triggering another interrupt + * while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll + * re-enable the interrupts EXAMPLE_LPSPI_MASTER_BASEADDRd on the LPSPI state after reading out the FIFO. + */ + LPSPI_DisableInterrupts(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_RxInterruptEnable); + + while (LPSPI_GetRxFifoCount(EXAMPLE_LPSPI_MASTER_BASEADDR)) + { + /*Read out the data*/ + masterRxData[masterRxCount] = LPSPI_ReadData(EXAMPLE_LPSPI_MASTER_BASEADDR); + + masterRxCount++; + + if (masterRxCount == TRANSFER_SIZE) + { + break; + } + } + + /* Re-enable the interrupts only if rxCount indicates there is more data to receive, + * else we may get a spurious interrupt. + * */ + if (masterRxCount < TRANSFER_SIZE) + { + /* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */ + LPSPI_EnableInterrupts(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_RxInterruptEnable); + } + } + + /*Update rxWatermark. There isn't RX interrupt for the last datas if the RX count is not greater than rxWatermark.*/ + if ((TRANSFER_SIZE - masterRxCount) <= g_masterRxWatermark) + { + EXAMPLE_LPSPI_MASTER_BASEADDR->FCR = + (EXAMPLE_LPSPI_MASTER_BASEADDR->FCR & (~LPSPI_FCR_RXWATER_MASK)) | + LPSPI_FCR_RXWATER(((TRANSFER_SIZE - masterRxCount) > 1) ? ((TRANSFER_SIZE - masterRxCount) - 1U) : (0U)); + } + + if (masterTxCount < TRANSFER_SIZE) + { + while ((LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_MASTER_BASEADDR) < g_masterFifoSize) && + (masterTxCount - masterRxCount < g_masterFifoSize)) + { + /*Write the word to TX register*/ + LPSPI_WriteData(EXAMPLE_LPSPI_MASTER_BASEADDR, masterTxData[masterTxCount]); + ++masterTxCount; + + if (masterTxCount == TRANSFER_SIZE) + { + break; + } + } + } + + /* Check if we're done with this transfer.*/ + if ((masterTxCount == TRANSFER_SIZE) && (masterRxCount == TRANSFER_SIZE)) + { + isMasterTransferCompleted = true; + /* Complete the transfer and disable the interrupts */ + LPSPI_DisableInterrupts(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_AllInterruptEnable); + } +/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + exception return operation might vector to incorrect interrupt */ +#if defined __CORTEX_M && (__CORTEX_M == 4U) + __DSB(); +#endif +} + +DECLARE_HW_IRQ(EXAMPLE_LPSPI_MASTER_IRQN, EXAMPLE_LPSPI_MASTER_IRQHandler, NONE); + +/*! + * @brief Main function + */ +int test_spi(void) +{ + /*Set clock source for LPSPI*/ + CLOCK_SetMux(kCLOCK_LpspiMux, EXAMPLE_LPSPI_CLOCK_SOURCE_SELECT); + CLOCK_SetDiv(kCLOCK_LpspiDiv, EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER); + + spi_print("LPSPI functional interrupt example start.\r\n"); + spi_print("This example use one lpspi instance as master and another as slave on one board.\r\n"); + spi_print("Master uses interrupt way and slave uses interrupt way.\r\n"); + spi_print( + "Note that some LPSPI instances interrupt is in INTMUX ," + "you should set the intmux when you porting this example accordingly \r\n"); + + spi_print("Please make sure you make the correct line connection. Basically, the connection is: \r\n"); + spi_print("LPSPI_master -- LPSPI_slave \r\n"); + spi_print(" CLK -- CLK \r\n"); + spi_print(" PCS -- PCS \r\n"); + spi_print(" SOUT -- SIN \r\n"); + spi_print(" SIN -- SOUT \r\n"); + + uint32_t errorCount; + uint32_t i; + lpspi_master_config_t masterConfig; + lpspi_slave_config_t slaveConfig; + uint32_t whichPcs; + uint8_t txWatermark; + + /*Set up the transfer data*/ + for (i = 0; i < TRANSFER_SIZE; i++) + { + masterTxData[i] = i % 256; + masterRxData[i] = 0; + + slaveTxData[i] = ~masterTxData[i]; + slaveRxData[i] = 0; + } + + /*Master config*/ + masterConfig.baudRate = TRANSFER_BAUDRATE; + masterConfig.bitsPerFrame = 8; + masterConfig.cpol = kLPSPI_ClockPolarityActiveHigh; + masterConfig.cpha = kLPSPI_ClockPhaseFirstEdge; + masterConfig.direction = kLPSPI_MsbFirst; + + masterConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.baudRate; + masterConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.baudRate; + masterConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.baudRate; + + masterConfig.whichPcs = EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT; + masterConfig.pcsActiveHighOrLow = kLPSPI_PcsActiveLow; + + masterConfig.pinCfg = kLPSPI_SdiInSdoOut; + masterConfig.dataOutConfig = kLpspiDataOutRetained; + + LPSPI_MasterInit(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterConfig, EXAMPLE_LPSPI_MASTER_CLOCK_FREQ); + + /*Slave config*/ + slaveConfig.bitsPerFrame = masterConfig.bitsPerFrame; + slaveConfig.cpol = masterConfig.cpol; + slaveConfig.cpha = masterConfig.cpha; + slaveConfig.direction = masterConfig.direction; + + slaveConfig.whichPcs = EXAMPLE_LPSPI_SLAVE_PCS_FOR_INIT; + slaveConfig.pcsActiveHighOrLow = masterConfig.pcsActiveHighOrLow; + + slaveConfig.pinCfg = kLPSPI_SdiInSdoOut; + slaveConfig.dataOutConfig = kLpspiDataOutRetained; + + LPSPI_SlaveInit(EXAMPLE_LPSPI_SLAVE_BASEADDR, &slaveConfig); + + /******************Set up slave first ******************/ + isSlaveTransferCompleted = false; + slaveTxCount = 0; + slaveRxCount = 0; + whichPcs = EXAMPLE_LPSPI_SLAVE_PCS_FOR_INIT; + + /*The TX and RX FIFO sizes are always the same*/ + g_slaveFifoSize = LPSPI_GetRxFifoSize(EXAMPLE_LPSPI_SLAVE_BASEADDR); + + /*Set the RX and TX watermarks to reduce the ISR times.*/ + if (g_slaveFifoSize > 1) + { + txWatermark = 1; + g_slaveRxWatermark = g_slaveFifoSize - 2; + } + else + { + txWatermark = 0; + g_slaveRxWatermark = 0; + } + + LPSPI_SetFifoWatermarks(EXAMPLE_LPSPI_SLAVE_BASEADDR, txWatermark, g_slaveRxWatermark); + + LPSPI_Enable(EXAMPLE_LPSPI_SLAVE_BASEADDR, false); + EXAMPLE_LPSPI_SLAVE_BASEADDR->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK); + LPSPI_Enable(EXAMPLE_LPSPI_SLAVE_BASEADDR, true); + + /*Flush FIFO , clear status , disable all the interrupts.*/ + LPSPI_FlushFifo(EXAMPLE_LPSPI_SLAVE_BASEADDR, true, true); + LPSPI_ClearStatusFlags(EXAMPLE_LPSPI_SLAVE_BASEADDR, kLPSPI_AllStatusFlag); + LPSPI_DisableInterrupts(EXAMPLE_LPSPI_SLAVE_BASEADDR, kLPSPI_AllInterruptEnable); + + EXAMPLE_LPSPI_SLAVE_BASEADDR->TCR = + (EXAMPLE_LPSPI_SLAVE_BASEADDR->TCR & + ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) | + LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(0) | LPSPI_TCR_TXMSK(0) | LPSPI_TCR_PCS(whichPcs); + + /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX , + * and you should also enable the INTMUX interrupt in your application. + */ + EnableIRQ(EXAMPLE_LPSPI_SLAVE_IRQN); + + /*TCR is also shared the FIFO , so wait for TCR written.*/ + while (LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_SLAVE_BASEADDR) != 0) + { + } + /*Fill up the TX data in FIFO */ + while (LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_SLAVE_BASEADDR) < g_slaveFifoSize) + { + /*Write the word to TX register*/ + LPSPI_WriteData(EXAMPLE_LPSPI_SLAVE_BASEADDR, slaveTxData[slaveTxCount]); + ++slaveTxCount; + + if (slaveTxCount == TRANSFER_SIZE) + { + break; + } + } + LPSPI_EnableInterrupts(EXAMPLE_LPSPI_SLAVE_BASEADDR, kLPSPI_RxInterruptEnable); + + /******************Set up master transfer******************/ + isMasterTransferCompleted = false; + masterTxCount = 0; + masterRxCount = 0; + whichPcs = EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT; + + /*The TX and RX FIFO sizes are always the same*/ + g_masterFifoSize = LPSPI_GetRxFifoSize(EXAMPLE_LPSPI_MASTER_BASEADDR); + + /*Set the RX and TX watermarks to reduce the ISR times.*/ + if (g_masterFifoSize > 1) + { + txWatermark = 1; + g_masterRxWatermark = g_masterFifoSize - 2; + } + else + { + txWatermark = 0; + g_masterRxWatermark = 0; + } + + LPSPI_SetFifoWatermarks(EXAMPLE_LPSPI_MASTER_BASEADDR, txWatermark, g_masterRxWatermark); + + LPSPI_Enable(EXAMPLE_LPSPI_MASTER_BASEADDR, false); + EXAMPLE_LPSPI_MASTER_BASEADDR->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK); + LPSPI_Enable(EXAMPLE_LPSPI_MASTER_BASEADDR, true); + + /*Flush FIFO , clear status , disable all the inerrupts.*/ + LPSPI_FlushFifo(EXAMPLE_LPSPI_MASTER_BASEADDR, true, true); + LPSPI_ClearStatusFlags(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_AllStatusFlag); + LPSPI_DisableInterrupts(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_AllInterruptEnable); + + EXAMPLE_LPSPI_MASTER_BASEADDR->TCR = + (EXAMPLE_LPSPI_MASTER_BASEADDR->TCR & + ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) | + LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(0) | LPSPI_TCR_TXMSK(0) | LPSPI_TCR_PCS(whichPcs); + + /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX , + * and you should also enable the INTMUX interupt in your application. + */ + EnableIRQ(EXAMPLE_LPSPI_MASTER_IRQN); + + /*TCR is also shared the FIFO , so wait for TCR written.*/ + while (LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_MASTER_BASEADDR) != 0) + { + } + /*Fill up the TX data in FIFO */ + while ((LPSPI_GetTxFifoCount(EXAMPLE_LPSPI_MASTER_BASEADDR) < g_masterFifoSize) && + (masterTxCount - masterRxCount < g_masterFifoSize)) + { + /*Write the word to TX register*/ + LPSPI_WriteData(EXAMPLE_LPSPI_MASTER_BASEADDR, masterTxData[masterTxCount]); + ++masterTxCount; + + if (masterTxCount == TRANSFER_SIZE) + { + break; + } + } + LPSPI_EnableInterrupts(EXAMPLE_LPSPI_MASTER_BASEADDR, kLPSPI_RxInterruptEnable); + + /******************Wait for master and slave transfer completed.******************/ + while ((!isSlaveTransferCompleted) || (!isMasterTransferCompleted)) + { + } + + errorCount = 0; + for (i = 0; i < TRANSFER_SIZE; i++) + { + if (masterTxData[i] != slaveRxData[i]) + { + errorCount++; + } + + if (slaveTxData[i] != masterRxData[i]) + { + errorCount++; + } + } + if (errorCount == 0) + { + spi_print("\r\nLPSPI transfer all data matched! \r\n"); + } + else + { + spi_print("\r\nError occurred in LPSPI transfer ! \r\n"); + } + + LPSPI_Deinit(EXAMPLE_LPSPI_MASTER_BASEADDR); + LPSPI_Deinit(EXAMPLE_LPSPI_SLAVE_BASEADDR); + + spi_print("End of example. \r\n"); + + while (1) + { + } +} + +SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), + spi, test_spi, SPI test ); + diff --git a/Ubiquitous/XiUOS/resources/Makefile b/Ubiquitous/XiUOS/resources/Makefile index 1c5a77e20..5ed9111ac 100644 --- a/Ubiquitous/XiUOS/resources/Makefile +++ b/Ubiquitous/XiUOS/resources/Makefile @@ -1,5 +1,5 @@ SRC_DIR := -SRC_FILES += bus.c +SRC_FILES += bus.c ifeq ($(CONFIG_KERNEL_DEVICE),y) SRC_FILES += device.c diff --git a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c index 70b9eeb19..9075d6ea9 100644 --- a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c +++ b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c @@ -69,7 +69,6 @@ #include "board.h" #include "ethernet.h" #include "enet_ethernetif.h" -#include char lwip_ipaddr[] = {192, 168, 250, 253}; char lwip_netmask[] = {255, 255, 255, 0}; @@ -453,9 +452,10 @@ void lwip_input_thread(void *param) void lwip_config_input(struct netif *net) { - pthread_t th_id = 0; + sys_thread_t th_id = 0; - th_id = sys_thread_new("eth_input", lwip_input_thread, net, 4096, 15); + th_id = sys_thread_new("eth_input", lwip_input_thread, net, LWIP_TASK_STACK_SIZE, + LWIP_DEMO_TASK_PRIO); if (th_id >= 0) { lw_print("%s %d successfully!\n", __func__, th_id); diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c index 0827bf3c5..b8fd680e5 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_config_demo.c @@ -70,8 +70,8 @@ void lwip_setip_thread(int argc, char *argv[]) pthread_t th_id; pthread_attr_t attr; - attr.schedparam.sched_priority = 15; - attr.stacksize = 4096; + attr.schedparam.sched_priority = LWIP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TASK_STACK_SIZE; if(argc >= 4) { diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c index 2a19317d8..f84053730 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c @@ -36,7 +36,6 @@ #include "pin_mux.h" #include "clock_config.h" -#include #include #include "connect_ethernet.h" @@ -61,14 +60,6 @@ ip4_addr_t ping_addr; * Code ******************************************************************************/ -static void *lwip_ping_test(void *param) -{ - IP4_ADDR(&ping_addr, lwip_gwaddr[0], lwip_gwaddr[1], lwip_gwaddr[2], lwip_gwaddr[3]); - ETH_BSP_Config(); - lwip_config_net(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - ping_init(&ping_addr); -} - void lwip_ping_thread(int argc, char *argv[]) { int result = 0; diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c index baebfbbcb..afc1aa67a 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c @@ -17,7 +17,6 @@ * @author AIIT XUOS Lab * @date 2021-05-29 */ -#include #include #include "board.h" #include "sys_arch.h" diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c index da25a31c8..5eb214771 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_udp_demo.c @@ -17,7 +17,6 @@ * @author AIIT XUOS Lab * @date 2021-05-29 */ -#include #include #include "board.h" #include "sys_arch.h" @@ -95,8 +94,7 @@ __exit: void *lwip_udp_send_run(int argc, char *argv[]) { int result = 0; - pthread_t th_id; - pthread_attr_t attr; + sys_thread_t th_id; memset(udp_send_msg, 0, sizeof(udp_send_msg)); @@ -118,7 +116,7 @@ void *lwip_udp_send_run(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("udp socket send", lwip_udp_send, NULL, 4096, 25); + sys_thread_new("udp socket send", lwip_udp_send, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),