diff --git a/bsp/nrf5x/libraries/drivers/SConscript b/bsp/nrf5x/libraries/drivers/SConscript index b446b7c3b4..e5b13d42ee 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 0000000000..25f53ea369 --- /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 0000000000..908ac87489 --- /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/libraries/drivers/drv_gpio.c b/bsp/nrf5x/libraries/drivers/drv_gpio.c index 3084fbc043..0a237526de 100644 --- a/bsp/nrf5x/libraries/drivers/drv_gpio.c +++ b/bsp/nrf5x/libraries/drivers/drv_gpio.c @@ -46,6 +46,24 @@ static const struct pin_index pins[] = __NRF5X_PIN(29, 0, 29), __NRF5X_PIN(30, 0, 30), __NRF5X_PIN(31, 0, 31), +#ifdef SOC_NRF52840 + __NRF5X_PIN(32, 1, 0 ), + __NRF5X_PIN(33, 1, 1 ), + __NRF5X_PIN(34, 1, 2 ), + __NRF5X_PIN(35, 1, 3 ), + __NRF5X_PIN(36, 1, 4 ), + __NRF5X_PIN(37, 1, 5 ), + __NRF5X_PIN(38, 1, 6 ), + __NRF5X_PIN(39, 1, 7 ), + __NRF5X_PIN(40, 1, 8 ), + __NRF5X_PIN(41, 1, 9 ), + __NRF5X_PIN(42, 1, 10), + __NRF5X_PIN(43, 1, 11), + __NRF5X_PIN(44, 1, 12), + __NRF5X_PIN(45, 1, 13), + __NRF5X_PIN(46, 1, 14), + __NRF5X_PIN(47, 1, 15), +#endif /* SOC_NRF52840 */ }; /* EVENTS_IN[n](n=0..7) and EVENTS_PORT */ @@ -356,4 +374,105 @@ int rt_hw_pin_init(void) } INIT_BOARD_EXPORT(rt_hw_pin_init); + +/* test GPIO write, read, input interrupt */ +#define DK_BOARD_LED_1 13 +#define DK_BOARD_LED_2 14 +#define DK_BOARD_LED_3 15 +#define DK_BOARD_LED_4 16 + +#define DK_BOARD_BUTTON_1 11 +#define DK_BOARD_BUTTON_2 12 +#define DK_BOARD_BUTTON_3 24 +#define DK_BOARD_BUTTON_4 25 + +void button_1_callback(void *args) +{ + static int flag1 = 0; + if(flag1 == 0) + { + flag1 = 1; + rt_pin_write(DK_BOARD_LED_1, PIN_LOW); + } + else + { + flag1 = 0; + rt_pin_write(DK_BOARD_LED_1, PIN_HIGH); + } +} +void button_2_callback(void *args) +{ + static int flag2 = 0; + if(flag2 == 0) + { + flag2 = 1; + rt_pin_write(DK_BOARD_LED_2, PIN_LOW); + } + else + { + flag2 = 0; + rt_pin_write(DK_BOARD_LED_2, PIN_HIGH); + } +} +void button_3_callback(void *args) +{ + static int flag3 = 0; + if(flag3 == 0) + { + flag3 = 1; + rt_pin_write(DK_BOARD_LED_3, PIN_LOW); + } + else + { + flag3 = 0; + rt_pin_write(DK_BOARD_LED_3, PIN_HIGH); + } +} +void button_4_callback(void *args) +{ + static int flag4 = 0; + if(flag4 == 0) + { + flag4 = 1; + rt_pin_write(DK_BOARD_LED_4, PIN_LOW); + } + else + { + flag4 = 0; + rt_pin_write(DK_BOARD_LED_4, PIN_HIGH); + } +} + +void gpio_sample(void) +{ + rt_err_t err_code; + + rt_pin_mode(DK_BOARD_LED_1, PIN_MODE_OUTPUT); + rt_pin_mode(DK_BOARD_LED_2, PIN_MODE_OUTPUT); + rt_pin_mode(DK_BOARD_LED_3, PIN_MODE_OUTPUT); + rt_pin_mode(DK_BOARD_LED_4, PIN_MODE_OUTPUT); + + rt_pin_write(DK_BOARD_LED_1, PIN_HIGH); + rt_pin_write(DK_BOARD_LED_2, PIN_HIGH); + rt_pin_write(DK_BOARD_LED_3, PIN_HIGH); + rt_pin_write(DK_BOARD_LED_4, PIN_HIGH); + + err_code = rt_pin_attach_irq(DK_BOARD_BUTTON_1, PIN_IRQ_MODE_FALLING, + button_1_callback, (void*) true); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) + rt_pin_irq_enable(DK_BOARD_BUTTON_1, PIN_IRQ_ENABLE); + + err_code = rt_pin_attach_irq(DK_BOARD_BUTTON_2, PIN_IRQ_MODE_FALLING, + button_2_callback, (void*) true); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) + rt_pin_irq_enable(DK_BOARD_BUTTON_2, PIN_IRQ_ENABLE); + + err_code = rt_pin_attach_irq(DK_BOARD_BUTTON_3, PIN_IRQ_MODE_FALLING, + button_3_callback, (void*) true); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) + rt_pin_irq_enable(DK_BOARD_BUTTON_3, PIN_IRQ_ENABLE); + + err_code = rt_pin_attach_irq(DK_BOARD_BUTTON_4, PIN_IRQ_MODE_FALLING, + button_4_callback, (void*) false); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) + rt_pin_irq_enable(DK_BOARD_BUTTON_4, PIN_IRQ_ENABLE); +} +MSH_CMD_EXPORT(gpio_sample, gpio sample); + #endif /* RT_USING_PIN */ diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index 1bf97f6e4d..756a81495e 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