初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

View File

@@ -0,0 +1,317 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_CLI_BLE_UART)
#include "nrf_cli_ble_uart.h"
#include "ble_nus.h"
#include "nrf_ringbuf.h"
#include "app_timer.h"
#include "nrf_assert.h"
#include "nrf_ble_gatt.h"
#define NRF_LOG_MODULE_NAME cli_ble
#if NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_CLI_BLE_UART_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR
#else //NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif //NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#if NRF_CLI_BLE_UART_MAX_CLIENTS > NRF_SDH_BLE_TOTAL_LINK_COUNT
#error "Too few BLE peripheral links are supported by the BLE SDH module for the maximal number \
of BLE transport instances"
#endif
#define NRF_CLI_BLE_UART_TIMEOUT_MS 50
#define OVERHEAD_LENGTH (OPCODE_LENGTH + HANDLE_LENGTH)
BLE_NUS_DEF(m_nus, NRF_CLI_BLE_UART_MAX_CLIENTS);
BLE_LINK_CTX_MANAGER_DEF(m_link_ctx_storage,
NRF_CLI_BLE_UART_MAX_CLIENTS,
sizeof(nrf_cli_ble_uart_internal_t *));
static void tx_try(nrf_cli_ble_uart_internal_t * p_instance, uint32_t threshold)
{
uint8_t * p_out_data;
size_t out_data_len =
nrf_ble_gatt_eff_mtu_get(p_instance->p_gatt, p_instance->p_cb->conn_handle) -
OVERHEAD_LENGTH;
ret_code_t err_code = nrf_ringbuf_get(p_instance->p_tx_ringbuf,
&p_out_data,
&out_data_len,
true);
if (err_code == NRF_SUCCESS)
{
if (out_data_len >= threshold)
{
size_t req_data_len = out_data_len;
err_code = ble_nus_data_send(&m_nus,
p_out_data,
(uint16_t*)&out_data_len,
p_instance->p_cb->conn_handle);
if ((err_code == NRF_ERROR_BUSY) || (err_code == NRF_ERROR_RESOURCES))
{
out_data_len = 0;
}
NRF_LOG_INFO("Conn_handle:%d TX req_len: %d, len: %d",
p_instance->p_cb->conn_handle, req_data_len, out_data_len);
NRF_LOG_HEXDUMP_DEBUG(p_out_data, out_data_len);
err_code = nrf_ringbuf_free(p_instance->p_tx_ringbuf, out_data_len);
ASSERT(err_code == NRF_SUCCESS);
}
else
{
err_code = nrf_ringbuf_free(p_instance->p_tx_ringbuf, 0);
ASSERT(err_code == NRF_SUCCESS);
}
}
}
static void nus_data_handler(ble_nus_evt_t * p_nus_evt)
{
ret_code_t err_code = NRF_SUCCESS;
nrf_cli_ble_uart_internal_t * p_instance;
nrf_cli_ble_uart_internal_t ** pp_instance;
err_code = blcm_link_ctx_get(&m_link_ctx_storage, p_nus_evt->conn_handle, (void *) &pp_instance);
ASSERT(err_code == NRF_SUCCESS);
p_instance = *pp_instance;
switch (p_nus_evt->type)
{
case BLE_NUS_EVT_RX_DATA:
{
NRF_LOG_INFO("Conn_handle:%d, Received: %d",
p_instance->p_cb->conn_handle, p_nus_evt->params.rx_data.length);
NRF_LOG_HEXDUMP_DEBUG(p_nus_evt->params.rx_data.p_data, p_nus_evt->params.rx_data.length);
size_t len = ((size_t) p_nus_evt->params.rx_data.length) & 0x0000FFFF;
err_code = nrf_ringbuf_cpy_put(p_instance->p_rx_ringbuf,
p_nus_evt->params.rx_data.p_data,
(size_t *)&len);
ASSERT(err_code == NRF_SUCCESS);
p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, p_instance->p_cb->p_context);
break;
}
case BLE_NUS_EVT_TX_RDY:
{
//TX_Complete
uint32_t max_tx_len = nrf_ble_gatt_eff_mtu_get(p_instance->p_gatt,
p_instance->p_cb->conn_handle) -
OVERHEAD_LENGTH;
tx_try(p_instance, max_tx_len);
p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_instance->p_cb->p_context);
break;
}
case BLE_NUS_EVT_COMM_STARTED:
p_instance->p_cb->service_started = true;
err_code = app_timer_start(*p_instance->p_timer,
APP_TIMER_TICKS(NRF_CLI_BLE_UART_TIMEOUT_MS),
p_instance);
ASSERT(err_code == NRF_SUCCESS);
NRF_LOG_INFO("Conn_handle:%d, communication started", p_instance->p_cb->conn_handle);
break;
case BLE_NUS_EVT_COMM_STOPPED:
(void)app_timer_stop(*p_instance->p_timer);
p_instance->p_cb->service_started = false;
NRF_LOG_INFO("Conn_handle:%d, communication stopped", p_instance->p_cb->conn_handle);
break;
default:
break;
}
}
static void timer_handler(void * p_context)
{
nrf_cli_ble_uart_internal_t * p_instance = (nrf_cli_ble_uart_internal_t *) p_context;
tx_try(p_instance, 1);
ret_code_t err_code = app_timer_start(*p_instance->p_timer,
APP_TIMER_TICKS(NRF_CLI_BLE_UART_TIMEOUT_MS), (void *)p_instance);
ASSERT(err_code == NRF_SUCCESS);
UNUSED_VARIABLE(err_code);
UNUSED_PARAMETER(p_context);
}
ret_code_t nrf_cli_ble_uart_service_init(void)
{
ble_nus_init_t nus_init;
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = nus_data_handler;
return ble_nus_init(&m_nus, &nus_init);
}
static ret_code_t cli_ble_uart_init(nrf_cli_transport_t const * p_transport,
void const * p_config,
nrf_cli_transport_handler_t evt_handler,
void * p_context)
{
ret_code_t err_code;
nrf_cli_ble_uart_internal_t ** pp_instance;
nrf_cli_ble_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
nrf_cli_ble_uart_config_t * p_ble_uart_config = (nrf_cli_ble_uart_config_t *)p_config;
p_instance->p_cb->handler = evt_handler;
p_instance->p_cb->p_context = p_context;
p_instance->p_cb->service_started = false;
p_instance->p_cb->conn_handle = p_ble_uart_config->conn_handle;
NRF_LOG_INFO("Conn_handle:%d init.", p_ble_uart_config->conn_handle);
nrf_ringbuf_init(p_instance->p_rx_ringbuf);
nrf_ringbuf_init(p_instance->p_tx_ringbuf);
err_code = blcm_link_ctx_get(&m_link_ctx_storage,
p_ble_uart_config->conn_handle,
(void *) &pp_instance);
VERIFY_SUCCESS(err_code);
*pp_instance = p_instance;
return NRF_SUCCESS;
}
static ret_code_t cli_ble_uart_uninit(nrf_cli_transport_t const * p_transport)
{
nrf_cli_ble_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
NRF_LOG_INFO("Conn_handle:%d uninit.", p_instance->p_cb->conn_handle);
ret_code_t ret = app_timer_stop(*p_instance->p_timer);
return ret;
}
static ret_code_t cli_ble_uart_enable(nrf_cli_transport_t const * p_transport, bool blocking)
{
nrf_cli_ble_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
NRF_LOG_INFO("Conn_handle:%d, enable blocking:%d", blocking, p_instance->p_cb->conn_handle);
if (blocking)
{
return NRF_ERROR_NOT_SUPPORTED;
}
else
{
ret_code_t err_code = NRF_SUCCESS;
if (!p_instance->p_cb->timer_created)
{
err_code = app_timer_create(p_instance->p_timer,
APP_TIMER_MODE_SINGLE_SHOT,
timer_handler);
p_instance->p_cb->timer_created = true;
}
return err_code;
}
}
static ret_code_t cli_ble_uart_read(nrf_cli_transport_t const * p_transport,
void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
nrf_cli_ble_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
*p_cnt = length;
ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt);
if (*p_cnt)
{
NRF_LOG_INFO("Conn_handle:%d, read req_len:%d read_len: %d",
p_instance->p_cb->conn_handle,
length,
*p_cnt);
NRF_LOG_HEXDUMP_DEBUG(p_data, *p_cnt);
}
return err_code;
}
static ret_code_t cli_ble_uart_write(nrf_cli_transport_t const * p_transport,
const void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
nrf_cli_ble_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
ret_code_t err_code = NRF_SUCCESS;
if (p_instance->p_cb->service_started)
{
*p_cnt = length;
err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt);
NRF_LOG_INFO("Conn_handle:%d, write req:%d, buffered:%d",
p_instance->p_cb->conn_handle, length, *p_cnt);
NRF_LOG_HEXDUMP_DEBUG(p_data, *p_cnt);
}
else
{
NRF_LOG_INFO("Conn_handle:%d, write req:%d. Notifications not enabled",
p_instance->p_cb->conn_handle, length);
*p_cnt = length;
p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_instance->p_cb->p_context);
}
return err_code;
}
const nrf_cli_transport_api_t nrf_cli_ble_uart_transport_api = {
.init = cli_ble_uart_init,
.uninit = cli_ble_uart_uninit,
.enable = cli_ble_uart_enable,
.read = cli_ble_uart_read,
.write = cli_ble_uart_write,
};
#endif //NRF_MODULE_ENABLED(NRF_CLI_BLE_UART)

View File

