Hi all,
Using UART is confusing for me because I see various implementations in the documentation. There is a Serial library, then there is the UART driver and HAL. The HAL is further divided to UART and UARTE. I read that the difference between UART and UARTE is that the UARTE uses EasyDMA.
I like to try a few things:
1. Use PPI to setup a timer event to trigger a UART TX task. Eg. Send out "Hello" every 1 second.
2. Use PPI to setup a timer event to trigger a UART RX task. Eg. Read from UART every 1 second.
For (1), I have setup the ppi channel as follows:
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1, nrf_drv_timer_event_address_get(&m_timer1, NRF_TIMER_EVENT_COMPARE0), nrf_drv_uart_task_address_get(&uart_driver_instance, NRF_UART_TASK_STARTTX));
In this case, should I be using nrf_uart_task_address_get or nrf_uarte_task_address_get or nrf_drv_uart_task_address_get?
I also noticed that there is a NRF_UART_TASK_STOPTX. Does it mean that I also need to have an event to trigger a stop task? Otherwise, it will never stop transmitting?
How does the UART tx happen? Should I be placing the string in some register or ram address so that when the task is triggered, the string is automatically send from the tx pin? If I am using UARTE, I presume i should initalise the tx buffer with this function nrf_uarte_tx_buffer_set.?
For(2), the ppi channel is setup as follows:
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1, nrf_drv_timer_event_address_get(&m_timer1, NRF_TIMER_EVENT_COMPARE0), nrf_drv_uart_task_address_get(&uart_driver_instance, NRF_UART_TASK_STARTRX));
Similarly, how does the RX happen? What do I need to configure for the RX data to be stored to memory? How can I access it later when I wake up the CPU? Do I also need another event to stop the RX task?
This is the code that I have now.
#include <stdint.h>
#include "nrf_delay.h"
#include "app_error.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "nrf_drv_uart.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#define UART0_USE_EASY_DMA true
#define UART_EASY_DMA_SUPPORT 1
//#define UART_LEGACY_SUPPORT 1
#define PPI_EXAMPLE_TIMER1_INTERVAL (1000) // Timer interval in milliseconds
static const nrf_drv_uart_t uart_driver_instance = NRF_DRV_UART_INSTANCE(UART0_INSTANCE_INDEX);
static const nrf_drv_timer_t m_timer1 = NRF_DRV_TIMER_INSTANCE(1);
static nrf_ppi_channel_t m_ppi_channel1;
static volatile uint32_t m_counter;
/* Timer event handler. Not used since Timer1 is used only for PPI. */
static void empty_timer_handler(nrf_timer_event_t event_type, void * p_context)
{
}
/** @brief Function for initializing the UART peripheral.
*/
static void uart_init(void)
{
uint32_t err_code = NRF_SUCCESS;
nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
config.use_easy_dma = true;
err_code = nrf_drv_uart_init(&uart_driver_instance, &config, NULL);
APP_ERROR_CHECK(err_code);
}
/** @brief Function for initializing the PPI peripheral.
*/
static void ppi_init(void)
{
uint32_t err_code = NRF_SUCCESS;
err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code);
/* Configure 1st available PPI channel to start UART RX event on TIMER1 COMPARE[0] match,
* which is every even number of seconds.
*/
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,
nrf_drv_timer_event_address_get(&m_timer1,
NRF_TIMER_EVENT_COMPARE0),
nrf_drv_uart_task_address_get(&uart_driver_instance,
NRF_UART_TASK_STARTTX));
APP_ERROR_CHECK(err_code);
// Enable both configured PPI channels
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
APP_ERROR_CHECK(err_code);
}
/** @brief Function for Timer 1 initialization.
* @details Initializes TIMER1 peripheral to generate an event every 1 seconds. The events
* are used to start UART TX or RX via PPI: TIMER1->EVENT_COMPARE[0] triggers UART->TASK_STARTTX/TASK_STARTRX.
*/
static void timer1_init(void)
{
// Check TIMER1 configuration for details.
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
timer_cfg.frequency = NRF_TIMER_FREQ_31250Hz;
ret_code_t err_code = nrf_drv_timer_init(&m_timer1, &timer_cfg, empty_timer_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_timer_extended_compare(&m_timer1,
NRF_TIMER_CC_CHANNEL0,
nrf_drv_timer_ms_to_ticks(&m_timer1,
PPI_EXAMPLE_TIMER1_INTERVAL),
NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
false);
}
/**
* @brief Function for application main entry.
*/
int main(void)
{
uint32_t old_val = 0;
uint32_t err_code;
err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
uart_init();
ppi_init();
timer1_init(); // Timer to generate events
nrf_drv_timer_enable(&m_timer1);
while (true)
{
}
}
Thanks in advance!