forked from xuos/xiuos
fixed UDP socket recv and send bug and support I2c Bus registration
This commit is contained in:
parent
2115572813
commit
28cf201808
|
@ -23,11 +23,15 @@
|
|||
#include "sys_arch.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/opt.h"
|
||||
#include <lwip/sockets.h>
|
||||
#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 <lwip/sockets.h>
|
||||
#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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES := fsl_adc.c adc_interrupt.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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 );
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -78,7 +78,6 @@
|
|||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
|
|
@ -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"
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := fsl_gpio.c
|
||||
SRC_FILES := connect_gpio.c fsl_gpio.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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 <device.h>
|
||||
#include <board.h>
|
||||
|
||||
#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);
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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 <board.h>
|
||||
#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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
|
@ -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
|
|
@ -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 <device.h>
|
||||
#include <bus.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* 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);
|
||||
|
|
@ -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/////////////////////////////////////////
|
|
@ -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
|
|
@ -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),
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@
|
|||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void enet_delay(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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 <device.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int Stm32HwI2cInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES := fsl_lpspi.c lpspi_interrupt.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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 );
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
SRC_DIR :=
|
||||
SRC_FILES += bus.c
|
||||
SRC_FILES += bus.c
|
||||
|
||||
ifeq ($(CONFIG_KERNEL_DEVICE),y)
|
||||
SRC_FILES += device.c
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
#include "board.h"
|
||||
#include "ethernet.h"
|
||||
#include "enet_ethernetif.h"
|
||||
#include <transform.h>
|
||||
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "pin_mux.h"
|
||||
#include "clock_config.h"
|
||||
|
||||
#include <transform.h>
|
||||
#include <sys_arch.h>
|
||||
#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;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-29
|
||||
*/
|
||||
#include <transform.h>
|
||||
#include <xiuos.h>
|
||||
#include "board.h"
|
||||
#include "sys_arch.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-29
|
||||
*/
|
||||
#include <transform.h>
|
||||
#include <xiuos.h>
|
||||
#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),
|
||||
|
|
Loading…
Reference in New Issue