@@ -0,0 +1,123 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_BLE_UART_H__
#define NRF_CLI_BLE_UART_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "nrf_cli.h"
#include "ble.h"
#include "app_timer.h"
#include "nrf_ringbuf.h"
#include "nordic_common.h"
#include "nrf_ble_gatt.h"
/**@file
*
* @defgroup nrf_cli_ble_uart BLE UART command line interface transport layer
* @ingroup nrf_cli
*
* @{
*
*/
/**
* @brief Command line interface transport.
*/
ret_code_t nrf_cli_ble_uart_service_init(void);
extern const nrf_cli_transport_api_t nrf_cli_ble_uart_transport_api;
typedef struct nrf_cli_ble_uart_internal_s nrf_cli_ble_uart_internal_t;
typedef struct {
nrf_cli_transport_handler_t handler;
void * p_context;
uint16_t conn_handle;
bool timer_created;
bool service_started;
} nrf_cli_ble_uart_internal_cb_t;
struct nrf_cli_ble_uart_internal_s {
nrf_cli_transport_t transport;
nrf_cli_ble_uart_internal_cb_t * p_cb;
app_timer_id_t const * p_timer;
nrf_ringbuf_t const * p_rx_ringbuf;
nrf_ringbuf_t const * p_tx_ringbuf;
nrf_ble_gatt_t const * p_gatt;
};
typedef struct {
uint16_t conn_handle;
} nrf_cli_ble_uart_config_t;
/**@brief CLI Bluetooth transport definition.
*
* @param _name Name of the instance.
* @param _p_gatt Pointer to the nrf_ble_gatt module.
* @param _tx_buf_sz Size of TX ring buffer.
* @param _rx_buf_sz Size of RX ring buffer.
*/
#define NRF_CLI_BLE_UART_DEF(_name, _p_gatt, _tx_buf_sz, _rx_buf_sz) \
APP_TIMER_DEF(CONCAT_2(_name, _timer)); \
NRF_RINGBUF_DEF(CONCAT_2(_name,_tx_ringbuf), _tx_buf_sz); \
NRF_RINGBUF_DEF(CONCAT_2(_name,_rx_ringbuf), _rx_buf_sz); \
static nrf_cli_ble_uart_internal_cb_t CONCAT_2(_name, _cb); \
static const nrf_cli_ble_uart_internal_t _name = { \
.transport = {.p_api = &nrf_cli_ble_uart_transport_api}, \
.p_cb = &CONCAT_2(_name, _cb), \
.p_timer = &CONCAT_2(_name, _timer), \
.p_rx_ringbuf = &CONCAT_2(_name,_rx_ringbuf), \
.p_tx_ringbuf = &CONCAT_2(_name,_tx_ringbuf), \
.p_gatt = _p_gatt, \
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_BLE_UART_H__ */

View File

@@ -0,0 +1,243 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM)
#include "nrf_cli_cdc_acm.h"
#include "nrf_queue.h"
#include "app_error.h"
#include "nrf_assert.h"
#if APP_USBD_CONFIG_EVENT_QUEUE_ENABLE
#error "Current CLI CDC implementation supports only USB with event queue disabled (see APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)"
#endif
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
app_usbd_cdc_acm_user_event_t event);
/*lint -save -e26 -e40 -e64 -e123 -e505 -e651*/
/**
* @brief CDC_ACM class instance.
* */
APP_USBD_CDC_ACM_GLOBAL_DEF(nrf_cli_cdc_acm,
cdc_acm_user_ev_handler,
NRF_CLI_CDC_ACM_COMM_INTERFACE,
NRF_CLI_CDC_ACM_DATA_INTERFACE,
NRF_CLI_CDC_ACM_COMM_EPIN,
NRF_CLI_CDC_ACM_DATA_EPIN,
NRF_CLI_CDC_ACM_DATA_EPOUT,
APP_USBD_CDC_COMM_PROTOCOL_AT_V250
);
/*lint -restore*/
NRF_QUEUE_DEF(uint8_t,
m_rx_queue,
2*NRF_DRV_USBD_EPSIZE,
NRF_QUEUE_MODE_OVERFLOW);
static char m_rx_buffer[NRF_DRV_USBD_EPSIZE];
static nrf_cli_cdc_acm_internal_t * mp_internal;
/**
* @brief Set new buffer and process any data if already present
*
* This is internal function.
* The result of its execution is the library waiting for the event of the new data.
* If there is already any data that was returned from the CDC internal buffer
* it would be processed here.
*/
static void cdc_acm_process_and_prepare_buffer(app_usbd_cdc_acm_t const * p_cdc_acm)
{
for (;;)
{
if (!nrf_queue_is_empty(&m_rx_queue))
{
mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, mp_internal->p_cb->p_context);
}
ret_code_t ret = app_usbd_cdc_acm_read_any(&nrf_cli_cdc_acm,
m_rx_buffer,
sizeof(m_rx_buffer));
if (ret == NRF_SUCCESS)
{
size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size);
ASSERT(size == qsize);
UNUSED_VARIABLE(qsize);
}
else if (ret == NRF_ERROR_IO_PENDING)
{
break;
}
else
{
APP_ERROR_CHECK(ret);
break;
}
}
}
/**
* @brief User event handler.
* */
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
app_usbd_cdc_acm_user_event_t event)
{
app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
switch (event)
{
case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
{
/*Setup first transfer*/
cdc_acm_process_and_prepare_buffer(p_cdc_acm);
break;
}
case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context);
break;
case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context);
break;
case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
{
/*Get amount of data transfered*/
size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size);
ASSERT(size == qsize);
UNUSED_VARIABLE(qsize);
/*Setup next transfer*/
cdc_acm_process_and_prepare_buffer(p_cdc_acm);
break;
}
default:
break;
}
}
static ret_code_t cli_cdc_acm_init(nrf_cli_transport_t const * p_transport,
void const * p_config,
nrf_cli_transport_handler_t evt_handler,
void * p_context)
{
UNUSED_PARAMETER(p_config);
nrf_cli_cdc_acm_internal_t * p_internal =
CONTAINER_OF(p_transport, nrf_cli_cdc_acm_internal_t, transport);
p_internal->p_cb->handler = evt_handler;
p_internal->p_cb->p_context = p_context;
mp_internal = p_internal;
return NRF_SUCCESS;
}
static ret_code_t cli_cdc_acm_uninit(nrf_cli_transport_t const * p_transport)
{
UNUSED_PARAMETER(p_transport);
return NRF_SUCCESS;
}
static ret_code_t cli_cdc_acm_enable(nrf_cli_transport_t const * p_transport,
bool blocking)
{
UNUSED_PARAMETER(p_transport);
if (blocking)
{
return NRF_ERROR_NOT_SUPPORTED;
}
else
{
return NRF_SUCCESS;
}
}
static ret_code_t cli_cdc_acm_read(nrf_cli_transport_t const * p_transport,
void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
UNUSED_PARAMETER(p_transport);
size_t size = nrf_queue_out(&m_rx_queue, p_data, length);
*p_cnt = size;
return NRF_SUCCESS;
}
static ret_code_t cli_cdc_acm_write(nrf_cli_transport_t const * p_transport,
void const * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
UNUSED_PARAMETER(p_transport);
ret_code_t ret;
ret = app_usbd_cdc_acm_write(&nrf_cli_cdc_acm, p_data, length);
if (ret == NRF_SUCCESS || ret == NRF_ERROR_INVALID_STATE)
{
*p_cnt = length;
ret = NRF_SUCCESS;
}
else if (ret == NRF_ERROR_BUSY)
{
*p_cnt = 0;
ret = NRF_SUCCESS;
}
else
{
/* Nothing to do */
}
return ret;
}
const nrf_cli_transport_api_t nrf_cli_cdc_acm_transport_api = {
.init = cli_cdc_acm_init,
.uninit = cli_cdc_acm_uninit,
.enable = cli_cdc_acm_enable,
.read = cli_cdc_acm_read,
.write = cli_cdc_acm_write,
};
#endif // NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM)

View File

