From e2263acd5b5d01cea3ea97e67168c30153d63986 Mon Sep 17 00:00:00 2001 From: guohp1128 <297273523@qq.com> Date: Tue, 18 Aug 2020 22:11:50 +0800 Subject: [PATCH] add nrf5x adc driver --- bsp/nrf5x/libraries/drivers/SConscript | 3 + bsp/nrf5x/libraries/drivers/drv_adc.c | 261 +++++++++++++++++++++++++ bsp/nrf5x/libraries/drivers/drv_adc.h | 46 +++++ bsp/nrf5x/nrf52840/board/Kconfig | 10 +- 4 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 bsp/nrf5x/libraries/drivers/drv_adc.c create mode 100644 bsp/nrf5x/libraries/drivers/drv_adc.h diff --git a/bsp/nrf5x/libraries/drivers/SConscript b/bsp/nrf5x/libraries/drivers/SConscript index b446b7c3b..e5b13d42e 100644 --- a/bsp/nrf5x/libraries/drivers/SConscript +++ b/bsp/nrf5x/libraries/drivers/SConscript @@ -22,6 +22,9 @@ if GetDepend(['BSP_USING_SPI']): if GetDepend(['BSP_USING_GPIO']): src += ['drv_gpio.c'] + +if GetDepend(['BSP_USING_SAADC']): + src += ['drv_adc.c'] if GetDepend(['BSP_USING_PWM']): src += ['drv_pwm.c'] diff --git a/bsp/nrf5x/libraries/drivers/drv_adc.c b/bsp/nrf5x/libraries/drivers/drv_adc.c new file mode 100644 index 000000000..25f53ea36 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_adc.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-18 guohp1128 the first version + */ + +#include "drv_adc.h" + +#ifdef RT_USING_ADC + +struct rt_adc_device nrf5x_adc_device; + +drv_nrfx_saadc_result_t results; +nrf_saadc_value_t result_buff_cache[8]; + +static void nrf5x_saadc_event_hdr(nrfx_saadc_evt_t const * p_event) +{ + uint8_t i,j; + if(p_event->type == NRFX_SAADC_EVT_DONE) + { + j = 0; + for(i = 0; i < 8; i++) + { + if(results.channels[i].channel_index == i) + { + results.result_buffer[i] = result_buff_cache[j]; + j ++; + } + } + results.done = 1; + } +} + +static uint32_t get_channels_mask(void) +{ + uint8_t i; + uint32_t mask = 0; + for(i = 0; i < 8; i++) + { + if(results.channels[i].channel_index != 0xff) + { + mask |= (1 << results.channels[i].channel_index); + } + } + return mask; +} + +static void set_channels(drv_nrfx_saadc_channel_t * channel) +{ + uint8_t i; + if(channel -> mode == NRF_SAADC_MODE_SINGLE_ENDED) + { + results.channels[channel->channel_num] = (nrfx_saadc_channel_t)NRFX_SAADC_DEFAULT_CHANNEL_SE(channel -> pin_p + 1, channel -> channel_num); + } + else if(channel -> mode == NRF_SAADC_MODE_DIFFERENTIAL) + { + results.channels[channel->channel_num] = (nrfx_saadc_channel_t)NRFX_SAADC_DEFAULT_CHANNEL_DIFFERENTIAL(channel -> pin_p + 1, channel -> pin_n + 1, channel -> channel_num); + } + results.channel_count = 0; + for(i = 0; i < 8; i++) + { + if(results.channels[i].channel_index != 0xff) + { + results.channel_count ++; + } + } +} + +/* channel: 0-7 */ +static rt_err_t nrf5x_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +{ + nrfx_err_t err_code = NRFX_SUCCESS; + uint8_t i,j; + + if (enabled) + { + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->parent.user_data != RT_NULL); + + drv_nrfx_saadc_channel_t * drv_channel_config = NULL; + drv_channel_config = (drv_nrfx_saadc_channel_t *)device->parent.user_data; + + set_channels(drv_channel_config); + + nrfx_saadc_channel_t channels_cache[results.channel_count]; + + j = 0; + for(i = 0; i < 8; i++) + { + if(results.channels[i].channel_index != 0xff) + { + channels_cache[j] = results.channels[i]; + j ++; + } + } + + err_code = nrfx_saadc_channels_config(channels_cache,results.channel_count); + + err_code = nrfx_saadc_simple_mode_set(get_channels_mask(), + NRF_SAADC_RESOLUTION_12BIT, + NRF_SAADC_OVERSAMPLE_DISABLED, + nrf5x_saadc_event_hdr); + + err_code = nrfx_saadc_buffer_set(result_buff_cache, results.channel_count); + } + else + { + results.channels[channel].channel_index = 0xff; + + results.channel_count = 0; + for(i = 0; i < 8; i++) + { + if(results.channels[i].channel_index != 0xff) + { + results.channel_count ++; + } + } + + if(results.channel_count == 0) + { + nrfx_saadc_channel_t channels_cache[1]; + err_code = nrfx_saadc_channels_config(channels_cache, 0); + return err_code; + } + else + { + nrfx_saadc_channel_t channels_cache[results.channel_count]; + + j = 0; + for(i = 0; i < 8; i++) + { + if(results.channels[i].channel_index != 0xff) + { + channels_cache[j] = results.channels[i]; + j ++; + } + } + + err_code = nrfx_saadc_channels_config(channels_cache,results.channel_count); + + err_code = nrfx_saadc_simple_mode_set(get_channels_mask(), + NRF_SAADC_RESOLUTION_12BIT, + NRF_SAADC_OVERSAMPLE_DISABLED, + nrf5x_saadc_event_hdr); + + err_code = nrfx_saadc_buffer_set(result_buff_cache, results.channel_count); + } + } + + return err_code; +} + +static rt_err_t nrf5x_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + nrfx_err_t err_code = NRFX_SUCCESS; + + if (results.channels[channel].channel_index != 0xff) + { + results.done = 0; + err_code = nrfx_saadc_mode_trigger(); + while(results.done == 0) + { + ; + } + * value = results.result_buffer[channel]; + results.done = 0; + } + + return err_code; +} + +static const struct rt_adc_ops nrf5x_adc_ops = +{ + .enabled = nrf5x_adc_enabled, + .convert = nrf5x_get_adc_value, +}; + +int rt_hw_adc_init(void) +{ + int result = RT_EOK; + uint8_t i; + char name_buf[6] = {'S', 'A', 'A', 'D', 'C', 0}; + + for(i = 0; i < 8; i++) + { + results.channels[i].channel_index = 0xff; + results.result_buffer[i] = 0; + results.channel_count = 0; + results.done = 0; + } + + /* initializing SAADC interrupt priority */ + if (nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY) != NRFX_SUCCESS) + { + rt_kprintf("%s init failed", name_buf); + rt_kprintf("The driver is already initialized."); + result = -RT_ERROR; + } + else + { + /* register ADC device */ + if (rt_hw_adc_register(&nrf5x_adc_device, name_buf, &nrf5x_adc_ops, nrf5x_adc_device.parent.user_data) == RT_EOK) + { + rt_kprintf("%s init success", name_buf); + } + else + { + rt_kprintf("%s register failed", name_buf); + result = -RT_ERROR; + } + } + return result; +} +INIT_BOARD_EXPORT(rt_hw_adc_init); + + +/*test saadc*/ +#include + +void saadc_sample(void) +{ + drv_nrfx_saadc_channel_t channel_config; + rt_uint32_t result; + + rt_adc_device_t adc_dev; + adc_dev = (rt_adc_device_t)rt_device_find("SAADC"); + adc_dev->parent.user_data = &channel_config; + + channel_config = (drv_nrfx_saadc_channel_t){.mode = 0, .pin_p = 1, .pin_n = 1, .channel_num = 0}; + rt_adc_enable(adc_dev, channel_config.channel_num); + + channel_config = (drv_nrfx_saadc_channel_t){.mode = 0, .pin_p = 2, .pin_n = 1, .channel_num = 1}; + rt_adc_enable(adc_dev, channel_config.channel_num); + + channel_config = (drv_nrfx_saadc_channel_t){.mode = 0, .pin_p = 7, .pin_n = 1, .channel_num = 5}; + rt_adc_enable(adc_dev, channel_config.channel_num); + + int count = 1; + while(count++) + { + result = rt_adc_read(adc_dev, 0); + rt_kprintf("saadc channel 0 value = %d, ",result); + + result = rt_adc_read(adc_dev, 1); + rt_kprintf("saadc channel 1 value = %d, ",result); + + result = rt_adc_read(adc_dev, 5); + rt_kprintf("saadc channel 5 value = %d",result); + + rt_kprintf("\r\n"); + rt_thread_mdelay(1000); + } +} +MSH_CMD_EXPORT(saadc_sample, saadc sample); + +#endif /* RT_USING_ADC */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_adc.h b/bsp/nrf5x/libraries/drivers/drv_adc.h new file mode 100644 index 000000000..908ac8748 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_adc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-18 guohp1128 the first version + */ + +#ifndef __DRV_ADC_H__ +#define __DRV_ADC_H__ + +#include +#include "rtdevice.h" +#include +#include + +/* + previous definition in application + + set single-ended mode or differential mode. + selection ADC input pin, and config the number of Channel. + + mode: 0 single-ended mode,1 differential mode + pin_p: 0-7 + pin_n: 0-7,if single-ended mode, pin_n invalid + channel_num: 0-7 + */ +typedef struct +{ + nrf_saadc_mode_t mode; ///< SAADC mode. Single-ended or differential. + uint8_t pin_p; ///< Input positive pin selection. + uint8_t pin_n; ///< Input negative pin selection. + uint8_t channel_num; ///< Channel number. +} drv_nrfx_saadc_channel_t; + +typedef struct +{ + nrfx_saadc_channel_t channels[8]; + uint8_t channel_count; + nrf_saadc_value_t result_buffer[8]; + uint8_t done; +} drv_nrfx_saadc_result_t; + +#endif /* __DRV_ADC_H__ */ diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index 1bf97f6e4..756a81495 100644 --- a/bsp/nrf5x/nrf52840/board/Kconfig +++ b/bsp/nrf5x/nrf52840/board/Kconfig @@ -12,7 +12,6 @@ config SOC_NORDIC config SOC_NORDIC default y - menu "Onboard Peripheral Drivers" config BSP_USING_JLINK_TO_USART bool "Enable JLINK TO USART (uart0|RX_PIN:8|TX_PIN:6)" @@ -61,6 +60,15 @@ menu "On-chip Peripheral Drivers" bool "Enable GPIO" select RT_USING_PIN default y + config BSP_USING_SAADC + bool "Enable SAADC" + select RT_USING_ADC + default n + if BSP_USING_SAADC + config NRFX_SAADC_ENABLED + int + default 1 + endif menuconfig BSP_USING_PWM bool "Enable PWM" select RT_USING_PWM -- GitLab