Initial public release.
This commit is contained in:
parent
7b169e8116
commit
dac4af8d25
255 changed files with 68595 additions and 2 deletions
1013
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE.c
Normal file
1013
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE.c
Normal file
File diff suppressed because it is too large
Load diff
79
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE.h
Normal file
79
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/** \dir "BLE"
|
||||
*
|
||||
* \brief This directory contains source code for managing Bluetooth Low Energy communications.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief This file defines the interface to the Bluetooth Low Energy communications used by this software.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMM_BLE_H
|
||||
#define COMM_BLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
// Define this to print out BLE trace statements to the console.
|
||||
//#define TRACE_BLE
|
||||
//#define VERBOSE_BLE_TRACE
|
||||
|
||||
#define COMM_BLE_TASK_STACK_SIZE_in_bytes 4096
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COMM_BLE_DEFAULT,
|
||||
COMM_BLE_INITIALIZING,
|
||||
COMM_BLE_IDLE,
|
||||
COMM_BLE_SCANNING_FOR_KTAG_PACKETS,
|
||||
COMM_BLE_ADVERTISING_AS_PERIPHERAL,
|
||||
COMM_BLE_ADVERTISING_AS_BROADCASTER,
|
||||
COMM_BLE_SCANNING_AND_ADVERTISING
|
||||
} COMM_BLE_StateID_T;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COMM_BLE_COMMAND_NO_OP,
|
||||
COMM_BLE_REQUEST_STATE_CHANGE,
|
||||
COMM_BLE_PROCESS_BLE_EVENTS,
|
||||
COMM_BLE_SCAN_FOR_KTAG_PACKETS,
|
||||
COMM_BLE_ADVERTISE_AS_BROADCASTER,
|
||||
COMM_BLE_ADVERTISE_AS_PERIPHERAL,
|
||||
COMM_BLE_STOP_ADVERTISING,
|
||||
COMM_BLE_SCAN_AND_ADVERTISE,
|
||||
// COMM_BLE_COMMAND_IS_OUT_OF_RANGE is one more than the last valid command.
|
||||
COMM_BLE_COMMAND_IS_OUT_OF_RANGE
|
||||
} COMM_BLE_Command_ID_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMM_BLE_Command_ID_T ID;
|
||||
void * Data;
|
||||
} COMM_BLE_Command_T;
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
extern cy_stc_ble_conn_handle_t appConnHandle[CY_BLE_CONN_COUNT];
|
||||
extern volatile uint8_t COMM_BLE_IASAlertLevel;
|
||||
|
||||
extern QueueHandle_t COMM_BLE_CommandQueue;
|
||||
|
||||
//! Handle of the COMM_BLE_Task() given when the task was created.
|
||||
extern TaskHandle_t COMM_BLE_Task_Handle;
|
||||
|
||||
/* Public Functions */
|
||||
void COMM_BLE_Init(void);
|
||||
void COMM_BLE_Task(void * pvParameters);
|
||||
void COMM_BLE_RequestState(COMM_BLE_StateID_T state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_BLE_H
|
252
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_Bond.c
Normal file
252
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_Bond.c
Normal file
|
@ -0,0 +1,252 @@
|
|||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
static bool removeBondListFlag = false;
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: App_DisplayBondList()
|
||||
********************************************************************************
|
||||
*
|
||||
* Summary:
|
||||
* This function displays the bond list.
|
||||
*
|
||||
*******************************************************************************/
|
||||
void App_DisplayBondList(void)
|
||||
{
|
||||
#ifdef TRACE_BLE
|
||||
cy_en_ble_api_result_t apiResult;
|
||||
cy_stc_ble_gap_peer_addr_info_t bondedDeviceInfo[CY_BLE_MAX_BONDED_DEVICES];
|
||||
cy_stc_ble_gap_bonded_device_list_info_t bondedDeviceList =
|
||||
{
|
||||
.bdHandleAddrList = bondedDeviceInfo
|
||||
};
|
||||
uint8_t deviceCount;
|
||||
|
||||
/* Find out whether the device has bonded information stored already or not */
|
||||
apiResult = Cy_BLE_GAP_GetBondList(&bondedDeviceList);
|
||||
if (apiResult != CY_BLE_SUCCESS)
|
||||
{
|
||||
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_GetBondList API Error: 0x");
|
||||
COMM_Console_Print_UInt32AsHex(apiResult);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceCount = bondedDeviceList.noOfDevices;
|
||||
|
||||
if(deviceCount != 0u)
|
||||
{
|
||||
uint8_t counter;
|
||||
|
||||
COMM_Console_Print_String("[BLE] Bond list:\n");
|
||||
|
||||
do
|
||||
{
|
||||
COMM_Console_Print_String(" ");
|
||||
COMM_Console_Print_UInt8(deviceCount);
|
||||
COMM_Console_Print_String(". ");
|
||||
|
||||
deviceCount--;
|
||||
|
||||
if(bondedDeviceList.bdHandleAddrList[deviceCount].bdAddr.type == CY_BLE_GAP_ADDR_TYPE_RANDOM)
|
||||
{
|
||||
COMM_Console_Print_String("Peer Random Address:");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("Peer Public Address:");
|
||||
}
|
||||
|
||||
for (counter = CY_BLE_GAP_BD_ADDR_SIZE; counter > 0u; counter--)
|
||||
{
|
||||
COMM_Console_Print_String(" ");
|
||||
COMM_Console_Print_UInt8AsHex(bondedDeviceList.bdHandleAddrList[deviceCount].bdAddr.bdAddr[counter - 1u]);
|
||||
}
|
||||
COMM_Console_Print_String(", bdHandle: 0x");
|
||||
COMM_Console_Print_UInt8AsHex(bondedDeviceList.bdHandleAddrList[deviceCount].bdHandle);
|
||||
COMM_Console_Print_String("\n");
|
||||
} while (deviceCount != 0u);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
}
|
||||
#endif // TRACE_BLE
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: App_RemoveDevidesFromBondList
|
||||
********************************************************************************
|
||||
*
|
||||
* Summary:
|
||||
* Remove devices from the bond list.
|
||||
*
|
||||
*******************************************************************************/
|
||||
void App_RemoveDevicesFromBondList(void)
|
||||
{
|
||||
#if(CY_BLE_BONDING_REQUIREMENT == CY_BLE_BONDING_YES)
|
||||
cy_en_ble_api_result_t apiResult;
|
||||
cy_stc_ble_gap_bd_addr_t peerBdAddr = { .type = 0u };
|
||||
#ifdef TRACE_BLE
|
||||
COMM_Console_Print_String("[BLE] Cleaning Bond List...\n\n");
|
||||
#endif // TRACE_BLE
|
||||
|
||||
/* Remove all bonded devices in the list */
|
||||
apiResult = Cy_BLE_GAP_RemoveBondedDevice(&peerBdAddr);
|
||||
if (apiResult != CY_BLE_SUCCESS)
|
||||
{
|
||||
#ifdef TRACE_BLE
|
||||
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_RemoveBondedDevice API Error: 0x");
|
||||
COMM_Console_Print_UInt32AsHex(apiResult);
|
||||
COMM_Console_Print_String("\n");
|
||||
#endif // TRACE_BLE
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TRACE_BLE
|
||||
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_RemoveBondedDevice complete.\n\n");
|
||||
#endif // TRACE_BLE
|
||||
}
|
||||
#else
|
||||
#ifdef TRACE_BLE
|
||||
COMM_Console_Print_String("[BLE] Bonding is disabled...no need to remove bonded devices.\n\n");
|
||||
#endif // TRACE_BLE
|
||||
#endif /* (CY_BLE_BONDING_REQUIREMENT == CY_BLE_BONDING_YES) */
|
||||
|
||||
/* Clean flag */
|
||||
removeBondListFlag = false;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: App_GetCountOfBondedDevices()
|
||||
********************************************************************************
|
||||
*
|
||||
* Summary:
|
||||
* This function returns the count of bonded devices
|
||||
*
|
||||
* Return:
|
||||
* uint32_t The count of bonded devices
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t App_GetCountOfBondedDevices(void)
|
||||
{
|
||||
cy_en_ble_api_result_t apiResult;
|
||||
cy_stc_ble_gap_peer_addr_info_t bondedDeviceInfo[CY_BLE_MAX_BONDED_DEVICES];
|
||||
cy_stc_ble_gap_bonded_device_list_info_t bondedDeviceList =
|
||||
{
|
||||
.bdHandleAddrList = bondedDeviceInfo
|
||||
};
|
||||
uint32_t deviceCount = 0u;
|
||||
|
||||
/* Find out whether the device has bonded information stored already or not */
|
||||
apiResult = Cy_BLE_GAP_GetBondList(&bondedDeviceList);
|
||||
if (apiResult != CY_BLE_SUCCESS)
|
||||
{
|
||||
#ifdef TRACE_BLE
|
||||
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_GetBondList API Error: 0x");
|
||||
COMM_Console_Print_UInt32AsHex(apiResult);
|
||||
COMM_Console_Print_String("\n");
|
||||
#endif // TRACE_BLE
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceCount = bondedDeviceList.noOfDevices;
|
||||
}
|
||||
|
||||
return (deviceCount);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: App_IsDeviceInBondList()
|
||||
********************************************************************************
|
||||
*
|
||||
* Summary:
|
||||
* This function check if device with bdHandle is in the bond list
|
||||
*
|
||||
* Parameters:
|
||||
* bdHandle - bond device handler
|
||||
*
|
||||
* Return:
|
||||
* bool - true value when bdHandle exists in bond list
|
||||
*
|
||||
*******************************************************************************/
|
||||
bool App_IsDeviceInBondList(uint32_t bdHandle)
|
||||
{
|
||||
cy_en_ble_api_result_t apiResult;
|
||||
cy_stc_ble_gap_peer_addr_info_t bondedDeviceInfo[CY_BLE_MAX_BONDED_DEVICES];
|
||||
cy_stc_ble_gap_bonded_device_list_info_t bondedDeviceList =
|
||||
{
|
||||
.bdHandleAddrList = bondedDeviceInfo
|
||||
};
|
||||
bool deviceIsDetected = false;
|
||||
uint32_t deviceCount;
|
||||
|
||||
/* Find out whether the device has bonding information stored already or not */
|
||||
apiResult = Cy_BLE_GAP_GetBondList(&bondedDeviceList);
|
||||
if (apiResult != CY_BLE_SUCCESS)
|
||||
{
|
||||
#ifdef TRACE_BLE
|
||||
COMM_Console_Print_String("[BLE] Cy_BLE_GAP_GetBondList API Error: 0x");
|
||||
COMM_Console_Print_UInt32AsHex(apiResult);
|
||||
COMM_Console_Print_String("\n");
|
||||
#endif // TRACE_BLE
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceCount = bondedDeviceList.noOfDevices;
|
||||
|
||||
if(deviceCount != 0u)
|
||||
{
|
||||
do
|
||||
{
|
||||
deviceCount--;
|
||||
if(bdHandle == bondedDeviceList.bdHandleAddrList[deviceCount].bdHandle)
|
||||
{
|
||||
deviceIsDetected = 1u;
|
||||
}
|
||||
} while(deviceCount != 0u);
|
||||
}
|
||||
}
|
||||
return(deviceIsDetected);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: App_SetRemoveBondListFlag()
|
||||
********************************************************************************
|
||||
* Summary:
|
||||
* Set flag for removing bond list
|
||||
*
|
||||
*******************************************************************************/
|
||||
void App_SetRemoveBondListFlag(void)
|
||||
{
|
||||
removeBondListFlag = true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: App_IsRemoveBondListFlag()
|
||||
********************************************************************************
|
||||
* Summary:
|
||||
* Get value of remove bond list flag
|
||||
*
|
||||
* Return:
|
||||
* true - remove bond list flag is set
|
||||
* false - remove bond list flag is clear
|
||||
*
|
||||
*******************************************************************************/
|
||||
bool App_IsRemoveBondListFlag(void)
|
||||
{
|
||||
return ((removeBondListFlag == true) ? true : false);
|
||||
}
|
||||
|
||||
/* Private Functions */
|
32
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_Bond.h
Normal file
32
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_Bond.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/** \file
|
||||
* \brief This file declares Bluetooth Low Energy bond list helper functions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMM_BLE_BOND_H
|
||||
#define COMM_BLE_BOND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
void App_DisplayBondList(void);
|
||||
void App_RemoveDevicesFromBondListBySW2Press(uint32_t seconds);
|
||||
void App_RemoveDevicesFromBondList(void);
|
||||
void App_SetRemoveBondListFlag(void);
|
||||
bool App_IsRemoveBondListFlag(void);
|
||||
bool App_IsDeviceInBondList(uint32_t bdHandle);
|
||||
uint32_t App_GetCountOfBondedDevices(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_BLE_BOND_H
|
177
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_UART.c
Normal file
177
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_UART.c
Normal file
|
@ -0,0 +1,177 @@
|
|||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
#define UART_CIRCULAR_BUFFER_SIZE 1024
|
||||
#define BLE_UART_BUFFER_CHARACTERISTIC_SIZE 20
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
static uint_fast16_t UART_Tx_Notifications_Enabled = 0;
|
||||
|
||||
static uint8_t UART_Tx_Buffer_Storage[UART_CIRCULAR_BUFFER_SIZE];
|
||||
static UTIL_CircularBuffer_T UART_Tx_Buffer;
|
||||
static uint8_t BLE_UART_Tx_Buffer[BLE_UART_BUFFER_CHARACTERISTIC_SIZE];
|
||||
static uint8_t Rx_Buffer[BLE_UART_BUFFER_CHARACTERISTIC_SIZE + 1];
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
void COMM_BLE_UART_Init(void)
|
||||
{
|
||||
UTIL_InitCircularBuffer(&UART_Tx_Buffer, UART_Tx_Buffer_Storage, UART_CIRCULAR_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
//! Sends a message over the BLE UART.
|
||||
void COMM_BLE_UART_PutString(const char8 * string, uint16_t length)
|
||||
{
|
||||
for (uint8_t i = 0; i < length; i++)
|
||||
{
|
||||
(void) UTIL_PushToCircularBuffer(&UART_Tx_Buffer, *string++);
|
||||
}
|
||||
}
|
||||
|
||||
//! Sends a single character over the BLE UART.
|
||||
void COMM_BLE_UART_PutChar(char8 character)
|
||||
{
|
||||
(void) UTIL_PushToCircularBuffer(&UART_Tx_Buffer, character);
|
||||
}
|
||||
|
||||
void COMM_BLE_UART_MaybeSendData(void)
|
||||
{
|
||||
int8_t length = 0;
|
||||
|
||||
if (UTIL_IsCircularBufferEmpty(&UART_Tx_Buffer) == false)
|
||||
{
|
||||
while ((length < BLE_UART_BUFFER_CHARACTERISTIC_SIZE) && (UTIL_IsCircularBufferEmpty(&UART_Tx_Buffer) == false))
|
||||
{
|
||||
uint8_t value;
|
||||
if (UTIL_PopFromCircularBuffer(&UART_Tx_Buffer, &value) == UTIL_CIRCULARBUFFERRESULT_SUCCESS)
|
||||
{
|
||||
BLE_UART_Tx_Buffer[length] = value;
|
||||
length++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
for (uint_fast8_t i = 0; i < CY_BLE_CONN_COUNT; i++)
|
||||
{
|
||||
if (Cy_BLE_GetConnectionState(appConnHandle[i]) >= CY_BLE_CONN_STATE_CONNECTED)
|
||||
{
|
||||
cy_stc_ble_gatt_handle_value_pair_t tempHandle;
|
||||
|
||||
tempHandle.attrHandle = CY_BLE_NORDIC_UART_SERVICE_TX_CHAR_HANDLE;
|
||||
tempHandle.value.val = (uint8 *) BLE_UART_Tx_Buffer;
|
||||
tempHandle.value.actualLen = length;
|
||||
tempHandle.value.len = length;
|
||||
|
||||
Cy_BLE_GATTS_WriteAttributeValueLocal(&tempHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Send notification to each client that has TX notifications enabled.
|
||||
for (uint_fast8_t i = 0; i < CY_BLE_CONN_COUNT; i++)
|
||||
{
|
||||
if ((Cy_BLE_GetConnectionState(appConnHandle[i]) >= CY_BLE_CONN_STATE_CONNECTED) &&
|
||||
Cy_BLE_GATTS_IsNotificationEnabled(&appConnHandle[i],
|
||||
CY_BLE_NORDIC_UART_SERVICE_TX_TXCCCD_DESC_HANDLE))
|
||||
{
|
||||
cy_stc_ble_gatt_handle_value_pair_t tempHandle;
|
||||
|
||||
tempHandle.attrHandle = CY_BLE_NORDIC_UART_SERVICE_TX_CHAR_HANDLE;
|
||||
tempHandle.value.val = (uint8 *) BLE_UART_Tx_Buffer;
|
||||
tempHandle.value.actualLen = length;
|
||||
tempHandle.value.len = length;
|
||||
|
||||
Cy_BLE_GATTS_SendNotification(&appConnHandle[i], &tempHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! BLE event handler for the BLE UART feature.
|
||||
/*!
|
||||
* This function should be called *before* events are handled in the event handler passed to
|
||||
* Cy_BLE_Start(). If it returns `false`, then the rest of the event handler should proceed.
|
||||
*
|
||||
* \param event BLE stack event code received from the BLE middleware (one of cy_en_ble_event_t).
|
||||
* \param eventParam pointer to an event-specific data structure containing the relevant event information.
|
||||
* \return true if this handler has completely handled the event, and no further
|
||||
* handling is necessary; false otherwise.
|
||||
*/
|
||||
bool COMM_BLE_UART_HandleEvent(uint32 event, void * eventParam)
|
||||
{
|
||||
static cy_stc_ble_gatts_write_cmd_req_param_t * writeReqParameter;
|
||||
bool handled = false;
|
||||
|
||||
/* Take an action based on the current event */
|
||||
switch ((cy_en_ble_event_t)event)
|
||||
{
|
||||
// Handle a write request.
|
||||
case CY_BLE_EVT_GATTS_WRITE_REQ:
|
||||
|
||||
writeReqParameter = (cy_stc_ble_gatts_write_cmd_req_param_t*)eventParam;
|
||||
|
||||
// Request to write the UART.
|
||||
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.2.0%2Fble_sdk_app_nus_eval.html&cp=5_5_0_4_1_2_24
|
||||
if (writeReqParameter->handleValPair.attrHandle == CY_BLE_NORDIC_UART_SERVICE_RX_CHAR_HANDLE)
|
||||
{
|
||||
// Only update the value and write the response if the requested write is allowed.
|
||||
if (CY_BLE_GATT_ERR_NONE == Cy_BLE_GATTS_WriteAttributeValuePeer(&writeReqParameter->connHandle, &writeReqParameter->handleValPair))
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; (i < BLE_UART_BUFFER_CHARACTERISTIC_SIZE) && (i < writeReqParameter->handleValPair.value.len); i++)
|
||||
{
|
||||
Rx_Buffer[i] = writeReqParameter->handleValPair.value.val[i];
|
||||
}
|
||||
|
||||
// NULL-terminate the buffer.
|
||||
Rx_Buffer[i] = 0x00;
|
||||
|
||||
Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);
|
||||
|
||||
COMM_Console_Execute_Internal_Command(Rx_Buffer);
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
// Request for UART Tx notifications.
|
||||
if (writeReqParameter->handleValPair.attrHandle == CY_BLE_NORDIC_UART_SERVICE_TX_TXCCCD_DESC_HANDLE)
|
||||
{
|
||||
if (CY_BLE_GATT_ERR_NONE == Cy_BLE_GATTS_WriteAttributeValuePeer(&writeReqParameter->connHandle, &writeReqParameter->handleValPair))
|
||||
{
|
||||
UART_Tx_Notifications_Enabled = writeReqParameter->handleValPair.value.val[0] & 0x01;
|
||||
|
||||
if (UART_Tx_Notifications_Enabled)
|
||||
{
|
||||
COMM_Console_Print_String("[BLE] UART Tx notifications enabled.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("[BLE] UART Tx notifications disabled.\n");
|
||||
}
|
||||
|
||||
Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// (`handled` is already set to false.)
|
||||
break;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
/* Private Functions */
|
30
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_UART.h
Normal file
30
2020TPCAppNoDFU.cydsn/COMM/BLE/COMM_BLE_UART.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/** \file
|
||||
* \brief This file declares interface functions to a BLE UART implementation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMM_BLE_UART_H
|
||||
#define COMM_BLE_UART_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
void COMM_BLE_UART_Init(void);
|
||||
void COMM_BLE_UART_PutString(const char8 * string, uint16_t length);
|
||||
void COMM_BLE_UART_PutChar(char8 character);
|
||||
void COMM_BLE_UART_MaybeSendData(void);
|
||||
bool COMM_BLE_UART_HandleEvent(uint32 event, void * eventParam);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_BLE_UART_H
|
50
2020TPCAppNoDFU.cydsn/COMM/COMM.h
Normal file
50
2020TPCAppNoDFU.cydsn/COMM/COMM.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/** \dir "COMM"
|
||||
*
|
||||
* \brief This directory contains source code for the communication interfaces used by this software.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief This file defines the interface to the communications used by this software.
|
||||
*
|
||||
* This file should be included by any file outside the COMM package wishing to make use
|
||||
* of any of the configuration information provided by the COMM package.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMM_H
|
||||
#define COMM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Include Files */
|
||||
#include "COMM_IPC_Messages.h"
|
||||
#include "BLE/COMM_BLE.h"
|
||||
#include "BLE/COMM_BLE_Bond.h"
|
||||
#include "BLE/COMM_BLE_UART.h"
|
||||
#include "COMM_Console.h"
|
||||
#include "COMM_Console_Util.h"
|
||||
#include "COMM_I2C_Bus.h"
|
||||
#include "COMM_Util.h"
|
||||
#include "ConsoleCommands/COMM_ConsoleCommands.h"
|
||||
#include "ConsoleCommands/COMM_BLE_ConsoleCommands.h"
|
||||
#include "ConsoleCommands/COMM_NVM_ConsoleCommands.h"
|
||||
#include "ConsoleCommands/COMM_RTOS_ConsoleCommands.h"
|
||||
#include "ConsoleCommands/COMM_STATE_ConsoleCommands.h"
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
#define DebugPrintf(...)
|
||||
#define Task_DebugPrintf(...)
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_H
|
639
2020TPCAppNoDFU.cydsn/COMM/COMM_Console.c
Normal file
639
2020TPCAppNoDFU.cydsn/COMM/COMM_Console.c
Normal file
|
@ -0,0 +1,639 @@
|
|||
/** \file
|
||||
* \brief This file implements a simple serial debug console and command interpreter.
|
||||
*/
|
||||
|
||||
/** \defgroup CONSOLE Console
|
||||
*
|
||||
* \brief Serial debug console command interpreter.
|
||||
*
|
||||
* \todo Describe the command interpreter.
|
||||
*
|
||||
* @{
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
//! Text representations of numeric digits, used by COMM_Console_Print_UInt32().
|
||||
static const char8 DIGITS[] = "0123456789ABCDEF";
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
//! Maximum number of characters (save one) able to be printed by COMM_Console_Print_String().
|
||||
#define MAX_CONSOLE_STRING_LENGTH 81
|
||||
|
||||
//! States in the COMM_Console_Task() state machine.
|
||||
typedef enum
|
||||
{
|
||||
COMM_STATE_INITIALIZING = 0,
|
||||
COMM_STATE_DISPLAY_POWERUP_INFO,
|
||||
COMM_STATE_IDLE,
|
||||
COMM_STATE_COMMAND_TOO_LONG,
|
||||
COMM_STATE_IDENTIFY_COMMAND,
|
||||
COMM_STATE_EXECUTE_COMMAND,
|
||||
COMM_STATE_UNKNOWN_COMMAND
|
||||
} COMM_Console_State_T;
|
||||
|
||||
/* Public Variables */
|
||||
char8 Command_Buffer[COMM_CONSOLE_COMMAND_MAX_LENGTH];
|
||||
uint_fast16_t Command_Buffer_Index = 0;
|
||||
TaskHandle_t COMM_Console_Task_Handle;
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
//! Current state of the COMM_Console_Task() state machine.
|
||||
static COMM_Console_State_T Current_State = COMM_STATE_INITIALIZING;
|
||||
|
||||
//! Next state of the COMM_Console_Task() state machine.
|
||||
static COMM_Console_State_T Next_State = COMM_STATE_INITIALIZING;
|
||||
|
||||
//! Index into the #COMM_Console_Command_Table for the command currently being handled.
|
||||
/*!
|
||||
* If #Current_Command is set to UINT_FAST16_MAX, the command being handled is unknown, or no command is being handled.
|
||||
*/
|
||||
static uint_fast16_t Current_Command = 0;
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
static void ConsoleISR(void);
|
||||
static bool ConsoleCommandMatches(const char8 * const command_name);
|
||||
static void ReverseString(char8 * value, uint32_t length);
|
||||
|
||||
/* Inline Functions */
|
||||
|
||||
//! Swaps the characters in x and y.
|
||||
static inline void Swap_Char8(char8 * x, char8 * y)
|
||||
{
|
||||
uint8_t temp = *x;
|
||||
*x = *y;
|
||||
*y = temp;
|
||||
}
|
||||
|
||||
static inline void Reset_Command_Buffer()
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
for (uint_fast16_t i = 0; i < COMM_CONSOLE_COMMAND_MAX_LENGTH; i++)
|
||||
{
|
||||
Command_Buffer[i] = COMM_CONSOLE_STRING_TERMINATOR;
|
||||
}
|
||||
Command_Buffer_Index = 0;
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
//! Initializes the console.
|
||||
/*!
|
||||
* \ingroup CONSOLE
|
||||
*/
|
||||
void COMM_Console_Init(void)
|
||||
{
|
||||
// Enable the pullup on the Rx pin to keep the noise down.
|
||||
Cy_GPIO_SetDrivemode(UART_Console_rx_PORT, UART_Console_rx_NUM, CY_GPIO_DM_PULLUP);
|
||||
UART_Console_Start();
|
||||
|
||||
/// Unmask only the RX FIFO not empty interrupt bit.
|
||||
UART_Console_HW->INTR_RX_MASK = SCB_INTR_RX_MASK_NOT_EMPTY_Msk;
|
||||
Cy_SysInt_Init(&Int_UART_Console_cfg, ConsoleISR);
|
||||
NVIC_ClearPendingIRQ(Int_UART_Console_cfg.intrSrc);
|
||||
NVIC_EnableIRQ(Int_UART_Console_cfg.intrSrc);
|
||||
}
|
||||
|
||||
//! Parses and handle console commands in the background.
|
||||
/*!
|
||||
* \ingroup CONSOLE
|
||||
*
|
||||
* The [UML State Machine Diagram](http://www.uml-diagrams.org/state-machine-diagrams.html) below
|
||||
* shows how the console messages processed by this code. Note that all of the *Character Rx'd*
|
||||
* transitions occur in the #UART_Console_SPI_UART_ISR_EntryCallback() itself on the PSoC4, in
|
||||
* #ConsoleRxISR() on the PSoC5, and in #ConsoleISR() on the PSoC6, to improve overall performance.
|
||||
*
|
||||
* \startuml{COMM_Console_Task.png} "Console Task"
|
||||
*
|
||||
* skinparam headerFontSize 18
|
||||
* skinparam state {
|
||||
* BackgroundColor #eeeeee
|
||||
* BackgroundColor<<Error>> #ffaaaa
|
||||
* FontName Impact
|
||||
* FontSize 18
|
||||
* }
|
||||
* skinparam note {
|
||||
* FontName "Comic Sans MS"
|
||||
* FontStyle italic
|
||||
* }
|
||||
*
|
||||
* state "Initializing" as STATE_INITIALIZING
|
||||
* [*] --> STATE_INITIALIZING
|
||||
* note left of STATE_INITIALIZING : Wait for the rest of the system to come online.
|
||||
* state "Display Powerup Info" as STATE_DISPLAY_POWERUP_INFO
|
||||
* STATE_DISPLAY_POWERUP_INFO : do/ print OS version
|
||||
* STATE_DISPLAY_POWERUP_INFO : do/ print configuration (debug or release)
|
||||
* STATE_INITIALIZING --> STATE_DISPLAY_POWERUP_INFO : after(100ms)
|
||||
* state "Idle" as STATE_IDLE
|
||||
* STATE_IDLE : do/ RTOS_Sleep()
|
||||
* STATE_DISPLAY_POWERUP_INFO --> STATE_IDLE
|
||||
* state STATE_IS_EOM <<choice>>
|
||||
* note top of STATE_IS_EOM : This happens in\nUART_Console_SPI_UART_ISR_ExitCallback() on PSoC4,\nConsoleRxISR() on PSoC5,\nand ConsoleISR() on PSoC6.
|
||||
* STATE_IDLE --> STATE_IS_EOM : character rx'd
|
||||
* state STATE_IS_COMMAND_BUFFER_FULL <<choice>>
|
||||
* note top of STATE_IS_COMMAND_BUFFER_FULL : This happens in\nUART_Console_SPI_UART_ISR_ExitCallback() on PSoC4,\nConsoleRxISR() on PSoC5,\nand ConsoleISR() on PSoC6.
|
||||
* STATE_IS_EOM --> STATE_IS_COMMAND_BUFFER_FULL : [else]
|
||||
* state "Identify Command" as STATE_IDENTIFY_COMMAND
|
||||
* STATE_IDENTIFY_COMMAND : do/ look for command in the COMM_Console_Command_Table[]
|
||||
* STATE_IS_EOM --> STATE_IDENTIFY_COMMAND : [rx'd character is EOM]
|
||||
* STATE_IDLE --> STATE_IDENTIFY_COMMAND : COMM_Console_Execute_Internal_Command()
|
||||
* state "Command Too Long" as STATE_COMMAND_TOO_LONG
|
||||
* STATE_COMMAND_TOO_LONG : do/ print error message
|
||||
* STATE_COMMAND_TOO_LONG : do/ reset command buffer
|
||||
* STATE_IS_COMMAND_BUFFER_FULL --> STATE_COMMAND_TOO_LONG : [command buffer is full]
|
||||
* STATE_IS_COMMAND_BUFFER_FULL --> STATE_IDLE : [else]/\nAppend received character to command buffer
|
||||
* STATE_COMMAND_TOO_LONG --> STATE_IDLE
|
||||
* state "Execute Command" as STATE_EXECUTE_COMMAND
|
||||
* STATE_EXECUTE_COMMAND : do/ execute console command
|
||||
* STATE_EXECUTE_COMMAND : exit/ reset command buffer
|
||||
* STATE_EXECUTE_COMMAND --> STATE_IDLE
|
||||
* STATE_IDENTIFY_COMMAND --> STATE_EXECUTE_COMMAND : [command matched]
|
||||
* state "Unknown Command" as STATE_UNKNOWN_COMMAND
|
||||
* STATE_UNKNOWN_COMMAND : do/ print error message
|
||||
* STATE_UNKNOWN_COMMAND : do/ reset command buffer
|
||||
* STATE_IDENTIFY_COMMAND --> STATE_UNKNOWN_COMMAND : [else]
|
||||
* STATE_UNKNOWN_COMMAND --> STATE_IDLE
|
||||
*
|
||||
* left footer Key: UML 2.5\nLast modified 2020-12-14
|
||||
* \enduml
|
||||
*
|
||||
* \return None (infinite loop)
|
||||
*/
|
||||
void COMM_Console_Task(void * pvParameters)
|
||||
{
|
||||
static TickType_t xTicksToWait = pdMS_TO_TICKS(10);
|
||||
static uint32_t * NotificationValue;
|
||||
|
||||
while(true)
|
||||
{
|
||||
(void) xTaskNotifyWait(0, 0, (uint32_t *)&NotificationValue, xTicksToWait);
|
||||
|
||||
// Change to the next state atomically.
|
||||
taskENTER_CRITICAL();
|
||||
Current_State = Next_State;
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
switch (Current_State)
|
||||
{
|
||||
default:
|
||||
case COMM_STATE_INITIALIZING:
|
||||
Next_State = COMM_STATE_DISPLAY_POWERUP_INFO;
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
xTicksToWait = 1;
|
||||
break;
|
||||
|
||||
case COMM_STATE_DISPLAY_POWERUP_INFO:
|
||||
COMM_Console_Print_String("[COMM] ");
|
||||
COMM_RTOS_HandleConsoleVersion(NULL, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("[COMM] Console ready (awaiting commands).\n");
|
||||
Next_State = COMM_STATE_IDLE;
|
||||
xTicksToWait = 1;
|
||||
break;
|
||||
|
||||
case COMM_STATE_IDLE:
|
||||
xTicksToWait = pdMS_TO_TICKS(100);
|
||||
break;
|
||||
|
||||
case COMM_STATE_COMMAND_TOO_LONG:
|
||||
COMM_Console_Print_String("[COMM] ERROR: Command \"");
|
||||
COMM_Console_Print_String(Command_Buffer);
|
||||
COMM_Console_Print_String("\" too long!\n");
|
||||
Reset_Command_Buffer();
|
||||
Next_State = COMM_STATE_IDLE;
|
||||
xTicksToWait = 1;
|
||||
break;
|
||||
|
||||
case COMM_STATE_IDENTIFY_COMMAND:
|
||||
Current_Command = UINT_FAST16_MAX;
|
||||
|
||||
for (uint_fast16_t i = 0; i < COMM_N_CONSOLE_COMMANDS; i++)
|
||||
{
|
||||
if (ConsoleCommandMatches(COMM_Console_Command_Table[i].Command_Name) == true)
|
||||
{
|
||||
Current_Command = i;
|
||||
Next_State = COMM_STATE_EXECUTE_COMMAND;
|
||||
xTicksToWait = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Current_Command == UINT_FAST16_MAX)
|
||||
{
|
||||
// No matching command was found.
|
||||
Next_State = COMM_STATE_UNKNOWN_COMMAND;
|
||||
xTicksToWait = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case COMM_STATE_EXECUTE_COMMAND:
|
||||
if (COMM_Console_Command_Table[Current_Command].Execute_Command != NULL)
|
||||
{
|
||||
COMM_Console_Command_Result_T result = COMM_Console_Command_Table[Current_Command].Execute_Command(Command_Buffer, Command_Buffer_Index);
|
||||
|
||||
if (result == COMM_CONSOLE_CMD_RESULT_PARAMETER_ERROR)
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Parameter error!\n");
|
||||
}
|
||||
}
|
||||
Reset_Command_Buffer();
|
||||
Next_State = COMM_STATE_IDLE;
|
||||
xTicksToWait = 1;
|
||||
break;
|
||||
|
||||
case COMM_STATE_UNKNOWN_COMMAND:
|
||||
COMM_Console_Print_String("ERROR: Command \"");
|
||||
COMM_Console_Print_String(Command_Buffer);
|
||||
COMM_Console_Print_String("\" not recognized! Try '?' for help.\n");
|
||||
Reset_Command_Buffer();
|
||||
Next_State = COMM_STATE_IDLE;
|
||||
xTicksToWait = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SystemKResult_T HW_Execute_Console_Command(const uint8_t * const command)
|
||||
{
|
||||
COMM_Console_Execute_Internal_Command(command);
|
||||
|
||||
return SYSTEMK_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
//! Executes a (potentially cross-task) console command.
|
||||
/*!
|
||||
* This function is used to initiate a console command from a software source internal to this
|
||||
* CPU. This provides a way to use preexisting console commands on TX-only consoles.
|
||||
*
|
||||
* \note If two calls to this function are made back-to-back (before the COMM_Console_Task() has an
|
||||
* opportunity to run), only the second command will be executed, as it will have overwritten the
|
||||
* first. Allow time for the console commands to execute between calls to this function.
|
||||
*
|
||||
* \param command String containing the command to be executed.
|
||||
*/
|
||||
void COMM_Console_Execute_Internal_Command(const uint8_t * const command)
|
||||
{
|
||||
bool finished = false;
|
||||
uint_fast16_t i = 0;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
while ( (finished == false) &&
|
||||
(i < COMM_CONSOLE_COMMAND_MAX_LENGTH) &&
|
||||
(command[i] != COMM_CONSOLE_END_OF_MESSAGE ) &&
|
||||
(command[i] != COMM_CONSOLE_STRING_TERMINATOR )
|
||||
)
|
||||
{
|
||||
Command_Buffer[i] = command[i];
|
||||
i++;
|
||||
}
|
||||
Command_Buffer_Index = i;
|
||||
|
||||
// If there is still room, terminate the command.
|
||||
if (i < COMM_CONSOLE_COMMAND_MAX_LENGTH)
|
||||
{
|
||||
Command_Buffer[i] = COMM_CONSOLE_END_OF_MESSAGE;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
Next_State = COMM_STATE_IDENTIFY_COMMAND;
|
||||
xTaskNotifyGive(COMM_Console_Task_Handle);
|
||||
}
|
||||
|
||||
//! Prints a NULL-terminated string to the serial console.
|
||||
void COMM_Console_Print_String(const char8 * const text)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_CONSOLE_STRING_LENGTH; i++)
|
||||
{
|
||||
// Check for the end of the string. If there is no NULL terminator, up to
|
||||
// MAX_CONSOLE_STRING_LENGTH characters of randomness will be printed.
|
||||
if (text[i] == COMM_CONSOLE_STRING_TERMINATOR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Send out the string, one character at a time.
|
||||
COMM_Console_PutChar(text[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//! Prints a 32-bit unsigned integer to the serial console.
|
||||
void COMM_Console_Print_UInt32(uint32_t value)
|
||||
{
|
||||
// The largest string for a unit32_t is 10 characters (4294967296).
|
||||
char8 buffer[10+1];
|
||||
uint_fast8_t buffer_index = 0;
|
||||
|
||||
while (value > 9)
|
||||
{
|
||||
uint8_t digit_index = value % 10;
|
||||
buffer[buffer_index] = DIGITS[digit_index];
|
||||
value = value / 10;
|
||||
buffer_index++;
|
||||
}
|
||||
buffer[buffer_index] = DIGITS[value];
|
||||
buffer_index++;
|
||||
ReverseString(buffer, buffer_index);
|
||||
|
||||
// NULL-terminate the string.
|
||||
buffer[buffer_index] = 0;
|
||||
|
||||
COMM_Console_Print_String(buffer);
|
||||
}
|
||||
|
||||
//! Prints a 32-bit signed integer to the serial console.
|
||||
void COMM_Console_Print_SInt32(int32_t value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
value *= -1;
|
||||
COMM_Console_PutChar('-');
|
||||
}
|
||||
|
||||
COMM_Console_Print_UInt32(value);
|
||||
}
|
||||
|
||||
//! Prints a 32-bit unsigned integer to the serial console using a hexadecimal representation.
|
||||
void COMM_Console_Print_UInt32AsHex(uint32_t value)
|
||||
{
|
||||
// The largest hexadecimal string for a unit32_t is 8 characters (FFFFFFFF).
|
||||
char8 buffer[8+1];
|
||||
uint_fast8_t buffer_index = 0;
|
||||
|
||||
while (value > 15)
|
||||
{
|
||||
uint8_t digit_index = value % 16;
|
||||
buffer[buffer_index] = DIGITS[digit_index];
|
||||
value = value / 16;
|
||||
buffer_index++;
|
||||
}
|
||||
buffer[buffer_index] = DIGITS[value];
|
||||
buffer_index++;
|
||||
ReverseString(buffer, buffer_index);
|
||||
|
||||
// NULL-terminate the string.
|
||||
buffer[buffer_index] = 0;
|
||||
|
||||
COMM_Console_PutChar('0');
|
||||
COMM_Console_PutChar('x');
|
||||
COMM_Console_Print_String(buffer);
|
||||
}
|
||||
|
||||
//! Prints a 64-bit unsigned integer to the serial console.
|
||||
void COMM_Console_Print_UInt64(uint64_t value)
|
||||
{
|
||||
// The largest string for a unit64_t is 20 characters (18446744073709551615).
|
||||
char8 buffer[20+1];
|
||||
uint_fast8_t buffer_index = 0;
|
||||
|
||||
while (value > 9)
|
||||
{
|
||||
uint8_t digit_index = value % 10;
|
||||
buffer[buffer_index] = DIGITS[digit_index];
|
||||
value = value / 10;
|
||||
buffer_index++;
|
||||
}
|
||||
buffer[buffer_index] = DIGITS[value];
|
||||
buffer_index++;
|
||||
ReverseString(buffer, buffer_index);
|
||||
|
||||
// NULL-terminate the string.
|
||||
buffer[buffer_index] = 0;
|
||||
|
||||
COMM_Console_Print_String(buffer);
|
||||
}
|
||||
|
||||
//! Prints a 64-bit unsigned integer to the serial console using a hexadecimal representation.
|
||||
void COMM_Console_Print_UInt64AsHex(uint64_t value)
|
||||
{
|
||||
// The largest hexadecimal string for a unit64_t is 16 characters (FFFFFFFFFFFFFFFF).
|
||||
char8 buffer[16+1];
|
||||
uint_fast8_t buffer_index = 0;
|
||||
|
||||
while (value > 15)
|
||||
{
|
||||
uint8_t digit_index = value % 16;
|
||||
buffer[buffer_index] = DIGITS[digit_index];
|
||||
value = value / 16;
|
||||
buffer_index++;
|
||||
}
|
||||
buffer[buffer_index] = DIGITS[value];
|
||||
buffer_index++;
|
||||
ReverseString(buffer, buffer_index);
|
||||
|
||||
// NULL-terminate the string.
|
||||
buffer[buffer_index] = 0;
|
||||
|
||||
COMM_Console_PutChar('0');
|
||||
COMM_Console_PutChar('x');
|
||||
COMM_Console_Print_String(buffer);
|
||||
}
|
||||
|
||||
//! Prints a floating-point number to the serial console.
|
||||
/*!
|
||||
* With thanks to Rick Regan and his [Quick and Dirty Floating-Point to Decimal Conversion](https://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-conversion/).
|
||||
*/
|
||||
void COMM_Console_Print_Float(float value)
|
||||
{
|
||||
#define MAX_INTEGRAL_DIGITS 12
|
||||
#define MAX_FRACTIONAL_DIGITS 6
|
||||
#define BUFFER_SIZE (MAX_INTEGRAL_DIGITS + MAX_FRACTIONAL_DIGITS + 2)
|
||||
|
||||
char8 buffer[BUFFER_SIZE];
|
||||
char8 integral_buffer_reversed[MAX_INTEGRAL_DIGITS];
|
||||
uint16_t buffer_index = 0;
|
||||
double integral_value;
|
||||
double fractional_value;
|
||||
bool overflow = false;
|
||||
|
||||
if (value < 0.0)
|
||||
{
|
||||
COMM_Console_Print_String("-");
|
||||
value *= -1.0;
|
||||
}
|
||||
|
||||
// Break the given value into fractional and integral parts.
|
||||
fractional_value = modf(value, &integral_value);
|
||||
|
||||
if (integral_value > 0)
|
||||
{
|
||||
// Convert the integral part.
|
||||
while ((integral_value > 0) && (buffer_index < MAX_INTEGRAL_DIGITS))
|
||||
{
|
||||
integral_buffer_reversed[buffer_index++] = '0' + (int)fmod(integral_value, 10);
|
||||
integral_value = floor(integral_value / 10);
|
||||
}
|
||||
|
||||
// If there is still an integral part remaining, and overflow has occurred.
|
||||
if (integral_value > 0)
|
||||
{
|
||||
overflow = true;
|
||||
}
|
||||
|
||||
// Reverse and append the integral part.
|
||||
for (uint16_t i = 0; i < buffer_index; i++)
|
||||
{
|
||||
buffer[i] = integral_buffer_reversed[buffer_index-i-1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append a leading zero.
|
||||
buffer[buffer_index++] = '0';
|
||||
}
|
||||
|
||||
// Append the decimal point.
|
||||
buffer[buffer_index++] = '.';
|
||||
|
||||
// Convert the fractional part, even if it is zero, and leave room for the NULL terminator.
|
||||
while (buffer_index < (BUFFER_SIZE - 1))
|
||||
{
|
||||
fractional_value *= 10;
|
||||
buffer[buffer_index++] = '0' + (int)fractional_value;
|
||||
fractional_value = modf(fractional_value, &integral_value);
|
||||
}
|
||||
|
||||
// Append the NULL terminator.
|
||||
buffer[buffer_index] = 0;
|
||||
|
||||
if (overflow == true)
|
||||
{
|
||||
COMM_Console_Print_String("OVERFLOW");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
//! Converts a byte to a two-character hexadecimal representation.
|
||||
/*!
|
||||
* \param buffer Buffer into which to place the resulting sting. It needs to be at least three
|
||||
* characters wide.
|
||||
* \param byte The byte to be converted.
|
||||
*/
|
||||
void COMM_Console_ByteToHex(char8 * buffer, uint8_t byte)
|
||||
{
|
||||
if (byte < 16)
|
||||
{
|
||||
buffer[0] = '0';
|
||||
buffer[1] = DIGITS[byte];
|
||||
buffer[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[0] = DIGITS[byte / 16];
|
||||
buffer[1] = DIGITS[byte % 16];
|
||||
buffer[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
static void ConsoleISR(void)
|
||||
{
|
||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
// Check for the "Rx FIFO not empty" interrput.
|
||||
if ((UART_Console_HW->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk ) != 0)
|
||||
{
|
||||
// Clear the "Rx FIFO not empty" interrput.
|
||||
UART_Console_HW->INTR_RX = UART_Console_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;
|
||||
|
||||
// Get the character.
|
||||
uint32_t value = UART_Console_Get();
|
||||
|
||||
// Check if there is actually data. Sometimes the flag is set when there is no data (why?).
|
||||
if (value != CY_SCB_UART_RX_NO_DATA)
|
||||
{
|
||||
char8 rx_data = (char8) value;
|
||||
|
||||
// Determine what to do with it.
|
||||
if (Command_Buffer_Index < COMM_CONSOLE_COMMAND_MAX_LENGTH)
|
||||
{
|
||||
if (rx_data == COMM_CONSOLE_END_OF_MESSAGE)
|
||||
{
|
||||
Command_Buffer[Command_Buffer_Index] = COMM_CONSOLE_STRING_TERMINATOR;
|
||||
Next_State = COMM_STATE_IDENTIFY_COMMAND;
|
||||
vTaskNotifyGiveFromISR(COMM_Console_Task_Handle, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
else
|
||||
{
|
||||
Command_Buffer[Command_Buffer_Index] = rx_data;
|
||||
Command_Buffer_Index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Next_State = COMM_STATE_COMMAND_TOO_LONG;
|
||||
vTaskNotifyGiveFromISR(COMM_Console_Task_Handle, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NVIC_ClearPendingIRQ(Int_UART_Console_cfg.intrSrc);
|
||||
|
||||
// If the state needs to change, a context switch might be required.
|
||||
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
static bool ConsoleCommandMatches(const char8 * const command_name)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
bool is_match = false;
|
||||
|
||||
if (Command_Buffer[i] == command_name[i])
|
||||
{
|
||||
is_match = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
while ( (is_match == true) &&
|
||||
(i < COMM_CONSOLE_COMMAND_MAX_LENGTH) &&
|
||||
(Command_Buffer[i] != COMM_CONSOLE_PARAMETER_DELIMITER) &&
|
||||
(Command_Buffer[i] != COMM_CONSOLE_END_OF_MESSAGE ) &&
|
||||
(Command_Buffer[i] != COMM_CONSOLE_STRING_TERMINATOR )
|
||||
)
|
||||
{
|
||||
if ( Command_Buffer[i] != command_name[i] )
|
||||
{
|
||||
is_match = false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return is_match;
|
||||
}
|
||||
|
||||
//! Reverses a string in place.
|
||||
/*!
|
||||
* \param value Pointer to the string to be reversed.
|
||||
* \param length Length of the string, including the NULL terminator.
|
||||
*/
|
||||
static void ReverseString(char8 * value, uint32_t length)
|
||||
{
|
||||
if (length > 1)
|
||||
{
|
||||
uint_fast32_t start = 0;
|
||||
uint_fast32_t end = length - 1;
|
||||
while (start < end)
|
||||
{
|
||||
Swap_Char8(value + start, value + end);
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
144
2020TPCAppNoDFU.cydsn/COMM/COMM_Console.h
Normal file
144
2020TPCAppNoDFU.cydsn/COMM/COMM_Console.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
/** \file
|
||||
* \brief This file defines the interface to a simple serial debug console and command interpreter.
|
||||
*
|
||||
* \note As always, <project.h> and <CONFIG.h> should be included <I>before</I> this file.
|
||||
*/
|
||||
|
||||
#ifndef COMM_CONSOLE_H
|
||||
#define COMM_CONSOLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
#define COMM_CONSOLE_TASK_STACK_SIZE_in_bytes 512
|
||||
|
||||
#define COMM_Console_PutChar UART_and_BLE_PutChar
|
||||
#define COMM_Console_PutString UART_and_BLE_PutString
|
||||
|
||||
#define COMM_CONSOLE_COMMAND_MAX_LENGTH 50
|
||||
|
||||
//! Character signifying the end of a console message.
|
||||
#define COMM_CONSOLE_END_OF_MESSAGE ('\n')
|
||||
|
||||
//! Character used between parameters in a console message.
|
||||
#define COMM_CONSOLE_PARAMETER_DELIMITER (' ')
|
||||
|
||||
//! Character signifying the end of a string.
|
||||
#define COMM_CONSOLE_STRING_TERMINATOR ('\0')
|
||||
|
||||
//! Result of executing a console command callback.
|
||||
typedef enum
|
||||
{
|
||||
COMM_CONSOLE_CMD_RESULT_UNKNOWN = 0,
|
||||
COMM_CONSOLE_CMD_RESULT_SUCCESS = 1,
|
||||
COMM_CONSOLE_CMD_RESULT_PARAMETER_ERROR = 2
|
||||
} COMM_Console_Command_Result_T;
|
||||
|
||||
//! Result of parsing a console command parameter.
|
||||
typedef enum
|
||||
{
|
||||
COMM_CONSOLE_PARAMETER_RESULT_UNKNOWN = 0,
|
||||
COMM_CONSOLE_PARAMETER_RESULT_SUCCESS = 1,
|
||||
COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR = 2,
|
||||
COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END = 3
|
||||
} COMM_Console_Parameter_Result_T;
|
||||
|
||||
//! Prototype of a console command callback.
|
||||
/*!
|
||||
* \ingroup CONSOLE
|
||||
* All console commands must use this signature.
|
||||
*
|
||||
* \param[in] data Pointer to the string containg the console command (and any arguments).
|
||||
* \param[in] size Size (in char8) of the data string.
|
||||
* \return #COMM_CONSOLE_CMD_RESULT_SUCCESS on success
|
||||
* \return #COMM_Console_Command_Result_T otherwise
|
||||
*/
|
||||
typedef COMM_Console_Command_Result_T (* const COMM_Console_Command_Handler_T)(char8 * data, uint32_t size);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char8 * const Command_Name;
|
||||
const char8 * const Help;
|
||||
COMM_Console_Command_Handler_T Execute_Command;
|
||||
} COMM_Console_Command_Table_Entry_T;
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
//! Handle of the COMM_Console_Task() given when the task was created.
|
||||
extern TaskHandle_t COMM_Console_Task_Handle;
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
void COMM_Console_Init(void);
|
||||
void COMM_Console_Task(void * pvParameters);
|
||||
void COMM_Console_Execute_Internal_Command(const uint8_t * const command);
|
||||
void COMM_Console_Print_String(const char8 * const text);
|
||||
void COMM_Console_Print_UInt32(uint32_t value);
|
||||
void COMM_Console_Print_SInt32(int32_t value);
|
||||
void COMM_Console_Print_UInt32AsHex(uint32_t value);
|
||||
void COMM_Console_Print_UInt64(uint64_t value);
|
||||
void COMM_Console_Print_UInt64AsHex(uint64_t value);
|
||||
void COMM_Console_Print_Float(float value);
|
||||
|
||||
void COMM_Console_ByteToHex(char8 * buffer, uint8_t byte);
|
||||
|
||||
/* Inline Functions */
|
||||
|
||||
//! Prints an 8-bit unsigned integer to the serial console.
|
||||
inline void COMM_Console_Print_UInt8(uint8_t value)
|
||||
{
|
||||
COMM_Console_Print_UInt32((uint32_t) value);
|
||||
}
|
||||
|
||||
//! Prints an 8-bit unsigned integer to the serial console using a hexadecimal representation.
|
||||
inline void COMM_Console_Print_UInt8AsHex(uint8_t value)
|
||||
{
|
||||
COMM_Console_Print_UInt32AsHex((uint32_t) value);
|
||||
}
|
||||
|
||||
//! Prints an 8-bit signed integer to the serial console.
|
||||
inline void COMM_Console_Print_Int8(int8_t value)
|
||||
{
|
||||
COMM_Console_Print_SInt32((int32_t) value);
|
||||
}
|
||||
|
||||
//! Prints a 16-bit unsigned integer to the serial console.
|
||||
inline void COMM_Console_Print_UInt16(uint16_t value)
|
||||
{
|
||||
COMM_Console_Print_UInt32((uint32_t) value);
|
||||
}
|
||||
|
||||
//! Prints a 16-bit unsigned integer to the serial console using a hexadecimal representation.
|
||||
inline void COMM_Console_Print_UInt16AsHex(uint16_t value)
|
||||
{
|
||||
COMM_Console_Print_UInt32AsHex((uint32_t) value);
|
||||
}
|
||||
|
||||
//! Prints a 16-bit signed integer to the serial console.
|
||||
inline void COMM_Console_Print_Int16(int16_t value)
|
||||
{
|
||||
COMM_Console_Print_SInt32((int32_t) value);
|
||||
}
|
||||
|
||||
static inline void UART_and_BLE_PutChar(uint8 txDataByte)
|
||||
{
|
||||
UART_Console_Put(txDataByte);
|
||||
COMM_BLE_UART_PutChar(txDataByte);
|
||||
}
|
||||
|
||||
static inline void UART_and_BLE_PutString(const char8 string[])
|
||||
{
|
||||
UART_Console_PutString(string);
|
||||
COMM_BLE_UART_PutString(string, strlen(string));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_CONSOLE_H
|
254
2020TPCAppNoDFU.cydsn/COMM/COMM_Console_Util.c
Normal file
254
2020TPCAppNoDFU.cydsn/COMM/COMM_Console_Util.c
Normal file
|
@ -0,0 +1,254 @@
|
|||
/** \file
|
||||
* \brief This file implements utility functions used by the command interpreter.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup CONSOLE
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
//! Find the start location of the nth parameter in the buffer.
|
||||
/*!
|
||||
* \note The command itself is parameter 0.
|
||||
*/
|
||||
COMM_Console_Parameter_Result_T COMM_Console_FindNthParameter(const char * const buffer, const uint8_t parameterNumber, const char ** parameterLocation)
|
||||
{
|
||||
uint32_t buffer_index = 0;
|
||||
uint32_t parameter_index = 0;
|
||||
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
|
||||
|
||||
while (parameterNumber != parameter_index)
|
||||
{
|
||||
if (buffer[buffer_index] == COMM_CONSOLE_PARAMETER_DELIMITER)
|
||||
{
|
||||
parameter_index++;
|
||||
}
|
||||
else if (buffer[buffer_index] == COMM_CONSOLE_END_OF_MESSAGE)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
break;
|
||||
}
|
||||
else if (buffer[buffer_index] == COMM_CONSOLE_STRING_TERMINATOR)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
break;
|
||||
}
|
||||
buffer_index++;
|
||||
}
|
||||
|
||||
if (result == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
*parameterLocation = &buffer[buffer_index];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt8(const char * const buffer, uint8_t * const parameterUInt8)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
|
||||
// Strings containing uint8s range from "0" to "255". The large number has three characters.
|
||||
uint_fast16_t MAX_CHARACTERS = 3;
|
||||
uint_fast16_t index = 0;
|
||||
|
||||
while (index < (MAX_CHARACTERS + 1))
|
||||
{
|
||||
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
|
||||
{
|
||||
value *= 10;
|
||||
value += buffer[index] - '0';
|
||||
index++;
|
||||
}
|
||||
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
|
||||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
|
||||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
|
||||
*parameterUInt8 = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt16(const char * const buffer, uint16_t * const parameterUInt16)
|
||||
{
|
||||
uint16_t value = 0;
|
||||
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
|
||||
// Strings containing uint16s range from "0" to "65535". The large number has five characters.
|
||||
uint_fast16_t MAX_CHARACTERS = 5;
|
||||
uint_fast16_t index = 0;
|
||||
|
||||
while (index < (MAX_CHARACTERS + 1))
|
||||
{
|
||||
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
|
||||
{
|
||||
value *= 10;
|
||||
value += buffer[index] - '0';
|
||||
index++;
|
||||
}
|
||||
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
|
||||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
|
||||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
|
||||
*parameterUInt16 = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterInt32(const char * const buffer, int32_t * const parameterInt32)
|
||||
{
|
||||
int32_t value = 0;
|
||||
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
bool is_negative = false;
|
||||
|
||||
// Strings containing int32s range from "-2147483648" to "2147483647". The negative number has eleven characters.
|
||||
uint_fast16_t MAX_CHARACTERS = 11;
|
||||
uint_fast16_t index = 0;
|
||||
|
||||
if (buffer[index] == '-')
|
||||
{
|
||||
is_negative = true;
|
||||
index++;
|
||||
}
|
||||
|
||||
while (index < (MAX_CHARACTERS + 1))
|
||||
{
|
||||
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
|
||||
{
|
||||
value *= 10;
|
||||
value += buffer[index] - '0';
|
||||
index++;
|
||||
}
|
||||
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
|
||||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
|
||||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_negative == true)
|
||||
{
|
||||
value *= -1;
|
||||
}
|
||||
|
||||
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
|
||||
*parameterInt32 = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt32(const char * const buffer, uint32_t * const parameterUInt32)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
|
||||
// Strings containing uint32s range from "0" to "4294967296". The large number has ten characters.
|
||||
uint_fast16_t MAX_CHARACTERS = 10;
|
||||
uint_fast16_t index = 0;
|
||||
|
||||
while (index < (MAX_CHARACTERS + 1))
|
||||
{
|
||||
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
|
||||
{
|
||||
value *= 10;
|
||||
value += buffer[index] - '0';
|
||||
index++;
|
||||
}
|
||||
else if ( (buffer[index] == COMM_CONSOLE_PARAMETER_DELIMITER) ||
|
||||
(buffer[index] == COMM_CONSOLE_STRING_TERMINATOR) ||
|
||||
(buffer[index] == COMM_CONSOLE_END_OF_MESSAGE) )
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
|
||||
*parameterUInt32 = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeHexParameterUInt64(const char * const buffer, uint64_t * const parameterUInt64)
|
||||
{
|
||||
COMM_Console_Parameter_Result_T result = COMM_CONSOLE_PARAMETER_RESULT_SUCCESS;
|
||||
struct _reent context;
|
||||
|
||||
context._errno = 0;
|
||||
|
||||
*parameterUInt64 = _strtoull_r(&context, buffer, NULL, 16);
|
||||
|
||||
if (context._errno != 0)
|
||||
{
|
||||
result = COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
50
2020TPCAppNoDFU.cydsn/COMM/COMM_Console_Util.h
Normal file
50
2020TPCAppNoDFU.cydsn/COMM/COMM_Console_Util.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/** \file
|
||||
* \brief Utility functions used by the command interpreter.
|
||||
*
|
||||
* \note As always, <project.h> and <RTOS.h> should be included <I>before</I> this file.
|
||||
*/
|
||||
|
||||
#ifndef COMM_CONSOLE_UTIL_H
|
||||
#define COMM_CONSOLE_UTIL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
COMM_Console_Parameter_Result_T COMM_Console_FindNthParameter(const char * const buffer, const uint8_t parameterNumber, const char ** parameterLocation);
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt8(const char * const buffer, uint8_t * const parameterUInt8);
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt16(const char * const buffer, uint16_t * const parameterUInt16);
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterInt32(const char * const buffer, int32_t * const parameterInt32);
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeParameterUInt32(const char * const buffer, uint32_t * const parameterUInt32);
|
||||
COMM_Console_Parameter_Result_T COMM_Console_DecodeHexParameterUInt64(const char * const buffer, uint64_t * const parameterUInt64);
|
||||
|
||||
//! Returns `true` if this character marks the end of a console message; `false` otherwise.
|
||||
inline bool COMM_Console_IsEndOfMessage(char8 character)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if ( (character == COMM_CONSOLE_END_OF_MESSAGE) ||
|
||||
(character == COMM_CONSOLE_STRING_TERMINATOR) )
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_CONSOLE_UTIL_H
|
33
2020TPCAppNoDFU.cydsn/COMM/COMM_I2C_Bus.c
Normal file
33
2020TPCAppNoDFU.cydsn/COMM/COMM_I2C_Bus.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/** \file
|
||||
* \brief This file implements the I²C bus.
|
||||
*
|
||||
* See COMM_I2C_Bus.h for a detailed description of the functionality implemented by this code.
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
SemaphoreHandle_t COMM_I2C_Bus_Mutex = NULL;
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
//! Initializes the I²C bus.
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
void COMM_I2C_Init(void)
|
||||
{
|
||||
COMM_I2C_Bus_Mutex = xSemaphoreCreateMutex();
|
||||
I2C_Start();
|
||||
}
|
||||
|
||||
|
||||
/* Private Functions */
|
29
2020TPCAppNoDFU.cydsn/COMM/COMM_I2C_Bus.h
Normal file
29
2020TPCAppNoDFU.cydsn/COMM/COMM_I2C_Bus.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/** \file
|
||||
* \brief This file defines the interface to the I²C bus.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMM_I2C_BUS_H
|
||||
#define COMM_I2C_BUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
|
||||
/* Include Files */
|
||||
|
||||
|
||||
/* Public Variables */
|
||||
extern SemaphoreHandle_t COMM_I2C_Bus_Mutex;
|
||||
|
||||
/* Public Functions */
|
||||
void COMM_I2C_Init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_I2C_BUS_H
|
285
2020TPCAppNoDFU.cydsn/COMM/COMM_IPC_Messages.c
Normal file
285
2020TPCAppNoDFU.cydsn/COMM/COMM_IPC_Messages.c
Normal file
|
@ -0,0 +1,285 @@
|
|||
/** \file
|
||||
* \brief This file implements messaging using inter-processor communication (IPC).
|
||||
*
|
||||
* \see https://community.cypress.com/thread/36182.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup CONSOLE
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <project.h>
|
||||
|
||||
#include "COMM_IPC_Messages.h"
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
#if (__CORTEX_M == 0)
|
||||
static void Message_Received_for_CM0(uint32_t * msg);
|
||||
static void Message_Received_by_CM4(void);
|
||||
#endif // (__CORTEX_M == 0)
|
||||
|
||||
#if (__CORTEX_M == 4)
|
||||
static void Message_Received_for_CM4(uint32_t * msg);
|
||||
static void Message_Received_by_CM0(void);
|
||||
#endif // (__CORTEX_M == 4)
|
||||
|
||||
static void IPC_UserPipeInit(void);
|
||||
static void IPC_UserPipeISR(void);
|
||||
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
//! Number of clients supported on the user pipe.
|
||||
#define CY_IPC_USRPIPE_CLIENT_CNT (uint32_t)(8u)
|
||||
|
||||
#define CY_IPC_CHAN_USRPIPE_CM0 (uint32_t)(8u)
|
||||
#define CY_IPC_CHAN_USRPIPE_CM4 (uint32_t)(9u)
|
||||
|
||||
#define CY_IPC_INTR_USRPIPE_CM0 (uint32_t)(8u)
|
||||
#define CY_IPC_INTR_USRPIPE_CM4 (uint32_t)(9u)
|
||||
|
||||
#define CY_IPC_EP_USRPIPE_ADDR_CM0_EP (uint32_t)(2u)
|
||||
#define CY_IPC_EP_USRPIPE_ADDR_CM4_EP (uint32_t)(3u)
|
||||
|
||||
#if (CY_CPU_CORTEX_M0P)
|
||||
#define IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_ADDR_CM0_EP
|
||||
#else
|
||||
#define IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_ADDR_CM4_EP
|
||||
#endif /* (CY_CPU_CORTEX_M0P) */
|
||||
|
||||
/* User Pipe Configuration */
|
||||
|
||||
#define IPC_USRPIPE_CHAN_MASK_CM0 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM0)
|
||||
#define IPC_USRPIPE_CHAN_MASK_CM4 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM4)
|
||||
#define IPC_USRPIPE_INTR_MASK (uint32_t)( IPC_USRPIPE_CHAN_MASK_CM0 | IPC_USRPIPE_CHAN_MASK_CM4 )
|
||||
#define IPC_INTR_USRPIPE_PRIOR_CM0 (uint32_t)(1u) /* Notifier Priority */
|
||||
#define IPC_INTR_USRPIPE_PRIOR_CM4 (uint32_t)(1u) /* Notifier Priority */
|
||||
#define IPC_INTR_USRPIPE_MUX_CM0 (uint32_t)(7u) /* IPC CYPRESS PIPE */
|
||||
#define IPC_USRPIPE_CONFIG_CM0 (uint32_t)(IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos)\
|
||||
|(CY_IPC_INTR_USRPIPE_CM0 << CY_IPC_PIPE_CFG_INTR_Pos )\
|
||||
|(CY_IPC_CHAN_USRPIPE_CM0)
|
||||
#define IPC_USRPIPE_CONFIG_CM4 (uint32_t)(IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos)\
|
||||
|(CY_IPC_INTR_USRPIPE_CM4 << CY_IPC_PIPE_CFG_INTR_Pos )\
|
||||
|(CY_IPC_CHAN_USRPIPE_CM4)
|
||||
|
||||
#define USRPIPE_CONFIG \
|
||||
{\
|
||||
/* .ep0ConfigData */ {\
|
||||
/* .ipcNotifierNumber */ CY_IPC_INTR_USRPIPE_CM0,\
|
||||
/* .ipcNotifierPriority */ IPC_INTR_USRPIPE_PRIOR_CM0,\
|
||||
/* .ipcNotifierMuxNumber */ IPC_INTR_USRPIPE_MUX_CM0,\
|
||||
/* .epAddress */ CY_IPC_EP_USRPIPE_ADDR_CM0_EP,\
|
||||
/* .epConfig */ IPC_USRPIPE_CONFIG_CM0\
|
||||
},\
|
||||
/* .ep1ConfigData */ {\
|
||||
/* .ipcNotifierNumber */ CY_IPC_INTR_USRPIPE_CM4,\
|
||||
/* .ipcNotifierPriority */ IPC_INTR_USRPIPE_PRIOR_CM4,\
|
||||
/* .ipcNotifierMuxNumber */ 0u,\
|
||||
/* .epAddress */ CY_IPC_EP_USRPIPE_ADDR_CM4_EP,\
|
||||
/* .epConfig */ IPC_USRPIPE_CONFIG_CM4\
|
||||
},\
|
||||
/* .endpointClientsCount */ CY_IPC_USRPIPE_CLIENT_CNT,\
|
||||
/* .endpointsCallbacksArray */ ipc_pipe_CbArray,\
|
||||
/* .userPipeIsrHandler */ &IPC_UserPipeISR\
|
||||
}
|
||||
|
||||
//! Client ID for messages from the CM0 to the CM4
|
||||
#define COMM_IPC_CM0_TO_CM4_CLIENT_ID 0
|
||||
//! Client ID for messages from the CM4 to the CM0
|
||||
#define COMM_IPC_CM4_TO_CM0_CLIENT_ID 1
|
||||
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
#if (__CORTEX_M == 0)
|
||||
static COMM_IPCMessage_T MessageBuffer =
|
||||
{
|
||||
.ClientID = _VAL2FLD(CY_IPC_PIPE_MSG_CLIENT, COMM_IPC_CM0_TO_CM4_CLIENT_ID) | _VAL2FLD(CY_IPC_PIPE_MSG_USR, 0) | _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, IPC_USRPIPE_INTR_MASK),
|
||||
.MessageID = COMM_SMM_DefaultNoMessage,
|
||||
.Data = NULL
|
||||
};
|
||||
|
||||
static volatile bool OK_to_send_from_CM0_to_CM4 = true;
|
||||
#endif // (__CORTEX_M == 0)
|
||||
|
||||
#if (__CORTEX_M == 4)
|
||||
static COMM_IPCMessage_T MessageBuffer =
|
||||
{
|
||||
.ClientID = _VAL2FLD(CY_IPC_PIPE_MSG_CLIENT, COMM_IPC_CM4_TO_CM0_CLIENT_ID) | _VAL2FLD(CY_IPC_PIPE_MSG_USR, 0) | _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, IPC_USRPIPE_INTR_MASK),
|
||||
.MessageID = COMM_SMM_DefaultNoMessage,
|
||||
.Data = NULL
|
||||
};
|
||||
|
||||
static volatile bool OK_to_send_from_CM4_to_CM0 = true;
|
||||
#endif // (__CORTEX_M == 4)
|
||||
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
#if (__CORTEX_M == 0)
|
||||
//! Initializes the inter-processor communications on the Cortex-M0 core.
|
||||
/*!
|
||||
* This should be called *before* calling Cy_SysEnableCM4().
|
||||
*/
|
||||
void COMM_InitIPCMessages(void)
|
||||
{
|
||||
IPC_UserPipeInit();
|
||||
|
||||
// Register a callback to handle messages from CM4.
|
||||
Cy_IPC_Pipe_RegisterCallback(IPC_EP_USRPIPE_ADDR,
|
||||
Message_Received_for_CM0,
|
||||
CY_IPC_EP_CYPIPE_CM4_ADDR);
|
||||
}
|
||||
#endif // (__CORTEX_M == 0)
|
||||
|
||||
#if (__CORTEX_M == 4)
|
||||
//! Initializes the inter-processor communications on the Cortex-M4 core.
|
||||
void COMM_InitIPCMessages(void)
|
||||
{
|
||||
IPC_UserPipeInit();
|
||||
|
||||
// Register a callback to handle messages from CM0.
|
||||
Cy_IPC_Pipe_RegisterCallback(IPC_EP_USRPIPE_ADDR,
|
||||
Message_Received_for_CM4,
|
||||
CY_IPC_EP_CYPIPE_CM0_ADDR);
|
||||
}
|
||||
#endif // (__CORTEX_M == 4)
|
||||
|
||||
|
||||
//! Sends an inter-processor communication message to the other core.
|
||||
bool COMM_SendMessageToOtherCore(COMM_IPCMessageID_T message_ID, void * message_data)
|
||||
{
|
||||
bool message_sent = false;
|
||||
|
||||
MessageBuffer.MessageID = message_ID;
|
||||
MessageBuffer.Data = message_data;
|
||||
|
||||
#if (__CORTEX_M == 0)
|
||||
if (OK_to_send_from_CM0_to_CM4 == true)
|
||||
{
|
||||
OK_to_send_from_CM0_to_CM4 = false;
|
||||
uint32_t timeout_in_us = 2000;
|
||||
cy_en_ipc_pipe_status_t ipcStatus;
|
||||
|
||||
do
|
||||
{
|
||||
ipcStatus = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_USRPIPE_ADDR_CM4_EP,
|
||||
CY_IPC_EP_USRPIPE_ADDR_CM0_EP,
|
||||
(uint32_t *) &MessageBuffer,
|
||||
Message_Received_by_CM4);
|
||||
Cy_SysLib_DelayUs(1u);
|
||||
timeout_in_us--;
|
||||
} while((ipcStatus != CY_IPC_PIPE_SUCCESS) && (timeout_in_us != 0));
|
||||
|
||||
message_sent = true;
|
||||
}
|
||||
#endif // (__CORTEX_M == 0)
|
||||
|
||||
#if (__CORTEX_M == 4)
|
||||
if (OK_to_send_from_CM4_to_CM0 == true)
|
||||
{
|
||||
OK_to_send_from_CM4_to_CM0 = false;
|
||||
uint32_t timeout_in_us = 2000;
|
||||
cy_en_ipc_pipe_status_t ipcStatus;
|
||||
|
||||
do
|
||||
{
|
||||
ipcStatus = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_USRPIPE_ADDR_CM0_EP,
|
||||
CY_IPC_EP_USRPIPE_ADDR_CM4_EP,
|
||||
(uint32_t *) &MessageBuffer,
|
||||
Message_Received_by_CM0);
|
||||
Cy_SysLib_DelayUs(1u);
|
||||
timeout_in_us--;
|
||||
} while((ipcStatus != CY_IPC_PIPE_SUCCESS) && (timeout_in_us != 0));
|
||||
|
||||
message_sent = true;
|
||||
}
|
||||
#endif // (__CORTEX_M == 4)
|
||||
|
||||
return message_sent;
|
||||
}
|
||||
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
#if (__CORTEX_M == 0)
|
||||
//! Callback for messages received by the CM0 core from the CM4 core.
|
||||
/*!
|
||||
* \note This code is executed inside an interrupt handler.
|
||||
*/
|
||||
static void Message_Received_for_CM0(uint32_t * msg)
|
||||
{
|
||||
switch (((COMM_IPCMessage_T *)msg)->MessageID)
|
||||
{
|
||||
default:
|
||||
case COMM_SMM_DefaultNoMessage:
|
||||
case COMM_SMM_NoMessage:
|
||||
break;
|
||||
|
||||
case COMM_SMM_RebootImmediately:
|
||||
// Perform a software reset of both cores.
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Message_Received_by_CM4(void)
|
||||
{
|
||||
OK_to_send_from_CM0_to_CM4 = true;
|
||||
}
|
||||
#endif // (__CORTEX_M == 0)
|
||||
|
||||
#if (__CORTEX_M == 4)
|
||||
//! Callback for messages received by the CM4 core from the CM0 core.
|
||||
/*!
|
||||
* \note This code is executed inside an interrupt handler.
|
||||
*/
|
||||
static void Message_Received_for_CM4(uint32_t * msg)
|
||||
{
|
||||
switch (((COMM_IPCMessage_T *)msg)->MessageID)
|
||||
{
|
||||
default:
|
||||
case COMM_SMM_DefaultNoMessage:
|
||||
case COMM_SMM_NoMessage:
|
||||
break;
|
||||
|
||||
case COMM_SMM_RebootImmediately:
|
||||
// This message does nothing on CM4
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Message_Received_by_CM0(void)
|
||||
{
|
||||
OK_to_send_from_CM4_to_CM0 = true;
|
||||
}
|
||||
#endif // (__CORTEX_M == 4)
|
||||
|
||||
//! Initializes the IPC user pipe.
|
||||
static void IPC_UserPipeInit(void)
|
||||
{
|
||||
static cy_ipc_pipe_callback_ptr_t ipc_pipe_CbArray[CY_IPC_USRPIPE_CLIENT_CNT];
|
||||
static const cy_stc_ipc_pipe_config_t userPipeConfig = USRPIPE_CONFIG;
|
||||
|
||||
uint32_t savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
||||
|
||||
Cy_IPC_Pipe_Init(&userPipeConfig);
|
||||
|
||||
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
||||
}
|
||||
|
||||
//! Interrupt service routine for the user pipe.
|
||||
void IPC_UserPipeISR(void)
|
||||
{
|
||||
Cy_IPC_Pipe_ExecuteCallback(IPC_EP_USRPIPE_ADDR);
|
||||
}
|
||||
|
49
2020TPCAppNoDFU.cydsn/COMM/COMM_IPC_Messages.h
Normal file
49
2020TPCAppNoDFU.cydsn/COMM/COMM_IPC_Messages.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
/** \file
|
||||
* \brief This file contains definitions and prototypes for messaging using inter-processor
|
||||
* communication (IPC).
|
||||
*/
|
||||
|
||||
#ifndef COMM_IPC_MESSAGES_H
|
||||
#define COMM_IPC_MESSAGES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
//! This is not an actual message. Upon receipt, do nothing.
|
||||
COMM_SMM_DefaultNoMessage = 0,
|
||||
//! Reboot the system immediately upon receipt of this message (Data is "don't care").
|
||||
COMM_SMM_RebootImmediately,
|
||||
//! This is not an actual message. Upon receipt, do nothing.
|
||||
COMM_SMM_NoMessage = 0xFFFFFFFF,
|
||||
} COMM_IPCMessageID_T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//! The client ID number is the index into the callback array.
|
||||
uint32_t ClientID;
|
||||
//! The message ID represents the meaning of the message being sent.
|
||||
COMM_IPCMessageID_T MessageID;
|
||||
//! The contents of Data are different for each message ID. See #COMM_IPCMessageID_T for more details.
|
||||
void * Data;
|
||||
} COMM_IPCMessage_T;
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
void COMM_InitIPCMessages(void);
|
||||
bool COMM_SendMessageToOtherCore(COMM_IPCMessageID_T message_ID, void * message_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_IPC_MESSAGES_H
|
48
2020TPCAppNoDFU.cydsn/COMM/COMM_Util.c
Normal file
48
2020TPCAppNoDFU.cydsn/COMM/COMM_Util.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/** \file
|
||||
* \brief This file implements utility functions used by the communications package.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup CONSOLE
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
static char8 uint64_buffer[20+1];
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
//! Converts a UInt64 to a NULL-terminated string.
|
||||
/*!
|
||||
* This function is necessary because newlib-nano does not support "%llu" / #PRIu64.
|
||||
* \see https://answers.launchpad.net/gcc-arm-embedded/+question/257014
|
||||
*
|
||||
* \note This function is not reentrant!
|
||||
*
|
||||
* \param value pointer to the digital input object.
|
||||
* \return pointer to a NULL-terminated string containing the base-10 textual representation of #value.
|
||||
*/
|
||||
char8 * COMM_UInt64ToDecimal(uint64_t value)
|
||||
{
|
||||
char8 * p = uint64_buffer + sizeof(uint64_buffer);
|
||||
*(--p) = 0x00;
|
||||
|
||||
for (bool first_time = true; value || first_time; first_time = false)
|
||||
{
|
||||
const uint32_t digit = value % 10;
|
||||
const char c = '0' + digit;
|
||||
*(--p) = c;
|
||||
value = value / 10;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Private Functions */
|
27
2020TPCAppNoDFU.cydsn/COMM/COMM_Util.h
Normal file
27
2020TPCAppNoDFU.cydsn/COMM/COMM_Util.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/** \file
|
||||
* \brief Utility functions used by the communications package.
|
||||
*
|
||||
* \note As always, <project.h> and <RTOS.h> should be included <I>before</I> this file.
|
||||
*/
|
||||
|
||||
#ifndef COMM_UTIL_H
|
||||
#define COMM_UTIL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
char8 * COMM_UInt64ToDecimal(uint64_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_UTIL_H
|
|
@ -0,0 +1,78 @@
|
|||
/** \file
|
||||
* \brief This file defines the serial console commands for the Bluetooth Low Energy subsystem.
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED) && (CONFIG__FEATURE_BLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
//! Console command handler for subcommands of the 'ble' command.
|
||||
COMM_Console_Command_Result_T COMM_HandleBLECommand(char8 * data, uint32_t size)
|
||||
{
|
||||
// data[0] through data[3] is 'ble '.
|
||||
|
||||
if (data[4] == '?')
|
||||
{
|
||||
COMM_Console_Print_String("ble ? Display this help.\n");
|
||||
COMM_Console_Print_String("ble cmd <id> Inject the BLE command with ID <id>.\n");
|
||||
}
|
||||
else if ( (data[4] == 'c') &&
|
||||
(data[5] == 'm') &&
|
||||
(data[6] == 'd') )
|
||||
|
||||
{
|
||||
if (COMM_Console_IsEndOfMessage(data[7]))
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: missing BLE command ID!\n");
|
||||
}
|
||||
else if (data[7] == ' ')
|
||||
{
|
||||
uint16_t id = 0;
|
||||
|
||||
if (COMM_Console_DecodeParameterUInt16(&(data[8]), &id) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
if ((id > COMM_BLE_COMMAND_NO_OP) && (id < COMM_BLE_COMMAND_IS_OUT_OF_RANGE))
|
||||
{
|
||||
COMM_BLE_Command_T command = {.ID = id, .Data = (void *)0x00};
|
||||
xQueueSend(COMM_BLE_CommandQueue, &command, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: specified BLE command ID (");
|
||||
COMM_Console_Print_UInt16(id);
|
||||
COMM_Console_Print_String(") is invalid!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: could not comprehend BLE command ID!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Unknown BLE command!\n");
|
||||
}
|
||||
|
||||
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED) && (CONFIG__FEATURE_BLE == CONFIG__FEATURE_ENABLED)
|
|
@ -0,0 +1,29 @@
|
|||
/** \file
|
||||
* \brief This file declares the serial console commands for the Bluetooth Low Energy subsystem.
|
||||
*/
|
||||
|
||||
#ifndef COMM_BLE_CONSOLECOMMANDS_H
|
||||
#define COMM_BLE_CONSOLECOMMANDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
COMM_Console_Command_Result_T COMM_HandleBLECommand(char8 * data, uint32_t size);
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_BLE_CONSOLECOMMANDS_H
|
|
@ -0,0 +1,72 @@
|
|||
/** \file
|
||||
* \brief This file defines the serial console commands for this CPU.
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
static COMM_Console_Command_Result_T HandleConsoleHelp(char8 * data, uint32_t size);
|
||||
static COMM_Console_Command_Result_T HandleConsoleComment(char8 * data, uint32_t size);
|
||||
static COMM_Console_Command_Result_T HandleConsoleUptime(char8 * data, uint32_t size);
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
const COMM_Console_Command_Table_Entry_T COMM_Console_Command_Table[] =
|
||||
{
|
||||
{"?", " Show this help.", HandleConsoleHelp},
|
||||
{"#", " Comment (Do not omit the space after the #.)", HandleConsoleComment},
|
||||
{"event", " Generate an event in the high-level state machine (\'event ?\' for help).", COMM_HandleEventCommand},
|
||||
{"ble", " Interact with the Bluetooth Low Energy subsystem (try \'ble ?\').", COMM_HandleBLECommand},
|
||||
{"up", " Display uptime.", HandleConsoleUptime},
|
||||
{"cpu (r)", " Display CPU usage ('r' to reset maximum).", COMM_RTOS_HandleConsoleCPU},
|
||||
{"stack", " Display stack usage.", COMM_RTOS_HandleConsoleStack},
|
||||
{"version", " Display RTOS version.", COMM_RTOS_HandleConsoleVersion},
|
||||
{"reboot", " Performs a software reset on both cores.", COMM_RTOS_HandleConsoleReboot},
|
||||
{"nvm", " Interact with the Nonvolatile Memory (try \'nvm ?\').", COMM_NVM_HandleConsoleNVMCommand},
|
||||
};
|
||||
|
||||
//! Size of the #COMM_Console_Command_Table array (i.e. the number of console commands).
|
||||
const uint_fast16_t COMM_N_CONSOLE_COMMANDS = (uint_fast16_t) (sizeof(COMM_Console_Command_Table) / sizeof(COMM_Console_Command_Table_Entry_T));
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
static COMM_Console_Command_Result_T HandleConsoleHelp(char8 * data, uint32_t size)
|
||||
{
|
||||
for (uint_fast16_t i = 0; i < COMM_N_CONSOLE_COMMANDS; i++)
|
||||
{
|
||||
COMM_Console_Print_String(COMM_Console_Command_Table[i].Command_Name);
|
||||
COMM_Console_Print_String(" ");
|
||||
COMM_Console_Print_String(COMM_Console_Command_Table[i].Help);
|
||||
COMM_Console_Print_String("\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static COMM_Console_Command_Result_T HandleConsoleComment(char8 * data, uint32_t size)
|
||||
{
|
||||
COMM_Console_Print_String("Comment.\n");
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static COMM_Console_Command_Result_T HandleConsoleUptime(char8 * data, uint32_t size)
|
||||
{
|
||||
#if (configTICK_RATE_HZ != 1000)
|
||||
#error This code assumes configTICK_RATE_HZ is set to 1000 (== 1ms ticks)!
|
||||
#endif // (configTICK_RATE_HZ != 1000)
|
||||
COMM_Console_Print_String("Up ");
|
||||
COMM_Console_Print_UInt32(xTaskGetTickCount());
|
||||
COMM_Console_Print_String(" milliseconds.\n");
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
|
@ -0,0 +1,30 @@
|
|||
/** \file
|
||||
* \brief This file configures the serial console commands on this CPU.
|
||||
*/
|
||||
|
||||
#ifndef COMM_CONSOLECOMMANDS_H
|
||||
#define COMM_CONSOLECOMMANDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
extern const COMM_Console_Command_Table_Entry_T COMM_Console_Command_Table[];
|
||||
extern const uint_fast16_t COMM_N_CONSOLE_COMMANDS;
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_CONSOLECOMMANDS_H
|
|
@ -0,0 +1,207 @@
|
|||
/** \file
|
||||
* \brief This file defines the serial console commands for the Nonvolatile Memory.
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
//! Console command handler for subcommands of the 'nvm' command.
|
||||
COMM_Console_Command_Result_T COMM_NVM_HandleConsoleNVMCommand(char8 * data, uint32_t size)
|
||||
{
|
||||
// data[0] through data[3] is 'nvm '.
|
||||
if (data[4] == '?')
|
||||
{
|
||||
COMM_Console_Print_String("nvm ? Display this help.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("nvm dump Display the entire Nonvolatile Memory.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("nvm names Display the NVM parameter names.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("nvm get <parameter> Display an individual parameter from NVM.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("nvm set <parameter> <value> Assign a value to an individual parameter in NVM (be careful!).\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
else if ((data[4] == 'd') && (data[5] == 'u') && (data[6] == 'm') && (data[7] == 'p'))
|
||||
{
|
||||
for (uint8_t i = 0; i < NVM_N_ONCHIP_EEPROM_ENTRIES; i++)
|
||||
{
|
||||
COMM_Console_Print_String("NVM[");
|
||||
COMM_Console_Print_UInt16(i);
|
||||
COMM_Console_Print_String("]: ");
|
||||
|
||||
for (uint8_t j = 0; j < NVM_OnChipEEPROMEntries[i]->Size; j++)
|
||||
{
|
||||
char8 buffer[3];
|
||||
|
||||
COMM_Console_ByteToHex(buffer, *(NVM_OnChipEEPROMEntries[i]->Value + j));
|
||||
COMM_Console_Print_String("0x");
|
||||
COMM_Console_Print_String(buffer);
|
||||
COMM_Console_Print_String(" ");
|
||||
}
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
}
|
||||
else if ((data[4] == 'n') && (data[5] == 'a') && (data[6] == 'm') && (data[7] == 'e') && (data[8] == 's'))
|
||||
{
|
||||
COMM_Console_Print_String("Valid NVM parameters:\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String(" test_1\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String(" test_2\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String(" volume\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
else if ((data[4] == 'g') && (data[5] == 'e') && (data[6] == 't') && (data[7] == ' '))
|
||||
{
|
||||
if (strncmp(&data[8], "volume", 6) == 0)
|
||||
{
|
||||
COMM_Console_Print_String("Volume: ");
|
||||
COMM_Console_Print_UInt8(NVM_VOLUME);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else if (strncmp(&data[8], "test_1", 6) == 0)
|
||||
{
|
||||
COMM_Console_Print_String("Test 1: ");
|
||||
COMM_Console_Print_UInt16(NVM_ONCHIP_TEST_1);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else if (strncmp(&data[8], "test_2", 6) == 0)
|
||||
{
|
||||
COMM_Console_Print_String("Test 2: ");
|
||||
COMM_Console_Print_UInt32(NVM_ONCHIP_TEST_2);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else if (strncmp(&data[8], "test_3", 6) == 0)
|
||||
{
|
||||
COMM_Console_Print_String("Test 3: ");
|
||||
COMM_Console_Print_UInt16(NVM_EXTERNAL_TEST_3);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else if (strncmp(&data[8], "test_4", 6) == 0)
|
||||
{
|
||||
COMM_Console_Print_String("Test 4: ");
|
||||
COMM_Console_Print_UInt32(NVM_EXTERNAL_TEST_4);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Unknown NVM parameter!\n");
|
||||
}
|
||||
}
|
||||
else if ((data[4] == 's') && (data[5] == 'e') && (data[6] == 't') && (data[7] == ' '))
|
||||
{
|
||||
if (strncmp(&data[8], "volume", 6) == 0)
|
||||
{
|
||||
uint8_t volume = 0;
|
||||
if (COMM_Console_DecodeParameterUInt8(&(data[15]), &volume) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
NVM_VOLUME = volume;
|
||||
NVM_SaveExternalEEPROMEntry(NVM_VOLUME_ENTRY_PTR);
|
||||
|
||||
COMM_Console_Print_String("Volume changed to ");
|
||||
COMM_Console_Print_UInt8(NVM_VOLUME);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
|
||||
}
|
||||
}
|
||||
else if (strncmp(&data[8], "test_1", 6) == 0)
|
||||
{
|
||||
uint16_t test_value = 0;
|
||||
if (COMM_Console_DecodeParameterUInt16(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
NVM_ONCHIP_TEST_1 = test_value;
|
||||
NVM_SaveOnChipEEPROMEntry(NVM_ONCHIP_TEST_1_ENTRY_PTR);
|
||||
|
||||
COMM_Console_Print_String("Test 1 value changed to ");
|
||||
COMM_Console_Print_UInt16(NVM_ONCHIP_TEST_1);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
|
||||
}
|
||||
}
|
||||
else if (strncmp(&data[8], "test_2", 6) == 0)
|
||||
{
|
||||
uint32_t test_value = 0;
|
||||
if (COMM_Console_DecodeParameterUInt32(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
NVM_ONCHIP_TEST_2 = test_value;
|
||||
NVM_SaveOnChipEEPROMEntry(NVM_ONCHIP_TEST_2_ENTRY_PTR);
|
||||
|
||||
COMM_Console_Print_String("Test 2 value changed to ");
|
||||
COMM_Console_Print_UInt32(NVM_ONCHIP_TEST_2);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
|
||||
}
|
||||
}
|
||||
else if (strncmp(&data[8], "test_3", 6) == 0)
|
||||
{
|
||||
uint16_t test_value = 0;
|
||||
if (COMM_Console_DecodeParameterUInt16(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
NVM_EXTERNAL_TEST_3 = test_value;
|
||||
NVM_SaveExternalEEPROMEntry(NVM_EXTERNAL_TEST_3_ENTRY_PTR);
|
||||
|
||||
COMM_Console_Print_String("Test 3 value changed to ");
|
||||
COMM_Console_Print_UInt16(NVM_EXTERNAL_TEST_3);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
|
||||
}
|
||||
}
|
||||
else if (strncmp(&data[8], "test_4", 6) == 0)
|
||||
{
|
||||
uint32_t test_value = 0;
|
||||
if (COMM_Console_DecodeParameterUInt32(&(data[15]), &test_value) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
NVM_EXTERNAL_TEST_4 = test_value;
|
||||
NVM_SaveExternalEEPROMEntry(NVM_EXTERNAL_TEST_4_ENTRY_PTR);
|
||||
|
||||
COMM_Console_Print_String("Test 4 value changed to ");
|
||||
COMM_Console_Print_UInt32(NVM_EXTERNAL_TEST_4);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Parameter value unrecognized or missing!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Unknown NVM parameter!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Unknown NVM command!\n");
|
||||
}
|
||||
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
|
@ -0,0 +1,29 @@
|
|||
/** \file
|
||||
* \brief This file declares the serial console commands for the Nonvolatile Memory.
|
||||
*/
|
||||
|
||||
#ifndef COMM_NVM_CONSOLECOMMANDS_H
|
||||
#define COMM_NVM_CONSOLECOMMANDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
COMM_Console_Command_Result_T COMM_NVM_HandleConsoleNVMCommand(char8 * data, uint32_t size);
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_NVM_CONSOLECOMMANDS_H
|
|
@ -0,0 +1,109 @@
|
|||
/** \file
|
||||
* \brief This file defines the serial console commands for the RTOS package.
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleVersion(char8 * data, uint32_t size)
|
||||
{
|
||||
COMM_Console_Print_String("PSoC 6 running FreeRTOS ");
|
||||
|
||||
COMM_Console_Print_String(tskKERNEL_VERSION_NUMBER);
|
||||
|
||||
#ifdef NDEBUG
|
||||
COMM_Console_Print_String(" (Release, compiled ");
|
||||
#else
|
||||
COMM_Console_Print_String(" (Debug, compiled ");
|
||||
#endif // NDEBUG
|
||||
|
||||
COMM_Console_Print_String(__DATE__);
|
||||
COMM_Console_Print_String(" ");
|
||||
COMM_Console_Print_String(__TIME__);
|
||||
COMM_Console_Print_String(").\n");
|
||||
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleStack(char8 * data, uint32_t size)
|
||||
{
|
||||
for (uint_fast8_t i = 0; i < CONFIG_N_TASK_HANDLES; i++)
|
||||
{
|
||||
TaskStatus_t status;
|
||||
vTaskGetInfo(*CONFIG_TaskHandles[i], &status, pdTRUE, eInvalid);
|
||||
COMM_Console_Print_String(status.pcTaskName);
|
||||
COMM_Console_Print_String(": ");
|
||||
COMM_Console_Print_UInt16(status.usStackHighWaterMark);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
|
||||
// Repeat for the Idle Task.
|
||||
{
|
||||
TaskStatus_t status;
|
||||
vTaskGetInfo(xTaskGetIdleTaskHandle(), &status, pdTRUE, eInvalid);
|
||||
COMM_Console_Print_String(status.pcTaskName);
|
||||
COMM_Console_Print_String(": ");
|
||||
COMM_Console_Print_UInt16(status.usStackHighWaterMark);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleCPU(char8 * data, uint32_t size)
|
||||
{
|
||||
// data[0] through data[3] is 'cpu '.
|
||||
if (data[4] == 'r')
|
||||
{
|
||||
//COMM_Console_Print_String("Max CPU reset.\n");
|
||||
COMM_Console_Print_String("(Not yet implemented.)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint_fast8_t i = 0; i < CONFIG_N_TASK_HANDLES; i++)
|
||||
{
|
||||
TaskStatus_t status;
|
||||
vTaskGetInfo(*CONFIG_TaskHandles[i], &status, pdTRUE, eInvalid);
|
||||
COMM_Console_Print_String(status.pcTaskName);
|
||||
COMM_Console_Print_String(": ");
|
||||
COMM_Console_Print_UInt32(status.ulRunTimeCounter);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
|
||||
// Repeat for the Idle Task.
|
||||
{
|
||||
TaskStatus_t status;
|
||||
vTaskGetInfo(xTaskGetIdleTaskHandle(), &status, pdTRUE, eInvalid);
|
||||
COMM_Console_Print_String(status.pcTaskName);
|
||||
COMM_Console_Print_String(": ");
|
||||
COMM_Console_Print_UInt16(status.ulRunTimeCounter);
|
||||
COMM_Console_Print_String("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleReboot(char8 * data, uint32_t size)
|
||||
{
|
||||
(void) COMM_SendMessageToOtherCore(COMM_SMM_RebootImmediately, NULL);
|
||||
|
||||
// Not that it matters...
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
|
@ -0,0 +1,32 @@
|
|||
/** \file
|
||||
* \brief This file declares the serial console commands for the RTOS package.
|
||||
*/
|
||||
|
||||
#ifndef COMM_RTOS_CONSOLECOMMANDS_H
|
||||
#define COMM_RTOS_CONSOLECOMMANDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleVersion(char8 * data, uint32_t size);
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleStack(char8 * data, uint32_t size);
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleCPU(char8 * data, uint32_t size);
|
||||
COMM_Console_Command_Result_T COMM_RTOS_HandleConsoleReboot(char8 * data, uint32_t size);
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_RTOS_CONSOLECOMMANDS_H
|
|
@ -0,0 +1,189 @@
|
|||
/** \file
|
||||
* \brief This file defines the serial console commands for the high-level state machine.
|
||||
*/
|
||||
|
||||
/* Include Files */
|
||||
#include "KTag.h"
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Local Definitions and Constants */
|
||||
|
||||
/* Private Function Prototypes */
|
||||
static void Simulate_Hit(uint8_t team_ID, uint16_t damage);
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Private Variables */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
//! Console command handler for the 'event' command.
|
||||
COMM_Console_Command_Result_T COMM_HandleEventCommand(char8 * data, uint32_t size)
|
||||
{
|
||||
// data[0] through data[5] is 'event '.
|
||||
|
||||
if (data[6] == '?')
|
||||
{
|
||||
COMM_Console_Print_String("event ? Display this help.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("event raw <id> Inject the event with ID <id>.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("event tag <n> Send <n> tag(s).\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
COMM_Console_Print_String("event hit <t> <d> Simulate a hit from team <t> for <d> damage.\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
else if ( (data[6] == 'r') &&
|
||||
(data[7] == 'a') &&
|
||||
(data[8] == 'w') )
|
||||
|
||||
{
|
||||
if (COMM_Console_IsEndOfMessage(data[9]))
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: missing event ID!\n");
|
||||
}
|
||||
else if (data[9] == ' ')
|
||||
{
|
||||
uint16_t id = 0;
|
||||
|
||||
if (COMM_Console_DecodeParameterUInt16(&(data[10]), &id) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
if ((id > KEVENT_NO_EVENT) && (id < KEVENT_IS_OUT_OF_RANGE))
|
||||
{
|
||||
KEvent_T raw_event = { .ID = id, .Data = (void *)0x00 };
|
||||
Post_KEvent(&raw_event);
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: specified event ID (");
|
||||
COMM_Console_Print_UInt16(id);
|
||||
COMM_Console_Print_String(") is invalid!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: could not comprehend event ID!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
|
||||
}
|
||||
}
|
||||
else if ( (data[6] == 't') &&
|
||||
(data[7] == 'a') &&
|
||||
(data[8] == 'g') )
|
||||
|
||||
{
|
||||
if (COMM_Console_IsEndOfMessage(data[9]))
|
||||
{
|
||||
if (Send_Tag() == SYSTEMK_RESULT_SUCCESS)
|
||||
{
|
||||
COMM_Console_Print_String("Tag sent.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("Error: Couldn't send tag!\n");
|
||||
}
|
||||
}
|
||||
else if (data[9] == ' ')
|
||||
{
|
||||
uint16_t times = 0;
|
||||
|
||||
if (COMM_Console_DecodeParameterUInt16(&(data[10]), ×) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
while (times > 0)
|
||||
{
|
||||
if (Send_Tag() == SYSTEMK_RESULT_SUCCESS)
|
||||
{
|
||||
COMM_Console_Print_String("Tag sent.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("Error: Couldn't send tag!\n");
|
||||
}
|
||||
//! \todo Why can't the console command 'event tag <n>' send tags faster than once per second?
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
times--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: could not comprehend tag repetitions!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
|
||||
}
|
||||
}
|
||||
else if ( (data[6] == 'h') &&
|
||||
(data[7] == 'i') &&
|
||||
(data[8] == 't') )
|
||||
|
||||
{
|
||||
if (COMM_Console_IsEndOfMessage(data[9]))
|
||||
{
|
||||
Simulate_Hit(1, 10);
|
||||
COMM_Console_Print_String("Hit!\n");
|
||||
}
|
||||
else if (data[9] == ' ')
|
||||
{
|
||||
uint8_t team_ID = 0;
|
||||
uint16_t damage = 10;
|
||||
|
||||
if (COMM_Console_DecodeParameterUInt8(&(data[10]), &team_ID) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
const char * damage_location;
|
||||
|
||||
// Damage is the first parameter after team ID.
|
||||
if (COMM_Console_FindNthParameter(&(data[10]), 1, &damage_location) == COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
if (COMM_Console_DecodeParameterUInt16(damage_location, &damage) != COMM_CONSOLE_PARAMETER_RESULT_SUCCESS)
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: could not comprehend damage--using default.\n");
|
||||
damage = 10;
|
||||
}
|
||||
}
|
||||
Simulate_Hit(team_ID, damage);
|
||||
COMM_Console_Print_String("Hit!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: could not comprehend team ID!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: unrecognized or mangled command!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMM_Console_Print_String("ERROR: Unknown event command!\n");
|
||||
}
|
||||
|
||||
|
||||
return COMM_CONSOLE_CMD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
static void Simulate_Hit(uint8_t team_ID, uint16_t damage)
|
||||
{
|
||||
static DecodedPacket_T Simulated_Tag_Rx_Buffer;
|
||||
static KEvent_T tag_received_event;
|
||||
|
||||
Simulated_Tag_Rx_Buffer.Tag.type = DECODED_PACKET_TYPE_TAG_RECEIVED;
|
||||
Simulated_Tag_Rx_Buffer.Tag.protocol = LASER_X_PROTOCOL;
|
||||
Simulated_Tag_Rx_Buffer.Tag.player_ID = 0x00;
|
||||
Simulated_Tag_Rx_Buffer.Tag.team_ID = team_ID;
|
||||
Simulated_Tag_Rx_Buffer.Tag.damage = damage;
|
||||
Simulated_Tag_Rx_Buffer.Tag.color = GetColorFromTeamID(team_ID);
|
||||
tag_received_event.ID = KEVENT_TAG_RECEIVED;
|
||||
tag_received_event.Data = &Simulated_Tag_Rx_Buffer;
|
||||
Post_KEvent(&tag_received_event);
|
||||
}
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
|
@ -0,0 +1,29 @@
|
|||
/** \file
|
||||
* \brief This file declares the serial console commands for the high-level state machine.
|
||||
*/
|
||||
|
||||
#ifndef COMM_STATE_CONSOLECOMMANDS_H
|
||||
#define COMM_STATE_CONSOLECOMMANDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
/* Include Files */
|
||||
|
||||
/* Preprocessor and Type Definitions */
|
||||
|
||||
/* Public Variables */
|
||||
|
||||
/* Public Functions */
|
||||
COMM_Console_Command_Result_T COMM_HandleEventCommand(char8 * data, uint32_t size);
|
||||
|
||||
#endif // (CONFIG__FEATURE_COMM_CONSOLE == CONFIG__FEATURE_ENABLED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // COMM_STATE_CONSOLECOMMANDS_H
|
Loading…
Add table
Add a link
Reference in a new issue