@@ -0,0 +1,95 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_CDC_ACM_H__
#define NRF_CLI_CDC_ACM_H__
#include <stdbool.h>
#include "nrf_cli.h"
#include "app_usbd_cdc_acm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@file
*
* @defgroup nrf_cli_cdc_acm CDC ACM command line interface transport layer
* @ingroup nrf_cli
*
* @{
*
*/
/**
* @brief Command line interface transport.
*/
extern const nrf_cli_transport_api_t nrf_cli_cdc_acm_transport_api;
/**
* @brief Command line interface class instance.
*/
extern const app_usbd_cdc_acm_t nrf_cli_cdc_acm;
typedef struct {
nrf_cli_transport_handler_t handler;
void * p_context;
} nrf_cli_cdc_acm_internal_cb_t;
typedef struct {
nrf_cli_transport_t transport;
nrf_cli_cdc_acm_internal_cb_t * p_cb;
} nrf_cli_cdc_acm_internal_t;
/**@brief CLI USB transport definition */
#define NRF_CLI_CDC_ACM_DEF(_name_) \
static nrf_cli_cdc_acm_internal_cb_t CONCAT_2(_name_, _cb); \
static const nrf_cli_cdc_acm_internal_t _name_ = { \
.transport = {.p_api = &nrf_cli_cdc_acm_transport_api}, \
.p_cb = &CONCAT_2(_name_, _cb), \
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_CDC_ACM_H__ */

View File

@@ -0,0 +1,164 @@
/**
* Copyright (c) 2018 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "nrf_cli.h"
#include "nrf_log.h"
static void cmd_reset(nrf_cli_t const * p_cli, size_t argc, char **argv)
{
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
return;
}
NVIC_SystemReset();
}
static void cmd_error(nrf_cli_t const * p_cli, size_t argc, char **argv)
{
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
return;
}
APP_ERROR_CHECK(NRF_ERROR_INTERNAL);
}
static void cmd_app_size(nrf_cli_t const * p_cli, size_t argc, char **argv)
{
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
return;
}
nrf_cli_fprintf(p_cli,
NRF_CLI_NORMAL,
"Application address:%d (0x%08X), size: %d (0x%08X)\r\n",
CODE_START,
CODE_START,
CODE_SIZE,
CODE_SIZE);
}
static void cmd_log_msg_error(nrf_cli_t const * p_cli, size_t argc, char **argv)
{
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
return;
}
switch (argc-1)
{
case 0:
NRF_LOG_ERROR("test error message");
break;
case 1:
NRF_LOG_ERROR("test error message: %d", strtol(argv[1], NULL, 10));
break;
case 2:
NRF_LOG_ERROR("test error message: %d %d", strtol(argv[1], NULL, 10),
strtol(argv[2], NULL, 10));
break;
default:
NRF_LOG_ERROR("test error message with more than 3 arguments");
break;
}
}
static void cmd_log_msg_warning(nrf_cli_t const * p_cli, size_t argc, char **argv)
{
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
return;
}
switch (argc-1)
{
case 0:
NRF_LOG_WARNING("test warning message");
break;
case 1:
NRF_LOG_WARNING("test warning message: %d", strtol(argv[1], NULL, 10));
break;
case 2:
NRF_LOG_WARNING("test warning message: %d %d", strtol(argv[1], NULL, 10),
strtol(argv[2], NULL, 10));
break;
default:
NRF_LOG_WARNING("test warning message with more than 3 arguments");
break;
}
}
/**
* @brief Command set array
* */
NRF_CLI_CMD_REGISTER(reset, NULL, "System reset.", cmd_reset);
NRF_CLI_CMD_REGISTER(error, NULL, "Trigger error.", cmd_error);
NRF_CLI_CMD_REGISTER(app_size, NULL, "Print application size.", cmd_app_size);
NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_msg)
{
NRF_CLI_CMD(error, NULL, "Error log message with parameters", cmd_log_msg_error),
NRF_CLI_CMD(warning, NULL, "Warning log message with parameters", cmd_log_msg_warning),
NRF_CLI_SUBCMD_SET_END
};
NRF_CLI_CMD_REGISTER(log_msg, &m_sub_log_msg, "Trigger log message with decimal arguments", NULL);

View File

@@ -0,0 +1,252 @@
/**
* Copyright (c) 2018 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#include "nrf_cli_libuarte.h"
#include "nrf_libuarte_async.h"
#include "nrf_assert.h"
#include "nrf_atomic.h"
#define NRF_LOG_MODULE_NAME cli_libuarte
#if NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR
#else //NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif //NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
static cli_libuarte_internal_t * mp_internal;
static nrf_atomic_flag_t m_uart_busy;
NRF_LIBUARTE_ASYNC_DEFINE(libuarte,
NRF_CLI_LIBUARTE_UARTE_INSTANCE,
NRF_CLI_LIBUARTE_TIMER_INSTANCE,
NRF_CLI_LIBUARTE_TIMEOUT_RTC_INSTANCE,
NRF_CLI_LIBUARTE_TIMEOUT_TIMER_INSTANCE,
3, 255);
static void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_event)
{
cli_libuarte_internal_t * p_internal = mp_internal;
ret_code_t err_code = NRF_SUCCESS;
size_t len;
UNUSED_VARIABLE(err_code);
switch (p_event->type)
{
case NRF_LIBUARTE_ASYNC_EVT_ERROR:
NRF_LOG_WARNING("(evt) ERROR");
break;
case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
{
len = (size_t)((uint32_t)p_event->data.rxtx.length & 0x0000FFFF);
err_code = nrf_ringbuf_cpy_put(p_internal->p_rx_ringbuf,
p_event->data.rxtx.p_data,
&len);
ASSERT(err_code == NRF_SUCCESS);
if (len != p_event->data.rxtx.length)
{
NRF_LOG_WARNING("Data lost, no room in RX ringbuf");
}
nrf_libuarte_async_rx_free(&libuarte, p_event->data.rxtx.p_data, p_event->data.rxtx.length);
if (p_event->data.rxtx.length)
{
NRF_LOG_DEBUG("(evt) RXRDY length:%d", p_event->data.rxtx.length);
NRF_LOG_HEXDUMP_DEBUG(p_event->data.rxtx.p_data, p_event->data.rxtx.length);
p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY,
p_internal->p_cb->p_context);
}
break;
}
case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
err_code = nrf_ringbuf_free(p_internal->p_tx_ringbuf, p_event->data.rxtx.length);
ASSERT(err_code == NRF_SUCCESS);
uint8_t * p_data;
len = 255;
err_code = nrf_ringbuf_get(p_internal->p_tx_ringbuf, &p_data, &len, true);
ASSERT(err_code == NRF_SUCCESS);
if (len)
{
NRF_LOG_DEBUG("(evt) Started TX (%d).", len);
err_code = nrf_libuarte_async_tx(&libuarte, p_data, len);
ASSERT(err_code == NRF_SUCCESS);
}
else
{
m_uart_busy = false;
}
p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_internal->p_cb->p_context);
NRF_LOG_DEBUG("(evt) TX completed (%d)", p_event->data.rxtx.length);
break;
default:
NRF_LOG_ERROR("(evt) Unknown event");
ASSERT(false);
break;
}
}
static ret_code_t cli_libuarte_init(nrf_cli_transport_t const * p_transport,
void const * p_config,
nrf_cli_transport_handler_t evt_handler,
void * p_context)
{
cli_libuarte_internal_t * p_internal = CONTAINER_OF(p_transport,
cli_libuarte_internal_t,
transport);
mp_internal = p_internal;
m_uart_busy = false;
p_internal->p_cb->handler = evt_handler;
p_internal->p_cb->p_context = p_context;
p_internal->p_cb->blocking = false;
cli_libuarte_config_t const * p_cli_libuarte_config = (cli_libuarte_config_t *)p_config;
nrf_libuarte_async_config_t uart_async_config = {
.tx_pin = p_cli_libuarte_config->tx_pin,
.rx_pin = p_cli_libuarte_config->rx_pin,
.baudrate = p_cli_libuarte_config->baudrate,
.parity = p_cli_libuarte_config->parity,
.hwfc = p_cli_libuarte_config->hwfc,
.timeout_us = 100,
.int_prio = APP_IRQ_PRIORITY_LOW
};
ret_code_t err_code = nrf_libuarte_async_init(&libuarte, &uart_async_config, uart_event_handler, NULL);
if (err_code == NRF_SUCCESS)
{
nrf_ringbuf_init(p_internal->p_rx_ringbuf);
nrf_ringbuf_init(p_internal->p_tx_ringbuf);
}
return err_code;
}
static ret_code_t cli_libuarte_uninit(nrf_cli_transport_t const * p_transport)
{
UNUSED_PARAMETER(p_transport);
nrf_libuarte_async_uninit(&libuarte);
return NRF_SUCCESS;
}
static ret_code_t cli_libuarte_enable(nrf_cli_transport_t const * p_transport,
bool blocking)
{
UNUSED_PARAMETER(p_transport);
if (blocking)
{
return NRF_ERROR_NOT_SUPPORTED;
}
else
{
nrf_libuarte_async_enable(&libuarte);
}
return NRF_SUCCESS;
}
static ret_code_t cli_libuarte_read(nrf_cli_transport_t const * p_transport,
void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
cli_libuarte_internal_t * p_instance =
CONTAINER_OF(p_transport, cli_libuarte_internal_t, transport);
*p_cnt = length;
ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt);
if (*p_cnt)
{
NRF_LOG_DEBUG("Read %d bytes (requested %d)", *p_cnt, length);
}
return err_code;
}
static ret_code_t cli_libuarte_write(nrf_cli_transport_t const * p_transport,
void const * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
cli_libuarte_internal_t * p_instance = CONTAINER_OF(p_transport,
cli_libuarte_internal_t,
transport);
*p_cnt = length;
ret_code_t err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt);
if (err_code == NRF_SUCCESS)
{
NRF_LOG_DEBUG("Requested write: %d, copied to ringbuf: %d.", length, *p_cnt);
if (nrf_atomic_flag_set_fetch(&m_uart_busy))
{
return err_code;
}
uint8_t * p_buf;
size_t len = 255;
if (nrf_ringbuf_get(p_instance->p_tx_ringbuf, &p_buf, &len, true) == NRF_SUCCESS)
{
NRF_LOG_DEBUG("Started TX (%d).", len);
err_code = nrf_libuarte_async_tx(&libuarte, p_buf, len);
if (p_instance->p_cb->blocking && (err_code == NRF_SUCCESS))
{
(void)nrf_ringbuf_free(p_instance->p_tx_ringbuf, len);
m_uart_busy = false;
}
}
}
return err_code;
}
const nrf_cli_transport_api_t cli_libuarte_transport_api = {
.init = cli_libuarte_init,
.uninit = cli_libuarte_uninit,
.enable = cli_libuarte_enable,
.read = cli_libuarte_read,
.write = cli_libuarte_write,
};

View File

@@ -0,0 +1,112 @@
/**
* Copyright (c) 2018 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_LOG_BACKEND_LIBUARTE_H__
#define NRF_LOG_BACKEND_LIBUARTE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "nrf_cli.h"
#include "nrf_ringbuf.h"
#include "app_timer.h"
#include "nrf_uarte.h"
/**@file
*
* @defgroup nrf_cli_libuarte libUARTE command line interface transport layer.
* @ingroup nrf_cli
*
* @{
*
*/
/**
* @brief Command line interface transport.
* */
extern const nrf_cli_transport_api_t cli_libuarte_transport_api;
typedef struct cli_libuarte_internal_s cli_libuarte_internal_t;
typedef struct {
nrf_cli_transport_handler_t handler;
void * p_context;
bool blocking;
} cli_libuarte_internal_cb_t;
struct cli_libuarte_internal_s {
nrf_cli_transport_t transport;
cli_libuarte_internal_cb_t * p_cb;
nrf_ringbuf_t const * p_rx_ringbuf;
nrf_ringbuf_t const * p_tx_ringbuf;
};
typedef struct
{
uint32_t tx_pin;
uint32_t rx_pin;
nrf_uarte_hwfc_t hwfc; ///< Flow control configuration.
nrf_uarte_parity_t parity; ///< Parity configuration.
nrf_uarte_baudrate_t baudrate; ///< Baudrate.
} cli_libuarte_config_t;
/**@brief CLI libUARTE transport definition.
*
* @param _name Name of instance.
* @param _tx_buf_sz Size of TX ring buffer.
* @param _rx_buf_sz Size of RX ring buffer.
*/
#define NRF_CLI_LIBUARTE_DEF(_name, _tx_buf_sz, _rx_buf_sz) \
NRF_RINGBUF_DEF(CONCAT_2(_name,_tx_ringbuf), _tx_buf_sz); \
NRF_RINGBUF_DEF(CONCAT_2(_name,_rx_ringbuf), _rx_buf_sz); \
static cli_libuarte_internal_cb_t CONCAT_2(_name, _cb); \
static const cli_libuarte_internal_t _name = { \
.transport = {.p_api = &cli_libuarte_transport_api}, \
.p_cb = &CONCAT_2(_name, _cb), \
.p_rx_ringbuf = &CONCAT_2(_name,_rx_ringbuf), \
.p_tx_ringbuf = &CONCAT_2(_name,_tx_ringbuf), \
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_LOG_BACKEND_LIBUARTE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,704 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_H__
#define NRF_CLI_H__
#include "sdk_common.h"
#include "nrf_cli_types.h"
#include "nrf_section.h"
#include "nrf_log_backend_interface.h"
#include "nrf_queue.h"
#include "nrf_log_ctrl.h"
#include "app_util_platform.h"
#include "nrf_memobj.h"
#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
#include "task_manager.h"
#endif
#include "nrf_fprintf.h"
#include "nrf_fprintf_format.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_CLI_RX_BUFF_SIZE 16
/* CLI reserves top task manager flags, bits 0...18 are available for application. */
#define NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT (1UL << 19)
#define NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT (1UL << 20)
#define NRF_CLI_LOG_PENDING_TASK_EVT (1UL << 21)
#define NRF_CLI_CMD_EXECUTE_EVT (1UL << 22)
#define NRF_CLI_KILL_TASK_EVT (1UL << 23)
#define NRF_CLI_TASK_EVTS (NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT | \
NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT | \
NRF_CLI_LOG_PENDING_TASK_EVT | \
NRF_CLI_CMD_EXECUTE_EVT | \
NRF_CLI_KILL_TASK_EVT)
/**
* @defgroup nrf_cli Command Line Interface
* @ingroup app_common
*
* @brief Module for unified command line handling.
*
* @{
*/
/**
* @brief Aliases to: @ref nrf_cli, @ref nrf_cli_cmd_entry, and @ref nrf_cli_static_entry.
* Must be created here to satisfy module declaration order dependencies.
*/
typedef struct nrf_cli nrf_cli_t;
typedef struct nrf_cli_cmd_entry nrf_cli_cmd_entry_t;
typedef struct nrf_cli_static_entry nrf_cli_static_entry_t;
/**
* @brief CLI dynamic command descriptor.
*
* @details Function shall fill the received @ref nrf_cli_static_entry structure with requested (idx)
* dynamic subcommand data. If there is more than one dynamic subcommand available,
* the function shall ensure that the returned commands: p_static->p_syntax are sorted in
* alphabetical order. If idx exceeds the available dynamic subcommands, the function must write
* to p_static->p_syntax NULL value. This will indicate to the CLI module that
* there are no more dynamic commands to read.
*/
typedef void (*nrf_cli_dynamic_get)(size_t idx, nrf_cli_static_entry_t * p_static);
/**
* @brief CLI command descriptor.
*/
struct nrf_cli_cmd_entry
{
bool is_dynamic;
union
{
nrf_cli_dynamic_get p_dynamic_get; //!< Pointer to function returning dynamic commands.
nrf_cli_static_entry_t const * p_static; //!< Pointer to array of static commands.
} u;
};
/**
* @brief CLI command handler prototype.
*/
typedef void (*nrf_cli_cmd_handler)(nrf_cli_t const * p_cli, size_t argc, char **argv);
/**
* @brief CLI static command descriptor.
*/
struct nrf_cli_static_entry
{
char const * p_syntax; //!< Command syntax strings.
char const * p_help; //!< Command help string.
nrf_cli_cmd_entry_t const * p_subcmd; //!< Pointer to subcommand.
nrf_cli_cmd_handler handler; //!< Command handler.
};
/**
* @brief Macro for defining and adding a root command (level 0).
*
* @note Each root command shall have unique syntax.
*
* @param[in] p_syntax Command syntax (for example: history).
* @param[in] p_subcmd Pointer to a subcommands array.
* @param[in] p_help Pointer to a command help string.
* @param[in] p_handler Pointer to a function handler.
*/
#define NRF_CLI_CMD_REGISTER(p_syntax, p_subcmd, p_help, p_handler) \
nrf_cli_static_entry_t const CONCAT_3(nrf_cli_, p_syntax, _raw) = \
NRF_CLI_CMD(p_syntax, p_subcmd, p_help, p_handler); \
NRF_SECTION_ITEM_REGISTER(cli_command, \
nrf_cli_cmd_entry_t const CONCAT_3(nrf_cli_, p_syntax, _const)) = { \
.is_dynamic = false, \
.u = {.p_static = &CONCAT_3(nrf_cli_, p_syntax, _raw)} \
}; \
NRF_SECTION_ITEM_REGISTER(cli_sorted_cmd_ptrs, char const * CONCAT_2(p_syntax, _str_ptr))
/**
* @brief Macro for creating a subcommand set. It must be used outside of any function body.
*
* @param[in] name Name of the subcommand set.
*/
#define NRF_CLI_CREATE_STATIC_SUBCMD_SET(name) \
/*lint -save -e85 -e31*/ \
static nrf_cli_static_entry_t const CONCAT_2(name, _raw)[]; \
static nrf_cli_cmd_entry_t const name = { \
.is_dynamic = false, \
.u = {.p_static = CONCAT_2(name, _raw) } \
}; \
static nrf_cli_static_entry_t const CONCAT_2(name, _raw)[] = /*lint -restore*/
/**
* @brief Define ending subcommands set.
*
*/
#define NRF_CLI_SUBCMD_SET_END {NULL}
/**
* @brief Macro for creating a dynamic entry.
*
* @param[in] name Name of the dynamic entry.
* @param[in] p_get Pointer to the function returning dynamic commands array @ref nrf_cli_dynamic_get.
*/
#define NRF_CLI_CREATE_DYNAMIC_CMD(name, p_get) \
/*lint -save -e19*/ \
static nrf_cli_cmd_entry_t const name = { \
.is_dynamic = true, \
.u = { .p_dynamic_get = p_get } \
}; /*lint -restore*/
/** @brief Macro for creating subcommands when C++ compiler is used.
*
* Example usage:
* @code
* NRF_CLI_CPP_CREATE_STATIC_SUBCMD_SET(cmd_syntax,
* NRF_CLI_CMD(abc, ...),
* NRF_CLI_CMD(def, ...),
* NRF_CLI_SUBCMD_SET_END
* );
* @endcode
*/
#define NRF_CLI_CPP_CREATE_STATIC_SUBCMD_SET(name, ...) \
static nrf_cli_static_entry_t const CONCAT_2(name, _raw)[] = { \
__VA_ARGS__ \
}; \
static nrf_cli_cmd_entry_t const name = { \
.is_dynamic = false, \
.u = { .p_static = CONCAT_2(name, _raw) } \
}
/**
* @brief Initializes a CLI command (@ref nrf_cli_static_entry).
*
* @param[in] _p_syntax Command syntax (for example: history).
* @param[in] _p_subcmd Pointer to a subcommands array.
* @param[in] _p_help Pointer to a command help string.
* @param[in] _p_handler Pointer to a function handler.
*/
#define NRF_CLI_CMD(_p_syntax, _p_subcmd, _p_help, _p_handler) { \
.p_syntax = (const char *) STRINGIFY(_p_syntax), \
.p_help = (const char *) _p_help, \
.p_subcmd = _p_subcmd, \
.handler = _p_handler \
}
/**
* @internal @brief Internal CLI state in response to data received from the terminal.
*/
typedef enum
{
NRF_CLI_RECEIVE_DEFAULT,
NRF_CLI_RECEIVE_ESC,
NRF_CLI_RECEIVE_ESC_SEQ,
NRF_CLI_RECEIVE_TILDE_EXP
} nrf_cli_receive_t;
/**
* @internal @brief Internal CLI state.
*/
typedef enum
{
NRF_CLI_STATE_UNINITIALIZED, //!< State uninitialized.
NRF_CLI_STATE_INITIALIZED, //!< State initialized but not active.
NRF_CLI_STATE_ACTIVE, //!< State active.
NRF_CLI_STATE_PANIC_MODE_ACTIVE, //!< State panic mode activated.
NRF_CLI_STATE_PANIC_MODE_INACTIVE //!< State panic mode requested but not supported.
} nrf_cli_state_t;
/**
* @brief Event type from CLI transport.
*/
typedef enum
{
NRF_CLI_TRANSPORT_EVT_RX_RDY,
NRF_CLI_TRANSPORT_EVT_TX_RDY
} nrf_cli_transport_evt_t;
typedef void (*nrf_cli_transport_handler_t)(nrf_cli_transport_evt_t evt_type, void * p_context);
typedef struct nrf_cli_transport_s nrf_cli_transport_t;
/**
* @brief Unified CLI transport interface.
*/
typedef struct
{
/**
* @brief Function for initializing the CLI transport interface.
*
* @param[in] p_transport Pointer to the transfer instance.
* @param[in] p_config Pointer to instance configuration.
* @param[in] evt_handler Event handler.
* @param[in] p_context Pointer to the context passed to event handler.
*
* @return Standard error code.
*/
ret_code_t (*init)(nrf_cli_transport_t const * p_transport,
void const * p_config,
nrf_cli_transport_handler_t evt_handler,
void * p_context);
/**
* @brief Function for uninitializing the CLI transport interface.
*
* @param[in] p_transport Pointer to the transfer instance.
*
* @return Standard error code.
*/
ret_code_t (*uninit)(nrf_cli_transport_t const * p_transport);
/**
* @brief Function for reconfiguring the transport to work in blocking mode.
*
* @param p_transport Pointer to the transfer instance.
* @param blocking If true, the transport is enabled in blocking mode.
*
* @return NRF_SUCCESS on successful enabling, error otherwise (also if not supported).
*/
ret_code_t (*enable)(nrf_cli_transport_t const * p_transport,
bool blocking);
/**
* @brief Function for writing data to the transport interface.
*
* @param[in] p_transport Pointer to the transfer instance.
* @param[in] p_data Pointer to the source buffer.
* @param[in] length Source buffer length.
* @param[in] p_cnt Pointer to the sent bytes counter.
*
* @return Standard error code.
*/
ret_code_t (*write)(nrf_cli_transport_t const * p_transport,
const void * p_data,
size_t length,
size_t * p_cnt);
/**
* @brief Function for reading data from the transport interface.
*
* @param[in] p_transport Pointer to the transfer instance.
* @param[in] p_data Pointer to the destination buffer.
* @param[in] length Destination buffer length.
* @param[in] p_cnt Pointer to the received bytes counter.
*
* @return Standard error code.
*/
ret_code_t (*read)(nrf_cli_transport_t const * p_transport,
void * p_data,
size_t length,
size_t * p_cnt);
} nrf_cli_transport_api_t;
struct nrf_cli_transport_s
{
nrf_cli_transport_api_t const * p_api;
};
#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
/**
* @brief CLI history object header.
*/
typedef PACKED_STRUCT
{
nrf_memobj_t * p_prev; //!< Pointer to the next object.
nrf_memobj_t * p_next; //!< Pointer to the previous object.
nrf_cli_cmd_len_t cmd_len; //!< Command length.
} nrf_cli_memobj_header_t;
#endif
#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
typedef struct
{
uint32_t log_lost_cnt; //!< Lost log counter.
} nrf_cli_statistics_t;
#endif
/**
* @internal @brief Flags for internal CLI usage.
*/
typedef struct
{
uint32_t insert_mode : 1; //!< Enables or disables console insert mode for text introduction.
uint32_t show_help : 1; //!< Shows help if the command was called with -h or --help parameter.
uint32_t use_colors : 1; //!< Enables or disables colored syntax.
uint32_t echo : 1; //!< Enables or disables CLI echo.
uint32_t processing : 1; //!< CLI is executing process function.
uint32_t tx_rdy : 1;
uint32_t last_nl : 8; //!< The last received newline character.
} nrf_cli_flag_t;
STATIC_ASSERT(sizeof(nrf_cli_flag_t) == sizeof(uint32_t));
/**
* @internal @brief Union for internal CLI usage.
*/
typedef union
{
uint32_t value;
nrf_cli_flag_t flag;
} nrf_cli_internal_t;
/**
* @brief CLI instance context.
*/
typedef struct
{
nrf_cli_state_t state; //!< Internal module state.
nrf_cli_receive_t receive_state; //!< Escape sequence indicator.
nrf_cli_static_entry_t active_cmd; //!< Currently executed command
nrf_cli_vt100_ctx_t vt100_ctx; //!< VT100 color and cursor position, terminal width.
nrf_cli_cmd_len_t cmd_buff_len; //!< Command length.
nrf_cli_cmd_len_t cmd_buff_pos; //!< Command buffer cursor position.
#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
nrf_cli_cmd_len_t cmd_tmp_buff_len; //!< Command length in tmp buffer
#endif
char cmd_buff[NRF_CLI_CMD_BUFF_SIZE]; //!< Command input buffer.
char temp_buff[NRF_CLI_CMD_BUFF_SIZE]; //!< Temporary buffer used by various functions.
char printf_buff[NRF_CLI_PRINTF_BUFF_SIZE]; //!< Printf buffer size.
#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
nrf_cli_statistics_t statistics; //!< CLI statistics.
#endif
#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
task_id_t task_id;
#endif
#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
nrf_memobj_t * p_cmd_list_head; //!< Pointer to the head of history list.
nrf_memobj_t * p_cmd_list_tail; //!< Pointer to the tail of history list.
nrf_memobj_t * p_cmd_list_element; //!< Pointer to an element of history list.
#endif
volatile nrf_cli_internal_t internal; //!< Internal CLI data
} nrf_cli_ctx_t;
extern const nrf_log_backend_api_t nrf_log_backend_cli_api;
typedef struct
{
nrf_queue_t const * p_queue;
void * p_context;
nrf_cli_t const * p_cli;
} nrf_cli_log_backend_t;
#if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG)
#define NRF_LOG_BACKEND_CLI_DEF(_name_, _queue_size_) \
NRF_QUEUE_DEF(nrf_log_entry_t, \
CONCAT_2(_name_, _queue),_queue_size_, NRF_QUEUE_MODE_NO_OVERFLOW); \
static nrf_cli_log_backend_t CONCAT_2(cli_log_backend,_name_) = { \
.p_queue = &CONCAT_2(_name_, _queue), \
}; \
NRF_LOG_BACKEND_DEF(_name_, nrf_log_backend_cli_api, &CONCAT_2(cli_log_backend,_name_))
#define NRF_CLI_BACKEND_PTR(_name_) &CONCAT_2(_name_, _log_backend)
#else
#define NRF_LOG_BACKEND_CLI_DEF(_name_, _queue_sz_)
#define NRF_CLI_BACKEND_PTR(_name_) NULL
#endif
#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
/* Header consists memory for cmd length and pointer to: prev and next element. */
#define NRF_CLI_HISTORY_HEADER_SIZE (sizeof(nrf_cli_memobj_header_t))
#define NRF_CLI_HISTORY_MEM_OBJ(name) \
NRF_MEMOBJ_POOL_DEF(CONCAT_2(name, _cmd_hist_memobj), \
NRF_CLI_HISTORY_HEADER_SIZE + \
NRF_CLI_HISTORY_ELEMENT_SIZE, \
NRF_CLI_HISTORY_ELEMENT_COUNT)
#define NRF_CLI_MEMOBJ_PTR(_name_) &CONCAT_2(_name_, _cmd_hist_memobj)
#else
#define NRF_CLI_MEMOBJ_PTR(_name_) NULL
#define NRF_CLI_HISTORY_MEM_OBJ(name)
#endif
/**
* @brief CLI instance internals.
*
* @ref nrf_cli_t
*/
struct nrf_cli
{
char const * const p_name; //!< Terminal name.
nrf_cli_transport_t const * p_iface; //!< Transport interface.
nrf_cli_ctx_t * p_ctx; //!< Internal context.
nrf_log_backend_t const * p_log_backend; //!< Logger backend.
nrf_fprintf_ctx_t * p_fprintf_ctx; //!< fprintf context.
nrf_memobj_pool_t const * p_cmd_hist_mempool; //!< Memory reserved for commands history.
};
/**
* @brief Macro for defining a command line interface instance.
*
* @param[in] name Instance name.
* @param[in] cli_prefix CLI prefix string.
* @param[in] p_transport_iface Pointer to the transport interface.
* @param[in] newline_ch Deprecated parameter, not used any more. Any uint8_t value can be used.
* @param[in] log_queue_size Logger processing queue size.
*/
#define NRF_CLI_DEF(name, cli_prefix, p_transport_iface, newline_ch, log_queue_size) \
static nrf_cli_t const name; \
static nrf_cli_ctx_t CONCAT_2(name, _ctx); \
NRF_FPRINTF_DEF(CONCAT_2(name, _fprintf_ctx), \
&name, \
CONCAT_2(name, _ctx).printf_buff, \
NRF_CLI_PRINTF_BUFF_SIZE, \
false, \
nrf_cli_print_stream); \
NRF_LOG_BACKEND_CLI_DEF(CONCAT_2(name, _log_backend), log_queue_size); \
NRF_CLI_HISTORY_MEM_OBJ(name); \
/*lint -save -e31*/ \
static nrf_cli_t const name = { \
.p_name = cli_prefix, \
.p_iface = p_transport_iface, \
.p_ctx = &CONCAT_2(name, _ctx), \
.p_log_backend = NRF_CLI_BACKEND_PTR(name), \
.p_fprintf_ctx = &CONCAT_2(name, _fprintf_ctx), \
.p_cmd_hist_mempool = NRF_CLI_MEMOBJ_PTR(name), \
} /*lint -restore*/
/**
* @brief Function for initializing a transport layer and internal CLI state.
*
* @param[in] p_cli Pointer to CLI instance.
* @param[in] p_transport_config Configuration forwarded to the transport during initialization.
* @param[in] use_colors Enables colored prints.
* @param[in] log_backend If true, the console will be used as logger backend.
* @param[in] init_lvl Default severity level for the logger.
*
* @return Standard error code.
*/
ret_code_t nrf_cli_init(nrf_cli_t const * p_cli,
void const * p_transport_config,
bool use_colors,
bool log_backend,
nrf_log_severity_t init_lvl);
ret_code_t nrf_cli_task_create(nrf_cli_t const * p_cli);
/**
* @brief Function for uninitializing a transport layer and internal CLI state.
* If function returns NRF_ERROR_BUSY, you must call @ref nrf_cli_process before calling
* nrf_cli_uninit again.
*
* @param p_cli Pointer to CLI instance.
*
* @return Standard error code.
*/
ret_code_t nrf_cli_uninit(nrf_cli_t const * p_cli);
/**
* @brief Function for starting CLI processing.
*
* @param p_cli Pointer to the CLI instance.
*
* @return Standard error code.
*/
ret_code_t nrf_cli_start(nrf_cli_t const * p_cli);
/**
* @brief Function for stopping CLI processing.
*
* @param p_cli Pointer to CLI instance.
*
* @return Standard error code.
*/
ret_code_t nrf_cli_stop(nrf_cli_t const * p_cli);
/**
* @brief CLI colors for @ref nrf_cli_fprintf function.
*/
#define NRF_CLI_DEFAULT NRF_CLI_VT100_COLOR_DEFAULT /**< Turn off character attributes. */
#define NRF_CLI_NORMAL NRF_CLI_VT100_COLOR_WHITE /**< Normal color printf. */
#define NRF_CLI_INFO NRF_CLI_VT100_COLOR_GREEN /**< Info color printf. */
#define NRF_CLI_OPTION NRF_CLI_VT100_COLOR_CYAN /**< Option color printf. */
#define NRF_CLI_WARNING NRF_CLI_VT100_COLOR_YELLOW /**< Warning color printf. */
#define NRF_CLI_ERROR NRF_CLI_VT100_COLOR_RED /**< Error color printf. */
/**
* @brief Printf-like function which sends formatted data stream to the CLI.
* This function shall not be used outside of the CLI module or CLI command context.
*
* @param[in] p_cli Pointer to the CLI instance.
* @param[in] color Printf color.
* @param[in] p_fmt Format string.
* @param[in] ... List of parameters to print.
*/
void nrf_cli_fprintf(nrf_cli_t const * p_cli,
nrf_cli_vt100_color_t color,
char const * p_fmt,
...);
/**
* @brief Print an info message to the CLI.
*
* See @ref nrf_cli_fprintf.
*
* @param[in] _p_cli Pointer to the CLI instance.
* @param[in] _ft Format string.
* @param[in] ... List of parameters to print.
*/
#define nrf_cli_info(_p_cli, _ft, ...) \
nrf_cli_fprintf(_p_cli, NRF_CLI_INFO, _ft "\n", ##__VA_ARGS__)
/**
* @brief Print a normal message to the CLI.
*
* See @ref nrf_cli_fprintf.
*
* @param[in] _p_cli Pointer to the CLI instance.
* @param[in] _ft Format string.
* @param[in] ... List of parameters to print.
*/
#define nrf_cli_print(_p_cli, _ft, ...) \
nrf_cli_fprintf(_p_cli, NRF_CLI_DEFAULT, _ft "\n", ##__VA_ARGS__)
/**
* @brief Print a warning message to the CLI.
*
* See @ref nrf_cli_fprintf.
*
* @param[in] _p_cli Pointer to the CLI instance.
* @param[in] _ft Format string.
* @param[in] ... List of parameters to print.
*/
#define nrf_cli_warn(_p_cli, _ft, ...) \
nrf_cli_fprintf(_p_cli, NRF_CLI_WARNING, _ft "\n", ##__VA_ARGS__)
/**
* @brief Print an error message to the CLI.
*
* See @ref nrf_cli_fprintf.
*
* @param[in] _p_cli Pointer to the CLI instance.
* @param[in] _ft Format string.
* @param[in] ... List of parameters to print.
*/
#define nrf_cli_error(_p_cli, _ft, ...) \
nrf_cli_fprintf(_p_cli, NRF_CLI_ERROR, _ft "\n", ##__VA_ARGS__)
/**
* @brief Process function, which should be executed when data is ready in the transport interface.
*
* @param[in] p_cli Pointer to the CLI instance.
*/
void nrf_cli_process(nrf_cli_t const * p_cli);
/**
* @brief Option descriptor.
*/
typedef struct nrf_cli_getopt_option
{
char const * p_optname; //!< Option long name.
char const * p_optname_short; //!< Option short name.
char const * p_optname_help; //!< Option help string.
} nrf_cli_getopt_option_t;
/**
* @brief Option structure initializer @ref nrf_cli_getopt_option.
*
* @param[in] _p_optname Option name long.
* @param[in] _p_shortname Option name short.
* @param[in] _p_help Option help string.
*/
#define NRF_CLI_OPT(_p_optname, _p_shortname, _p_help) { \
.p_optname = _p_optname, \
.p_optname_short = _p_shortname, \
.p_optname_help = _p_help, \
}
/**
* @brief Informs that a command has been called with -h or --help option.
*
* @param[in] p_cli Pointer to the CLI instance.
*
* @return True if help has been requested.
*/
__STATIC_INLINE bool nrf_cli_help_requested(nrf_cli_t const * p_cli);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE bool nrf_cli_help_requested(nrf_cli_t const * p_cli)
{
return p_cli->p_ctx->internal.flag.show_help;
}
#endif
/**
* @brief Prints the current command help.
* @details Function will print a help string with: the currently entered command, its options,
* and subcommands (if they exist).
*
* @param[in] p_cli Pointer to the CLI instance.
* @param[in] p_opt Pointer to the optional option array.
* @param[in] opt_len Option array size.
*/
void nrf_cli_help_print(nrf_cli_t const * p_cli,
nrf_cli_getopt_option_t const * p_opt,
size_t opt_len);
/**
* @internal @brief This function shall not be used directly, it is required by the
* nrf_fprintf module.
*
* @param[in] p_user_ctx Pointer to the context for the CLI instance.
* @param[in] p_data Pointer to the data buffer.
* @param[in] data_len Data buffer size.
*/
void nrf_cli_print_stream(void const * p_user_ctx, char const * p_data, size_t data_len);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_H__ */

View File

@@ -0,0 +1,102 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_TYPES_H__
#define NRF_CLI_TYPES_H__
#include <inttypes.h>
#include "sdk_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#if (NRF_CLI_CMD_BUFF_SIZE > 65535)
typedef uint32_t nrf_cli_cmd_len_t;
#elif (NRF_CLI_CMD_BUFF_SIZE > 255)
typedef uint16_t nrf_cli_cmd_len_t;
#else
typedef uint8_t nrf_cli_cmd_len_t;
#endif
typedef enum
{
NRF_CLI_VT100_COLOR_DEFAULT,
NRF_CLI_VT100_COLOR_BLACK,
NRF_CLI_VT100_COLOR_RED,
NRF_CLI_VT100_COLOR_GREEN,
NRF_CLI_VT100_COLOR_YELLOW,
NRF_CLI_VT100_COLOR_BLUE,
NRF_CLI_VT100_COLOR_MAGENTA,
NRF_CLI_VT100_COLOR_CYAN,
NRF_CLI_VT100_COLOR_WHITE,
VT100_COLOR_END
} nrf_cli_vt100_color_t;
typedef struct
{
nrf_cli_vt100_color_t col; // text color
nrf_cli_vt100_color_t bgcol; // background color
} nrf_cli_vt100_colors_t;
typedef struct
{
nrf_cli_cmd_len_t cur_x; // horizontal cursor position in edited command line
nrf_cli_cmd_len_t cur_x_end; // horizontal cursor position at the end of command
nrf_cli_cmd_len_t cur_y; // vertical cursor position in edited command
nrf_cli_cmd_len_t cur_y_end; // vertical cursor position at the end of command
nrf_cli_cmd_len_t terminal_hei; // terminal screen height
nrf_cli_cmd_len_t terminal_wid; // terminal screen width
uint8_t name_len; // console name length
} nrf_cli_multiline_cons_t;
typedef struct
{
nrf_cli_multiline_cons_t cons;
nrf_cli_vt100_colors_t col;
nrf_cli_cmd_len_t printed_cmd; // printed commands counter
} nrf_cli_vt100_ctx_t;
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_TYPES_H__ */

View File

@@ -0,0 +1,632 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_VT100_H__
#define NRF_CLI_VT100_H__
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_CLI_VT100_ASCII_ESC (0x1b)
#define NRF_CLI_VT100_ASCII_DEL (0x7F)
#define NRF_CLI_VT100_ASCII_BSPACE (0x08)
#define NRF_CLI_VT100_ASCII_CTRL_A (0x1)
#define NRF_CLI_VT100_ASCII_CTRL_C (0x03)
#define NRF_CLI_VT100_ASCII_CTRL_E (0x5)
#define NRF_CLI_VT100_ASCII_CTRL_L (0x0C)
#define NRF_CLI_VT100_ASCII_CTRL_U (0x15)
#define NRF_CLI_VT100_ASCII_CTRL_W (0x17)
#define NRF_CLI_VT100_SETNL \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', '0', 'h', '\0' \
} /* Set new line mode */
#define NRF_CLI_VT100_SETAPPL \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', 'h', '\0' \
} /* Set cursor key to application */
#define NRF_CLI_VT100_SETCOL_132 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '3', 'h', '\0' \
} /* Set number of columns to 132 */
#define NRF_CLI_VT100_SETSMOOTH \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '4', 'h', '\0' \
} /* Set smooth scrolling */
#define NRF_CLI_VT100_SETREVSCRN \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '5', 'h', '\0' \
} /* Set reverse video on screen */
#define NRF_CLI_VT100_SETORGREL \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '6', 'h', '\0' \
} /* Set origin to relative */
#define NRF_CLI_VT100_SETWRAP_ON \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'h', '\0' \
} /* Set auto-wrap mode */
#define NRF_CLI_VT100_SETWRAP_OFF \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'l', '\0' \
} /* Set auto-wrap mode */
#define NRF_CLI_VT100_SETREP \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '8', 'h', '\0' \
} /* Set auto-repeat mode */
#define NRF_CLI_VT100_SETINTER \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '9', 'h', '\0' \
} /* Set interlacing mode */
#define NRF_CLI_VT100_SETLF \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', '0', 'l', '\0' \
} /* Set line feed mode */
#define NRF_CLI_VT100_SETCURSOR \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', 'l', '\0' \
} /* Set cursor key to cursor */
#define NRF_CLI_VT100_SETVT52 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '2', 'l', '\0' \
} /* Set VT52 (versus ANSI) */
#define NRF_CLI_VT100_SETCOL_80 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '3', 'l', '\0' \
} /* Set number of columns to 80 */
#define NRF_CLI_VT100_SETJUMP \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '4', 'l', '\0' \
} /* Set jump scrolling */
#define NRF_CLI_VT100_SETNORMSCRN \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '5', 'l', '\0' \
} /* Set normal video on screen */
#define NRF_CLI_VT100_SETORGABS \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '6', 'l', '\0' \
} /* Set origin to absolute */
#define NRF_CLI_VT100_RESETWRAP \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'l', '\0' \
} /* Reset auto-wrap mode */
#define NRF_CLI_VT100_RESETREP \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '8', 'l', '\0' \
} /* Reset auto-repeat mode */
#define NRF_CLI_VT100_RESETINTER \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '9', 'l', '\0' \
} /* Reset interlacing mode */
#define NRF_CLI_VT100_ALTKEYPAD \
{ \
NRF_CLI_VT100_ASCII_ESC, '=', '\0' \
} /* Set alternate keypad mode */
#define NRF_CLI_VT100_NUMKEYPAD \
{ \
NRF_CLI_VT100_ASCII_ESC, '>', '\0' \
} /* Set numeric keypad mode */
#define NRF_CLI_VT100_SETUKG0 \
{ \
NRF_CLI_VT100_ASCII_ESC, '(', 'A', '\0' \
} /* Set United Kingdom G0 character set */
#define NRF_CLI_VT100_SETUKG1 \
{ \
NRF_CLI_VT100_ASCII_ESC, ')', 'A', '\0' \
} /* Set United Kingdom G1 character set */
#define NRF_CLI_VT100_SETUSG0 \
{ \
NRF_CLI_VT100_ASCII_ESC, '(', 'B', '\0' \
} /* Set United States G0 character set */
#define NRF_CLI_VT100_SETUSG1 \
{ \
NRF_CLI_VT100_ASCII_ESC, ')', 'B', '\0' \
} /* Set United States G1 character set */
#define NRF_CLI_VT100_SETSPECG0 \
{ \
NRF_CLI_VT100_ASCII_ESC, '(', '0', '\0' \
} /* Set G0 special chars. & line set */
#define NRF_CLI_VT100_SETSPECG1 \
{ \
NRF_CLI_VT100_ASCII_ESC, ')', '0', '\0' \
} /* Set G1 special chars. & line set */
#define NRF_CLI_VT100_SETALTG0 \
{ \
NRF_CLI_VT100_ASCII_ESC, '(', '1', '\0' \
} /* Set G0 alternate character ROM */
#define NRF_CLI_VT100_SETALTG1 \
{ \
NRF_CLI_VT100_ASCII_ESC, ')', '1', '\0' \
} /* Set G1 alternate character ROM */
#define NRF_CLI_VT100_SETALTSPECG0 \
{ \
NRF_CLI_VT100_ASCII_ESC, '(', '2', '\0' \
} /* Set G0 alt char ROM and spec. graphics */
#define NRF_CLI_VT100_SETALTSPECG1 \
{ \
NRF_CLI_VT100_ASCII_ESC, ')', '2', '\0' \
} /* Set G1 alt char ROM and spec. graphics */
#define NRF_CLI_VT100_SETSS2 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'N', '\0' \
} /* Set single shift 2 */
#define NRF_CLI_VT100_SETSS3 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', '\0' \
} /* Set single shift 3 */
#define NRF_CLI_VT100_MODESOFF \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'm', '\0' \
} /* Turn off character attributes */
#define NRF_CLI_VT100_MODESOFF_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '0', 'm', '\0' \
} /* Turn off character attributes */
#define NRF_CLI_VT100_BOLD \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '1', 'm', '\0' \
} /* Turn bold mode on */
#define NRF_CLI_VT100_LOWINT \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', 'm', '\0' \
} /* Turn low intensity mode on */
#define NRF_CLI_VT100_UNDERLINE \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '4', 'm', '\0' \
} /* Turn underline mode on */
#define NRF_CLI_VT100_BLINK \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '5', 'm', '\0' \
} /* Turn blinking mode on */
#define NRF_CLI_VT100_REVERSE \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '7', 'm', '\0' \
} /* Turn reverse video on */
#define NRF_CLI_VT100_INVISIBLE \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '8', 'm', '\0' \
} /* Turn invisible text mode on */
#define NRF_CLI_VT100_SETWIN(t, b) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (t), ';', (b), 'r', '\0' \
} /* Set top and bottom line#s of a window */
#define NRF_CLI_VT100_CURSORUP(n) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (n), 'A', '\0' \
} /* Move cursor up n lines */
#define NRF_CLI_VT100_CURSORDN(n) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (n), 'B', '\0' \
} /* Move cursor down n lines */
#define NRF_CLI_VT100_CURSORRT(n) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (n), 'C', '\0' \
} /* Move cursor right n lines */
#define NRF_CLI_VT100_CURSORLF(n) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (n), 'D', '\0' \
} /* Move cursor left n lines */
#define NRF_CLI_VT100_CURSORHOME \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'H', '\0' \
} /* Move cursor to upper left corner */
#define NRF_CLI_VT100_CURSORHOME_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', ';', 'H', '\0' \
} /* Move cursor to upper left corner */
#define NRF_CLI_VT100_CURSORPOS(v, h) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (v), ';', (h), 'H', '\0' \
} /* Move cursor to screen location v,h */
#define NRF_CLI_VT100_HVHOME \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'f', '\0' \
} /* Move cursor to upper left corner */
#define NRF_CLI_VT100_HVHOME_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', ';', 'f', '\0' \
} /* Move cursor to upper left corner */
#define NRF_CLI_VT100_HVPOS(v, h) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', (v), ';', (h), 'f', '\0' \
} /* Move cursor to screen location v,h */
#define NRF_CLI_VT100_INDEX \
{ \
NRF_CLI_VT100_ASCII_ESC, 'D', '\0' \
} /* Move/scroll window up one line */
#define NRF_CLI_VT100_REVINDEX \
{ \
NRF_CLI_VT100_ASCII_ESC, 'M', '\0' \
} /* Move/scroll window down one line */
#define NRF_CLI_VT100_NEXTLINE \
{ \
NRF_CLI_VT100_ASCII_ESC, 'E', '\0' \
} /* Move to next line */
#define NRF_CLI_VT100_SAVECURSOR \
{ \
NRF_CLI_VT100_ASCII_ESC, '7', '\0' \
} /* Save cursor position and attributes */
#define NRF_CLI_VT100_RESTORECURSOR \
{ \
NRF_CLI_VT100_ASCII_ESC, '8', '\0' \
} /* Restore cursor position and attribute */
#define NRF_CLI_VT100_TABSET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'H', '\0' \
} /* Set a tab at the current column */
#define NRF_CLI_VT100_TABCLR \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'g', '\0' \
} /* Clear a tab at the current column */
#define NRF_CLI_VT100_TABCLR_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '0', 'g', '\0' \
} /* Clear a tab at the current column */
#define NRF_CLI_VT100_TABCLRALL \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '3', 'g', '\0' \
} /* Clear all tabs */
#define NRF_CLI_VT100_DHTOP \
{ \
NRF_CLI_VT100_ASCII_ESC, '#', '3', '\0' \
} /* Double-height letters, top half */
#define NRF_CLI_VT100_DHBOT \
{ \
NRF_CLI_VT100_ASCII_ESC, '#', '4', '\0' \
} /* Double-height letters, bottom hal */
#define NRF_CLI_VT100_SWSH \
{ \
NRF_CLI_VT100_ASCII_ESC, '#', '5', '\0' \
} /* Single width, single height letters */
#define NRF_CLI_VT100_DWSH \
{ \
NRF_CLI_VT100_ASCII_ESC, '#', '6', '\0' \
} /* Double width, single height letters */
#define NRF_CLI_VT100_CLEAREOL \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'K', '\0' \
} /* Clear line from cursor right */
#define NRF_CLI_VT100_CLEAREOL_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '0', 'K', '\0' \
} /* Clear line from cursor right */
#define NRF_CLI_VT100_CLEARBOL \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '1', 'K', '\0' \
} /* Clear line from cursor left */
#define NRF_CLI_VT100_CLEARLINE \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', 'K', '\0' \
} /* Clear entire line */
#define NRF_CLI_VT100_CLEAREOS \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'J', '\0' \
} /* Clear screen from cursor down */
#define NRF_CLI_VT100_CLEAREOS_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '0', 'J', '\0' \
} /* Clear screen from cursor down */
#define NRF_CLI_VT100_CLEARBOS \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '1', 'J', '\0' \
} /* Clear screen from cursor up */
#define NRF_CLI_VT100_CLEARSCREEN \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', 'J', '\0' \
} /* Clear entire screen */
#define NRF_CLI_VT100_DEVSTAT \
{ \
NRF_CLI_VT100_ASCII_ESC, '5', 'n', '\0' \
} /* Device status report */
#define NRF_CLI_VT100_TERMOK \
{ \
NRF_CLI_VT100_ASCII_ESC, '0', 'n', '\0' \
} /* Response: terminal is OK */
#define NRF_CLI_VT100_TERMNOK \
{ \
NRF_CLI_VT100_ASCII_ESC, '3', 'n', '\0' \
} /* Response: terminal is not OK */
#define NRF_CLI_VT100_GETCURSOR \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '6', 'n', '\0' \
} /* Get cursor position */
#define NRF_CLI_VT100_CURSORPOSAT \
{ \
NRF_CLI_VT100_ASCII_ESC, (v), ';', (h), 'R', '\0' \
} /* Response: cursor is at v,h */
#define NRF_CLI_VT100_IDENT \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', 'c', '\0' \
} /* Identify what terminal type */
#define NRF_CLI_VT100_IDENT_ \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '0', 'c', '\0' \
} /* Identify what terminal type */
#define NRF_CLI_VT100_GETTYPE \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', ';', (n), '0', 'c', '\0'\
} /* Response: terminal type code n */
#define NRF_CLI_VT100_RESET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'c', '\0' \
} /* Reset terminal to initial state */
#define NRF_CLI_VT100_ALIGN \
{ \
NRF_CLI_VT100_ASCII_ESC, '#', '8', '\0' \
} /* Screen alignment display */
#define NRF_CLI_VT100_TESTPU \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '1', 'y', '\0' \
} /* Confidence power up test */
#define NRF_CLI_VT100_TESTLB \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '2', 'y', '\0' \
} /* Confidence loopback test */
#define NRF_CLI_VT100_TESTPUREP \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '9', 'y', '\0' \
} /* Repeat power up test */
#define NRF_CLI_VT100_TESTLBREP \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '1', '0', 'y', '\0' \
} /* Repeat loopback test */
#define NRF_CLI_VT100_LEDSOFF \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '0', 'q', '\0' \
} /* Turn off all four leds */
#define NRF_CLI_VT100_LED1 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '1', 'q', '\0' \
} /* Turn on LED #1 */
#define NRF_CLI_VT100_LED2 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '2', 'q', '\0' \
} /* Turn on LED #2 */
#define NRF_CLI_VT100_LED3 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '3', 'q', '\0' \
} /* Turn on LED #3 */
#define NRF_CLI_VT100_LED4 \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '4', 'q', '\0' \
} /* Turn on LED #4 */
/* Function Keys */
#define NRF_CLI_VT100_PF1 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'P', '\0' \
}
#define NRF_CLI_VT100_PF2 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'Q', '\0' \
}
#define NRF_CLI_VT100_PF3 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'R', '\0' \
}
#define NRF_CLI_VT100_PF4 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'S', '\0' \
}
/* Arrow keys */
#define NRF_CLI_VT100_UP_RESET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'A', '\0' \
}
#define NRF_CLI_VT100_UP_SET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'A', '\0' \
}
#define NRF_CLI_VT100_DOWN_RESET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'B', '\0' \
}
#define NRF_CLI_VT100_DOWN_SET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'B', '\0' \
}
#define NRF_CLI_VT100_RIGHT_RESET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'C', '\0' \
}
#define NRF_CLI_VT100_RIGHT_SET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'C', '\0' \
}
#define NRF_CLI_VT100_LEFT_RESET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'D', '\0' \
}
#define NRF_CLI_VT100_LEFT_SET \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'D', '\0' \
}
/* Numeric Keypad Keys */
#define NRF_CLI_VT100_NUMERIC_0 \
{ \
'0', '\0' \
}
#define NRF_CLI_VT100_ALT_0 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'p', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_1 \
{ \
'1', '\0' \
}
#define NRF_CLI_VT100_ALT_1 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'q', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_2 \
{ \
'2', '\0' \
}
#define NRF_CLI_VT100_ALT_2 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'r', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_3 \
{ \
'3', '\0' \
}
#define NRF_CLI_VT100_ALT_3 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 's', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_4 \
{ \
'4', '\0' \
}
#define NRF_CLI_VT100_ALT_4 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 't', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_5 \
{ \
'5', '\0' \
}
#define NRF_CLI_VT100_ALT_5 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'u', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_6 \
{ \
'6', '\0' \
}
#define NRF_CLI_VT100_ALT_6 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'v', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_7 \
{ \
'7', '\0' \
}
#define NRF_CLI_VT100_ALT_7 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'w', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_8 \
{ \
'8', '\0' \
}
#define NRF_CLI_VT100_ALT_8 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'x', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_9 \
{ \
'9', '\0'
#define NRF_CLI_VT100_ALT_9 \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'y' \
}
#define NRF_CLI_VT100_NUMERIC_MINUS \
{ \
'-', '\0' \
}
#define NRF_CLI_VT100_ALT_MINUS \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'm', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_COMMA \
{ \
',', '\0' \
}
#define NRF_CLI_VT100_ALT_COMMA \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'l', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_PERIOD \
{ \
'.', '\0' \
}
#define NRF_CLI_VT100_ALT_PERIOD \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'n', '\0' \
}
#define NRF_CLI_VT100_NUMERIC_ENTER \
{ \
ASCII_CR \
}
#define NRF_CLI_VT100_ALT_ENTER \
{ \
NRF_CLI_VT100_ASCII_ESC, 'O', 'M', '\0' \
}
#define NRF_CLI_VT100_COLOR(__col) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '1', ';', '3', '0' + (__col), 'm', '\0' \
}
#define NRF_CLI_VT100_BGCOLOR(__col) \
{ \
NRF_CLI_VT100_ASCII_ESC, '[', '4', '0' + (__col), 'm', '\0' \
}
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_VT100_H__ */

