This commit is contained in:
2024-07-12 15:19:46 +08:00
commit 7ca1af130d
895 changed files with 282694 additions and 0 deletions
+402
View File
@@ -0,0 +1,402 @@
/**
****************************************************************************************
*
* @file aes.h
*
* @brief Header file for AES crypto module
*
* Copyright (C) RivieraWaves 2017-2018
*
****************************************************************************************
*/
#ifndef AES_H_
#define AES_H_
/**
****************************************************************************************
* @defgroup AES Crypto module
* @ingroup ROOT
* @brief AES Crypto module
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h"
#include "co_bt.h" // Common defines
/*
* Defines
****************************************************************************************
*/
/// Size of an a AES Message block in bytes
#define AES_BLOCK_SIZE 16
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Call back definition of the function that can handle result of an AES based algorithm
*
* @param[in] status Execution status
* @param[in] aes_res 16 bytes block result
* @param[in] src_info Information provided by requester
****************************************************************************************
*/
typedef void (*aes_func_result_cb) (uint8_t status, const uint8_t* aes_res, uint32_t src_info);
/**
****************************************************************************************
* @brief Call back definition of the function that can handle result of AES-CCM Cipher/Decipher
*
* @param[in] mic_error True if a MIC error detected when Decipher, False else
* In case of MIC error output message is considered invalid
* @param[in] src_info Information provided by requester
****************************************************************************************
*/
typedef void (*aes_ccm_func_result_cb) (bool mic_error, uint32_t src_info);
#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/**
****************************************************************************************
* @brief Call back definition of the Resolvable Private Address resolution function
*
* @param[in] index Index of the IRK used to resolve the provided RPA (number of IRK if not resolved)
* @param[in] src_info Information provided by requester
****************************************************************************************
*/
typedef void (*aes_rpa_func_result_cb) (uint8_t index, uint32_t src_info);
#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize AES function management
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
****************************************************************************************
*/
void aes_init(uint8_t init_type);
/**
****************************************************************************************
* @brief Handler of AES execution (HW accelerator if BLE controller present, HCI Encrypt for BLE Host Stack)
*
* @param[in] status Status of AES execution
* @param[in] result 16 bytes result of AES execution
****************************************************************************************
*/
void aes_result_handler(uint8_t status, uint8_t* result);
/**
****************************************************************************************
* @brief Perform an AES encryption - result within callback
* @param[in] key Key used for the encryption
* @param[in] val Value to encrypt using AES
* @param[in] copy Copy parameters because source is destroyed
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_encrypt(const uint8_t* key, const uint8_t *val, bool copy, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Generate a random number using AES encryption - result within callback
*
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_rand(aes_func_result_cb res_cb, uint32_t src_info);
#if (BLE_HOST_PRESENT)
/**
****************************************************************************************
* @brief Compute Confirm value
*
* @param[in] k Key used for aes functions
* @param[in] r Random number
* @param[in] p1 p1 = pres || preq || rat || iat
* @param[in] p2 p2 = padding || ia || ra
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_c1(const uint8_t* k, const uint8_t* r, const uint8_t* p1, const uint8_t* p2,
aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Compute LE Secure Connections Confirm Value Generation Function f4
*
* @param[in] u U is 256 bits
* @param[in] v V is 256 bits
* @param[in] x X is 128 bits
* @param[in] z Z is 8 bits
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_f4(const uint8_t* u, const uint8_t* v, const uint8_t* x, uint8_t z,
aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Compute LE Secure Connections Key Generation Function f5
*
* @param[in] w W is 256 bits
* @param[in] n1 N1 is 128 bits
* @param[in] n2 N2 is 128 bits
* @param[in] a1 A1 is 56 bits
* @param[in] a2 A2 is 56 bits
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_f5(const uint8_t* w, const uint8_t* n1, const uint8_t* n2, const uint8_t* a1, const uint8_t* a2,
aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Compute LE Secure Connections Check Value Generation Function f6
*
* @param[in] w W is 128 bits
* @param[in] n1 N1 is 128 bits
* @param[in] n2 N2 is 128 bits
* @param[in] r R is 128 bits
* @param[in] iocap IOcap is 24 bits
* @param[in] a1 A1 is 56 bits
* @param[in] a2 A2 is 56 bits
*
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_f6(const uint8_t* w, const uint8_t* n1, const uint8_t* n2, const uint8_t* r, const uint8_t* iocap,
const uint8_t* a1, const uint8_t* a2, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Compute LE Secure Connections Numeric Comparison Value Generation Function g2
*
* @param[in] u U is 256 bits
* @param[in] v V is 256 bits
* @param[in] x X is 128 bits
* @param[in] y Y is 128 bits
*
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_g2(const uint8_t* u, const uint8_t* v, const uint8_t* x, const uint8_t* y,
aes_func_result_cb res_cb, uint32_t src_info);
#endif // (BLE_HOST_PRESENT)
#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/**
****************************************************************************************
* @brief Start the AES CMAC crypto function. Allocate memory for the CMAC and
* begins the subkey generation
*
* @param[in] key Pointer to the Key to be used
* @param[in] message Pointer to the block of data the data on which the CMAC is performed
* @param[in] message_len Length (in bytes) of the block of data M
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_cmac(const uint8_t* key, const uint8_t* message, uint16_t message_len,
aes_func_result_cb res_cb, uint32_t src_info);
#if (BLE_MESH)
/**
****************************************************************************************
* @brief Start the AES S1 crypto function.
*
* @param[in] message Message used to generate Salted key
* @param[in] message_len Length (in bytes) of the block of data M
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_s1(const uint8_t* message, uint8_t message_len, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Start the AES K1 crypto function.
*
* @param[in] salt Salted Key to use
* @param[in] n Value of N
* @param[in] n_len Length of N
* @param[in] p Value of P
* @param[in] p_len Length of P
* @param[in] res_cb Function that will handle the AES based result (16 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_k1(const uint8_t* salt, const uint8_t* n, uint8_t n_len, const uint8_t* p, uint8_t p_len,
aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Start the AES K2 crypto function.
*
* @param[in] n Value of N - 128 bits
* @param[in] p Value of P
* @param[in] p_len Length of P
* @param[in] res_cb Function that will handle the AES based result (33 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_k2(const uint8_t* n, const uint8_t* p, uint8_t p_len, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Start the AES K3 crypto function.
*
* @param[in] n Value of N - 128 bits
* @param[in] res_cb Function that will handle the AES based result (8 bytes)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_k3(const uint8_t* n, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Start the AES K4 crypto function.
*
* @param[in] n Value of N - 128 bits
* @param[in] res_cb Function that will handle the AES based result (1 byte)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_k4(const uint8_t* n, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Start the AES CCM crypto function. Allocate memory for the CCM and start processing it
* Execute result callback at end of function execution
*
* @param[in] key Pointer to the Key to be used
* @param[in] nonce 13 Bytes Nonce to use for cipher/decipher
* @param[in] in_message Input message for AES-CCM exectuion
* @param[out] out_message Output message that will contain cipher+mic or decipher data
* @param[in] message_len Length of Input/Output message without mic
* @param[in] mic_len Length of the mic to use (2, 4, 6, 8, 10, 12, 14, 16 valid)
* @param[in] cipher True to encrypt message, False to decrypt it.
* @param[in] add_auth_data Additional Authentication data used for computation of MIC
* @param[in] add_auth_data_len Length of Additional Authentication data
* @param[in] res_cb Function that will handle the AES CCM result
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_ccm(const uint8_t* key, const uint8_t* nonce, const uint8_t* in_message,
uint8_t* out_message, uint16_t message_len, uint8_t mic_len, bool cipher,
const uint8_t* add_auth_data, uint8_t add_auth_data_len, aes_ccm_func_result_cb res_cb, uint32_t src_info);
#endif // (BLE_MESH)
/**
****************************************************************************************
* @brief Key Conversion Function h6
*
* @param[in] w W is a 128bits data
* @param[in] keyId KeyID is a 32 bits data
* @param[in] res_cb Function that will handle the AES CCM result
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_h6(const uint8_t* w, const uint8_t* key_id, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Key Conversion Function h7
*
* @param[in] salt SALT is a 128bits data
* @param[in] w W is a 128bits key
* @param[in] res_cb Function that will handle the AES CCM result
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_h7(const uint8_t* salt, const uint8_t* w, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Group Session Key Derivation Function h8
*
* @param[in] k K is a 128bits data
* @param[in] s S is a 128bits key
* @param[in] keyId KeyID is a 32 bits data
* @param[in] res_cb Function that will handle the AES CCM result
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_h8(const uint8_t* k, const uint8_t* s, const uint8_t* key_id, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Group Long Term Key Generation Function h9
*
* @param[in] w W is a 128bits data
* @param[in] keyId KeyID is a 32 bits data
* @param[in] res_cb Function that will handle the AES CCM result
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_h9(const uint8_t* w, const uint8_t* key_id, aes_func_result_cb res_cb, uint32_t src_info);
#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/**
****************************************************************************************
* @brief Resolvable Private Address generation Function
*
* @param[in] irk Pointer to IRK (local IRK to generate a local RPA)
* @param[in] res_cb Function that will handle the AES RPA generation result (address generated in the 6 LSBs of the returned buffer)
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_rpa_gen(struct irk* irk, aes_func_result_cb res_cb, uint32_t src_info);
/**
****************************************************************************************
* @brief Resolvable Private Address resolution Function
*
* @param[in] nb_irk Number of IRKs provided
* @param[in] irk Table of IRKs (stored internally to AES RPA, caller can destroy the table)
* @param[in] addr BD address to resolve
* @param[in] res_cb Function that will handle the AES RPA resolution result
* @param[in] src_info Information used retrieve requester
****************************************************************************************
*/
void aes_rpa_resolve(uint8_t nb_irk, struct irk* irk, struct bd_addr* addr, aes_rpa_func_result_cb res_cb, uint32_t src_info);
#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/// @} AES
///
#endif /* AES_H_ */
+197
View File
@@ -0,0 +1,197 @@
/**
****************************************************************************************
*
* @file aes_int.h
*
* @brief Header file for AES Internal crypto module
*
* Copyright (C) RivieraWaves 2017-2018
*
****************************************************************************************
*/
#ifndef AES_INT_H_
#define AES_INT_H_
/**
****************************************************************************************
* @defgroup AES_INT
* @ingroup AES
* @brief AES_INT Crypto internal definitions
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h"
#include "aes.h"
#include "co_bt.h" // Common defines
#include "co_list.h" // List usage
/*
* Defines
****************************************************************************************
*/
// Size of an a AES Message block in bytes
#define AES_BLOCK_SIZE 16
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
struct aes_func_env;
/**
****************************************************************************************
* Callback used to continue execution of the AES based function.
*
* @param[in] aes_result Result of the AES (aes(key , val))
*
* @return True if function execution is over
****************************************************************************************
*/
typedef bool (*aes_func_continue_cb) (struct aes_func_env* aes_env, uint8_t* aes_result);
/// Environment variable required for an AES based function
/// This structure must be Header of all function environment variables
struct aes_func_env
{
/// used to put AES function in the AES execution queue
struct co_list_hdr hdr;
/// AES continue callback
aes_func_continue_cb aes_continue_cb;
/// AES End callback
aes_func_result_cb aes_res_cb;
/// Key to use for the AES execution
const uint8_t* key;
/// Value to use for AES Cypher/Decypher
const uint8_t* val;
/// Information put in source id message to retrieve requester
uint32_t src_info;
};
#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
// Structure definition of the AES CMAC algorithm
struct aes_cmac_env
{
/// AES Environment structure
struct aes_func_env aes_env;
/// M: Pointer to the message to be authenticated
const uint8_t* message; // pointer to memory allocated by calling function
/// K: authentication key
const uint8_t* auth_key;
/// T: message authentication code
uint8_t auth_code[AES_BLOCK_SIZE];
/// Length of the message
uint16_t message_len;
/// Number of blocks (1 block = 16 bytes)
uint8_t num_blocks;
/// Current block to process
uint8_t cur_block;
};
#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/*
* GLOBAL VARIABLE DECLARATIONS
****************************************************************************************
*/
/// zero block
extern const uint8_t aes_cmac_zero[AES_BLOCK_SIZE];
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Allocate environment for the AES based function execution
*
* @param[in] size Size of the environment to allocate (must be >= sizeof(struct aes_func_env))
* @param[in] aes_continue_cb Callback used to send the AES result
* @param[in] res_cb Function that will handle end of AES Based algorithm
* @param[in] src_info Information used to retrieve requester
*
* @return Allocated environment variable
****************************************************************************************
*/
struct aes_func_env* aes_alloc(uint16_t size, aes_func_continue_cb aes_continue_cb, aes_func_result_cb res_cb,
uint32_t src_info);
/**
****************************************************************************************
* @brief AES Cypher request function.
*
* This will queue AES request in the AES execution queue
* When the AES result is received, the AES continue callback is executed.
*
* If AES continue function returns that AES execution is over, a message will be send to destination task
* with latest AES result.
*
* @param[in] env AES environment
* @param[in] key Key used for cyphering
* @param[in] val Value to cypher
****************************************************************************************
*/
void aes_start(struct aes_func_env* env, const uint8_t* key, const uint8_t *val);
#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/**
****************************************************************************************
* @brief Start the AES CMAC crypto function. Allocate memory for the CMAC and
* begins the subkey generation
*
* @param[in] enc AES CMAC Environment
* @param[in] key Pointer to the Key to be used
* @param[in] message Pointer to the block of data the data on which the CMAC is performed
* @param[in] message_len Length (in bytes) of the block of data M
****************************************************************************************
*/
void aes_cmac_start(struct aes_cmac_env* env, const uint8_t* key, const uint8_t* message, uint16_t message_len);
/**
****************************************************************************************
* @brief Continue AES CMAC algorithm
*
* @param[in] env AES CMAC Environment
* @param[in] aes_res AES Result
*
* @return True if algorithm is over, False else
****************************************************************************************
*/
bool aes_cmac_continue(struct aes_cmac_env* env, uint8_t* aes_res);
/**
* @brief Perform a XOR of two numbers.
*
* @param[out] result Output 128 bits number: result = a ^ b
* @param[in] a first 128 bits operand
* @param[in] b second 128 bits operand
* @param[in] size number of bytes to XOR
*/
void aes_xor_128(uint8_t* result, const uint8_t* a, const uint8_t* b, uint8_t size);
/**
* @brief Perform shift left of a 128 bits numvber
*
* @param[in] input Input 128 bits number
* @param[out] output Output 128 bits number: output = input << 1
*/
void aes_shift_left_128(const uint8_t* input,uint8_t* output);
#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT)
/// @} AES_INT
///
#endif /* AES_INT_H_ */
+62
View File
@@ -0,0 +1,62 @@
/**
****************************************************************************************
*
* @file co_bt.h
*
* @brief This file contains the common Bluetooth defines, enumerations and structures
* definitions for use by all modules in RW stack.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef CO_BT_H_
#define CO_BT_H_
/**
****************************************************************************************
* @addtogroup COMMON Common SW Block
* @ingroup ROOT
* @brief The Common RW SW Block.
*
* The COMMON is the block with Bluetooth definitions and structures shared
* to all the protocol stack blocks. This also contain software wide error code
* definitions, mathematical functions, help functions, list and buffer definitions.
*
* @{
****************************************************************************************
*/
/**
****************************************************************************************
* @addtogroup CO_BT Common Bluetooth defines
* @ingroup COMMON
* @brief Common Bluetooth definitions and structures.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdbool.h> // standard boolean definitions
#include <stddef.h> // standard definitions
#include <stdint.h> // standard integer definitions
/*
* DEFINES
****************************************************************************************
*/
#include "co_bt_defines.h" // Bluetooth defines
#include "co_lmp.h" // Bluetooth LMP definitions
#include "co_hci.h" // Bluetooth HCI definitions
#include "co_error.h" // Bluetooth error codes definitions
/// @} CO_BT
#endif // CO_BT_H_
File diff suppressed because it is too large Load Diff
+643
View File
@@ -0,0 +1,643 @@
/**
****************************************************************************************
*
* @file co_buf.h
*
* @brief The Common Time module provides buffer used for manipulation of data for network
* protocol that uses encapsulation of header or trailing information.
* A buffer is a contiguous memory section used to store message information including
* several protocol layers.
* Since a unique buffer can be used by multiple layers, a mechanism monitors the
* buffer life cycle. Finally, if data usage information are kept within the buffer,
* it speeds up software to retrieve the execution context.
*
*
* Copyright (C) RivieraWaves 2009-2019
*
****************************************************************************************
*/
#ifndef _CO_BUF_H_
#define _CO_BUF_H_
/**
****************************************************************************************
* @defgroup CO_BUF Utilities
* @ingroup COMMON
* @brief Time utilities
*
* This module contains the Common time utilities functions and macros.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard definitions
#include <stddef.h> // standard definitions
#include "arch.h" // Arch defines
#include "co_list.h" // List manipulation
#include "co_utils.h" // Bit Field manipulation
/*
* MACRO DEFINITIONS
****************************************************************************************
*/
/*
* ENUMERATIONS DEFINITIONS
****************************************************************************************
*/
/// size of meta-data variables 32 bytes
#define CO_BUF_META_DATA_SIZE (32 >> 2)
/// Buffer Error status codes
enum co_buf_err
{
/// No Error
CO_BUF_ERR_NO_ERROR = 0x00,
/// Invalid parameter(s)
CO_BUF_ERR_INVALID_PARAM = 0x01,
/// Not enough resources
CO_BUF_ERR_INSUFFICIENT_RESOURCE = 0x02,
/// Resource is busy, operation cannot be performed
CO_BUF_ERR_RESOURCE_BUSY = 0x03,
};
/// Buffer meta-data bit field
enum co_buf_metadata_bf
{
/// Size of meta-data data frozen. This size has a step of 4 bytes
CO_BUF_METADATA_FROZEN_SIZE_LSB = 0,
CO_BUF_METADATA_FROZEN_SIZE_MASK = 0x0F,
/// If equals 1, a callback is executed before freeing the buffer.
CO_BUF_METADATA_FREE_CB_POS = 4,
CO_BUF_METADATA_FREE_CB_BIT = 0x10,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// Buffer structure
typedef struct co_buf
{
/// List header for chaining
co_list_hdr_t hdr;
/// Length of the data part
uint16_t data_len;
/// Prefix length available
uint16_t head_len;
/// Suffix length available
uint16_t tail_len;
/// Pool identifier (@see enum co_buf_pool_id)
uint8_t pool_id;
/// Acquisition counter
uint8_t acq_cnt;
/// Meta-data variable that can be used for multiple purposes
/// meta-data is always 32 bits aligned
uint32_t metadata[CO_BUF_META_DATA_SIZE];
/// Pattern used to verify that meta-data didnt overflow
uint8_t pattern;
/// Meta-data bit field (@see enum co_buf_metadata_bf)
uint8_t metadata_bf;
/// Padding
uint16_t padding;
/// Variable buffer array that contains header, data and tail payload
/// Length is buf_len = (head_len + data_len + tail_len)
uint8_t buf[__ARRAY_EMPTY];
} co_buf_t;
/**
****************************************************************************************
* @brief This function is called when all software modules has release the buffer.
*
* @param[in] p_env Pointer to environment that will be used as callback parameter.
****************************************************************************************
*/
typedef void (*co_buf_free_cb)(co_buf_t* p_buf, void* p_env);
/*
* CONSTANT DECLARATIONS
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Allocate a buffer and specify initial length of head, data and tail parts.
* When doing a buffer allocation, acquisition counter is equals to 1.
*
* If total length is lower than @see CO_BUF_SMALL_SIZE and small buffer pool is not empty:
* A buffer will be picked from small buffer pool.
* else if total length is lower than @see CO_BUF_BIG_SIZE and big buffer pool is not empty:
* A buffer will be picked from big buffer pool.
* else:
* the buffer will be dynamically allocated.
*
* @param[out] pp_buf Pointer to a variable that will contain the address of the allocated buffer.
* @param[in] head_len Initial Head Length.
* @param[in] data_len Initial Data Length.
* @param[in] tail_len Initial Tail Length.
*
* @return CO_BUF_ERR_NO_ERROR if buffer can be allocated.
* CO_BUF_ERR_INSUFFICIENT_RESOURCE if no more buffers are available.
****************************************************************************************
*/
uint8_t co_buf_alloc(co_buf_t** pp_buf, uint16_t head_len, uint16_t data_len, uint16_t tail_len);
/**
****************************************************************************************
* @brief Prepare a buffer and specify initial length of head, data and tail parts.
*
* Buffer pointer provided must have a total length greater or equals to head_len + data_len + tail_len
* When doing a buffer allocation, acquisition counter is equals to 1.
* Buffer isnt free by @see co_buf_release function when acquisition counter is equals to 0.
*
* @param[out] p_buf Pointer to buffer to prepare.
* @param[in] head_len Initial Head Length.
* @param[in] data_len Initial Data Length.
* @param[in] tail_len Initial Tail Length.
*
* @return CO_BUF_ERR_NO_ERROR if buffer can be allocated.
****************************************************************************************
*/
// uint8_t co_buf_prepare(co_buf_t* p_buf, uint16_t head_len, uint16_t data_len, uint16_t tail_len);
/**
****************************************************************************************
* @brief Function used to increment value of acquire counter of a buffer during processing
* of buffer content.
*
* @param[in] p_buf Pointer to acquired buffer
*
* @return CO_BUF_ERR_NO_ERROR if operation succeed
****************************************************************************************
*/
uint8_t co_buf_acquire(co_buf_t *p_buf);
/**
****************************************************************************************
* @brief Function used to release previously acquired buffer. The acquire counter for
* this buffer is decremented. If the acquire counter value becomes zero,
* the buffer is freed as no more entity is using the buffer anymore.
*
* if acquire counter becomes zero
* if a free callback has been configured using @see co_buf_cb_set:
* call the free callback
*
* if buffer comes from a buffer pool:
* buffer is pushed to the corresponding pool, and available for another
* software module
*
* else if buffer comes from dynamic memory:
* corresponding memory is free
*
* else if a buffer has been initialized with @see co_buf_prepare:
* nothing is done
*
* @note A software module shall not use a buffer after releasing it.
*
* @param[in] p_buf Pointer to acquired buffer.
*
* @return CO_BUF_ERR_NO_ERROR if buffer has been released.
* CO_BUF_ERR_INVALID_PARAM if buffer was free.
****************************************************************************************
*/
uint8_t co_buf_release(co_buf_t *p_buf);
/**
****************************************************************************************
* @brief Retrieve buffer data pointer.
*
* @param[in] p_buf Pointer to buffer
*
* @return Pointer to first byte of data field ; NULL if an error occurs
****************************************************************************************
*/
__INLINE uint8_t* co_buf_data(co_buf_t *p_buf)
{
uint8_t* p_ret = NULL;
if(p_buf)
{
p_ret = &(p_buf->buf[p_buf->head_len]);
}
return (p_ret);
}
/**
****************************************************************************************
* @brief Retrieve buffer data length.
*
* @param[in] p_buf Pointer to buffer
*
* @return Buffer data field size. 0 if an error occurs.
****************************************************************************************
*/
__INLINE uint16_t co_buf_data_len(const co_buf_t *p_buf)
{
uint16_t ret = 0;
if(p_buf)
{
ret = p_buf->data_len;
}
return (ret);
}
/**
****************************************************************************************
* @brief Retrieve buffer available prefix length.
*
* @param[in] p_buf Pointer to buffer
*
* @return Buffer data prefix size available. 0 if an error occurs.
****************************************************************************************
*/
__INLINE uint16_t co_buf_head_len(const co_buf_t *p_buf)
{
uint16_t ret = 0;
if(p_buf)
{
ret = p_buf->head_len;
}
return (ret);
}
/**
****************************************************************************************
* @brief Memory Size of the buffer
*
* @param[in] p_buf Pointer to buffer
*
* @return Memory size of the buffer
****************************************************************************************
*/
uint16_t co_buf_size(const co_buf_t *p_buf);
/**
****************************************************************************************
* @brief Retrieve buffer head pointer.
*
* @param[in] p_buf Pointer to buffer
*
* @return Pointer to first byte of tail field ; NULL if an error occurs
****************************************************************************************
*/
__INLINE uint8_t* co_buf_head(co_buf_t *p_buf)
{
uint8_t* p_ret = NULL;
if(p_buf)
{
p_ret = &(p_buf->buf[0]);
}
return (p_ret);
}
/**
****************************************************************************************
* @brief Prefix the data with a given header length, it is mandatory that data reserved
* length is less or equals to header length.
* Header length is reduced according to number of byte reserved.
*
* @param[in] p_buf Pointer to buffer
* @param[in] length Length of prefix data to reserve.
*
* @return CO_BUF_ERR_NO_ERROR if needed length has been reserved.
* CO_BUF_ERR_INVALID_PARAM if provided length is higher than current length of head part.
****************************************************************************************
*/
uint8_t co_buf_head_reserve(co_buf_t *p_buf, uint16_t length);
/**
****************************************************************************************
* @brief Remove a data prefix of a specific length header length, it is mandatory that
* data released length is less or equals to data length.
* Header length is increased according to number of byte released.
*
* @param[in] p_buf Pointer to buffer
* @param[in] length Length of prefix data to release.
*
* @return CO_BUF_ERR_NO_ERROR if needed length has been released.
* CO_BUF_ERR_INVALID_PARAM if provided length is higher than current length of data part.
****************************************************************************************
*/
uint8_t co_buf_head_release(co_buf_t *p_buf, uint16_t length);
/**
****************************************************************************************
* @brief Retrieve buffer tail pointer.
*
* @param[in] p_buf Pointer to buffer
*
* @return Pointer to first byte of tail field ; NULL if an error occurs
****************************************************************************************
*/
__INLINE uint8_t* co_buf_tail(co_buf_t *p_buf)
{
uint8_t* p_ret = NULL;
if(p_buf)
{
p_ret = &(p_buf->buf[p_buf->head_len + p_buf->data_len]);
}
return (p_ret);
}
/**
****************************************************************************************
* @brief Retrieve buffer available suffix length.
*
* @param[in] p_buf Pointer to buffer
*
* @return Buffer data suffix size available. 0 if an error occurs.
****************************************************************************************
*/
__INLINE uint16_t co_buf_tail_len(const co_buf_t *p_buf)
{
uint16_t ret = 0;
if(p_buf)
{
ret = p_buf->tail_len;
}
return (ret);
}
/**
****************************************************************************************
* @brief Prefix the data with a given tail length, it is mandatory that data reserved
* length is less or equals to header length.
* Tail length is reduced according to number of byte reserved.
*
* @param[in] p_buf Pointer to buffer
* @param[in] length Length of suffix data to reserve.
*
* @return CO_BUF_ERR_NO_ERROR if needed length has been reserved.
* CO_BUF_ERR_INVALID_PARAM if provided length is higher than current length of tail part.
****************************************************************************************
*/
uint8_t co_buf_tail_reserve(co_buf_t *p_buf, uint16_t length);
/**
****************************************************************************************
* @brief Remove a data suffix of a specific length header length, it is mandatory that
* data released length is less or equals to data length.
* Tail length is increased according to number of byte released.
*
* @param[in] p_buf Pointer to buffer
* @param[in] length Length of suffix data to release.
*
* @return CO_BUF_ERR_NO_ERROR if needed length has been released.
* CO_BUF_ERR_INVALID_PARAM if provided length is higher than current length of data part.
****************************************************************************************
*/
uint8_t co_buf_tail_release(co_buf_t *p_buf, uint16_t length);
/**
****************************************************************************************
* @brief Retrieve pointer to buffer meta-data. This pointer is 32-bit aligned, and
* corresponds to buffer meta-data start pointer plus blocked meta-data length
*
* @param[in] p_buf Pointer to buffer
*
* @return Pointer to the available meta-data pointer ;NULL if an error occurs
****************************************************************************************
*/
__INLINE uint8_t* co_buf_metadata(co_buf_t *p_buf)
{
uint8_t* p_ret = NULL;
if((p_buf) && (GETF(p_buf->metadata_bf, CO_BUF_METADATA_FROZEN_SIZE) < CO_BUF_META_DATA_SIZE))
{
p_ret = (uint8_t*) &(p_buf->metadata[GETF(p_buf->metadata_bf, CO_BUF_METADATA_FROZEN_SIZE)]);
}
return (p_ret);
}
/**
****************************************************************************************
* @brief Freeze some meta-data into the buffer, this update the meta-data
* pointer given by @see co_buf_metadata function .
* Frozen meta-data should not be updated. A software module that has frozen some
* meta-data must unblock it before using it or before releasing buffer.
*
* Length provided is aligned to 4 bytes in order to ensure that meta-data pointer
* is always 32-bits aligned. Length parameter cannot exceed remaining meta-data
* length.
*
* @param[in] p_buf Pointer to buffer
* @param[in] length Number of byte in buffer meta-data to freeze.
*
* @return CO_BUF_ERR_NO_ERROR if needed length has been frozen.
* CO_BUF_ERR_INVALID_PARAM if provided length is higher than remaining meta-data size
****************************************************************************************
*/
uint8_t co_buf_metadata_freeze(co_buf_t *p_buf, uint8_t length);
/**
****************************************************************************************
* @brief Unfreeze some meta-data into the buffer, this update the meta-data
* pointer given by @see co_buf_metadata function.
* Length provided is aligned to 4 bytes in order to ensure that meta-data
* pointer is always 32-bits aligned.
*
* Length parameter cannot exceed meta-data frozen length
*
* @param[in] p_buf Pointer to buffer
* @param[in] length Number of byte in buffer meta-data to un-freeze.
*
* @return CO_BUF_ERR_NO_ERROR if needed length has been frozen.
* CO_BUF_ERR_INVALID_PARAM if provided length is higher than frozen meta-data size
****************************************************************************************
*/
// uint8_t co_buf_metadata_unfreeze(co_buf_t *p_buf, uint8_t length);
/**
****************************************************************************************
* @brief Retrieve number of bytes in meta-data field that can be used by software layer
*
* @param[in] p_buf Pointer to buffer
*
* @return Number of byte in buffer meta-data remains 0 if an error occurs
****************************************************************************************
*/
__INLINE uint8_t co_buf_metadata_len(const co_buf_t *p_buf)
{
uint8_t ret = 0;
if(p_buf)
{
ret = (CO_BUF_META_DATA_SIZE - GETF(p_buf->metadata_bf, CO_BUF_METADATA_FROZEN_SIZE)) << 2;
}
return (ret);
}
/**
****************************************************************************************
* @brief Allocate a new buffer, specify initial length of head and tail parts, plus copy
* data of input buffer.
*
* @see m_buf_alloc function is used to allocate output buffer.
*
* @note meta-data isn't copied
*
* @param[in] p_buf_in Pointer to input buffer.
* @param[in] p_buf_out Pointer to output buffer.
* @param[in] length Length of data to copy
*
* @return CO_BUF_ERR_NO_ERROR if buffer can be allocated.
* CO_BUF_ERR_INSUFFICIENT_RESOURCE if no more buffers are available.
****************************************************************************************
*/
uint8_t co_buf_duplicate(const co_buf_t *p_buf_in, co_buf_t **pp_buf_out, uint16_t head_len, uint16_t tail_len);
/**
****************************************************************************************
* @brief Copy content of a buffer to another buffer.
*
* @param[in] p_buf_in Pointer to input buffer.
* @param[in] p_buf_out Pointer to output buffer.
* @param[in] length Length of data to copy
* @param[in] copy_meta_size Indicate size of meta-data to copy. It doesn't copy frozen data.
*
* @return CO_BUF_ERR_NO_ERROR if copy has been properly performed.
* CO_BUF_ERR_INVALID_PARAM if the output buffer data size is cannot accept input data length.
****************************************************************************************
*/
uint8_t co_buf_copy(const co_buf_t *p_buf_in, co_buf_t *p_buf_out, uint16_t length, uint8_t copy_meta_size);
/**
****************************************************************************************
* @brief Reuse a given buffer with keeping data information. This can be done only if
* buffer has been released by other software module. meta-data data can be
* considered empty if function execution succeeds.
*
* If this function succeeds it must be considered as an old buffer release and
* new buffer allocation.
* If function execution fails, the buffer is not considered as released
*
* @param[in] p_buf Pointer to the buffer.
*
* @return CO_BUF_ERR_NO_ERROR if buffer has been properly released and reused
* CO_BUF_ERR_RESOURCE_BUSY if buffer acquisition counter > 1
****************************************************************************************
*/
uint8_t co_buf_reuse(co_buf_t *p_buf);
/**
****************************************************************************************
* @brief Reuse a given buffer without keeping data information. This can be done only if
* buffer has been released by other software module. meta-data data can be
* considered empty if function execution succeeds.
*
* Size of header, data_ and trailing length must not exceed size of the buffer.
*
* If this function succeeds it must be considered as an old buffer release and
* new buffer allocation.
* If function execution fails, the buffer is not considered as released.
*
* @param[in] p_buf Pointer to the buffer.
* @param[in] head_len Initial Head Length.
* @param[in] data_len Initial Data Length.
* @param[in] tail_len Initial Tail Length.
*
* @return CO_BUF_ERR_NO_ERROR if buffer has been properly released and reused
* CO_BUF_ERR_RESOURCE_BUSY if buffer acquisition counter > 1
* CO_BUF_ERR_INVALID_PARAM if length fields exceed length of initial buffer
****************************************************************************************
*/
// uint8_t co_buf_reuse_full(co_buf_t *p_buf, uint16_t head_len, uint16_t data_len, uint16_t tail_len);
/**
****************************************************************************************
* @brief TThis function allows a software module to be informed when buffer is free.
* It freezes 8 bytes in buffer meta-data.
*
* This function shall be called only after a buffer allocation or reuse.
*
* @param[in] p_buf Pointer to the buffer.
* @param[in] cb_free Pointer to the function called when the buffer is free.
* @param[in] p_env Pointer to environment that will be used as callback parameter.
*
* @return CO_BUF_ERR_NO_ERROR callback has been properly set
* CO_BUF_ERR_RESOURCE_BUSY if some buffer meta-data already frozen
****************************************************************************************
*/
uint8_t co_buf_cb_free_set(co_buf_t *p_buf, co_buf_free_cb cb_free, void* p_env);
/**
****************************************************************************************
* @brief This function copies content of an input memory data to the data part of a
* buffer. The length field shall not exceed buffer data length.
*
* @param[in] p_buf Pointer to the buffer.
* @param[in] p_in Pointer to input data.
* @param[in] length Length of data to copy
*
* @return CO_BUF_ERR_NO_ERROR if copy has been properly performed.
* CO_BUF_ERR_INVALID_PARAM if data length fields < length parameter
****************************************************************************************
*/
uint8_t co_buf_copy_data_from_mem(co_buf_t *p_buf, const uint8_t *p_in, uint16_t length);
/**
****************************************************************************************
* @brief This function copies data part of a buffer into an output memory block.
* The length field shall not exceed buffer data length..
*
* @param[in] p_buf Pointer to the buffer.
* @param[in] p_out Pointer to output data.
* @param[in] length Length of data to copy
*
* @return CO_BUF_ERR_NO_ERROR if copy has been properly performed.
* CO_BUF_ERR_INVALID_PARAM if data length fields < length parameter
****************************************************************************************
*/
uint8_t co_buf_copy_data_to_mem(const co_buf_t *p_buf, uint8_t *p_out, uint16_t length);
/**
****************************************************************************************
* @brief Initialize Common buffer module.
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
* @param[in] p_big_pool Pointer to the Big pool memory Array
* @param[in] p_small_pool Pointer to the Small pool memory Array
****************************************************************************************
*/
void co_buf_init(uint8_t init_type, uint32_t* p_big_pool, uint32_t* p_small_pool);
/// @} CO_BUF
#endif // _CO_BUF_H_
+134
View File
@@ -0,0 +1,134 @@
/**
****************************************************************************************
*
* @file co_djob.h
*
* @brief Common delayed job definitions
*
* Copyright (C) RivieraWaves 2009-2019
*
****************************************************************************************
*/
#ifndef _CO_DJOB_H_
#define _CO_DJOB_H_
/**
****************************************************************************************
* @defgroup CO_DJOB Utilities
* @ingroup COMMON
* @brief Delayed job utilities
*
* This module contains the delayed job utilities functions and macros.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard definitions
#include <stddef.h> // standard definitions
#include "co_list.h" // common bt definitions
/*
* MACRO DEFINITIONS
****************************************************************************************
*/
/*
* ENUMERATIONS DEFINITIONS
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Job function to called into a background context
*
* @param[in] p_env Pointer to environment that will be used as callback parameter.
****************************************************************************************
*/
typedef void (*co_djob_cb)(void* p_env);
/// Job element structure
typedef struct co_djob
{
/// List element header
co_list_hdr_t hdr;
/// Pointer to environment that will be used as callback parameter.
void* p_env;
/// Callback to execute in background context
co_djob_cb cb;
} co_djob_t;
/*
* CONSTANT DECLARATIONS
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/*
****************************************************************************************
* Delayed Job functions
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Prepare Delayed job structure
*
* @param[in] p_djob Pointer to the delayed job structure
* @param[in] cb Callback to execute in background context
* @param[in] p_env Pointer to environment that will be used as callback parameter.
****************************************************************************************
*/
void co_djob_prepare(co_djob_t* p_djob, co_djob_cb cb, void* p_env);
/**
****************************************************************************************
* @brief Register to execute a job delayed in background
*
* @param[in] p_djob Pointer to the delayed job structure
****************************************************************************************
*/
void co_djob_reg(co_djob_t* p_djob);
/**
****************************************************************************************
* @brief Un-register a job that waits to be executed
*
* @param[in] p_djob Pointer to the delayed job structure
****************************************************************************************
*/
void co_djob_unreg(co_djob_t* p_djob);
/**
****************************************************************************************
* @brief Initialize Common delayed job module.
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
****************************************************************************************
*/
void co_djob_init(uint8_t init_type);
/// @} CO_DJOB
#endif // _CO_DJOB_H_
@@ -0,0 +1,349 @@
/**
****************************************************************************************
*
* @file co_endian.h
*
* @brief Common endianness conversion functions
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _CO_ENDIAN_H_
#define _CO_ENDIAN_H_
#include <stdint.h> // standard integer definitions
#include "rwip_config.h" // stack configuration
#include "arch.h" // architectural platform definition
/**
****************************************************************************************
* @defgroup CO_ENDIAN Endianness
* @ingroup COMMON
* @brief Endianness conversion functions.
*
* This set of functions converts values between the local system
* and a external one. It is inspired from the <tt>htonl</tt>-like functions
* from the standard C library.
*
* Example:
* @code
* struct eth_header *header = get_header(); // get pointer on Eth II packet header
* uint16_t eth_id; // will contain the type of the packet
* eth_id = co_ntohs(header->eth_id); // retrieve the type with correct endianness
* @endcode
*
* @{
* ****************************************************************************************
* */
/**
****************************************************************************************
* @brief Swap bytes of an array of bytes
* .
* The swap is done in every case. Should not be called directly.
*
* @param[in] p_val_out The output value.
* @param[in] p_val_in The input value.
*
* @param[in] len number of bytes to swap
****************************************************************************************
*/
__INLINE void co_bswap(uint8_t* p_val_out, const uint8_t* p_val_in, uint16_t len)
{
while (len > 0)
{
len--;
*p_val_out = p_val_in[len];
p_val_out++;
}
}
/// @} CO_ENDIAN
/**
****************************************************************************************
* @brief Swap bytes of a 32 bits value.
* The swap is done in every case. Should not be called directly.
* @param[in] val32 The 32 bits value to swap.
* @return The 32 bit swapped value.
****************************************************************************************
*/
__INLINE uint32_t co_bswap32(uint32_t val32)
{
return (val32<<24) | ((val32<<8)&0xFF0000) | ((val32>>8)&0xFF00) | ((val32>>24)&0xFF);
}
/**
****************************************************************************************
* @brief Swap bytes of a 24 bits value.
* The swap is done in every case. Should not be called directly.
* @param[in] val24 The 24 bits value to swap.
* @return The 24 bit swapped value.
****************************************************************************************
*/
__INLINE uint32_t co_bswap24(uint32_t val24)
{
return ((val24<<16)&0xFF0000) | ((val24)&0xFF00) | ((val24>>16)&0xFF);
}
/**
****************************************************************************************
* @brief Swap bytes of a 16 bits value.
* The swap is done in every case. Should not be called directly.
* @param[in] val16 The 16 bit value to swap.
* @return The 16 bit swapped value.
****************************************************************************************
*/
__INLINE uint16_t co_bswap16(uint16_t val16)
{
return ((val16<<8)&0xFF00) | ((val16>>8)&0xFF);
}
/// @} CO_ENDIAN
/**
* ****************************************************************************************
* @defgroup CO_ENDIAN_NET Endianness (Network)
* @ingroup CO_ENDIAN
* @brief Endianness conversion functions for Network data
*
* Converts values between the local system and big-endian network data
* (e.g. IP, Ethernet, but NOT WLAN).
*
* The \b host term in the descriptions of these functions refers
* to the local system, i.e. \b application or \b embedded system.
* Therefore, these functions will behave differently depending on which
* side they are used. The reason of this terminology is to keep the
* same name than the standard C function.
*
* Behavior will depends on the endianness of the host:
* - little endian: swap bytes;
* - big endian: identity function.
*
* @{
* ****************************************************************************************
* */
/**
****************************************************************************************
* @brief Convert host to network long word.
*
* @param[in] hostlong Long word value to convert.
*
* @return The converted long word.
****************************************************************************************
*/
__INLINE uint32_t co_htonl(uint32_t hostlong)
{
#if (!CPU_LE)
return hostlong;
#else
return co_bswap32(hostlong);
#endif // CPU_LE
}
/**
****************************************************************************************
* @brief Convert host to network long 24-bit value.
*
* @param[in] val24 24-bit value to convert.
*
* @return The converted 24-but value.
****************************************************************************************
*/
__INLINE uint32_t co_hton24(uint32_t host24)
{
#if (!CPU_LE)
return host24;
#else
return co_bswap24(host24);
#endif // CPU_LE
}
/**
****************************************************************************************
* @brief Convert host to network short word.
*
* @param[in] hostshort Short word value to convert.
*
* @return The converted short word.
****************************************************************************************
*/
__INLINE uint16_t co_htons(uint16_t hostshort)
{
#if (!CPU_LE)
return hostshort;
#else
return co_bswap16(hostshort);
#endif // CPU_LE
}
/**
****************************************************************************************
* @brief Convert network to host long word.
*
* @param[in] netlong Long word value to convert.
*
* @return The converted long word.
****************************************************************************************
*/
__INLINE uint32_t co_ntohl(uint32_t netlong)
{
return co_htonl(netlong);
}
/**
****************************************************************************************
* @brief Convert network to host 24-bit value.
*
* @param[in] val24 24-bit to convert.
*
* @return The converted 24-bit value.
****************************************************************************************
*/
__INLINE uint32_t co_ntoh24(uint32_t val24)
{
return co_hton24(val24);
}
/**
****************************************************************************************
* @brief Convert network to host short word.
*
* @param[in] netshort Short word value to convert.
*
* @return The converted short word.
****************************************************************************************
*/
__INLINE uint16_t co_ntohs(uint16_t netshort)
{
return co_htons(netshort);
}
/// @} CO_ENDIAN_NET
/**
* ****************************************************************************************
* @defgroup CO_ENDIAN_BT Endianness (BT)
* @ingroup CO_ENDIAN
* @brief Endianness conversion functions for Bluetooth data (HCI and protocol)
*
* Converts values between the local system and little-endian Bluetooth data.
*
* The \b host term in the descriptions of these functions refers
* to the local system (check \ref CO_ENDIAN_NET "this comment").
*
* Behavior will depends on the endianness of the host:
* - little endian: identity function;
* - big endian: swap bytes.
*
* @addtogroup CO_ENDIAN_BT
* @{
* ****************************************************************************************
* */
/**
****************************************************************************************
* @brief Convert Bluetooth to host 24-bit value.
*
* @param[in] val24 24-bit to convert.
*
* @return The converted 24-bit value.
****************************************************************************************
*/
__INLINE uint32_t co_htob24(uint32_t val24)
{
#if (CPU_LE)
return val24;
#else
return co_hton24(val24);
#endif // CPU_LE
}
/**
****************************************************************************************
* @brief Convert host to Bluetooth long word.
*
* @param[in] hostlong Long word value to convert.
*
* @return The converted long word.
****************************************************************************************
*/
__INLINE uint32_t co_htobl(uint32_t hostlong)
{
#if (CPU_LE)
return hostlong;
#else
return co_bswap32(hostlong);
#endif // CPU_LE
}
/**
****************************************************************************************
* @brief Convert host to Bluetooth short word.
*
* @param[in] hostshort Short word value to convert.
*
* @return The converted short word.
****************************************************************************************
*/
__INLINE uint16_t co_htobs(uint16_t hostshort)
{
#if (CPU_LE)
return hostshort;
#else
return co_bswap16(hostshort);
#endif // CPU_LE
}
/**
****************************************************************************************
* @brief Convert Bluetooth to host 24-bit value.
*
* @param[in] val24 24-bit to convert.
*
* @return The converted 24-bit value.
****************************************************************************************
*/
__INLINE uint32_t co_btoh24(uint32_t val24)
{
return co_htob24(val24);
}
/**
****************************************************************************************
* @brief Convert Bluetooth to host long word.
*
* @param[in] btlong Long word value to convert.
*
* @return The converted long word.
****************************************************************************************
*/
__INLINE uint32_t co_btohl(uint32_t btlong)
{
return co_htobl(btlong);
}
/**
****************************************************************************************
* @brief Convert Bluetooth to host short word.
*
* @param[in] btshort Short word value to convert.
*
* @return The converted short word.
****************************************************************************************
*/
__INLINE uint16_t co_btohs(uint16_t btshort)
{
return co_htobs(btshort);
}
/// @} CO_ENDIAN
#endif // _CO_ENDIAN_H_
+116
View File
@@ -0,0 +1,116 @@
/**
****************************************************************************************
*
* @file co_error.h
*
* @brief List of codes for error in RW Software.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef CO_ERROR_H_
#define CO_ERROR_H_
/**
****************************************************************************************
* @addtogroup CO_ERROR Error Codes
* @ingroup COMMON
* @brief Defines error codes in messages.
*
* @{
****************************************************************************************
*/
/*
* DEFINES
****************************************************************************************
*/
enum co_error
{
/*****************************************************
*** ERROR CODES ***
*****************************************************/
CO_ERROR_NO_ERROR = 0x00,
CO_ERROR_UNKNOWN_HCI_COMMAND = 0x01,
CO_ERROR_UNKNOWN_CONNECTION_ID = 0x02,
CO_ERROR_HARDWARE_FAILURE = 0x03,
CO_ERROR_PAGE_TIMEOUT = 0x04,
CO_ERROR_AUTH_FAILURE = 0x05,
CO_ERROR_PIN_MISSING = 0x06,
CO_ERROR_MEMORY_CAPA_EXCEED = 0x07,
CO_ERROR_CON_TIMEOUT = 0x08,
CO_ERROR_CON_LIMIT_EXCEED = 0x09,
CO_ERROR_SYNC_CON_LIMIT_DEV_EXCEED = 0x0A,
CO_ERROR_CON_ALREADY_EXISTS = 0x0B,
CO_ERROR_COMMAND_DISALLOWED = 0x0C,
CO_ERROR_CONN_REJ_LIMITED_RESOURCES = 0x0D,
CO_ERROR_CONN_REJ_SECURITY_REASONS = 0x0E,
CO_ERROR_CONN_REJ_UNACCEPTABLE_BDADDR = 0x0F,
CO_ERROR_CONN_ACCEPT_TIMEOUT_EXCEED = 0x10,
CO_ERROR_UNSUPPORTED = 0x11,
CO_ERROR_INVALID_HCI_PARAM = 0x12,
CO_ERROR_REMOTE_USER_TERM_CON = 0x13,
CO_ERROR_REMOTE_DEV_TERM_LOW_RESOURCES = 0x14,
CO_ERROR_REMOTE_DEV_POWER_OFF = 0x15,
CO_ERROR_CON_TERM_BY_LOCAL_HOST = 0x16,
CO_ERROR_REPEATED_ATTEMPTS = 0x17,
CO_ERROR_PAIRING_NOT_ALLOWED = 0x18,
CO_ERROR_UNKNOWN_LMP_PDU = 0x19,
CO_ERROR_UNSUPPORTED_REMOTE_FEATURE = 0x1A,
CO_ERROR_SCO_OFFSET_REJECTED = 0x1B,
CO_ERROR_SCO_INTERVAL_REJECTED = 0x1C,
CO_ERROR_SCO_AIR_MODE_REJECTED = 0x1D,
CO_ERROR_INVALID_LMP_PARAM = 0x1E,
CO_ERROR_UNSPECIFIED_ERROR = 0x1F,
CO_ERROR_UNSUPPORTED_LMP_PARAM_VALUE = 0x20,
CO_ERROR_ROLE_CHANGE_NOT_ALLOWED = 0x21,
CO_ERROR_LMP_RSP_TIMEOUT = 0x22,
CO_ERROR_LMP_COLLISION = 0x23,
CO_ERROR_LMP_PDU_NOT_ALLOWED = 0x24,
CO_ERROR_ENC_MODE_NOT_ACCEPT = 0x25,
CO_ERROR_LINK_KEY_CANT_CHANGE = 0x26,
CO_ERROR_QOS_NOT_SUPPORTED = 0x27,
CO_ERROR_INSTANT_PASSED = 0x28,
CO_ERROR_PAIRING_WITH_UNIT_KEY_NOT_SUP = 0x29,
CO_ERROR_DIFF_TRANSACTION_COLLISION = 0x2A,
CO_ERROR_QOS_UNACCEPTABLE_PARAM = 0x2C,
CO_ERROR_QOS_REJECTED = 0x2D,
CO_ERROR_CHANNEL_CLASS_NOT_SUP = 0x2E,
CO_ERROR_INSUFFICIENT_SECURITY = 0x2F,
CO_ERROR_PARAM_OUT_OF_MAND_RANGE = 0x30,
CO_ERROR_ROLE_SWITCH_PEND = 0x32, /* LM_ROLE_SWITCH_PENDING */
CO_ERROR_RESERVED_SLOT_VIOLATION = 0x34, /* LM_RESERVED_SLOT_VIOLATION */
CO_ERROR_ROLE_SWITCH_FAIL = 0x35, /* LM_ROLE_SWITCH_FAILED */
CO_ERROR_EIR_TOO_LARGE = 0x36, /* LM_EXTENDED_INQUIRY_RESPONSE_TOO_LARGE */
CO_ERROR_SP_NOT_SUPPORTED_HOST = 0x37,
CO_ERROR_HOST_BUSY_PAIRING = 0x38,
CO_ERROR_CONTROLLER_BUSY = 0x3A,
CO_ERROR_UNACCEPTABLE_CONN_PARAM = 0x3B,
CO_ERROR_ADV_TO = 0x3C,
CO_ERROR_TERMINATED_MIC_FAILURE = 0x3D,
CO_ERROR_CONN_FAILED_TO_BE_EST = 0x3E,
CO_ERROR_CCA_REJ_USE_CLOCK_DRAG = 0x40,
CO_ERROR_TYPE0_SUBMAP_NOT_DEFINED = 0x41,
CO_ERROR_UNKNOWN_ADVERTISING_ID = 0x42,
CO_ERROR_LIMIT_REACHED = 0x43,
CO_ERROR_OPERATION_CANCELED_BY_HOST = 0x44,
CO_ERROR_PKT_TOO_LONG = 0x45,
CO_ERROR_UNDEFINED = 0xFF,
/*****************************************************
*** HW ERROR CODES ***
*****************************************************/
CO_ERROR_HW_UART_OUT_OF_SYNC = 0x00,
CO_ERROR_HW_MEM_ALLOC_FAIL = 0x01,
};
/// @} CO_ERROR
#endif // CO_ERROR_H_
File diff suppressed because it is too large Load Diff
+316
View File
@@ -0,0 +1,316 @@
/**
****************************************************************************************
*
* @file co_list.h
*
* @brief Common list structures definitions
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _CO_LIST_H_
#define _CO_LIST_H_
/**
*****************************************************************************************
* @defgroup CO_LIST List management
* @ingroup COMMON
*
* @brief List management.
*
* This module contains the list structures and handling functions.
* @{
*****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard definition
#include <stdbool.h> // boolean definition
#include <stddef.h> // for NULL and size_t
#include "rwip_config.h" // stack configuration
#include "compiler.h" // for __INLINE
/*
* DEFINES
****************************************************************************************
*/
/// structure of a list element header
/*@TRACE*/
struct co_list_hdr
{
/// Pointer to next co_list_hdr
struct co_list_hdr *next;
};
/// simplify type name of list element header
typedef struct co_list_hdr co_list_hdr_t;
/// structure of a list
struct co_list
{
/// pointer to first element of the list
struct co_list_hdr *first;
/// pointer to the last element
struct co_list_hdr *last;
#if (KE_PROFILING)
/// number of element in the list
uint32_t cnt;
/// max number of element in the list
uint32_t maxcnt;
/// min number of element in the list
uint32_t mincnt;
#endif //KE_PROFILING
};
/// simplify type name of list
typedef struct co_list co_list_t;
/*
* MACROS
****************************************************************************************
*/
/// pop a specific element from the list
#define CO_LIST_POP_ELT(list, elt) co_list_extract(&(list), &(elt->hdr));
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize a list to defaults values.
*
* @param list Pointer to the list structure.
****************************************************************************************
*/
void co_list_init(struct co_list *list);
/**
****************************************************************************************
* @brief Construct a list of free elements representing a pool
*
* @param list Pointer to the list structure
* @param pool Pointer to the pool to be initialized
* @param elmt_size Size of one element of the pool (in bytes)
* @param elmt_cnt Number of elements available in the pool
****************************************************************************************
*/
void co_list_pool_init(struct co_list *list,
void *pool,
size_t elmt_size,
uint32_t elmt_cnt);
/**
****************************************************************************************
* @brief Add an element as last on the list.
*
* @param list Pointer to the list structure
* @param list_hdr Pointer to the header to add at the end of the list
*
****************************************************************************************
*/
void co_list_push_back(struct co_list *list, struct co_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Append a sequence of elements at the end of a list.
*
* Note: the elements to append shall be linked together
*
* @param list Pointer to the list structure
* @param first_hdr Pointer to the first element to append
* @param last_hdr Pointer to the last element to append
****************************************************************************************
*/
void co_list_push_back_sublist(struct co_list *list, struct co_list_hdr *first_hdr, struct co_list_hdr *last_hdr);
/**
****************************************************************************************
* @brief Add an element as first on the list.
*
* @param list Pointer to the list structure
* @param list_hdr Pointer to the header to add at the beginning of the list
****************************************************************************************
*/
void co_list_push_front(struct co_list *list, struct co_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Extract the first element of the list.
* @param list Pointer to the list structure
* @return The pointer to the element extracted, and NULL if the list is empty.
****************************************************************************************
*/
struct co_list_hdr *co_list_pop_front(struct co_list *list);
/**
****************************************************************************************
* @brief Search for a given element in the list, and extract it if found.
*
* @param list Pointer to the list structure
* @param list_hdr Element to extract
*
* @return true if the element is found in the list, false otherwise
****************************************************************************************
*/
bool co_list_extract(struct co_list *list, struct co_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Extract an element when the previous element is known
*
* Note: the element to remove shall follow immediately the reference within the list
*
* @param list Pointer to the list structure
* @param elt_ref_hdr Pointer to the referenced element (NULL if element to extract is the first in the list)
* @param elt_to_rem_hdr Pointer to the element to be extracted
****************************************************************************************
*/
void co_list_extract_after(struct co_list *list, struct co_list_hdr *elt_ref_hdr, struct co_list_hdr *elt_to_rem_hdr);
/**
****************************************************************************************
* @brief Extract a sub-list when the previous element is known
*
* Note: the elements to remove shall be linked together and follow immediately the reference element
*
* @param[in] list Pointer to the list structure
* @param[in] ref_hdr Pointer to the referenced element (NULL if first element to extract is first in the list)
* @param[in] last_hdr Pointer to the last element to extract ()
****************************************************************************************
*/
void co_list_extract_sublist(struct co_list *list, struct co_list_hdr *ref_hdr, struct co_list_hdr *last_hdr);
/**
****************************************************************************************
* @brief Searched a given element in the list.
*
* @param list Pointer to the list structure
* @param list_hdr Pointer to the searched element
*
* @return true if the element is found in the list, false otherwise
****************************************************************************************
*/
// bool co_list_find(struct co_list *list, struct co_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Merge two lists in a single one.
*
* This function appends the list pointed by list2 to the list pointed by list1. Once the
* merge is done, it empties list2.
*
* @param list1 Pointer to the destination list
* @param list2 Pointer to the list to append to list1
****************************************************************************************
*/
// void co_list_merge(struct co_list *list1, struct co_list *list2);
/**
****************************************************************************************
* @brief Insert a given element in the list before the referenced element.
*
* @param list Pointer to the list structure
* @param elt_ref_hdr Pointer to the referenced element
* @param elt_to_add_hdr Pointer to the element to be inserted
*
* @return true if the element is found in the list, false otherwise
****************************************************************************************
*/
void co_list_insert_before(struct co_list *list,
struct co_list_hdr *elt_ref_hdr, struct co_list_hdr *elt_to_add_hdr);
/**
****************************************************************************************
* @brief Insert a given element in the list after the referenced element.
*
* @param list Pointer to the list structure
* @param elt_ref_hdr Pointer to the referenced element
* @param elt_to_add_hdr Pointer to the element to be inserted
*
* @return true if the element is found in the list, false otherwise
****************************************************************************************
*/
void co_list_insert_after(struct co_list *list,
struct co_list_hdr *elt_ref_hdr, struct co_list_hdr *elt_to_add_hdr);
/**
****************************************************************************************
* @brief Count number of elements present in the list
*
* @param list Pointer to the list structure
*
* @return Number of elements present in the list
****************************************************************************************
*/
// uint16_t co_list_size(struct co_list *list);
/**
****************************************************************************************
* @brief Test if the list is empty.
* @param list Pointer to the list structure.
* @return true if the list is empty, false else otherwise.
****************************************************************************************
*/
__INLINE bool co_list_is_empty(const struct co_list *const list)
{
bool listempty;
listempty = (list->first == NULL);
return (listempty);
}
/**
****************************************************************************************
* @brief Pick the first element from the list without removing it.
*
* @param list Pointer to the list structure.
*
* @return First element address. Returns NULL pointer if the list is empty.
****************************************************************************************
*/
__INLINE struct co_list_hdr *co_list_pick(const struct co_list *const list)
{
return(list->first);
}
/**
****************************************************************************************
* @brief Pick last element from the list without removing it.
*
* @param list Pointer to the list structure.
*
* @return Last element address. Returns NULL pointer if the list is empty.
****************************************************************************************
*/
__INLINE struct co_list_hdr *co_list_tail(const struct co_list *const list)
{
return(list->last);
}
/**
****************************************************************************************
* @brief Return following element of a list element.
*
* @param list_hdr Pointer to the list element.
*
* @return The pointer to the next element.
****************************************************************************************
*/
__INLINE struct co_list_hdr *co_list_next(const struct co_list_hdr *const list_hdr)
{
return(list_hdr->next);
}
/// @} CO_LIST
#endif // _CO_LIST_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+307
View File
@@ -0,0 +1,307 @@
/**
****************************************************************************************
*
* @file co_math.h
*
* @brief Common optimized math functions
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _CO_MATH_H_
#define _CO_MATH_H_
/**
*****************************************************************************************
* @defgroup CO_MATH Math functions
* @ingroup COMMON
* @brief Optimized math functions and other computations.
*
* @{
*****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard integer definitions
#include <stdbool.h> // boolean definitions
#include <stdlib.h> // standard library
#include "compiler.h" // for __INLINE
#include "arch.h" // for ASSERT_ERR
extern void srand (unsigned int seed);
extern int rand (void);
/*
* MACROS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Return value with one bit set.
*
* @param[in] pos Position of the bit to set.
*
* @return Value with one bit set. There is no return type since this is a macro and this
* will be resolved by the compiler upon assignment to an l-value.
****************************************************************************************
*/
#define CO_BIT(pos) (1UL<<(pos))
/**
****************************************************************************************
* @brief Return value bit into a bit field.
*
* @param[in] bf Bit Field
* @param[in] pos Position of the bit
*
* @return value of a bit into a bit field
****************************************************************************************
*/
#define CO_BIT_GET(bf, pos) (((((uint8_t*)bf)[((pos) >> 3)])>>((pos) & 0x7)) & 0x1)
/**
****************************************************************************************
* @brief Update value bit into a bit field.
*
* @param[in] bf Bit Field
* @param[in] pos Position of the bit
* @param[in] val New value of the bit (0 or 1)
****************************************************************************************
*/
#define CO_BIT_SET(bf, pos, val) (((uint8_t*)bf)[((pos) >> 3)]) = ((((uint8_t*)bf)[((pos) >> 3)]) & ~CO_BIT(((pos) & 0x7))) \
| (((val) & 0x1) << ((pos) & 0x7))
/**
****************************************************************************************
* @brief Align val on the multiple of 4 equal or nearest higher.
* @param[in] val Value to align.
* @return Value aligned.
****************************************************************************************
*/
#define CO_ALIGN4_HI(val) (((val)+3)&~3)
/**
****************************************************************************************
* @brief Align val on the multiple of 4 equal or nearest lower.
* @param[in] val Value to align.
* @return Value aligned.
****************************************************************************************
*/
#define CO_ALIGN4_LO(val) ((val)&~3)
/**
****************************************************************************************
* @brief Align val on the multiple of 2 equal or nearest higher.
* @param[in] val Value to align.
* @return Value aligned.
****************************************************************************************
*/
#define CO_ALIGN2_HI(val) (((val)+1)&~1)
/**
****************************************************************************************
* @brief Align val on the multiple of 2 equal or nearest lower.
* @param[in] val Value to align.
* @return Value aligned.
****************************************************************************************
*/
#define CO_ALIGN2_LO(val) ((val)&~1)
/**
****************************************************************************************
* Perform a division and ceil up the result
*
* @param[in] val Value to divide
* @param[in] div Divide value
* @return ceil(val/div)
****************************************************************************************
*/
#define CO_DIVIDE_CEIL(val, div) (((val) + ((div) - 1))/ (div))
/**
****************************************************************************************
* Perform a division and round the result
*
* @param[in] val Value to divide
* @param[in] div Divide value
* @return round(val/div)
****************************************************************************************
*/
#define CO_DIVIDE_ROUND(val, div) (((val) + ((div) >> 1))/ (div))
/**
****************************************************************************************
* Perform a modulo operation
*
* @param[in] val Dividend
* @param[in] div Divisor
* @return val/div)
****************************************************************************************
*/
//#define CO_MOD(val, div) ((val) % (div))
__INLINE uint32_t co_mod(uint32_t val, uint32_t div)
{
ASSERT_ERR(div);
return ((val) % (div));
}
#define CO_MOD(val, div) co_mod(val, div)
/*
* FUNCTION DEFINTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Count leading zeros.
* @param[in] val Value to count the number of leading zeros on.
* @return Number of leading zeros when value is written as 32 bits.
****************************************************************************************
*/
__INLINE uint32_t co_clz(uint32_t val)
{
#if defined(__arm__)
return __builtin_clz(val);
#elif defined(__GNUC__)
if (val == 0)
{
return 32;
}
return __builtin_clz(val);
#else
uint32_t i;
for (i = 0; i < 32; i++)
{
if (val & CO_BIT(31 - i))
break;
}
return i;
#endif // defined(__arm__)
}
/**
****************************************************************************************
* @brief Count trailing zeros.
* @param[in] val Value to count the number of trailing zeros on.
* @return Number of trailing zeros when value is written as 32 bits.
****************************************************************************************
*/
__INLINE uint32_t co_ctz(uint32_t val)
{
#if defined(__arm__)
return __builtin_ctz(val);
#elif defined(__GNUC__)
if (val == 0)
{
return 32;
}
return __builtin_ctz(val);
#else
uint32_t i;
for (i = 0; i < 32; i++)
{
if (val & CO_BIT(i))
break;
}
return i;
#endif // defined(__arm__)
}
/**
****************************************************************************************
* @brief Function to initialize the random seed.
* @param[in] seed The seed number to use to generate the random sequence.
****************************************************************************************
*/
__INLINE void co_random_init(uint32_t seed)
{
srand(seed);
}
/**
****************************************************************************************
* @brief Function to get an 8 bit random number.
* @return Random byte value.
****************************************************************************************
*/
__INLINE uint8_t co_rand_byte(void)
{
return (uint8_t)(rand() & 0xFF);
}
/**
****************************************************************************************
* @brief Function to get an 16 bit random number.
* @return Random half word value.
****************************************************************************************
*/
__INLINE uint16_t co_rand_hword(void)
{
return (uint16_t)(rand() & 0xFFFF);
}
/**
****************************************************************************************
* @brief Function to get an 32 bit random number.
* @return Random word value.
****************************************************************************************
*/
__INLINE uint32_t co_rand_word(void)
{
return (uint32_t)rand();
}
/**
****************************************************************************************
* @brief Function to return the smallest of 2 unsigned 32 bits words.
* @return The smallest value.
****************************************************************************************
*/
__INLINE uint32_t co_min(uint32_t a, uint32_t b)
{
return a < b ? a : b;
}
/**
****************************************************************************************
* @brief Function to return the smallest of 2 signed 32 bits words.
* @return The smallest value.
****************************************************************************************
*/
__INLINE int32_t co_min_s(int32_t a, int32_t b)
{
return a < b ? a : b;
}
/**
****************************************************************************************
* @brief Function to return the greatest of 2 unsigned 32 bits words.
* @return The greatest value.
****************************************************************************************
*/
__INLINE uint32_t co_max(uint32_t a, uint32_t b)
{
return a > b ? a : b;
}
/**
****************************************************************************************
* @brief Function to return the absolute value of a signed integer.
* @return The absolute value.
****************************************************************************************
*/
__INLINE int co_abs(int val)
{
return (val < 0) ? (0 - val) : val;
}
/// @} CO_MATH
#endif // _CO_MATH_H_
+210
View File
@@ -0,0 +1,210 @@
/**
****************************************************************************************
*
* @file co_time.h
*
* @brief The Common Time module provides information about the device time and a
* scheduler for timers used by the different modules. It maintains a list of
* pending timers sorted by ascending expiration time. One timer is programmed
* at a given time. A callback is associated with each timer and is called upon
* expiration of the timer.
*
* Timers shall be used for non real time software.
*
* Copyright (C) RivieraWaves 2009-2019
*
****************************************************************************************
*/
#ifndef _CO_TIME_H_
#define _CO_TIME_H_
/**
****************************************************************************************
* @defgroup CO_TIME Utilities
* @ingroup COMMON
* @brief Time utilities
*
* This module contains the Common time utilities functions and macros.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard definitions
#include <stddef.h> // standard definitions
/*
* MACRO DEFINITIONS
****************************************************************************************
*/
/*
* ENUMERATIONS DEFINITIONS
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Function to called once timer expires
*
* @param[in] p_env Pointer to environment that will be used as callback parameter.
****************************************************************************************
*/
typedef void (*co_time_timer_cb)(void* p_env);
/// Timer structure
typedef struct co_time_timer
{
/// Pointer to next timer in timer list
struct co_time_timer * p_next;
/// Pointer to environment that will be used as callback parameter.
void* p_env;
/// Callback to execute in background context upon timer expiration
co_time_timer_cb cb;
/// Expiration time [0-31] part (in milliseconds)
uint32_t exp_time_ms_lsb;
/// Timer bit field (@see enum co_time_timer_bf)
uint32_t timer_bf;
} co_time_timer_t;
/// Time Structure
typedef struct co_time
{
/// Current time [0-31] part (in milliseconds)
uint32_t ms_lsb;
/// Current time [32-39] part (in milliseconds)
uint8_t ms_msb;
} co_time_t;
/*
* CONSTANT DECLARATIONS
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize Common time module.
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
****************************************************************************************
*/
void co_time_init(uint8_t init_type);
/*
****************************************************************************************
* Time and timer functions
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Retrieve current time in milliseconds.
*
* Time value can be either Up-time of the device or Time since the device has been
* started for the first time.
*
* This depends if system is able to compensate power-off time to update internal time value
*
* @return current time in milliseconds.
*
****************************************************************************************
*/
co_time_t co_time_get(void);
/**
****************************************************************************************
* @brief Retrieve current time in milliseconds.
*
* Compensate device time. This compensation should be done after power-up of the device.
* The time compensation is automatically performed by device when wake-up from sleep mode.
* This function shall be called when no timer are programmed at device start-up.
*
* @param[in] delta_time_ms_lsb Delta time [0-31] part (in milliseconds)
* @param[in] delta_time_ms_msb Delta time [32-39] part (in milliseconds)
****************************************************************************************
*/
// void co_time_compensate(uint32_t delta_time_ms_lsb, uint8_t delta_time_ms_msb);
/**
****************************************************************************************
* @brief Initialize timer structure.
*
* @param[in] p_timer Pointer to the timer structure.
* @param[in] cb Function to be called upon timer expiration.
* @param[in] p_env Pointer to be passed to the callback
****************************************************************************************
*/
void co_time_timer_init(co_time_timer_t* p_timer, co_time_timer_cb cb, void* p_env);
/**
****************************************************************************************
* @brief Program a timer to be scheduled in the future.
* If timer is already programmed, it is restarted.
* If delay is less than 10ms, delay is set to 10ms.
*
* @param[in] p_timer Pointer to the timer structure.
* @param[in] delay_ms Duration before expiration of the timer (in milliseconds).
****************************************************************************************
*/
void co_time_timer_set(co_time_timer_t* p_timer, uint32_t delay_ms);
/**
****************************************************************************************
* @brief Program a timer to be scheduled in the future with duration greater than 49 days.
* If timer is already programmed, it is restarted.
* If delay is less than 10ms, delay is set to 10ms.
*
* @param[in] p_timer Pointer to the timer structure.
* @param[in] delay_ms_lsb Duration before expiration of the timer [0-31] part (in milliseconds)
* @param[in] delay_ms_msb Duration before expiration of the timer [32-39] part (in milliseconds)
****************************************************************************************
*/
// void co_time_timer_long_set(co_time_timer_t* p_timer, uint32_t delay_ms_lsb, uint8_t delay_ms_msb);
/**
****************************************************************************************
* @brief Program a timer to be scheduled periodically. If timer is already programmed,
* it is restarted.
* If period exceed maximum value, timer is programmed using maximum period.
* If period less than 10ms, period is set to 10ms.
*
* @param[in] p_timer Pointer to the timer structure.
* @param[in] period_ms Periodic duration (in milliseconds). Range [10, 48388607] max ~2 hours
****************************************************************************************
*/
// void co_time_timer_periodic_set(co_time_timer_t* p_timer, uint32_t period_ms);
/**
****************************************************************************************
* @brief Stop a programmed timer.
*
* @param[in] p_timer Pointer to the timer structure.
****************************************************************************************
*/
void co_time_timer_stop(co_time_timer_t* p_timer);
/// @} CO_TIME
#endif // _CO_TIME_H_
+721
View File
@@ -0,0 +1,721 @@
/**
****************************************************************************************
*
* @file co_utils.h
*
* @brief Common utilities definitions
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _CO_UTILS_H_
#define _CO_UTILS_H_
/**
****************************************************************************************
* @defgroup CO_UTILS Utilities
* @ingroup COMMON
* @brief Common utilities
*
* This module contains the common utilities functions and macros.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard definitions
#include <stddef.h> // standard definitions
#include "co_bt.h" // common bt definitions
#include "rwip_config.h" // SW configuration
#include "rwip.h" // SW configuration
#include "compiler.h" // for inline functions
/*
* MACRO DEFINITIONS
****************************************************************************************
*/
/// Common constants - bit field definitions
#define BIT0 0x0001
#define BIT1 0x0002
#define BIT2 0x0004
#define BIT3 0x0008
#define BIT4 0x0010
#define BIT5 0x0020
#define BIT6 0x0040
#define BIT7 0x0080
#define BIT8 0x0100
#define BIT9 0x0200
#define BIT10 0x0400
#define BIT11 0x0800
#define BIT12 0x1000
#define BIT13 0x2000
#define BIT14 0x4000
#define BIT15 0x8000
/// Number of '1' bits in a byte
#define NB_ONE_BITS(byte) (one_bits[byte & 0x0F] + one_bits[byte >> 4])
/// Get the number of elements within an array, give also number of rows in a 2-D array
#define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0]))
/// Get the number of columns within a 2-D array
#define ARRAY_NB_COLUMNS(array) (sizeof((array[0]))/sizeof((array)[0][0]))
/// Macro for LMP message handler function declaration or definition
#define LMP_MSG_HANDLER(msg_name) int lmp_##msg_name##_handler(struct lmp_##msg_name const *param, \
ke_task_id_t const dest_id)
/// Macro for LMP message handler function declaration or definition
#define LLCP_MSG_HANDLER(msg_name) int llcp_##msg_name##_handler(struct llcp_##msg_name const *param, \
ke_task_id_t const dest_id)
/// Macro for HCI message handler function declaration or definition (for multi-instantiated tasks)
#define HCI_CMD_HANDLER_C(cmd_name, param_struct) int hci_##cmd_name##_cmd_lc_handler(param_struct const *param, \
ke_task_id_t const dest_id, \
uint16_t opcode)
/// Macro for HCI message handler function declaration or definition (with parameters)
#define HCI_CMD_HANDLER(cmd_name, param_struct) int hci_##cmd_name##_cmd_handler(param_struct const *param, \
uint16_t opcode)
/// Macro for HCI message handler function declaration or definition (with parameters)
#define HCI_CMD_HANDLER_TAB(task) const struct task##_hci_cmd_handler task##_hci_command_handler_tab[] =
/// MACRO to build a subversion field from the Minor and Release fields
#define CO_SUBVERSION_BUILD(minor, release) (((minor) << 8) | (release))
/// Macro to get a structure from one of its structure field
#define CONTAINER_OF(ptr, type, member) ((type *)( (char *)ptr - offsetof(type,member) ))
/// count number of bit into a long field
#define CO_BIT_CNT(val) (co_bit_cnt((uint8_t*) &(val), sizeof(val)))
/// Increment value and make sure it's never greater or equals max (else wrap to 0)
#define CO_VAL_INC(_val, _max) \
(_val) = (_val) + 1; \
if((_val) >= (_max)) (_val) = 0
/// Add value and make sure it's never greater or equals max (else wrap)
/// _add must be less that _max
#define CO_VAL_ADD(_val, _add, _max) \
(_val) = (_val) + (_add); \
if((_val) >= (_max)) (_val) -= (_max)
/// sub value and make sure it's never greater or equals max (else wrap)
/// _sub must be less that _max
#define CO_VAL_SUB(_val, _sub, _max) \
if((_val) < (_sub)) (_val) += _max; \
(_val) = (_val) - (_sub)
/*
* ENUMERATIONS DEFINITIONS
****************************************************************************************
*/
/// Status returned by generic packer-unpacker
enum CO_UTIL_PACK_STATUS
{
CO_UTIL_PACK_OK,
CO_UTIL_PACK_IN_BUF_OVFLW,
CO_UTIL_PACK_OUT_BUF_OVFLW,
CO_UTIL_PACK_WRONG_FORMAT,
CO_UTIL_PACK_ERROR,
};
/// Rate information
/*@TRACE*/
enum phy_rate
{
/// 1 Mbits/s Rate
CO_RATE_1MBPS = 0,
/// 2 Mbits/s Rate
CO_RATE_2MBPS = 1,
/// 125 Kbits/s Rate
CO_RATE_125KBPS = 2,
/// 500 Kbits/s Rate
CO_RATE_500KBPS = 3,
/// Undefined rate (used for reporting when no packet is received)
CO_RATE_UNDEF = 4,
CO_RATE_MAX = 4,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/*
* CONSTANT DECLARATIONS
****************************************************************************************
*/
/// Number of '1' bits in values from 0 to 15, used to fasten bit counting
extern const unsigned char one_bits[16];
/// Conversion table Sleep Clock Accuracy to PPM
extern const uint16_t co_sca2ppm[];
/// NULL BD address
extern const struct bd_addr co_null_bdaddr;
/// Default BD address
extern struct bd_addr co_default_bdaddr;
/// NULL Key
extern const uint8_t co_null_key[KEY_LEN];
/// Table for converting rate to PHY
extern const uint8_t co_rate_to_phy[];
/// Table for converting PHY to rate (Warning: the coded PHY is converted to 125K by default)
extern const uint8_t co_phy_to_rate[];
/// Convert PHY mask (with one single bit set) to a value
extern const uint8_t co_phy_mask_to_value[];
/// Convert PHY a value to the corresponding mask bit
extern const uint8_t co_phy_value_to_mask[];
/// Convert Rate value to the corresponding PHY mask bit
extern const uint8_t co_rate_to_phy_mask[];
/// Convert PHY mask bit to the corresponding Rate value
extern const uint8_t co_phy_mask_to_rate[];
#if BLE_PWR_CTRL
/// Convert PHY rate value of power control to the corresponding PHY mask bit
extern const uint8_t co_phypwr_value_to_mask[];
/// Convert PHY mask bit of power control to the corresponding PHY rate value
extern const uint8_t co_phypwr_mask_to_value[];
/// Convert PHY rate value of power control to Rate value
extern const uint8_t co_phypwr_to_rate[];
/// Convert Rate value to PHY rate value of power control
extern const uint8_t co_rate_to_phypwr[];
/// Convert Rate value to PHY mask value of power control
extern const uint8_t co_rate_to_phypwr_mask[];
#endif // BLE_PWR_CTRL
/// Convert Rate value to byte duration in us
extern const uint8_t co_rate_to_byte_dur_us[];
/*
* OPERATIONS ON BT CLOCK
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Clocks addition with 2 operands
*
* @param[in] clock_a 1st operand value (in BT half-slots)
* @param[in] clock_b 2nd operand value (in BT half-slots)
* @return result operation result (in BT half-slots)
****************************************************************************************
*/
#define CLK_ADD_2(clock_a, clock_b) ((uint32_t)(((clock_a) + (clock_b)) & RWIP_MAX_CLOCK_TIME))
/**
****************************************************************************************
* @brief Clocks addition with 3 operands
*
* @param[in] clock_a 1st operand value (in BT half-slots)
* @param[in] clock_b 2nd operand value (in BT half-slots)
* @param[in] clock_c 3rd operand value (in BT half-slots)
* @return result operation result (in BT half-slots)
****************************************************************************************
*/
#define CLK_ADD_3(clock_a, clock_b, clock_c) ((uint32_t)(((clock_a) + (clock_b) + (clock_c)) & RWIP_MAX_CLOCK_TIME))
/**
****************************************************************************************
* @brief Clocks subtraction
*
* @param[in] clock_a 1st operand value (in BT half-slots)
* @param[in] clock_b 2nd operand value (in BT half-slots)
* @return result operation result (in BT half-slots)
****************************************************************************************
*/
#define CLK_SUB(clock_a, clock_b) ((uint32_t)(((clock_a) - (clock_b)) & RWIP_MAX_CLOCK_TIME))
/**
****************************************************************************************
* @brief Bluetooth timestamp Clocks subtraction
*
* @param[in] clock_a 1st operand value (in microseconds)
* @param[in] clock_b 2nd operand value (in microseconds)
* @return result operation result (in microseconds)
****************************************************************************************
*/
#define CLK_BTS_SUB(clock_a, clock_b) (((int32_t) ((clock_a) - (clock_b))))
/**
****************************************************************************************
* @brief Check if clock_a is lower than or equal to clock_b
*
* @param[in] clock_a Clock A value (in BT half-slots)
* @param[in] clock_b Clock B value (in BT half-slots)
* @return result True: clock_a lower than or equal to clock_b | False: else
****************************************************************************************
*/
#define CLK_BTS_LOWER_EQ(clock_a, clock_b) (CLK_BTS_SUB(clock_b, clock_a) < (RWIP_MAX_BTS_TIME >> 1))
/**
****************************************************************************************
* @brief Clocks time difference
*
* @param[in] clock_a 1st operand value (in BT half-slots)
* @param[in] clock_b 2nd operand value (in BT half-slots)
* @return result return the time difference from clock A to clock B
* - result < 0 => clock_b is in the past
* - result == 0 => clock_a is equal to clock_b
* - result > 0 => clock_b is in the future
****************************************************************************************
*/
#define CLK_DIFF(clock_a, clock_b) ( (CLK_SUB((clock_b), (clock_a)) > ((RWIP_MAX_CLOCK_TIME+1) >> 1)) ? \
((int32_t)((-CLK_SUB((clock_a), (clock_b))))) : ((int32_t)((CLK_SUB((clock_b), (clock_a))))) )
/// macro to extract a field from a value containing several fields
/// @param[in] __r bit field value
/// @param[in] __f field name
/// @return the value of the register masked and shifted
#define GETF(__r, __f) \
(( (__r) & (__f##_MASK) ) >> (__f##_LSB))
/// macro to set a field value into a value containing several fields.
/// @param[in] __r bit field value
/// @param[in] __f field name
/// @param[in] __v value to put in field
#define SETF(__r, __f, __v) \
do { \
ASSERT_INFO( ( ( ( (__v) << (__f##_LSB) ) & ( ~(__f##_MASK) ) ) ) == 0 ,(__f##_MASK), (__v)); \
__r = (((__r) & ~(__f##_MASK)) | (__v) << (__f##_LSB)); \
} while (0)
/// macro to extract a bit field from a value containing several fields
/// @param[in] __r bit field value
/// @param[in] __b bit field name
/// @return the value of the register masked and shifted
#define GETB(__r, __b) \
(( (__r) & (__b##_BIT) ) >> (__b##_POS))
/// macro to set a bit field value into a value containing several fields.
/// @param[in] __r bit field value
/// @param[in] __b bit field name
/// @param[in] __v value to put in field
#define SETB(__r, __b, __v) \
do { \
ASSERT_ERR( ( ( ( (__v ? 1 : 0) << (__b##_POS) ) & ( ~(__b##_BIT) ) ) ) == 0 ); \
__r = (((__r) & ~(__b##_BIT)) | (__v ? 1 : 0) << (__b##_POS)); \
} while (0)
/// macro to toggle a bit into a value containing several bits.
/// @param[in] __r bit field value
/// @param[in] __b bit field name
#define TOGB(__r, __b) \
do { \
__r = ((__r) ^ (__b##_BIT)); \
} while (0)
/**
****************************************************************************************
* @brief Check if clock_a is equal to clock_b
*
* @param[in] clock_a Clock A value (in BT half-slots)
* @param[in] clock_b Clock B value (in BT half-slots)
* @return result True: clock_a lower than or equal to clock_b | False: else
****************************************************************************************
*/
#define CLK_EQ(clock_a, clock_b) (clock_b == clock_a)
/**
****************************************************************************************
* @brief Check if clock_a is lower than or equal to clock_b
*
* @param[in] clock_a Clock A value (in BT half-slots)
* @param[in] clock_b Clock B value (in BT half-slots)
* @return result True: clock_a lower than or equal to clock_b | False: else
****************************************************************************************
*/
#define CLK_LOWER_EQ(clock_a, clock_b) (CLK_SUB(clock_b, clock_a) < (RWIP_MAX_CLOCK_TIME >> 1))
/**
****************************************************************************************
* @brief Check if clock A is lower than or equal to clock B (with half-us precision)
*
* @param[in] int_a Integer part of clock A (in BT half-slots)
* @param[in] fract_a Fractional part of clock A (in half-us) (range: 0 to 624)
* @param[in] int_b Integer part of clock B (in BT half-slots)
* @param[in] fract_b Fractional part of clock B (in half-us) (range: 0 to 624)
* @return result True: clock A lower than or equal to clock B | False: else
****************************************************************************************
*/
#define CLK_LOWER_EQ_HUS(int_a, fract_a, int_b, fract_b) ( CLK_GREATER_THAN(int_b, int_a) \
|| ( CLK_EQ(int_a, int_b) \
&& (fract_a <= fract_b) ) ) \
/**
****************************************************************************************
* @brief Check if clock_a is greater than clock_b
*
* @param[in] clock_a Clock A value (in BT half-slots)
* @param[in] clock_b Clock B value (in BT half-slots)
* @return result True: clock_a is greater than clock_b | False: else
****************************************************************************************
*/
#define CLK_GREATER_THAN(clock_a, clock_b) !(CLK_LOWER_EQ(clock_a, clock_b))
/**
****************************************************************************************
* @brief Check if clock A is greater than clock B (with half-us precision)
*
* @param[in] int_a Integer part of clock A (in BT half-slots)
* @param[in] fract_a Fractional part of clock A (in half-us) (range: 0 to 624)
* @param[in] int_b Integer part of clock B (in BT half-slots)
* @param[in] fract_b Fractional part of clock B (in half-us) (range: 0 to 624)
* @return result True: clock A greater than clock B | False: else
****************************************************************************************
*/
#define CLK_GREATER_THAN_HUS(int_a, fract_a, int_b, fract_b) ( CLK_GREATER_THAN(int_a, int_b) \
|| ( CLK_EQ(int_a, int_b) \
&& (fract_a > fract_b) ) ) \
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Read an aligned 32 bit word.
* @param[in] ptr32 The address of the first byte of the 32 bit word.
* @return The 32 bit value.
****************************************************************************************
*/
__INLINE uint32_t co_read32(void const *ptr32)
{
return *((uint32_t*)ptr32);
}
/**
****************************************************************************************
* @brief Read an aligned 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @return The 16 bits value.
****************************************************************************************
*/
__INLINE uint16_t co_read16(void const *ptr16)
{
return *((uint16_t*)ptr16);
}
/**
****************************************************************************************
* @brief Write an aligned 32 bits word.
* @param[in] ptr32 The address of the first byte of the 32 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE void co_write32(void const *ptr32, uint32_t value)
{
*(uint32_t*)ptr32 = value;
}
/**
****************************************************************************************
* @brief Write an aligned 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE void co_write16(void const *ptr16, uint32_t value)
{
*(uint16_t*)ptr16 = value;
}
/**
****************************************************************************************
* @brief Write a 8 bits word.
* @param[in] ptr8 The address of the first byte of the 8 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE void co_write8(void const *ptr8, uint32_t value)
{
*(uint8_t*)ptr8 = value;
}
/**
****************************************************************************************
* @brief Read a packed 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @return The 16 bits value.
****************************************************************************************
*/
__INLINE uint16_t co_read16p(void const *ptr16)
{
uint16_t value = ((uint8_t *)ptr16)[0] | ((uint8_t *)ptr16)[1] << 8;
return value;
}
/**
****************************************************************************************
* @brief Read a packed 24 bits word.
* @param[in] ptr24 The address of the first byte of the 24 bits word.
* @return The 24 bits value.
****************************************************************************************
*/
__INLINE uint32_t co_read24p(void const *ptr24)
{
uint16_t addr_l, addr_h;
addr_l = co_read16p(ptr24);
addr_h = *((uint8_t *)ptr24 + 2) & 0x00FF;
return ((uint32_t)addr_l | (uint32_t)addr_h << 16);
}
/**
****************************************************************************************
* @brief Write a packed 24 bits word.
* @param[in] ptr24 The address of the first byte of the 24 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE void co_write24p(void const *ptr24, uint32_t value)
{
uint8_t *ptr=(uint8_t*)ptr24;
*ptr++ = (uint8_t)(value&0xff);
*ptr++ = (uint8_t)((value&0xff00)>>8);
*ptr++ = (uint8_t)((value&0xff0000)>>16);
}
/**
****************************************************************************************
* @brief Read a packed 32 bits word.
* @param[in] ptr32 The address of the first byte of the 32 bits word.
* @return The 32 bits value.
****************************************************************************************
*/
__INLINE uint32_t co_read32p(void const *ptr32)
{
uint16_t addr_l, addr_h;
addr_l = co_read16p(ptr32);
addr_h = co_read16p((uint8_t *)ptr32 + 2);
return ((uint32_t)addr_l | (uint32_t)addr_h << 16);
}
/**
****************************************************************************************
* @brief Write a packed 32 bits word.
* @param[in] ptr32 The address of the first byte of the 32 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE void co_write32p(void const *ptr32, uint32_t value)
{
uint8_t *ptr=(uint8_t*)ptr32;
*ptr++ = (uint8_t)(value&0xff);
*ptr++ = (uint8_t)((value&0xff00)>>8);
*ptr++ = (uint8_t)((value&0xff0000)>>16);
*ptr = (uint8_t)((value&0xff000000)>>24);
}
/**
****************************************************************************************
* @brief Write a packed 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE void co_write16p(void const *ptr16, uint16_t value)
{
uint8_t *ptr=(uint8_t*)ptr16;
*ptr++ = value&0xff;
*ptr = (value&0xff00)>>8;
}
/**
****************************************************************************************
* Count number of bit set to 1 in a value with variable length
*
* @param[in] p_val Pointer to value
* @param[in] size Number of Bytes
* @return Number of bit counted
****************************************************************************************
*/
__INLINE uint8_t co_bit_cnt(const uint8_t* p_val, uint8_t size)
{
uint8_t nb_bit = 0;
while(size-- > 0)
{
nb_bit += NB_ONE_BITS(*p_val);
p_val++;
}
return (nb_bit);
}
#if (RW_DEBUG || DISPLAY_SUPPORT)
/**
****************************************************************************************
* @brief Convert bytes to hexadecimal string
*
* @param[out] dest Pointer to the destination string (must be 2x longer than input table)
* @param[in] src Pointer to the bytes table
* @param[in] nb_bytes Number of bytes to display in the string
****************************************************************************************
*/
void co_bytes_to_string(char* dest, uint8_t* src, uint8_t nb_bytes);
#endif //(RW_DEBUG || DISPLAY_SUPPORT)
/**
****************************************************************************************
* @brief Compares two Bluetooth device addresses
*
* This function checks if the two bd address are equal.
*
* @param[in] bd_address1 Pointer on the first bd address to be compared.
* @param[in] bd_address2 Pointer on the second bd address to be compared.
*
* @return result of the comparison (true: equal | false: different).
****************************************************************************************
*/
bool co_bdaddr_compare(struct bd_addr const *bd_address1, struct bd_addr const *bd_address2);
#if (BT_EMB_PRESENT)
/**
******************************************************************************
* @brief Convert an duration in baseband slot to a duration in number of ticks.
* @param[in] slot_cnt Duration in number of baseband slot
* @return Duration (in number of ticks).
******************************************************************************
*/
uint32_t co_slot_to_duration(uint32_t slot_cnt);
/**
******************************************************************************
* @brief Count the number of good channels in a map
* @param[in] map Channel Map (bit fields for the 79 BT RF channels)
* @return Number of good channels
******************************************************************************
*/
uint8_t co_nb_good_channels(const struct chnl_map* map);
#endif //BT_EMB_PRESENT
/**
****************************************************************************************
* @brief Pack parameters from a C structure to a packed buffer
*
* This function packs parameters according to a specific format. It takes care of the
* endianess, padding, required by the compiler.
*
* By default output format is LSB but it can be changed with first character of format string
* - < : LSB output format
* - > : MSB output format
*
* Format strings are the mechanism used to specify the expected layout when packing and unpacking data. They are built
* up from Format Characters, which specify the type of data being packed/unpacked.
* - B : byte - 8bits value
* - H : word - 16bits value
* - L : long - 32-bits value
* - D : 24 bits value
* - XXB: table of several bytes, where XX is the byte number, in decimal
* - XXG: Number of several bytes, where XX is the byte number, in decimal - subject to be swapped according to endianess
* - nB : table size over 1 byte, followed by the table of bytes
* - NB : table size over 2 bytes, followed by the table of bytes
*
* Example: "BBLH12BLnB" => 1 byte | 1 byte | 1 long | 1 short | 12-bytes table | 1 long | table size over 1 byte | n-bytes table
*
* Note: the function works in the same buffer
*
* @param[out] out Output Data Buffer
* @param[in] in Input Data Buffer
* @param[out] out_len Output size of packed data (in bytes)
* @param[in] in_len Input buffer size (in bytes)
* @param[in] format Parameters format
*
* @return Status of the packing operation
*****************************************************************************************
*/
uint8_t co_util_pack(uint8_t* out, uint8_t* in, uint16_t* out_len, uint16_t in_len, const char* format);
/**
****************************************************************************************
* @brief Unpack parameters from an unpacked buffer to a C structure
*
* This function unpacks parameters according to a specific format. It takes care of the
* endianess, padding, required by the compiler.
*
* By default input format is LSB but it can be changed with first character of format string
* - < : LSB input format
* - > : MSB input format
*
* Format strings are the mechanism used to specify the expected layout when packing and unpacking data. They are built
* up from Format Characters, which specify the type of data being packed/unpacked.
* - B : byte - 8bits value
* - H : word - 16bits value
* - L : long - 32-bits value
* - D : 24 bits value
* - XXB: table of several bytes, where XX is the byte number, in decimal
* - XXG: Number of several bytes, where XX is the byte number, in decimal - subject to be swapped according to endianess
* - nB : table size over 1 byte, followed by the table of bytes
* - NB : table size over 2 bytes, followed by the table of bytes
*
* Example: "BBLH12BLnB" => 1 byte | 1 byte | 1 long | 1 short | 12-bytes table | 1 long | table size over 1 byte | n-bytes table
*
* Note: the output buffer provided must be large enough to contain the unpacked data.
* Note2: if a NULL output buffer is provided, the function does not copy the unpacked parameters. It still parses the
* format string and input buffer to return the number of unpacked bytes. Can be used to compute the expected unpacked
* buffer size.
*
* @param[out] out Unpacked parameters buffer
* @param[in] in Packed parameters buffer
* @param[inout] out_len Input: buffer size / Output: size of unpacked data (in bytes)
* @param[in] in_len Size of the packed data (in bytes)
* @param[in] format Parameters format
*
* @return Status of the unpacking operation
*****************************************************************************************
*/
uint8_t co_util_unpack(uint8_t* out, uint8_t* in, uint16_t* out_len, uint16_t in_len, const char* format);
// void set_ble_mac_addr(struct bd_addr* addr);
// struct bd_addr* get_ble_mac_addr(void);
/// @} CO_UTILS
#endif // _CO_UTILS_H_
@@ -0,0 +1,46 @@
/**
****************************************************************************************
*
* @file co_version.h
*
* @brief Version definitions for BT5.1
*
* Copyright (C) RivieraWaves 2009-2018
*
*
****************************************************************************************
*/
#ifndef _CO_VERSION_H_
#define _CO_VERSION_H_
/**
****************************************************************************************
* @defgroup CO_VERSION Version Defines
* @ingroup COMMON
*
* @brief Bluetooth Controller Version definitions.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "co_bt.h" // BT standard definitions
/// RWBT SW Major Version
#define RWBT_SW_VERSION_MAJOR (BT52_VERSION)
/// RWBT SW Minor Version
#define RWBT_SW_VERSION_MINOR 0
/// RWBT SW Build Version
#define RWBT_SW_VERSION_BUILD 4
/// RWBT SW Major Version
#define RWBT_SW_VERSION_SUB_BUILD 0
/// @} CO_VERSION
#endif // _CO_VERSION_H_
+92
View File
@@ -0,0 +1,92 @@
/**
****************************************************************************************
*
* @file dbg.h
*
* @brief Debug function
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef DBG_H_
#define DBG_H_
/**
****************************************************************************************
* @addtogroup DBG
* @ingroup CONTROLLER
* @brief Debug
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // stack configuration
#include "dbg_swdiag.h" // sw profiling definitions
#include "dbg_trc.h" // debug tracer definition
/*
* FUNCTION DECLARATION
****************************************************************************************
*/
#define _DEBUG_ 0
#if CMD_TEST
#define TEST_LOGI(...) DEBUG(__VA_ARGS__)
#else
#define TEST_LOGI(...)
#endif
#if _DEBUG_
#define LOGI(...) DEBUG(__VA_ARGS__)
#define DUMP_DATA_PRINTF(data, length) printf_hexdump((uint8_t *)data, length)
#define LOGI_ERR(...) \
do { \
DEBUG("[%s] [%d]: ", __FILE__, __LINE__); \
DEBUG(__VA_ARGS__); \
} while (0)
#else
#define LOGI(...)
#define DUMP_DATA_PRINTF(data, length)
#define LOGI_ERR(...)
#endif
#define _TOSTRING(s) #s
#define TOSTRING(s) _TOSTRING(s)
/**
****************************************************************************************
* @brief Initialization of the BT Debug task
*
* This function initializes the the DBG task
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
****************************************************************************************
*/
void dbg_init(uint8_t init_type);
/**
****************************************************************************************
* @brief Send back to host status of platform reset request.
*
* @param status Reset error code
*
****************************************************************************************
*/
void dbg_platform_reset_complete(uint32_t error);
void printf_hexdump(const void *data, int length);
///@} DBG
#endif // DBG_H_
+153
View File
@@ -0,0 +1,153 @@
/**
****************************************************************************************
*
* @file dbg_iqgen.h
*
* @brief I&Q Samples Generator API.
*
* Copyright (C) RivieraWaves 2018
*
*
****************************************************************************************
*/
#ifndef DBG_IQGEN_H_
#define DBG_IQGEN_H_
/**
****************************************************************************************
* @addtogroup DBGIQGEN
* @ingroup IQ
* @brief Debug SW - I&Q samples Generator.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h"
#if BLE_IQ_GEN
#include "reg_iqgen.h" // I&Q sample generator register functions
/*
* CONSTANT DEFINITIONS
****************************************************************************************
*/
/// Maximum number of supported antenna patterns
#define DBG_IQGEN_MAX_ANTENNA (8)
/// bit defintitions for debug configuration
#define DBG_IQGEN_PATTERN_MODE_BIT (1<<0)
#define DBG_IQGEN_TIMING_MODE_BIT (1<<1)
#define DBG_IQGEN_ANT_ID_MODE_BIT (2<<1)
/// I&Q samples generation control
enum dbg_iqgen_ctnl
{
/// I&Q samples up count
DBG_IQGEN_UPCOUNT = 0,
/// I&Q samples down count
DBG_IQGEN_DOWNCOUNT = 1,
/// I&Q samples fixed value
DBG_IQGEN_FIXEDVAL = 2,
/// I&Q samples PRBS
DBG_IQGEN_PRBSPATTERN = 3,
};
/// I&Q samples generation antenna sweep pattern
enum dbg_iqgen_antenna_pattern
{
/// antenna up-sweep
DBG_IQGEN_ANT_UPSWEEP = 0,
/// antenna up-down sweep
DBG_IQGEN_ANT_UPDNSWEEP = 1,
};
/// I&Q samples generation timing mode
enum dbg_iqgen_timing_mode
{
/// 1us switching/sampling interval
DBG_IQGEN_1US_INTV = 0,
/// 2us switching/sampling interval
DBG_IQGEN_2US_INTV = 1,
};
/// antenna switch enable mode
enum dbg_iqgen_antenna_switch_mode
{
/// Accepts antenna ID switching inputs from baseband
DBG_IQGEN_BASEBAND_SWITCHING = 0,
/// Antenna switching is internally enabled
DBG_IQGEN_INTERNAL_SWITCHING = 1,
};
/*
* VARIABLE DECLARATION
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Enable I&Q sample generator
*
* @param[in] nb_antenna Number of antenna (valid range 1-8)
* @param[in] pattern_mode Antenna sweep pattern (@see enum dbg_iqgen_antenna_pattern)
* @param[in] timing_mode Timing interval mode (@see enum dbg_iqgen_timing_mode)
* @param[in] ant_switch_mode Antenna switching mode (@see enum dbg_iqgen_antenna_switch_mode)
*
****************************************************************************************
*/
void dbg_iqgen_config_enable(uint8_t nb_antenna, uint8_t pattern_mode, uint8_t timing_mode, uint8_t ant_switch_mode);
/**
****************************************************************************************
* @brief Disable I&Q sample generator
*
****************************************************************************************
*/
void dbg_iqgen_disable();
/**
****************************************************************************************
* @brief Configure I&Q samples for a specific antenna
*
* @param[in] antenna ID antenna id (valid range 0-7)
* @param[in] i_cntl configuration mode for I-samples (@see enum dbg_iqgen_cntl)
* @param[in] q_cntl configuration mode for Q-samples (@see enum dbg_iqgen_cntl)
* @param[in] i_val I-samples initial value
* @param[in] q_val Q-samples initial value
*
****************************************************************************************
*/
void dbg_iqgen_antenna_config(uint8_t antenna_id, uint8_t i_cntl, uint8_t q_cntl, uint8_t i_val, uint8_t q_val);
/**
****************************************************************************************
* @brief I&Q Generator configure
*
* @param[in] param configuration structure (@see hci_dbg_iqgen_cfg_cmd)
****************************************************************************************
*/
uint8_t dbg_iqgen_config(struct hci_dbg_iqgen_cfg_cmd const *cfg);
#endif //BLE_IQ_GEN
/// @} DBGIQGEN
#endif // DBG_IQGEN_H_
+212
View File
@@ -0,0 +1,212 @@
/**
****************************************************************************************
*
* @file dbg_mwsgen.h
*
* @brief MWS/WLAN Generator API.
*
* Copyright (C) RivieraWaves 2015
*
*
****************************************************************************************
*/
#ifndef DBG_MWSGEN_H_
#define DBG_MWSGEN_H_
/**
****************************************************************************************
* @addtogroup DBGMWSGEN
* @ingroup DBG
* @brief Debug SW - MWS/WLAN Generator.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h"
#if (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST)
#include "reg_mwsgen.h" // MWS Event Generator register functions
/*
* CONSTANT DEFINITIONS
****************************************************************************************
*/
#if (RW_WLAN_COEX)
/// WLAN coexistence disabled
#define DBG_COEX_WLAN_DISABLED 0
/// WLAN coexistence enabled
#define DBG_COEX_WLAN_ENABLED 1
#endif
#if (RW_MWS_COEX)
/// MWS coexistence disabled
#define DBG_COEX_MWS_DISABLED 0
/// MWS coexistence enabled
#define DBG_COEX_MWS_ENABLED 1
#endif
/*
* VARIABLE DECLARATION
****************************************************************************************
*/
#if (RW_WLAN_COEX_TEST)
extern uint32_t dbg_coex_scenario;
#endif // RW_WLAN_COEX_TEST
#if (RW_MWS_COEX_TEST)
extern uint32_t dbg_coex_scenario;
#endif // RW_MWS_COEX_TEST
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
#if (RW_MWS_COEX_TEST)
/**
****************************************************************************************
* @brief Set the scenario for the unitary testing.
*
* @param[in] scenario Scenario type
*
* @return none
*
****************************************************************************************
*/
uint8_t dbg_mwscoex_scen_set(uint32_t scenario);
/**
****************************************************************************************
* @brief Initialize and configure MWS event generator registers to be in MWS mode.
****************************************************************************************
*/
void dbg_mwsgen_init(void);
/**
****************************************************************************************
* @brief Configure MWS generator
*
* @param[in] period Period of the mws signal (us)
* @param[in] duty_cycle Duration of the high level (us)
* @param[in] tx_act Duration of the tx activity (us)
* @param[in] rx_act Duration of the rx activity (us)
*
****************************************************************************************
*/
void dbg_mwsgen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act);
/**
****************************************************************************************
* @brief Configure the WLAN COEX mode for BT.
*
* @param[in] txmode
* @param[in] rxmode
* @param[in] txmsk
* @param[in] rxmsk
* @param[in] txfmsk
* @param[in] rxfmsk
* @param[in] scanfmsk
* @param[in] knudge
*
****************************************************************************************
*/
void dbg_mws_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txfms, uint8_t rxfmsk, uint8_t scanfmsk, uint8_t knudge);
/**
****************************************************************************************
* @brief Start the MWS signal generator.
*
****************************************************************************************
*/
void dbg_mwsgen_start(void);
/**
****************************************************************************************
* @brief Stop the MWS signal generator.
*
****************************************************************************************
*/
void dbg_mwsgen_stop(void);
#endif // RW_MWS_COEX_TEST
#if (RW_WLAN_COEX_TEST)
/**
****************************************************************************************
* @brief Set the scenario for the unitary testing.
*
* @param[in] scenario Scenario type
*
* @return none
*
****************************************************************************************
*/
uint8_t dbg_wlcoex_scen_set(uint32_t scenario);
/**
****************************************************************************************
* @brief Initialize and configure MWS event generator registers to be in WLAN mode.
****************************************************************************************
*/
void dbg_wlangen_init(void);
/**
****************************************************************************************
* @brief Set the period and duty cycle for the wlrxbsy signal.
*
* @param[in] period Period of the wlrxbsy signal (us)
* @param[in] duty_cycle Duration of the high level (us)
* @param[in] tx_act Duration of the tx activity (us)
* @param[in] rx_act Duration of the rx activity (us)
*
****************************************************************************************
*/
void dbg_wlangen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act);
/**
****************************************************************************************
* @brief Configure the WLAN COEX mode for BT.
*
* @param[in] txmode
* @param[in] rxmode
* @param[in] txmsk
* @param[in] rxmsk
* @param[in] txthr
* @param[in] rxthr
* @param[in] pduration
* @param[in] pdelay
*
****************************************************************************************
*/
void dbg_wlan_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txthr, uint8_t rxthr, uint8_t pduration, uint8_t pdelay);
/**
****************************************************************************************
* @brief Start the wlrxbs signal generator.
*
****************************************************************************************
*/
void dbg_wlangen_start(void);
/**
****************************************************************************************
* @brief Stop the wlrxbs signal generator.
*
****************************************************************************************
*/
void dbg_wlangen_stop(void);
#endif // RW_WLAN_COEX_TEST
#endif // (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST)
/// @} DBGMWSGEN
#endif // DBG_MWSGEN_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,237 @@
/**
****************************************************************************************
*
* @file dbg_trc_config.h
*
* @brief Configuration of the Tracer module
*
* Copyright (C) RivieraWaves 2009-2016
*
****************************************************************************************
*/
#ifndef DBG_TRC_CONFIG_H_
#define DBG_TRC_CONFIG_H_
/**
****************************************************************************************
* @addtogroup TRACER
* @{
* @name Tracer module configuration
* @{
****************************************************************************************
*/
#if defined CFG_TRC_ALL
#define TRC_KE_MSG 1
#define TRC_KE_TMR 1
#define TRC_KE_EVT 1
#define TRC_MEM 1
#define TRC_SW_ASS 1
#define TRC_CUSTOM 1
#if (BLE_EMB_PRESENT || BT_EMB_PRESENT)
#define TRC_ARB 1
#define TRC_PROG 1
#define TRC_SLEEP 1
#else // (BLE_EMB_PRESENT || BT_EMB_PRESENT)
#define TRC_ARB 0
#define TRC_PROG 0
#define TRC_SLEEP 0
#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT)
#if (BLE_EMB_PRESENT)
#define TRC_CS_BLE 1
#define TRC_LLCP 1
#define TRC_LLC_STATE_TRANS 1
#define TRC_RX_DESC 1
#define TRC_ADV 1
#define TRC_ACL 1
#else /*(BLE_EMB_PRESENT)*/
#define TRC_CS_BLE 0
#define TRC_LLCP 0
#define TRC_LLC_STATE_TRANS 0
#define TRC_RX_DESC 0
#define TRC_ADV 0
#define TRC_ACL 0
#endif /*(BLE_EMB_PRESENT)*/
#if (BLE_EMB_PRESENT && BLE_HOST_PRESENT)
#define TRC_HCI 1
#else /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/
#define TRC_HCI 0
#endif /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/
#if (BLE_HOST_PRESENT)
#define TRC_L2CAP 1
#else
#define TRC_L2CAP 0
#endif /*(BLE_HOST_PRESENT)*/
#if (BT_EMB_PRESENT)
#define TRC_CS_BT 1
#define TRC_LMP 1
#define TRC_LC_STATE_TRANS 1
#else
#define TRC_CS_BT 0
#define TRC_LMP 0
#define TRC_LC_STATE_TRANS 0
#endif /*(BT_EMB_PRESENT)*/
#else /*(CFG_TRC_ALL)*/
#if defined CFG_TRC_KE_MSG
#define TRC_KE_MSG 1
#else
#define TRC_KE_MSG 0
#endif /*(CFG_TRC_KE_MSG)*/
#if defined CFG_TRC_KE_TMR
#define TRC_KE_TMR 1
#else
#define TRC_KE_TMR 0
#endif /*CFG_TRC_KE_TMR*/
#if defined CFG_TRC_KE_EVT
#define TRC_KE_EVT 1
#else
#define TRC_KE_EVT 0
#endif /*CFG_TRC_KE_EVT*/
#if defined CFG_TRC_MEM
#define TRC_MEM 1
#else
#define TRC_MEM 0
#endif /*CFG_TRC_MEM*/
#if defined CFG_TRC_SW_ASS
#define TRC_SW_ASS 1
#else
#define TRC_SW_ASS 0
#endif /*CFG_TRC_SW_ASS*/
#if defined CFG_TRC_CUSTOM
#define TRC_CUSTOM 1
#else
#define TRC_CUSTOM 0
#endif /*CFG_TRC_CUSTOM*/
#if (BLE_EMB_PRESENT)
#if defined CFG_TRC_CS_BLE
#define TRC_CS_BLE 1
#else
#define TRC_CS_BLE 0
#endif /*(CFG_TRC_CS_BLE)*/
#if defined CFG_TRC_LLCP
#define TRC_LLCP 1
#else
#define TRC_LLCP 0
#endif /*(CFG_TRC_LLCP)*/
#if defined CFG_TRC_LLC_STATE_TRANS
#define TRC_LLC_STATE_TRANS 1
#else
#define TRC_LLC_STATE_TRANS 0
#endif /*(CFG_TRC_LLC_STATE_TRANS)*/
#if defined CFG_TRC_ARB
#define TRC_ARB 1
#else
#define TRC_ARB 0
#endif /*CFG_TRC_ARB*/
#if defined CFG_TRC_RX_DESC
#define TRC_RX_DESC 1
#else
#define TRC_RX_DESC 0
#endif /*CFG_TRC_RX_DESC*/
#if defined CFG_TRC_PROG
#define TRC_PROG 1
#else
#define TRC_PROG 0
#endif /*CFG_TRC_PROG*/
#if defined CFG_TRC_SLEEP
#define TRC_SLEEP 1
#else
#define TRC_SLEEP 0
#endif /*CFG_TRC_SLEEP*/
#if defined CFG_TRC_ADV
#define TRC_ADV 1
#else
#define TRC_ADV 0
#endif /*(CFG_TRC_ADV)*/
#if defined CFG_TRC_ACL
#define TRC_ACL 1
#else
#define TRC_ACL 0
#endif /*(CFG_TRC_ACL)*/
#else /*(BLE_EMB_PRESENT)*/
#define TRC_CS_BLE 0
#define TRC_LLCP 0
#define TRC_LLC_STATE_TRANS 0
#define TRC_ARB 0
#define TRC_RX_DESC 0
#define TRC_PROG 0
#define TRC_SLEEP 0
#define TRC_ADV 0
#define TRC_ACL 0
#endif /*(BLE_EMB_PRESENT)*/
#if (BLE_EMB_PRESENT && BLE_HOST_PRESENT)
#if defined CFG_TRC_HCI
#define TRC_HCI 1
#else
#define TRC_HCI 0
#endif /*CFG_TRC_HCI*/
#else /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/
#define TRC_HCI 0
#endif /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/
#if (BLE_HOST_PRESENT)
#if defined CFG_TRC_L2CAP
#define TRC_L2CAP 1
#else
#define TRC_L2CAP 0
#endif /*CFG_TRC_L2CAP*/
#else /*BLE_HOST_PRESENT*/
#define TRC_L2CAP 0
#endif /*BLE_HOST_PRESENT*/
#if (BT_EMB_PRESENT)
#if defined CFG_TRC_CS_BT
#define TRC_CS_BT 1
#else
#define TRC_CS_BT 0
#endif /*CFG_TRC_CS_BT*/
#if defined CFG_TRC_LMP
#define TRC_LMP 1
#else
#define TRC_LMP 0
#endif /*CFG_TRC_LMP*/
#if defined CFG_TRC_LC_STATE_TRANS
#define TRC_LC_STATE_TRANS 1
#else
#define TRC_LC_STATE_TRANS 0
#endif /*CFG_TRC_LC_STATE_TRANS*/
#else /*BT_EMB_PRESENT*/
#define TRC_CS_BT 0
#define TRC_LMP 0
#define TRC_LC_STATE_TRANS 0
#endif /*BT_EMB_PRESENT*/
#endif /* CFG_TRC_ALL */
/// @} TRACER
#endif /* DBG_TRC_CONFIG_H_ */
+159
View File
@@ -0,0 +1,159 @@
/**
****************************************************************************************
*
* @file dbg_trc_int.h
*
* @brief This file contains definitions related to the Tracer module.
*
* Copyright (C) RivieraWaves 2009-2015
*
****************************************************************************************
*/
#ifndef DBG_TRC_INT_H_
#define DBG_TRC_INT_H_
/**
****************************************************************************************
* @addtogroup TRACER
* @{
****************************************************************************************
*/
#include "rwip_config.h"
#if (TRACER_PRESENT)
#include <stdint.h> // standard definitions
#include <stdbool.h> // boolean
/*
* DEFINES
****************************************************************************************
*/
///Channel index length
#define CHANNEL_ID_LEN 1
///lengths of trace packet fields
#define SEQ_NUM_LEN 2
#define TIMESTAMP_LEN 4
#define TRC_CODE_LEN 1
#define TRC_FIX_LEN \
CHANNEL_ID_LEN +\
TRC_MSG_HDR_LEN +\
SEQ_NUM_LEN +\
TIMESTAMP_LEN +\
TRC_CODE_LEN
/**
****************************************************************************************
* @brief Convenient wrapper to trc_mem_alloc()
*
* This macro calls trc_mem_alloc() passing as parameter the length of the trace packet
*
* @param[in] trace_pay Trace payload length
*
* @return Pointer to trace code field(or NULL if the trace cannot be written)
****************************************************************************************
*/
#define TRC_MEM_ALLOC(trace_pay) \
dbg_trc_mem_alloc(TRC_FIX_LEN + trace_pay)
typedef uint8_t trc_id_t;
typedef uint8_t trc_opcode_t;
/*
* STRUCTURES DEFINITIONS
****************************************************************************************
*/
///Tracer Environment context structure
struct dbg_trc_env_tag
{
/// Current tracer configuration word
uint32_t curr_cw;
/// Compiled tracer configuration word
uint32_t compiled_cw;
};
/*
* GLOBAL VARIABLE DEFINITIONS
****************************************************************************************
*/
///Tracer environment context
extern struct dbg_trc_env_tag dbg_trc_env;
/*
* TRANSPORT LAYER FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief initialize tracer TL
****************************************************************************************
*/
void dbg_trc_tl_init();
/**
****************************************************************************************
* @brief trigger the transmission of tracer packets
****************************************************************************************
*/
void dbg_trc_tx_trigger(void);
/*
* MEMORY FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize tracer memory
****************************************************************************************
*/
void dbg_trc_mem_init();
/**
****************************************************************************************
* @brief Try to write a trace in memory.
* @param[in] trace_len Trace packet length (expressed in bytes)
*
* @return Pointer to trace code field(or NULL if the trace cannot be written)
****************************************************************************************
*/
uint8_t *dbg_trc_mem_alloc(uint16_t const trace_len);
/**
****************************************************************************************
* @brief Try to read a trace from the memory.
*
* @return Pointer to the total size of the trace (or NULL if the trace cannot be read)
****************************************************************************************
*/
uint8_t *dbg_trc_mem_read();
/**
****************************************************************************************
* @brief Deallocate a trace from the memory.
*
* This function marks the trace block pointed by the reading pointer as invalid and moves
* it to the next trace block
*
****************************************************************************************
*/
void dbg_trc_mem_dealloc();
/**
****************************************************************************************
* @brief Initialization of the tracer
*
* This function initializes the tracer
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
****************************************************************************************
*/
void dbg_trc_init(uint8_t init_type);
#endif /* TRACER_PRESENT */
/// @} TRACER
#endif /* DBG_TRC_INT_H_ */
@@ -0,0 +1,132 @@
/**
****************************************************************************************
*
* @file ecc_p256.h
*
* @brief ECC functions for P256
*
* Copyright (C) RivieraWaves 2009-2015
*
****************************************************************************************
*/
#ifndef ECC_P256_H_
#define ECC_P256_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h"
#include <stdint.h>
#include <stdbool.h>
#include "ke_task.h"
/*
* DEFINES
****************************************************************************************
*/
#define ECC_PUBLICKEY_GENERATION 0x01
#define ECC_DHKEY_GENERATION 0x02
/*
* STRUCTURE DEFINITIONS
****************************************************************************************
*/
/// Multiplication result message structure
/*@TRACE*/
struct ecc_result_ind
{
uint8_t key_res_x[32];
uint8_t key_res_y[32];
};
/*
* VARIABLE DECLARATION
****************************************************************************************
*/
/// Debug Private Key
extern const uint8_t DebugE256SecretKey[32];
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize Elliptic Curve algorithm
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
****************************************************************************************
*/
void ecc_init(uint8_t init_type);
/**
****************************************************************************************
* @brief Generate a Secret Key compliant with ECC P256 algorithm
*
* If key is forced, just check its validity
*
* @param[out] secret_key Private key - MSB First
* @param[in] forced True if provided key is forced, else generate it.
****************************************************************************************
*/
void ecc_gen_new_secret_key(uint8_t* secret_key, bool forced);
/**
****************************************************************************************
* @brief Generate a new Public key pair using ECC P256 algorithm
*
* @param[in] secret_key Private key - MSB First
* @param[in] blocking Force to run full algorithm without continue mode
****************************************************************************************
*/
void ecc_gen_new_public_key(uint8_t* secret_key256, ke_msg_id_t msg_id, ke_task_id_t task_id);
/**
****************************************************************************************
* @brief Generate a new DHKey using ECC P256 algorithm
*
* @param[in] key_type Type of key to generate (1: public key | 2: DH key)
* @param[in] secret_key Private key - MSB First
* @param[in] public_key_x Peer public key x coordinate - LSB First
* @param[in] public_key_y Peer public key y coordinate - LSB First
* @param[in] msg_id Message task ID for the result indication
* @param[in] task_id Client task ID (Task type + instance)
* @param[in] public_key_valid True: public key is valid, False: public key uncertain
*
* @return status 0 if key generation is started, > 0 otherwise
****************************************************************************************
*/
uint8_t ecc_generate_key256(uint8_t key_type, const uint8_t* secret_key, const uint8_t* public_key_x, const uint8_t* public_key_y, ke_msg_id_t msg_id, ke_task_id_t task_id, bool public_key_valid);
/**
****************************************************************************************
* @brief Abort a current DHKey generation procedure
*
* @param[in] task_id Client task ID (Task type + instance)
****************************************************************************************
*/
void ecc_abort_key256_generation(ke_task_id_t task_id);
/**
****************************************************************************************
* @brief Retrieve debug private and public keys
*
* @param[out] secret_key Private key - MSB First
* @param[out] pub_key_x Public key x coordinate - LSB First
* @param[out] pub_key_y Public key y coordinate - LSB First
****************************************************************************************
*/
void ecc_get_debug_Keys(uint8_t*secret_key, uint8_t* pub_key_x, uint8_t* pub_key_y);
#endif /* ECC_P256_H_ */
@@ -0,0 +1,593 @@
/*!
* \file xc6xxx_fmc_spi.c
*
* \brief Target xc6xxx hal fmc spi implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx_fmc_spi.h"
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void *ram_memcpy_bytes(void *dst, const void *src, int size)
{
if(dst == NULL || src == NULL || size <= 0)
return NULL;
char *pdst = (char *)dst;
char *psrc = (char *)src;
if(pdst > psrc && pdst < psrc + size) {
pdst = pdst + size - 1;
psrc = psrc + size - 1;
while(size--)
*pdst-- = *psrc--;
} else {
while(size--)
*pdst++ = *psrc++;
}
return dst;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_Status_Wait_Idle(void)
{
uint32_t reg = 0;
do {
__READ_REG32(BLE_COMN_AGC_REG_OUT0, reg);
} while(!(reg & FMC_IDLE_Msk));
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_WriteNByte(uint8_t* txdata, uint16_t len)
{
if(len == 0) return;
uint16_t n;
uint8_t remain = len % 4;
uint16_t cnt = len / 4;
uint32_t mid_data[64+1] = { 0 };
if(cnt != 0) {
for(n=0; n<cnt; n++) {
mid_data[n] = ((txdata[n*4] << 24) | (txdata[n*4+1] << 16) |
(txdata[n*4+2] << 8) | txdata[n*4+3]);
}
}
if(remain != 0) {
for(n=0; n<remain; n++) {
mid_data[cnt] |= (txdata[cnt*4+n] << (24-8*n));
}
}
if(cnt != 0) {
if(remain != 0)
cnt = cnt + 1;
for(n=0; n<cnt; n++)
__FMC_SPI_SendByte(mid_data[n]);
} else {
__FMC_SPI_SendByte(mid_data[0]);
}
while(!(*FMC_SSI_STS & FMC_SPI_STS_REG_FLAG_TFE) ||
(*FMC_SSI_STS & FMC_SSI_STS_BUSY));
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_ReadNByte(uint8_t* rxdata, uint16_t len)
{
if(len == 0) return;
uint16_t n;
uint8_t remain = len % 4;
uint16_t cnt = len / 4;
uint32_t mid_data = 0;
if(cnt != 0) {
for(n=0; n<cnt; n++) {
mid_data = __FMC_SPI_RecvByte( );
// printf("0_rcv: 0x%08x\n", mid_data);
rxdata[n*4] = mid_data >> 24;
rxdata[n*4+1] = mid_data >> 16;
rxdata[n*4+2] = mid_data >> 8;
rxdata[n*4+3] = mid_data;
}
}
if(remain != 0) {
mid_data = __FMC_SPI_RecvByte( );
// printf("1_rcv: 0x%08x\n", mid_data);
for(n=0; n<remain; n++) {
rxdata[cnt*4+n] = mid_data >> 24;
rxdata[cnt*4+1+n] = mid_data >> 16;
rxdata[cnt*4+2+n] = mid_data >> 8;
rxdata[cnt*4+3+n] = mid_data;
}
}
while(*FMC_SSI_STS & FMC_SPI_STS_REG_FLAG_RFNE) {
mid_data = __FMC_SPI_RecvByte( );
}
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Enable(uint8_t dfs)
{
__WRITE_REG32(FMC_SSI_EN, 0);
if(dfs != 0x1f) {
uint32_t reg= *FMC_SSI_CTRL0;
__CLEAR_BIT(reg, (uint32_t)0x1f);
__SET_BIT(reg, (uint32_t)dfs);
__WRITE_REG32(FMC_SSI_CTRL0, reg);
}
__WRITE_REG32(FMC_SSI_EN, 1);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Disable(void)
{
__WRITE_REG32(FMC_SSI_EN, 0);
uint32_t reg= *FMC_SSI_CTRL0;
__CLEAR_BIT(reg, (uint32_t)0x1f);
__SET_BIT(reg, (uint32_t)0x1f);
__WRITE_REG32(FMC_SSI_CTRL0, reg);
__WRITE_REG32(FMC_SSI_EN, 1);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Init_Oprt(void)
{
/* BT_CLK 时钟控制寄存器 */
__WRITE_REG32(CPR_BT_CLK_CTL, ((1<<4) | ((1<<4)<<16)));
/* BT_MODEM_CLK 时钟控制寄存器 */
__WRITE_REG32(CPR_BT_MODEM_CTL, ((1<<4) | ((1<<4)<<16)));
/* 配置 BT_PCLK_EN 使能 */
__SET_BIT(*CPR_CTLAPBCLKEN_GRCTL, ((1<<10) | ((1<<10)<<16)));
__WRITE_REG32(CPR_SSI0_MCLK_CTL, ((1<<16) | ((0<<4) | ((1<<16)<<4))));
__WRITE_REG32(CPR_RSTCTL_SUBRST_SW, ((0<<2) | ((1<<2)<<16)));
__WRITE_REG32(CPR_RSTCTL_SUBRST_SW, ((1<<2) | ((1<<2)<<16)));
FMC_Status_Wait_Idle( );
__WRITE_REG32(FMC_SSI_EN, 0);
uint32_t reg= *FMC_SSI_CTRL0;
__CLEAR_BIT(reg, (uint32_t)0x1f);
__SET_BIT(reg, (uint32_t)0x1f);
__WRITE_REG32(FMC_SSI_CTRL0, reg);
*FMC_SSI_CTRL0 &= ~((uint32_t)0x01 << 14);
__WRITE_REG32(FMC_SSI_SE, 1);
__WRITE_REG32(FMC_SSI_IE, 0);
__WRITE_REG32(FMC_SSI_BAUD, 2);
__WRITE_REG32(FMC_SSI_TXFTL, 0);
__WRITE_REG32(FMC_SSI_RXFTL, 0);
__WRITE_REG32(FMC_SSI_EN, 1);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_PowerDown(void)
{
FMC_Status_Wait_Idle( );
uint8_t cmd[4];
cmd[0] = 0;
cmd[1] = 0;
cmd[2] = 0;
cmd[3] = CMD_PWRDWN;
FMC_SPI_Enable(0x07);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_Disable( );
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_WakeUp(void)
{
FMC_Status_Wait_Idle( );
uint8_t cmd[4];
cmd[0] = 0;
cmd[1] = 0;
cmd[2] = 0;
cmd[3] = CMD_RELEASE_PWRDWN;
FMC_SPI_Enable(0x07);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_Disable( );
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE uint8_t FMC_SPI_Flash_Status(void)
{
FMC_Status_Wait_Idle( );
uint8_t cmd[2] = { 0 };
uint8_t sta[4] = { 0xff, 0xff, 0xff, 0xff };
cmd[0] = CMD_READ_STATUS;
cmd[1] = 0xff;
FMC_SPI_Enable(0x1f);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_ReadNByte(sta, sizeof(sta));
FMC_SPI_Disable( );
return sta[1];
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_Wait_Busy(void)
{
while(( FMC_SPI_Flash_Status( ) & 0x01 ));
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_Write_Enable(void)
{
FMC_Status_Wait_Idle( );
uint8_t cmd[4] = { 0 };
cmd[0] = 0;
cmd[1] = 0;
cmd[2] = 0;
cmd[3] = CMD_WRITE_ENABLE;
FMC_SPI_Enable(0x07);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_Disable( );
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_Erase_Sector(uint32_t Dst_Addr)
{
// FMC_Status_Wait_Idle( );
FMC_SPI_Flash_Wait_Busy( );
FMC_SPI_Flash_Write_Enable( );
FMC_SPI_Flash_Wait_Busy( );
uint8_t cmd[4] = { 0 };
cmd[0] = CMD_SECTOR_ERASE;
cmd[1] = Dst_Addr>>16;
cmd[2] = Dst_Addr>>8;
cmd[3] = Dst_Addr;
FMC_SPI_Enable(0x1f);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_Disable( );
FMC_SPI_Flash_Wait_Busy( );
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_WritePage(uint32_t WriteAddr, uint8_t *data, uint16_t size)
{
if(size > FLASH_PAGE_SIZE)
return;
uint32_t addr = WriteAddr;
uint8_t cmd[16+4] = { 0 };
for(uint8_t i=0; i<16; i++) {
FMC_SPI_Flash_Wait_Busy( );
FMC_SPI_Flash_Write_Enable( );
FMC_SPI_Flash_Wait_Busy( );
cmd[0] = CMD_PAGE_PROGRAM;
cmd[1] = addr >> 16;
cmd[2] = addr >> 8;
cmd[3] = addr;
ram_memcpy_bytes(&cmd[4], data+i*16, 16);
FMC_Status_Wait_Idle( );
FMC_SPI_Enable(0x1f);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
addr += 16;
}
FMC_SPI_Flash_Wait_Busy( );
FMC_SPI_Disable( );
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_ReadPage(uint32_t ReadAddr, uint8_t *data, uint16_t size)
{
if(size > FLASH_PAGE_SIZE)
return;
FMC_Status_Wait_Idle( );
uint8_t cmd[16+4] = { 0 };
uint8_t mid[16+4] = { 0 };
uint16_t rx_idx = 0;
uint32_t addr = ReadAddr;
for(uint8_t i=0; i<16; i++) {
cmd[0] = CMD_READ_DATA;
cmd[1] = addr >> 16;
cmd[2] = addr >> 8;
cmd[3] = addr;
FMC_SPI_Enable(0x1f);
FMC_SPI_WriteNByte(cmd, 20); //sizeof(cmd)
FMC_SPI_ReadNByte(mid, 20); //sizeof(mid)
ram_memcpy_bytes(&data[rx_idx], mid+4, 16);
addr += 16;
rx_idx += 16;
}
FMC_SPI_Disable( );
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE uint8_t FMC_SPI_FlashWrite(uint32_t writeAddr, uint8_t *buff, uint16_t len)
{
uint32_t cur_addr = writeAddr;
uint32_t end_addr = writeAddr + len;
uint16_t wt_len = 0;
uint16_t CurPageNum = 0; //本次数据存储所占用的当前页号
uint32_t CurStartPsr = 0; //本次地址在 当前页所占的位置
uint8_t temp_buff[FLASH_PAGE_SIZE] = { 0 };
while (cur_addr != end_addr) {
/* code */
CurPageNum = CUR_PAGE_NUM(cur_addr);
CurStartPsr = CUR_START_PSR(cur_addr);
FMC_SPI_Flash_ReadPage(CurPageNum*FLASH_PAGE_SIZE, temp_buff, FLASH_PAGE_SIZE);
if(CurStartPsr) {
ram_memcpy_bytes(&temp_buff[CurStartPsr], buff+wt_len, (256-CurStartPsr)>len-wt_len? len-wt_len:(256-CurStartPsr));
wt_len += wt_len + ((256-CurStartPsr)>len-wt_len? len-wt_len:(256-CurStartPsr));
cur_addr += wt_len;
} else {
ram_memcpy_bytes(temp_buff, buff+wt_len, len-wt_len>256? 256:len-wt_len);
cur_addr += (len-wt_len>256? 256:len-wt_len);
wt_len += (len-wt_len>256? 256:len-wt_len);
}
FMC_SPI_Flash_WritePage(CurPageNum*FLASH_PAGE_SIZE, temp_buff, FLASH_PAGE_SIZE);
}
return 0;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
* @return[out]
*
****************************************************************************************
*/
__RAM_CODE uint8_t FMC_SPI_FlashRead(uint32_t readAddr, uint8_t *buff, uint16_t len)
{
uint32_t cur_addr = readAddr;
uint32_t end_addr = readAddr + len;
uint16_t rd_len = 0;
uint16_t CurPageNum = 0; //本次数据存储所占用的当前页号
uint32_t CurStartPsr = 0; //本次地址在 当前页所占的位置
uint8_t temp_buff[FLASH_PAGE_SIZE] = { 0 };
while (cur_addr != end_addr) {
CurPageNum = CUR_PAGE_NUM(cur_addr);
CurStartPsr = CUR_START_PSR(cur_addr);
FMC_SPI_Flash_ReadPage(CurPageNum*FLASH_PAGE_SIZE, temp_buff, FLASH_PAGE_SIZE);
if(CurStartPsr) {
ram_memcpy_bytes(buff, &temp_buff[CurStartPsr], (256-CurStartPsr)>len-rd_len? len-rd_len:(256-CurStartPsr));
rd_len += rd_len + ((256-CurStartPsr)>len-rd_len? len-rd_len:(256-CurStartPsr));
cur_addr += rd_len;
} else {
ram_memcpy_bytes(buff+rd_len, temp_buff, len-rd_len>256? 256:len-rd_len);
cur_addr += (len-rd_len>256? 256:len-rd_len);
rd_len += (len-rd_len>256? 256:len-rd_len);
}
}
return 0;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_RUID(uint8_t *ruid)
{
FMC_Status_Wait_Idle( );
FMC_SPI_Flash_Wait_Busy( );
uint8_t cmd[21] = { 0 };
uint8_t id[21] = { 0 };
cmd[0] = CMD_RUID;
cmd[1] = 0xff;
cmd[2] = 0xff;
cmd[3] = 0xff;
cmd[4] = 0xff;
FMC_SPI_Enable(0x1f);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_ReadNByte(id, sizeof(id));
FMC_SPI_Disable( );
ram_memcpy_bytes(ruid, &id[5], 16);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
__RAM_CODE void FMC_SPI_Flash_RDID(uint8_t *rdid)
{
FMC_Status_Wait_Idle( );
FMC_SPI_Flash_Wait_Busy( );
uint8_t cmd[4] = { 0 };
uint8_t id[4] = { 0 };
cmd[0] = CMD_RDID;
cmd[1] = 0xff;
cmd[2] = 0xff;
cmd[3] = 0xff;
FMC_SPI_Enable(0x1f);
FMC_SPI_WriteNByte(cmd, sizeof(cmd));
FMC_SPI_ReadNByte(id, sizeof(id));
FMC_SPI_Disable( );
ram_memcpy_bytes(rdid, &id[1], 3);
}
@@ -0,0 +1,145 @@
/*!
* \file xc6xxx_fmc_spi.h
*
* \brief The header of xc6xxx_fmc_spi.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC6xxx_FMC_SPI_H_
#define __XC6xxx_FMC_SPI_H_
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define __RAM_CODE __attribute__((section("ram_code")))
#define __WRITE_REG32(REG, VAL) ((*REG) = (VAL))
#define __READ_REG32(REG, VAL) ((VAL) = (*REG))
#define __SET_BIT(REG, BIT) ((REG) |= (BIT))
#define __CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
// Register Address Definition
#define CPR_BASE 0x40000000UL
#define FMC_BASE 0x51000000UL
#define BLE_COMMON_BASE 0x53022000UL
#define CPR_BT_CLK_CTL ((volatile uint32_t *)(CPR_BASE + 0x40))
#define CPR_BT_MODEM_CTL ((volatile uint32_t *)(CPR_BASE + 0x48))
#define CPR_SSI0_MCLK_CTL ((volatile uint32_t *)(CPR_BASE + 0x50))
#define CPR_CTLAPBCLKEN_GRCTL ((volatile uint32_t *)(CPR_BASE + 0x70))
#define CPR_RSTCTL_SUBRST_SW ((volatile uint32_t *)(CPR_BASE + 0x104))
#define FMC_SSI_CTRL0 ((volatile uint32_t *)(FMC_BASE + 0x00))
#define FMC_SSI_CTRL1 ((volatile uint32_t *)(FMC_BASE + 0x04))
#define FMC_SSI_EN ((volatile uint32_t *)(FMC_BASE + 0x08))
#define FMC_SSI_SE ((volatile uint32_t *)(FMC_BASE + 0x10))
#define FMC_SSI_BAUD ((volatile uint32_t *)(FMC_BASE + 0x14))
#define FMC_SSI_TXFTL ((volatile uint32_t *)(FMC_BASE + 0x18))
#define FMC_SSI_RXFTL ((volatile uint32_t *)(FMC_BASE + 0x1C))
#define FMC_SSI_TXFL ((volatile uint32_t *)(FMC_BASE + 0x20))
#define FMC_SSI_RXFL ((volatile uint32_t *)(FMC_BASE + 0x24))
#define FMC_SSI_STS ((volatile uint32_t *)(FMC_BASE + 0x28))
#define FMC_SSI_IE ((volatile uint32_t *)(FMC_BASE + 0x2C))
#define FMC_SSI_DATA ((volatile uint32_t *)(FMC_BASE + 0x60))
#define BLE_COMN_AGC_REG_OUT0 ((volatile uint32_t *)(BLE_COMMON_BASE + 0x28))
#define FMC_IDLE_Pos (31U)
#define FMC_IDLE_Msk (1UL << FMC_IDLE_Pos)
#define FMC_IDLE_STATUS FMC_IDLE_Msk
#define FMC_SSI_STS_BUSY (1UL)
#define FMC_SSI_STS_REG_TFE_Pos (2UL)
#define FMC_SSI_STS_REG_TFE_EMPTY (1UL << FMC_SSI_STS_REG_TFE_Pos) /*!< 发送 FIFO 空. */
#define FMC_SPI_STS_REG_FLAG_TFE ((uint16_t)FMC_SSI_STS_REG_TFE_EMPTY)
#define FMC_SSI_STS_REG_RFNE_Pos (3UL) /*!< Position of RFNE field. */
#define FMC_SSI_STS_REG_RFNE_NOT_EMPTY (1UL << FMC_SSI_STS_REG_RFNE_Pos) /*!<接收 FIFO 非空 */
#define FMC_SPI_STS_REG_FLAG_RFNE ((uint16_t)FMC_SSI_STS_REG_RFNE_NOT_EMPTY)
#define CMD_READ_DATA (uint8_t)0x03
#define CMD_READ_STATUS (uint8_t)0x05
#define CMD_CHIP_ERASE (uint8_t)0xc7
#define CMD_WRITE_ENABLE (uint8_t)0x06
#define CMD_WRITE_DISABLE (uint8_t)0x04
#define CMD_PAGE_PROGRAM (uint8_t)0x02
#define CMD_BLOCK_ERASE (uint8_t)0xD8
#define CMD_SECTOR_ERASE (uint8_t)0x20
#define CMD_PAGE_ERASE (uint8_t)0x81
#define CMD_RELEASE_PWRDWN (uint8_t)0xAB
#define CMD_PWRDWN (uint8_t)0xB9
#define CMD_RUID (uint8_t)0x4B
#define CMD_RDID (uint8_t)0x9F
#define FLASH_PAGE_SIZE 256
#define CUR_PAGE_NUM(addr) (addr/FLASH_PAGE_SIZE)
#define CUR_START_PSR(addr) (addr%FLASH_PAGE_SIZE)
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
__RAM_CODE static inline void __FMC_SPI_SendByte(uint32_t byte)
{
*FMC_SSI_DATA = byte;
}
__RAM_CODE static inline uint32_t __FMC_SPI_RecvByte(void)
{
return (uint32_t)(*FMC_SSI_DATA);
}
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
__RAM_CODE void FMC_SPI_Init_Oprt(void);
__RAM_CODE void FMC_SPI_Flash_PowerDown(void);
__RAM_CODE void FMC_SPI_Flash_WakeUp(void);
__RAM_CODE void FMC_SPI_Flash_Wait_Busy(void);
__RAM_CODE void FMC_SPI_Flash_Write_Enable(void);
__RAM_CODE void FMC_SPI_Flash_Erase_Sector(uint32_t Dst_Addr);
__RAM_CODE void FMC_SPI_Flash_Erase_Page(uint32_t Dst_Addr);
__RAM_CODE void FMC_SPI_Flash_WritePage(uint32_t WriteAddr, uint8_t *data, uint16_t size);
__RAM_CODE void FMC_SPI_Flash_ReadPage(uint32_t ReadAddr, uint8_t *data, uint16_t size);
__RAM_CODE uint8_t FMC_SPI_FlashWrite(uint32_t writeAddr, uint8_t *buff, uint16_t len);
__RAM_CODE uint8_t FMC_SPI_FlashRead(uint32_t readAddr, uint8_t *buff, uint16_t len);
__RAM_CODE void FMC_SPI_Flash_RUID(uint8_t *ruid);
__RAM_CODE void FMC_SPI_Flash_RDID(uint8_t *rdid);
#ifdef __cplusplus
}
#endif
#endif /* __XC6xxx_FMC_SPI_H_ */
+136
View File
@@ -0,0 +1,136 @@
/**
****************************************************************************************
*
* @file h4tl.h
*
* @brief H4 UART Transport Layer header file.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef H4TL_H_
#define H4TL_H_
/**
****************************************************************************************
* @addtogroup H4TL H4 UART Transport Layer
* @ingroup H4TL
* @brief H4 UART Transport Layer
*
* This module creates the abstraction between External UART driver and HCI generic functions
* (designed for H4 UART transport layer).
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // stack configuration
#if (H4TL_SUPPORT)
#include "rwip.h" // SW interface
#include <stdint.h> // standard integer definition
#include <stdbool.h> // standard boolean definition
/*
* DEFINES
****************************************************************************************
*/
/// Size of the logical channel identifier for H4 messages
#define H4TL_LOGICAL_CHANNEL_LEN (1)
/**
* Number of H4TL interfaces
*
* * NB=2: AHI and HCI: for Host-only stack with external app
* - HCI has index 0
* - AHI has index 1
* * NB=1: AHI or HCI: for all other partitions
*
* Note: it is not possible to have no channel (H4TL must not be included in build in this case)
*/
#if (!BLE_EMB_PRESENT && HCI_TL_SUPPORT && AHI_TL_SUPPORT)
#define H4TL_NB_CHANNEL 2
#else // (!BLE_EMB_PRESENT && HCI_TL_SUPPORT && AHI_TL_SUPPORT)
#define H4TL_NB_CHANNEL 1
#endif // (!BLE_EMB_PRESENT && HCI_TL_SUPPORT && AHI_TL_SUPPORT)
/*
* GLOBAL VARIABLE DECLARATIONS
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief H4TL transport initialization.
*
* Puts the External Interface driver in reception, waiting for simple 1 byte message type. Space for
* reception is allocated with ke_msg_alloc and the pointer is handed to env.rx. RX
* interrupt is enabled.
*
* @param[in] tl_type Transport Layer Interface (@see enum h4tl_itf)
* @param[in] eif External interface API
*
*****************************************************************************************
*/
void h4tl_init(uint8_t tl_type, const struct rwip_eif_api* eif);
/**
****************************************************************************************
* @brief H4TL write function.
*
* @param[in] type Type of the buffer to be transmitted. It can take one of the following
* values:
* - @ref HCI_EVT_MSG_TYPE for event message
* - @ref HCI_ACL_MSG_TYPE for ACL data
* - @ref HCI_SYNC_MSG_TYPE for synchronous data
*
* @param[in] buf Pointer to the buffer to be transmitted. @note The buffer passed as
* parameter must have one free byte before the first payload byte, so that the H4TL
* module can put the type byte as first transmitted data.
*
* @param[in] len Length of the buffer to be transmitted.
* @param[in] tx_callback Callback for indicating the end of transfer
*****************************************************************************************
*/
void h4tl_write(uint8_t type, uint8_t *buf, uint16_t len, void (*tx_callback)(void));
/**
****************************************************************************************
* @brief Start External Interface input flow
*
*****************************************************************************************
*/
void h4tl_start(void);
/**
****************************************************************************************
* @brief Stop External Interface input flow if possible
*
* @return true if External Interface flow was stopped, false otherwise
*****************************************************************************************
*/
bool h4tl_stop(void);
#endif //H4TL_SUPPORT
/// @} H4TL
#endif // H4TL_H_
+102
View File
@@ -0,0 +1,102 @@
/**
****************************************************************************************
*
* @file ke.h
*
* @brief This file contains the definition of the kernel environment.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_H_
#define _KE_H_
/**
****************************************************************************************
* @addtogroup ENV Environment
* @ingroup KERNEL
* @brief Kernel Environment
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // stack configuration
#include <stdbool.h> // standard boolean definitions
#include <stdint.h> // standard integer definitions
/*
* ENUMERATION
****************************************************************************************
*/
/// Kernel Error Status
enum KE_STATUS
{
KE_SUCCESS = 0,
KE_FAIL
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief This function performs all the initializations of the kernel.
*
* It initializes first the heap, then the message queues and the events. Then if required
* it initializes the trace.
*
****************************************************************************************
*/
void ke_init(void);
/**
****************************************************************************************
* @brief This function flushes all messages currently pending in the kernel.
*
****************************************************************************************
*/
void ke_flush(void);
/**
****************************************************************************************
* @brief This function checks if sleep is possible or kernel is processing
*
* @return True if sleep is allowed, false otherwise
****************************************************************************************
*/
bool ke_sleep_check(void);
#if (KE_PROFILING)
/**
****************************************************************************************
* @brief This function gets the statistics of the kernel usage.
*
* @param[out] max_msg_sent Max message sent
* @param[out] max_msg_saved Max message saved
* @param[out] max_timer_used Max timer used
* @param[out] max_heap_used Max heap used
****************************************************************************************
*/
enum KE_STATUS ke_stats_get(uint8_t* max_msg_sent,
uint8_t* max_msg_saved,
uint8_t* max_timer_used,
uint16_t* max_heap_used);
#endif //KE_PROFILING
/// @} KE
#endif // _KE_H_
+152
View File
@@ -0,0 +1,152 @@
/**
****************************************************************************************
*
* @file ke_event.h
*
* @brief This file contains the definition related to kernel events.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_EVENT_H_
#define _KE_EVENT_H_
/**
****************************************************************************************
* @addtogroup EVT Events and Schedule
* @ingroup KERNEL
* @brief Event scheduling module.
*
* The KE_EVT module implements event scheduling functions. It can be used to
* implement deferred actions.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // stack configuration
#include <stdint.h> // standard integer definition
/*
* CONSTANTS
****************************************************************************************
*/
/// Status of ke_task API functions
enum KE_EVENT_STATUS
{
KE_EVENT_OK = 0,
KE_EVENT_FAIL,
KE_EVENT_UNKNOWN,
KE_EVENT_CAPA_EXCEEDED,
KE_EVENT_ALREADY_EXISTS,
};
/*
* TYPE DEFINITION
****************************************************************************************
*/
/*
* FUNCTION PROTOTYPES
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize Kernel event module.
****************************************************************************************
*/
void ke_event_init(void);
/**
****************************************************************************************
* @brief Register an event callback.
*
* @param[in] event_type Event type.
* @param[in] p_callback Pointer to callback function.
*
* @return Status
****************************************************************************************
*/
uint8_t ke_event_callback_set(uint8_t event_type, void (*p_callback)(void));
/**
****************************************************************************************
* @brief Set an event
*
* This primitive sets one event. It will trigger the call to the corresponding event
* handler in the next scheduling call.
*
* @param[in] event_type Event to be set.
****************************************************************************************
*/
void ke_event_set(uint8_t event_type);
/**
****************************************************************************************
* @brief Clear an event
*
* @param[in] event_type Event to be cleared.
****************************************************************************************
*/
void ke_event_clear(uint8_t event_type);
/**
****************************************************************************************
* @brief Get the status of an event
*
* @param[in] event_type Event to get.
*
* @return Event status (0: not set / 1: set)
****************************************************************************************
*/
uint8_t ke_event_get(uint8_t event_type);
/**
****************************************************************************************
* @brief Get all event status
*
* @return Events bit field
****************************************************************************************
*/
uint32_t ke_event_get_all(void);
/**
****************************************************************************************
* @brief Flush all pending events.
****************************************************************************************
*/
void ke_event_flush(void);
/**
****************************************************************************************
* @brief Event scheduler entry point.
*
* This primitive is the entry point of Kernel event scheduling.
****************************************************************************************
*/
void ke_event_schedule(void);
/// @} EVT
#endif //_KE_EVENT_H_
+153
View File
@@ -0,0 +1,153 @@
/**
****************************************************************************************
*
* @file ke_mem.h
*
* @brief API for the heap management module.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_MEM_H_
#define _KE_MEM_H_
#include "rwip_config.h" // IP configuration
#include <stdint.h> // standard integer
#include <stdbool.h> // standard includes
/**
****************************************************************************************
* @defgroup MEM Memory
* @ingroup KERNEL
* @brief Heap management module.
*
* This module implements heap management functions that allow initializing heap,
* allocating and freeing memory.
*
* @{
****************************************************************************************
*/
// forward declarations
struct mblock_free;
/**
****************************************************************************************
* @brief Heap initialization.
*
* This function performs the following operations:
* - sanity checks
* - check memory allocated is at least large enough to hold two block descriptors to hold
* start and end
* - initialize the first and last descriptors
* - save heap into kernel environment variable.
*
* @param[in] type Memory type.
* @param[in|out] heap Heap pointer
* @param[in] heap_size Size of the heap
*
*
****************************************************************************************
*/
void ke_mem_init(uint8_t type, uint8_t* heap, uint16_t heap_size);
/**
****************************************************************************************
* @brief Allocation of a block of memory.
*
* Allocates a memory block whose size is size; if no memory is available return NULL
*
* @param[in] size Size of the memory area that need to be allocated.
* @param[in] type Type of memory block
*
* @return A pointer to the allocated memory area.
*
****************************************************************************************
*/
void *ke_malloc(uint32_t size, uint8_t type);
/**
****************************************************************************************
* @brief Check if it's possible to allocate a block of memory with a specific size.
*
* @param[in] size Size of the memory area that need to be allocated.
* @param[in] type Type of memory block
*
* @return True if memory block can be allocated, False else.
*
****************************************************************************************
*/
bool ke_check_malloc(uint32_t size, uint8_t type);
/**
****************************************************************************************
* @brief Freeing of a block of memory.
*
* Free the memory area pointed by mem_ptr : mark the block as free and insert it in
* the pool of free block.
*
* @param[in] mem_ptr Pointer to the memory area that need to be freed.
*
****************************************************************************************
*/
void ke_free(void *mem_ptr);
/**
****************************************************************************************
* @brief Check if current heap is empty or not (not used)
*
* @param[in] type Type of memory heap block
*
* @return true if heap not used, false else.
****************************************************************************************
*/
bool ke_mem_is_empty(uint8_t type);
/**
****************************************************************************************
* @brief Check if current pointer is free or not
*
* @param[in] mem_ptr pointer to a memory block
*
* @return true if already free, false else.
****************************************************************************************
*/
bool ke_is_free(void* mem_ptr);
#if (KE_PROFILING)
/**
****************************************************************************************
* @brief Retrieve memory usage of selected heap.
*
* @param[in] type Type of memory heap block
*
* @return current memory usage of current heap.
****************************************************************************************
*/
uint16_t ke_get_mem_usage(uint8_t type);
/**
****************************************************************************************
* @brief Retrieve max memory usage of all heap.
* This command also resets max measured value.
*
* @return max memory usage of all heap.
****************************************************************************************
*/
uint32_t ke_get_max_mem_usage(void);
#endif // (KE_PROFILING)
///@} MEM
#endif // _KE_MEM_H_
+320
View File
@@ -0,0 +1,320 @@
/**
****************************************************************************************
*
* @file ke_msg.h
*
* @brief This file contains the definition related to message scheduling.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_MSG_H_
#define _KE_MSG_H_
/**
****************************************************************************************
* @defgroup MSG Message Exchange
* @ingroup KERNEL
* @brief Message scheduling module.
*
* The MSG module implements message scheduling functions.
* A kernel message has an ID, a receiver task ID and a source task ID.
* In most cases, it also has parameters which are defined in
* a structure dynamically embedded in the message structure,
* so the whole message will be managed internally as one block.
*
* A message can also have one extra parameter which is referenced
* in the normal parameter structure. This extra block is assumed
* to be large by the kernel and will be moved by DMA if needed.
* This feature allows moving MMPDU from LMAC to UMAC.
*
* In order to send a message, a function first have to allocate
* the memory for this message. It can be done with the wrapper
* macro KE_MSG_ALLOC() (which will call ke_msg_alloc()).
* The message can then be sent with ke_msg_send(). The kernel
* will take care of freeing the allocated memory.
* If the message has no parameters, the ke_msg_send_basic() function
* can be used.
*
* @{
****************************************************************************************
*/
#include <stddef.h> // standard definition
#include <stdint.h> // standard integer
#include <stdbool.h> // standard boolean
#include "arch.h" // architectural definition
#include "compiler.h" // compiler definition
#include "co_list.h" // list definition
/// Task Identifier. Composed by the task type and the task index.
typedef uint16_t ke_task_id_t;
/// Builds the task identifier from the type and the index of that task.
#define KE_BUILD_ID(type, index) ( (ke_task_id_t)(((index) << 8)|(type)) )
/// Retrieves task type from task id.
#define KE_TYPE_GET(ke_task_id) ((ke_task_id) & 0xFF)
/// Retrieves task index number from task id.
#define KE_IDX_GET(ke_task_id) (((ke_task_id) >> 8) & 0xFF)
/// Task State
typedef uint8_t ke_state_t;
/// Message Identifier. The number of messages is limited to 0xFFFF.
/// The message ID is divided in two parts:
/// bits[15~8]: task index (no more than 255 tasks support)
/// bits[7~0]: message index(no more than 255 messages per task)
/*@TRACE*/
typedef uint16_t ke_msg_id_t;
/// Message structure.
typedef struct ke_msg
{
struct co_list_hdr hdr; ///< List header for chaining
ke_msg_id_t id; ///< Message id.
ke_task_id_t dest_id; ///< Destination kernel identifier.
ke_task_id_t src_id; ///< Source kernel identifier.
uint16_t param_len; ///< Parameter embedded struct length.
uint32_t param[__ARRAY_EMPTY]; ///< Parameter embedded struct. Must be word-aligned.
} ke_msg_t;
/// Status returned by a task when handling a message
/*@TRACE*/
enum ke_msg_status_tag
{
KE_MSG_CONSUMED = 0, ///< consumed, msg and ext are freed by the kernel
KE_MSG_NO_FREE, ///< consumed, nothing is freed by the kernel
KE_MSG_SAVED, ///< not consumed, will be pushed in the saved queue
};
/**
****************************************************************************************
* @brief Convert a parameter pointer to a message pointer
*
* @param[in] param_ptr Pointer to the parameter member of a ke_msg
* Usually retrieved by a ke_msg_alloc()
*
* @return The pointer to the ke_msg
****************************************************************************************
*/
__INLINE struct ke_msg * ke_param2msg(void const *param_ptr)
{
return (struct ke_msg*) (((uint8_t*)param_ptr) - offsetof(struct ke_msg, param));
}
/**
****************************************************************************************
* @brief Convert a message pointer to a parameter pointer
*
* @param[in] msg Pointer to the ke_msg.
*
* @return The pointer to the param member
****************************************************************************************
*/
__INLINE void * ke_msg2param(struct ke_msg const *msg)
{
return (void*) (((uint8_t*) msg) + offsetof(struct ke_msg, param));
}
/**
****************************************************************************************
* @brief Convenient wrapper to ke_msg_alloc()
*
* This macro calls ke_msg_alloc() and cast the returned pointer to the
* appropriate structure. Can only be used if a parameter structure exists
* for this message (otherwise, use ke_msg_send_basic()).
*
* @param[in] id Message identifier
* @param[in] dest Destination Identifier
* @param[in] src Source Identifier
* @param[in] param_str parameter structure tag
*
* @return Pointer to the parameter member of the ke_msg.
****************************************************************************************
*/
#define KE_MSG_ALLOC(id, dest, src, param_str) \
(struct param_str*) ke_msg_alloc(id, dest, src, sizeof(struct param_str))
/**
****************************************************************************************
* @brief Convenient wrapper to ke_msg_free()
*
* This macro calls ke_msg_free() with the appropriate msg pointer as parameter, according
* to the message parameter pointer passed.
*
* @param[in] param_ptr parameter structure pointer
****************************************************************************************
*/
#define KE_MSG_FREE(param_ptr) ke_msg_free(ke_param2msg((param_ptr)))
/**
****************************************************************************************
* @brief Convenient wrapper to ke_msg_alloc()
*
* This macro calls ke_msg_alloc() and cast the returned pointer to the
* appropriate structure with a variable length. Can only be used if a parameter structure exists
* for this message (otherwise, use ke_msg_send_basic()).Can only be used if the data array is
* located at the end of the structure.
*
* @param[in] id Message identifier
* @param[in] dest Destination Identifier
* @param[in] src Source Identifier
* @param[in] param_str parameter structure tag
* @param[in] length length for the data
*
* @return Pointer to the parameter member of the ke_msg.
****************************************************************************************
*/
#define KE_MSG_ALLOC_DYN(id, dest, src, param_str,length) (struct param_str*)ke_msg_alloc(id, dest, src, \
(sizeof(struct param_str) + (length)));
/**
****************************************************************************************
* @brief Allocate memory for a message
*
* This primitive allocates memory for a message that has to be sent. The memory
* is allocated dynamically on the heap and the length of the variable parameter
* structure has to be provided in order to allocate the correct size.
*
* Several additional parameters are provided which will be preset in the message
* and which may be used internally to choose the kind of memory to allocate.
*
* The memory allocated will be automatically freed by the kernel, after the
* pointer has been sent to ke_msg_send(). If the message is not sent, it must
* be freed explicitly with ke_msg_free().
*
* Allocation failure is considered critical and should not happen.
*
* @param[in] id Message identifier
* @param[in] dest_id Destination Task Identifier
* @param[in] src_id Source Task Identifier
* @param[in] param_len Size of the message parameters to be allocated
*
* @return Pointer to the parameter member of the ke_msg. If the parameter
* structure is empty, the pointer will point to the end of the message
* and should not be used (except to retrieve the message pointer or to
* send the message)
****************************************************************************************
*/
void *ke_msg_alloc(ke_msg_id_t const id, ke_task_id_t const dest_id,
ke_task_id_t const src_id, uint16_t const param_len);
/**
****************************************************************************************
* @brief Message sending.
*
* Send a message previously allocated with any ke_msg_alloc()-like functions.
*
* The kernel will take care of freeing the message memory.
*
* Once the function have been called, it is not possible to access its data
* anymore as the kernel may have copied the message and freed the original
* memory.
*
* @param[in] param_ptr Pointer to the parameter member of the message that
* should be sent.
****************************************************************************************
*/
void ke_msg_send(void const *param_ptr);
/**
****************************************************************************************
* @brief Basic message sending.
*
* Send a message that has a zero length parameter member. No allocation is
* required as it will be done internally.
*
* @param[in] id Message identifier
* @param[in] dest_id Destination Identifier
* @param[in] src_id Source Identifier
****************************************************************************************
*/
void ke_msg_send_basic(ke_msg_id_t const id, ke_task_id_t const dest_id, ke_task_id_t const src_id);
/**
****************************************************************************************
* @brief Message forwarding.
*
* Forward a message to another task by changing its destination and source tasks IDs.
*
* @param[in] param_ptr Pointer to the parameter member of the message that
* should be sent.
* @param[in] dest_id New destination task of the message.
* @param[in] src_id New source task of the message.
****************************************************************************************
*/
void ke_msg_forward(void const *param_ptr, ke_task_id_t const dest_id, ke_task_id_t const src_id);
/**
****************************************************************************************
* @brief Message forwarding.
*
* Forward a message to another task by changing its message ID and its destination and source tasks IDs.
*
* @param[in] param_ptr Pointer to the parameter member of the message that
* should be sent.
* @param[in] msg_id New ID of the message.
* @param[in] dest_id New destination task of the message.
* @param[in] src_id New source task of the message.
****************************************************************************************
*/
void ke_msg_forward_new_id(void const *param_ptr,
ke_msg_id_t const msg_id, ke_task_id_t const dest_id, ke_task_id_t const src_id);
/**
****************************************************************************************
* @brief Free allocated message
*
* @param[in] msg Pointer to the message to be freed (not the parameter member!)
****************************************************************************************
*/
void ke_msg_free(struct ke_msg const *param);
/**
****************************************************************************************
* @brief Retrieve destination task identifier of a kernel message
*
* @param[in] param_ptr Pointer to the parameter member of the message.
*
* @return message destination task
****************************************************************************************
*/
ke_msg_id_t ke_msg_dest_id_get(void const *param_ptr);
/**
****************************************************************************************
* @brief Retrieve source task identifier of a kernel message
*
* @param[in] param_ptr Pointer to the parameter member of the message.
*
* @return message source task
****************************************************************************************
*/
ke_msg_id_t ke_msg_src_id_get(void const *param_ptr);
/**
* Used to know if message is present in kernel queue or not.
*
* @param[in] param_ptr Pointer to the parameter member of the message.
*
* @return True if message is present in Kernel Queue, False else.
*/
bool ke_msg_in_queue(void const *param_ptr);
/// @} MSG
#endif // _KE_MSG_H_
+221
View File
@@ -0,0 +1,221 @@
/**
****************************************************************************************
*
* @file ke_task.h
*
* @brief This file contains the definition related to kernel task management.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_TASK_H_
#define _KE_TASK_H_
/**
****************************************************************************************
* @defgroup TASK Task and Process
* @ingroup KERNEL
* @brief Task management module.
*
* This module implements the functions used for managing tasks.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard integer
#include <stdbool.h> // standard boolean
#include "rwip_config.h" // stack configuration
#include "compiler.h" // compiler defines, INLINE
#include "ke_msg.h" // kernel message defines
/* Default Message handler code to handle several message type in same handler. */
#define KE_MSG_DEFAULT_HANDLER (0xFFFF)
/* Invalid task */
#define KE_TASK_INVALID (0xFFFF)
/* Used to know if a message is not present in kernel queue */
#define KE_MSG_NOT_IN_QUEUE ((struct co_list_hdr *) 0xFFFFFFFF)
/// Status of ke_task API functions
enum KE_TASK_STATUS
{
KE_TASK_OK = 0,
KE_TASK_FAIL,
KE_TASK_UNKNOWN,
KE_TASK_CAPA_EXCEEDED,
KE_TASK_ALREADY_EXISTS,
};
#define MSG_T(msg) ((ke_task_id_t)((msg) >> 8))
#define MSG_I(msg) ((msg) & ((1<<8)-1))
/// Format of a task message handler function
typedef int (*ke_msg_func_t)(ke_msg_id_t const msgid, void const *param,
ke_task_id_t const dest_id, ke_task_id_t const src_id);
/// Macro for message handler function declaration or definition
#define KE_MSG_HANDLER(msg_name, param_struct) int msg_name##_handler(ke_msg_id_t const msgid, \
param_struct const *param, \
ke_task_id_t const dest_id, \
ke_task_id_t const src_id)
#define KE_MSG_HANDLER_NO_STATIC(msg_name, param_struct) int msg_name##_handler(ke_msg_id_t const msgid, \
param_struct const *param, \
ke_task_id_t const dest_id, \
ke_task_id_t const src_id)
/// Macro for message handlers table declaration or definition
#define KE_MSG_HANDLER_TAB(task) const struct ke_msg_handler task##_msg_handler_tab[] =
/// Element of a message handler table.
struct ke_msg_handler
{
/// Id of the handled message.
ke_msg_id_t id;
/// Pointer to the handler function for the msgid above.
ke_msg_func_t func;
};
/// Task descriptor grouping all information required by the kernel for the scheduling.
typedef struct ke_task_desc
{
/// Pointer to the message handler table
const struct ke_msg_handler* msg_handler_tab;
/// Pointer to the state table (one element for each instance).
ke_state_t* state;
/// Maximum index of supported instances of the task.
uint16_t idx_max;
/// Number of messages handled
uint16_t msg_cnt;
} ke_task_desc_t;
/*
* FUNCTION PROTOTYPES
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize Kernel task module.
****************************************************************************************
*/
void ke_task_init(void);
/**
****************************************************************************************
* @brief Create a task.
*
* @param[in] task_type Task type.
* @param[in] p_task_desc Pointer to task descriptor.
*
* @return Status
****************************************************************************************
*/
uint8_t ke_task_create(uint8_t task_type, struct ke_task_desc const * p_task_desc);
/**
****************************************************************************************
* @brief Delete a task.
*
* @param[in] task_type Task type.
*
* @return Status
****************************************************************************************
*/
uint8_t ke_task_delete(uint8_t task_type);
/**
****************************************************************************************
* @brief Retrieve the state of a task.
*
* @param[in] id Task id.
*
* @return Current state of the task
****************************************************************************************
*/
ke_state_t ke_state_get(ke_task_id_t const id);
/**
****************************************************************************************
* @brief Set the state of the task identified by its Task Id.
*
* In this function we also handle the SAVE service: when a task state changes we
* try to activate all the messages currently saved in the save queue for the given
* task identifier.
*
* @param[in] id Identifier of the task instance whose state is going to be modified
* @param[in] state_id New State
*
****************************************************************************************
*/
void ke_state_set(ke_task_id_t const id, ke_state_t const state_id);
/**
****************************************************************************************
* @brief Generic message handler to consume message without handling it in the task.
*
* @param[in] msgid Id of the message received (probably unused)
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id TaskId of the receiving task.
* @param[in] src_id TaskId of the sending task.
*
* @return KE_MSG_CONSUMED
****************************************************************************************
*/
int ke_msg_discard(ke_msg_id_t const msgid, void const *param,
ke_task_id_t const dest_id, ke_task_id_t const src_id);
/**
****************************************************************************************
* @brief Generic message handler to consume message without handling it in the task.
*
* @param[in] msgid Id of the message received (probably unused)
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id TaskId of the receiving task.
* @param[in] src_id TaskId of the sending task.
*
* @return KE_MSG_CONSUMED
****************************************************************************************
*/
int ke_msg_save(ke_msg_id_t const msgid, void const *param,
ke_task_id_t const dest_id, ke_task_id_t const src_id);
/**
****************************************************************************************
* @brief This function flushes all messages, currently pending in the kernel for a
* specific task.
*
* @param[in] task The Task Identifier that shall be flushed.
****************************************************************************************
*/
void ke_task_msg_flush(ke_task_id_t task);
/**
****************************************************************************************
* @brief Check validity of a task. If task type or task instance does not exist,
* return invalid task
*
* @param[in] task Task Identifier to check.
*
* @return Task identifier if valid, invalid identifier else.
****************************************************************************************
*/
ke_task_id_t ke_task_check(ke_task_id_t task);
/// @} TASK
#endif // _KE_TASK_H_
+105
View File
@@ -0,0 +1,105 @@
/**
****************************************************************************************
*
* @file ke_timer.h
*
* @brief This file contains the definitions used for timer management
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_TIMER_H_
#define _KE_TIMER_H_
/**
****************************************************************************************
* @defgroup TIMER BT Time
* @ingroup KERNEL
* @brief Timer management module.
*
* This module implements the functions used for managing kernel timers.
*
****************************************************************************************
*/
#include "rwip.h" // RW definitions
#include "rwip_config.h" // stack configuration
#include "ke_msg.h" // messaging definition
/*
* DEFINITIONS
****************************************************************************************
*/
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/*
* FUNCTION PROTOTYPES
****************************************************************************************
*/
/**
****************************************************************************************
* @brief This function flushes all timers pending in the kernel.
*
****************************************************************************************
*/
void ke_timer_flush(void);
/**
****************************************************************************************
* @brief Set a timer.
*
* The function first cancel the timer if it is already existing, then
* it creates a new one. The timer can be one-shot or periodic, i.e. it
* will be automatically set again after each trigger.
*
* When the timer expires, a message is sent to the task provided as
* argument, with the timer id as message id.
*
*
* @param[in] timer_id Timer identifier (message identifier type).
* @param[in] task_id Task identifier which will be notified
* @param[in] delay Delay in time milliseconds.
****************************************************************************************
*/
void ke_timer_set(ke_msg_id_t const timer_id, ke_task_id_t const task, uint32_t delay_ms);
/**
****************************************************************************************
* @brief Remove an registered timer.
*
* This function search for the timer identified by its id and its task id.
* If found it is stopped and freed, otherwise an error message is returned.
*
* @param[in] timer_id Timer identifier.
* @param[in] task Task identifier.
****************************************************************************************
*/
void ke_timer_clear(ke_msg_id_t const timerid, ke_task_id_t const task);
/**
****************************************************************************************
* @brief Checks if a requested timer is active.
*
* This function pops the first timer from the timer queue and notifies the appropriate
* task by sending a kernel message. If the timer is periodic, it is set again;
* if it is one-shot, the timer is freed. The function checks also the next timers
* and process them if they have expired or are about to expire.
****************************************************************************************
*/
bool ke_timer_active(ke_msg_id_t const timer_id, ke_task_id_t const task_id);
/// @} TIMER
#endif // _KE_TIMER_H_
+65
View File
@@ -0,0 +1,65 @@
/**
****************************************************************************************
*
* @file ke_env.h
*
* @brief This file contains the definition of the kernel.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_ENV_H_
#define _KE_ENV_H_
/**
****************************************************************************************
* @addtogroup ENV Environment
* @ingroup KERNEL
* @brief Kernel Environment
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // stack configuration
#include "ke_event.h" // kernel event
#include "co_list.h" // kernel queue definition
// forward declaration
struct mblock_free;
/// Kernel environment definition
struct ke_env_tag
{
/// Queue of sent messages but not yet delivered to receiver
struct co_list queue_sent;
/// Queue of messages delivered but not consumed by receiver
struct co_list queue_saved;
/// Queue of timers
struct co_list queue_timer;
/// Root pointer = pointer to first element of heap linked lists
struct mblock_free * heap[KE_MEM_BLOCK_MAX];
/// Size of heaps
uint16_t heap_size[KE_MEM_BLOCK_MAX];
#if (KE_PROFILING)
/// Size of heap used
uint16_t heap_used[KE_MEM_BLOCK_MAX];
/// Maximum heap memory used
uint32_t max_heap_used;
#endif //KE_PROFILING
};
/// Kernel environment
extern struct ke_env_tag ke_env;
/// @} ENV
#endif // _KE_ENV_H_
+107
View File
@@ -0,0 +1,107 @@
/**
****************************************************************************************
*
* @file ke_queue.h
*
* @brief This file contains the definition of the message object, queue element
* object and queue object
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _KE_QUEUE_H_
#define _KE_QUEUE_H_
/**
****************************************************************************************
* @addtogroup QUEUE Queues and Lists
* @ingroup KERNEL
* @brief Queue management module
*
* This module implements the functions used for managing message queues.
* These functions must not be called under IRQ!
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h> // standard integer
#include <stdbool.h> // standard boolean
#include "compiler.h" // compiler definitions
#include "co_list.h" // list definition
/*
* FUNCTION PROTOTYPES
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Pop entry to the queue
*
* @param[in] queue Pointer to the queue.
* @param[in] element Pointer to the element.
****************************************************************************************
*/
__INLINE void ke_queue_push(struct co_list *const queue, struct co_list_hdr *const element)
{
co_list_push_back(queue, element);
}
/**
****************************************************************************************
* @brief Pop entry from the queue
*
* @param[in] queue Pointer to the queue.
*
* @return Pointer to the element.
****************************************************************************************
*/
__INLINE struct co_list_hdr *ke_queue_pop(struct co_list *const queue)
{
return co_list_pop_front(queue);
}
/**
****************************************************************************************
* @brief Extracts an element matching a given algorithm.
*
* @param[in] queue Pointer to the queue.
* @param[in] func Matching function.
* @param[in] arg Match argument.
*
* @return Pointer to the element found and removed (NULL otherwise).
****************************************************************************************
*/
struct co_list_hdr *ke_queue_extract(struct co_list * const queue,
bool (*func)(struct co_list_hdr const * elmt, uint32_t arg),
uint32_t arg);
/**
****************************************************************************************
* @brief Insert an element in a sorted queue.
*
* This primitive use a comparison function from the parameter list to select where the
* element must be inserted.
*
* @param[in] queue Pointer to the queue.
* @param[in] element Pointer to the element to insert.
* @param[in] cmp Comparison function (return true if first element has to be inserted
* before the second one).
*
* @return Pointer to the element found and removed (NULL otherwise).
****************************************************************************************
*/
void ke_queue_insert(struct co_list * const queue, struct co_list_hdr * const element,
bool (*cmp)(struct co_list_hdr const *elementA,
struct co_list_hdr const *elementB));
/// @} QUEUE
#endif // _KE_QUEUE_H_
+194
View File
@@ -0,0 +1,194 @@
/**
****************************************************************************************
*
* @file nvds.h
*
* @brief Non Volatile Data Storage (NVDS) driver
*
* Copyright (C) RivieraWaves 2009-2015
*
****************************************************************************************
*/
#ifndef _NVDS_H_
#define _NVDS_H_
/**
****************************************************************************************
* @addtogroup NVDS
* @ingroup COMMON
* @brief Non Volatile Data Storage (NVDS)
*
* Parameters management
* there are two compilation options:
* + NVDS_8BIT_TAGLENGTH :
* if set, each TAG has a maximum length of 256 bytes
* if not set, each TAG has a maximum length of 65536 bytes
* + NVDS_PACKED :
* if not set, all the TAG header structures and TAG data contents are stored with an
* alignment on 32 bit boundary
* if set, all the TAG header structures and TAG data contents are stored
* consecutively without gaps (as would be a structure with pragma packed)
* + NVDS_READ_WRITE :
* if not set, only GET action on TAGs is provided.
* if set, PUT/DEL/LOCK actions are provided in addition of GET action.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdbool.h> // boolean definition
#include <stdint.h> // integer definition
/*
* DEFINES
****************************************************************************************
*/
/// NVDS is defined as read-write
#define NVDS_READ_WRITE 1
/// NVDS is defined as packed
#define NVDS_PACKED 1
/// NVDS has 8-bit length tags
#define NVDS_8BIT_TAGLENGTH 1
#define FLASH_BASE (252*1024)
#define FLASH_SECTOR_SIZE (4*1024)
/// Type of the tag length (8 or 16 bits)
#if (NVDS_8BIT_TAGLENGTH)
typedef uint8_t nvds_tag_len_t;
#else
typedef uint16_t nvds_tag_len_t;
#endif // NVDS_8BIT_TAGLENGTH
/*
* ENUMERATION DEFINITIONS
****************************************************************************************
*/
/// Possible Returned Status
enum NVDS_STATUS
{
/// NVDS status OK
NVDS_OK,
/// generic NVDS status KO
NVDS_FAIL,
/// NVDS TAG unrecognized
NVDS_TAG_NOT_DEFINED,
/// No space for NVDS
NVDS_NO_SPACE_AVAILABLE,
/// Length violation
NVDS_LENGTH_OUT_OF_RANGE,
/// NVDS parameter locked
NVDS_PARAM_LOCKED,
/// NVDS corrupted
NVDS_CORRUPT
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize NVDS.
* @return NVDS_OK
****************************************************************************************
*/
uint8_t nvds_init(uint8_t *base, uint32_t len);
/**
****************************************************************************************
* @brief Look for a specific tag and return, if found and matching (in length), the
* DATA part of the TAG.
*
* If the length does not match, the TAG header structure is still filled, in order for
* the caller to be able to check the actual length of the TAG.
*
* @param[in] tag TAG to look for whose DATA is to be retrieved
* @param[in] length Expected length of the TAG
* @param[out] buf A pointer to the buffer allocated by the caller to be filled with
* the DATA part of the TAG
*
* @return NVDS_OK The read operation was performed
* NVDS_LENGTH_OUT_OF_RANGE The length passed in parameter is different than the TAG's
****************************************************************************************
*/
uint8_t nvds_get(uint8_t tag, nvds_tag_len_t * lengthPtr, uint8_t *buf);
#if (NVDS_READ_WRITE == 1)
/**
****************************************************************************************
* @brief Look for a specific tag and delete it (Status set to invalid)
*
* Implementation notes
* 1. The write function call return status is not handled
*
* @param[in] tag TAG to mark as deleted
*
* @return NVDS_OK TAG found and deleted
* NVDS_PARAM_LOCKED TAG found but can not be deleted because it is locked
* (others) return values from function call @ref nvds_browse_tag
****************************************************************************************
*/
uint8_t nvds_del(uint8_t tag);
/**
****************************************************************************************
* @brief Look for a specific tag and lock it (Status lock bit set to LOCK).
*
* The write function call return status is not handled
*
* @param[in] tag TAG to mark as locked
*
* @return NVDS_OK TAG found and locked
* (others) return values from function call @ref nvds_browse_tag
****************************************************************************************
*/
uint8_t nvds_lock(uint8_t tag);
/**
****************************************************************************************
* @brief This function adds a specific TAG to the NVDS.
*
* Steps:
* 1) parse all the TAGs to:
* 1.1) calculate the total size of all the valid TAGs
* 1.2) erase the existing TAGs that have the same ID
* 1.3) check if we can use the same TAG area in case of an EEPROM
* 1.4) check that the TAG is not locked
* 2) if we have to add the new TAG at the end fo the NVDS (cant use same area):
* 2.1) allocate the appropriate amount of memory
* 2.2) purge the NVDS
* 2.3) free the memory allocated
* 2.4) check that there is now enough room for the new TAG or return
* NO_SPACE_AVAILABLE
* 3) add the new TAG
*
* @param[in] tag TAG to look for whose DATA is to be retrieved
* @param[in] length Expected length of the TAG
* @param[in] buf Pointer to the buffer containing the DATA part of the TAG to add to
* the NVDS
*
* @return NVDS_OK New TAG correctly written to the NVDS
* NVDS_PARAM_LOCKED New TAG is trying to overwrite a TAG that is locked
* NO_SPACE_AVAILABLE New TAG can not fit in the available space in the NVDS
****************************************************************************************
*/
uint8_t nvds_put(uint8_t tag, nvds_tag_len_t length, uint8_t *buf);
#endif //(NVDS_READ_WRITE == 1)
/// @} NVDS
#endif // _NVDS_H_
+949
View File
@@ -0,0 +1,949 @@
/**
****************************************************************************************
*
* @file nvds.c
*
* @brief Non Volatile Data Storage (NVDS) driver
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
/**
****************************************************************************************
* @addtogroup NVDS
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // RW SW configuration
#if (NVDS_SUPPORT)
#include <string.h> // string definitions
#include <stddef.h> // standard definitions
#include <limits.h> // limits definitions
#include "nvds.h" // nvds definitions
#include "arch.h" // main
#include "co_math.h" // math operations
#if (USE_ROM_FLASH)
#include "xc6xxx_fmc_spi.h"
#endif // (USE_ROM_FLASH)
#define NVDS_RAM_SUPPORT defined(CFG_GAIA)
#if (NVDS_RAM_SUPPORT)
#include "mailbox.h"
#endif // NVDS_RAM_SUPPORT
#include "dbg.h"
/*
* DEFINES
****************************************************************************************
*/
/// NVDS parameter data maximum length
#if NVDS_8BIT_TAGLENGTH
#define NVDS_PARAMETER_MAX_LENGTH UCHAR_MAX
#else // NVDS_8BIT_TAGLENGTH
#define NVDS_PARAMETER_MAX_LENGTH USHRT_MAX
#endif // NVDS_8BIT_TAGLENGTH
/// TAG STATUS bit assignment
#define NVDS_STATUS_VALID_MASK 0x01
#define NVDS_STATUS_VALID 0x00
#define NVDS_STATUS_NOT_VALID 0x01
#define NVDS_STATUS_LOCKED_MASK 0x02
#define NVDS_STATUS_LOCKED 0x00
#define NVDS_STATUS_NOT_LOCKED 0x02
#define NVDS_STATUS_ERASED_MASK 0x04
#define NVDS_STATUS_ERASED 0x00
#define NVDS_STATUS_NOT_ERASED 0x04
#if (NVDS_READ_WRITE == 1)
/// Max storage for the NVDS device which can be used for tags
#define NVDS_MAX_STORAGE_SIZE 0x0800 // 2KB
#endif //(NVDS_READ_WRITE == 1)
// NVDS Mapping
/// Magic number offset
#define NVDS_MAGIC_NUMBER_ADDRESS 0x0000
/// Size of magic number
#define NVDS_MAGIC_NUMBER_LENGTH 4
/// Start of NVDS data
#if (NVDS_PACKED == 1)
#define NVDS_START_STORAGE_AREA_ADDRESS \
NVDS_MAGIC_NUMBER_ADDRESS + NVDS_MAGIC_NUMBER_LENGTH
#else //(NVDS_PACKED == 0)
#define NVDS_START_STORAGE_AREA_ADDRESS \
CO_ALIGN4_HI(NVDS_MAGIC_NUMBER_ADDRESS) + \
CO_ALIGN4_HI(NVDS_MAGIC_NUMBER_LENGTH)
#endif //(NVDS_PACKED == 1)
/// Value found in flash when nothing has been written
#define NVDS_NO_TAG 0xFF
/*
* MACROS
****************************************************************************************
*/
/// Check is tag is the last one
#define NVDS_IS_TAG_LAST(h) \
((h).tag == NVDS_NO_TAG)
/// Check is tag is valid
#define NVDS_IS_TAG_OK(h) \
((((h).status) & (NVDS_STATUS_VALID_MASK|NVDS_STATUS_ERASED_MASK)) == \
(NVDS_STATUS_VALID|NVDS_STATUS_NOT_ERASED))
/// Check is tag is locked
#define NVDS_IS_TAG_LOCKED(h) \
((((h).status) & NVDS_STATUS_LOCKED_MASK) == NVDS_STATUS_LOCKED)
/// Set tag as erased
#define NVDS_SET_TAG_ERASED(h) \
((((h).status) & (~NVDS_STATUS_ERASED_MASK)) | NVDS_STATUS_ERASED)
/// Set tag as locked
#define NVDS_SET_TAG_LOCKED(h) \
((((h).status) & (~NVDS_STATUS_LOCKED_MASK)) | NVDS_STATUS_LOCKED)
/// Set tag as valid
#define NVDS_SET_TAG_OK(h) \
(NVDS_STATUS_VALID | NVDS_STATUS_NOT_LOCKED | NVDS_STATUS_NOT_ERASED)
/// Macro for alignment
#if (NVDS_PACKED == 1)
#define NVDS_ALIGNMENT(p) (p)
#else //(NVDS_PACKED == 0)
#define NVDS_ALIGNMENT(p) CO_ALIGN4_HI(p)
#endif //(NVDS_PACKED == 1)
/// Length of tag header
#define NVDS_TAG_HEADER_LENGTH \
NVDS_ALIGNMENT(sizeof(struct nvds_tag_header))
/// Length of tag data
#define NVDS_TAG_CONTENT_LENGTH(h) \
NVDS_ALIGNMENT((h).length)
/// Full length of tag (header+data)
#define NVDS_TAG_FULL_LENGTH(h) \
NVDS_TAG_HEADER_LENGTH + NVDS_TAG_CONTENT_LENGTH(h)
/*
* STRUCT DEFINITIONS
****************************************************************************************
*/
/// Structure defining the header of a TAG. It is very important that the TAG remains
/// the first element of the structure because it defines the LAST TAG of the NVDS when
/// set the oxFF.
struct nvds_tag_header
{
/// current TAG identifier
uint8_t tag;
/// status of the TAG (erased, locked ...)
uint8_t status;
/// length of the TAG
nvds_tag_len_t length;
};
/// Environment structure of the NVDS module
struct nvds_env_tag
{
/// Function to read the device Address being in the NVDS memory space
void (*read)(uint32_t const address,
uint32_t const length,
uint8_t* const buf);
/// Function to write the device Address being in the NVDS memory space
void (*write)(uint32_t const address,
uint32_t const length,
uint8_t* const buf);
/// Function to erase the entire NVDS memory space
void (*erase)(uint32_t const address,
uint32_t const length);
/// NVDS base pointer
uint8_t *nvds_space;
/// Total size of the NVDS area
uint32_t total_size;
/// Flash ID
uint8_t flash_id;
};
/*
* GLOBAL VARIABLE DECLARATIONS
****************************************************************************************
*/
#if (NVDS_READ_WRITE == 1)
/// temporary buffer used for purging
__STATIC uint8_t nvds_temp_buf[NVDS_MAX_STORAGE_SIZE];
#endif //(NVDS_READ_WRITE == 1)
/// NVDS magic number keyword
// __STATIC const uint8_t nvds_magic_number[NVDS_MAGIC_NUMBER_LENGTH] = {'N', 'V', 'D', 'S'};
__STATIC const uint8_t nvds_magic_number[NVDS_MAGIC_NUMBER_LENGTH] = {'N', 'V', 'D', 'S'};
/// NVDS environment
__STATIC struct nvds_env_tag nvds_env;
/*
* LOCAL FUNCTION DECLARATION
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Check if the current NVDS has the correct magic number set.
*
* Implementation notes:we do not put an assert on the read access because we could be in
* the situation of a dummy read (returns always NVDS_FAIL) and we want to return
* correctly the FALSE.
*
* @return True if the NVDS has the Magic Number set, false otherwise.
****************************************************************************************
*/
__STATIC bool nvds_is_magic_number_ok(void);
/**
****************************************************************************************
* @brief Look for a specific TAG.
*
* If found, it returns the address and the header, otherwise the TAG address returned
* points to a location where it is possible to store a new TAG.
* The TAG is returned only if it is valid (not erased). This function is useful to find
* a single valid TAG element or find the next available space for a new TAG.
*
* @param[in] tag TAG to look for
* @param[out] nvds_tag_header_ptr Pointer to the TAG header structure allocated by the
* caller to contain the searched TAG header
* @param[out] tag_address_ptr Pointer to the NVDS address at which TAG was found
* (returned) or if the TAG was not found, first address
* free for storing new TAG in NVDS
*
* @return Return codes from the @ref nvds_walk_tag function call
****************************************************************************************
*/
__STATIC uint8_t nvds_browse_tag(uint8_t tag,
struct nvds_tag_header *nvds_tag_header_ptr,
uint32_t *tag_address_ptr);
/**
****************************************************************************************
* @brief Read the TAG header that MUST be present at NVDS address cur_tag_addr and fill
* the TAG header structure that is allocated by the caller and referenced by
* nvds_tag_header_ptr.
*
* Upon completion of the read, the next TAG address is computed and returned to the
* caller through nxt_tag_addr_ptr (except if the current TAG is the LAST one).
* If the caller wishes to read the first TAG of the NVDS, the value
* NVDS_START_STORAGE_AREA_ADDRESS can be used as the cur_tag_addr.
* If the current Address specified is pointing at the position of the last element of
* the NVDS the function returns NVDS_TAG_NOT_DEFINED. In this case, there is NO VALUE
* returned through nxt_tag_addr_ptr. The cur_tag_addr is already pointing to an empty
* TAG.
* The TAG read is not check for validity, this information should be handled by the
* caller if he wishes to use the TAG information correctly.
*
* @param[in] cur_tag_addr Address of the current TAG in NVDS memory space
* @param[out] nvds_tag_header_ptr A pointer to an allocated space for the parameter header
* @param[out] nxt_tag_addr_ptr A pointer to the next TAG address in the NVDS memory space
*
* @return NVDS_OK TAG read, header filled and next TAG address filled
* NVDS_TAG_NOT_DEFINED Last TAG reached, header filled with garbage
* NVDS_CORRUPT Current TAG is overcoming the NVDS size limit
****************************************************************************************
*/
__STATIC uint8_t nvds_walk_tag (uint32_t cur_tag_addr,
struct nvds_tag_header *nvds_tag_header_ptr,
uint32_t *nxt_tag_addr_ptr);
#if (NVDS_RAM_SUPPORT)
/**
****************************************************************************************
* @brief Hook a RAM driver to the NVDS.
* If NVDS media is stored in RAM,
*
* @return NVDS_OK
****************************************************************************************
*/
__STATIC uint8_t nvds_ram_init(uint8_t *base, uint32_t len);
/**
****************************************************************************************
* @brief RAM Read function
*
* @param[in] address Start address of the data to read from NVDS
* @param[in] length Length of the data to read from NVDS
* @param[in] buf Pointer to the buffer containing the DATA to read from the NVDS
****************************************************************************************
*/
__STATIC void nvds_ram_read(uint32_t address, uint32_t length, uint8_t *buf);
/**
****************************************************************************************
* @brief RAM Write function
*
* @param[in] address NVDS address at which the write operation must be performed
* @param[in] length Length of the write operation to perform
* @param[in] buf Pointer to a buffer containing the data to write
****************************************************************************************
*/
__STATIC void nvds_ram_write(uint32_t address, uint32_t length, uint8_t *buf);
/**
****************************************************************************************
* @brief RAM Erase function
* @param[in] address NVDS address at which the erase operation must be performed
* @param[in] length Length of the erase operation to perform
****************************************************************************************
*/
__STATIC void nvds_ram_erase(uint32_t address, uint32_t length);
#else // !(NVDS_RAM_SUPPORT)
/**
****************************************************************************************
* @brief Hook a dummy driver to the NVDS.
* If no valid NVDS media was found, to avoid incorrect behavior a dummy driver should
* be hooked to the NVDS.
*
* @return NVDS_OK
****************************************************************************************
*/
#if (NVDS_READ_WRITE == 0)
__STATIC uint8_t nvds_null_init(void);
/**
****************************************************************************************
* @brief Dummy function to safely replace Read function
*
* @param[in] address Start address of the data to read from NVDS
* @param[in] length Length of the data to read from NVDS
* @param[in] buf Pointer to the buffer containing the DATA to read from the NVDS
****************************************************************************************
*/
__STATIC void nvds_null_read(uint32_t address, uint32_t length, uint8_t *buf);
/**
****************************************************************************************
* @brief Dummy function to safely replace Write function
*
* @param[in] address NVDS address at which the write operation must be performed
* @param[in] length Length of the write operation to perform
* @param[in] buf Pointer to a buffer containing the data to write
****************************************************************************************
*/
__STATIC void nvds_null_write(uint32_t address, uint32_t length, uint8_t *buf);
/**
****************************************************************************************
* @brief Dummy function to safely replace Erase function
* @param[in] address NVDS address at which the erase operation must be performed
* @param[in] length Length of the erase operation to perform
****************************************************************************************
*/
__STATIC void nvds_null_erase(uint32_t address, uint32_t length);
#endif // (NVDS_READ_WRITE == 0)
/**
****************************************************************************************
* @brief Read data from NVDS.
*
* @param[in] address Start address of the data to read from NVDS
* @param[in] length Length of the data to read from NVDS
* @param[in] buf Pointer to the buffer containing the DATA to read from the NVDS
****************************************************************************************
*/
__STATIC void nvds_read(uint32_t address, uint32_t length, uint8_t *buf);
#if (NVDS_READ_WRITE == 1)
/**
****************************************************************************************
* @brief Write data into NVDS
*
* @param[in] address Start address of the data to write to NVDS
* @param[in] length Length of the data to write to NVDS
* @param[in] buf Pointer to the buffer containing the DATA to write to the NVDS
****************************************************************************************
*/
__STATIC void nvds_write(uint32_t address, uint32_t length, uint8_t *buf);
/**
****************************************************************************************
* @brief Erase data in NVDS
*
* @param[in] address Start address of the data to read from NVDS
* @param[in] length Length of the data to read from NVDS
****************************************************************************************
*/
__STATIC void nvds_erase(uint32_t address, uint32_t length);
#endif // (NVDS_READ_WRITE == 1)
#endif //!(NVDS_RAM_SUPPORT)
#if (NVDS_READ_WRITE == 1)
/**
****************************************************************************************
* @brief Initialize the NVDS memory.
*
* This function clears the entire memory content and writes the MagicNumber
****************************************************************************************
*/
__STATIC void nvds_init_memory(void);
/**
****************************************************************************************
* @brief Purge NVDS memory
*
* This function performs a read of all the valid TAGs of the NVDS, stores them in
* the temporary buffer allocated by the caller, flushes the NVDS and then rewrites all
* the valid TAGs.
*
* It is used to purge the NVDS when there is no more space to store a new TAG for
* example or regularly to save TAG browse time.
*
* @param[in] length Length of the buffer allocated to perform the temporary storage of
* the NVDS while purging (erase and compress)
* @param[in] buf A pointer to the buffer allocated by the caller for the temporary
* storage of the NVDS while purging
****************************************************************************************
*/
__STATIC void nvds_purge(uint32_t length, uint8_t* buf);
#endif //(NVDS_READ_WRITE == 1)
/*
* LOCAL FUNCTION DEFINITIONS
****************************************************************************************
*/
__STATIC bool nvds_is_magic_number_ok(void)
{
bool is_magic_number_ok = false;
uint8_t read_magic_number[NVDS_MAGIC_NUMBER_LENGTH];
// Look for the magic number
nvds_env.read(NVDS_MAGIC_NUMBER_ADDRESS, sizeof(read_magic_number), read_magic_number);
// Compare the read magic number with the correct value
if (memcmp(read_magic_number, nvds_magic_number, NVDS_MAGIC_NUMBER_LENGTH)==0)
{
is_magic_number_ok = true;
}
return is_magic_number_ok;
}
__STATIC uint8_t nvds_walk_tag (uint32_t cur_tag_addr,
struct nvds_tag_header *nvds_tag_header_ptr,
uint32_t *nxt_tag_addr_ptr)
{
uint8_t status = NVDS_OK;
// Read the current parameter header
nvds_env.read((uint32_t)cur_tag_addr,
(uint32_t)sizeof(struct nvds_tag_header),
(uint8_t*)nvds_tag_header_ptr);
// Check if the read operation completed successfully
if (!NVDS_IS_TAG_LAST(*nvds_tag_header_ptr))
{
// Calculate the address of the next tag
*nxt_tag_addr_ptr = cur_tag_addr + NVDS_TAG_FULL_LENGTH(*nvds_tag_header_ptr);
// Check if there is enough space to read next header
// the limit is set minus 1 because we need to leave at least an end marker
if (*nxt_tag_addr_ptr > (nvds_env.total_size - 1))
{
// Going above NVDS limit, probably an error occurred
ASSERT_ERR(0);
status = NVDS_CORRUPT;
}
}
else
{
// this is beyond the last TAG
status = NVDS_TAG_NOT_DEFINED;
}
return(status);
}
__STATIC uint8_t nvds_browse_tag (uint8_t tag,
struct nvds_tag_header *nvds_tag_header_ptr,
uint32_t *tag_address_ptr)
{
uint8_t status;
uint32_t cur_tag_addr, nxt_tag_addr;
// set the address to the first data byte of the NVDS
nxt_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS;
do
{
// go to the next tag
cur_tag_addr = nxt_tag_addr;
// retrieve the parameter header
status = nvds_walk_tag(cur_tag_addr, nvds_tag_header_ptr, &nxt_tag_addr);
} while ((status == NVDS_OK) &&
!((nvds_tag_header_ptr->tag == tag) && NVDS_IS_TAG_OK(*nvds_tag_header_ptr)));
// the returned address is the last address found
*tag_address_ptr = cur_tag_addr;
return(status);
}
#if (NVDS_RAM_SUPPORT)
__STATIC void nvds_ram_read(uint32_t address, uint32_t length, uint8_t *buf)
{
// Test the validity of address + length
ASSERT_ERR(((address + length) <= nvds_env.total_size));
// Read the RAM memory
memcpy(buf,(void*)(nvds_env.nvds_space + address),length);
}
#if (NVDS_READ_WRITE == 1)
__STATIC void nvds_ram_write(uint32_t address, uint32_t length, uint8_t *buf)
{
// Test the validity of address + length
ASSERT_ERR(((address + length) <= nvds_env.total_size));
// Write the RAM memory
memcpy((void*)(nvds_env.nvds_space + address),buf,length);
}
__STATIC void nvds_ram_erase(uint32_t address, uint32_t length)
{
uint8_t buf[4];
uint32_t incr;
// Write 0 the RAM memory
buf[0] = 255;
buf[1] = 255;
buf[2] = 255;
buf[3] = 255;
for (incr = 0; incr < length; incr=incr+4)
{
memcpy((void*)nvds_env.nvds_space + address + incr, buf, 4);
}
}
#endif
__STATIC uint8_t nvds_ram_init(uint8_t *base, uint32_t len)
{
uint8_t status = NVDS_OK;
// Initialize the pointer to the NVDS
nvds_env.nvds_space = base;
// initialize the access functions
nvds_env.read = &nvds_ram_read;
#if (NVDS_READ_WRITE == 1)
nvds_env.write = &nvds_ram_write;
nvds_env.erase = &nvds_ram_erase;
#else //(NVDS_READ_WRITE == 0)
nvds_env.write = &nvds_null_write;
nvds_env.erase = &nvds_null_erase;
#endif //(NVDS_READ_WRITE == 1)
nvds_env.total_size = len;
// Check if NVDS is correctly initialized
if (!nvds_is_magic_number_ok())
{
#if (NVDS_READ_WRITE == 1)
// Initialize the memory
nvds_init_memory();
#else //(NVDS_READ_WRITE == 0)
// No NVDS, so select the NULL NVDS
nvds_null_init();
// Return bad status
status = NVDS_FAIL;
#endif //(NVDS_READ_WRITE == 1)
}
return (status);
}
#else // !(NVDS_RAM_SUPPORT)
#if (NVDS_READ_WRITE == 0)
__STATIC void nvds_null_read(uint32_t address, uint32_t length, uint8_t *buf){}
__STATIC void nvds_null_write(uint32_t address, uint32_t length, uint8_t *buf){}
__STATIC void nvds_null_erase(uint32_t address, uint32_t length){}
__STATIC uint8_t nvds_null_init(void)
{
// init all the structure
memset( &nvds_env, 0, sizeof(nvds_env));
nvds_env.read = nvds_null_read;
nvds_env.write = nvds_null_write;
nvds_env.erase = nvds_null_erase;
return NVDS_OK;
}
#endif // (NVDS_READ_WRITE == 0)
__STATIC void nvds_read(uint32_t address, uint32_t length, uint8_t *buf)
{
// Test the validity of address + length
ASSERT_ERR(((address + length) <= nvds_env.total_size));
// Read the memory
#if (USE_XIP)
GLOBAL_INT_DISABLE();
FMC_SPI_FlashRead((uint32_t)nvds_env.nvds_space + address, buf, length);
GLOBAL_INT_RESTORE();
#endif // (USE_XIP)
// rom_env.stack_printf("nvds_read address=%x length=%x\n", address, length);
// DUMP_DATA_PRINTF(buf, length);
}
#if (NVDS_READ_WRITE == 1)
__STATIC void nvds_write(uint32_t address, uint32_t length, uint8_t *buf)
{
// Test the validity of address + length
ASSERT_ERR(((address + length) <= nvds_env.total_size));
// Read the memory
#if (USE_XIP)
GLOBAL_INT_DISABLE();
FMC_SPI_FlashWrite((uint32_t)nvds_env.nvds_space + address, buf, length);
GLOBAL_INT_RESTORE();
#endif // (USE_XIP)
// rom_env.stack_printf("nvds_write address=%x length=%x\n", address, length);
// DUMP_DATA_PRINTF(buf, length);
}
__STATIC void nvds_erase(uint32_t address, uint32_t length)
{
uint8_t sector_cnt = length/FLASH_SECTOR_SIZE;
uint32_t erase_base = (uint32_t)nvds_env.nvds_space + address;
uint32_t erase_address = 0;
if(length % FLASH_SECTOR_SIZE){
sector_cnt = sector_cnt + 1;
}
for(uint16_t i=0; i<sector_cnt; i++){
// flash_erase(nvds_env.flash_id, (uint32_t)nvds_env.nvds_space + address, length, NULL);
erase_address = erase_base + i * FLASH_SECTOR_SIZE;
#if (USE_XIP)
GLOBAL_INT_DISABLE();
FMC_SPI_Flash_Erase_Sector(erase_address);
GLOBAL_INT_RESTORE();
#endif // (USE_XIP)
}
}
#endif // (NVDS_READ_WRITE == 1)
#endif // !(NVDS_RAM_SUPPORT)
#if (NVDS_READ_WRITE == 1)
__STATIC void nvds_init_memory(void)
{
// clear the device
nvds_env.erase((uint32_t)NVDS_MAGIC_NUMBER_ADDRESS, nvds_env.total_size);
// Write the magic number at address 0
nvds_env.write((uint32_t)NVDS_MAGIC_NUMBER_ADDRESS,
(uint32_t)NVDS_MAGIC_NUMBER_LENGTH,
(uint8_t*)nvds_magic_number);
}
__STATIC void nvds_purge(uint32_t length, uint8_t* buf)
{
uint8_t status;
struct nvds_tag_header tag_hdr;
uint32_t nxt_tag_addr;
uint32_t total_length;
uint8_t *walk_ptr;
// store all the valid TAG elements in the locally allocated buffer
total_length = 0;
nxt_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS;
walk_ptr = buf;
do
{
// go to the next tag
uint32_t cur_tag_addr = nxt_tag_addr;
status = nvds_walk_tag(cur_tag_addr, (struct nvds_tag_header*)&tag_hdr, &nxt_tag_addr);
if ((status == NVDS_OK) && NVDS_IS_TAG_OK(tag_hdr))
{
// check that the current size is not overcoming the buffer
total_length += NVDS_TAG_FULL_LENGTH(tag_hdr);
ASSERT_ERR(total_length <= length);
// copy the header content
*((struct nvds_tag_header*)walk_ptr) = tag_hdr;
// increment the pointer to the data part
walk_ptr += NVDS_TAG_HEADER_LENGTH;
cur_tag_addr += NVDS_TAG_HEADER_LENGTH;
// retrieve all the data part
nvds_env.read((uint32_t)cur_tag_addr, (uint32_t)tag_hdr.length, walk_ptr);
// increment the walking pointer
walk_ptr += NVDS_TAG_CONTENT_LENGTH(tag_hdr);
}
} while (status == NVDS_OK);
// reinitialize the flash
nvds_init_memory();
// rewrite the NVDS once cleaned
nvds_env.write((uint32_t)NVDS_START_STORAGE_AREA_ADDRESS,
(uint32_t)total_length,
buf);
}
#endif //(NVDS_READ_WRITE == 1)
/*
* EXPORTED FUNCTION DEFINITIONS
****************************************************************************************
*/
uint8_t nvds_init(uint8_t *base, uint32_t len)
{
LOGI("nvds_init base=%x len=%d\n", base, len);
uint8_t status = NVDS_OK;
// Initialize the pointer to the NVDS
nvds_env.nvds_space = base;
// initialize the access functions
nvds_env.read = &nvds_read;
nvds_env.write = &nvds_write;
nvds_env.erase = &nvds_erase;
nvds_env.total_size = len;
// Check if NVDS is correctly initialized
if (!nvds_is_magic_number_ok())
{
nvds_init_memory();
}
return (status);
}
uint8_t nvds_get(uint8_t tag, nvds_tag_len_t * lengthPtr, uint8_t *buf)
{
uint8_t status;
uint32_t tag_addr;
struct nvds_tag_header tag_hdr;
// try to find the TAG in the NVDS
status = nvds_browse_tag(tag, &tag_hdr, &tag_addr);
// if the TAG was found
if (status == NVDS_OK)
{
// The parameter is valid, verify that buffer is large enough to store it
if (*lengthPtr < tag_hdr.length)
{
status = NVDS_LENGTH_OUT_OF_RANGE;
}
else // All is OK, proceed to the read operation
{
// Copy data to output buffer
nvds_env.read((uint32_t)(tag_addr + NVDS_TAG_HEADER_LENGTH),
(uint32_t)tag_hdr.length,
buf);
// Return tag address
*lengthPtr = tag_hdr.length;
}
}
else
{
// Nothing to return, set length to 0
*lengthPtr = 0;
}
return(status);
}
#if (NVDS_READ_WRITE == 1)
uint8_t nvds_del(uint8_t tag)
{
uint8_t status;
struct nvds_tag_header tag_hdr;
uint32_t tag_addr;
uint8_t status_to_write;
// look for the TAG
status = nvds_browse_tag(tag, &tag_hdr, &tag_addr);
// Verify whether the parameter is locked or not
if ((status == NVDS_OK) && NVDS_IS_TAG_LOCKED(tag_hdr))
{
status = NVDS_PARAM_LOCKED;
}
// Proceed to the delete operation
if (status == NVDS_OK)
{
// then we set parameter to erased
status_to_write = NVDS_SET_TAG_ERASED(tag_hdr);
nvds_env.write((uint32_t)(tag_addr+offsetof(struct nvds_tag_header, status)),
(uint32_t) sizeof(status_to_write),
(uint8_t*) &status_to_write);
#if (NVDS_RAM_SUPPORT)
mailbox_send(E_NVDS_SAVE_REQ, NULL, 0); // request NVDS saved
#endif //(NVDS_RAM_SUPPORT)
}
return(status);
}
uint8_t nvds_lock(uint8_t tag)
{
uint8_t status;
struct nvds_tag_header tag_hdr;
uint32_t tag_addr;
uint8_t status_to_write;
// look for the TAG
status = nvds_browse_tag(tag, &tag_hdr, &tag_addr);
// Proceed to the lock operation
if (status == NVDS_OK)
{
// The tag has been found, set the parameter to locked
status_to_write = NVDS_SET_TAG_LOCKED(tag_hdr);
nvds_env.write((uint32_t)(tag_addr+offsetof(struct nvds_tag_header, status)),
(uint32_t)sizeof(status_to_write),
&status_to_write);
}
return(status);
}
uint8_t nvds_put(uint8_t tag, nvds_tag_len_t length, uint8_t *buf)
{
uint8_t status;
struct nvds_tag_header tag_hdr;
uint8_t tag_buffer[NVDS_PARAMETER_MAX_LENGTH];
uint32_t cur_tag_addr, nxt_tag_addr;
uint8_t status_to_write;
uint32_t total_length;
/* parse once all the TAG elements of the NVDS to:
* 1) find same tag
* 2) erase and invalidate the former tag
* 3) compute the total length needed by the all valid tags
* 4) retrieve the first address where new data can be stored */
total_length = 0;
nxt_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS;
do
{
// Go to the next tag
cur_tag_addr = nxt_tag_addr;
// Read the next TAG header structure
status = nvds_walk_tag(cur_tag_addr, &tag_hdr, &nxt_tag_addr);
// check TAG is valid
if ((status == NVDS_OK) && NVDS_IS_TAG_OK(tag_hdr))
{
// check TAG is identical to the new one
if (tag_hdr.tag == tag)
{
// check TAG is not locked
if (NVDS_IS_TAG_LOCKED(tag_hdr))
{
return NVDS_PARAM_LOCKED;
}
// Read parameter data
nvds_env.read((uint32_t)(cur_tag_addr + NVDS_TAG_HEADER_LENGTH),
(uint32_t)tag_hdr.length,
tag_buffer);
// Compare data with new parameter
if((tag_hdr.length == length) && !memcmp(buf, tag_buffer, tag_hdr.length))
{
return NVDS_OK;
}
// then we set parameter to erased
status_to_write = NVDS_SET_TAG_ERASED(tag_hdr);
nvds_env.write((uint32_t)(cur_tag_addr+offsetof(struct nvds_tag_header, status)),
(uint32_t) sizeof(status_to_write),
(uint8_t*) &status_to_write);
}
else
{
// add the current tag length to the total length (used for purge)
total_length += NVDS_TAG_FULL_LENGTH(tag_hdr);
}
}
} while (status == NVDS_OK);
// check that we've reached the last TAG of the NVDS
if (status != NVDS_OK)
{
/* check if there is enough space to write next tag
the limit is calculated including 2 TAG headers (the current and the next
that is used to leave at least an end marker) */
if ((cur_tag_addr + (NVDS_TAG_HEADER_LENGTH*2) + NVDS_ALIGNMENT(length))
> (nvds_env.total_size))
{
ASSERT_ERR(nvds_temp_buf != NULL);
// purge the NVDS using the current buffer
nvds_purge(total_length, nvds_temp_buf);
// compute the next tag address in the NVDS memory space
cur_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS + NVDS_ALIGNMENT(total_length);
// if there is still not enough space, return an error
if ((cur_tag_addr + NVDS_TAG_HEADER_LENGTH + NVDS_ALIGNMENT(length))
> (nvds_env.total_size - 1))
{
return NVDS_NO_SPACE_AVAILABLE;
}
}
}
// First of all, write the data of the parameter
nvds_env.write((uint32_t)(cur_tag_addr+NVDS_TAG_HEADER_LENGTH),
(uint32_t)length,
buf);
// Second of all, configure the new value of the TAG HEADER
tag_hdr.tag = tag;
tag_hdr.status = NVDS_SET_TAG_OK(tag_hdr);
tag_hdr.length = length;
// Third of all, write the new TAG HEADER
nvds_env.write((uint32_t)(cur_tag_addr),
(uint32_t)sizeof(tag_hdr),
(uint8_t*)&tag_hdr);
#if (NVDS_RAM_SUPPORT)
mailbox_send(E_NVDS_SAVE_REQ, NULL, 0); // request NVDS saved
#endif //(NVDS_RAM_SUPPORT)
return(NVDS_OK);
}
#endif // NVDS_RAM_SUPPORT
#endif //(NVDS_SUPPORT)
/// @} NVDS
+54
View File
@@ -0,0 +1,54 @@
/**
****************************************************************************************
*
* @file rf.h
*
* @brief Common header file for all radios.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef RF_H_
#define RF_H_
/**
****************************************************************************************
* @addtogroup RF
* @ingroup DRIVERS
* @brief Common definitions for radio modules.
*
* This module declares the functions and constants that have to be defined for all RF.
*
* @{
****************************************************************************************
*/
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
struct rwip_rf_api; // forward declaration to avoid including rw.h
/**
*****************************************************************************************
* @brief Initialization of RF.
*
* This function initializes the RF and fills the structure containing the function
* pointers and parameters required by the RW BT stack.
*
* @param[out] api Pointer to the BT RF API structure
*
*****************************************************************************************
*/
void rf_init(struct rwip_rf_api *api);
//modem init
void modem_init(void);
/// @} RF
#endif // RF_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+190
View File
@@ -0,0 +1,190 @@
/**
****************************************************************************************
*
* @file rwip_task.h
*
* @brief Task Identifier description for the RW IP
*
* Copyright (C) RivieraWaves 2009-2016
*
****************************************************************************************
*/
#ifndef RWIP_TASK_H_
#define RWIP_TASK_H_
/**
****************************************************************************************
* @addtogroup ROOT
* @{
*
* Information about RW SW TASK
*
* @name RW TASK Configuration
* @{
****************************************************************************************
*/
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Build the first message ID of a task. (in fact a ke_msg_id_t)
#define TASK_FIRST_MSG(task) ((uint16_t)((task) << 8))
/// Builds the task identifier from the type and the index of that task.
#define TASK_BUILD(type, index) ((uint16_t)(((index) << 8)|(type)) )
/// Retrieves task type from task id.
#define TASK_TYPE_GET(ke_task_id) (((uint16_t)ke_task_id) & 0xFF)
/// Retrieves task index number from task id.
#define TASK_IDX_GET(ke_task_id) ((((uint16_t)ke_task_id) >> 8) & 0xFF)
/// Message identifier index
#define MSG_ID(task, idx) (TASK_FIRST_MSG((TASK_ID_ ## task)) + idx)
/// Tasks types definition, this value shall be in [0-254] range
/*@TRACE*/
enum TASK_API_ID
{
// -----------------------------------------------------------------------------------
// ---------------------- Controller Task identifer ----------------------------------
// -----------------------------------------------------------------------------------
// Link Layer Tasks
TASK_ID_LLM = 0, // BLE Link manager
TASK_ID_LLC = 1, // BLE Link controller
TASK_ID_LLD = 2, // BLE Link driver
TASK_ID_LLI = 3, // BLE Link ISO
TASK_ID_DBG = 4, // Debug task
// BT Controller Tasks
TASK_ID_LM = 5, // BT Link manager
TASK_ID_LC = 6, // BT Link controller
TASK_ID_LB = 7, // BT Broadcast
TASK_ID_LD = 8, // BT Link driver
// -----------------------------------------------------------------------------------
// --------------------- BLE HL TASK API Identifiers ---------------------------------
// --------------------- SHALL NOT BE CHANGED ---------------------------------
// -----------------------------------------------------------------------------------
TASK_ID_L2CAP = 10, // L2CAP Task
TASK_ID_GATT = 11, // Generic Attribute Profile Task
TASK_ID_GAPM = 13, // Generic Access Profile Manager
TASK_ID_GAPC = 14, // Generic Access Profile Controller
TASK_ID_APP = 15, // Application API
// -----------------------------------------------------------------------------------
// --------------------- TRANSPORT AND PLATFORM TASKS --------------------------------
// -----------------------------------------------------------------------------------
TASK_ID_AHI = 16, // Application Host Interface
TASK_ID_HCI = 17, // Host to Control Interface
TASK_ID_DISPLAY = 19, // LCD/Display task
// -----------------------------------------------------------------------------------
// --------------------- BLE Profile TASK API Identifiers ----------------------------
// --------------------- SHALL NOT BE CHANGED ---------------------------------
// -----------------------------------------------------------------------------------
TASK_ID_DISS = 20, // Device Information Service Server Task
TASK_ID_DISC = 21, // Device Information Service Client Task
TASK_ID_PROXM = 22, // Proximity Monitor Task
TASK_ID_PROXR = 23, // Proximity Reporter Task
TASK_ID_FINDL = 24, // Find Me Locator Task
TASK_ID_FINDT = 25, // Find Me Target Task
TASK_ID_HTPC = 26, // Health Thermometer Collector Task
TASK_ID_HTPT = 27, // Health Thermometer Sensor Task
TASK_ID_BLPS = 28, // Blood Pressure Sensor Task
TASK_ID_BLPC = 29, // Blood Pressure Collector Task
TASK_ID_HRPS = 30, // Heart Rate Sensor Task
TASK_ID_HRPC = 31, // Heart Rate Collector Task
TASK_ID_TIPS = 32, // Time Server Task
TASK_ID_TIPC = 33, // Time Client Task
TASK_ID_SCPPS = 34, // Scan Parameter Profile Server Task
TASK_ID_SCPPC = 35, // Scan Parameter Profile Client Task
TASK_ID_BASS = 36, // Battery Service Server Task
TASK_ID_BASC = 37, // Battery Service Client Task
TASK_ID_HOGPD = 38, // HID Device Task
TASK_ID_HOGPBH = 39, // HID Boot Host Task
TASK_ID_HOGPRH = 40, // HID Report Host Task
TASK_ID_GLPS = 41, // Glucose Profile Sensor Task
TASK_ID_GLPC = 42, // Glucose Profile Collector Task
TASK_ID_RSCPS = 43, // Running Speed and Cadence Profile Server Task
TASK_ID_RSCPC = 44, // Running Speed and Cadence Profile Collector Task
TASK_ID_CSCPS = 45, // Cycling Speed and Cadence Profile Server Task
TASK_ID_CSCPC = 46, // Cycling Speed and Cadence Profile Client Task
TASK_ID_ANPS = 47, // Alert Notification Profile Server Task
TASK_ID_ANPC = 48, // Alert Notification Profile Client Task
TASK_ID_PASPS = 49, // Phone Alert Status Profile Server Task
TASK_ID_PASPC = 50, // Phone Alert Status Profile Client Task
TASK_ID_CPPS = 51, // Cycling Power Profile Server Task
TASK_ID_CPPC = 52, // Cycling Power Profile Client Task
TASK_ID_LANS = 53, // Location and Navigation Profile Server Task
TASK_ID_LANC = 54, // Location and Navigation Profile Client Task
TASK_ID_IPSS = 55, // Internet Protocol Support Profile Server Task
TASK_ID_IPSC = 56, // Internet Protocol Support Profile Client Task
TASK_ID_ENVS = 57, // Environmental Sensing Profile Server Task
TASK_ID_ENVC = 58, // Environmental Sensing Profile Client Task
TASK_ID_WSCS = 59, // Weight Scale Profile Server Task
TASK_ID_WSCC = 60, // Weight Scale Profile Client Task
TASK_ID_UDSS = 61, // User Data Service Server Task
TASK_ID_UDSC = 62, // User Data Service Client Task
TASK_ID_BCSS = 63, // Body Composition Server Task
TASK_ID_BCSC = 64, // Body Composition Client Task
TASK_ID_WPTS = 65, // Wireless Power Transfer Profile Server Task
TASK_ID_WPTC = 66, // Wireless Power Transfer Profile Client Task
TASK_ID_PLXS = 67, // Pulse Oximeter Profile Server Task
TASK_ID_PLXC = 68, // Pulse Oximeter Profile Client Task
TASK_ID_CGMS = 69, // Continuous Glucose Monitoring Server Task
TASK_ID_CGMC = 70, // Continuous Glucose Monitoring Client Task
TASK_ID_CSISM = 71, // Coordinated Set Identification Profile Set Member Task
TASK_ID_CSISC = 72, // Coordinated Set Identification Profile Set Coordinator Task
TASK_ID_OTS = 73, // Object Transfer Profile Server Task
TASK_ID_OTC = 74, // Object Transfer Profile Client Task
TASK_ID_MESH = 200, // Mesh Task
TASK_ID_GAF = 210, // Generic Audio Framework
TASK_ID_AM0 = 240, // BLE Audio Mode 0
TASK_ID_THPP = 242, // Throughput profile tester used for debugging
TASK_ID_INVALID = 0xFF, // Invalid Task Identifier
};
/// @} BT Stack Configuration
/// @} ROOT
#endif //RWIP_CONFIG_H_
+127
View File
@@ -0,0 +1,127 @@
/**
****************************************************************************************
*
* @file rwip_int.h
*
* @brief RW IP internal SW main module
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _RWIP_INT_H_
#define _RWIP_INT_H_
/**
****************************************************************************************
* @addtogroup ROOT
* @brief Entry points of the RW IP stacks/modules
*
* This module contains the primitives that allow an application accessing and running the
* RW IP protocol stacks / modules.
*
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // stack configuration
#include <stdint.h> // standard integer definitions
#include <stdbool.h> // standard boolean definitions
/*
* DEFINES
****************************************************************************************
*/
/*
* STRUCTURE DEFINITIONS
****************************************************************************************
*/
#if (BLE_EMB_PRESENT && BLE_ISO_PRESENT)
/// structure that represents ISO timer
typedef struct rwip_iso_timer_
{
/// Target BTS time (in us)
uint32_t tgt_bts[RWIP_ISO_TIMER_FIFO_DEPTH];
/// Current ISO timer index
uint8_t curr_idx;
/// Next ISO timer index
uint8_t next_idx;
/// Number of ISO timers programmed
uint8_t prog_nb;
} rwip_iso_timer_t;
#endif // (BLE_EMB_PRESENT && BLE_ISO_PRESENT)
/// RWIP Environment structure
struct rwip_env_tag
{
#if (BLE_EMB_PRESENT && BLE_ISO_PRESENT)
rwip_iso_timer_t iso_timer;
#endif // (BLE_EMB_PRESENT && BLE_ISO_PRESENT)
#if (BLE_EMB_PRESENT || BT_EMB_PRESENT)
/// Arbiter target timer (integer part, in half slots)
uint32_t timer_arb_target;
/// Alarm target timer (integer part, in half slots)
uint32_t timer_alarm_target;
#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT)
/// Common target timer (in half slots)
uint32_t timer_co_target;
/// Last Sampled time (used for time conversion)
rwip_time_t last_samp_time;
#if (BLE_EMB_PRESENT || BT_EMB_PRESENT)
/// Contains sleep duration accumulated timing error (32kHz: 1/2 half us | 32.768kHz: 1/256 half-us)
uint32_t sleep_acc_error;
/// Power_up delay (in LP clock cycle unit, depends on Low power clock frequency)
uint32_t lp_cycle_wakeup_delay;
/// Duration of sleep and wake-up algorithm (depends on CPU speed) expressed in half us.
uint16_t sleep_algo_dur;
#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT)
/// Prevent sleep bit field
uint16_t prevent_sleep;
#if (BLE_EMB_PRESENT || BT_EMB_PRESENT)
/// External wake-up support
bool ext_wakeup_enable;
#if (!BLE_EMB_PRESENT)
/// BTS sampling clock half microseconds residual (0 or 1)
uint8_t samp_hus_residual;
#endif // (!BLE_EMB_PRESENT)
#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT)
};
/*
* GLOBAL DEFINITIONS
****************************************************************************************
*/
/// RW SW environment
extern struct rwip_env_tag rwip_env;
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
/**
* Initialization of the RW IP Common core driver
*
* @param[in] init_type Type of initialization (@see enum rwip_init_type)
*/
void rwip_driver_init(uint8_t init_type);
///@} ROOT
#endif // _RWIP_INT_H_
+72
View File
@@ -0,0 +1,72 @@
/*!
* \file shell.h
*
* \brief The head file of shell.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SHELL_H__
#define __SHELL_H__
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "xc6xxx.h"
#include "shell_handler.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define XC_DATA_LEN 64U
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
XC_SHELL_CMD_RECV = 0,
XC_SHELL_CMD_PROC
} eXC_Shell_Proc_state;
typedef struct
{
char *cmd;
eXC_Cmd_State (*fn)(eCMD_Type opt, int srgc, char *srgv[]);
} XC_Cmd_Table_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_shell_test_case(void);
#ifdef __cplusplus
}
#endif
#endif /* __SHELL_H__ */
@@ -0,0 +1,93 @@
/*!
* \file shell.h
*
* \brief The head file of shell_handler.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SHELL_HANDLER_H__
#define __SHELL_HANDLER_H__
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define XC_CMD_SIZE 255U
// XC Command
#define XC_OK "OK"
#define XC_ERROR "+CME ERROR:"
#define XC_CMD_TEST "+TEST"
#define XC_CMD_BLE_MAC "+BMACADDR"
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
XC_CMD_ERROR = -1,
XC_CMD_SUCCESS = 0
} eXC_Cmd_State;
typedef enum
{
QUERY_CMD = 0x00,
SET_CMD
} eCMD_Type;
typedef struct
{
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
uint8_t byte4;
uint8_t byte5;
} BLE_Mac_Addr_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern uint8_t XC_Cmd[XC_CMD_SIZE];
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
eXC_Cmd_State xc_test_handler(eCMD_Type opt, int srgc, char *srgv[]);
eXC_Cmd_State xc_ble_mac_addr_handler(eCMD_Type opt, int srgc, char *srgv[]);
#ifdef __cplusplus
}
#endif
#endif /* __SHELL_HANDLER_H__ */
+199
View File
@@ -0,0 +1,199 @@
/*!
* \file shell.c
*
* \brief Target shell implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "shell.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static XC_Cmd_Table_t XC_CMD_Table[] = {
{ XC_CMD_TEST, xc_test_handler },
{ XC_CMD_BLE_MAC, xc_ble_mac_addr_handler },
};
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define XC_CMD_TABLE_SIZE (sizeof(XC_CMD_Table) / sizeof(XC_Cmd_Table_t))
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
*
* @return[out]
*
****************************************************************************************
*/
void xc_shell_init(void)
{
UART_InitTypeDef UART_InitStruct={0};
UART_InitStruct.Parity = UART_PARITY_DISABLE;
UART_InitStruct.StopBits = UART_STOP_1_BITS;
UART_InitStruct.WordLength = UART_UARTx_TCR_CLS_8BITS;
UART_InitStruct.BaudRate = UART_BAUDRATE_115200;
UART_InitStruct.HardwareFlowControl = UART_UARTx_MCR_AFCE_DISABLE;
UART_Init(XC_UART0, &UART_InitStruct);
UART_Enable_RxIT(XC_UART0);
NVIC_EnableIRQ(UART0_IRQn);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
*
* @return[out]
*
****************************************************************************************
*/
eXC_Cmd_State xc_shell_proc(uint8_t *data, uint16_t data_len)
{
int srgc = 0;
int index = 0;
char *ptr = NULL;
char *srgv[XC_DATA_LEN];
eXC_Cmd_State ret = XC_CMD_ERROR;
uint8_t *rx_cmd = data + 2;
int16_t rx_cmd_idx = data_len - 2;
if(data_len <=2 && data[data_len] == '\0') {
return ret;
}
if(rx_cmd_idx <= 0 || rx_cmd[rx_cmd_idx] != '\0') {
return ret;
}
// 注意这里 XC指令 只判定大写
if(data[0] != 'X' || data[1] != 'C') {
goto xc_end;
}
for(index = 0; index < XC_CMD_TABLE_SIZE; index++) {
int cmd_len = strlen(XC_CMD_Table[index].cmd);
if(!strncmp((const char *)rx_cmd, XC_CMD_Table[index].cmd, cmd_len)) {
ptr = (char *)rx_cmd + cmd_len;
break;
}
}
if (index >= XC_CMD_TABLE_SIZE || !XC_CMD_Table[index].fn) {
goto xc_end;
}
if(ptr[0] == '?') {
ret = XC_CMD_Table[index].fn(QUERY_CMD, srgc, srgv);
} else if(ptr[0] == '=' ) {
ptr += 1;
char *str = strtok((char *)ptr, " ");
while(str) {
srgv[srgc++] = str;
str = strtok((char *)NULL, " ");
}
ret = XC_CMD_Table[index].fn(SET_CMD, srgc, srgv);
} else {
ret = XC_CMD_ERROR;
}
xc_end:
if(ret == XC_CMD_ERROR) {
snprintf((char *)XC_Cmd, XC_CMD_SIZE, "\r\n%s %x\r\n", XC_ERROR, 1);
UART_SendData(XC_UART0, XC_Cmd, strlen((const char *)XC_Cmd));
} else {
UART_SendData(XC_UART0, XC_Cmd, strlen((const char *)XC_Cmd));
}
memset(XC_Cmd, 0, XC_CMD_SIZE);
return ret;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
*
* @return[out]
*
****************************************************************************************
*/
void xc_shell_test_case(void)
{
eXC_Shell_Proc_state sh_sta = XC_SHELL_CMD_RECV;
uint8_t recv_buff[XC_CMD_SIZE] = { 0 };
uint16_t recv_len = 0;
xc_shell_init( );
while(1) {
/* main loop */
switch(sh_sta) {
case XC_SHELL_CMD_RECV: {
recv_len += UART_ReceiveData(XC_UART0, recv_buff+recv_len);
if(recv_len) {
if((recv_buff[recv_len-2] == '\r') &&
(recv_buff[recv_len-1] == '\n'))
sh_sta = XC_SHELL_CMD_PROC;
}
}
break;
case XC_SHELL_CMD_PROC: {
// UART_SendData(XC_UART0, recv_buff, recv_len);
(void)xc_shell_proc(recv_buff, recv_len);
recv_len = 0;
sh_sta = XC_SHELL_CMD_RECV;
}
break;
default:
break;
}
}
}
@@ -0,0 +1,114 @@
/*!
* \file shell_handler.c
*
* \brief Target shell handler implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "shell_handler.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
uint8_t XC_Cmd[XC_CMD_SIZE] = { 0 };
BLE_Mac_Addr_t Mac_Addr;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
*
* @return[out]
*
****************************************************************************************
*/
eXC_Cmd_State xc_test_handler(eCMD_Type opt, int srgc, char *srgv[])
{
eXC_Cmd_State ret = XC_CMD_ERROR;
switch(opt) {
case QUERY_CMD: {
ret = XC_CMD_SUCCESS;
snprintf((char *)XC_Cmd, XC_CMD_SIZE, "\r\n%s\r\n", XC_OK);
}
break;
default:
break;
}
return ret;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
*
* @return[out]
*
****************************************************************************************
*/
eXC_Cmd_State xc_ble_mac_addr_handler(eCMD_Type opt, int srgc, char *srgv[])
{
eXC_Cmd_State ret = XC_CMD_ERROR;
switch(opt) {
case QUERY_CMD: {
ret = XC_CMD_SUCCESS;
snprintf((char *)XC_Cmd, XC_CMD_SIZE, "\r\n%s: %02x:%02x:%02x:%02x:%02x:%02x\r\nOK\r\n",
XC_CMD_BLE_MAC, Mac_Addr.byte0, Mac_Addr.byte1, Mac_Addr.byte2,
Mac_Addr.byte3, Mac_Addr.byte4, Mac_Addr.byte5);
}
break;
case SET_CMD: {
if(srgc < 1) break;
Mac_Addr.byte0 = atoi(srgv[0]);
Mac_Addr.byte1 = atoi(srgv[1]);
Mac_Addr.byte2 = atoi(srgv[2]);
Mac_Addr.byte3 = atoi(srgv[3]);
Mac_Addr.byte4 = atoi(srgv[4]);
Mac_Addr.byte5 = atoi(srgv[5]);
ret = XC_CMD_SUCCESS;
snprintf((char *)XC_Cmd, XC_CMD_SIZE, "\r\n%s: %02x:%02x:%02x:%02x:%02x:%02x\r\nOK\r\n",
XC_CMD_BLE_MAC, Mac_Addr.byte0, Mac_Addr.byte1, Mac_Addr.byte2,
Mac_Addr.byte3, Mac_Addr.byte4, Mac_Addr.byte5);
}
break;
default:
break;
}
return ret;
}