View File

@@ -0,0 +1,223 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_CLI_RTT)
#include <SEGGER_RTT_Conf.h>
#include <SEGGER_RTT.h>
#include "nrf_cli_rtt.h"
#include "nrf_assert.h"
#include "nrf_delay.h"
#define RTT_RX_TIMEOUT 100
static bool m_host_present;
static void timer_handler(void * p_context)
{
nrf_cli_rtt_internal_t * p_internal = (nrf_cli_rtt_internal_t *)p_context;
if (SEGGER_RTT_HasData(0))
{
p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, p_internal->p_cb->p_context);
}
p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_internal->p_cb->p_context);
ret_code_t err_code = app_timer_start(*p_internal->p_timer,
APP_TIMER_TICKS(RTT_RX_TIMEOUT),
p_context);
ASSERT(err_code == NRF_SUCCESS);
UNUSED_VARIABLE(err_code);
}
static ret_code_t cli_rtt_init(nrf_cli_transport_t const * p_transport,
void const * p_config,
nrf_cli_transport_handler_t evt_handler,
void * p_context)
{
UNUSED_PARAMETER(p_config);
nrf_cli_rtt_internal_t * p_internal =
CONTAINER_OF(p_transport, nrf_cli_rtt_internal_t, transport);
p_internal->p_cb->handler = evt_handler;
p_internal->p_cb->p_context = p_context;
p_internal->p_cb->timer_created = false;
SEGGER_RTT_Init();
m_host_present = true;
return NRF_SUCCESS;
}
static ret_code_t cli_rtt_uninit(nrf_cli_transport_t const * p_transport)
{
nrf_cli_rtt_internal_t * p_internal =
CONTAINER_OF(p_transport, nrf_cli_rtt_internal_t, transport);
return app_timer_stop(*p_internal->p_timer);
}
static ret_code_t cli_rtt_enable(nrf_cli_transport_t const * p_transport,
bool blocking)
{
nrf_cli_rtt_internal_t * p_internal =
CONTAINER_OF(p_transport, nrf_cli_rtt_internal_t, transport);
ret_code_t err_code = NRF_SUCCESS;
if (p_internal->p_cb->timer_created)
{
err_code = app_timer_stop(*p_internal->p_timer); //Timer may be running or inactive
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE))
{
return err_code;
}
else
{
err_code = NRF_SUCCESS;
}
}
if (!blocking)
{
if (!p_internal->p_cb->timer_created)
{
err_code = app_timer_create(p_internal->p_timer,
APP_TIMER_MODE_SINGLE_SHOT,
timer_handler);
p_internal->p_cb->timer_created = true;
}
if (err_code == NRF_SUCCESS)
{
err_code = app_timer_start(*p_internal->p_timer,
APP_TIMER_TICKS(RTT_RX_TIMEOUT),
p_internal);
SEGGER_RTT_Init();
}
}
return err_code;
}
static ret_code_t cli_rtt_read(nrf_cli_transport_t const * p_transport,
void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
UNUSED_PARAMETER(p_transport);
size_t rcnt = SEGGER_RTT_Read(NRF_CLI_RTT_TERMINAL_ID, p_data, length);
*p_cnt = rcnt;
return NRF_SUCCESS;
}
static ret_code_t cli_rtt_write(nrf_cli_transport_t const * p_transport,
const void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
UNUSED_PARAMETER(p_transport);
if (!(CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk))
{
/* If an RTT session is not active, but the RTT console is processed, the program may hang.
* Workaround: If the debugger is not connected, always return NRF_SUCCESS.
*/
*p_cnt = length;
return NRF_SUCCESS;
}
size_t idx = 0;
uint32_t processed;
uint32_t watchdog_counter = NRF_CLI_RTT_TX_RETRY_CNT;
const uint8_t * p_buffer = (const uint8_t *)p_data;
do {
processed = SEGGER_RTT_Write(NRF_CLI_RTT_TERMINAL_ID, &p_buffer[idx], length);
if (processed == 0)
{
/* There are two possible reasons for not writing any data to RTT:
* - The host is not connected and not reading the data.
* - The buffer got full and will be read by the host.
* These two situations are distinguished using the following algorithm.
* At the begining, the module assumes that the host is active,
* so when no data is read, it busy waits and retries.
* If, after retrying, the host reads the data, the module assumes that the host is active.
* If it fails, the module assumes that the host is inactive and stores that information. On next
* call, only one attempt takes place. The host is marked as active if the attempt is successful.
*/
if (!m_host_present)
{
break;
}
else
{
nrf_delay_ms(NRF_CLI_RTT_TX_RETRY_DELAY_MS);
watchdog_counter--;
if (watchdog_counter == 0)
{
m_host_present = false;
break;
}
}
}
m_host_present = true;
idx += processed;
length -= processed;
} while (length);
if (idx > 0)
{
*p_cnt = idx;
}
else
{
*p_cnt = length;
}
return NRF_SUCCESS;
}
const nrf_cli_transport_api_t nrf_cli_rtt_transport_api = {
.init = cli_rtt_init,
.uninit = cli_rtt_uninit,
.enable = cli_rtt_enable,
.read = cli_rtt_read,
.write = cli_rtt_write,
};
#endif

View File

@@ -0,0 +1,100 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_RTT_H__
#define NRF_CLI_RTT_H__
#include "nrf_cli.h"
#include "app_timer.h"
#include "nordic_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@file
*
* @defgroup nrf_cli_rtt RTT command line interface transport layer
* @ingroup nrf_cli
*
* @{
*
*/
/**
* @brief Command line interface transport.
*/
extern const nrf_cli_transport_api_t nrf_cli_rtt_transport_api;
/**
* @brief CLI RTT transport control block structure.
*/
typedef struct {
nrf_cli_transport_handler_t handler; //!< Event handler
void * p_context; //!< User context.
bool timer_created;//!< Flag indicating whether a timer is created.
} nrf_cli_rtt_internal_cb_t;
/**
* @brief CLI RTT transport instance structure.
*/
typedef struct {
nrf_cli_transport_t transport; //!< Transport structure.
nrf_cli_rtt_internal_cb_t * p_cb; //!< Pointer to the instance control block.
app_timer_id_t const * p_timer; //!< Pointer to the app_timer instance.
} nrf_cli_rtt_internal_t;
/**@brief CLI RTT transport definition */
#define NRF_CLI_RTT_DEF(_name_) \
APP_TIMER_DEF(CONCAT_2(_name_, _timer)); \
static nrf_cli_rtt_internal_cb_t CONCAT_2(_name_, _cb); \
static const nrf_cli_rtt_internal_t _name_ = { \
.transport = {.p_api = &nrf_cli_rtt_transport_api}, \
.p_cb = &CONCAT_2(_name_, _cb), \
.p_timer = &CONCAT_2(_name_, _timer) \
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_RTT_H__ */

View File

@@ -0,0 +1,308 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_CLI_UART)
#include "nrf_cli_uart.h"
#include "nrf_drv_uart.h"
#include "nrf_assert.h"
#define NRF_LOG_MODULE_NAME cli_uart
#define NRF_LOG_LEVEL (NRF_CLI_UART_CONFIG_LOG_ENABLED ? NRF_CLI_UART_CONFIG_LOG_LEVEL : 0)
#define NRF_LOG_INFO_COLOR NRF_CLI_UART_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_CLI_UART_CONFIG_DEBUG_COLOR
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#define CLI_UART_RX_TIMEOUT 100
static ret_code_t rx_try(nrf_cli_uart_internal_t * p_internal)
{
ret_code_t err_code;
size_t len = 255;
uint8_t * p_data;
err_code = nrf_ringbuf_alloc(p_internal->p_rx_ringbuf, &p_data, &len, true);
ASSERT(err_code == NRF_SUCCESS);
if ((err_code == NRF_SUCCESS) && len)
{
err_code = nrf_drv_uart_rx(p_internal->p_uart, p_data, len);
if (err_code == NRF_SUCCESS)
{
err_code = app_timer_start(*p_internal->p_timer,
APP_TIMER_TICKS(CLI_UART_RX_TIMEOUT),
p_internal);
}
}
return err_code;
}
static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context)
{
nrf_cli_uart_internal_t * p_internal = (nrf_cli_uart_internal_t *)p_context;
ret_code_t err_code = NRF_SUCCESS;
UNUSED_VARIABLE(err_code);
uint8_t * p_data;
size_t len = 255;
switch (p_event->type)
{
case NRF_DRV_UART_EVT_ERROR:
NRF_LOG_WARNING("id:%d, evt: ERROR:%d",
p_internal->p_uart->inst_idx,
p_event->data.error.error_mask);
err_code = nrf_ringbuf_put(p_internal->p_rx_ringbuf, p_event->data.error.rxtx.bytes);
ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM));
err_code = rx_try(p_internal);
ASSERT(err_code == NRF_SUCCESS);
break;
case NRF_DRV_UART_EVT_RX_DONE:
err_code = nrf_ringbuf_put(p_internal->p_rx_ringbuf, p_event->data.rxtx.bytes);
ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM));
if (p_event->data.rxtx.bytes)
{
NRF_LOG_INFO("id:%d, evt: RXRDY len:%d",
p_internal->p_uart->inst_idx,
p_event->data.rxtx.bytes);
NRF_LOG_HEXDUMP_DEBUG(p_event->data.rxtx.p_data, p_event->data.rxtx.bytes);
p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY,
p_internal->p_cb->p_context);
}
err_code = rx_try(p_internal);
ASSERT(err_code == NRF_SUCCESS);
break;
case NRF_DRV_UART_EVT_TX_DONE:
err_code = nrf_ringbuf_free(p_internal->p_tx_ringbuf, p_event->data.rxtx.bytes);
ASSERT(err_code == NRF_SUCCESS);
len = 255;
err_code = nrf_ringbuf_get(p_internal->p_tx_ringbuf, &p_data, &len, true);
ASSERT(err_code == NRF_SUCCESS);
if (len)
{
NRF_LOG_INFO("id:%d, evt uart_tx, len:%d", p_internal->p_uart->inst_idx, len);
err_code = nrf_drv_uart_tx(p_internal->p_uart, p_data, len);
ASSERT(err_code == NRF_SUCCESS);
}
p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_internal->p_cb->p_context);
NRF_LOG_INFO("id:%d, evt: TXRDY, len:%d",
p_internal->p_uart->inst_idx,
p_event->data.rxtx.bytes);
break;
default:
NRF_LOG_ERROR("Unknown event");
ASSERT(false);
}
}
static void timer_handler(void * p_context)
{
nrf_cli_uart_internal_t * p_internal = (nrf_cli_uart_internal_t *)p_context;
NRF_LOG_DEBUG("id:%d, evt: Timeout", p_internal->p_uart->inst_idx);
nrf_drv_uart_rx_abort(p_internal->p_uart);
}
static ret_code_t cli_uart_init(nrf_cli_transport_t const * p_transport,
void const * p_config,
nrf_cli_transport_handler_t evt_handler,
void * p_context)
{
nrf_cli_uart_internal_t * p_internal =
CONTAINER_OF(p_transport,
nrf_cli_uart_internal_t,
transport);
p_internal->p_cb->handler = evt_handler;
p_internal->p_cb->p_context = p_context;
p_internal->p_cb->timer_created = false;
p_internal->p_cb->blocking = false;
nrf_drv_uart_config_t * p_uart_config = (nrf_drv_uart_config_t *)p_config;
memcpy(&p_internal->p_cb->uart_config, p_uart_config, sizeof(nrf_drv_uart_config_t));
p_uart_config->p_context = (void *)p_internal;
ret_code_t err_code = nrf_drv_uart_init(p_internal->p_uart,
p_uart_config,
uart_event_handler);
if (err_code == NRF_SUCCESS)
{
nrf_ringbuf_init(p_internal->p_rx_ringbuf);
nrf_ringbuf_init(p_internal->p_tx_ringbuf);
}
return err_code;
}
static ret_code_t cli_uart_uninit(nrf_cli_transport_t const * p_transport)
{
nrf_cli_uart_internal_t * p_internal =
CONTAINER_OF(p_transport,
nrf_cli_uart_internal_t,
transport);
nrf_drv_uart_uninit(p_internal->p_uart);
return app_timer_stop(*p_internal->p_timer);
}
static ret_code_t cli_uart_enable(nrf_cli_transport_t const * p_transport,
bool blocking)
{
nrf_cli_uart_internal_t * p_internal =
CONTAINER_OF(p_transport,
nrf_cli_uart_internal_t,
transport);
ret_code_t err_code = NRF_SUCCESS;
if (p_internal->p_cb->timer_created)
{
err_code = app_timer_stop(*p_internal->p_timer); //Timer may be running or inactive
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE))
{
return err_code;
}
else
{
err_code = NRF_SUCCESS;
}
}
if (blocking)
{
nrf_drv_uart_uninit(p_internal->p_uart);
err_code = nrf_drv_uart_init(p_internal->p_uart, &p_internal->p_cb->uart_config, NULL);
if (err_code == NRF_SUCCESS)
{
p_internal->p_cb->blocking = true;
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_NOT_SUPPORTED;
}
}
else
{
if (!p_internal->p_cb->timer_created)
{
err_code = app_timer_create(p_internal->p_timer,
APP_TIMER_MODE_SINGLE_SHOT,
timer_handler);
p_internal->p_cb->timer_created = true;
}
if (err_code == NRF_SUCCESS)
{
err_code = rx_try(p_internal);
}
}
return err_code;
}
static ret_code_t cli_uart_read(nrf_cli_transport_t const * p_transport,
void * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
nrf_cli_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_uart_internal_t, transport);
*p_cnt = length;
ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt);
if (*p_cnt)
{
NRF_LOG_INFO("id:%d, read:%d", p_instance->p_uart->inst_idx, *p_cnt);
}
return err_code;
}
static ret_code_t cli_uart_write(nrf_cli_transport_t const * p_transport,
void const * p_data,
size_t length,
size_t * p_cnt)
{
ASSERT(p_cnt);
nrf_cli_uart_internal_t * p_instance =
CONTAINER_OF(p_transport, nrf_cli_uart_internal_t, transport);
ret_code_t err_code;
*p_cnt = length;
err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt);
if (err_code == NRF_SUCCESS)
{
NRF_LOG_INFO("id:%d, write, req:%d, done:%d",
p_instance->p_uart->inst_idx,
length,
*p_cnt);
if (!nrf_drv_uart_tx_in_progress(p_instance->p_uart))
{
uint8_t * p_buf;
size_t len = 255;
if (nrf_ringbuf_get(p_instance->p_tx_ringbuf, &p_buf, &len, true) == NRF_SUCCESS)
{
NRF_LOG_INFO("id:%d, uart_tx, len:%d", p_instance->p_uart->inst_idx, len);
err_code = nrf_drv_uart_tx(p_instance->p_uart, p_buf, len);
if (p_instance->p_cb->blocking && (err_code == NRF_SUCCESS))
{
(void)nrf_ringbuf_free(p_instance->p_tx_ringbuf, len);
}
}
}
}
return err_code;
}
const nrf_cli_transport_api_t nrf_cli_uart_transport_api = {
.init = cli_uart_init,
.uninit = cli_uart_uninit,
.enable = cli_uart_enable,
.read = cli_uart_read,
.write = cli_uart_write,
};
#endif

View File

@@ -0,0 +1,115 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_CLI_UART_H__
#define NRF_CLI_UART_H__
#include "nrf_cli.h"
#include "nrf_drv_uart.h"
#include "nrf_ringbuf.h"
#include "app_timer.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@file
*
* @defgroup nrf_cli_uart UART command line interface transport layer
* @ingroup nrf_cli
*
* @{
*
*/
/**
* @brief Command line interface transport.
*/
extern const nrf_cli_transport_api_t nrf_cli_uart_transport_api;
typedef struct nrf_cli_uart_internal_s nrf_cli_uart_internal_t;
typedef struct {
nrf_cli_transport_handler_t handler;
void * p_context;
nrf_drv_uart_config_t uart_config;
bool timer_created;
bool blocking;
} nrf_cli_uart_internal_cb_t;
struct nrf_cli_uart_internal_s {
nrf_cli_transport_t transport;
nrf_cli_uart_internal_cb_t * p_cb;
app_timer_id_t const * p_timer;
nrf_ringbuf_t const * p_rx_ringbuf;
nrf_ringbuf_t const * p_tx_ringbuf;
nrf_drv_uart_t const * p_uart;
};
typedef nrf_drv_uart_config_t nrf_cli_uart_config_t;
/**@brief CLI UART transport definition.
*
* @param _name Name of the instance.
* @param _uart_id UART instance ID.
* @param _tx_buf_sz Size of TX ring buffer.
* @param _rx_buf_sz Size of RX ring buffer.
*/
#define NRF_CLI_UART_DEF(_name, _uart_id, _tx_buf_sz, _rx_buf_sz) \
APP_TIMER_DEF(CONCAT_2(_name, _timer)); \
NRF_RINGBUF_DEF(CONCAT_2(_name,_tx_ringbuf), _tx_buf_sz); \
NRF_RINGBUF_DEF(CONCAT_2(_name,_rx_ringbuf), _rx_buf_sz); \
static const nrf_drv_uart_t CONCAT_2(_name,_uart) = \
NRF_DRV_UART_INSTANCE(_uart_id); \
static nrf_cli_uart_internal_cb_t CONCAT_2(_name, _cb); \
static const nrf_cli_uart_internal_t _name = { \
.transport = {.p_api = &nrf_cli_uart_transport_api}, \
.p_cb = &CONCAT_2(_name, _cb), \
.p_timer = &CONCAT_2(_name, _timer), \
.p_rx_ringbuf = &CONCAT_2(_name,_rx_ringbuf), \
.p_tx_ringbuf = &CONCAT_2(_name,_tx_ringbuf), \
.p_uart = &CONCAT_2(_name,_uart), \
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_CLI_UART_H__ */