初始化仓库,提交zhongkong工程源码 zsxfly20240415

This commit is contained in:
zsxfly 2024-04-15 09:23:32 +08:00
commit b5bba5e376
704 changed files with 186388 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/.vscode/
output/

BIN
Release Notes SDK.docx Normal file

Binary file not shown.

1213
ble/api/att.h Normal file

File diff suppressed because it is too large Load Diff

1213
ble/api/att.h~RFea659d8.TMP Normal file

File diff suppressed because it is too large Load Diff

592
ble/api/attm_api.h Normal file
View File

@ -0,0 +1,592 @@
/**
****************************************************************************************
*
* @file attm_api.h
*
* @brief Attribute Manager API functions.
*
****************************************************************************************
*/
#ifndef ATTM_API_H_
#define ATTM_API_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "att.h"
#include "task.h"
/*
* MACRO DEFINES
****************************************************************************************
*/
/// update attribute permission on specific handle
#define ATTM_UPDATE_PERM(handle, access, right) \
attm_att_update_perm(handle, (PERM_MASK_ ## access), PERM(access, right))
#define ATTM_UPDATE_PERM_VAL(handle, access, val) \
attm_att_update_perm(handle, (PERM_MASK_ ## access), ((val) << (PERM_POS_ ## access)))
// --------------------------- Database permissions -----------------------------
/// Macro used to retrieve access permission rights
#define PERM_GET(perm, access)\
(((perm) & (PERM_MASK_ ## access)) >> (PERM_POS_ ## access))
/// Macro used to set a permission value
#define PERM_SET(perm, access, value)\
perm = ((perm & ~(PERM_MASK_ ## access)) | ((value << (PERM_POS_ ## access)) & (PERM_MASK_ ## access)))
/// Macro used to retrieve permission value from access and rights on attribute.
#define PERM(access, right) \
(((PERM_RIGHT_ ## right) << (PERM_POS_ ## access)) & (PERM_MASK_ ## access))
/// Macro used know if permission is set or not.
#define PERM_IS_SET(perm, access, right) \
(((perm) & (((PERM_RIGHT_ ## right) << (PERM_POS_ ## access))) \
& (PERM_MASK_ ## access)) == PERM(access, right))
/// Macro used to create permission value
#define PERM_VAL(access, perm) \
((((perm) << (PERM_POS_ ## access))) & (PERM_MASK_ ## access))
/// Retrieve attribute security level from attribute right and service right
#define ATT_GET_SEC_LVL(att_right, svc_right) \
co_max(((att_right) & PERM_RIGHT_AUTH), ((svc_right) & PERM_RIGHT_AUTH));
/// Retrieve UUID LEN from UUID Length Permission
#define ATT_UUID_LEN(uuid_len_perm) ((uuid_len_perm == 0) ? ATT_UUID16_LEN : \
((uuid_len_perm == 1) ? ATT_UUID32_LEN : \
((uuid_len_perm == 2) ? ATT_UUID128_LEN : 0)))
/// Initialization of attribute element
#define ATT_ELEMT_INIT {{NULL}, false}
/**
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
* |EXT | WS | I | N | WR | WC | RD | B | NP | IP | WP | RP |
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
*
* Bit [0-1] : Read Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON)
* Bit [2-3] : Write Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON)
* Bit [4-5] : Indication Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON)
* Bit [6-7] : Notification Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON)
*
* Bit [8] : Extended properties present (only relevant for a characteristic value)
* Bit [9] : Broadcast permission (only relevant for a characteristic value)
* Bit [10] : Write Command accepted
* Bit [11] : Write Signed accepted
* Bit [12] : Write Request accepted
* Bit [13] : Encryption key Size must be 16 bytes
*/
enum attm_perm_mask
{
/// retrieve all permission info
PERM_MASK_ALL = 0x0000,
/// Read Permission Mask
PERM_MASK_RP = 0x0003,
PERM_POS_RP = 0,
/// Write Permission Mask
PERM_MASK_WP = 0x000C,
PERM_POS_WP = 2,
/// Indication Access Mask
PERM_MASK_IP = 0x0030,
PERM_POS_IP = 4,
/// Notification Access Mask
PERM_MASK_NP = 0x00C0,
PERM_POS_NP = 6,
/// Broadcast descriptor present
PERM_MASK_BROADCAST = 0x0100,
PERM_POS_BROADCAST = 8,
/// Read Access Mask
PERM_MASK_RD = 0x0200,
PERM_POS_RD = 9,
/// Write Command Enabled attribute Mask
PERM_MASK_WRITE_COMMAND = 0x0400,
PERM_POS_WRITE_COMMAND = 10,
/// Write Request Enabled attribute Mask
PERM_MASK_WRITE_REQ = 0x0800,
PERM_POS_WRITE_REQ = 11,
/// Notification Access Mask
PERM_MASK_NTF = 0x1000,
PERM_POS_NTF = 12,
/// Indication Access Mask
PERM_MASK_IND = 0x2000,
PERM_POS_IND = 13,
/// Write Signed Enabled attribute Mask
PERM_MASK_WRITE_SIGNED = 0x4000,
PERM_POS_WRITE_SIGNED = 14,
/// Extended properties descriptor present
PERM_MASK_EXT = 0x8000,
PERM_POS_EXT = 15,
/// Properties
PERM_MASK_PROP = 0xFF00,
PERM_POS_PROP = 8,
};
/**
* Value permission bit field
*
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
* | RI |UUID_LEN |EKS | MAX_LEN (RI = 1) / Value Offset (RI = 0) |
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
*
* Bit [0-11] : Maximum Attribute Length or Value Offset pointer
* Bit [12] : Encryption key Size must be 16 bytes
* Bit [14-13]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU)
* Bit [15] : Trigger Read Indication (0 = Value present in Database, 1 = Value not present in Database)
*/
enum attm_value_perm_mask
{
/// Maximum Attribute Length
PERM_MASK_MAX_LEN = 0x0FFF,
PERM_POS_MAX_LEN = 0,
/// Attribute value Offset
PERM_MASK_VAL_OFFSET = 0x0FFF,
PERM_POS_VAL_OFFSET = 0,
/// Check Encryption key size Mask
PERM_MASK_EKS = 0x1000,
PERM_POS_EKS = 12,
/// UUID Length
PERM_MASK_UUID_LEN = 0x6000,
PERM_POS_UUID_LEN = 13,
/// Read trigger Indication
PERM_MASK_RI = 0x8000,
PERM_POS_RI = 15,
};
/**
* Service permissions
*
* 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+
* |SEC |UUID_LEN |DIS | AUTH |EKS | MI |
* +----+----+----+----+----+----+----+----+
*
* Bit [0] : Task that manage service is multi-instantiated (Connection index is conveyed)
* Bit [1] : Encryption key Size must be 16 bytes
* Bit [2-3]: Service Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = Secure Connect)
* Bit [4] : Disable the service
* Bit [5-6]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU)
* Bit [7] : Secondary Service (0 = Primary Service, 1 = Secondary Service)
*/
enum attm_svc_perm_mask
{
/// Task that manage service is multi-instantiated
PERM_MASK_SVC_MI = 0x01,
PERM_POS_SVC_MI = 0,
/// Check Encryption key size for service Access
PERM_MASK_SVC_EKS = 0x02,
PERM_POS_SVC_EKS = 1,
/// Service Permission authentication
PERM_MASK_SVC_AUTH = 0x0C,
PERM_POS_SVC_AUTH = 2,
/// Disable the service
PERM_MASK_SVC_DIS = 0x10,
PERM_POS_SVC_DIS = 4,
/// Service UUID Length
PERM_MASK_SVC_UUID_LEN = 0x60,
PERM_POS_SVC_UUID_LEN = 5,
/// Service type Secondary
PERM_MASK_SVC_SECONDARY = 0x80,
PERM_POS_SVC_SECONDARY = 7,
};
/// Attribute & Service access mode
enum
{
/// Disable access
PERM_RIGHT_DISABLE = 0,
/// Enable access
PERM_RIGHT_ENABLE = 1,
};
/// Attribute & Service access rights
enum
{
/// No Authentication
PERM_RIGHT_NO_AUTH = 0,
/// Access Requires Unauthenticated link
PERM_RIGHT_UNAUTH = 1,
/// Access Requires Authenticated link
PERM_RIGHT_AUTH = 2,
/// Access Requires Secure Connection link
PERM_RIGHT_SEC_CON = 3,
};
/// Attribute & Service UUID Length
enum
{
/// 16 bits UUID
PERM_UUID_16 = 0,
PERM_RIGHT_UUID_16 = 0,
/// 32 bits UUID
PERM_UUID_32 = 1,
PERM_RIGHT_UUID_32 = 1,
/// 128 bits UUID
PERM_UUID_128 = 2,
PERM_RIGHT_UUID_128 = 2,
/// Invalid
PERM_UUID_RFU = 3,
};
/// execute flags
enum
{
/// Cancel All the Reliable Writes
ATT_CANCEL_ALL_PREPARED_WRITES = 0x00,
/// Write All the Reliable Writes
ATT_EXECUTE_ALL_PREPARED_WRITES
};
/*
* DATA STRUCTURES
****************************************************************************************
*/
/// 16bits UUID service description
struct attm_desc
{
/// 16 bits UUID LSB First
uint16_t uuid;
/// Attribute Permissions (@see enum attm_perm_mask)
uint16_t perm;
/// Attribute Extended Permissions (@see enum attm_value_perm_mask)
uint16_t ext_perm;
/// Attribute Max Size
/// note: for characteristic declaration contains handle offset
/// note: for included service, contains target service handle
uint16_t max_size;
};
/// 128bits UUID service description
struct attm_desc_128
{
/// 128 bits UUID LSB First
uint8_t uuid[ATT_UUID128_LEN];
/// Attribute Permissions (@see enum attm_perm_mask)
uint16_t perm;
/// Attribute Extended Permissions (@see enum attm_value_perm_mask)
uint16_t ext_perm;
/// Attribute Max Size
/// note: for characteristic declaration contains handle offset
/// note: for included service, contains target service handle
uint16_t max_size;
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Function use to ease service database creation.
* Use @see attmdb_add_service function of attmdb module to create service database,
* then use @see attmdb_add_attribute function of attmdb module to create attributes
* according to database description array given in parameter.
*
* @note: database description array shall be const to reduce memory consumption (only ROM)
* @note: It supports only 16 bits UUIDs
*
* @note: If shdl = 0, it return handle using first available handle (shdl is
* modified); else it verifies if start handle given can be used to allocates handle range.
*
* @param[in|out] shdl Service start handle.
* @param[in] uuid Service UUID
* @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of
* att_db (Max: 32 attributes); if the bit is set to 1, the
* attribute will be added in the service.
* @param[in] max_nb_att Number of attributes in the service
* @param[in|out] att_tbl Array which will be fulfilled with the difference between
* each characteristic handle and the service start handle.
* This array is useful if several characteristics are optional
* within the service, can be set to NULL if not needed.
* @param[in] dest_id Task ID linked to the service. This task will be notified
* each time the service content is modified by a peer device.
* @param[in|out] att_db Table containing all attributes information
* @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask)
*
* @return Command status code:
* - @ref LE_SUCCESS: If database creation succeeds.
* - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override
* some existing services handles.
* - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer.
* or of new attribute cannot be added because all expected
* attributes already added or buffer overflow detected during
* allocation
****************************************************************************************
*/
uint8_t attm_svc_create_db(uint16_t *shdl, uint16_t uuid, uint8_t *cfg_flag, uint8_t max_nb_att,
uint8_t *att_tbl, task_id_t dest_id,
const struct attm_desc *att_db, uint8_t svc_perm);
/**
****************************************************************************************
* @brief Function use to ease service database creation.
* Use @see attmdb_add_service function of attmdb module to create service database,
* then use @see attmdb_add_attribute function of attmdb module to create attributes
* according to database description array given in parameter.
*
* @note: database description array shall be const to reduce memory consumption (only ROM)
* @note: It supports 128, 32 and 16 bits UUIDs
*
* @note: If shdl = 0, it return handle using first available handle (shdl is
* modified); else it verifies if start handle given can be used to allocates handle range.
*
* @param[in|out] shdl Service start handle.
* @param[in] uuid Service UUID
* @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of
* att_db (Max: 32 attributes); if the bit is set to 1, the
* attribute will be added in the service.
* @param[in] max_nb_att Number of attributes in the service
* @param[in|out] att_tbl Array which will be fulfilled with the difference between
* each characteristic handle and the service start handle.
* This array is useful if several characteristics are optional
* within the service, can be set to NULL if not needed.
* @param[in] dest_id Task ID linked to the service. This task will be notified
* each time the service content is modified by a peer device.
* @param[in|out] att_db Table containing all attributes information
* @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask)
*
* @return Command status code:
* - @ref LE_SUCCESS: If database creation succeeds.
* - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override
* some existing services handles.
* - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer.
* or of new attribute cannot be added because all expected
* attributes already added or buffer overflow detected during
* allocation
****************************************************************************************
*/
uint8_t attm_svc_create_db_128(uint16_t *shdl, const uint8_t* uuid, uint8_t *cfg_flag, uint8_t max_nb_att,
uint8_t *att_tbl, task_id_t dest_id,
const struct attm_desc_128 *att_db, uint8_t svc_perm);
/**
****************************************************************************************
* @brief Function use to verify if several services can be allocated on a contiguous
* handle range. If this command succeed, it means that service allocation will succeed.
*
* If start_hdl = 0, it return handle using first available handle (start_hdl is
* modified); else it verifies if start handle given can be used to allocates handle range.
*
* @param[in|out] start_hdl Service start handle.
* @param[in] nb_att Number of handle to allocate (containing service handles)
*
* @return Command status code:
* - @ref LE_SUCCESS: If service allocation succeeds.
* - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid
****************************************************************************************
*/
uint8_t attm_reserve_handle_range(uint16_t* start_hdl, uint8_t nb_att);
/**
****************************************************************************************
* @brief Update attribute value
*
* Updating attribute value do not trigger any notification or indication, this shall be
* handled by GATT task.
*
* @param[in] handle Attribute handle.
* @param[in] length Size of new attribute value
* @param[in] offset Data offset of in the payload to set
* @param[in] value Attribute value payload
*
* @return Command status code:
* - @ref LE_SUCCESS: If attribute value update succeeds
* - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database
* - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database or
* cannot be modified
* - @ref ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN: If new value length exceeds maximum attribute
* value length.
*
****************************************************************************************
*/
uint8_t attm_att_set_value(uint16_t handle, att_size_t length, att_size_t offset, uint8_t* value);
/**
****************************************************************************************
* @brief Retrieve attribute value
*
* @param[in] handle Attribute handle.
* @param[out] length Size of attribute value
* @param[out] value Pointer to attribute value payload
*
* @return Command status code:
* - @ref LE_SUCCESS: If request succeeds
* - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database
* - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database
****************************************************************************************
*/
uint8_t attm_get_value(uint16_t handle, att_size_t* length, uint8_t** value);
/**
****************************************************************************************
* @brief Update attribute permission
*
* @param[in] handle Attribute handle.
* - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database
* @param[in] perm New attribute permission
* @param[in] ext_perm New attribute extended permission
*
* @return Command status code:
* - @ref LE_SUCCESS: If request succeeds
* - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database
* - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed
****************************************************************************************
*/
uint8_t attm_att_set_perm(uint16_t handle, uint16_t perm, uint16_t ext_perm);
/**
****************************************************************************************
* @brief Reset some permissions bit in the Handle passed as parameter.
*
* @param[in] handle Attribute handle.
* @param[in] access_mask Access mask of permission to update
* @param[in] perm New value of the permission to update
*
*
* @return Command status code:
* - @ref LE_SUCCESS: If request succeeds
* - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database
* - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed
****************************************************************************************
*/
uint8_t attm_att_update_perm(uint16_t handle, uint16_t access_mask, uint16_t perm);
/**
****************************************************************************************
* @brief Update attribute service permission
*
* @param[in] handle Attribute handle.
* @param[in] perm New attribute permission
*
* @return Command status code:
* - @ref LE_SUCCESS: If request succeeds
* - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database
****************************************************************************************
*/
uint8_t attm_svc_set_perm(uint16_t handle, uint8_t perm);
/**
****************************************************************************************
* @brief Retrieve attribute service permission
*
* @param[in] handle Attribute handle.
* @param[out] perm Permission value to return
*
* @return Command status code:
* - @ref LE_SUCCESS: If request succeeds
* - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database
****************************************************************************************
*/
uint8_t attm_svc_get_perm(uint16_t handle, uint8_t* perm);
/**
****************************************************************************************
* @brief Control visibility of a service from peer device. service present in database
* but cannot be access by a peer device.
*
* @param[in] handle Service handle.
* @param[in] hide True to hide the service, False to restore visibility
*
* @return Command status code:
* - @ref LE_SUCCESS: If service allocation succeeds.
* - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid
****************************************************************************************
*/
uint8_t attmdb_svc_visibility_set(uint16_t handle, bool hide);
/**
****************************************************************************************
* @brief Clear database
*
* For debug purpose only, this function clear the database and unalloc all services
* within database.
*
* This function shall be used only for qualification and tests in order to manually
* change database without modifying software.
****************************************************************************************
*/
void attmdb_destroy(void);
/**
****************************************************************************************
* @brief Compare if two UUIDs matches
*
* @param[in] uuid_a UUID A value
* @param[in] uuid_a_len UUID A length
* @param[in] uuid_b UUID B value
* @param[in] uuid_b_len UUID B length
*
* @return true if UUIDs matches, false otherwise
****************************************************************************************
*/
bool attm_uuid_comp(uint8_t *uuid_a, uint8_t uuid_a_len, uint8_t *uuid_b, uint8_t uuid_b_len);
/**
****************************************************************************************
* @brief Check if two UUIDs matches (2nd UUID is a 16 bits UUID with LSB First)
*
* @param[in] uuid_a UUID A value
* @param[in] uuid_a_len UUID A length
* @param[in] uuid_b UUID B 16 bit value
*
* @return true if UUIDs matches, false otherwise
****************************************************************************************
*/
bool attm_uuid16_comp(uint8_t *uuid_a, uint8_t uuid_a_len, uint16_t uuid_b);
/**
****************************************************************************************
* @brief Convert UUID value to 128 bit UUID
*
* @param[out] uuid128 converted 32-bit Bluetooth UUID to 128-bit UUID
* @param[in] uuid UUID to convert to 128-bit UUID
* @param[in] uuid_len UUID length
*
****************************************************************************************
*/
void attm_convert_to128(uint8_t *uuid128, uint8_t *uuid, uint8_t uuid_len);
/**
****************************************************************************************
* @brief Check if it's a Bluetooth 16-bits UUID for 128-bit input
*
* @param[in] uuid 128-bit UUID
*
* @return true if uuid is a Bluetooth 16-bit UUID, false else.
****************************************************************************************
*/
bool attm_is_bt16_uuid(uint8_t *uuid);
/**
****************************************************************************************
* @brief Check if it's a Bluetooth 32 bits UUID for 128-bit input
*
* @param[in] uuid 128-bit UUID
*
* @return true if uuid is a Bluetooth 32-bits UUID, false else.
****************************************************************************************
*/
bool attm_is_bt32_uuid(uint8_t *uuid);
#endif // ATTM_API_H_

238
ble/api/bledef.h Normal file
View File

@ -0,0 +1,238 @@
/**
****************************************************************************************
*
* @file bledef.h
*
* @brief Interface functions of ble stack
*
****************************************************************************************
*/
#ifndef _BLEDEF_H_
#define _BLEDEF_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "blelib.h"
#include "ke_api.h"
#include "gapm_api.h"
#include "gapc_api.h"
#include "gatt_api.h"
#include "prf_api.h"
/*
* DEFINES
****************************************************************************************
*/
/// Status of ble
enum ble_status
{
/// ble in active
BLE_IN_ACTIVE = 0,
/// ble in idle, sys can be put in sleep
BLE_IN_IDLE = 1,
/// ble in sleeping, core can deep sleep soon
BLE_IN_SLEEP = 2,
/// ble in deep sleep, discard status
BLE_IN_DEEPSL = BLE_IN_SLEEP,
/// ble in wakeup, correction ongoing.
BLE_IN_WAKEUP = 4,
};
/// Default LP Cycles of ble_sleep(), unit in 31.25us
#define BLE_SLP_TWOSC (64) // 2ms
#define BLE_SLP_DURMAX (0x7D00) // 1s
/// Judge BLE Lib valid or not, if need
#define BLE_LIB_IS_RIGHT() (ble_exch_size() <= BLE_EXCH_SIZE)
/*
* FUNCTION DECLARATION
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Configure Heap of Ble Stack
*
****************************************************************************************
*/
void ble_heap(heap_cfg_t *cfg);
/**
****************************************************************************************
* @brief Initializes Ble Stack.
*
****************************************************************************************
*/
void ble_init(void);
/**
****************************************************************************************
* @brief Initializes RF & Modem.
*
****************************************************************************************
*/
void rfmdm_init(void);
/**
****************************************************************************************
* @brief Set RF Tx PA Level.
*
* @param[in] pa_target PA Level(0x00 ~ 0x0F). Default(0x0F).
****************************************************************************************
*/
void rf_pa_set(uint8_t pa_target);
/**
****************************************************************************************
* @brief Reset link layer and the host
*
* @return Message GAPM_CMP_EVT(operation GAPM_RESET)
****************************************************************************************
*/
void ble_reset(void);
/**
****************************************************************************************
* @brief Init Task of Application, interval call gapm_reset() to start.
*
****************************************************************************************
*/
void ble_app(void);
/**
****************************************************************************************
* @brief Schedule all pending events.
*
****************************************************************************************
*/
void ble_schedule(void);
#if (BLE_LITELIB)
/**
****************************************************************************************
* @brief Resume BLE quickly to continue run.
*
****************************************************************************************
*/
void ble_resume(void);
#endif //(BLE_LITELIB)
/**
****************************************************************************************
* @brief Wakeup BLE from sleep state.
*
* @return LP Cycles of sleeped time when wakeup enabled, 0 means not in sleep state.
****************************************************************************************
*/
uint32_t ble_wakeup(void);
/**
****************************************************************************************
* @brief BLE try to enter sleep mode.
*
* @param[in] twosc LP Cycles of oscillator stabilization when exit sleep state.
* @param[in] dur_max LP Cycles of max deepsltime, 0 means result of ble_slpdur_get() used.
*
* @return ble status (@see enum ble_status)
****************************************************************************************
*/
uint8_t ble_sleep(uint16_t twosc, uint32_t dur_max);
/**
****************************************************************************************
* @brief Get BLE current time.
*
* @return half-slot time(unit in 312.5us)
****************************************************************************************
*/
uint32_t ble_time_get(void);
/**
****************************************************************************************
* @brief Get max sleep time when BLE is idle state.
*
* @return LP Cycles of sleep time(unit in 31.25us), 0 means prevent sleep
****************************************************************************************
*/
uint32_t ble_slpdur_get(void);
/**
****************************************************************************************
* @brief Get ble6*.lib version.
*
* @return Version Info Struct:
* Byte0 Maximum Actvs - (ACT_MAX<<4) | CON_MAX, eg. 0x43=4ACT3CON
* Byte1 Support Feats - b[4]: Mesh, b[3:0]: Peri|Central|Broadcast|Observer
* Byte2 Build Version - eg. 0
* Byte3 Major Version - eg. 0x13=v1.3
****************************************************************************************
*/
uint32_t ble_lib_vers(void);
/**
****************************************************************************************
* @brief Get memory size of Exchange with BLE HW.
*
* @return size in bytes, aligned 4
****************************************************************************************
*/
uint32_t ble_exch_size(void);
/**
****************************************************************************************
* @brief Config SLAVE_ROLE ACL More Data(MD)
*
* @param[in] en set 1 to allow receiving the ACK in the same event, 0 to disable(default).
*
****************************************************************************************
*/
void ble_txmd_set(uint8_t en);
/**
****************************************************************************************
* @brief Config LPCLK(RC32K) Drift
*
* @param[in] ppm the drift of RC32K, defalut 500ppm.
*
****************************************************************************************
*/
void ble_drift_set(uint16_t ppm);
/**
****************************************************************************************
* @brief Set Sync Word for BLE-2.4G Protocol.
*
* @param[in] syncw Sync Word
****************************************************************************************
*/
void ble_2G4_set(uint16_t sync_l, uint16_t sync_h);
/**
****************************************************************************************
* @brief Set Slave applied latency or not.
*
* @param[in] applied True applied or False no applied.
****************************************************************************************
*/
void ble_latency_applied(bool applied);
/**
****************************************************************************************
* @brief Set channel selection algorithm #2 is supported or not.
*
* @param[in] en set 1 to allow channel selection algorithm #2 is supported, 0 to disable(default).
****************************************************************************************
*/
void ble_txchsel2_set(uint8_t en);
#endif // _BLEDEF_H_

92
ble/api/blelib.h Normal file
View File

@ -0,0 +1,92 @@
/**
****************************************************************************************
*
* @file blelib.h
*
* @brief BLE Lib Definitions.
*
****************************************************************************************
*/
#ifndef _BLELIB_H_
#define _BLELIB_H_
/*
* DEFINITIONS
****************************************************************************************
*/
/// struct *_env_tag *_env
#define __VAR_ENV __attribute__((section("le_env_mem_area"), zero_init))
/// define the BLE Task handler attribute for this compiler
#define __TASKFN __attribute__((section("le_task_hdl_func")))
/// Lite Mode(ble6_lite.lib) or Multi Mode(ble6.lib)
#if (BLE_LITELIB)
/// Maximum number of simultaneous conntions - only 1 slave role, support ultra low power
#define BLE_CONNECTION_MAX (1)
/// Maximum number of simultaneous activities(only 1 Advertising and 1 Connection)
#define BLE_ACTIVITY_MAX (2)
/// Memory usage for BLE HW Exchange - at Retention Memory Area
#define BLE_EXCH_BASE (0x20008000)
#define BLE_EXCH_SIZE (0x0BAC)
#define BLE_EXCH_END (BLE_EXCH_BASE + BLE_EXCH_SIZE)
/// Lite Heap usage for BLE Stack(MEM_ENV + MEM_MSG) - at Retention Memory Area
#define BLE_HEAP_BASE (BLE_EXCH_END)
#define BLE_HEAP_ENV_SIZE (0x600)
#define BLE_HEAP_MSG_SIZE (0x600)
#define BLE_HEAP_SIZE (BLE_HEAP_ENV_SIZE + BLE_HEAP_MSG_SIZE)
#define BLE_HEAP_END (BLE_HEAP_BASE + BLE_HEAP_SIZE)
/// Memory Area for *ble6*.lib (+RW +ZI) - at Retention Memory Area
#define BLE_RWZI_BASE (BLE_HEAP_END)
#define BLE_RWZI_END (0x2000A000)
#define BLE_RWZI_SIZE (BLE_RWZI_END - BLE_RWZI_BASE)
#else //!(BLE_LITELIB)
#if (BLE_LARGELIB)
///Maximum number of simultaneous conntions
#define BLE_CONNECTION_MAX (6)
/// Maximum number of simultaneous activities(Advertising, Scanning, Initiating, Connection)
#define BLE_ACTIVITY_MAX (8)
/// Memory usage for BLE HW Exchange - at Retention Memory Area
#define BLE_EXCH_BASE (0x20008000)
#define BLE_EXCH_SIZE (0x1590)
#else //(BLE_DFLTLIB)
///Maximum number of simultaneous conntions
#define BLE_CONNECTION_MAX (3)
/// Maximum number of simultaneous activities(Advertising, Scanning, Initiating, Connection)
#define BLE_ACTIVITY_MAX (4)
/// Memory usage for BLE HW Exchange - at Retention Memory Area
#define BLE_EXCH_BASE (0x20008000)
#define BLE_EXCH_SIZE (0x0FD8)
#endif //(BLE_DFLTLIB)
#define BLE_EXCH_END (BLE_EXCH_BASE + BLE_EXCH_SIZE)
/// Multi Heap usage for BLE Stack(MEM_ENV + MEM_MSG) - exceed Retention Memory
#if !(BLE_HEAP_BASE)
#define BLE_HEAP_BASE (0x20004E00)
#endif //(BLE_HEAP_BASE)
#if !(BLE_HEAP_ENV_SIZE)
#define BLE_HEAP_ENV_SIZE (0xC00)
#endif //(BLE_HEAP_ENV_SIZE)
#if !(BLE_HEAP_MSG_SIZE)
#define BLE_HEAP_MSG_SIZE (0x2000)
#endif //(BLE_HEAP_ENV_SIZE)
#define BLE_HEAP_SIZE (BLE_HEAP_ENV_SIZE + BLE_HEAP_MSG_SIZE)
/// Memory Area for *ble6*.lib (+RW +ZI) - at Retention Memory Area
#define BLE_RWZI_BASE (BLE_EXCH_END)
#define BLE_RWZI_END (0x2000A000)
#define BLE_RWZI_SIZE (BLE_RWZI_END - BLE_RWZI_BASE)
#endif //(BLE_LITELIB)
#endif /* _BLELIB_H_ */

23
ble/api/fcc.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef B6X_FCC_H_
#define B6X_FCC_H_
#include <stdint.h>
void fcc_init(void);
void fcc_stop(void);
/// freq_idx:0 ~ 39(2402 ~ 2480)
/// Tx调制数据
void fcc_tx_mod(uint8_t freq_idx);
/// Rx调制数据
void fcc_rx_mod(uint8_t freq_idx);
/// Tx单载波(定频)
void fcc_tx_carr(uint8_t freq_idx);
/// Rx单载波(定频)
void fcc_rx_carr(uint8_t freq_idx);
#endif // B6X_FCC_H_

740
ble/api/gap.h Normal file
View File

@ -0,0 +1,740 @@
/**
****************************************************************************************
*
* @file gap.h
*
* @brief Generic Access Profile Header file.
*
****************************************************************************************
*/
#ifndef GAP_H_
#define GAP_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Minimal authorized MTU value (defined by Bluetooth SIG)
#define GAP_MIN_LE_MTU (23)
/// Minimal authorized MTU value if secure connection is supported
#define GAP_MIN_LE_MTU_SEC_CON (65)
/// Maximum MTU (defined in BLE Lib)
#define GAP_MAX_LE_MTU (512)
/// BD address length
#define GAP_BD_ADDR_LEN (6)
/// LE Channel map length
#define GAP_LE_CHNL_MAP_LEN (0x05)
/// LE Feature Flags Length
#define GAP_LE_FEATS_LEN (0x08)
/// ADV Data and Scan Response length
#define GAP_ADV_DATA_LEN (0x1F)
#define GAP_SCAN_RSP_DATA_LEN (0x1F)
/// Random number length
#define GAP_RAND_NB_LEN (0x08)
/// Key length
#define GAP_KEY_LEN (16)
/// P256 Key Len
#define GAP_P256_KEY_LEN (0x20)
///***** AD Type Flag - Bit set *******/
/// Limited discovery flag - AD Flag
#define GAP_LE_LIM_DISCOVERABLE_FLG 0x01
/// General discovery flag - AD Flag
#define GAP_LE_GEN_DISCOVERABLE_FLG 0x02
/// Legacy BT not supported - AD Flag
#define GAP_BR_EDR_NOT_SUPPORTED 0x04
/// Dual mode for controller supported (BR/EDR/LE) - AD Flag
#define GAP_SIMUL_BR_EDR_LE_CONTROLLER 0x08
/// Dual mode for host supported (BR/EDR/LE) - AD Flag
#define GAP_SIMUL_BR_EDR_LE_HOST 0x10
/*********** GAP Miscellaneous Defines *************/
/// Invalid connection index
#define GAP_INVALID_CONIDX 0xFF
/// Invalid connection handle
#define GAP_INVALID_CONHDL 0xFFFF
/// Connection interval min (N*1.250ms)
#define GAP_CONN_INTERVAL_MIN 6 //(7.5ms)
/// Connection interval Max (N*1.250ms)
#define GAP_CONN_INTERVAL_MAX 3200 //(4 sec)
/// Connection latency min (N*cnx evt)
#define GAP_CONN_LATENCY_MIN 0 //(0x00)
/// Connection latency Max (N*cnx evt
#define GAP_CONN_LATENCY_MAX 499 //(0x1F3)
/// Supervision TO min (N*10ms)
#define GAP_CONN_SUP_TO_MIN 10 //(100ms)
/// Supervision TO Max (N*10ms)
#define GAP_CONN_SUP_TO_MAX 3200 //(32 sec)
/// Length of resolvable random address prand part
#define GAP_ADDR_PRAND_LEN (3)
/// Length of resolvable random address hash part
#define GAP_ADDR_HASH_LEN (3)
/// HCI 7.8.33 LE Set Data Length Command
/// Preferred minimum number of payload octets
#define LE_MIN_OCTETS (27)
/// Preferred minimum number of microseconds
#define LE_MIN_TIME (328)
/// Preferred minimum number of microseconds LL:4.5.10
#define LE_MIN_TIME_CODED (2704)
/// Preferred maximum number of payload octets
#define LE_MAX_OCTETS (251)
/// Preferred maximum number of microseconds
#define LE_MAX_TIME (2120)
/// Preferred maximum number of microseconds LL:4.5.10
#define LE_MAX_TIME_CODED (17040)
/*
* DEFINES - Optional for BLE application usage
****************************************************************************************
*/
/// Central idle timer
/// TGAP(conn_pause_central)
/// recommended value: 1 s: (100 for ke timer)
#define GAP_TMR_CONN_PAUSE_CT 0x0064
/// Minimum time upon connection establishment before the peripheral
/// starts a connection update procedure: TGAP(conn_pause_peripheral)
/// recommended value: 5 s: (500 for ke timer)
#define GAP_TMR_CONN_PAUSE_PH 0x01F4
/// Minimum time to perform scanning when user initiated
/// TGAP(scan_fast_period)
/// recommended value: 30.72 s: (3072 for ke timer)
#define GAP_TMR_SCAN_FAST_PERIOD 0x0C00
/// Minimum time to perform advertising when user initiated
/// TGAP(adv_fast_period)
/// recommended value: 30 s: (3000 for ke timer)
#define GAP_TMR_ADV_FAST_PERIOD 0x0BB8
/// Scan interval used during Link Layer Scanning State when
/// performing the Limited Discovery procedure
/// TGAP(lim_disc_scan_int)
/// recommended value: 11.25ms; (18 decimal)
#define GAP_LIM_DISC_SCAN_INT 0x0012
/// Scan interval in any discovery or connection establishment
/// procedure when user initiated: TGAP(scan_fast_interval)
/// recommended value: 30 to 60 ms; N * 0.625
#define GAP_SCAN_FAST_INTV 0x0030
/// Scan window in any discovery or connection establishment
/// procedure when user initiated: TGAP(scan_fast_window)
/// recommended value: 30 ms; N * 0.625
#define GAP_SCAN_FAST_WIND 0x0030
/// Scan interval in any discovery or connection establishment
/// procedure when background scanning: TGAP(scan_slow_interval1)
/// recommended value: 1.28 s : 0x00CD (205); N * 0.625
#define GAP_SCAN_SLOW_INTV1 0x00CD
/// Scan interval in any discovery or connection establishment
/// procedure when background scanning: TGAP(scan_slow_interval2)
/// recommended value: 2.56 s : 0x019A (410); N * 0.625
#define GAP_SCAN_SLOW_INTV2 0x019A
/// Scan window in any discovery or connection establishment
/// procedure when background scanning: TGAP(scan_slow_window1)
/// recommended value: 11.25 ms : 0x0012 (18); N * 0.625
#define GAP_SCAN_SLOW_WIND1 0x0012
/// Scan window in any discovery or connection establishment
/// procedure when background scanning: TGAP(scan_slow_window2)
/// recommended value: 22.5 ms : 0x0024 (36); N * 0.625
#define GAP_SCAN_SLOW_WIND2 0x0024
/// Minimum to maximum advertisement interval in any discoverable
/// or connectable mode when user initiated: TGAP(adv_fast_interval1)
/// recommended value: 30 to 60 ms; N * 0.625
#define GAP_ADV_FAST_INTV1 0x0030
/// Minimum to maximum advertisement interval in any discoverable
/// or connectable mode when user initiated: TGAP(adv_fast_interval2)
/// recommended value: 100 to 150 ms; N * 0.625
#define GAP_ADV_FAST_INTV2 0x0064
/// Minimum to maximum advertisement interval in any discoverable or
/// connectable mode when background advertising: TGAP(adv_slow_interval)
/// recommended value: 1 to 1.2 s : 0x00B0 (176); N * 0.625
#define GAP_ADV_SLOW_INTV 0x00B0
/// Minimum to maximum connection interval upon any connection
/// establishment: TGAP(initial_conn_interval)
/// recommended value: 30 to 50 ms ; N * 1.25 ms
#define GAP_INIT_CONN_MIN_INTV 0x0018
#define GAP_INIT_CONN_MAX_INTV 0x0028
/// Scan Defines
#define GAP_INQ_SCAN_INTV 0x0012
#define GAP_INQ_SCAN_WIND 0x0012
/// Connection supervision timeout
/// recommended value: 20s
#define GAP_CONN_SUPERV_TIMEOUT 0x07D0
/// Minimum connection event
/// default value: 0x0000
#define GAP_CONN_MIN_CE 0x0000
/// Maximum connection event
/// default value: 0xFFFF
#define GAP_CONN_MAX_CE 0xFFFF
/// Connection latency
/// default value: 0x0000
#define GAP_CONN_LATENCY 0x0000
/// Maximum time to remain advertising when in the Limited
/// Discover able mode: TGAP(lim_adv_timeout)
/// required value: 180s: (18000 for ke timer)
#define GAP_TMR_LIM_ADV_TIMEOUT 0x4650
/// Minimum time to perform scanning when performing
/// the General Discovery procedure: TGAP(gen_disc_scan_min)
/// recommended value: 10.24s: (1024 for ke timer)
#define GAP_TMR_GEN_DISC_SCAN 0x0400
/// Minimum time to perform scanning when performing the
/// Limited Discovery procedure: TGAP(lim_disc_scan_min)
/// recommended value: 10.24s: (1024 for ke timer)
#define GAP_TMR_LIM_DISC_SCAN 0x0400
/// Minimum time interval between private address change
/// TGAP(private_addr_int)
/// recommended value: 15 minutes
/// Minimum value 150s
#define GAP_TMR_PRIV_ADDR_MIN (150)
/// Maximum time interval between private address change
/// 0xA1B8 (approximately 11.5 hours)
#define GAP_TMR_PRIV_ADDR_MAX (0xA1B8)
/// Timer used in connection parameter update procedure
/// TGAP(conn_param_timeout)
/// recommended value: 30 s: (3000 for ke timer)
#define GAP_TMR_CONN_PARAM_TIMEOUT 0x0BB8
/// Timer used in LE credit based connection procedure
/// TGAP(lecb_conn_timeout)
/// recommended value: 30 s: (3000 for ke timer)
#define GAP_TMR_LECB_CONN_TIMEOUT 0x0BB8
/// Timer used in LE credit based disconnection procedure
/// TGAP(lecb_disconn_timeout)
/// recommended value: 30 s: (3000 for ke timer)
#define GAP_TMR_LECB_DISCONN_TIMEOUT 0x0BB8
/// GAP Appearance or Icon Characteristic - 2 octets
/// - @url https://specificationrefs.bluetooth.com/assigned-values/Appearance%20Values.pdf
#define GAP_APPEARANCE_UNKNOWN 0x0000 //!< Unknown
#define GAP_APPEARANCE_GENERIC_PHONE 0x0040 //!< Generic Phone
#define GAP_APPEARANCE_GENERIC_COMPUTER 0x0080 //!< Generic Computer
#define GAP_APPEARANCE_GENERIC_WATCH 0x00C0 //!< Generic Watch
#define GAP_APPEARANCE_WATCH_SPORTS 0x00C1 //!< Watch: Sports Watch
#define GAP_APPEARANCE_GENERIC_CLOCK 0x0100 //!< Generic Clock
#define GAP_APPEARANCE_GENERIC_DISPLAY 0x0140 //!< Generic Display
#define GAP_APPEARANCE_GENERIC_RC 0x0180 //!< Generic Remote Control
#define GAP_APPEARANCE_GENERIC_EYE_GALSSES 0x01C0 //!< Generic Eye-glasses
#define GAP_APPEARANCE_GENERIC_TAG 0x0200 //!< Generic Tag
#define GAP_APPEARANCE_GENERIC_KEYRING 0x0240 //!< Generic Keyring
#define GAP_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 //!< Generic Media Player
#define GAP_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 //!< Generic Barcode Scanner
#define GAP_APPEARANCE_GENERIC_THERMOMETER 0x0300 //!< Generic Thermometer
#define GAP_APPEARANCE_GENERIC_THERMO_EAR 0x0301 //!< Thermometer: Ear
#define GAP_APPEARANCE_GENERIC_HR_SENSOR 0x0340 //!< Generic Heart rate Sensor
#define GAP_APPEARANCE_GENERIC_HRS_BELT 0x0341 //!< Heart Rate Sensor: Heart Rate Belt
#define GAP_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 //!< Generic Blood Pressure
#define GAP_APPEARANCE_GENERIC_BP_ARM 0x0381 //!< Blood Pressure: Arm
#define GAP_APPEARANCE_GENERIC_BP_WRIST 0x0382 //!< Blood Pressure: Wrist
#define GAP_APPEARANCE_GENERIC_HID 0x03C0 //!< Generic Human Interface Device (HID)
#define GAP_APPEARANCE_HID_KEYBOARD 0x03C1 //!< HID Keyboard
#define GAP_APPEARANCE_HID_MOUSE 0x03C2 //!< HID Mouse
#define GAP_APPEARANCE_HID_JOYSTIC 0x03C3 //!< HID Joystick
#define GAP_APPEARANCE_HID_GAMEPAD 0x03C4 //!< HID Gamepad
#define GAP_APPEARANCE_HID_DIGITIZER_TYABLET 0x03C5 //!< HID Digitizer Tablet
#define GAP_APPEARANCE_HID_DIGITAL_CARDREADER 0x03C6 //!< HID Card Reader
#define GAP_APPEARANCE_HID_DIGITAL_PEN 0x03C7 //!< HID Digital Pen
#define GAP_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 //!< HID Barcode Scanner
/// GAP Peripheral Preferred Connection Parameter - 8 octets
#define GAP_PPCP_CONN_INTV_MAX 0x0064
#define GAP_PPCP_CONN_INTV_MIN 0x00C8
#define GAP_PPCP_SLAVE_LATENCY 0x0000
#define GAP_PPCP_STO_MULT 0x07D0
/*
* Enumerations
****************************************************************************************
*/
/// GAP Advertising Flags
enum gap_ad_type
{
/// Flag
GAP_AD_TYPE_FLAGS = 0x01,
/// Use of more than 16 bits UUID
GAP_AD_TYPE_MORE_16_BIT_UUID = 0x02,
/// Complete list of 16 bit UUID
GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID = 0x03,
/// Use of more than 32 bit UUD
GAP_AD_TYPE_MORE_32_BIT_UUID = 0x04,
/// Complete list of 32 bit UUID
GAP_AD_TYPE_COMPLETE_LIST_32_BIT_UUID = 0x05,
/// Use of more than 128 bit UUID
GAP_AD_TYPE_MORE_128_BIT_UUID = 0x06,
/// Complete list of 128 bit UUID
GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID = 0x07,
/// Shortened device name
GAP_AD_TYPE_SHORTENED_NAME = 0x08,
/// Complete device name
GAP_AD_TYPE_COMPLETE_NAME = 0x09,
/// Transmit power
GAP_AD_TYPE_TRANSMIT_POWER = 0x0A,
/// Class of device
GAP_AD_TYPE_CLASS_OF_DEVICE = 0x0D,
/// Simple Pairing Hash C
GAP_AD_TYPE_SP_HASH_C = 0x0E,
/// Simple Pairing Randomizer
GAP_AD_TYPE_SP_RANDOMIZER_R = 0x0F,
/// Temporary key value
GAP_AD_TYPE_TK_VALUE = 0x10,
/// Out of Band Flag
GAP_AD_TYPE_OOB_FLAGS = 0x11,
/// Slave connection interval range
GAP_AD_TYPE_SLAVE_CONN_INT_RANGE = 0x12,
/// Require 16 bit service UUID
GAP_AD_TYPE_RQRD_16_BIT_SVC_UUID = 0x14,
/// Require 32 bit service UUID
GAP_AD_TYPE_RQRD_32_BIT_SVC_UUID = 0x1F,
/// Require 128 bit service UUID
GAP_AD_TYPE_RQRD_128_BIT_SVC_UUID = 0x15,
/// Service data 16-bit UUID
GAP_AD_TYPE_SERVICE_16_BIT_DATA = 0x16,
/// Service data 32-bit UUID
GAP_AD_TYPE_SERVICE_32_BIT_DATA = 0x20,
/// Service data 128-bit UUID
GAP_AD_TYPE_SERVICE_128_BIT_DATA = 0x21,
/// Public Target Address
GAP_AD_TYPE_PUB_TGT_ADDR = 0x17,
/// Random Target Address
GAP_AD_TYPE_RAND_TGT_ADDR = 0x18,
/// Appearance
GAP_AD_TYPE_APPEARANCE = 0x19,
/// Advertising Interval
GAP_AD_TYPE_ADV_INTV = 0x1A,
/// LE Bluetooth Device Address
GAP_AD_TYPE_LE_BT_ADDR = 0x1B,
/// LE Role
GAP_AD_TYPE_LE_ROLE = 0x1C,
/// Simple Pairing Hash C-256
GAP_AD_TYPE_SPAIR_HASH = 0x1D,
/// Simple Pairing Randomizer R-256
GAP_AD_TYPE_SPAIR_RAND = 0x1E,
/// 3D Information Data
GAP_AD_TYPE_3D_INFO = 0x3D,
/// Manufacturer specific data
GAP_AD_TYPE_MANU_SPECIFIC_DATA = 0xFF,
};
/// Constant defining the role
enum conn_role
{
/// Master role
ROLE_MASTER,
/// Slave role
ROLE_SLAVE,
};
/// BD address type
enum addr_type
{
/// Public BD address
ADDR_PUBLIC = 0x00,
/// Random BD Address
ADDR_RAND,
/// Controller generates Resolvable Private Address based on the
/// local IRK from resolving list. If resolving list contains no matching
/// entry, use public address.
ADDR_RPA_OR_PUBLIC,
/// Controller generates Resolvable Private Address based on the
/// local IRK from resolving list. If resolving list contains no matching
/// entry, use random address.
ADDR_RPA_OR_RAND,
/// mask used to determine Address type in the air
ADDR_MASK = 0x01,
/// mask used to determine if an address is an RPA
ADDR_RPA_MASK = 0x02,
/// Random device address (controller unable to resolve)
ADDR_RAND_UNRESOLVED = 0xFE,
/// No address provided (anonymous advertisement)
ADDR_NONE = 0xFF,
};
/// Random Address type
enum gap_rnd_addr_type
{
/// Static random address - 11 (MSB->LSB)
GAP_STATIC_ADDR = 0xC0,
/// Private non resolvable address - 01 (MSB->LSB)
GAP_NON_RSLV_ADDR = 0x00,
/// Private resolvable address - 01 (MSB->LSB)
GAP_RSLV_ADDR = 0x40,
};
/// Boolean value set
enum
{
/// Disable
GAP_DISABLE = 0x00,
/// Enable
GAP_ENABLE
};
/// GAP Attribute database handles
/// Generic Access Profile Service
enum
{
GAP_IDX_PRIM_SVC,
GAP_IDX_CHAR_DEVNAME,
GAP_IDX_DEVNAME,
GAP_IDX_CHAR_ICON,
GAP_IDX_ICON,
GAP_IDX_CHAR_SLAVE_PREF_PARAM,
GAP_IDX_SLAVE_PREF_PARAM,
GAP_IDX_CHAR_CNT_ADDR_RESOL,
GAP_IDX_CNT_ADDR_RESOL,
GAP_IDX_CHAR_RSLV_PRIV_ADDR_ONLY,
GAP_IDX_RSLV_PRIV_ADDR_ONLY,
GAP_IDX_NUMBER
};
/****************** GAP Role **********************/
enum gap_role
{
/// No role set yet
GAP_ROLE_NONE = 0x00,
/// Observer role
GAP_ROLE_OBSERVER = 0x01,
/// Broadcaster role
GAP_ROLE_BROADCASTER = 0x02,
/// Master/Central role
GAP_ROLE_CENTRAL = (0x04 | GAP_ROLE_OBSERVER),
/// Peripheral/Slave role
GAP_ROLE_PERIPHERAL = (0x08 | GAP_ROLE_BROADCASTER),
/// Device has all role, both peripheral and central
GAP_ROLE_ALL = (GAP_ROLE_CENTRAL | GAP_ROLE_PERIPHERAL),
};
/// IO Capability Values
enum gap_io_cap
{
/// Display Only
GAP_IO_CAP_DISPLAY_ONLY = 0x00,
/// Display Yes No
GAP_IO_CAP_DISPLAY_YES_NO,
/// Keyboard Only
GAP_IO_CAP_KB_ONLY,
/// No Input No Output
GAP_IO_CAP_NO_INPUT_NO_OUTPUT,
/// Keyboard Display
GAP_IO_CAP_KB_DISPLAY,
GAP_IO_CAP_LAST
};
/// TK Type
enum gap_tk_type
{
/// TK get from out of band method
GAP_TK_OOB = 0x00,
/// TK generated and shall be displayed by local device
GAP_TK_DISPLAY,
/// TK shall be entered by user using device keyboard
GAP_TK_KEY_ENTRY
};
/// OOB Data Present Flag Values
enum gap_oob
{
/// OOB Data not present
GAP_OOB_AUTH_DATA_NOT_PRESENT = 0x00,
/// OOB data present
GAP_OOB_AUTH_DATA_PRESENT,
GAP_OOB_AUTH_DATA_LAST
};
/// Authentication mask
enum gap_auth_mask
{
/// No Flag set
GAP_AUTH_NONE = 0,
/// Bond authentication
GAP_AUTH_BOND = (1 << 0),
/// Man In the middle protection
GAP_AUTH_MITM = (1 << 2),
/// Secure Connection
GAP_AUTH_SEC_CON = (1 << 3),
/// Key Notification
GAP_AUTH_KEY_NOTIF = (1 << 4)
};
/// Security Link Level
enum gap_lk_sec_lvl
{
/// No authentication
GAP_LK_NO_AUTH = 0,
/// Unauthenticated link
GAP_LK_UNAUTH,
/// Authenticated link
GAP_LK_AUTH,
/// Secure Connection link
GAP_LK_SEC_CON,
};
/// Authentication Requirements
enum gap_auth
{
/// No MITM No Bonding
GAP_AUTH_REQ_NO_MITM_NO_BOND = (GAP_AUTH_NONE),
/// No MITM Bonding
GAP_AUTH_REQ_NO_MITM_BOND = (GAP_AUTH_BOND),
/// MITM No Bonding
GAP_AUTH_REQ_MITM_NO_BOND = (GAP_AUTH_MITM),
/// MITM and Bonding
GAP_AUTH_REQ_MITM_BOND = (GAP_AUTH_MITM | GAP_AUTH_BOND),
/// SEC_CON and No Bonding
GAP_AUTH_REQ_SEC_CON_NO_BOND = (GAP_AUTH_SEC_CON),
/// SEC_CON and Bonding
GAP_AUTH_REQ_SEC_CON_BOND = (GAP_AUTH_SEC_CON | GAP_AUTH_BOND),
GAP_AUTH_REQ_LAST,
/// Mask of authentication features without reserved flag
GAP_AUTH_REQ_MASK = 0x1F,
};
/// Key Distribution Flags
enum gap_kdist
{
/// No Keys to distribute
GAP_KDIST_NONE = 0x00,
/// Encryption key in distribution
GAP_KDIST_ENCKEY = (1 << 0),
/// IRK (ID key)in distribution
GAP_KDIST_IDKEY = (1 << 1),
/// CSRK(Signature key) in distribution
GAP_KDIST_SIGNKEY= (1 << 2),
/// LTK in distribution
GAP_KDIST_LINKKEY= (1 << 3),
GAP_KDIST_LAST = (1 << 4)
};
/// Security Defines
enum gap_sec_req
{
/// No security (no authentication and encryption)
GAP_NO_SEC = 0x00,
/// Unauthenticated pairing with encryption
GAP_SEC1_NOAUTH_PAIR_ENC,
/// Authenticated pairing with encryption
GAP_SEC1_AUTH_PAIR_ENC,
/// Unauthenticated pairing with data signing
GAP_SEC2_NOAUTH_DATA_SGN,
/// Authentication pairing with data signing
GAP_SEC2_AUTH_DATA_SGN,
/// Secure Connection pairing with encryption
GAP_SEC1_SEC_CON_PAIR_ENC,
};
/// Bit field use to select the preferred TX or RX LE PHY. 0 means no preferences
enum gap_phy
{
/// No preferred PHY
GAP_PHY_ANY = 0x00,
/// LE 1M PHY preferred for an active link
GAP_PHY_LE_1MBPS = (1 << 0),
/// LE 2M PHY preferred for an active link
GAP_PHY_LE_2MBPS = (1 << 1),
/// LE Coded PHY preferred for an active link
GAP_PHY_LE_CODED = (1 << 2),
};
/// Option for PHY configuration
enum gap_phy_option
{
/// No preference for rate used when transmitting on the LE Coded PHY
GAP_PHY_OPT_LE_CODED_ALL_RATES = 0,
/// S=2, 500kbps rate preferred when transmitting on the LE Coded PHY
GAP_PHY_OPT_LE_CODED_500K_RATE = 1,
/// S=8, 125kbps when transmitting on the LE Coded PHY
GAP_PHY_OPT_LE_CODED_125K_RATE = 2,
};
/// Enumeration of TX/RX PHY used for Test Mode
enum gap_test_phy
{
/// LE 1M PHY (TX or RX)
GAP_TEST_PHY_1MBPS = 1,
/// LE 2M PHY (TX or RX)
GAP_TEST_PHY_2MBPS = 2,
/// LE Coded PHY (RX Only)
GAP_TEST_PHY_CODED = 3,
/// LE Coded PHY with S=8 data coding (TX Only)
GAP_TEST_PHY_125KBPS = 3,
/// LE Coded PHY with S=2 data coding (TX Only)
GAP_TEST_PHY_500KBPS = 4,
};
/// Modulation index
enum gap_modulation_idx
{
/// Assume transmitter will have a standard modulation index
GAP_MODULATION_STANDARD,
/// Assume transmitter will have a stable modulation index
GAP_MODULATION_STABLE,
};
/// Packet Payload type for test mode
enum gap_pkt_pld_type
{
/// PRBS9 sequence "11111111100000111101..." (in transmission order)
GAP_PKT_PLD_PRBS9,
/// Repeated "11110000" (in transmission order)
GAP_PKT_PLD_REPEATED_11110000,
/// Repeated "10101010" (in transmission order)
GAP_PKT_PLD_REPEATED_10101010,
/// PRBS15 sequence
GAP_PKT_PLD_PRBS15,
/// Repeated "11111111" (in transmission order) sequence
GAP_PKT_PLD_REPEATED_11111111,
/// Repeated "00000000" (in transmission order) sequence
GAP_PKT_PLD_REPEATED_00000000,
/// Repeated "00001111" (in transmission order) sequence
GAP_PKT_PLD_REPEATED_00001111,
/// Repeated "01010101" (in transmission order) sequence
GAP_PKT_PLD_REPEATED_01010101,
};
/*************** GAP Structures ********************/
/// Device name
/*@TRACE*/
struct gap_dev_name
{
/// name length
uint16_t length;
/// name value
uint8_t value[];
};
/// Slave preferred connection parameters
/*@TRACE*/
struct gap_slv_pref
{
/// Connection interval minimum
uint16_t con_intv_min;
/// Connection interval maximum
uint16_t con_intv_max;
/// Slave latency
uint16_t slave_latency;
/// Connection supervision timeout multiplier
uint16_t conn_timeout;
};
/// BD Address structure
/*@TRACE*/
typedef struct
{
/// 6-byte array address value
uint8_t addr[GAP_BD_ADDR_LEN];
} bd_addr_t;
/// Channel map structure
/*@TRACE*/
typedef struct
{
/// 5-byte channel map array
uint8_t map[GAP_LE_CHNL_MAP_LEN];
} le_chnl_map_t;
/// Random number structure
/*@TRACE*/
typedef struct
{
/// 8-byte array for random number
uint8_t nb[GAP_RAND_NB_LEN];
} rand_nb_t;
/// P256 Public key data format
typedef struct
{
/// X Coordinate of the key
uint8_t x[GAP_P256_KEY_LEN];
/// X Coordinate of the key
uint8_t y[GAP_P256_KEY_LEN];
} public_key_t;
/// Address information about a device address
/*@TRACE*/
struct gap_bdaddr
{
/// BD Address of device
bd_addr_t addr;
/// Address type of the device 0=public/1=private random
uint8_t addr_type;
};
/// Resolving list device information
/*@TRACE*/
struct gap_ral_dev_info
{
/// Device identity
struct gap_bdaddr addr;
/// Privacy Mode
uint8_t priv_mode;
/// Peer IRK
uint8_t peer_irk[GAP_KEY_LEN];
/// Local IRK
uint8_t local_irk[GAP_KEY_LEN];
};
/// Generic Security key structure
/*@TRACE*/
struct gap_sec_key
{
/// Key value MSB -> LSB
uint8_t key[GAP_KEY_LEN];
};
#endif // GAP_H_

1127
ble/api/gapc.h Normal file

File diff suppressed because it is too large Load Diff

388
ble/api/gapc_api.h Normal file
View File

@ -0,0 +1,388 @@
/**
****************************************************************************************
*
* @file gapc_api.h
*
* @brief Generic Access Profile Controller API functions.
*
****************************************************************************************
*/
#ifndef GAPC_API_H_
#define GAPC_API_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include "gapc.h"
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Response GAPC_CONNECTION_REQ_IND with specific link data configuration.
*
* @param[in] conidx Connection index
* @param[in] auth Authentication(@see gap_auth)
****************************************************************************************
*/
void gapc_connect_rsp(uint8_t conidx, uint8_t auth);
/**
****************************************************************************************
* @brief Response GAPC_PARAM_UPDATE_REQ_IND(Master confirm or not).
*
* @param[in] conidx Connection index
* @param[in] accept True or False to accept slave connection parameters
* @param[in] ce_min Minimum Connection Event Duration
* @param[in] ce_max Maximum Connection Event Duration
****************************************************************************************
*/
void gapc_param_update_rsp(uint8_t conidx, bool accept, uint16_t ce_min, uint16_t ce_max);
/**
****************************************************************************************
* @brief Set the PHY configuration for current active link.
*
* @param[in] conidx Connection index
* @param[in] tx_phy PHY for data transmission(@see enum gap_phy)
* @param[in] rx_phy PHY for data reception(@see enum gap_phy)
* @param[in] phy_opt PHY options(@see enum gapc_phy_option)
*
*@return Message GAPC_LE_PHY_IND
****************************************************************************************
*/
void gapc_update_phy(uint8_t conidx, uint8_t tx_phy, uint8_t rx_phy, uint8_t phy_opt);
/**
****************************************************************************************
* @brief Set the BLE Data Length Extension for current active link.
*
* @param[in] conidx Connection index
* @param[in] tx_octets Length of data transmission(@see LE_MAX_OCTETS)
* @param[in] tx_time Time of data transmission(@see LE_MAX_TIME)
*
*@return Message GAPC_LE_PKT_SIZE_IND
****************************************************************************************
*/
void gapc_update_dle(uint8_t conidx, uint16_t tx_octets, uint16_t tx_time);
/**
****************************************************************************************
* @brief Perform update of connection parameters command.
*
* @param[in] conidx Connection index
* @param[in] param Connection parameters
*
*@return Message GAPC_PARAM_UPDATED_IND
****************************************************************************************
*/
void gapc_update_param(uint8_t conidx, struct gapc_conn_param const* param);
/**
****************************************************************************************
* @brief Request disconnection of current link command.
*
* @param[in] conidx Connection index
* @param[in] reason Reason of disconnection
*
*@return Message GAPC_DISCONNECT_IND
****************************************************************************************
*/
void gapc_disconnect(uint8_t conidx);
/**
****************************************************************************************
* @brief Send gapc_get_info_cmd, Retrieve Connection information
*
* @param[in] conidx Connection index
* @param[in] info Connection information (@see gapc_operation)
****************************************************************************************
*/
void gapc_get_info(uint8_t conidx, uint8_t info);
/**
****************************************************************************************
* @brief Retrieve connection index from connection handle.
*
* @param[in] conhdl Connection handle
*
* @return Return found connection index, GAP_INVALID_CONIDX if not found.
****************************************************************************************
*/
uint8_t gapc_get_conidx(uint16_t conhdl);
/**
****************************************************************************************
* @brief Retrieve connection handle from connection index.
*
* @param[in] conidx Connection index
*
* @return Return found connection handle, GAP_INVALID_CONHDL if not found.
****************************************************************************************
*/
uint16_t gapc_get_conhdl(uint8_t conidx);
/**
****************************************************************************************
* @brief Retrieve connection role from connection index.
*
* @param[in] conidx Connection index
*
* @return Return found connection role
****************************************************************************************
*/
uint8_t gapc_get_role(uint8_t conidx);
/**
****************************************************************************************
* @brief Retrieve link authentication level
*
* @param[in] conidx Connection index
* @return Link authentication level
****************************************************************************************
*/
uint8_t gapc_auth_get(uint8_t conidx);
/**
****************************************************************************************
* @brief Set resolvable address used for connection establishment as local address.
*
* @brief conidx Connection index
* @brief p_addr Pointer to the resolvable address used by either advertising activity or
* resolvable activity.
****************************************************************************************
*/
void gapc_set_local_addr(uint8_t conidx, uint8_t *p_addr);
/**
****************************************************************************************
* @brief Retrieve connection address information on current link.
*
* @param[in] conidx Connection index
* @param[in] src information source(@see gapc_smp_addr_src)
*
* @return Return found connection address
****************************************************************************************
*/
struct gap_bdaddr* gapc_get_bdaddr(uint8_t conidx, uint8_t src);
/**
****************************************************************************************
* @brief Get destination task id for asynchronous event, meaning events that are not
* linked to an operation.
* Note the provided connection index shall be valid (gapc_env[conidx] is not NULL)
*
* @param[in] conidx Connection Index
*
* @return ID of the destination task.
****************************************************************************************
*/
task_id_t gapc_get_dest_task(uint8_t conidx);
/**
****************************************************************************************
* @brief Check if current link support security requirements.
*
* @param[in] conidx Connection index
* @param[in] sec_req Link security requirement to test
*
* @return True if link requirement is supported, False else.
****************************************************************************************
*/
bool gapc_is_sec_set(uint8_t conidx, uint8_t sec_req);
/**
****************************************************************************************
* @brief Retrieve Link Security level
*
* @param[in] conidx Connection index
*
* @return Link Security level.
****************************************************************************************
*/
uint8_t gapc_lk_sec_lvl_get(uint8_t conidx);
/**
****************************************************************************************
* @brief Retrieve the encryption key size of the connection
*
* @param[in] conidx Connection index
*
* @return encryption key size (size is 7 - 16 byte range)
*
****************************************************************************************
*/
uint8_t gapc_enc_keysize_get(uint8_t conidx);
/**
****************************************************************************************
* @brief Get Service Change Client Configuration
*
* @param[in] conidx Connection index
*
* @return Service Change Client Configuration
****************************************************************************************
*/
bool gapc_svc_chg_ccc_get(uint8_t conidx);
/**
****************************************************************************************
* @brief Set Service Change Client Configuration
*
* @param[in] conidx Connection index
* @param[in] enable True if CCC is enabled, False else
*
****************************************************************************************
*/
void gapc_svc_chg_ccc_set(uint8_t conidx, bool enable);
/**
****************************************************************************************
* @brief Send bond request(Master Role).
*
* @param[in] conidx Connection index
* @param[in] feat Pairing Feature(@see gapc_pairing)
****************************************************************************************
*/
void gapc_smp_bond_req(uint8_t conidx, struct gapc_pairing const* feat);
/**
****************************************************************************************
* @brief Send encrypt request(Master Role).
*
* @param[in] conidx Connection index
* @param[in] ltk Long term key(@see gapc_ltk)
****************************************************************************************
*/
void gapc_smp_encrypt_req(uint8_t conidx, struct gapc_ltk const* ltk);
/**
****************************************************************************************
* @brief Send security request.
*
* @param[in] conidx Connection index
* @param[in] auth Authentication req(@see gap_auth)
****************************************************************************************
*/
void gapc_smp_security_req(uint8_t conidx, uint8_t auth);
/**
****************************************************************************************
* @brief Send Keypress Notification.
*
* @param[in] conidx Connection index
* @param[in] keyntf Keypress type req(@see gapc_key_ntf_type)
****************************************************************************************
*/
void gapc_key_press_notify(uint8_t conidx, uint8_t keyntf);
/**
****************************************************************************************
* @brief Respond to peer pairing information request(GAPC_PAIRING_REQ)
*
* @param[in] conidx Connection Index
* @param[in] feat Pairing feature information, NULL means pairing rejected
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_rsp(uint8_t conidx, struct gapc_pairing *feat);
/**
****************************************************************************************
* @brief Handles LTK exchange part of pairing(GAPC_BOND_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] ltk The Long Term Key transmitted by application
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_ltk_exch(uint8_t conidx, struct gapc_ltk* ltk);
/**
****************************************************************************************
* @brief Handles IRK exchange part of pairing(GAPC_BOND_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] irk The Identity Resolving Key transmitted by application
* @param[in] identity Device identity address
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_irk_exch(uint8_t conidx, struct gap_sec_key* irk, struct gap_bdaddr *identity);
/**
****************************************************************************************
* @brief Handles CSRK exchange part of pairing(GAPC_BOND_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] csrk The Connection signature resolving key transmitted by application
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_csrk_exch(uint8_t conidx, struct gap_sec_key *csrk);
/**
****************************************************************************************
* @brief Handles TK exchange part of pairing(GAPC_BOND_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] accept True if pairing is accepted, False else
* @param[in] tk The Temporary Key transmitted by application
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_tk_exch(uint8_t conidx, bool accept, struct gap_sec_key *tk);
#if (SEC_CON_ENB)
/**
****************************************************************************************
* @brief Handles OOB exchange part of pairing(GAPC_BOND_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] accept Accept or Reject the OOB (reject if OOB reception not available on the device)
* @param[in] csrk The OOB Confirm and OOB Rand from the peer
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_oob_exch(uint8_t conidx, bool accept, struct gapc_oob *oob);
/**
****************************************************************************************
* @brief Handles Numeric Value Acceptance as part of pairing(GAPC_BOND_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] accept Accept or Reject the numeric comparison
*
* @return status of pairing
****************************************************************************************
*/
uint8_t gapc_smp_pairing_nc_exch(uint8_t conidx, uint8_t accept);
#endif //(SEC_CON_ENB)
/**
****************************************************************************************
* @brief Slave respond to peer device encryption request(GAPC_ENCRYPT_REQ_IND)
*
* @param[in] conidx Connection Index
* @param[in] key_size Encryption key size(7~16)
* @param[in] ltk 16-bytes LTK(Accept) or NULL(Reject) to start encryption
****************************************************************************************
*/
uint8_t gapc_smp_encrypt_cfm(uint8_t conidx, uint8_t key_size, struct gap_sec_key *ltk);
#endif // GAPC_API_H_

1769
ble/api/gapm.h Normal file

File diff suppressed because it is too large Load Diff

275
ble/api/gapm_api.h Normal file
View File

@ -0,0 +1,275 @@
/**
****************************************************************************************
*
* @file gapm_api.h
*
* @brief Generic Access Profile Manager API functions.
*
****************************************************************************************
*/
#ifndef GAPM_API_H_
#define GAPM_API_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "gapm.h"
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Reset link layer and the host
*
* @return Message GAPM_CMP_EVT(operation GAPM_RESET)
****************************************************************************************
*/
void gapm_reset(void);
/**
****************************************************************************************
* @brief Initial device configuration
*
* @param[in] cfg Configure
*
* @return Message GAPM_CMP_EVT(operation GAPM_SET_DEV_CONFIG)
****************************************************************************************
*/
void gapm_set_dev(const struct gapm_dev_config *cfg, const bd_addr_t *bdaddr, const uint8_t *irk);
/**
****************************************************************************************
* @brief Generate a 8-byte random number
*
* @return Message GAPM_CMP_EVT(operation GAPM_GEN_RAND_NB)
****************************************************************************************
*/
void gapm_gen_rand(void);
/**
****************************************************************************************
* @brief Modify current IRK
*
* @return Message GAPM_CMP_EVT(operation GAPM_SET_IRK)
****************************************************************************************
*/
void gapm_set_irk(uint8_t *irk);
/**
****************************************************************************************
* @brief Create activity.
*
* @param[in] actv_type Activity type(@see gapm_actv_type)
* @param[in] addr_type Own addr type(@see gapm_own_addr)
*
* @return Message GAPM_CMP_EVT(operation GAPM_CREATE_XXX_ACTIVITY) and GAPM_ACTIVITY_CREATED_IND
****************************************************************************************
*/
void gapm_create_activity(uint8_t actv_type, uint8_t addr_type);
/**
****************************************************************************************
* @brief Start activity.
*
* @param[in] actv_idx Activity index
* @param[in] addr_type Own addr type(@see gapm_own_addr)
*
* @return Message GAPM_CMP_EVT(operation GAPM_START_ACTIVITY)
****************************************************************************************
*/
void gapm_start_activity(uint8_t actv_idx, uint16_t param_len, const void* param);
/**
****************************************************************************************
* @brief Stop activity.
*
* @param[in] actv_idx Activity index
*
* @return Message GAPM_CMP_EVT(operation GAPM_STOP_ACTIVITY) and GAPM_ACTIVITY_STOPPED_IND
****************************************************************************************
*/
void gapm_stop_activity(uint8_t actv_idx);
/**
****************************************************************************************
* @brief Delete activity.
*
* @param[in] actv_idx Activity index
*
* @return Message GAPM_CMP_EVT(operation GAPM_DELETE_ACTIVITY)
****************************************************************************************
*/
void gapm_delete_activity(uint8_t actv_idx);
/**
****************************************************************************************
* @brief Create advertising activity.
*
* @param[in] addr_type Own addr type(@see gapm_own_addr)
* @param[in] adv_param Advertising parameters
*
* @return Message GAPM_CMP_EVT(operation GAPM_CREATE_ADV_ACTIVITY) and GAPM_ACTIVITY_CREATED_IND
****************************************************************************************
*/
void gapm_create_advertising(uint8_t addr_type, const struct gapm_adv_create_param *adv_param);
/**
****************************************************************************************
* @brief Start advertising activity.
*
* @param[in] adv_idx Activity index
* @param[in] duration Advertising duration, 0 for always on
*
* @return Message GAPM_CMP_EVT(operation GAPM_START_ACTIVITY)
****************************************************************************************
*/
void gapm_start_advertising(uint8_t adv_idx, uint16_t duration);
/// Macro of Stop advertising
#define gapm_stop_advertising(adv_idx) gapm_stop_activity(adv_idx)
/// Macro of Delete advertising
#define gapm_delete_advertising(adv_idx) gapm_delete_activity(adv_idx)
/**
****************************************************************************************
* @brief Fill advertising data.
*
* @param[in] adv_idx Activity index
* @param[in] op_typ Data operation(GAPM_SET_ADV_DATA or GAPM_SET_SCAN_RSP_DATA)
*
* @return Message GAPM_CMP_EVT(operation GAPM_SET_ADV_DATA or GAPM_SET_SCAN_RSP_DATA)
****************************************************************************************
*/
void gapm_set_adv_data(uint8_t adv_idx, uint8_t op_typ, uint16_t len, const uint8_t *data);
/**
****************************************************************************************
* @brief Retrieve local public address.
*
* @return Return local public address
****************************************************************************************
*/
bd_addr_t* gapm_get_bdaddr(void);
/**
****************************************************************************************
* @brief Retrieve the device address type (@see enum gapm_addr_type)
*
* @return address type
****************************************************************************************
*/
uint8_t gapm_get_address_type(void);
/**
****************************************************************************************
* @brief Returns the local Public Key
*
* @return pointer to the local Public Key
****************************************************************************************
*/
public_key_t* gapm_get_local_public_key(void);
/**
****************************************************************************************
* @brief Retrieve if Legacy pairing is supported on local device
*
* @return True if legacy pairing is supported
****************************************************************************************
*/
bool gapm_is_legacy_pairing_supp(void);
/**
****************************************************************************************
* @brief Retrieve if Secure Connection pairing is supported on local device
*
* @return True if Secure Connection pairing is supported
****************************************************************************************
*/
bool gapm_is_sec_con_pairing_supp(void);
/**
****************************************************************************************
* @brief Set the pairing mode is supported on local device
*
* @param[in] mode Pairing supported (@see gapm_pairing_mode)
****************************************************************************************
*/
void gapm_set_pairing_supp(uint8_t mode);
/**
****************************************************************************************
* @brief Return the maximal MTU value
*
* @return Maximal MTU value
****************************************************************************************
*/
uint16_t gapm_get_max_mtu(void);
/**
****************************************************************************************
* @brief Set the maximal MTU value
*
* @param[in] mtu Max MTU value (Minimum is 23)
****************************************************************************************
*/
void gapm_set_max_mtu(uint16_t mtu);
/**
****************************************************************************************
* @brief Return the maximal MPS value
*
* @return Maximal MPS value
****************************************************************************************
*/
uint16_t gapm_get_max_mps(void);
/**
****************************************************************************************
* @brief Set the maximal MPS value
*
* @param[in] mps Max MPS value (Minimum is 23)
****************************************************************************************
*/
void gapm_set_max_mps(uint16_t mps);
/**
****************************************************************************************
* @brief Get if preferred connection parameters present in GAP ATT database
*
* @return True if referred connection parameters present in GAP ATT database, False else
****************************************************************************************
*/
bool gapm_is_pref_con_param_pres(void);
/**
****************************************************************************************
* @brief retrieve gap attribute handle from attribute index.
*
* @param[in] att_idx Attribute index
*
* @return Attribute handle
****************************************************************************************
*/
uint16_t gapm_get_att_handle(uint8_t att_idx);
/**
****************************************************************************************
* @brief Check If Service changed feature is enabled or not
*
* @return true if enabled, false else.
****************************************************************************************
*/
bool gapm_svc_chg_en(void);
#endif // GAPM_API_H_

850
ble/api/gatt.h Normal file
View File

@ -0,0 +1,850 @@
/**
****************************************************************************************
*
* @file gatt.h
*
* @brief Generic Attribute Profile Messages.
*
****************************************************************************************
*/
#ifndef _GATT_H_
#define _GATT_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "le_err.h"
#include "task.h"
#include "att.h"
#include "gap.h"
/*
* DEFINES
****************************************************************************************
*/
/// Macro for Instance of GATT TASK
#define GATT(idx) TASK_ID(GATT, idx)
/// GATT Task messages
/*@TRACE*/
enum gatt_msg_id
{
/* Default event */
/// Command Complete event
GATT_CMP_EVT = MSG_ID(GATT, 0x00),
/* ATTRIBUTE CLIENT */
GATT_CLIENT_CMD = MSG_ID(GATT, 0x01),
/// Server configuration request
GATT_EXC_MTU_CMD = GATT_CLIENT_CMD, //MSG_ID(GATT, 0x01),
/*Discover All Services */
/*Discover Services by Service UUID*/
/*Find Included Services*/
/*Discover Characteristics by UUID*/
/*Discover All Characteristics of a Service*/
/*Discover All Characteristic Descriptors*/
/// Discovery command
GATT_DISC_CMD = GATT_CLIENT_CMD, //MSG_ID(GATT, 0x03),
/*Read Value*/
/*Read Using UUID*/
/*Read Long Value*/
/*Read Multiple Values*/
/// Read command
GATT_READ_CMD = GATT_CLIENT_CMD, //MSG_ID(GATT, 0x08),
/*Write without response*/
/*Write without response with Authentication*/
/*Write Characteristic Value*/
/*Signed Write Characteristic Value*/
/*Write Long Characteristic Value*/
/*Characteristic Value Reliable Write*/
/*Write Characteristic Descriptors*/
/*Write Long Characteristic Descriptors*/
/*Characteristic Value Reliable Write*/
/// Write command request
GATT_WRITE_CMD = GATT_CLIENT_CMD, //MSG_ID(GATT, 0x0A),
/* Cancel / Execute pending write operations */
/// Execute write characteristic request
GATT_EXECUTE_WRITE_CMD = GATT_CLIENT_CMD, //MSG_ID(GATT, 0x0B),
/// Indicate that the ATT MTU has been updated (negotiated)
GATT_MTU_CHANGED_IND = MSG_ID(GATT, 0x02),
/* GATT -> HL: Events to Upper layer */
/*Discover All Services*/
/// Discovery services indication
GATT_DISC_SVC_IND = MSG_ID(GATT, 0x04),
/*Find Included Services*/
/// Discover included services indication
GATT_DISC_SVC_INCL_IND = MSG_ID(GATT, 0x05),
/*Discover All Characteristics of a Service*/
/// Discover characteristic indication
GATT_DISC_CHAR_IND = MSG_ID(GATT, 0x06),
/*Discover All Characteristic Descriptors*/
/// Discovery characteristic descriptor indication
GATT_DISC_CHAR_DESC_IND = MSG_ID(GATT, 0x07),
/// Read response
GATT_READ_IND = MSG_ID(GATT, 0x09),
/* Reception of an indication or notification from peer device. */
/// peer device triggers an event (notification)
GATT_EVENT_IND = MSG_ID(GATT, 0x0C),
/// peer device triggers an event that requires a confirmation (indication)
GATT_EVENT_REQ_IND = MSG_ID(GATT, 0x0D),
/// Confirm reception of event (trigger a confirmation message)
GATT_EVENT_CFM = MSG_ID(GATT, 0x0E),
/// Registration to peer device events (Indication/Notification).
GATT_REG_TO_PEER_EVT_CMD = MSG_ID(GATT, 0x0F),
/* -------------------------- ATTRIBUTE SERVER ------------------------------- */
/*Notify Characteristic*/
/*Indicate Characteristic*/
/// send an event to peer device
GATT_SEND_EVT_CMD = MSG_ID(GATT, 0x10),
GATT_SERVER_CFM = MSG_ID(GATT, 0x11),
/// REad command confirmation from upper layers.
GATT_READ_CFM = GATT_SERVER_CFM, //MSG_ID(GATT, 0x14),
/// Write command confirmation from upper layers.
GATT_WRITE_CFM = GATT_SERVER_CFM, //= MSG_ID(GATT, 0x16),
/// Attribute info from upper layer confirmation
GATT_ATT_INFO_CFM = GATT_SERVER_CFM, //= MSG_ID(GATT, 0x18),
/* Indicate that read operation is requested. */
/// Read command indicated to upper layers.
GATT_READ_REQ_IND = MSG_ID(GATT, 0x13),
/* Indicate that write operation is requested. */
/// Write command indicated to upper layers.
GATT_WRITE_REQ_IND = MSG_ID(GATT, 0x15),
/* Indicate that write operation is requested. */
/// Request Attribute info to upper layer - could be trigger during prepare write
GATT_ATT_INFO_REQ_IND = MSG_ID(GATT, 0x17),
/* ----------------------- SERVICE DISCOVERY PROCEDURE ---------------------- */
/// Service Discovery command
GATT_SDP_SVC_DISC_CMD = MSG_ID(GATT, 0x19),
/// Service Discovery indicate that a service has been found.
GATT_SDP_SVC_IND = MSG_ID(GATT, 0x1A),
/* -------------------------- TRANSACTION ERROR EVENT ------------------------ */
/// Transaction Timeout Error Event no more transaction will be accepted
GATT_TRANSACTION_TO_ERROR_IND = MSG_ID(GATT, 0x1B),
/// Indication to the task that sends the unknown message
GATT_UNKNOWN_MSG_IND = MSG_ID(GATT, 0x1C),
/* --------------------------------- ROBUST CACHE --------------------------------- */
/// Command used to read peer database hash
GATT_READ_DB_HASH_CMD = MSG_ID(GATT, 0x20),
/// Provide value of the peer database hash
GATT_DB_HASH_IND = MSG_ID(GATT, 0x21),
/// Command used to enable Robust database caching
/// (Register to service changed, Set client supported features and read database hash)
GATT_ROBUST_DB_CACHE_EN_CMD = MSG_ID(GATT, 0x22),
/// Informs that peer database updated and need to be refreshed
/// This also means that no more indication/notification will be received till database hash isn't read
GATT_DB_CACHE_OUT_OF_SYNC_IND = MSG_ID(GATT, 0x23),
/// Informs that peer device database updated using service changed indication
GATT_SVC_CHG_REQ_IND = MSG_ID(GATT, 0x24),
/// Message used to confirm that database updated is understood by application
GATT_SVC_CHG_CFM = MSG_ID(GATT, 0x25),
/* ----------------------------------- GATT INFO ---------------------------------- */
/// Provide information about GATT for current connection that can be reuse on another connection
GATT_CON_INFO_IND = MSG_ID(GATT, 0x28),
};
/// request operation type - application interface
/*@TRACE*/
enum gatt_operation
{
/* Attribute Client Flags */
/* No Operation (if nothing has been requested) */
/* ************************************************ */
/// No operation
GATT_NO_OP = 0x00,
/* Operation flags for MTU Exchange */
/* ************************************************ */
/// Perform MTU exchange
GATT_MTU_EXCH = 0x01,
/* Operation flags for discovery operation */
/* ************************************************ */
/// Discover all services
GATT_DISC_ALL_SVC = 0x02,
/// Discover services by UUID
GATT_DISC_BY_UUID_SVC = 0x03,
/// Discover included services
GATT_DISC_INCLUDED_SVC = 0x04,
/// Discover all characteristics
GATT_DISC_ALL_CHAR = 0x05,
/// Discover characteristic by UUID
GATT_DISC_BY_UUID_CHAR = 0x06,
/// Discover characteristic descriptor
GATT_DISC_DESC_CHAR = 0x07,
/* Operation flags for reading attributes */
/* ************************************************ */
/// Read attribute
GATT_READ = 0x08,
/// Read long attribute
GATT_READ_LONG = 0x09,
/// Read attribute by UUID
GATT_READ_BY_UUID = 0x0A,
/// Read multiple attribute
GATT_READ_MULTIPLE = 0x0B,
/* Operation flags for writing/modifying attributes */
/* ************************************************ */
/// Write attribute
GATT_WRITE = 0x0C,
/// Write no response
GATT_WRITE_NO_RESPONSE = 0x0D,
/// Write signed
GATT_WRITE_SIGNED = 0x0E,
/// Execute write
GATT_EXEC_WRITE = 0x0F,
/* Operation flags for registering to peer device */
/* ************************************************ */
/// Register to peer device events
GATT_REGISTER = 0x10,
/// Unregister from peer device events
GATT_UNREGISTER = 0x11,
/* Operation flags for sending events to peer device*/
/* ************************************************ */
/// Send an attribute notification
GATT_NOTIFY = 0x12,
/// Send an attribute indication
GATT_INDICATE = 0x13,
/// Send a service changed indication
GATT_SVC_CHANGED = 0x14,
/* Service Discovery Procedure */
/* ************************************************ */
/// Search specific service
GATT_SDP_DISC_SVC = 0x15,
/// Search for all services
GATT_SDP_DISC_SVC_ALL = 0x16,
/// Cancel Service Discovery Procedure
GATT_SDP_DISC_CANCEL = 0x17,
/* Robust Cache */
/* ************************************************ */
/// Read peer database hash
GATT_READ_DB_HASH = 0x20,
/// Enable Robust database cache feature
GATT_ROBUST_DB_CACHE_EN = 0x21,
GATT_READ_RSP = 0x40,
GATT_WRITE_RSP = 0x41,
GATT_ATT_INFO_RSP = 0x42,
};
/// Service Discovery Attribute type
/*@TRACE*/
enum gatt_sdp_att_type
{
/// No Attribute Information
GATT_SDP_NONE,
/// Included Service Information
GATT_SDP_INC_SVC,
/// Characteristic Declaration
GATT_SDP_ATT_CHAR,
/// Attribute Value
GATT_SDP_ATT_VAL,
/// Attribute Descriptor
GATT_SDP_ATT_DESC,
};
/// Command complete event data structure
struct gatt_op_cmd
{
/// GATT request type
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
};
/// Command complete event data structure
/*@TRACE*/
struct gatt_cmp_evt
{
/// GATT request type
uint8_t operation;
/// Status of the request
uint8_t status;
/// operation sequence number - provided when operation is started
uint16_t seq_num;
};
/// Service Discovery Command Structure
/*@TRACE*/
struct gatt_exc_mtu_cmd
{
/// GATT request type
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
};
/// Indicate that the ATT MTU has been updated (negotiated)
/*@TRACE*/
struct gatt_mtu_changed_ind
{
/// Exchanged MTU value
uint16_t mtu;
/// operation sequence number
uint16_t seq_num;
};
/// Service Discovery Command Structure
/*@TRACE*/
struct gatt_disc_cmd
{
/// GATT request type
uint8_t operation;
/// UUID length
uint8_t uuid_len;
/// operation sequence number
uint16_t seq_num;
/// start handle range
uint16_t start_hdl;
/// start handle range
uint16_t end_hdl;
/// UUID
uint8_t uuid[];
};
/// Discover Service indication Structure
/*@TRACE*/
struct gatt_disc_svc_ind
{
/// start handle
uint16_t start_hdl;
/// end handle
uint16_t end_hdl;
/// UUID length
uint8_t uuid_len;
/// service UUID
uint8_t uuid[];
};
/// Discover Service indication Structure
/*@TRACE*/
struct gatt_disc_svc_incl_ind
{
/// element handle
uint16_t attr_hdl;
/// start handle
uint16_t start_hdl;
/// end handle
uint16_t end_hdl;
/// UUID length
uint8_t uuid_len;
/// included service UUID
uint8_t uuid[];
};
/// Discovery All Characteristic indication Structure
/*@TRACE*/
struct gatt_disc_char_ind
{
/// database element handle
uint16_t attr_hdl;
/// pointer attribute handle to UUID
uint16_t pointer_hdl;
/// properties
uint8_t prop;
/// UUID length
uint8_t uuid_len;
/// characteristic UUID
uint8_t uuid[];
};
/// Discovery Characteristic Descriptor indication Structure
/*@TRACE*/
struct gatt_disc_char_desc_ind
{
/// database element handle
uint16_t attr_hdl;
/// UUID length
uint8_t uuid_len;
/// Descriptor UUID
uint8_t uuid[];
};
/// Simple Read (GATT_READ or GATT_READ_LONG)
/*@TRACE
gatt_read = gatt_read_simple
gatt_read_long = gatt_read_simple*/
struct gatt_read_simple
{
/// attribute handle
uint16_t handle;
/// start offset in data payload
uint16_t offset;
/// Length of data to read (0 = read all)
uint16_t length;
};
/// Read by UUID: search UUID and read it's characteristic value (GATT_READ_BY_UUID)
/// Note: it doesn't perform an automatic read long.
/*@TRACE*/
struct gatt_read_by_uuid
{
/// Start handle
uint16_t start_hdl;
/// End handle
uint16_t end_hdl;
/// Size of UUID
uint8_t uuid_len;
/// UUID value
uint8_t uuid[];
};
/// Read Multiple short characteristic (GATT_READ_MULTIPLE)
/*@TRACE*/
struct gatt_read_multiple
{
/// attribute handle
uint16_t handle;
/// Known Handle length (shall be != 0)
uint16_t len;
};
/// request union according to read type
/*@TRACE
@trc_ref gatt_operation
*/
union gatt_read_req
{
/// Simple Read (GATT_READ or GATT_READ_LONG)
//@trc_union parent.operation == GATT_READ or parent.operation == GATT_READ_LONG
struct gatt_read_simple simple;
/// Read by UUID (GATT_READ_BY_UUID)
//@trc_union parent.operation == GATT_READ_BY_UUID
struct gatt_read_by_uuid by_uuid;
/// Read Multiple short characteristic (GATT_READ_MULTIPLE)
//@trc_union parent.operation == GATT_READ_MULTIPLE
struct gatt_read_multiple multiple[1];
};
/// Read command (Simple, Long, Multiple, or by UUID)
/*@TRACE*/
struct gatt_read_cmd
{
/// request type
uint8_t operation;
/// number of read (only used for multiple read)
uint8_t nb;
/// operation sequence number
uint16_t seq_num;
/// request union according to read type
union gatt_read_req req;
};
/// Attribute value read indication
/*@TRACE*/
struct gatt_read_ind
{
/// Attribute handle
uint16_t handle;
/// Read offset
uint16_t offset;
/// Read length
uint16_t length;
/// Handle value
uint8_t value[];
};
/// Write peer attribute value command
/*@TRACE*/
struct gatt_write_cmd
{
/// Request type
uint8_t operation;
/// Perform automatic execution
/// (if false, an ATT Prepare Write will be used this shall be use for reliable write)
bool auto_execute;
/// operation sequence number
uint16_t seq_num;
/// Attribute handle
uint16_t handle;
/// Write offset
uint16_t offset;
/// Write length
uint16_t length;
/// Internal write cursor shall be initialized to 0
uint16_t cursor;
/// Value to write
uint8_t value[];
};
/// Write peer attribute value command
/*@TRACE*/
struct gatt_execute_write_cmd
{
/// Request type
uint8_t operation;
/// [True = perform/False cancel] pending write operations
bool execute;
/// operation sequence number
uint16_t seq_num;
};
/// peer device triggers an event (notification)
/*@TRACE*/
struct gatt_event_ind
{
/// Event Type
uint8_t type;
/// Data length
uint16_t length;
/// Attribute handle
uint16_t handle;
/// Event Value
uint8_t value[];
};
/// peer device triggers an event that requires a confirmation (indication)
/*@TRACE*/
struct gatt_event_req_ind
{
/// Event Type
uint8_t type;
/// Data length
uint16_t length;
/// Attribute handle
uint16_t handle;
/// Event Value
uint8_t value[];
};
/// Confirm reception of event (trigger a confirmation message)
/*@TRACE*/
struct gatt_event_cfm
{
/// Attribute handle
uint16_t handle;
};
/// Register to peer device events command
/*@TRACE*/
struct gatt_reg_to_peer_evt_cmd
{
/// Request type
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
/// attribute start handle
uint16_t start_hdl;
/// attribute end handle
uint16_t end_hdl;
};
/// Send an event to peer device
/*@TRACE*/
struct gatt_send_evt_cmd
{
/// Request type (notification / indication)
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
/// characteristic handle
uint16_t handle;
/// length of packet to send
uint16_t length;
/// data value
uint8_t value[];
};
/// Inform that attribute value is requested by lower layers.
/*@TRACE*/
struct gatt_read_req_ind
{
/// Handle of the attribute that has to be read
uint16_t handle;
};
/// Confirm Read Request requested by GATT to profile
/*@TRACE*/
struct gatt_read_cfm
{
/// Response type
uint8_t operation;
/// Status of read command execution by upper layers
uint8_t status;
/// Handle of the attribute read
uint16_t handle;
/// Data length read
uint16_t length;
/// attribute data value
uint8_t value[];
};
/// Inform that a modification of database has been requested by peer device.
/*@TRACE*/
struct gatt_write_req_ind
{
/// Handle of the attribute that has to be written
uint16_t handle;
/// offset at which the data has to be written
uint16_t offset;
/// Data length to be written
uint16_t length;
/// Data to be written in attribute database
uint8_t value[];
};
/// Confirm modification of database from upper layer when requested by peer device.
/*@TRACE*/
struct gatt_write_cfm
{
/// Response type
uint8_t operation;
/// Status of write command execution by upper layers
uint8_t status;
/// Handle of the attribute written
uint16_t handle;
};
/// Parameters for @ref GATT_SEND_SVC_CHANGED_CMD message
/*@TRACE*/
struct gatt_send_svc_changed_cmd
{
/// Request Type
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
/// Start of Affected Attribute Handle Range
uint16_t svc_shdl;
/// End of Affected Attribute Handle Range
uint16_t svc_ehdl;
};
/// Parameters for @ref GATT_SVC_CHANGED_CFG_IND and @ref GATT_SVC_CHANGED message
/*@TRACE*/
struct gatt_svc_changed_cfg
{
/**
* Current value of the Client Characteristic Configuration descriptor for the Service
* Changed characteristic
*/
uint16_t ind_cfg;
};
/// Request Attribute info to upper layer - could be trigger during prepare write
/*@TRACE*/
struct gatt_att_info_req_ind
{
/// Handle of the attribute for which info are requested
uint16_t handle;
};
/// Attribute info from upper layer confirmation
/*@TRACE*/
struct gatt_att_info_cfm
{
/// Response type
uint8_t operation;
/// use to know if it's possible to modify the attribute
/// can contains authorization or application error code.
uint8_t status;
/// Handle of the attribute
uint16_t handle;
/// Current length of the attribute
uint16_t length;
};
/// Service Discovery command
/*@TRACE*/
struct gatt_sdp_svc_disc_cmd
{
/// GATT Request Type
/// - GATT_SDP_DISC_SVC Search specific service
/// - GATT_SDP_DISC_SVC_ALL Search for all services
/// - GATT_SDP_DISC_CANCEL Cancel Service Discovery Procedure
uint8_t operation;
/// Service UUID Length
uint8_t uuid_len;
/// operation sequence number
uint16_t seq_num;
/// Search start handle
uint16_t start_hdl;
/// Search end handle
uint16_t end_hdl;
/// Service UUID
uint8_t uuid[ATT_UUID128_LEN];
};
/// Information about included service
/*@TRACE*/
struct gatt_sdp_include_svc
{
/// Attribute Type
/// - GATT_SDP_INC_SVC: Included Service Information
uint8_t att_type;
/// Included service UUID Length
uint8_t uuid_len;
/// Included Service UUID
uint8_t uuid[ATT_UUID128_LEN];
/// Included service Start Handle
uint16_t start_hdl;
/// Included service End Handle
uint16_t end_hdl;
};
/// Information about attribute characteristic
/*@TRACE*/
struct gatt_sdp_att_char
{
/// Attribute Type
/// - GATT_SDP_ATT_CHAR: Characteristic Declaration
uint8_t att_type;
/// Value property
uint8_t prop;
/// Value Handle
uint16_t handle;
};
/// Information about attribute
/*@TRACE*/
struct gatt_sdp_att
{
/// Attribute Type
/// - GATT_SDP_ATT_VAL: Attribute Value
/// - GATT_SDP_ATT_DESC: Attribute Descriptor
uint8_t att_type;
/// Attribute UUID Length
uint8_t uuid_len;
/// Attribute UUID
uint8_t uuid[ATT_UUID128_LEN];
};
/// Attribute information
/*@TRACE
@trc_ref gatt_sdp_att_type
*/
union gatt_sdp_att_info
{
/// Attribute Type
uint8_t att_type;
/// Information about attribute characteristic
//@trc_union att_type == GATT_SDP_ATT_CHAR
struct gatt_sdp_att_char att_char;
/// Information about included service
//@trc_union att_type == GATT_SDP_INC_SVC
struct gatt_sdp_include_svc inc_svc;
/// Information about attribute
//@trc_union att_type == GATT_SDP_ATT_VAL or att_type == GATT_SDP_ATT_DESC
struct gatt_sdp_att att;
};
/// Service Discovery indicate that a service has been found.
/*@TRACE
@trc_arr info $end_hdl - $start_hdl
*/
struct gatt_sdp_svc_ind
{
/// Service UUID Length
uint8_t uuid_len;
/// Service UUID
uint8_t uuid[ATT_UUID128_LEN];
/// Service start handle
uint16_t start_hdl;
/// Service end handle
uint16_t end_hdl;
/// attribute information present in the service
/// (length = end_hdl - start_hdl)
union gatt_sdp_att_info info[];
};
/// Indicate that an unknown message has been received
/*@TRACE*/
struct gatt_unknown_msg_ind
{
/// Unknown message id
msg_id_t unknown_msg_id;
};
/// Command used to enable Robust database caching
/// (Register to service changed, Set client supported features and read database hash)
/*@TRACE*/
struct gatt_robust_db_cache_en_cmd
{
/// GATT Request Type
/// - GATT_ROBUST_DB_CACHE_EN Enable Robust database caching
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
};
/// Command used to read peer database hash
/*@TRACE*/
struct gatt_read_db_hash_cmd
{
/// GATT Request Type
/// - GATT_READ_DB_HASH Read peer database hash
uint8_t operation;
/// operation sequence number
uint16_t seq_num;
};
/// Provide value of the peer database hash
/*@TRACE*/
struct gatt_db_hash_ind
{
/// Database Hash
uint8_t hash[GAP_KEY_LEN];
};
/// Informs that peer device database updated using service changed indication
/*@TRACE
@trc_arr info $end_hdl - $start_hdl
*/
struct gatt_svc_chg_req_ind
{
/// Start handle
uint16_t start_handle;
/// End Handle
uint16_t end_handle;
};
/// Provide information about GATT for current connection that can be reuse on another connection
/*@TRACE*/
struct gatt_con_info_ind
{
// GATT Client Side
/// Peer GATT Service Start handle
uint16_t gatt_start_handle;
/// Peer GATT Service End Handle
uint16_t gatt_end_handle;
/// Peer Service Change value handle
uint16_t svc_chg_handle;
// GATT Service Side
/// Client bond data information (@see enum gapc_cli_info)
uint8_t cli_info;
/// Client supported features (@see enum gapc_cli_feat)
uint8_t cli_feat;
};
#endif // _GATT_H_

238
ble/api/gatt_api.h Normal file
View File

@ -0,0 +1,238 @@
/**
****************************************************************************************
*
* @file gatt_api.h
*
* @brief GATT API functions.
*
****************************************************************************************
*/
#ifndef GATT_API_H_
#define GATT_API_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include "gatt.h"
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Gets the negotiated MTU.
*
* @param[in] conidx connection index
*
* @return MTU negotiated
****************************************************************************************
*/
uint16_t gatt_get_mtu(uint8_t conidx);
/**
****************************************************************************************
* @brief Exchange MTU Command.
*
* @param[in] idx connection index
* @param[in] mtu Max MTU value (Minimum is 23)
*
* @return state in GATT_MTU_CHANGED_IND
****************************************************************************************
*/
void gatt_exmtu(uint8_t conidx, uint16_t mtu);
/**
****************************************************************************************
* @brief Change service.
*
* @param[in] idx connection index
* @param[in] shdl Start handle
* @param[in] ehdl End handle
* @return state in GATT_SVC_CHANGED_CFG_IND
****************************************************************************************
*/
void gatt_svc_chg(uint8_t conidx, uint16_t shdl, uint16_t ehdl);
/**
****************************************************************************************
* @brief Discovery command.
*
* @param[in] idx connection index
* @param[in] operation Operation flags @see GATT_OPERATION about discovery operation
* @param[in] shdl Start handle
* @param[in] ehdl End handle
* @param[in] ulen UUID length
* @param[in] uuid Pointer to the uuid data
* @return Info in GATT_DISC_SVC_IND,GATT_DISC_SVC_INCL_IND,GATT_DISC_CHAR_IND or GATT_DISC_CHAR_DESC_IND
****************************************************************************************
*/
void gatt_disc(uint8_t conidx, uint8_t operation, uint16_t shdl, uint16_t ehdl, uint8_t ulen, const uint8_t *uuid);
/**
****************************************************************************************
* @brief Write command request.
*
* @param[in] idx Connection index
* @param[in] operation Operation flags @see GATT_OPERATION about Operation flags for writing/modifying attributes
* @param[in] handle Handle to Write
* @param[in] value Pointer to the value data
* @param[in] length Value length
* @return state in GATT_WRITE_REQ_IND
****************************************************************************************
*/
void gatt_write(uint8_t conidx, uint8_t operation, uint16_t handle, uint8_t* value, uint16_t length);
/**
****************************************************************************************
* @brief Prepare write command request.
*
* @param[in] idx Connection index
* @param[in] handle Handle to write
* @param[in] value Pointer to the value data
* @param[in] length Value length
* @param[in] offset Write offset @see gatt_write_cmd
* @return state in GATT_ATT_INFO_REQ_IND
****************************************************************************************
*/
void gatt_pre_write(uint8_t conidx, uint16_t handle, uint8_t* value, uint16_t length, uint16_t offset);
/**
****************************************************************************************
* @brief Execute write characteristic request.
*
* @param[in] idx Connection index
* @param[in] execute Cancel(0) / Execute(1) pending write operations
* @return state in GATT_WRITE_REQ_IND
****************************************************************************************
*/
void gatt_exe_write(uint8_t conidx, bool execute);
/**
****************************************************************************************
* @brief Read command.
*
* @param[in] idx Connection index
* @param[in] handle Handle to read
* @param[in] length Data length
* @return state in GATT_READ_IND
****************************************************************************************
*/
void gatt_read(uint8_t conidx, uint16_t handle, uint16_t length);
/**
****************************************************************************************
* @brief Read command.
*
* @param[in] idx Connection index
* @param[in] handle Handle to read
* @param[in] length Data length
* @param[in] offset Read offset @see gatt_read_simple
* @return state in GATT_READ_IND
****************************************************************************************
*/
void gatt_read_long(uint8_t conidx, uint16_t handle, uint16_t length, uint16_t offset);
/**
****************************************************************************************
* @brief Read Using UUID.
*
* @param[in] idx Connection index
* @param[in] ulen UUID length
* @param[in] uuid Pointer to the uuid data
* @param[in] shdl Start handle
* @param[in] ehdl End handle
* @return state in GATT_READ_IND
****************************************************************************************
*/
void gatt_read_by_uuid(uint8_t conidx, uint8_t ulen, uint8_t *uuid, uint16_t shdl, uint16_t ehdl);
/**
****************************************************************************************
* @brief Read Multiple Values.
*
* @param[in] idx Connection index
* @param[in] nb number of read @see gatt_read_cmd
* @param[in] handles Pointer to the handles data @see gatt_read_multiple
* @return state in GATT_READ_IND
****************************************************************************************
*/
void gatt_read_by_multiple(uint8_t conidx, uint8_t nb, uint8_t* handles);
/**
****************************************************************************************
* @brief Write Confirm.
*
* @param[in] idx Connection index
* @param[in] status confirm status to peer. @see att_err
* @param[in] handle Handle to write confirm.
****************************************************************************************
*/
void gatt_write_cfm(uint8_t conidx, uint8_t status, uint16_t handle);
/**
****************************************************************************************
* @brief Read Confirm.
*
* @param[in] idx Connection index
* @param[in] status confirm status to peer. @see att_err
* @param[in] handle Handle to read confirm.
* @param[in] length Data length
* @param[in] data Pointer the confirm data to peer.
****************************************************************************************
*/
void gatt_read_cfm(uint8_t conidx, uint8_t status, uint16_t handle, uint16_t length, const uint8_t *data);
/**
****************************************************************************************
* @brief Info Confirm.
*
* @param[in] idx Connection index
* @param[in] status confirm status to peer. @see att_err
* @param[in] handle Handle to info confirm.
* @param[in] length Data length
****************************************************************************************
*/
void gatt_info_cfm(uint8_t conidx, uint8_t status, uint16_t handle, uint16_t length);
/**
****************************************************************************************
* @brief Send notification to peer.
*
* @param[in] conidx Connection Index
* @param[in] handle Handle to NOTIFY.
* @param[in] length Data length
* @param[in] data Pointer the data to peer.
****************************************************************************************
*/
void gatt_ntf_send(uint8_t conidx, uint16_t handle, uint16_t length, const uint8_t *data);
/**
****************************************************************************************
* @brief Send indication to peer.
*
* @param[in] conidx Connection Index
* @param[in] handle Handle to INDICATE.
* @param[in] length Data length
* @param[in] data Pointer the data to peer.
****************************************************************************************
*/
void gatt_ind_send(uint8_t conidx, uint16_t handle, uint16_t length, const uint8_t *data);
/**
****************************************************************************************
* @brief Event Confirm.
*
* @param[in] idx Connection index
* @param[in] handle Handle to event confirm.
****************************************************************************************
*/
void gatt_evt_cfm(uint8_t conidx, uint16_t handle);
#endif // GATT_API_H_

414
ble/api/ke_api.h Normal file
View File

@ -0,0 +1,414 @@
/**
****************************************************************************************
*
* @file ke_api.h
*
* @brief kernel management API functions.
*
****************************************************************************************
*/
#ifndef KE_API_H_
#define KE_API_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "task.h"
#include "list.h"
/*
* DEFINITIONS
****************************************************************************************
*/
/// heap memory types.
enum mem_type
{
/// Heap for environment allocated
MEM_ENV,
/// Heap for messages allocated
MEM_MSG,
MEM_TYPE_MAX
};
typedef struct ke_heap_cfg
{
uint32_t base[MEM_TYPE_MAX];
uint16_t size[MEM_TYPE_MAX];
} heap_cfg_t;
/*
* FUNCTION DECLARATIONS: Task API
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Create a task.
*
* @param[in] task_type Task type.
* @param[in] p_desc Pointer to task descriptor.
*
* @return Task status
****************************************************************************************
*/
uint8_t ke_task_create(uint8_t task_type, task_func_t p_desc);
/**
****************************************************************************************
* @brief Delete a task.
*
* @param[in] task_type Task type.
*
* @return Task status
****************************************************************************************
*/
uint8_t ke_task_delete(uint8_t task_type);
/**
****************************************************************************************
* @brief Retrieve the state of a task.
*
* @param[in] task Task id.
*
* @return Current state of the task
****************************************************************************************
*/
state_t ke_state_get(task_id_t task);
/**
****************************************************************************************
* @brief Set the state of a task(try to activate saved messages queue).
*
* @param[in] task Task id
* @param[in] state New State
****************************************************************************************
*/
void ke_state_set(task_id_t task, state_t state);
/*
* FUNCTION DECLARATIONS: Message API
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Convert a parameter pointer to a message pointer
*
* @param[in] param_ptr Pointer to the parameter member of a message
*
* @return The pointer to the message
****************************************************************************************
*/
__INLINE__ struct msg_elem * ke_param2msg(const void *param_ptr)
{
return (struct msg_elem*) (((uint8_t*)param_ptr) - offsetof(struct msg_elem, param));
}
/**
****************************************************************************************
* @brief Convert a message pointer to a parameter pointer
*
* @param[in] msg Pointer to the message.
*
* @return The pointer to the param member
****************************************************************************************
*/
__INLINE__ void * ke_msg2param(struct msg_elem const *msg)
{
return (void*) (((uint8_t*) msg) + offsetof(struct msg_elem, param));
}
/**
****************************************************************************************
* @brief Macro wrapper to ke_msg_alloc() and cast the returned pointer to struct.
*
* @param[in] msgid Message id
* @param[in] dest_id Destination Task id
* @param[in] src_id Source Task id
* @param[in] param_str parameter structure
*
* @return Pointer to the parameter member.
****************************************************************************************
*/
#define KE_MSG_ALLOC(msgid, dest_id, src_id, param_str) \
(struct param_str*) ke_msg_alloc(msgid, dest_id, src_id, sizeof(struct param_str))
/**
****************************************************************************************
* @brief Macro wrapper to ke_msg_alloc() with a variable length data[] located at the end.
*
* @param[in] msgid Message id
* @param[in] dest_id Destination Task id
* @param[in] src_id Source Task id
* @param[in] param_str parameter structure
* @param[in] length length for the data
*
* @return Pointer to the parameter member.
****************************************************************************************
*/
#define KE_MSG_ALLOC_DYN(msgid, dest_id, src_id, param_str, length) \
(struct param_str*)ke_msg_alloc(msgid, dest_id, src_id, (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.
*
* 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] msgid Message id
* @param[in] dest_id Destination Task id
* @param[in] src_id Source Task id
* @param[in] param_len Size of the message parameters to be allocated
*
* @return Pointer to the parameter member of the message. If the parameter
* structure is empty, the pointer will point to the end of the message.
****************************************************************************************
*/
void *ke_msg_alloc(msg_id_t msgid, task_id_t dest_id, task_id_t src_id, uint16_t param_len);
/**
****************************************************************************************
* @brief Send a message previously allocated with ke_msg_alloc() 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
****************************************************************************************
*/
void ke_msg_send(const void *param_ptr);
/**
****************************************************************************************
* @brief Send a message that has a zero length parameter member.
*
* @param[in] msgid Message id
* @param[in] dest_id Destination Task id
* @param[in] src_id Source Task id
****************************************************************************************
*/
void ke_msg_send_basic(msg_id_t msgid, task_id_t dest_id, task_id_t src_id);
/**
****************************************************************************************
* @brief Forward a message to another task by changing its tasks IDs.
*
* @param[in] param_ptr Pointer to the parameter member 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(const void *param_ptr, task_id_t dest_id, task_id_t src_id);
/**
****************************************************************************************
* @brief Forward a message to another task by changing its message ID and tasks IDs.
*
* @param[in] param_ptr Pointer to the parameter member of the message.
* @param[in] msgid 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(const void *param_ptr, msg_id_t msgid, task_id_t dest_id, task_id_t src_id);
/**
****************************************************************************************
* @brief Marco wrapper to ke_msg_free() with the appropriate msg pointer as parameter.
*
* @param[in] param_ptr parameter structure pointer
****************************************************************************************
*/
#define KE_MSG_FREE(param_ptr) ke_msg_free(ke_param2msg((param_ptr)))
/**
****************************************************************************************
* @brief Free allocated message
*
* @param[in] msg Pointer to the message(not the parameter member!)
****************************************************************************************
*/
void ke_msg_free(struct msg_elem const *msg);
/**
****************************************************************************************
* @brief Retrieve destination task id of a message
*
* @param[in] param_ptr Pointer to the parameter member of the message.
*
* @return message destination task
****************************************************************************************
*/
msg_id_t ke_msg_dest_id_get(const void *param_ptr);
/**
****************************************************************************************
* @brief Retrieve source task id of a message
*
* @param[in] param_ptr Pointer to the parameter member of the message.
*
* @return message source task
****************************************************************************************
*/
msg_id_t ke_msg_src_id_get(const void *param_ptr);
/**
****************************************************************************************
* @brief 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(const void *param_ptr);
/*
* FUNCTION DECLARATIONS: Heap API
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Allocation of a size block of memory.
*
* @param[in] size Size of the memory area that need to be allocated.
* @param[in] type Type of memory block(@see mem_type)
*
* @return A pointer to the allocated memory area, or NULL if no memory is available.
****************************************************************************************
*/
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(@see mem_type)
*
* @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.
*
* @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
*
* @param[in] type Type of memory heap block(@see mem_type)
*
* @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);
/*
* FUNCTION DECLARATIONS: Timer API
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Retrieve kernel time.
*
* @return time value (unit 10 ms)
****************************************************************************************
*/
uint32_t ke_time(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 id (message id type).
* @param[in] task Task id which will be notified
* @param[in] delay Delay in time units(10ms).
****************************************************************************************
*/
void ke_timer_set(msg_id_t timer_id, task_id_t task, uint32_t delay);
/**
****************************************************************************************
* @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 id.
* @param[in] task Task id.
****************************************************************************************
*/
void ke_timer_clear(msg_id_t timer_id, task_id_t task);
/**
****************************************************************************************
* @brief Checks if a requested timer is active(in the timer queue).
*
* @param[in] timer_id Timer id.
* @param[in] task Task id.
****************************************************************************************
*/
bool ke_timer_active(msg_id_t timer_id, task_id_t task);
/**
****************************************************************************************
* @brief Adjust all timers to align to a new SCLK after a system clock adjust.
*
* @param[in] delay Delay in time units(10ms).
****************************************************************************************
*/
void ke_timer_adjust_all(uint32_t delay);
#endif // KE_API_H_

266
ble/api/l2cc.h Normal file
View File

@ -0,0 +1,266 @@
/**
****************************************************************************************
*
* @file l2cc.h
*
* @brief L2CAP Controller Messages.
*
****************************************************************************************
*/
#ifndef L2CC_H_
#define L2CC_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "task.h"
#include <stdbool.h>
/*
* MESSAGES
****************************************************************************************
*/
/// Message of the L2CC task
/*@TRACE*/
enum l2cc_msg_id
{
/// L2CAP Operation completed event
L2CC_CMP_EVT = MSG_ID(L2CC, 0x04),
/* ************* LE Credit Based Connection ************* */
/// LE credit based connection request
L2CC_LECB_CONNECT_CMD = MSG_ID(L2CC, 0x05),
/// LE credit based connection request indication
L2CC_LECB_CONNECT_REQ_IND = MSG_ID(L2CC, 0x06),
/// LE credit based connection request confirmation
L2CC_LECB_CONNECT_CFM = MSG_ID(L2CC, 0x07),
/// LE credit based connection indication
L2CC_LECB_CONNECT_IND = MSG_ID(L2CC, 0x08),
/// LE credit based disconnect request
L2CC_LECB_DISCONNECT_CMD = MSG_ID(L2CC, 0x09),
/// LE credit based disconnect indication
L2CC_LECB_DISCONNECT_IND = MSG_ID(L2CC, 0x0A),
/// LE credit based credit addition
L2CC_LECB_ADD_CMD = MSG_ID(L2CC, 0x0B),
/// LE credit based credit addition indication
L2CC_LECB_ADD_IND = MSG_ID(L2CC, 0x0C),
/// Send data over LE Credit Based Connection
L2CC_LECB_SDU_SEND_CMD = MSG_ID(L2CC, 0x0D),
/// Received data from LE Credit Based connection.
L2CC_LECB_SDU_RECV_IND = MSG_ID(L2CC, 0x0E),
/// Indication to the task that sends the unknown message
L2CC_UNKNOWN_MSG_IND = MSG_ID(L2CC, 0x0F), //!< L2CC_UNKNOWN_MSG_IND
};
/// request operation type - application interface
enum l2cc_op
{
/* Operation Flags */
/* No Operation (if nothing has been requested) */
/* ************************************************ */
/// No operation
L2CC_NO_OP = 0x00,
/* LE Credit Based */
/* ************************************************ */
/// LE credit based connection request
L2CC_LECB_CONNECT,
/// LE credit based disconnection request
L2CC_LECB_DISCONNECT,
/// LE credit addition request
L2CC_LECB_CREDIT_ADD,
/// Send SDU
L2CC_LECB_SDU_SEND,
};
/// Default L2Cap SDU definition
/*@TRACE*/
struct l2cc_sdu
{
/// Channel Identifier
uint16_t cid;
/// Number of credit used
uint16_t credit;
/// SDU Data length
uint16_t length;
/// data
uint8_t data[];
};
/// Operation completed event
/*@TRACE*/
struct l2cc_cmp_evt
{
/// L2CC request type (@see enum l2cc_op)
uint8_t operation;
/// Status of request.
uint8_t status;
/// Channel ID
uint16_t cid;
/// Number of peer credit used - only relevant for LECB
uint16_t credit;
};
/// LE credit based connection request
/*@TRACE*/
struct l2cc_lecb_connect_cmd
{
/// L2CC request type:
/// - L2CC_LECB_CONNECT: LE credit connection
uint8_t operation;
/// parameter used for internal usage
uint8_t pkt_id;
/// LE Protocol/Service Multiplexer
uint16_t le_psm;
/// Local Channel identifier (0: automatically allocate a free channel)
uint16_t local_cid;
/// Credit allocated for the LE Credit Based Connection
/// Shall be at least: floor(((SDU + 2) + (MPS - 1)) / MPS) + 1
/// To be sure that 1 SDU can be fully received without requesting credits to application
uint16_t local_credit;
/// Maximum SDU size - Shall not exceed device MTU
uint16_t local_mtu;
/// Maximum Packet size - Shall not exceed device MPS
uint16_t local_mps;
};
/// LE credit based connection request indication
/*@TRACE*/
struct l2cc_lecb_connect_req_ind
{
/// LE Protocol/Service Multiplexer
uint16_t le_psm;
/// Peer Channel identifier
uint16_t peer_cid;
/// Maximum SDU size
uint16_t peer_mtu;
/// Maximum Packet size
uint16_t peer_mps;
};
/// LE credit based connection request confirmation
/*@TRACE*/
struct l2cc_lecb_connect_cfm
{
/// Peer Channel identifier
uint16_t peer_cid;
/// True to accept the incoming connection, False else
bool accept;
/// Local Channel identifier (0: automatically allocate a free channel)
uint16_t local_cid;
/// Credit allocated for the LE Credit Based Connection
/// Shall be at least: floor(((SDU + 2) + (MPS - 1)) / MPS) + 1
/// To be sure that 1 SDU can be fully received without requesting credits to application
uint16_t local_credit;
/// Maximum SDU size - Shall not exceed device MTU
uint16_t local_mtu;
/// Maximum Packet size - Shall not exceed device MPS
uint16_t local_mps;
};
/// LE credit based connection indication
/*@TRACE*/
struct l2cc_lecb_connect_ind
{
/// Status
uint8_t status;
/// LE Protocol/Service Multiplexer
uint16_t le_psm;
/// Local Channel identifier
uint16_t local_cid;
/// Destination Credit for the LE Credit Based Connection
uint16_t peer_credit;
/// Maximum SDU size
uint16_t peer_mtu;
/// Maximum Packet size
uint16_t peer_mps;
};
/// LE credit based disconnect request
/*@TRACE*/
struct l2cc_lecb_disconnect_cmd
{
/// L2CC request type:
/// - L2CC_LECB_DISCONNECT: LE credit disconnection
uint8_t operation;
/// parameter used for internal usage
uint8_t pkt_id;
/// Local Channel identifier
uint16_t local_cid;
};
/// LE credit based disconnect indication
/*@TRACE*/
struct l2cc_lecb_disconnect_ind
{
/// Local Channel identifier
uint16_t local_cid;
/// Reason
uint8_t reason;
};
/// LE credit based credit addition
/*@TRACE*/
struct l2cc_lecb_add_cmd
{
/// L2CC request type:
/// - L2CC_LECB_CREDIT_ADD: LE credit addition
uint8_t operation;
/// parameter used for internal usage
uint8_t pkt_id;
/// Local Channel identifier
uint16_t local_cid;
/// Credit added locally for channel identifier
uint16_t credit;
};
/// LE credit based credit addition indication
/*@TRACE*/
struct l2cc_lecb_add_ind
{
/// Local Channel identifier
uint16_t local_cid;
/// Destination added credit (relative value)
uint16_t peer_added_credit;
};
/// Send data over an LE Credit Based Connection
/*@TRACE*/
struct l2cc_lecb_sdu_send_cmd
{
/// L2CC request type (@see enum l2cc_op):
/// - L2CC_LECB_SDU_SEND: Send a SDU
uint8_t operation;
/// offset value information - for internal use only
uint16_t offset;
/// SDU information
struct l2cc_sdu sdu;
};
/// Inform that a data packet has been received from a LE Credit Based connection.
/*@TRACE*/
struct l2cc_lecb_sdu_recv_ind
{
/// Status information
uint8_t status;
/// offset value information
uint16_t offset;
/// SDU information
struct l2cc_sdu sdu;
};
/// Indicate that an unknown message has been received
/*@TRACE*/
struct l2cc_unknown_msg_ind
{
/// Unknown message id
msg_id_t unknown_msg_id;
};
#endif // _L2CC_H_

418
ble/api/le_err.h Normal file
View File

@ -0,0 +1,418 @@
/**
****************************************************************************************
*
* @file le_err.h
*
* @brief BLE Layers error codes.
*
****************************************************************************************
*/
#ifndef LE_ERR_H_
#define LE_ERR_H_
/// No error, success
#define LE_SUCCESS 0x00
/// Error code from HCI TO HL Range - from 0x90 to 0xD5
#define LE_ERR_HCI2HL(err) (((err) != 0) ? ((err) + 0x90) : (0))
/// Error code from HL TO HCI Range - from 0x90 to 0xD5
#define LE_ERR_HL2HCI(err) (((err) > 0x90) ? ((err) - 0x90) : (0))
/// GAP Specific Error Codes
enum gap_err
{
/// No error
GAP_ERR_NO_ERROR = 0x00,
/// Invalid parameters set
GAP_ERR_INVALID_PARAM = 0x40,
/// Problem with protocol exchange, get unexpected response
GAP_ERR_PROTOCOL_PROBLEM = 0x41,
/// Request not supported by software configuration
GAP_ERR_NOT_SUPPORTED = 0x42,
/// Request not allowed in current state.
GAP_ERR_COMMAND_DISALLOWED = 0x43,
/// Requested operation canceled.
GAP_ERR_CANCELED = 0x44,
/// Requested operation timeout.
GAP_ERR_TIMEOUT = 0x45,
/// Link connection lost during operation.
GAP_ERR_DISCONNECTED = 0x46,
/// Search algorithm finished, but no result found
GAP_ERR_NOT_FOUND = 0x47,
/// Request rejected by peer device
GAP_ERR_REJECTED = 0x48,
/// Problem with privacy configuration
GAP_ERR_PRIVACY_CFG_PB = 0x49,
/// Duplicate or invalid advertising data
GAP_ERR_ADV_DATA_INVALID = 0x4A,
/// Insufficient resources
GAP_ERR_INSUFF_RESOURCES = 0x4B,
/// Unexpected Error
GAP_ERR_UNEXPECTED = 0x4C,
/// Feature mismatch
GAP_ERR_MISMATCH = 0x4D,
};
/// ATT Specific Error Codes
enum att_err
{
/// No error
ATT_ERR_NO_ERROR = 0x00,
/// 0x01: Handle is invalid
ATT_ERR_INVALID_HANDLE = 0x01,
/// 0x02: Read permission disabled
ATT_ERR_READ_NOT_PERMITTED = 0x02,
/// 0x03: Write permission disabled
ATT_ERR_WRITE_NOT_PERMITTED = 0x03,
/// 0x04: Incorrect PDU
ATT_ERR_INVALID_PDU = 0x04,
/// 0x05: Authentication privilege not enough
ATT_ERR_INSUFF_AUTHEN = 0x05,
/// 0x06: Request not supported or not understood
ATT_ERR_REQUEST_NOT_SUPPORTED = 0x06,
/// 0x07: Incorrect offset value
ATT_ERR_INVALID_OFFSET = 0x07,
/// 0x08: Authorization privilege not enough
ATT_ERR_INSUFF_AUTHOR = 0x08,
/// 0x09: Capacity queue for reliable write reached
ATT_ERR_PREPARE_QUEUE_FULL = 0x09,
/// 0x0A: Attribute requested not existing
ATT_ERR_ATTRIBUTE_NOT_FOUND = 0x0A,
/// 0x0B: Attribute requested not long
ATT_ERR_ATTRIBUTE_NOT_LONG = 0x0B,
/// 0x0C: Encryption size not sufficient
ATT_ERR_INSUFF_ENC_KEY_SIZE = 0x0C,
/// 0x0D: Invalid length of the attribute value
ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN = 0x0D,
/// 0x0E: Operation not fit to condition
ATT_ERR_UNLIKELY_ERR = 0x0E,
/// 0x0F: Attribute requires encryption before operation
ATT_ERR_INSUFF_ENC = 0x0F,
/// 0x10: Attribute grouping not supported
ATT_ERR_UNSUPP_GRP_TYPE = 0x10,
/// 0x11: Resources not sufficient to complete the request
ATT_ERR_INSUFF_RESOURCE = 0x11,
/// 0x80: Application error (also used in PRF Errors)
ATT_ERR_APP_ERROR = 0x80,
};
/// L2C Specific Error Codes
enum l2c_err
{
/// No error
L2C_ERR_NO_ERROR = 0x00,
/// Message cannot be sent because connection lost. (disconnected)
L2C_ERR_CONNECTION_LOST = 0x30,
/// Invalid PDU length exceed MTU
L2C_ERR_INVALID_MTU_EXCEED = 0x31,
/// Invalid PDU length exceed MPS
L2C_ERR_INVALID_MPS_EXCEED = 0x32,
/// Invalid Channel ID
L2C_ERR_INVALID_CID = 0x33,
/// Invalid PDU
L2C_ERR_INVALID_PDU = 0x34,
/// Connection refused - no resources available
L2C_ERR_NO_RES_AVAIL = 0x35,
/// Connection refused - insufficient authentication
L2C_ERR_INSUFF_AUTHEN = 0x36,
/// Connection refused - insufficient authorization
L2C_ERR_INSUFF_AUTHOR = 0x37,
/// Connection refused - insufficient encryption key size
L2C_ERR_INSUFF_ENC_KEY_SIZE = 0x38,
/// Connection Refused - insufficient encryption
L2C_ERR_INSUFF_ENC = 0x39,
/// Connection refused - LE_PSM not supported
L2C_ERR_LEPSM_NOT_SUPP = 0x3A,
/// No more credit
L2C_ERR_INSUFF_CREDIT = 0x3B,
/// Command not understood by peer device
L2C_ERR_NOT_UNDERSTOOD = 0x3C,
/// Credit error, invalid number of credit received
L2C_ERR_CREDIT_ERROR = 0x3D,
/// Channel identifier already allocated
L2C_ERR_CID_ALREADY_ALLOC = 0x3E,
/// Unknown PDU
L2C_ERR_UNKNOWN_PDU = 0x3F,
};
/// GATT Specific Error Codes
enum gatt_err
{
/// No error
GATT_ERR_NO_ERROR = 0x00,
/// Problem with ATTC protocol response
GATT_ERR_INVALID_ATT_LEN = 0x50,
/// Error in service search
GATT_ERR_INVALID_TYPE_IN_SVC_SEARCH = 0x51,
/// Invalid write data
GATT_ERR_WRITE = 0x52,
/// Signed write error
GATT_ERR_SIGNED_WRITE = 0x53,
/// No attribute client defined
GATT_ERR_ATTRIBUTE_CLIENT_MISSING = 0x54,
/// No attribute server defined
GATT_ERR_ATTRIBUTE_SERVER_MISSING = 0x55,
/// Permission set in service/attribute are invalid
GATT_ERR_INVALID_PERM = 0x56,
};
/// SMP Specific Error Codes
enum smp_err
{
/// No error
SMP_ERR_NO_ERROR = 0x00,
// Local device SMP Protocol Errors
/// The user input of pass key failed, for example, the user canceled the operation.
SMP_ERR_LOC_PASSKEY_ENTRY_FAILED = 0x61,
/// The OOB Data is not available.
SMP_ERR_LOC_OOB_NOT_AVAILABLE = 0x62,
/// The pairing procedure cannot be performed as authentication requirements cannot be met
/// due to IO capabilities of one or both devices.
SMP_ERR_LOC_AUTH_REQ = 0x63,
/// The confirm value does not match the calculated confirm value.
SMP_ERR_LOC_CONF_VAL_FAILED = 0x64,
/// Pairing is not supported by the device.
SMP_ERR_LOC_PAIRING_NOT_SUPP = 0x65,
/// The resultant encryption key size is insufficient for the security requirements of
/// this device.
SMP_ERR_LOC_ENC_KEY_SIZE = 0x66,
/// The SMP command received is not supported on this device.
SMP_ERR_LOC_CMD_NOT_SUPPORTED = 0x67,
/// Pairing failed due to an unspecified reason.
SMP_ERR_LOC_UNSPECIFIED_REASON = 0x68,
/// Pairing or Authentication procedure is disallowed because too little time has elapsed
/// since last pairing request or security request.
SMP_ERR_LOC_REPEATED_ATTEMPTS = 0x69,
/// The command length is invalid or a parameter is outside of the specified range.
SMP_ERR_LOC_INVALID_PARAM = 0x6A,
/// Indicates to the remote device that the DHKey Check value received doesn't
/// match the one calculated by the local device.
SMP_ERR_LOC_DHKEY_CHECK_FAILED = 0x6B,
/// Indicates that the confirm values in the numeric comparison protocol do not match.
SMP_ERR_LOC_NUMERIC_COMPARISON_FAILED = 0x6C,
// Remote peer SMP Protocol Errors
/// The user input of passkey failed, for example, the user canceled the operation.
SMP_ERR_REM_PASSKEY_ENTRY_FAILED = 0x71,
/// The OOB Data is not available.
SMP_ERR_REM_OOB_NOT_AVAILABLE = 0x72,
/// The pairing procedure cannot be performed as authentication requirements cannot be
/// met due to IO capabilities of one or both devices.
SMP_ERR_REM_AUTH_REQ = 0x73,
/// The confirm value does not match the calculated confirm value.
SMP_ERR_REM_CONF_VAL_FAILED = 0x74,
/// Pairing is not supported by the device.
SMP_ERR_REM_PAIRING_NOT_SUPP = 0x75,
/// The resultant encryption key size is insufficient for the security requirements of
/// this device.
SMP_ERR_REM_ENC_KEY_SIZE = 0x76,
/// The SMP command received is not supported on this device.
SMP_ERR_REM_CMD_NOT_SUPPORTED = 0x77,
/// Pairing failed due to an unspecified reason.
SMP_ERR_REM_UNSPECIFIED_REASON = 0x78,
/// Pairing or Authentication procedure is disallowed because too little time has elapsed
/// since last pairing request or security request.
SMP_ERR_REM_REPEATED_ATTEMPTS = 0x79,
/// The command length is invalid or a parameter is outside of the specified range.
SMP_ERR_REM_INVALID_PARAM = 0x7A,
/// Indicates to the remote device that the DHKey Check value received doesn't
/// match the one calculated by the local device.
SMP_ERR_REM_DHKEY_CHECK_FAILED = 0x7B,
/// Indicates that the confirm values in the numeric comparison protocol do not match.
SMP_ERR_REM_NUMERIC_COMPARISON_FAILED = 0x7C,
// SMP Errors triggered by local device
/// The provided resolvable address has not been resolved.
SMP_ERR_ADDR_RESOLV_FAIL = 0xD0,
/// The Signature Verification Failed
SMP_ERR_SIGN_VERIF_FAIL = 0xD1,
/// The encryption procedure failed because the slave device didn't find the LTK
/// needed to start an encryption session.
SMP_ERR_ENC_KEY_MISSING = 0xD2,
/// The encryption procedure failed because the slave device doesn't support the
/// encryption feature.
SMP_ERR_ENC_NOT_SUPPORTED = 0xD3,
/// A timeout has occurred during the start encryption session.
SMP_ERR_ENC_TIMEOUT = 0xD4,
};
/// Profiles Specific Error Codes
enum prf_err
{
/// No error
PRF_ERR_NO_ERROR = 0x00,
/// Application Error
PRF_ERR_APP_ERROR = 0x80,
/// Invalid parameter in request
PRF_ERR_INVALID_PARAM = 0x81,
/// Inexistent handle for sending a read/write characteristic request
PRF_ERR_INEXISTENT_HDL = 0x82,
/// Discovery stopped due to missing attribute according to specification
PRF_ERR_STOP_DISC_CHAR_MISSING = 0x83,
/// Too many SVC instances found -> protocol violation
PRF_ERR_MULTIPLE_SVC = 0x84,
/// Discovery stopped due to found attribute with incorrect properties
PRF_ERR_STOP_DISC_WRONG_CHAR_PROP = 0x85,
/// Too many Char. instances found-> protocol violation
PRF_ERR_MULTIPLE_CHAR = 0x86,
/// Attribute write not allowed
PRF_ERR_NOT_WRITABLE = 0x87,
/// Attribute read not allowed
PRF_ERR_NOT_READABLE = 0x88,
/// Request not allowed
PRF_ERR_REQ_DISALLOWED = 0x89,
/// Notification Not Enabled
PRF_ERR_NTF_DISABLED = 0x8A,
/// Indication Not Enabled
PRF_ERR_IND_DISABLED = 0x8B,
/// Feature not supported by profile
PRF_ERR_FEATURE_NOT_SUPPORTED = 0x8C,
/// Read value has an unexpected length
PRF_ERR_UNEXPECTED_LEN = 0x8D,
/// Disconnection occurs
PRF_ERR_DISCONNECTED = 0x8E,
/// Procedure Timeout
PRF_ERR_PROC_TIMEOUT = 0x8F,
/// Client characteristic configuration improperly configured
PRF_CCCD_IMPR_CONFIGURED = 0xFD,
/// Procedure already in progress
PRF_PROC_IN_PROGRESS = 0xFE,
/// Out of Range
PRF_OUT_OF_RANGE = 0xFF,
};
/// LL Conveyed Error Codes
enum ll_err
{
/// No error
LL_ERR_NO_ERROR = 0x00,
/// Unknown HCI Command
LL_ERR_UNKNOWN_HCI_COMMAND = 0x91,
/// Unknown Connection Identifier
LL_ERR_UNKNOWN_CONNECTION_ID = 0x92,
/// Hardware Failure
LL_ERR_HARDWARE_FAILURE = 0x93,
/// BT Page Timeout
LL_ERR_PAGE_TIMEOUT = 0x94,
/// Authentication failure
LL_ERR_AUTH_FAILURE = 0x95,
/// Pin code missing
LL_ERR_PIN_MISSING = 0x96,
/// Memory capacity exceed
LL_ERR_MEMORY_CAPA_EXCEED = 0x97,
/// Connection Timeout
LL_ERR_CON_TIMEOUT = 0x98,
/// Connection limit Exceed
LL_ERR_CON_LIMIT_EXCEED = 0x99,
/// Synchronous Connection limit exceed
LL_ERR_SYNC_CON_LIMIT_DEV_EXCEED = 0x9A,
/// ACL Connection exits
LL_ERR_ACL_CON_EXISTS = 0x9B,
/// Command Disallowed
LL_ERR_COMMAND_DISALLOWED = 0x9C,
/// Connection rejected due to limited resources
LL_ERR_CONN_REJ_LIMITED_RESOURCES = 0x9D,
/// Connection rejected due to security reason
LL_ERR_CONN_REJ_SECURITY_REASONS = 0x9E,
/// Connection rejected due to unacceptable BD Addr
LL_ERR_CONN_REJ_UNACCEPTABLE_BDADDR = 0x9F,
/// Connection rejected due to Accept connection timeout
LL_ERR_CONN_ACCEPT_TIMEOUT_EXCEED = 0xA0,
/// Not Supported
LL_ERR_UNSUPPORTED = 0xA1,
/// invalid parameters
LL_ERR_INVALID_HCI_PARAM = 0xA2,
/// Remote user terminate connection
LL_ERR_REMOTE_USER_TERM_CON = 0xA3,
/// Remote device terminate connection due to low resources
LL_ERR_REMOTE_DEV_TERM_LOW_RESOURCES = 0xA4,
/// Remote device terminate connection due to power off
LL_ERR_REMOTE_DEV_POWER_OFF = 0xA5,
/// Connection terminated by local host
LL_ERR_CON_TERM_BY_LOCAL_HOST = 0xA6,
/// Repeated attempts
LL_ERR_REPEATED_ATTEMPTS = 0xA7,
/// Pairing not Allowed
LL_ERR_PAIRING_NOT_ALLOWED = 0xA8,
/// Unknown PDU Error
LL_ERR_UNKNOWN_LMP_PDU = 0xA9,
/// Unsupported remote feature
LL_ERR_UNSUPPORTED_REMOTE_FEATURE = 0xAA,
/// Sco Offset rejected
LL_ERR_SCO_OFFSET_REJECTED = 0xAB,
/// SCO Interval Rejected
LL_ERR_SCO_INTERVAL_REJECTED = 0xAC,
/// SCO air mode Rejected
LL_ERR_SCO_AIR_MODE_REJECTED = 0xAD,
/// Invalid LMP parameters
LL_ERR_INVALID_LMP_PARAM = 0xAE,
/// Unspecified error
LL_ERR_UNSPECIFIED_ERROR = 0xAF,
/// Unsupported LMP Parameter value
LL_ERR_UNSUPPORTED_LMP_PARAM_VALUE = 0xB0,
/// Role Change Not allowed
LL_ERR_ROLE_CHANGE_NOT_ALLOWED = 0xB1,
/// LMP Response timeout
LL_ERR_LMP_RSP_TIMEOUT = 0xB2,
/// LMP Collision
LL_ERR_LMP_COLLISION = 0xB3,
/// LMP Pdu not allowed
LL_ERR_LMP_PDU_NOT_ALLOWED = 0xB4,
/// Encryption mode not accepted
LL_ERR_ENC_MODE_NOT_ACCEPT = 0xB5,
/// Link Key Cannot be changed
LL_ERR_LINK_KEY_CANT_CHANGE = 0xB6,
/// Quality of Service not supported
LL_ERR_QOS_NOT_SUPPORTED = 0xB7,
/// Error, instant passed
LL_ERR_INSTANT_PASSED = 0xB8,
/// Pairing with unit key not supported
LL_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUP = 0xB9,
/// Transaction collision
LL_ERR_DIFF_TRANSACTION_COLLISION = 0xBA,
/// Unacceptable parameters
LL_ERR_QOS_UNACCEPTABLE_PARAM = 0xBC,
/// Quality of Service rejected
LL_ERR_QOS_REJECTED = 0xBD,
/// Channel class not supported
LL_ERR_CHANNEL_CLASS_NOT_SUP = 0xBE,
/// Insufficient security
LL_ERR_INSUFFICIENT_SECURITY = 0xBF,
/// Parameters out of mandatory range
LL_ERR_PARAM_OUT_OF_MAND_RANGE = 0xC0,
/// Role switch pending
LL_ERR_ROLE_SWITCH_PEND = 0xC2,
/// Reserved slot violation
LL_ERR_RESERVED_SLOT_VIOLATION = 0xC4,
/// Role Switch fail
LL_ERR_ROLE_SWITCH_FAIL = 0xC5,
/// Error, EIR too large
LL_ERR_EIR_TOO_LARGE = 0xC6,
/// Simple pairing not supported by host
LL_ERR_SP_NOT_SUPPORTED_HOST = 0xC7,
/// Host pairing is busy
LL_ERR_HOST_BUSY_PAIRING = 0xC8,
/// Controller is busy
LL_ERR_CONTROLLER_BUSY = 0xCA,
/// Unacceptable connection initialization
LL_ERR_UNACCEPTABLE_CONN_INT = 0xCB,
/// Direct Advertising Timeout
LL_ERR_DIRECT_ADV_TO = 0xCC,
/// Connection Terminated due to a MIC failure
LL_ERR_TERMINATED_MIC_FAILURE = 0xCD,
/// Connection failed to be established
LL_ERR_CONN_FAILED_TO_BE_EST = 0xCE,
};
#endif // LE_ERR_H_

258
ble/api/list.h Normal file
View File

@ -0,0 +1,258 @@
/**
****************************************************************************************
*
* @file list.h
*
* @brief List definitions
*
****************************************************************************************
*/
#ifndef _LIST_H_
#define _LIST_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifndef __INLINE__
#define __INLINE__ __forceinline static
#endif
/*
* DEFINES
****************************************************************************************
*/
/// structure of a list element header
typedef struct list_hdr
{
/// Pointer to next list_hdr
struct list_hdr *next;
} list_hdr_t;
/// structure of a list
typedef struct list
{
/// pointer to first element of the list
struct list_hdr *first;
/// pointer to the last element
struct list_hdr *last;
} list_t;
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize a list to defaults values.
*
* @param list Pointer to the list structure.
****************************************************************************************
*/
void list_init(list_t *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
* @param elmt_cnt Nb of elements available in the pool
****************************************************************************************
*/
void list_pool_init(list_t *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 list_push_back(list_t *list, list_hdr_t *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 list_push_back_sublist(list_t *list, list_hdr_t *first_hdr, list_hdr_t *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 list_push_front(list_t *list, list_hdr_t *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.
****************************************************************************************
*/
list_hdr_t *list_pop_front(list_t *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 list_extract(list_t *list, list_hdr_t *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 list_extract_after(list_t *list, list_hdr_t *elt_ref_hdr, list_hdr_t *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 list_extract_sublist(list_t *list, list_hdr_t *ref_hdr, list_hdr_t *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 list_find(list_t *list, list_hdr_t *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 list_merge(list_t *list1, list_t *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 list_insert_before(list_t *list, list_hdr_t *elt_ref_hdr, list_hdr_t *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 list_insert_after(list_t *list, list_hdr_t *elt_ref_hdr, list_hdr_t *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 list_size(list_t *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 list_is_empty(const list_t *const list)
{
return (list->first == NULL);
}
/**
****************************************************************************************
* @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__ list_hdr_t *list_pick(const list_t *const list)
{
return(list->first);
}
/**
****************************************************************************************
* @brief Return following element of a list element.
*
* @param list_hdr Pointer to the list element.
*
* @return The pointer to the next element.
****************************************************************************************
*/
__INLINE__ list_hdr_t *list_next(const list_hdr_t *const list_hdr)
{
return(list_hdr->next);
}
#endif // _LIST_H_

220
ble/api/task.h Normal file
View File

@ -0,0 +1,220 @@
/**
****************************************************************************************
*
* @file task.h
*
* @brief Task Definitions
*
****************************************************************************************
*/
#ifndef _TASK_H_
#define _TASK_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "list.h"
#include "utils.h"
#include "blelib.h"
/*
* DEFINITIONS
****************************************************************************************
*/
/// Type ID: 0~255(Group)
typedef uint8_t tid_t;
/// State
typedef uint8_t state_t;
/**
* Task Identifier bit field
*
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
* | Instance Index | Task Type(Group ID) |
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
*
* Bit [0-7] : task type (Group ID, @see enum TASK_TYPE)
* Bit [8-15]: instance index(single or multi-instantiated task)
*/
typedef uint16_t task_id_t;
/// Builds task identifier from 'task' and 'index'.
#define TASK_BUILD(task, index) ((uint16_t)(((index) << 8) | (task)))
/// Builds task identifier from 'type'(TASK_xxxx) and 'index'.
#define TASK_ID(type, index) ((uint16_t)(((index) << 8) | (TASK_ ## type)))
/// Retrieves task type from 'task_id'.
#define TASK_TYPE(task_id) ((task_id) & 0xFF)
/// Retrieves task index number from 'task_id'.
#define TASK_IDX(task_id) (((task_id) >> 8) & 0xFF)
/// Invalid task
#define TASK_INVALID (0xFFFF)
/**
* Message Identifier bit field
*
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
* | Msg Type(Task Base) | Msg Index(Offset) |
* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
*
* Bit [0-7] : message index(no more than 255 messages per task)
* Bit [8-15]: message type (no more than 255 tasks support)
*/
typedef uint16_t msg_id_t;
/// Build message identifier from 'type_id' and 'index'.
#define MSG_BUILD(tid, index) ((uint16_t)((tid) << 8) | (index))
/// Build message identifier from 'type'(TID_xxxx) and 'index'.
#define MSG_ID(type, index) ((uint16_t)((TID_ ## type) << 8) | (index))
/// Retrieves message type from 'msg_id'.
#define MSG_TYPE(msg_id) (((uint16_t)msg_id) >> 8)
/// Retrieves message index from 'msg_id'.
#define MSG_IDX(msg_id) ((msg_id) & 0xFF)
/// Default Message(to handle several message type in same handler).
#define MSG_DEFAULT (0xFFFF)
/// Message to get Task State Pointer
#define MSG_TASK_STATE (0x0000)
/// Format of task dispatch function type
typedef void* (*task_func_t)(msg_id_t msgid, uint8_t task_idx);
/// Format of message handler function type
typedef int (*msg_func_t)(msg_id_t msgid, const void *param, \
task_id_t dest_id, task_id_t src_id);
/// Macro for message handler function definition
#define MSG_HANDLER(msg_name, param_struct) \
static int msg_name##_handler(msg_id_t msgid, param_struct const *param, \
task_id_t dest_id, task_id_t src_id)
/// Macro for message handlers table definition
#define MSG_HANDLER_TAB(task) const struct msg_handler task##_msg_handler_tab[] =
/// Status returned by Message Handler
enum msg_status
{
MSG_STATUS_FREE = 0, ///< consumed, msg and ext are freed by the kernel
MSG_STATUS_NO_FREE = 1, ///< consumed, nothing is freed by the kernel
MSG_STATUS_SAVED = 2, ///< not consumed, will be pushed in the saved queue
};
/// Status returned by task API functions
enum task_status
{
TASK_OK = 0,
TASK_FAIL = 1,
TASK_ERR_UNKNOWN = 2,
TASK_ERR_EXCEEDED = 3,
TASK_ERR_EXISTS = 4,
};
/// Element of a message handler table.
struct msg_handler
{
msg_id_t id; ///< Id of the handled message.
msg_func_t func; ///< Pointer to the handler function.
};
/// Message Element.
struct msg_elem
{
list_hdr_t hdr; ///< List header for chaining
msg_id_t msgid; ///< Message id.
task_id_t dest_id; ///< Destination kernel identifier.
task_id_t src_id; ///< Source kernel identifier.
uint16_t param_len; ///< Parameter embedded struct length.
uint32_t param[]; ///< Parameter embedded struct. Must be word-aligned.
};
/// Tasks types definition
enum task_type
{
/******** Low Layer Tasks ********/
// Link Layer Controller Task
TASK_LLC = 0x01,
// HCI Test & Debug Task
TASK_HCI = 0x02,
/******** App Layer Tasks ********/
// Application Main Task
TASK_APP = 0x03,
/******** Host Layer Tasks ********/
// L2CAP Controller Task
// - handles L2CAP attribute and security block.
TASK_L2CC = 0x04,
// Generic Attribute Profile Task
// - includes services and characteristic discovery, configuration exchanges
// - and attribute value access operations(reading, writing, notification and indication).
TASK_GATT = 0x05,
// Generic Access Profile Manager Task
// - manage all non connected stuff, configuring device mode(discoverable, connectable, etc.)
// - and perform required actions(scanning, connection, etc.)
// - and manage GAP Controller state according to corresponding BLE connection states.
TASK_GAPM = 0x06,
// Generic Access Profile Controller Task
// - perform GAP action related to a BLE connection(pairing, update parameters, disconnect, etc.)
// - GAP controller is multi-instantiated, one task instance per BLE connection.
TASK_GAPC = 0x07,
// Maximum number of tasks
TASK_MAX,
// MACRO of Invalid Task
TASK_NONE = 0xFF,
};
/// Type ID for identifying Group(Messages and Profiles)
enum type_id
{
/******** Low Layer Identifiers ********/
TID_LLC = 1, // LL Controller
TID_LLD = 2, // LL Driver
TID_HCI = 3, // HCI
/******** Host Layer Identifiers ********/
TID_L2CC = 4, // L2CAP Controller
TID_GATT = 5, // Generic Attribute Profile
TID_GAPM = 6, // Generic Access Profile Manager
TID_GAPC = 7, // Generic Access Profile Controller
/******** App Layer Identifiers ********/
TID_APP = 9, // Application Task
TID_MESH = 10, // Mesh Reserved 10~15
/******** PRF Layer Identifiers ********/
/* User customize */
/* End customize */
// MACRO of Invalid Identifier
TID_INVALID = 0xFF,
};
#endif //_TASK_H_

508
ble/api/utils.h Normal file
View File

@ -0,0 +1,508 @@
/**
****************************************************************************************
*
* @file utils.h
*
* @brief Common Utilities definitions (functions and macros).
*
****************************************************************************************
*/
#ifndef _UTILS_H_
#define _UTILS_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#ifndef __INLINE__
#define __INLINE__ __forceinline static
#endif
#ifndef ASSERT_ERR
/// Assertions showing a critical error
#define ASSERT_ERR(cond)
/// Assertions showing a critical info
#define ASSERT_INFO(cond, param0, param1)
/// Assertions showing a non-critical problem
#define ASSERT_WARN(cond, param0, param1)
/// DUMP data array present in the SW.
#define DUMP_DATA(data, length)
#endif
/*
* MACRO
****************************************************************************************
*/
/// Value with one bit set
#ifndef BIT
#define BIT(pos) (1UL<<(pos))
#endif
#define IS_POWER2(n) ((n) && !((n) & (n-1)))
/// Number of '1' bits in a byte
#define NB_1BITS(byte) popcnt8(byte)
#define ONE_BITS(byte) NB_1BITS(byte)
/// Get the number of elements within an array
#define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0]))
/// maroc to Get a structure from one of its structure field
#define CONTAINER_OF(ptr, type, member) ((type *)((char *)ptr - offsetof(type,member)))
/// Bit checking
#define CHKF(flag, mask) (((flag)&(mask)) == mask)
/// Get a field from a value containing several fields
/// @param[in] __r bit field value
/// @param[in] __f field name(_MASK & _LSB)
/// @return the value of the register masked and shifted
#define GETF(__r, __f) (( (__r) & (__f##_MASK) ) >> (__f##_LSB))
/// Set a field value into a value containing several fields.
/// @param[in] __r bit field value
/// @param[in] __f field name(_MASK & _LSB)
/// @param[in] __v value to put in field
#define SETF(__r, __f, __v) \
do { \
ASSERT_ERR( ( ( ( (__v) << (__f##_LSB) ) & ( ~(__f##_MASK) ) ) ) == 0); \
__r = (((__r) & ~(__f##_MASK)) | (__v) << (__f##_LSB)); \
} while (0)
/// Get a bit field from a value containing several fields
/// @param[in] __r bit field value
/// @param[in] __b bit field name(_BIT & _POS)
/// @return the value of the register masked and shifted
#define GETB(__r, __b) (( (__r) & (__b##_BIT) ) >> (__b##_POS))
/// 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) << (__b##_POS) ) & ( ~(__b##_BIT) ) ) ) == 0 ); \
__r = (((__r) & ~(__b##_BIT)) | (__v) << (__b##_POS)); \
} while (0)
/// Align value on the multiple of 4 equal or nearest higher.
/// @param[in] val Value to align.
#define ALIGN4_HI(_val) (((_val) + 3) & ~3)
/// Align value on the multiple of 4 equal or nearest lower.
/// * @param[in] _val Value to align.
#define ALIGN4_LO(_val) ((_val) & ~3)
/// @brief Align value on the multiple of 2 equal or nearest higher.
/// * @param[in] _val Value to align.
#define ALIGN2_HI(_val) (((_val) + 1) & ~1)
/// @brief Align value on the multiple of 2 equal or nearest lower.
/// * @param[in] _val Value to align.
#define ALIGN2_LO(_val) ((_val) & ~1)
/// Perform a modulo(%) operation
/// @param[in] _val Dividend
/// @param[in] _div Divisor
#define MOD(_val, _div) ((_val) % (_div))
/// Perform a division and ceil up the result
/// * @param[in] _val Value to divide
/// * @param[in] _div Divide value
#define DIV_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
#define DIV_ROUND(_val, _div) (((_val) + ((_div) >> 1))/ (_div))
/// Increment value (wrap to 0 if reach max)
/// * @param[in] _val Value to inc
/// * @param[in] _max Max Range
#define VAL_INC(_val, _max) \
(_val) = (_val) + 1; \
if ((_val) >= (_max)) (_val) = 0
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Function to initialize the random seed.
* @param[in] seed The seed number to use to generate the random sequence.
****************************************************************************************
*/
__INLINE__ void rand_init(uint32_t seed)
{
srand(seed);
}
/**
****************************************************************************************
* @brief Function to get an 8 bit random number.
* @return Random byte value.
****************************************************************************************
*/
__INLINE__ uint8_t 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 rand_hword(void)
{
return (uint16_t)(rand() & 0xFFFF);
}
/**
****************************************************************************************
* @brief Function to get an 32 bit random number.
* @return Random word value.
****************************************************************************************
*/
__INLINE__ uint32_t rand_word(void)
{
return (uint32_t)rand();
}
/**
****************************************************************************************
* @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 read32(const void *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 read16(const void *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 write32(const void *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 write16(const void *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 write8(const void *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 read16p(const void *ptr16)
{
uint16_t value = ((uint8_t *)ptr16)[0] | ((uint8_t *)ptr16)[1] << 8;
return value;
}
/**
****************************************************************************************
* @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 write16p(const void *ptr16, uint16_t value)
{
uint8_t *ptr=(uint8_t*)ptr16;
*ptr++ = value&0xff;
*ptr = (value&0xff00)>>8;
}
/**
****************************************************************************************
* @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 read24p(const void *ptr24)
{
uint16_t addr_l, addr_h;
addr_l = 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 write24p(const void *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 read32p(const void *ptr32)
{
uint16_t addr_l, addr_h;
addr_l = read16p(ptr32);
addr_h = 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 write32p(const void *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 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.
****************************************************************************************
*/
#if !(USE_ARM_FUNC)
uint32_t co_clz(uint32_t val);
#else
__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 & BIT(31 - i))
break;
}
return i;
#endif // defined(__arm__)
}
#endif //(USE_ARM_FUNC)
/**
****************************************************************************************
* @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.
****************************************************************************************
*/
#if !(USE_ARM_FUNC)
uint32_t co_ctz(uint32_t val);
#else
__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 & BIT(i))
break;
}
return i;
#endif // defined(__arm__)
}
#endif //(USE_ARM_FUNC)
/**
****************************************************************************************
* @brief Count binary ones.
* @param[in] val Value to count the number of ones in the binary representation.
* @return Number of ones when value is written as 32 bits.
****************************************************************************************
*/
#if !(USE_ARM_FUNC)
uint8_t co_ones(uint32_t val);
#else
__INLINE__ uint8_t co_ones(uint32_t val)
{
#if defined(__arm__) || defined(__GNUC__)
return __builtin_popcount(val);
#else
uint32_t i, ones=0;
for (i = 0; i < 32; i++)
{
if (val & BIT(i))
ones++;
}
return ones;
#endif // defined(__arm__)
}
#endif //(USE_ARM_FUNC)
/**
****************************************************************************************
* @brief Count '1' bits in a byte value, repalce NB_1BITS(byte)
* @return Number of '1' bits in a byte
****************************************************************************************
*/
uint8_t popcnt8(uint8_t byte);
/**
****************************************************************************************
* @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 ? val*(-1) : val;
}
/**
****************************************************************************************
* @brief Perform a modulo operation
* @return val%div
****************************************************************************************
*/
__INLINE__ uint32_t co_mod(uint32_t val, uint32_t div)
{
//ASSERT_ERR(div);
return ((val) % (div));
}
/**
****************************************************************************************
* @brief Function to return the hex char of a 4bit.
* @return The hex char.
****************************************************************************************
*/
__INLINE__ uint8_t co_hex(uint8_t b4)
{
return b4 < 10 ? b4 + '0' : b4 - 10 + 'A';
}
#endif // _UTILS_H_

584
ble/app/app.c Normal file
View File

@ -0,0 +1,584 @@
/**
****************************************************************************************
*
* @file app.c
*
* @brief Application entry point - Example
*
* < __weak func as demo, recommend to Override its in 'user porject'/src/myapp.c >
****************************************************************************************
*/
#include "app.h"
#include "bledef.h"
#include "drvs.h"
#include "prf_api.h"
#if (DBG_APP)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#endif
/*
* DEFAULT CONFIGURATION
****************************************************************************************
*/
#if !defined(BLE_DEV_NAME)
#define BLE_DEV_NAME "myBle6"
#endif
#if !defined(BLE_ADDR)
#define BLE_ADDR { 0x30, 0x06, 0x23, 0x20, 0x01, 0xD2 }
#endif
#if !defined(BLE_ROLE)
#if (BLE_NB_SLAVE && BLE_NB_MASTER)
#define BLE_ROLE (GAP_ROLE_CENTRAL | GAP_ROLE_PERIPHERAL)
#elif (BLE_NB_MASTER)
#define BLE_ROLE (GAP_ROLE_CENTRAL)
#else // Only Slave
#define BLE_ROLE (GAP_ROLE_PERIPHERAL)
#endif
#endif
#if !defined(BLE_PHY)
#define BLE_PHY (GAP_PHY_LE_1MBPS) // | GAP_PHY_LE_2MBPS)
#endif
#if !defined(BLE_PAIRING)
#define BLE_PAIRING (GAPM_PAIRING_LEGACY)
#endif
#if !defined(BLE_AUTH)
#define BLE_AUTH (GAP_AUTH_REQ_NO_MITM_NO_BOND)
#endif
#if !defined(BLE_SECREQ)
#define BLE_SECREQ (GAP_NO_SEC)
#endif
/*
* VARIABLES DEFINITIONS
****************************************************************************************
*/
/// Application Environment
__VAR_ENV struct app_env_tag app_env;
/// Ble local address (user customize)
const bd_addr_t ble_dev_addr = { BLE_ADDR };
/// GAP device configuration
const struct gapm_dev_config ble_dev_config =
{
// Device Role: Central, Peripheral (@see gap_role)
.gap_role = BLE_ROLE,
// Pairing mode authorized (@see enum gapm_pairing_mode)
.pairing = BLE_PAIRING,
// Preferred LE PHY for data (@see enum gap_phy)
.pref_phy = BLE_PHY,
// Maximal MTU acceptable for device (23~512)
.max_mtu = BLE_MTU,
};
/// GAP debug LTK for testing
#if (BLE_DBG_LTK)
const struct gapc_ltk debugLTK =
{
/// Long Term Key
.ltk = {{0x88, 0x0D, 0x00, 0x20, 0xAC, 0x32, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}},
/// Encryption Diversifier
.ediv = 0xB951,
/// Random Number
.randnb = {{0x02, 0x18, 0xAC, 0x32, 0x00, 0x20, 0x00, 0x00}},
/// Encryption key size (7 to 16)
.key_size = 16,
/// Extend Info
.ext_info =0,
};
#endif
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section Profile Interface
****************************************************************************************
*/
// Connection interval unit in 1.25ms
#define SLV_PREF_INTV_MIN (10)
#define SLV_PREF_INTV_MAX (10)
// Slave latency
#define SLV_PREF_LATENCY (0)
// Connection supervision timeout multiplier unit in 10ms
#define SLV_PREF_TIME_OUT (300)
/**
****************************************************************************************
* @brief Retrieve Dev Info to Generic Access Profile, User implement for Callback.
*
* @param[in] conidx connection index
* @param[in] req iequest of info type @see enum gapc_dev_info
* @param[in] maxlen buffer length, DEV_NAME_MAX_LEN or size of gapc_conn_param
* @param[out] info pointer of buffer
*
* @return Length of device information, 0 means an error occurs.
****************************************************************************************
*/
__weak uint16_t gap_svc_get_dev_info(uint8_t conidx, uint8_t req, uint16_t maxlen, uint8_t *info)
{
if (req == GAPC_DEV_NAME)
{
return app_name_get(DEV_NAME_MAX_LEN, info);
}
else if (req == GAPC_DEV_APPEARANCE)
{
write16(info, app_icon_get());
return sizeof(uint16_t);
}
#if (GAP_ATT_CFG & 0x40/*PCP_EN*/)
else if (req == GAPC_DEV_SLV_PREF_PARAMS)
{
struct gapc_conn_param *slv_pref = (struct gapc_conn_param *)info;
// Peripheral Preferred Connection Parameters
slv_pref->intv_min = SLV_PREF_INTV_MIN;
slv_pref->intv_max = SLV_PREF_INTV_MAX;
slv_pref->latency = SLV_PREF_LATENCY;
slv_pref->time_out = SLV_PREF_TIME_OUT;
return sizeof(struct gapc_conn_param);
}
#endif
return 0;
}
/**
****************************************************************************************
* @brief Create profiles, maybe User Override! (__weak func)
* Added in order and judged status in each profile-func.
****************************************************************************************
*/
__weak void app_prf_create(void)
{
// Generic Access Profile(0x1800)
gap_svc_init(GAP_START_HDL, GAP_ATT_CFG);
// Generic Attribute Profile(0x1801)
#if (PRF_GATT)
gatt_svc_init(GATT_START_HDL);
#endif
// Standard Profiles
#if (PRF_DISS)
diss_svc_init();
#endif
#if (PRF_BASS)
bass_svc_init();
#endif
#if (PRF_HIDS)
hids_prf_init();
#endif
#if (PRF_SCPS)
scps_svc_init();
#endif
#if (PRF_MESH)
mesh_svc_init(MESH_START_HDL, MESH_SVC_CFG);
#endif
// Customize Profiles
#if (PRF_SESS)
sess_svc_init();
#endif
#if (PRF_OTAS)
otas_svc_init();
#endif
#if (PRF_PTSS)
ptss_svc_init();
#endif
}
/**
****************************************************************************************
* @section App Interface
****************************************************************************************
*/
/**
****************************************************************************************
* @brief API to Init Application, maybe User Override! (__weak func)
*
* @param[in] rsn reset reason @see enum rst_src_bfs
****************************************************************************************
*/
__weak void app_init(uint16_t rsn)
{
// Init BLE and App to startup or Resume BLE to continue if it wakeup from poweroff.
#if (BLE_LITELIB)
if (RSN_IS_BLE_WKUP(rsn))
{
// Resume BLE (Only supported in LiteLib)
ble_resume();
rc32k_conf(RCLK_DPLL, 7);
}
else
#endif //(BLE_LITELIB)
{
heap_cfg_t heap;
// Config Heap, resized with special lib
heap.base[MEM_ENV] = BLE_HEAP_BASE;
heap.size[MEM_ENV] = BLE_HEAP_ENV_SIZE;
heap.base[MEM_MSG] = BLE_HEAP_BASE + BLE_HEAP_ENV_SIZE;
heap.size[MEM_MSG] = BLE_HEAP_MSG_SIZE;
ble_heap(&heap);
// Init BLE and App
ble_init();
ble_app();
// Init RC32K with Calibration
#if (CFG_SLEEP || RC32K_CALIB_PERIOD)
//rc32k_init(); - replace to watch calib result
rc32k_conf(RCLK_DPLL, 7);
uint16_t trim = rc32k_calib();
DEBUG("RC32K Calib(Msb:%d,Lsb:%d)", trim & 0xF, trim >> 4);
#endif //(CFG_SLEEP || RC32K_CALIB_PERIOD)
}
// Init RF & Modem
rfmdm_init();
NVIC_EnableIRQ(BLE_IRQn);
}
/**
****************************************************************************************
* @brief API to Set State of Application, maybe User Override! (__weak func)
*
* @param[in] state new state
****************************************************************************************
*/
__weak void app_state_set(uint8_t state)
{
DEBUG("State(old:%d,new:%d)", app_state_get(), state);
app_env.state = state;
// Indication, User add more...
}
/**
****************************************************************************************
* @brief API to Get Device Name, maybe User Override! (__weak func)
*
* @param[in] size Length of name Buffer
* @param[out] name Pointer of name buffer
*
* @return Length of device name
****************************************************************************************
*/
__weak uint8_t app_name_get(uint8_t size, uint8_t *name)
{
uint8_t len = sizeof(BLE_DEV_NAME) - 1;
// eg. prefix(BLE_DEV_NAME) + suffix(Addr[0])
if (size < len + 2)
{
// no enough buffer, short copy
len = size;
memcpy(name, BLE_DEV_NAME, len);
}
else
{
// prefix + suffix
memcpy(name, BLE_DEV_NAME, len);
name[len++] = co_hex(ble_dev_addr.addr[0] >> 4);
name[len++] = co_hex(ble_dev_addr.addr[0] & 0x0F);
}
return len;
}
/**
****************************************************************************************
* @section FSM Interface
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Finite state machine for Device Configure, maybe User Override! (__weak func)
*
* @param[in] evt configure event @see enum ble_event
****************************************************************************************
*/
__weak void app_conf_fsm(uint8_t evt)
{
if (evt == BLE_RESET)
{
memset(&app_env, 0, sizeof(app_env));
// Set device config
gapm_set_dev(&ble_dev_config, &ble_dev_addr, NULL);
}
else /*if (evt == BLE_CONFIGURED)*/
{
#if (CFG_SLEEP)
// Set Sleep duration if need
#if (RC32K_CALIB_PERIOD)
ke_timer_set(APP_TIMER_RC32K_CORR, TASK_APP, RC32K_CALIB_PERIOD);
#endif //(RC32K_CALIB_PERIOD)
#endif //(CFG_SLEEP)
app_state_set(APP_IDLE);
// Create Profiles
app_prf_create();
#if (APP_ACTV_EN)
// Create Activities
app_actv_create();
#endif //(APP_ACTV_EN)
#if (PRF_MESH)
// Create Mesh Instance
app_mesh_create();
#endif //(PRF_MESH)
}
}
/**
****************************************************************************************
* @brief Finite state machine for connection event, maybe User Override! (__weak func)
*
* @param[in] evt connection event @see enum ble_event
* @param[in] conidx connection index
* @param[in] param param of connection event
****************************************************************************************
*/
__weak void app_conn_fsm(uint8_t evt, uint8_t conidx, const void* param)
{
switch (evt)
{
case BLE_CONNECTED:
{
// Connected state, record Index
app_env.curidx = conidx;
app_state_set(APP_CONNECTED);
#if (BLE_MULTI_CONN)
uint8_t role = gapc_get_role(conidx);
// Set Connection Bit of conidx
app_env.conbits |= (1 << conidx);
app_env.conrole = (app_env.conrole & ~(1 << conidx)) | (role << conidx);
DEBUG(" multi(cbit:%02X,rbit:%02X,curr:%d)", app_env.conbits, app_env.conrole, app_env.curidx);
// Restart Advertising for more connections as slave role - update from v1.3
if ((role == ROLE_SLAVE)&& (ONE_BITS(app_env.conrole) < BLE_NB_SLAVE))
{
app_adv_action(ACTV_START);
}
#endif //(BLE_MULTI_CONN)
gapc_connect_rsp(conidx, BLE_AUTH);
// Enable profiles by role
} break;
case BLE_DISCONNECTED:
{
#if (BLE_MULTI_CONN)
DEBUG(" Befor(cbit:%02X,rbit:%02X,curr:%d)", app_env.conbits, app_env.conrole, app_env.curidx);
// Clr Connection Bit of conidx
app_env.conbits &= ~(1 << conidx);
if (app_env.conbits == 0)
{
// Go READY when all disconnected
app_state_set(APP_READY);
}
else
{
// Find new index when curr disconnected
if (conidx == app_env.curidx)
{
// Least index of connection or * User customize *
app_env.curidx = co_ctz(app_env.conbits);
}
}
// Role Operation
if (app_env.conrole & (1 << conidx))
{
// As slave role, Clr Bit
app_env.conrole &= ~(1 << conidx);
#if (APP_ACTV_EN && BLE_EN_ADV)
// Restart Advertising
app_adv_action(ACTV_START);
#endif //(APP_ACTV_EN && BLE_EN_ADV)
}
#if (BLE_NB_MASTER)
else
{
struct gapc_disconnect_ind *param = (struct gapc_disconnect_ind *)param;
// As master role, to do * User customize *
if (param->reason == 8 /*ERR_CON_TIMEOUT*/)
{
}
}
#endif // BLE_NB_MASTER
DEBUG(" After(cbit:%02X,rbit:%02X,curr:%d)", app_env.conbits, app_env.conrole, app_env.curidx);
#else
{
app_state_set(APP_READY);
#if (APP_ACTV_EN && BLE_EN_ADV)
// Slave role, Restart Advertising
app_adv_action(ACTV_START);
#endif //(APP_ACTV_EN && BLE_EN_ADV)
}
#endif //(BLE_MULTI_CONN)
} break;
case BLE_BONDED:
{
// todo, eg. save the generated slave's LTK to flash
app_ltk_save(conidx, NULL);
} break;
case BLE_ENCRYPTED:
{
// todo
} break;
default:
break;
}
}
/**
****************************************************************************************
* @section SMP Interface
****************************************************************************************
*/
/**
****************************************************************************************
* @brief API to Get Pairing Feature, maybe User Override! (__weak func)
*
* @param[out] feat Pointer of pairing buffer to fill
****************************************************************************************
*/
__weak void app_pairing_get(struct gapc_pairing *feat)
{
// IO capabilities (@see gap_io_cap)
feat->iocap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
// OOB information (@see gap_oob)
feat->oob = GAP_OOB_AUTH_DATA_NOT_PRESENT;
// Authentication (@see gap_auth)
feat->auth = BLE_AUTH;
// Encryption key size (7 to 16)
feat->key_size = GAP_KEY_LEN;
//Initiator key distribution (@see gap_kdist)
feat->ikey_dist = GAP_KDIST_NONE;
//Responder key distribution (@see gap_kdist)
feat->rkey_dist = GAP_KDIST_ENCKEY;
// Device security requirements (@see gap_sec_req)
feat->sec_req = BLE_SECREQ;
}
/**
****************************************************************************************
* @brief API to Generate LTK for bonding, maybe User Override! (__weak func)
*
* @param[in] conidx connection index
* @param[in|out] ltk Pointer of ltk buffer
****************************************************************************************
*/
__weak void app_ltk_gen(uint8_t conidx, struct gapc_ltk *ltk)
{
// generate key values, User need record it to save later
// ltk->ediv = (uint16_t)rand_word();
// ltk->key_size = GAP_KEY_LEN;
// ltk->ext_info = 0;
// for (uint8_t i = 0; i < GAP_RAND_NB_LEN; i++)
// {
// ltk->randnb.nb[i] = (uint8_t)rand_word();
// }
// for (uint8_t i = 0; i < GAP_KEY_LEN; i++)
// {
// ltk->ltk.key[i] = (uint8_t)rand_word();
// }
#if (BLE_DBG_LTK)
// (here use debugLTK as testing)
memcpy(ltk, &debugLTK, sizeof(struct gapc_ltk));
#endif
}
/**
****************************************************************************************
* @brief API to Save LTK when bonded, maybe User Override! (__weak func)
*
* @param[in] conidx connection index
* @param[in] ltk Pointer of LTK data
****************************************************************************************
*/
__weak void app_ltk_save(uint8_t conidx, const struct gapc_ltk *ltk)
{
// todo, save slave's LTK to flash
}
/**
****************************************************************************************
* @brief API to Find LTK when re-encryption, maybe User Override! (__weak func)
*
* @param[in] ediv EDIV value for matching
* @param[in] rand_nb Rand Nb values for matching
*
* @return NULL for not matched, else return Pointer of LTK found.
****************************************************************************************
*/
__weak const uint8_t *app_ltk_find(uint16_t ediv, const uint8_t *rand_nb)
{
// Compare ediv and rand_nb (here use debugLTK as testing)
#if (BLE_DBG_LTK)
if ((ediv == debugLTK.ediv)
&& (memcmp(rand_nb, debugLTK.randnb.nb, GAP_RAND_NB_LEN) == 0))
{
return debugLTK.ltk.key;
}
#endif
// Not found
return NULL;
}

352
ble/app/app.h Normal file
View File

@ -0,0 +1,352 @@
/**
****************************************************************************************
*
* @file app.h
*
* @brief Header file - Application Defines
*
****************************************************************************************
*/
#ifndef _APP_H_
#define _APP_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include "string.h"
#include "blelib.h"
#include "ke_api.h"
#include "app_actv.h"
/*
* DEFINES
****************************************************************************************
*/
/// Number of Roles, Local Device act as Slave or Master
#if !defined(BLE_NB_SLAVE)
#define BLE_NB_SLAVE (1)
#endif
#if !defined(BLE_NB_MASTER)
#define BLE_NB_MASTER (0)
#endif
#if (BLE_NB_SLAVE + BLE_NB_MASTER > BLE_CONNECTION_MAX)
#error "Number of roles must not exceed BLE_CONNECTION_MAX"
#endif
/// Single or Multiple Connections
#if (BLE_NB_SLAVE + BLE_NB_MASTER > 1)
#define BLE_MULTI_CONN (1)
#else
#define BLE_MULTI_CONN (0)
#endif
/// Enable of Activities(adv/scan/init) @see app_actv.c
#if !defined(BLE_EN_ADV)
#define BLE_EN_ADV (BLE_NB_SLAVE)
#endif
#if !defined(BLE_EN_SCAN)
#define BLE_EN_SCAN (BLE_NB_MASTER)
#endif
#if !defined(BLE_EN_INIT)
#define BLE_EN_INIT (BLE_NB_MASTER)
#endif
#if !defined(APP_ACTV_EN)
#define APP_ACTV_EN (BLE_EN_ADV || BLE_EN_SCAN || BLE_EN_INIT)
#endif
/// Enable Pairing and Bond, used debugLTK @see app_gapc.c
#if !defined(BLE_EN_SMP)
#define BLE_EN_SMP (1)
#endif
#if !defined(BLE_DBG_LTK)
#define BLE_DBG_LTK (0)
#endif
/// Maximal Transmission Unit
#if !defined(BLE_MTU)
#define BLE_MTU (124)
#endif
/// Maximal length of the Device Name value
#define DEV_NAME_MAX_LEN (20)
/// Generic Access Service
#if !defined(BLE_DEV_ICON)
#define BLE_DEV_ICON (0x0000) // Unknow appearance
#endif
/// Period of RC32K Calibration(0 means only calib once when init)
#if !defined(RC32K_CALIB_PERIOD) && (CFG_SLEEP)
#define RC32K_CALIB_PERIOD (15000) // unit in 1ms
#endif
#if ((RC32K_CALIB_PERIOD > 0) && (RC32K_CALIB_PERIOD < 1000) && (CFG_SLEEP))
#error "RC32K_CALIB_PERIOD Less than 1000ms"
#endif
/*
* MACROS
****************************************************************************************
*/
/// Macro of Application Handler Functions
#define APP_SUBTASK_HANDLER(sub) int app_##sub##_handler(msg_id_t msgid, const void *param, \
task_id_t dest_id, task_id_t src_id)
#define APP_MSG_HANDLER(msg) static void app_##msg##_handler(msg_id_t msgid, struct msg const *param, \
task_id_t dest_id, task_id_t src_id)
#define APP_MSG_HANDLER_T(msg) static void app_##msg##_handler(msg_id_t msgid, const void *param, \
task_id_t dest_id, task_id_t src_id)
#define APP_MSG_FUNCTION(msg) app_##msg##_handler(msgid, param, dest_id, src_id)
/*
* ENUMERATIONS
****************************************************************************************
*/
/// APP Task messages
enum app_msg_id
{
APP_BASE_MSG = MSG_ID(APP, 0),
/* Add more messages, such as TIMEOUT */
APP_TIMER_RC32K_CORR,
APP_TIMER_10MINUTES,
};
/// States of APP task
enum app_state_type
{
// Init state
APP_INIT,
// Idle state
APP_IDLE,
// Ready State
APP_READY,
// Connected state
APP_CONNECTED,
APP_PAIRING,
APP_BONDED,
APP_ENCRYPTED,
// Number of defined states.
APP_STATE_MAX
};
/// Event of Ble Finite state machine
enum ble_event
{
// Configure Events
BLE_RESET,
BLE_CONFIGURED,
// Connection Events
BLE_CONNECTED,
BLE_DISCONNECTED,
BLE_BONDED,
BLE_ENCRYPTED,
};
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// Application environment structure
struct app_env_tag
{
// Application State
state_t state;
// Curr Connection Index
uint8_t curidx;
#if (BLE_MULTI_CONN)
// Bits of Connection Index(0:Not Connect, 1:Connected)
uint8_t conbits;
// Bits of Connection Roles(0:Master or None, 1:Slave)
uint8_t conrole;
#endif //(BLE_MULTI_CONN)
};
/*
* VARIABLE DECLARATION
****************************************************************************************
*/
/// Application environment
extern struct app_env_tag app_env;
/// Ble local address (user customize)
extern const bd_addr_t ble_dev_addr;
/// GAP device configuration
extern const struct gapm_dev_config ble_dev_config;
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief API to Init Application, maybe User Override! (__weak func)
*
* @param[in] rsn reset reason @see enum rst_src_bfs
****************************************************************************************
*/
void app_init(uint16_t rsn);
/**
****************************************************************************************
* @brief API to Create Profiles, maybe User Override! (__weak func)
* Added in order and judged status in each profile-func.
****************************************************************************************
*/
void app_prf_create(void);
/**
****************************************************************************************
* @brief API to Create Mesh Instance, maybe User Override! (__weak func)
* Config Mesh stack and Register models.
****************************************************************************************
*/
void app_mesh_create(void);
/**
****************************************************************************************
* @brief Finite state machine for Device Configure, maybe User Override! (__weak func)
*
* @param[in] evt configure event @see enum ble_event
****************************************************************************************
*/
void app_conf_fsm(uint8_t evt);
/**
****************************************************************************************
* @brief Finite state machine for connection event, maybe User Override! (__weak func)
*
* @param[in] evt connection event @see enum ble_event
* @param[in] conidx connection index
* @param[in] param param of connection event
****************************************************************************************
*/
void app_conn_fsm(uint8_t evt, uint8_t conidx, const void*param);
/**
****************************************************************************************
* @brief API to Set State of Application, maybe User Override! (__weak func)
*
* @param[in] state new state
****************************************************************************************
*/
void app_state_set(uint8_t state);
/**
****************************************************************************************
* @brief Macro API to Get Application State
*
* @return state type - 1 octets
****************************************************************************************
*/
static __inline state_t app_state_get(void)
{
return app_env.state;
}
/**
****************************************************************************************
* @brief Macro API to Get Device Appearance
*
* @return icon type - 2 octets
****************************************************************************************
*/
static __inline uint16_t app_icon_get(void)
{
return BLE_DEV_ICON;
}
/**
****************************************************************************************
* @brief API to Get Device Name, maybe User Override! (__weak func)
*
* @param[in] size Length of name Buffer
* @param[out] name Pointer of name buffer
*
* @return Length of device name
****************************************************************************************
*/
uint8_t app_name_get(uint8_t size, uint8_t *name);
/**
****************************************************************************************
* @brief API to Get Pairing Feature, maybe User Override! (__weak func)
*
* @param[out] feat Pointer of pairing buffer to fill
****************************************************************************************
*/
void app_pairing_get(struct gapc_pairing *feat);
/**
****************************************************************************************
* @brief API to Generate LTK for bonding, maybe User Override! (__weak func)
*
* @param[in] conidx connection index
* @param[out] ltk Pointer of LTK buffer to fill
****************************************************************************************
*/
void app_ltk_gen(uint8_t conidx, struct gapc_ltk *ltk);
/**
****************************************************************************************
* @brief API to Save LTK when bonded, maybe User Override! (__weak func)
*
* @param[in] conidx connection index
* @param[in] ltk Pointer of LTK data
****************************************************************************************
*/
void app_ltk_save(uint8_t conidx, const struct gapc_ltk *ltk);
/**
****************************************************************************************
* @brief API to Find LTK when re-encryption, maybe User Override! (__weak func)
*
* @param[in] ediv EDIV value for matching
* @param[in] rand_nb Rand Nb values for matching
*
* @return NULL for not matched, else return Pointer of LTK found.
****************************************************************************************
*/
const uint8_t *app_ltk_find(uint16_t ediv, const uint8_t *rand_nb);
/**
****************************************************************************************
* @brief Dispatch TASK_APP message to sub-handler.
*
* @param[in] msgid Id of the message received.
* @param[in] task_idx Index of the receiving task instance.
*
* @return Handler of the message or NULL.
****************************************************************************************
*/
void* app_task_dispatch(msg_id_t msgid, uint8_t task_idx);
#endif // _APP_H_

950
ble/app/app_actv.c Normal file
View File

@ -0,0 +1,950 @@
/**
****************************************************************************************
*
* @file app_actv.c
*
* @brief Application Activity(Advertising, Scanning and Initiating) - Example
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#include "app.h"
#include "gapm_api.h"
#if (DBG_ACTV)
#include "dbg.h"
#define DEBUG(format, ...) debug("<ACTV>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
#if (APP_ACTV_EN)
/*
* DEFINES
****************************************************************************************
*/
/// Index & State of activities - User Customize
struct actv_env_tag
{
#if (BLE_EN_ADV)
/// Advertising index and state
uint8_t advidx;
uint8_t advsta;
#endif //(BLE_EN_ADV)
#if (BLE_EN_SCAN)
/// Scanning index and state
uint8_t scanidx;
uint8_t scansta;
#endif //(BLE_EN_SCAN)
#if (BLE_EN_INIT)
/// Initiating index and state
uint8_t initidx;
uint8_t initsta;
#endif //(BLE_EN_INIT)
};
/// Activities environment
struct actv_env_tag actv_env;
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section Advertising Activity - Example for User Customize
* enable via pre-define @see BLE_EN_ADV
****************************************************************************************
*/
#if (BLE_EN_ADV)
#undef DEBUG
#if (DBG_ACTV)
#include "dbg.h"
#define DEBUG(format, ...) debug("<ADV>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Advertising duration - 0 mean Always ON (in multiple of 10ms)
#if !defined(APP_ADV_DURATION)
#define APP_ADV_DURATION (0)
#endif
/// Advertising channel map - 37, 38, 39
#if !defined(APP_ADV_CHMAP)
#define APP_ADV_CHMAP (0x07)
#endif
/// Advertising minimum interval - (n)*0.625ms
#if !defined(APP_ADV_INT_MIN)
#define APP_ADV_INT_MIN (64)
#endif
/// Advertising maximum interval - (n)*0.625ms
#if !defined(APP_ADV_INT_MAX)
#define APP_ADV_INT_MAX (160)
#endif
#if (APP_ADV_INT_MIN > APP_ADV_INT_MAX)
#error "ADV_INT_MIN must not exceed ADV_INT_MAX"
#endif
/// Fast advertising interval
#define APP_ADV_FAST_INT (32)
/// Flag of Fixed data
//#define APP_ADV_FIXED_DATA (0)
#if (APP_ADV_FIXED_DATA)
/**
* ADV Unit: 1B(Len=1+n) 1B(Type) nB(Data), @see gap_ad_type
* --------------------------------------------------------------------------------------
* x03 - Length
* x03 - Service 16-bit UUIDs List type
* x00\xFF - Custom Serial Profile:0xFF00
* x03 - Length
* x19 - Appearance type
* x00\x00 - Unknow Device
* x09 - Length
* x09 - Complete Name type
* myBle5.2 - Device Name
* --------------------------------------------------------------------------------------
*/
#define APP_ADV_DATA "\x03\x03\x00\xFF\x03\x19\x00\x00\x09\x09myBle5.2"
#define APP_ADV_DATA_LEN (sizeof(APP_ADV_DATA)-1)
/**
* Scan response data (ADV Unit), @see gap_ad_type
* --------------------------------------------------------------------------------------
* x09 - Length
* xFF - Vendor specific advertising type
* xC5\x09\x48\x59\x2D\x42\x4C\x45 - CompId(0x09C5) + Serial(BLE)
* x09 - Length
* x09 - Complete Name type
* myBle5.2 - Device Name
* --------------------------------------------------------------------------------------
*/
#define APP_SCNRSP_DATA "\x09\xFF\xC5\x09\x48\x59\x2D\x42\x4C\x45"
#define APP_SCNRSP_DATA_LEN (sizeof(APP_SCNRSP_DATA)-1)
#endif // (APP_ADV_FIXED_DATA)
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
static void app_adv_create(void)
{
struct gapm_adv_create_param adv_param;
// Advertising type (@see enum gapm_adv_type)
adv_param.type = GAPM_ADV_TYPE_LEGACY;
// Discovery mode (@see enum gapm_adv_disc_mode)
adv_param.disc_mode = GAPM_ADV_MODE_GEN_DISC;
// Advertising properties (@see enum gapm_adv_prop)
#if (DBG_GAPM)
adv_param.prop = GAPM_ADV_PROP_UNDIR_CONN_MASK | GAPM_ADV_PROP_SCAN_REQ_NTF_EN_BIT;
#else
adv_param.prop = GAPM_ADV_PROP_UNDIR_CONN_MASK;
#endif
// Filtering policy (@see enum gapm_adv_filter_policy)
adv_param.filter_pol = GAPM_ADV_ALLOW_SCAN_ANY_CON_ANY;
// Config primary advertising (@see gapm_adv_prim_cfg)
adv_param.prim_cfg.phy = GAP_PHY_LE_1MBPS;
adv_param.prim_cfg.chnl_map = APP_ADV_CHMAP;
adv_param.prim_cfg.adv_intv_min = APP_ADV_INT_MIN;
adv_param.prim_cfg.adv_intv_max = APP_ADV_INT_MAX;
DEBUG("create(disc:%d,prop:%d)\r\n", adv_param.disc_mode, adv_param.prop);
gapm_create_advertising(GAPM_STATIC_ADDR, &adv_param);
}
static void app_adv_set_adv_data(void)
{
#if (APP_ADV_FIXED_DATA)
gapm_set_adv_data(actv_env.advidx, GAPM_SET_ADV_DATA,
APP_ADV_DATA_LEN, (const uint8_t *)APP_ADV_DATA);
#else
// Reserve 3Bytes for AD_TYPE_FLAGS
uint8_t adv_data[GAP_ADV_DATA_LEN];
uint8_t length = 11;
// Set flags: 3B
adv_data[0] = 0x02;
adv_data[1] = GAP_AD_TYPE_FLAGS; // 0x01 0xFF;//
adv_data[2] = 0x06;
// Set list of UUIDs: 4B
adv_data[3] = 0x03;
adv_data[4] = GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID; // 0x03
#if (PRF_HIDS)
write16p(&adv_data[5], 0x1812); // HID Service
#else
write16p(&adv_data[5], 0xFF00); // Serial Service
#endif
// Set appearance: 4B
uint16_t icon = app_icon_get();
adv_data[7] = 0x03;
adv_data[8] = GAP_AD_TYPE_APPEARANCE; // 0x19
write16p(&adv_data[9], icon);
gapm_set_adv_data(actv_env.advidx, GAPM_SET_ADV_DATA, length, adv_data);
#endif
}
static void app_adv_set_scan_rsp(void)
{
#if (APP_ADV_FIXED_DATA)
gapm_set_adv_data(actv_env.advidx, GAPM_SET_SCAN_RSP_DATA,
APP_SCNRSP_DATA_LEN, (const uint8_t *)APP_SCNRSP_DATA);
#else
uint8_t length;
uint8_t rsp_data[DEV_NAME_MAX_LEN+2];
// Set device name
length = app_name_get(DEV_NAME_MAX_LEN, &rsp_data[2]);
rsp_data[0] = length + 1;
rsp_data[1] = GAP_AD_TYPE_COMPLETE_NAME; // 0x09
gapm_set_adv_data(actv_env.advidx, GAPM_SET_SCAN_RSP_DATA, length + 2, rsp_data);
#endif
}
/**
****************************************************************************************
* @brief Action/Command of Advertising
*
* @param[in] actv_op Operation of activity
****************************************************************************************
*/
void app_adv_action(uint8_t actv_op)
{
switch (actv_op)
{
case ACTV_CREATE:
{
if (actv_env.advsta == ACTV_STATE_OFF)
{
//DEBUG("Creating");
app_adv_create();
actv_env.advsta = ACTV_STATE_CREATE;
}
} break;
case ACTV_START:
{
if (actv_env.advsta == ACTV_STATE_READY)
{
DEBUG("Starting");
gapm_start_advertising(actv_env.advidx, APP_ADV_DURATION);
actv_env.advsta = ACTV_STATE_START;
}
} break;
case ACTV_STOP:
{
if (actv_env.advsta == ACTV_STATE_START)
{
DEBUG("Stopping");
gapm_stop_activity(actv_env.advidx);
actv_env.advsta = ACTV_STATE_STOP;
}
} break;
case ACTV_DELETE:
{
if ((actv_env.advsta != ACTV_STATE_OFF) && (actv_env.advsta != ACTV_STATE_START))
{
DEBUG("Deleting");
gapm_delete_activity(actv_env.advidx);
actv_env.advsta = ACTV_STATE_OFF;
}
} break;
case ACTV_RELOAD:
{
if (actv_env.advsta == ACTV_STATE_START)
{
DEBUG("Stopping");
gapm_stop_activity(actv_env.advidx);
actv_env.advsta = ACTV_STATE_STOP;
}
if ((actv_env.advsta != ACTV_STATE_OFF) && (actv_env.advsta != ACTV_STATE_START))
{
DEBUG("Deleting");
gapm_delete_activity(actv_env.advidx);
actv_env.advsta = ACTV_STATE_OFF;
}
app_adv_create();
actv_env.advsta = ACTV_STATE_CREATE;
} break;
default:
break;
}
}
/**
****************************************************************************************
* @brief Event Procedure of Advertising
*
* @param[in] gapm_op Operation of gapm
* @param[in] status Status of event
****************************************************************************************
*/
void app_adv_event(uint8_t gapm_op, uint8_t status)
{
DEBUG("Evt(op:0x%X,sta:0x%X)", gapm_op, status);
switch (gapm_op)
{
case (GAPM_CREATE_ADV_ACTIVITY):
{
app_adv_set_adv_data();
} break;
case (GAPM_SET_ADV_DATA):
{
app_adv_set_scan_rsp();
} break;
case (GAPM_SET_SCAN_RSP_DATA):
{
actv_env.advsta = ACTV_STATE_READY;
app_adv_action(ACTV_START);
app_state_set(APP_READY);
} break;
case (GAPM_STOP_ACTIVITY):
{
if ((actv_env.advsta == ACTV_STATE_START) || (actv_env.advsta == ACTV_STATE_STOP))
{
actv_env.advsta = ACTV_STATE_READY;
}
} break;
default:
break;
}
}
#endif //(BLE_EN_ADV)
/**
****************************************************************************************
* @section Scanning Activity - Example for User Customize
* enable via pre-define @see BLE_EN_SCAN
****************************************************************************************
*/
#if (BLE_EN_SCAN)
#undef DEBUG
#if (DBG_ACTV)
#include "dbg.h"
#define DEBUG(format, ...) debug("<SCAN>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
#define SCAN_NUM_MAX (5)
uint8_t scan_cnt = 0;
struct gap_bdaddr scan_addr_list[SCAN_NUM_MAX];
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
static void app_start_scanning(void)
{
struct gapm_scan_param scan_param;
/// Type of scanning to be started (@see enum gapm_scan_type)
scan_param.type = GAPM_SCAN_TYPE_CONN_DISC;
/// Properties for the scan procedure (@see enum gapm_scan_prop)
scan_param.prop = GAPM_SCAN_PROP_PHY_1M_BIT | GAPM_SCAN_PROP_ACTIVE_1M_BIT | GAPM_SCAN_PROP_FILT_TRUNC_BIT;
/// Duplicate packet filtering policy (@see enum gapm_dup_filter_pol)
scan_param.dup_filt_pol = GAPM_DUP_FILT_EN;
/// Scan window opening parameters for LE 1M PHY (in unit of 625us)
scan_param.scan_param_1m.scan_intv = GAP_SCAN_FAST_INTV;
scan_param.scan_param_1m.scan_wd = GAP_SCAN_FAST_WIND;
/// Scan window opening parameters for LE Coded PHY
//scan_param.scan_param_coded.scan_intv = GAP_SCAN_SLOW_INTV1;
//scan_param.scan_param_coded.scan_wd = GAP_SCAN_SLOW_WIND1;
/// Scan duration (in unit of 10ms). 0 means that the controller will scan continuously until
/// reception of a stop command from the application
scan_param.duration = 500;//GAP_TMR_GEN_DISC_SCAN;
/// Scan period (in unit of 1.28s). Time interval betweem two consequent starts of a scan duration
/// by the controller. 0 means that the scan procedure is not periodic
scan_param.period = 0;
gapm_start_activity(actv_env.scanidx, sizeof(struct gapm_scan_param), &scan_param);
}
/**
****************************************************************************************
* @brief Action/Command of Scanning
*
* @param[in] actv_op Operation of activity
****************************************************************************************
*/
void app_scan_action(uint8_t actv_op)
{
switch (actv_op)
{
case ACTV_CREATE:
{
if (actv_env.scansta == ACTV_STATE_OFF)
{
DEBUG("Creating");
gapm_create_activity(GAPM_ACTV_TYPE_SCAN, GAPM_STATIC_ADDR);
actv_env.scansta = ACTV_STATE_CREATE;
}
} break;
case ACTV_START:
{
scan_cnt = 0;
if (actv_env.scansta == ACTV_STATE_READY)
{
DEBUG("Starting");
app_start_scanning();
actv_env.scansta = ACTV_STATE_START;
}
} break;
case ACTV_STOP:
{
if (actv_env.scansta == ACTV_STATE_START)
{
DEBUG("Stopping");
gapm_stop_activity(actv_env.scanidx);
actv_env.scansta = ACTV_STATE_STOP;
}
} break;
case ACTV_DELETE:
{
if ((actv_env.scansta != ACTV_STATE_OFF) && (actv_env.scansta != ACTV_STATE_START))
{
DEBUG("Deleting");
gapm_delete_activity(actv_env.scanidx);
actv_env.scansta = ACTV_STATE_OFF;
}
} break;
case ACTV_RELOAD:
{
if (actv_env.scansta == ACTV_STATE_START)
{
DEBUG("Stopping");
gapm_stop_activity(actv_env.scanidx);
actv_env.scansta = ACTV_STATE_STOP;
}
if ((actv_env.scansta != ACTV_STATE_OFF) && (actv_env.scansta != ACTV_STATE_START))
{
DEBUG("Deleting");
gapm_delete_activity(actv_env.scanidx);
actv_env.scansta = ACTV_STATE_OFF;
}
DEBUG("Creating");
gapm_create_activity(GAPM_ACTV_TYPE_SCAN, GAPM_STATIC_ADDR);
actv_env.scansta = ACTV_STATE_CREATE;
} break;
default:
break;
}
}
/**
****************************************************************************************
* @brief Event Procedure of Scanning
*
* @param[in] gapm_op Operation of gapm
* @param[in] status Status of event
****************************************************************************************
*/
void app_scan_event(uint8_t gapm_op, uint8_t status)
{
DEBUG("Evt(op:0x%X,sta:0x%X)", gapm_op, status);
switch (gapm_op)
{
case GAPM_CREATE_SCAN_ACTIVITY:
{
actv_env.scansta = ACTV_STATE_READY;
} break;
case GAPM_STOP_ACTIVITY:
{
if ((actv_env.scansta == ACTV_STATE_START) || (actv_env.scansta == ACTV_STATE_STOP))
{
actv_env.scansta = ACTV_STATE_READY;
}
DEBUG("-->Filter DevAddr");
for (uint8_t idx = 0; idx < scan_cnt; idx++)
{
DEBUG("Scan List[%d]-->", idx);
debugHex((uint8_t *)(&scan_addr_list[idx]), sizeof(struct gap_bdaddr));
}
} break;
default:
break;
}
}
/**
****************************************************************************************
* @brief Store result of Scanning when filter by app_actv_report_ind
*
* @param[in] paddr gap_bdaddr of peer device
****************************************************************************************
*/
void app_scan_result(const struct gap_bdaddr* paddr)
{
for (uint8_t i = 0; i < scan_cnt; i++)
{
if (!memcmp(&scan_addr_list[i], paddr,sizeof(struct gap_bdaddr)))//save addr but diffrent
{
return;
}
}
if (scan_cnt < SCAN_NUM_MAX) //get null array
{
memcpy(&scan_addr_list[scan_cnt], paddr,sizeof(struct gap_bdaddr));
scan_cnt++;
}
}
/**
****************************************************************************************
* @brief Handles activity report. (@see GAPM_EXT_ADV_REPORT_IND)
*
* @param[in] report Report of Advertising data be scanned
****************************************************************************************
*/
void app_actv_report_ind(struct gapm_ext_adv_report_ind const* report)
{
// filter report
if ((report->info & GAPM_REPORT_INFO_REPORT_TYPE_MASK) == GAPM_REPORT_TYPE_ADV_LEG)
{
const uint8_t *p_cursor = report->data;
const uint8_t *p_end_cusor = report->data + report->length;
while (p_cursor < p_end_cusor)
{
// Extract AD type
uint8_t ad_type = *(p_cursor + 1);
if (ad_type == GAP_AD_TYPE_APPEARANCE)
{
uint16_t icon = read16p(p_cursor+2);
// Filter special appearance device
if ((icon == 0x03C1) || (icon == 0x03C5)) // HID Gamepad
{
app_scan_result(&report->trans_addr);
break;
}
}
else if ((ad_type == GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID) || (ad_type == GAP_AD_TYPE_MORE_16_BIT_UUID))
{
uint16_t uuid = read16p(p_cursor+2);
// Filter special uuid device
if (((uuid == 0x18F0) || (uuid == 0xFF00)))// && (param->trans_addr.addr.addr[0] == 0x04))
{
app_scan_result(&report->trans_addr);
break;
}
}
else
{
// Filter Rule more...
}
/* Go to next advertising info */
p_cursor += (*p_cursor + 1);
}
}
}
#endif //(BLE_EN_SCAN)
/**
****************************************************************************************
* @section Initiating Activity - Example for User Customize
* enable via pre-define @see BLE_EN_INIT
****************************************************************************************
*/
#if (BLE_EN_INIT)
#undef DEBUG
#if (DBG_ACTV)
#include "dbg.h"
#define DEBUG(format, ...) debug("<INIT>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#endif
#if !defined(APP_INIT_TIMEOUT)
#define APP_INIT_TIMEOUT 100 // timeout unit in 10ms
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
const struct gap_bdaddr dflt_peer =
{
.addr = {{0x11, 0x22, 0x33, 0xa1, 0x01, 0xd3}},
.addr_type = ADDR_RAND,
};
const struct gapm_conn_param dflt_conn_param =
{
/// Minimum value for the connection interval (in unit of 1.25ms). Allowed range is 7.5ms to 4s.
.conn_intv_min = 10,
/// Maximum value for the connection interval (in unit of 1.25ms). Allowed range is 7.5ms to 4s.
.conn_intv_max = 10,
/// Slave latency. Number of events that can be missed by a connected slave device
.conn_latency = 0,
/// Link supervision timeout (in unit of 10ms). Allowed range is 100ms to 32s
.supervision_to = 300,
/// Recommended minimum duration of connection events (in unit of 625us)
.ce_len_min = 2,
/// Recommended maximum duration of connection events (in unit of 625us)
.ce_len_max = 4,
};
/*
* FUNCTION DEFINITIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Start initiating to peer device
*
* @param[in] paddr gap_bdaddr of peer device
****************************************************************************************
*/
void app_start_initiating(const struct gap_bdaddr* paddr)
{
if ((actv_env.initsta == ACTV_STATE_READY) || (actv_env.initsta == ACTV_STATE_STOP))
{
struct gapm_init_param init_param;
if (paddr == NULL)
{
paddr = &dflt_peer;
}
init_param.type = GAPM_INIT_TYPE_DIRECT_CONN_EST;
init_param.prop = GAPM_INIT_PROP_1M_BIT;
init_param.conn_to = APP_INIT_TIMEOUT; // timeout unit in 10ms, update from v1.3
init_param.scan_param_1m.scan_intv = GAP_SCAN_FAST_INTV;
init_param.scan_param_1m.scan_wd = GAP_SCAN_FAST_WIND;
memcpy(&init_param.conn_param_1m, &dflt_conn_param, sizeof(struct gapm_conn_param));
memcpy(&init_param.peer_addr, paddr, sizeof(struct gap_bdaddr));
gapm_start_activity(actv_env.initidx, sizeof(struct gapm_init_param), &init_param);
DEBUG("Starting");
actv_env.initsta = ACTV_STATE_START;
}
}
/**
****************************************************************************************
* @brief Action/Command of Initiating
*
* @param[in] actv_op Operation of activity
****************************************************************************************
*/
void app_init_action(uint8_t actv_op)
{
switch (actv_op)
{
case ACTV_CREATE:
{
if (actv_env.initsta == ACTV_STATE_OFF)
{
DEBUG("Creating");
gapm_create_activity(GAPM_ACTV_TYPE_INIT, GAPM_STATIC_ADDR);
actv_env.initsta = ACTV_STATE_CREATE;
}
} break;
case ACTV_START:
{
app_start_initiating(NULL);
} break;
case ACTV_STOP:
{
if (actv_env.initsta == ACTV_STATE_START)
{
DEBUG("Stopping");
gapm_stop_activity(actv_env.initidx);
actv_env.initsta = ACTV_STATE_STOP;
}
} break;
case ACTV_DELETE:
{
if ((actv_env.initsta != ACTV_STATE_OFF) && (actv_env.initsta != ACTV_STATE_START))
{
DEBUG("Deleting");
gapm_delete_activity(actv_env.initidx);
actv_env.initsta = ACTV_STATE_OFF;
}
} break;
case ACTV_RELOAD:
{
if (actv_env.initsta == ACTV_STATE_START)
{
DEBUG("Stopping");
gapm_stop_activity(actv_env.initidx);
actv_env.initsta = ACTV_STATE_STOP;
}
if ((actv_env.initsta != ACTV_STATE_OFF) && (actv_env.initsta != ACTV_STATE_START))
{
DEBUG("Deleting");
gapm_delete_activity(actv_env.initidx);
actv_env.initsta = ACTV_STATE_OFF;
}
DEBUG("Creating");
gapm_create_activity(GAPM_ACTV_TYPE_INIT, GAPM_STATIC_ADDR);
actv_env.initsta = ACTV_STATE_CREATE;
} break;
default:
break;
}
}
/**
****************************************************************************************
* @brief Event Procedure of Initiating
*
* @param[in] gapm_op Operation of gapm
* @param[in] status Status of event
****************************************************************************************
*/
void app_init_event(uint8_t gapm_op, uint8_t status)
{
DEBUG("Evt(op:0x%X,sta:0x%X)", gapm_op, status);
switch (gapm_op)
{
case GAPM_CREATE_INIT_ACTIVITY:
{
actv_env.initsta = ACTV_STATE_READY;
} break;
case GAPM_STOP_ACTIVITY:
{
if ((actv_env.initsta == ACTV_STATE_START) || (actv_env.initsta == ACTV_STATE_STOP))
{
actv_env.initsta = ACTV_STATE_READY;
}
} break;
default:
break;
}
}
#endif //(BLE_EN_INIT)
/**
****************************************************************************************
* @brief Create activities when Initialization complete.
****************************************************************************************
*/
void app_actv_create(void)
{
memset(&actv_env, 0, sizeof(actv_env));
#if (BLE_EN_ADV)
app_adv_action(ACTV_CREATE);
#endif //(BLE_EN_ADV)
#if (BLE_EN_SCAN)
app_scan_action(ACTV_CREATE);
#endif //(BLE_EN_SCAN)
#if (BLE_EN_INIT)
app_init_action(ACTV_CREATE);
#endif //(BLE_EN_INIT)
}
/**
****************************************************************************************
* @brief Handles activity command complete event.
*
* @param[in] gapm_op Operation of gapm
* @param[in] status Status of event
****************************************************************************************
*/
void app_actv_cmp_evt(uint8_t operation, uint8_t status)
{
switch (operation)
{
#if (BLE_EN_ADV)
case (GAPM_CREATE_ADV_ACTIVITY):
case (GAPM_SET_ADV_DATA):
case (GAPM_SET_SCAN_RSP_DATA):
{
app_adv_event(operation, status);
} break;
#endif //(BLE_EN_ADV)
#if (BLE_EN_SCAN)
case GAPM_CREATE_SCAN_ACTIVITY:
{
app_scan_event(operation, status);
} break;
#endif //(BLE_EN_SCAN)
#if (BLE_EN_INIT)
case GAPM_CREATE_INIT_ACTIVITY:
{
app_init_event(operation, status);
} break;
#endif //(BLE_EN_INIT)
default:
break;
}
}
/**
****************************************************************************************
* @brief Handles activity created. (@see GAPM_ACTIVITY_CREATED_IND)
*
* @param[in] actv_type Type of activities(@see enum gapm_actv_type)
* @param[in] actv_idx Index of activities created
****************************************************************************************
*/
void app_actv_created_ind(uint8_t actv_type, uint8_t actv_idx)
{
switch (actv_type)
{
#if (BLE_EN_ADV)
case GAPM_ACTV_TYPE_ADV:
{
actv_env.advidx = actv_idx;
} break;
#endif //(BLE_EN_ADV)
#if (BLE_EN_SCAN)
case GAPM_ACTV_TYPE_SCAN:
{
actv_env.scanidx = actv_idx;
} break;
#endif //(BLE_EN_SCAN)
#if (BLE_EN_INIT)
case GAPM_ACTV_TYPE_INIT:
{
actv_env.initidx = actv_idx;
} break;
#endif //(BLE_EN_INIT)
default:
break;
}
}
/**
****************************************************************************************
* @brief Handles activity stopped. (@see GAPM_ACTIVITY_STOPPED_IND)
*
* @param[in] actv_type Type of activity(@see enum gapm_actv_type)
* @param[in] reason Reason of stopped
****************************************************************************************
*/
void app_actv_stopped_ind(uint8_t actv_type, uint8_t actv_idx, uint8_t reason)
{
switch (actv_type)
{
#if (BLE_EN_ADV)
case GAPM_ACTV_TYPE_ADV:
{
// Advertising Stopped by slave connection or duration timeout
app_adv_event(GAPM_STOP_ACTIVITY, reason);
// Duration timeout, go IDLE - update from v1.3
if ((reason == GAP_ERR_TIMEOUT) && (app_state_get() == APP_READY))
{
app_state_set(APP_IDLE);
}
} break;
#endif //(BLE_EN_ADV)
#if (BLE_EN_SCAN)
case GAPM_ACTV_TYPE_SCAN:
{
app_scan_event(GAPM_STOP_ACTIVITY, reason);
} break;
#endif //(BLE_EN_SCAN)
#if (BLE_EN_INIT)
case GAPM_ACTV_TYPE_INIT:
{
app_init_event(GAPM_STOP_ACTIVITY, reason);
} break;
#endif //(BLE_EN_INIT)
default:
break;
}
}
#endif //(APP_ACTV_EN)

178
ble/app/app_actv.h Normal file
View File

@ -0,0 +1,178 @@
/**
****************************************************************************************
*
* @file app_actv.h
*
* @brief Header file - Application Activity(Advertising, Scanning and Initiating).
*
****************************************************************************************
*/
#ifndef APP_ACTV_H_
#define APP_ACTV_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include "string.h"
#include "gapm.h"
#include "gapc.h"
/*
* DEFINES
****************************************************************************************
*/
/// Operation of Activity
enum actv_op
{
// Activity create
ACTV_CREATE = 0,
// Activity start
ACTV_START,
// Activity stop
ACTV_STOP,
// Activity delete
ACTV_DELETE,
// Activity reload
ACTV_RELOAD,
};
/// States of Activity
enum actv_state
{
// Activity disable
ACTV_STATE_OFF = 0,
// Activity creating
ACTV_STATE_CREATE,
// Activity created
ACTV_STATE_READY,
// Activity started
ACTV_STATE_START,
// Activity stopping
ACTV_STATE_STOP,
};
/// Configure of Activity - Used for PTS-Test
struct actv_conf
{
// discovery mode (@see gapm_adv_disc_mode)
uint8_t adv_disc;
// adv properties (@see enum gapm_adv_prop)
uint8_t adv_prop;
// bit7~2:data type bit1~0:address type (@see gapm_own_addr)
uint8_t adv_conf;
// own address type as master role (@see gapm_own_addr)
uint8_t mst_conf;
// /// Scanning Types (@see enum gapm_scan_type)
uint8_t sca_type;
};
extern uint8_t scan_cnt;
extern struct gap_bdaddr scan_addr_list[];
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Create activities when Initialization complete.
****************************************************************************************
*/
void app_actv_create(void);
/**
****************************************************************************************
* @brief Handles activity command complete event.
*
* @param[in] gapm_op Operation of gapm
* @param[in] status Status of event
****************************************************************************************
*/
void app_actv_cmp_evt(uint8_t gapm_op, uint8_t status);
/**
****************************************************************************************
* @brief Handles activity created. (@see GAPM_ACTIVITY_CREATED_IND)
*
* @param[in] actv_type Type of activity(@see enum gapm_actv_type)
* @param[in] actv_idx Index of activity created
****************************************************************************************
*/
void app_actv_created_ind(uint8_t actv_type, uint8_t actv_idx);
/**
****************************************************************************************
* @brief Handles activity stopped. (@see GAPM_ACTIVITY_STOPPED_IND)
*
* @param[in] actv_type Type of activity(@see enum gapm_actv_type)
* @param[in] reason Reason of stopped
****************************************************************************************
*/
void app_actv_stopped_ind(uint8_t actv_type, uint8_t actv_idx, uint8_t reason);
/**
****************************************************************************************
* @brief Handles activity report. (@see GAPM_EXT_ADV_REPORT_IND)
*
* @param[in] report Report of Advertising data be scanned
****************************************************************************************
*/
void app_actv_report_ind(struct gapm_ext_adv_report_ind const* report);
/**
****************************************************************************************
* @brief Action/Command of Advertising
*
* @param[in] actv_op Operation of activity
****************************************************************************************
*/
void app_adv_action(uint8_t actv_op);
/**
****************************************************************************************
* @brief Action/Command of Scanning
*
* @param[in] actv_op Operation of activity
****************************************************************************************
*/
void app_scan_action(uint8_t actv_op);
/**
****************************************************************************************
* @brief Store result of Scanning when filter by app_actv_report_ind
*
* @param[in] paddr gap_bdaddr of peer device
****************************************************************************************
*/
void app_scan_result(const struct gap_bdaddr* paddr);
/**
****************************************************************************************
* @brief Action/Command of Initiating
*
* @param[in] actv_op Operation of activity
****************************************************************************************
*/
void app_init_action(uint8_t actv_op);
/**
****************************************************************************************
* @brief Start initiating to peer device
*
* @param[in] paddr gap_bdaddr of peer device
****************************************************************************************
*/
void app_start_initiating(const struct gap_bdaddr* paddr);
#endif // APP_ACTV_H_

382
ble/app/app_gapc.c Normal file
View File

@ -0,0 +1,382 @@
/**
****************************************************************************************
*
* @file app_gapc.c
*
* @brief App SubTask of GAP Controller Message - Example
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "bledef.h"
#include "app.h"
#if (DBG_GAPC)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat,len)
#endif
/*
* DEFINES
****************************************************************************************
*/
/*
* MESSAGE HANDLERS
****************************************************************************************
*/
APP_MSG_HANDLER(gapc_cmp_evt)
{
// Command complete, may ignore
DEBUG("CMP_EVT(op:%d,sta:0x%x)", param->operation, param->status);
}
APP_MSG_HANDLER(gapc_connection_req_ind)
{
#if (DBG_GAPC)
uint8_t conidx = TASK_IDX(src_id);
#endif
DEBUG("gapc_connection_req_ind(cid:%d,chdl:%d,conn[intv:%d,late:%d,to:%d],acc:%d,caddr:%d)", conidx, param->conhdl,
param->con_interval, param->con_latency, param->sup_to, param->clk_accuracy, param->peer_addr_type);
debugHex(param->peer_addr.addr, GAP_BD_ADDR_LEN);
// Indicate Connect_Req_Pkt be send, need wait to sync (try 6 times of conn_event).
// If synced, goto gapc_connection_ind. Otherwise, goto gapc_disconnect_ind(reason=0x3E)
//app_conn_fsm(BLE_CONNECTING, conidx, param);
}
APP_MSG_HANDLER(gapc_connection_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("gapc_connection_ind(cid:%d,chdl:%d,role:%d)", conidx, param->conhdl, param->role);
// Connection established, update from v1.3
app_conn_fsm(BLE_CONNECTED, conidx, param);
}
APP_MSG_HANDLER(gapc_disconnect_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("gapc_disconnect_ind(cid:%d,hdl:%d,reason:0x%X)", conidx, param->conhdl, param->reason);
app_conn_fsm(BLE_DISCONNECTED, conidx, param);
}
APP_MSG_HANDLER(gapc_param_update_req_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("param_update(cid:%d,invM:%d,invI:%d,late:%d,timo:%d)", conidx,
param->intv_max, param->intv_min, param->latency, param->time_out);
// Connection param accept or reject
gapc_param_update_rsp(conidx, true, 0x2, 0x4);
}
APP_MSG_HANDLER(gapc_param_updated_ind)
{
DEBUG("param_updated_ind(cid:%d,intv:%d,late:%d,timo:%d)", TASK_IDX(src_id),
param->con_interval, param->con_latency, param->sup_to);
// Current param, may update to slaves
}
APP_MSG_HANDLER(gapc_le_pkt_size_ind)
{
DEBUG("le_pkt_size_ind(cid:%d,txB:%d,txT:%d,rxB:%d,rxT:%d)", TASK_IDX(src_id),
param->max_tx_octets, param->max_tx_time, param->max_rx_octets, param->max_rx_time);
}
#if (BLE_EN_SMP)
APP_MSG_HANDLER(gapc_bond_req_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("bond_req_ind(req:%d)", param->request);
switch (param->request)
{
case (GAPC_PAIRING_REQ):
{
struct gapc_pairing feat;
// Retrieve pairing feature to response
app_pairing_get(&feat);
gapc_smp_pairing_rsp(conidx, &feat);
DEBUG("PAIRING_REQ(auth:0x%X)", param->data.auth_req);
debugHex((uint8_t *)&feat, sizeof(struct gapc_pairing));
} break;
case (GAPC_LTK_EXCH):
{
struct gapc_ltk ltk;
// Generate all rand values to exchange
app_ltk_gen(conidx, &ltk);
gapc_smp_pairing_ltk_exch(conidx, &ltk);
DEBUG("LTK_EXCH(size:%d)", param->data.key_size);
debugHex((uint8_t *)&ltk, sizeof(struct gapc_ltk));
} break;
case (GAPC_IRK_EXCH):
{
DEBUG("IRK_EXCH");
// Load IRK
//memcpy(&(data.irk.irk), gapm_get_irk(), GAP_KEY_LEN);
// load device address
//memcpy(&(data.irk.addr.addr), gapm_get_bdaddr(), GAP_BD_ADDR_LEN);
//data.irk.addr.addr_type = (data.irk.addr.addr.addr[5] & 0xC0) ? ADDR_RAND : ADDR_PUBLIC;
} break;
case (GAPC_TK_EXCH):
{
DEBUG("TK_EXCH(type:%d)", param->data.tk_type);
if (param->data.tk_type == GAP_TK_OOB)
{
DEBUG("TK_OOB>>>");
return;
}
else if (param->data.tk_type == GAP_TK_DISPLAY)
{
struct gap_sec_key tk;
// Generate a PIN Code- (Between 100000 and 999999)
uint32_t pin_code = (100000 + (rand_word() % 900000));
// Set the TK value
memset(&tk.key, 0, GAP_KEY_LEN);
write32p(&tk.key, pin_code);
DEBUG("TK_DISPLAY:%06d", pin_code);
gapc_smp_pairing_tk_exch(conidx, true, &tk);
}
else //if (param->data.tk_type == GAP_TK_KEY_ENTRY)
{
DEBUG("TK_KEY_ENTRY>>>");
return;
}
} break;
case (GAPC_CSRK_EXCH):
{
struct gap_sec_key csrk;
DEBUG("CSRK_EXCH");
memset(&csrk.key, 0, GAP_KEY_LEN);
gapc_smp_pairing_csrk_exch(conidx, &csrk);
} break;
#if (SEC_CON_ENB)
case (GAPC_OOB_EXCH):
{
DEBUG("OOB_EXCH(conf,rand)>>>");
debugHex(param->data.oob_data.conf, GAP_KEY_LEN);
debugHex(param->data.oob_data.rand, GAP_KEY_LEN);
return;
} //break;
case (GAPC_NC_EXCH):
{
DEBUG("NC_EXCH(%06d)", read32p(param->data.nc_data.value));
gapc_smp_pairing_nc_exch(conidx, true);
} break;
#endif //(SEC_CON_ENB)
default:
{
// not happen
} break;
}
}
APP_MSG_HANDLER(gapc_bond_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("bond_ind(info:%d)", param->info);
switch (param->info)
{
case (GAPC_PAIRING_SUCCEED):
{
DEBUG("PAIRING_SUCCEED(auth:%X,ltk:%d)", param->data.auth.info, param->data.auth.ltk_present);
// Update the bonding status
app_conn_fsm(BLE_BONDED, conidx, param);
} break;
case (GAPC_PAIRING_FAILED):
{
DEBUG("PAIRING_FAILED(reason:0x%X)", param->data.reason);
//gapc_smp_security_req(conidx, GAP_AUTH_REQ_NO_MITM_NO_BOND);
} break;
case (GAPC_REPEATED_ATTEMPT):
{
DEBUG("REPEATED_ATTEMPT");
gapc_disconnect(conidx);
} break;
case (GAPC_IRK_EXCH):
{
DEBUG("IRK_EXCH(irk,addr)");
debugHex(param->data.irk.irk.key, GAP_KEY_LEN);
debugHex(param->data.irk.addr.addr.addr, GAP_BD_ADDR_LEN);
// Store peer identity
} break;
// In Secure Connections we get BOND_IND with SMPC calculated LTK
case (GAPC_LTK_EXCH) :
{
DEBUG("Bond LTK_EXCH(size:%d)", param->data.ltk.key_size);
debugHex(param->data.ltk.ltk.key, sizeof(struct gapc_ltk));
// Store peer LTK
// if ((gapc_auth_get(conidx) & GAP_AUTH_SEC_CON) || (gapc_get_role(conidx) == ROLE_MASTER))
// {
// app_ltk_save(conidx, &param->data.ltk);
// }
} break;
default:
break;
}
}
APP_MSG_HANDLER(gapc_encrypt_req_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("encrypt_req_ind(ediv:0x%X,rand)", param->ediv);
debugHex(param->rand_nb.nb, GAP_RAND_NB_LEN);
// Check if the provided EDIV and Rand Nb values match with the stored values
struct gap_sec_key *ltk = (struct gap_sec_key *)app_ltk_find(param->ediv, param->rand_nb.nb);
if (ltk != NULL)
{
DEBUG("->Find Same LTK");
gapc_smp_encrypt_cfm(conidx, GAP_KEY_LEN, ltk);
}
else
{
// bonded with another device, disconnect the link
DEBUG("->Find Diff LTK");
gapc_smp_encrypt_cfm(conidx, 0, NULL);
//gapc_smp_security_req(conidx, GAP_AUTH_REQ_NO_MITM_BOND);
gapc_disconnect(conidx);
}
}
APP_MSG_HANDLER(gapc_encrypt_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("encryp_ind(auth:%d)", param->auth);
// encryption/ re-encryption succeeded
app_conn_fsm(BLE_ENCRYPTED, conidx, param);
}
APP_MSG_HANDLER(gapc_security_ind)
{
// slave request security
DEBUG("security_ind(auth:%d)", param->auth);
}
#endif //(BLE_EN_SMP)
/**
****************************************************************************************
* @brief SubTask Handler of GAP controller Message.
****************************************************************************************
*/
APP_SUBTASK_HANDLER(gapc_msg)
{
switch (msgid)
{
case GAPC_CMP_EVT:
{
APP_MSG_FUNCTION(gapc_cmp_evt);
} break;
case GAPC_CONNECTION_REQ_IND:
{
APP_MSG_FUNCTION(gapc_connection_req_ind);
} break;
case GAPC_CONNECTION_IND:
{
// Connection established, update from v1.3
APP_MSG_FUNCTION(gapc_connection_ind);
} break;
case GAPC_DISCONNECT_IND:
{
APP_MSG_FUNCTION(gapc_disconnect_ind);
} break;
case GAPC_PARAM_UPDATE_REQ_IND:
{
APP_MSG_FUNCTION(gapc_param_update_req_ind);
} break;
case GAPC_PARAM_UPDATED_IND:
{
APP_MSG_FUNCTION(gapc_param_updated_ind);
} break;
#if (BLE_EN_SMP)
case GAPC_BOND_REQ_IND:
{
APP_MSG_FUNCTION(gapc_bond_req_ind);
} break;
case GAPC_BOND_IND:
{
APP_MSG_FUNCTION(gapc_bond_ind);
} break;
case GAPC_ENCRYPT_REQ_IND:
{
APP_MSG_FUNCTION(gapc_encrypt_req_ind);
} break;
case GAPC_ENCRYPT_IND:
{
APP_MSG_FUNCTION(gapc_encrypt_ind);
} break;
case GAPC_SECURITY_IND:
{
APP_MSG_FUNCTION(gapc_security_ind);
} break;
#endif //(BLE_EN_SMP)
case GAPC_LE_PKT_SIZE_IND:
{
APP_MSG_FUNCTION(gapc_le_pkt_size_ind);
} break;
default:
{
DEBUG("Unknow MsgId:0x%X", msgid);
} break;
}
return (MSG_STATUS_FREE);
}

146
ble/app/app_gapm.c Normal file
View File

@ -0,0 +1,146 @@
/**
****************************************************************************************
*
* @file app_gapm.c
*
* @brief App SubTask of GAP Manager Message - Example
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#include <stdint.h>
#include "bledef.h"
#include "app.h"
#if (DBG_GAPM)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* MESSAGE HANDLERS
****************************************************************************************
*/
APP_MSG_HANDLER(gapm_cmp_evt)
{
if (param->operation == GAPM_RESET)
{
DEBUG("Reset(sta:0x%02X)", param->status);
// Dev Config after reset
app_conf_fsm(BLE_RESET);
}
else if (param->operation == GAPM_SET_DEV_CONFIG)
{
DEBUG("Dev Config(sta:0x%02X)", param->status);
// Init profiles or activities after config
app_conf_fsm(BLE_CONFIGURED);
}
#if (APP_ACTV_EN)
else if (param->operation >= GAPM_CREATE_ADV_ACTIVITY)
{
DEBUG("Actv Evt(op:0x%02X,sta:0x%02X)", param->operation, param->status);
app_actv_cmp_evt(param->operation, param->status);
}
#endif //(APP_ACTV_EN)
else
{
DEBUG("Unknow Evt(op:0x%02X,sta:0x%02X)", param->operation, param->status);
}
}
#if (APP_ACTV_EN)
APP_MSG_HANDLER(gapm_activity_created_ind)
{
DEBUG("Actv Created(id:%d,typ:%d)", param->actv_idx, param->actv_type);
app_actv_created_ind(param->actv_type, param->actv_idx);
}
APP_MSG_HANDLER(gapm_activity_stopped_ind)
{
DEBUG("Actv Stopped(id:%d,typ:%d,rea:0x%02X)", param->actv_idx, param->actv_type, param->reason);
app_actv_stopped_ind(param->actv_type, param->actv_idx, param->reason);
}
#if (BLE_EN_SCAN)
APP_MSG_HANDLER(gapm_ext_adv_report_ind)
{
DEBUG("Scanned(id:%d,info:0x%02x,Addr{T:%d},Data{L:%d})", param->actv_idx, param->info,
param->trans_addr.addr_type, param->length);
debugHex((uint8_t *)(&param->trans_addr), sizeof(struct gap_bdaddr));
debugHex(param->data, param->length);
DEBUG("\r\n");
app_actv_report_ind(param);
}
#endif //(BLE_EN_SCAN)
#endif //(APP_ACTV_EN)
#if (DBG_GAPM)
APP_MSG_HANDLER(gapm_scan_request_ind)
{
DEBUG("Scan request(id:%d,Addr{T:%d})", param->actv_idx, param->trans_addr.addr_type);
debugHex((uint8_t *)(&param->trans_addr), sizeof(struct gap_bdaddr));
}
#endif
/**
****************************************************************************************
* @brief SubTask Handler of GAP manager Message.
****************************************************************************************
*/
APP_SUBTASK_HANDLER(gapm_msg)
{
switch (msgid)
{
case GAPM_CMP_EVT:
{
APP_MSG_FUNCTION(gapm_cmp_evt);
} break;
#if (APP_ACTV_EN)
case GAPM_ACTIVITY_CREATED_IND:
{
APP_MSG_FUNCTION(gapm_activity_created_ind);
} break;
case GAPM_ACTIVITY_STOPPED_IND:
{
APP_MSG_FUNCTION(gapm_activity_stopped_ind);
} break;
#if (BLE_EN_SCAN)
case GAPM_EXT_ADV_REPORT_IND:
{
APP_MSG_FUNCTION(gapm_ext_adv_report_ind);
} break;
#endif //(BLE_EN_SCAN)
#if (DBG_GAPM)
case GAPM_SCAN_REQUEST_IND:
{
APP_MSG_FUNCTION(gapm_scan_request_ind);
} break;
#endif
#endif //(APP_ACTV_EN)
default:
{
DEBUG("Unknow MsgId:0x%X", msgid);
} break;
}
return (MSG_STATUS_FREE);
}

157
ble/app/app_gatt.c Normal file
View File

@ -0,0 +1,157 @@
/**
****************************************************************************************
*
* @file app_gatt.c
*
* @brief App SubTask of GATT Message - Example
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#if (GATT_CLI)
#include "app.h"
#include "gatt.h"
#include "gatt_api.h"
#if (DBG_GATT)
#include "dbg.h"
#define DEBUG(format, ...) debug("<GATT>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* DEFINES
****************************************************************************************
*/
/*
* MESSAGE HANDLERS
****************************************************************************************
*/
APP_MSG_HANDLER(gatt_cmp_evt)
{
DEBUG("Cmp_evt(op:%d,sta:0x%02x)", param->operation, param->status);
}
APP_MSG_HANDLER(gatt_mtu_changed_ind)
{
DEBUG("mtu_chg:%d,seq:%d", param->mtu, param->seq_num);
}
APP_MSG_HANDLER(gatt_disc_svc_ind)
{
DEBUG("disc_svc(shdl:0x%X,ehdl:0x%X,ulen:%d)", param->start_hdl, param->end_hdl, param->uuid_len);
debugHex(param->uuid, param->uuid_len);
}
APP_MSG_HANDLER(gatt_disc_svc_incl_ind)
{
DEBUG("disc_incl(ahdl:0x%X,shdl:0x%X,ehdl:0x%X,ulen:%d)", param->attr_hdl, param->start_hdl, param->end_hdl, param->uuid_len);
debugHex(param->uuid, param->uuid_len);
}
APP_MSG_HANDLER(gatt_disc_char_ind)
{
DEBUG("disc_char(ahdl:0x%X,phdl:0x%X,prop:0x%X,ulen:%d)", param->attr_hdl, param->pointer_hdl, param->prop, param->uuid_len);
debugHex(param->uuid, param->uuid_len);
}
APP_MSG_HANDLER(gatt_disc_char_desc_ind)
{
DEBUG("disc_desc(ahdl:0x%X,ulen:%d)", param->attr_hdl, param->uuid_len);
debugHex(param->uuid, param->uuid_len);
}
APP_MSG_HANDLER(gatt_read_ind)
{
DEBUG("Read_ind(hdl:0x%02x,oft:%d,len:%d)", param->handle, param->offset, param->length);
debugHex(param->value, param->length);
}
APP_MSG_HANDLER(gatt_event_ind)
{
DEBUG("Evt_ind(typ:%d,hdl:0x%02x,len:%d)", param->type, param->handle, param->length);
debugHex(param->value, param->length);
}
APP_MSG_HANDLER(gatt_event_req_ind)
{
uint8_t conidx = TASK_IDX(src_id);
DEBUG("Evt_req_ind(typ:%d,hdl:0x%02x,len:%d)", param->type, param->handle, param->length);
debugHex(param->value, param->length);
gatt_evt_cfm(conidx, param->handle);
}
/**
****************************************************************************************
* @brief SubTask Handler of GATT Message.
****************************************************************************************
*/
APP_SUBTASK_HANDLER(gatt_msg)
{
switch (msgid)
{
case GATT_CMP_EVT:
{
APP_MSG_FUNCTION(gatt_cmp_evt);
} break;
case GATT_MTU_CHANGED_IND:
{
APP_MSG_FUNCTION(gatt_mtu_changed_ind);
} break;
case GATT_DISC_SVC_IND:
{
APP_MSG_FUNCTION(gatt_disc_svc_ind);
} break;
case GATT_DISC_SVC_INCL_IND:
{
APP_MSG_FUNCTION(gatt_disc_svc_incl_ind);
} break;
case GATT_DISC_CHAR_IND:
{
APP_MSG_FUNCTION(gatt_disc_char_ind);
} break;
case GATT_DISC_CHAR_DESC_IND:
{
APP_MSG_FUNCTION(gatt_disc_char_desc_ind);
} break;
case GATT_READ_IND:
{
APP_MSG_FUNCTION(gatt_read_ind);
} break;
case GATT_EVENT_IND:
{
APP_MSG_FUNCTION(gatt_event_ind);
} break;
case GATT_EVENT_REQ_IND:
{
APP_MSG_FUNCTION(gatt_event_req_ind);
} break;
default:
{
DEBUG("Unknow MsgId:0x%X", msgid);
} break;
}
return (MSG_STATUS_FREE);
}
#endif //(GATT_CLI)

110
ble/app/app_msg.c Normal file
View File

@ -0,0 +1,110 @@
/**
****************************************************************************************
*
* @file app_msg.c
*
* @brief Application Messages Handler - Example
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#include "app.h"
#include "drvs.h"
#if (DBG_APP)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* MESSAGE HANDLERS
****************************************************************************************
*/
/// SubTask Declaration, User add more...
extern APP_SUBTASK_HANDLER(gapm_msg);
extern APP_SUBTASK_HANDLER(gapc_msg);
extern APP_SUBTASK_HANDLER(gatt_msg);
extern APP_SUBTASK_HANDLER(l2cc_msg);
extern APP_SUBTASK_HANDLER(mesh_msg);
/**
****************************************************************************************
* @brief SubTask Handler of Custom or Unknow Message. (__weak func)
****************************************************************************************
*/
__weak APP_SUBTASK_HANDLER(custom)
{
#if (RC32K_CALIB_PERIOD)
if (msgid == APP_TIMER_RC32K_CORR)
{
DEBUG("rc32k_calib");
rc32k_calib();
ke_timer_set(APP_TIMER_RC32K_CORR, TASK_APP, RC32K_CALIB_PERIOD);
}
else
#endif //(RC32K_CALIB_PERIOD)
{
uint16_t length = ke_param2msg(param)->param_len;
DEBUG("Unknow MsgId:0x%X", msgid);
debugHex((uint8_t *)param, length);
}
return (MSG_STATUS_FREE);
}
/**
****************************************************************************************
* @brief Dispatch TASK_APP message to sub-handler.
*
* @param[in] msgid Id of the message received.
* @param[in] task_idx Index of the receiving task instance.
*
* @return Handler of the message or NULL.
****************************************************************************************
*/
__TASKFN void* app_task_dispatch(msg_id_t msgid, uint8_t task_idx)
{
msg_func_t handler = NULL;
switch (MSG_TYPE(msgid))
{
case (TID_GAPM):
handler = app_gapm_msg_handler;
break;
case (TID_GAPC):
handler = app_gapc_msg_handler;
break;
#if (GATT_CLI)
case (TID_GATT):
handler = app_gatt_msg_handler;
break;
#endif
#if (L2CC_LECB)
case (TID_L2CC):
handler = app_l2cc_msg_handler;
break;
#endif
#if (PRF_MESH)
case TID_MESH:
handler = app_mesh_msg_handler;
break;
#endif
default:
{
handler = app_custom_handler;
} break;
}
return handler;
}

BIN
ble/lib/ble6.lib Normal file

Binary file not shown.

BIN
ble/lib/ble6_8act_6con.lib Normal file

Binary file not shown.

3945
ble/lib/ble6_fw.hex Normal file

File diff suppressed because it is too large Load Diff

BIN
ble/lib/ble6_fw.lib Normal file

Binary file not shown.

BIN
ble/lib/ble6_lite.lib Normal file

Binary file not shown.

263
ble/prf/prf.h Normal file
View File

@ -0,0 +1,263 @@
/**
****************************************************************************************
*
* @file prf.h
*
* @brief Header file - used to manage and access BLE profiles.
*
****************************************************************************************
*/
#ifndef _PRF_H_
#define _PRF_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "string.h"
#include "blelib.h"
#include "le_err.h"
#include "att.h"
#include "attm_api.h"
#include "gatt_api.h"
/*
* DEFINES
****************************************************************************************
*/
/// Attribute is mandatory
#define ATT_MANDATORY (0xFF)
/// Attribute is optional
#define ATT_OPTIONAL (0x00)
/// Possible values for setting client configuration characteristics
enum prf_cli_conf
{
/// Stop notification/indication
PRF_CLI_STOP_NTFIND = 0x0000,
/// Start notification
PRF_CLI_START_NTF = 0x0001,
/// Start indication
PRF_CLI_START_IND = 0x0002,
};
/// Possible values for setting server configuration characteristics
enum prf_srv_conf
{
/// Stop Broadcast
PRF_SRV_STOP_BCST = 0x0000,
/// Start Broadcast
PRF_SRV_START_BCST = 0x0001,
};
/// Service type
enum prf_svc_type
{
PRF_PRIMARY_SERVICE = 0x00,
PRF_SECONDARY_SERVICE = 0x01
};
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// Characteristic Presentation Format Descriptor Size
#define PRF_PRES_FMT_SIZE (7)
/// Characteristic Presentation information
struct prf_pres_fmt
{
/// Unit (The Unit is a UUID)
uint16_t unit;
/// Description
uint16_t description;
/// Format
uint8_t format;
/// Exponent
uint8_t exponent;
/// Name space
uint8_t name_space;
};
/// Time profile Date and Time Size
#define PRF_DATA_TIME_SIZE (7)
/// Time profile information
struct prf_date_time
{
/// year time element
uint16_t year;
/// month time element
uint8_t month;
/// day time element
uint8_t day;
/// hour time element
uint8_t hour;
/// minute time element
uint8_t min;
/// second time element
uint8_t sec;
};
/**
* SFLOAT: Short Floating Point Type
*
* +----------+----------+---------+
* | Exponent | Mantissa | Total |
* +------+----------+----------+---------+
* | size | 4 bits | 12 bits | 16 bits |
* +------+----------+----------+---------+
*/
typedef uint16_t prf_sfloat;
/// Attribute information
struct prf_att_info
{
/// Attribute Handle
uint16_t handle;
/// Attribute length
uint16_t length;
/// Status of request
uint8_t status;
/// Attribute value
uint8_t value[];
};
/// service handles
struct prf_svc
{
/// start handle
uint16_t shdl;
/// end handle
uint16_t ehdl;
};
/// included service handles
struct prf_incl_svc
{
/// attribute handle
uint16_t handle;
/// included service start handle
uint16_t start_hdl;
/// included service end handle
uint16_t end_hdl;
/// UUID length
uint8_t uuid_len;
/// UUID
uint8_t uuid[ATT_UUID128_LEN];
};
/// characteristic info
struct prf_char_inf
{
/// Characteristic handle
uint16_t char_hdl;
/// Value handle
uint16_t val_hdl;
/// Characteristic properties
uint8_t prop;
/// End of characteristic offset
uint8_t char_ehdl_off;
};
/// characteristic description
struct prf_desc_inf
{
/// Descriptor handle
uint16_t desc_hdl;
};
/// Characteristic definition
struct prf_char_def
{
/// Characteristic UUID
uint16_t uuid;
/// Requirement Attribute Flag
uint8_t req_flag;
/// Mandatory Properties
uint8_t prop_mand;
};
/// Characteristic Descriptor definition
struct prf_desc_def
{
/// Characteristic Descriptor uuid
uint16_t uuid;
/// requirement attribute flag
uint8_t req_flag;
/// Corresponding characteristic code
uint8_t char_code;
};
/// Message structure used to inform APP that a profile client role has been disabled
struct prf_client_disable_ind
{
/// Status
uint8_t status;
};
/// Message structure used to inform APP that an error has occured in the profile server role task
struct prf_server_error_ind
{
/// Message ID
uint16_t msg_id;
/// Status
uint8_t status;
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief SVR Pack Characteristic Presentation Format descriptor value
****************************************************************************************
*/
void prf_pack_pres_fmt(uint8_t *packed_val, const struct prf_pres_fmt* pres_fmt);
/**
****************************************************************************************
* @brief SVR Pack date time value
*
* @param[out] packed_date packed date time
* @param[in] date_time structure date time
*
* @return size of packed value
****************************************************************************************
*/
uint8_t prf_pack_date_time(uint8_t *packed_date, const struct prf_date_time* date_time);
/**
****************************************************************************************
* @brief CLI Unpack Characteristic Presentation Format descriptor value
****************************************************************************************
*/
void prf_unpack_pres_fmt(const uint8_t *packed_val, struct prf_pres_fmt* pres_fmt);
/**
****************************************************************************************
* @brief CLI Unpack date time value
*
* @param[in] packed_date packed date time
* @param[out] date_time structure date time
*
* @return size of packed value
****************************************************************************************
*/
uint8_t prf_unpack_date_time(uint8_t *packed_date, struct prf_date_time* date_time);
#endif /* _PRF_H_ */

213
ble/prf/prf_api.h Normal file
View File

@ -0,0 +1,213 @@
/**
****************************************************************************************
*
* @file prf_api.h
*
* @brief Header file - BLE Profiles' API functions, all inlcuded.
*
****************************************************************************************
*/
#ifndef PRF_API_H_
#define PRF_API_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Profile Enable
#if !defined(PRF_GATT)
#define PRF_GATT (1)
#endif
/// Service Start Handle(0 = dynamically allocated)
#if !defined(GAP_START_HDL)
#define GAP_START_HDL (0)
#endif
#if !defined(GATT_START_HDL)
#define GATT_START_HDL (0)
#endif
#if !defined(MESH_START_HDL)
#define MESH_START_HDL (0)
#endif
#if !defined(MESH_SVC_CFG)
#define MESH_SVC_CFG (0x03) //(MESH_ATT_PROV | MESH_ATT_PROXY)
#endif
/// Attributes present in GAP Service
#if !defined(GAP_ATT_CFG)
#if (PRF_HIDS)
#define GAP_ATT_CFG (0x40) //(GAP_ATT_SLV_PREF_PAR_BIT)
#else
#define GAP_ATT_CFG (0)
#endif //(PRF_HIDS)
#endif
/// GAP Attribute write permission requirement
enum gap_att_write_perm
{
/// Disable write access
GAP_ATT_WRITE_DISABLE = 0,
/// Enable write access - no authentication required
GAP_ATT_WRITE_NO_AUTH = 1,
/// Write access requires unauthenticated link
GAP_ATT_WRITE_UNAUTH = 2,
/// Write access requires authenticated link
GAP_ATT_WRITE_AUTH = 3,
/// Write access requires secure connected link
GAP_ATT_WRITE_SEC_CON = 4
};
/// GAP Attribute Configuration
/// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
/// | RFU |PCP | ICON_PERM | NAME_PERM |
/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
/// - Bit [0-2] : Device Name write permission requirements for peer device (@see gap_att_write_perm)
/// - Bit [3-5] : Device Appearance write permission requirements for peer device (@see gap_att_write_perm)
/// - Bit [6] : Slave Preferred Connection Parameters present
/// - Bit [7-15]: Reserved
enum gap_att_cfg
{
/// Device Name write permission requirements for peer device
GAP_ATT_NAME_PERM_MASK = 0x0007,
GAP_ATT_NAME_PERM_LSB = 0,
/// Device Appearance write permission requirements for peer device
GAP_ATT_ICON_PERM_MASK = 0x0038,
GAP_ATT_ICON_PERM_LSB = 3,
/// Slave Preferred Connection Parameters present in GAP Service.
GAP_ATT_SLV_PREF_PAR_BIT = 0x0040,
GAP_ATT_SLV_PREF_PAR_POS = 6,
};
/// Mesh Attribute Configuration
enum mesh_att_cfg
{
/// Provisioning attribute
MESH_ATT_PROV = (1 << 0),
/// Proxy attribute
MESH_ATT_PROXY = (1 << 1),
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Generic Access Profile(0x1800) in the DB.
*
* @param[in] start_hdl Service start handle
* @param[in] att_cfg Attribute configuration @see gap_att_cfg
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t gap_svc_init(uint16_t start_hdl, uint16_t att_cfg);
/**
****************************************************************************************
* @brief Retrieve Dev Info to Generic Access Profile, User implement for Callback.
*
* @param[in] conidx connection index
* @param[in] req request of info type @see enum gapc_dev_info
* @param[in] maxlen buffer length, DEV_NAME_MAX_LEN or size of gapc_conn_param
* @param[out] info pointer of buffer
*
* @return Length of device information, 0 means an error occurs.
****************************************************************************************
*/
uint16_t gap_svc_get_dev_info(uint8_t conidx, uint8_t req, uint16_t maxlen, uint8_t *info);
/**
****************************************************************************************
* @brief Peer update device name or appearance to Generic Access Profile, default reject.
*
* @param[in] conidx connection index
* @param[in] req GAPC_DEV_NAME or GAPC_DEV_APPEARANCE @see enum gapc_dev_info
* @param[in] len length of info data
* @param[out] info pointer of data
*
* @return status of accept(GAP_ERR_NO_ERROR) or reject(GAP_ERR_REJECTED).
****************************************************************************************
*/
uint8_t gap_svc_set_dev_info(uint8_t conidx, uint8_t req, uint16_t len, const uint8_t *info);
/**
****************************************************************************************
* @brief Add Generic Attribute Profile(0x1801) in the DB.
*
* @param[in] start_hdl Service start handle
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t gatt_svc_init(uint16_t start_hdl);
/**
****************************************************************************************
* @brief Add Mesh Profiles in the DB.
*
* @param[in] start_hdl Service start handle
* @param[in] svc_cfg Service configuration
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t mesh_svc_init(uint16_t start_hdl, uint16_t svc_cfg);
/*
* STANDARD PROFILES
****************************************************************************************
*/
/// Device Information Service Server
#include "prf_diss.h"
/// Battery Service Server
#include "prf_bass.h"
/// HID Over GATT Profile Server
#include "prf_hids.h"
#if (PRF_SCPS)
/// Scan Parameters Profile Server
#include "prf_scps.h"
#endif
/// user add more...
/*
* CUSTOMIZED PROFILES
****************************************************************************************
*/
/// Serial Service Profile
#include "prf_sess.h"
#if (PRF_OTAS)
/// OTA Service Profile
#include "prf_otas.h"
#endif
#if (PRF_PTSS)
/// Profile Testing Service
#include "prf_ptss.h"
#endif
/// user add more...
#endif /* PRF_API_H_ */

481
ble/prf/prf_bass.c Normal file
View File

@ -0,0 +1,481 @@
/**
****************************************************************************************
*
* @file prf_bass.c
*
* @brief Battery Service - Server Role Implementation.
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#if (PRF_BASS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "prf_bass.h"
#if (DBG_BASS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat,len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Value of Battery Level and Power State
#define BAT_LVL_MIN (0)
#define BAT_LVL_MAX (100)
#define BAT_LVL_DFT (88) // 88%
#define PWR_STA_DFT (0xBB)
/// Macro for Client Config value operation
#define BAS_LVL_NTF_GET(conidx) \
((bass_env.lvl_ntfs >> (conidx)) & PRF_CLI_START_NTF)
#define BAS_LVL_NTF_CLR(conidx) \
bass_env.lvl_ntfs &= ~(PRF_CLI_START_NTF << (conidx))
#define BAS_LVL_NTF_SET(conidx, conf) \
bass_env.lvl_ntfs = (bass_env.lvl_ntfs & ~(PRF_CLI_START_NTF << (conidx))) | ((conf) << (conidx))
#if (BAS_PWR_STA)
#define BAS_PWR_NTF_GET(conidx) \
((bass_env.pwr_ntfs >> (conidx)) & PRF_CLI_START_NTF)
#define BAS_PWR_NTF_CLR(conidx) \
bass_env.pwr_ntfs &= ~(PRF_CLI_START_NTF << (conidx))
#define BAS_PWR_NTF_SET(conidx, conf) \
bass_env.pwr_ntfs = (bass_env.pwr_ntfs & ~(PRF_CLI_START_NTF << (conidx))) | ((conf) << (conidx))
#endif
/// Bits of Battery Power State
struct bat_pwr_sta_def
{
uint8_t level : 2; // bit[0:1] (0-Unknown, 1-Not Supported, 2-No, 3-Yes)
uint8_t charging : 2; // bit[2:3] (0-Unknown, 1-Not Chargeable, 2-No, 3-Yes)
uint8_t discharging : 2; // bit[4:5] (0-Unknown, 1-Not Supported, 2-No, 3-Yes)
uint8_t present : 2; // bit[6:7] (0-Unknown, 1-Not Supported, 2-No, 3-Yes)
};
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
/// BAS Server Environment Variable
typedef struct bass_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// Current Battery Level(0~100), unit in '%'
uint8_t bat_lvl;
// Client Config Bits of Battery Level - each 1Bit(NTF only), so max_peer=8.
uint8_t lvl_ntfs;
#if (BAS_PWR_STA)
// Current Power State, @see struct bat_pwr_sta_def
uint8_t pwr_sta;
// Client Config Bits of Power State - each 1Bit(NTF only), so max_peer=8.
uint8_t pwr_ntfs;
#endif
} bass_env_t;
/// Global Variable Declarations
__VAR_ENV bass_env_t bass_env;
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// BAS Attributes Index
enum bas_att_idx
{
// Service Declaration, *MUST* Start at 0
BAS_IDX_SVC,
// Battery Level Char.
BAS_IDX_BAT_LVL_CHAR,
BAS_IDX_BAT_LVL_VAL,
BAS_IDX_BAT_LVL_NTF_CFG,
#if (BAS_PWR_STA)
// Battery Power State Char.
BAS_IDX_PWR_STA_CHAR,
BAS_IDX_PWR_STA_VAL,
BAS_IDX_PWR_STA_NTF_CFG,
#endif //(BAS_PWR_STA)
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
BAS_IDX_NB,
};
/// Attributes Description
const att_decl_t bas_atts[] =
{
// Battery Level Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( BAS_IDX_BAT_LVL_CHAR ),
ATT_ELMT( BAS_IDX_BAT_LVL_VAL, ATT_CHAR_BATTERY_LEVEL, PROP_NTF | PROP_RD, 0),
ATT_ELMT_DESC_CLI_CHAR_CFG( BAS_IDX_BAT_LVL_NTF_CFG ),
#if (BAS_PWR_STA)
// Battery Power State Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( BAS_IDX_PWR_STA_CHAR ),
ATT_ELMT(BAS_IDX_PWR_STA_VAL, ATT_CHAR_BATTERY_POWER_STATE, PROP_NTF | PROP_RD, 0),
ATT_ELMT_DESC_CLI_CHAR_CFG( BAS_IDX_PWR_STA_NTF_CFG ),
#endif
};
/// Service Description
const struct svc_decl bas_svc_db =
{
.uuid = ATT_SVC_BATTERY_SERVICE,
.info = SVC_UUID(16),
.atts = bas_atts,
.nb_att = BAS_IDX_NB - 1,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve attribute handle from index (@see bass_att_idx)
static uint16_t bass_get_att_handle(uint8_t att_idx)
{
ASSERT_ERR(att_idx < BAS_IDX_NB);
return (att_idx + bass_env.start_hdl);
}
/// Retrieve attribute index form handle
static uint8_t bass_get_att_idx(uint16_t handle)
{
ASSERT_ERR((handle >= bass_env.start_hdl) && (handle < bass_env.start_hdl + BAS_IDX_NB));
return (handle - bass_env.start_hdl);
}
/// Handles reception of the atts request from peer device
static void bass_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t att_idx = bass_get_att_idx(handle);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,att:%d)", conidx, opcode, handle, att_idx);
switch (opcode)
{
case ATTS_READ_REQ:
{
if (att_idx == BAS_IDX_BAT_LVL_VAL)
{
DEBUG(" read_cfm(bat_lvl:%d)", bass_env.bat_lvl);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint8_t), &(bass_env.bat_lvl));
break;
}
if (att_idx == BAS_IDX_BAT_LVL_NTF_CFG)
{
// retrieve notification config
uint16_t cli_cfg = BAS_LVL_NTF_GET(conidx);
DEBUG(" read_cfm(lvl_ntf:%d)", cli_cfg);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
break;
}
#if (BAS_PWR_STA)
if (att_idx == BAS_IDX_PWR_STA_VAL)
{
DEBUG(" read_cfm(pwr_sta:%d)", bass_env.pwr_sta);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint8_t), &(bass_env.pwr_sta));
break;
}
if (att_idx == BAS_IDX_PWR_STA_NTF_CFG)
{
// retrieve notification config
uint16_t cli_cfg = BAS_PWR_NTF_GET(conidx);
DEBUG(" read_cfm(pwr_ntf:%d)", cli_cfg);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
break;
}
#endif //(BAS_PWR_STA)
// Send error response
gatt_read_cfm(conidx, PRF_ERR_APP_ERROR, handle, 0, NULL);
} break;
case ATTS_WRITE_REQ:
{
const struct atts_write_ind *ind = param;
DEBUG(" write_req(hdl:0x%x,att:%d,wr:0x%x,len:%d)", handle, att_idx, ind->wrcode, ind->length);
#if (BAS_PWR_STA)
if ((att_idx == BAS_IDX_BAT_LVL_NTF_CFG) || (att_idx == BAS_IDX_PWR_STA_NTF_CFG))
#else
if (att_idx == BAS_IDX_BAT_LVL_NTF_CFG)
#endif //(BAS_PWR_STA)
{
if ((!ind->more) && (ind->length == sizeof(uint16_t)))
{
uint16_t cli_cfg = read16p(ind->value);
// update configuration if value for stop or NTF start
if (cli_cfg <= PRF_CLI_START_NTF)
{
// Send write confirm quickly!
gatt_write_cfm(conidx, LE_SUCCESS, handle);
#if (BAS_PWR_STA)
if (att_idx == BAS_IDX_PWR_STA_NTF_CFG)
{
DEBUG(" set pwr_ntf(cid:%d,cfg:%d)", conidx, cli_cfg);
BAS_PWR_NTF_SET(conidx, cli_cfg);
// Send Battery Power State Notify
if (cli_cfg == PRF_CLI_START_NTF)
{
gatt_ntf_send(conidx, bass_get_att_handle(BAS_IDX_PWR_STA_VAL), sizeof(uint8_t), &bass_env.pwr_sta);
}
}
else
#endif //(BAS_PWR_STA)
{
DEBUG(" set lvl_ntf(cid:%d,cfg:%d)", conidx, cli_cfg);
BAS_LVL_NTF_SET(conidx, cli_cfg);
// Send Battery Level Notify
if (cli_cfg == PRF_CLI_START_NTF)
{
gatt_ntf_send(conidx, bass_get_att_handle(BAS_IDX_BAT_LVL_VAL), sizeof(uint8_t), &bass_env.bat_lvl);
}
}
break;
}
}
}
// Send write confirm with error!
gatt_write_cfm(conidx, PRF_ERR_APP_ERROR, handle);
} break;
case ATTS_INFO_REQ:
{
uint16_t length = ATT_MAX_LEN_GET(att_idx, bas_atts);
// Send length-info confirm for prepWR judging.
DEBUG(" info_cfm(hdl:0x%x,att:%d,len:%d)", handle, att_idx, length);
gatt_info_cfm(conidx, LE_SUCCESS, handle, length);
} break;
case ATTS_CMP_EVT:
{
const struct atts_cmp_evt *evt = param;
DEBUG(" cmp_evt(op:0x%x,sta:0x%x)", evt->operation, evt->status);
// add 'if' to avoid warning #117-D: "evt" never referenced
if (evt->operation == GATT_NOTIFY)
{
// Update operation result
}
} break;
default:
{
// nothing to do
} break;
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Battery Service Profile in the DB.
* Customize via pre-define @see BAS_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t bass_svc_init(void)
{
uint8_t status = LE_SUCCESS;
// Init Environment
bass_env.start_hdl = BAS_START_HDL;
bass_env.bat_lvl = BAT_LVL_DFT;
bass_env.lvl_ntfs = PRF_CLI_START_NTF;
#if (BAS_PWR_STA)
bass_env.pwr_sta = PWR_STA_DFT;
bass_env.pwr_ntfs = PRF_CLI_START_NTF;
#endif //(BAS_PWR_STA)
// Create Service in database
status = attmdb_svc_create(&bass_env.start_hdl, NULL, &bas_svc_db, bass_svc_func);
DEBUG("svc_init(sta:0x%X,shdl:%d)", status, bass_env.start_hdl);
return status;
}
/**
****************************************************************************************
* @brief Transmit Battery Level to peer device via NTF
*
* @param[in] conidx peer device connection index
* @param[in] bat_lvl Battery Level
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
static uint8_t bass_bat_lvl_send(uint8_t conidx, uint8_t bat_lvl)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
if ((bat_lvl <= BAT_LVL_MAX)
&& (BAS_LVL_NTF_GET(conidx) == PRF_CLI_START_NTF))
{
status = LE_SUCCESS;
gatt_ntf_send(conidx, bass_get_att_handle(BAS_IDX_BAT_LVL_VAL), sizeof(uint8_t), &bat_lvl);
}
return status;
}
/**
****************************************************************************************
* @brief Update Battery Level value
*
* @param[in] bat_lvl Battery Level
****************************************************************************************
*/
void bass_bat_lvl_update(uint8_t bat_lvl)
{
if (bass_env.bat_lvl != bat_lvl)
{
bass_env.bat_lvl = bat_lvl;
// todo update operation, loop on all connection
for (uint8_t idx = 0; idx < BLE_CONNECTION_MAX; idx++)
{
bass_bat_lvl_send(idx, bass_env.bat_lvl);
}
}
}
/**
****************************************************************************************
* @brief Enable Battery level Notification Configurations
*
* @param[in] conidx Connection index
* @param[in] ntf_cfg Notification Config @see prf_cli_conf
****************************************************************************************
*/
void bass_set_lvl_ntf(uint8_t conidx, uint8_t ntf_cfg)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
ntf_cfg &= PRF_CLI_START_NTF; // NTF only(0x0001)
// update configuration
BAS_LVL_NTF_SET(conidx, ntf_cfg);
}
}
#if (BAS_PWR_STA)
/**
****************************************************************************************
* @brief Transmit Battery Power State to peer device via NTF
*
* @param[in] conidx peer device connection index
* @param[in] pwr_sta Power State
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
static uint8_t bass_pwr_sta_send(uint8_t conidx, uint8_t pwr_sta)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
if (BAS_PWR_NTF_GET(conidx) == PRF_CLI_START_NTF)
{
status = LE_SUCCESS;
gatt_ntf_send(conidx, bass_get_att_handle(BAS_IDX_PWR_STA_VAL), sizeof(uint8_t), &pwr_sta);
}
return status;
}
/**
****************************************************************************************
* @brief Update Battery Power State value
*
* @param[in] pwr_sta Power State
****************************************************************************************
*/
void bass_pwr_sta_update(uint8_t pwr_sta)
{
if (bass_env.pwr_sta != pwr_sta)
{
bass_env.pwr_sta = pwr_sta;
// todo update operation, loop on all connection
for (uint8_t idx = 0; idx < BLE_CONNECTION_MAX; idx++)
{
bass_pwr_sta_send(idx, bass_env.pwr_sta);
}
}
}
/**
****************************************************************************************
* @brief Enable Battery Power State Notification Configurations
*
* @param[in] conidx Connection index
* @param[in] ntf_cfg Notification Config @see prf_cli_conf
****************************************************************************************
*/
void bass_set_pwr_ntf(uint8_t conidx, uint8_t ntf_cfg)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
ntf_cfg &= PRF_CLI_START_NTF; // NTF only(0x0001)
// update configuration
BAS_PWR_NTF_SET(conidx, ntf_cfg);
}
}
#endif //(BAS_PWR_STA)
#endif //(PRF_BASS)

92
ble/prf/prf_bass.h Normal file
View File

@ -0,0 +1,92 @@
/**
****************************************************************************************
*
* @file prf_bass.h
*
* @brief Header file - Battery Service Server Role
*
****************************************************************************************
*/
#ifndef PRF_BASS_H_
#define PRF_BASS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Server Start Handle(0 = dynamically allocated)
#if !defined(BAS_START_HDL)
#define BAS_START_HDL (0)
#endif
/// Support Battery Power State Characteristic
#if !defined(BAS_PWR_STA)
#define BAS_PWR_STA (1)
#endif
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Battery Service Profile in the DB.
* Customize via pre-define @see BAS_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t bass_svc_init(void);
/**
****************************************************************************************
* @brief Update Battery Level value
*
* @param[in] bat_lvl Battery Level
****************************************************************************************
*/
void bass_bat_lvl_update(uint8_t bat_lvl);
/**
****************************************************************************************
* @brief Enable Battery Level Notification Configurations
*
* @param[in] conidx Connection index
* @param[in] ntf_cfg Notification Config @see prf_cli_conf
****************************************************************************************
*/
void bass_set_lvl_ntf(uint8_t conidx, uint8_t ntf_cfg);
#if (BAS_PWR_STA)
/**
****************************************************************************************
* @brief Update Battery Power State value
*
* @param[in] pwr_sta Power State
****************************************************************************************
*/
void bass_pwr_sta_update(uint8_t pwr_sta);
/**
****************************************************************************************
* @brief Enable Battery Power State Notification Configurations
*
* @param[in] conidx Connection index
* @param[in] ntf_cfg Notification Config @see prf_cli_conf
****************************************************************************************
*/
void bass_set_pwr_ntf(uint8_t conidx, uint8_t ntf_cfg);
#else
#define bass_pwr_sta_update(pwr_sta)
#define bass_set_pwr_ntf(conidx, ntf_cfg)
#endif
#endif /* PRF_BASS_H_ */

412
ble/prf/prf_diss.c Normal file
View File

@ -0,0 +1,412 @@
/**
****************************************************************************************
*
* @file prf_diss.c
*
* @brief Device Information Service(DIS) - Server Role Implementation.
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#if (PRF_DISS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "prf_diss.h"
#if (DBG_DISS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Manufacturer Name Value
#define INFO_MANUF_NAME ("BLE5x")
#define INFO_MANUF_NAME_LEN (sizeof(INFO_MANUF_NAME)-1)
/// Model Number String Value
#define INFO_MODEL_NB_STR ("BLE5.2")
#define INFO_MODEL_NB_STR_LEN (sizeof(INFO_MODEL_NB_STR)-1)
/// Serial Number
#define INFO_SERIAL_NB_STR ("11.0.2-LE")
#define INFO_SERIAL_NB_STR_LEN (sizeof(INFO_SERIAL_NB_STR)-1)
/// Firmware Revision
#define INFO_FW_REV_STR ("11.0.2")
#define INFO_FW_REV_STR_LEN (sizeof(INFO_FW_REV_STR)-1)
/// System ID Value - LSB -> MSB, Length=8(DIS_SYS_ID_LEN)
#define INFO_SYS_ID ("\x12\x34\x56\xFF\xFE\x9A\xBC\xDE")
#define INFO_SYS_ID_LEN (sizeof(INFO_SYS_ID)-1)
/// Hardware Revision String
#define INFO_HW_REV_STR ("1.0.0")
#define INFO_HW_REV_STR_LEN (sizeof(INFO_HW_REV_STR)-1)
/// Software Revision String
#define INFO_SW_REV_STR ("1.0.0")
#define INFO_SW_REV_STR_LEN (sizeof(INFO_SW_REV_STR)-1)
/// IEEE Certif, Length>=6(DIS_IEEE_CERTIF_MIN_LEN)
#define INFO_IEEE ("\xFF\xEE\xDD\xCC\xBB\xAA")
#define INFO_IEEE_LEN (sizeof(INFO_IEEE)-1)
/**
* PNP ID Value - LSB -> MSB, Length=7(DIS_PNP_ID_LEN)
* Vendor ID Source : 0x02 (USB Implementer¡¯s Forum assigned Vendor ID value)
* Vendor ID : 0x045E (Microsoft Corp)
* Product ID : 0x0040
* Product Version : 0x0300
*/
#define INFO_PNP_ID ("\x02\x5E\x04\x40\x00\x00\x03")
#define INFO_PNP_ID_LEN (sizeof(INFO_PNP_ID)-1)
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
/// DIS Server Environment Variable
typedef struct diss_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// Supported features @see enum dis_features
uint16_t features;
} diss_env_t;
/// Global Variable Declarations
__VAR_ENV diss_env_t diss_env;
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// DIS Attributes Index, keep up with @see enum dis_values
enum dis_att_idx
{
// Service Declaration, *MUST* Start at 0
DIS_IDX_SVC,
// Manufacturer Name String Char.
DIS_IDX_MANUF_NAME_CHAR,
DIS_IDX_MANUF_NAME_VAL,
// Model Number String Char.
DIS_IDX_MODEL_NB_STR_CHAR,
DIS_IDX_MODEL_NB_STR_VAL,
// Serial Number String Char.
DIS_IDX_SERIAL_NB_STR_CHAR,
DIS_IDX_SERIAL_NB_STR_VAL,
// Hardware Revision String Char.
DIS_IDX_HW_REV_STR_CHAR,
DIS_IDX_HW_REV_STR_VAL,
// Firmware Revision String Char.
DIS_IDX_FW_REV_STR_CHAR,
DIS_IDX_FW_REV_STR_VAL,
// Software Revision String Char.
DIS_IDX_SW_REV_STR_CHAR,
DIS_IDX_SW_REV_STR_VAL,
// System Identifier Char.
DIS_IDX_SYS_ID_CHAR,
DIS_IDX_SYS_ID_VAL,
// IEEE Certificate Char.
DIS_IDX_IEEE_CHAR,
DIS_IDX_IEEE_VAL,
// PnP ID Char.
DIS_IDX_PNP_ID_CHAR,
DIS_IDX_PNP_ID_VAL,
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
DIS_IDX_NB,
};
/// Attributes Description
const att_decl_t dis_atts[] =
{
// Manufacturer Name Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_MANUF_NAME_CHAR ),
ATT_ELMT( DIS_IDX_MANUF_NAME_VAL, ATT_CHAR_MANUF_NAME, PROP_RD, DIS_VAL_MAX_LEN ),
// Model Number String Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_MODEL_NB_STR_CHAR ),
ATT_ELMT( DIS_IDX_MODEL_NB_STR_VAL, ATT_CHAR_MODEL_NB, PROP_RD, DIS_VAL_MAX_LEN ),
// Serial Number String Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_SERIAL_NB_STR_CHAR ),
ATT_ELMT( DIS_IDX_SERIAL_NB_STR_VAL, ATT_CHAR_SERIAL_NB, PROP_RD, DIS_VAL_MAX_LEN ),
// Hardware Revision String Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_HW_REV_STR_CHAR ),
ATT_ELMT( DIS_IDX_HW_REV_STR_VAL, ATT_CHAR_HW_REV, PROP_RD, DIS_VAL_MAX_LEN ),
// Firmware Revision String Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_FW_REV_STR_CHAR ),
ATT_ELMT( DIS_IDX_FW_REV_STR_VAL, ATT_CHAR_FW_REV, PROP_RD, DIS_VAL_MAX_LEN ),
// Software Revision String Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_SW_REV_STR_CHAR ),
ATT_ELMT( DIS_IDX_SW_REV_STR_VAL, ATT_CHAR_SW_REV, PROP_RD, DIS_VAL_MAX_LEN ),
// System ID Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_SYS_ID_CHAR ),
ATT_ELMT( DIS_IDX_SYS_ID_VAL, ATT_CHAR_SYS_ID, PROP_RD, DIS_SYS_ID_LEN ),
// IEEE 11073-20601 Regulatory Certification Data List Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_IEEE_CHAR ),
ATT_ELMT( DIS_IDX_IEEE_VAL, ATT_CHAR_IEEE_CERTIF, PROP_RD, DIS_SYS_ID_LEN ),
// PnP ID Char. Declaration and Value
ATT_ELMT_DECL_CHAR( DIS_IDX_PNP_ID_CHAR ),
ATT_ELMT( DIS_IDX_PNP_ID_VAL, ATT_CHAR_PNP_ID, PROP_RD, DIS_PNP_ID_LEN ),
};
/// Service Description
const struct svc_decl dis_svc_db =
{
{.uuid = ATT_SVC_DEVICE_INFO},
.info = SVC_UUID(16),
.atts = dis_atts,
.nb_att = DIS_IDX_NB - 1,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve value index from attribute handle
static uint8_t diss_get_val_idx(uint16_t handle)
{
// handle start from first characteristic value handle
uint16_t cur_hdl = diss_env.start_hdl + 2;
for (uint8_t idx = 0; idx < DIS_CHAR_MAX; idx++)
{
if (((diss_env.features >> idx) & 1) == 1)
{
// check if value handle correspond to requested handle
if (cur_hdl == handle)
{
return idx;
}
cur_hdl += 2;
}
}
return DIS_CHAR_MAX;
}
/// Handles reception of the read request from peer device
static void diss_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t val_idx = diss_get_val_idx(handle);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,att:%d)", conidx, opcode, handle, val_idx);
if (opcode == ATTS_READ_REQ)
{
// Check Characteristic Code
if (val_idx < DIS_CHAR_MAX)
{
uint16_t length;
const uint8_t *value = diss_value_get(val_idx, &length);
if (value != NULL)
{
// Send value to peer device.
gatt_read_cfm(conidx, LE_SUCCESS, handle, length, value);
return;
}
}
// application error, value cannot be retrieved
gatt_read_cfm(conidx, PRF_ERR_APP_ERROR, handle, 0, NULL);
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Device Information Profile in the DB.
* Customize via pre-define @see DIS_START_HDL @see DIS_FEATURES
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t diss_svc_init(void)
{
uint8_t status = LE_SUCCESS;
uint32_t cfg_att = 0;
// Init Environment
diss_env.start_hdl = DIS_START_HDL;
diss_env.features = DIS_FEATURES;
// Compute Attributes supported
for (uint8_t i = 0; i < DIS_CHAR_MAX; i++)
{
if (((diss_env.features >> i) & 1) == 1)
{
cfg_att |= (3 << (i*2 + 1)); // 3:CHAR + VAL
}
}
// Create Service in database
status = attmdb_svc_create(&diss_env.start_hdl, (uint8_t *)&cfg_att, &dis_svc_db, diss_svc_func);
DEBUG("svc_init(sta:0x%X,shdl:%d,feat:0x%X,cfg:0x%X)",
status, diss_env.start_hdl, diss_env.features, cfg_att);
return status;
}
/**
****************************************************************************************
* @brief Get value for attribute read (__weak func)
*
* @param[in] val_idx Index of Value to set @see enum dis_values
* @param[out] p_len Value Length
*
* @return Value data pointer
****************************************************************************************
*/
__weak const uint8_t *diss_value_get(uint8_t val_idx, uint16_t *p_len)
{
uint16_t length = 0;
const uint8_t *p_data = NULL;
// Retrieve value information
switch (val_idx)
{
#if DIS_FEAT_SUP(MANUF_NAME)
case DIS_MANUF_NAME_CHAR:
{
length = INFO_MANUF_NAME_LEN;
p_data = (const uint8_t *)INFO_MANUF_NAME;
} break;
#endif
#if DIS_FEAT_SUP(MODEL_NB_STR)
case DIS_MODEL_NB_STR_CHAR:
{
length = INFO_MODEL_NB_STR_LEN;
p_data = (const uint8_t *)INFO_MODEL_NB_STR;
} break;
#endif
#if DIS_FEAT_SUP(SERIAL_NB_STR)
case DIS_SERIAL_NB_STR_CHAR:
{
length = INFO_SERIAL_NB_STR_LEN;
p_data = (const uint8_t *)INFO_SERIAL_NB_STR;
} break;
#endif
#if DIS_FEAT_SUP(HW_REV_STR)
case DIS_HW_REV_STR_CHAR:
{
length = INFO_HW_REV_STR_LEN;
p_data = (const uint8_t *)INFO_HW_REV_STR;
} break;
#endif
#if DIS_FEAT_SUP(FW_REV_STR)
case DIS_FW_REV_STR_CHAR:
{
length = INFO_FW_REV_STR_LEN;
p_data = (const uint8_t *)INFO_FW_REV_STR;
} break;
#endif
#if DIS_FEAT_SUP(SW_REV_STR)
case DIS_SW_REV_STR_CHAR:
{
length = INFO_SW_REV_STR_LEN;
p_data = (const uint8_t *)INFO_SW_REV_STR;
} break;
#endif
#if DIS_FEAT_SUP(SYS_ID)
case DIS_SYS_ID_CHAR:
{
// Check if length matches particular requirements
if (INFO_SYS_ID_LEN == DIS_SYS_ID_LEN)
{
length = INFO_SYS_ID_LEN;
p_data = (const uint8_t *)INFO_SYS_ID;
}
} break;
#endif
#if DIS_FEAT_SUP(IEEE)
case DIS_IEEE_CHAR:
{
// Check if length matches particular requirements
if (INFO_IEEE_LEN >= DIS_IEEE_CERTIF_MIN_LEN)
{
length = INFO_IEEE_LEN;
p_data = (const uint8_t *)INFO_IEEE;
}
} break;
#endif
#if DIS_FEAT_SUP(PNP_ID)
case DIS_PNP_ID_CHAR:
{
// Check if length matches particular requirements
if (INFO_PNP_ID_LEN == DIS_PNP_ID_LEN)
{
length = INFO_PNP_ID_LEN;
p_data = (const uint8_t *)INFO_PNP_ID;
}
} break;
#endif
default:
break;
}
// Check value length not exceed MAX_LEN
if (length > DIS_VAL_MAX_LEN)
{
length = DIS_VAL_MAX_LEN;
}
DEBUG("value_get(req:%d,len:%d)", val_idx, length);
*p_len = length;
return p_data;
}
#endif //(PRF_DISS)

121
ble/prf/prf_diss.h Normal file
View File

@ -0,0 +1,121 @@
/**
****************************************************************************************
*
* @file prf_diss.h
*
* @brief Header file - Device Information Service Server.
*
****************************************************************************************
*/
#ifndef PRF_DISS_H_
#define PRF_DISS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Service Start Handle(0 = dynamically allocated)
#if !defined(DIS_START_HDL)
#define DIS_START_HDL (0)
#endif
/// Information Characteristic Support
#if !defined(DIS_FEATURES)
#define DIS_FEATURES ( DIS_FEAT_MANUF_NAME_BIT |\
DIS_FEAT_SERIAL_NB_STR_BIT |\
DIS_FEAT_HW_REV_STR_BIT |\
DIS_FEAT_FW_REV_STR_BIT |\
DIS_FEAT_PNP_ID_BIT )
#endif
/// Maximal length for Char. values(20 bytes default)
#if !defined(DIS_VAL_MAX_LEN)
#define DIS_VAL_MAX_LEN (20)
#endif
/// System ID string length
#define DIS_SYS_ID_LEN (0x08)
/// IEEE Certif length (min 6 bytes)
#define DIS_IEEE_CERTIF_MIN_LEN (0x06)
/// PnP ID length
#define DIS_PNP_ID_LEN (0x07)
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// Supported Feature Flags, Bits of Index @see enum dis_values
#define DIS_FEAT_MANUF_NAME_BIT (0x0001) //(1 << DIS_MANUF_NAME_CHAR)
#define DIS_FEAT_MODEL_NB_STR_BIT (0x0002) //(1 << DIS_MODEL_NB_STR_CHAR)
#define DIS_FEAT_SERIAL_NB_STR_BIT (0x0004) //(1 << DIS_SERIAL_NB_STR_CHAR)
#define DIS_FEAT_HW_REV_STR_BIT (0x0008) //(1 << DIS_HW_REV_STR_CHAR)
#define DIS_FEAT_FW_REV_STR_BIT (0x0010) //(1 << DIS_FW_REV_STR_CHAR)
#define DIS_FEAT_SW_REV_STR_BIT (0x0020) //(1 << DIS_SW_REV_STR_CHAR)
#define DIS_FEAT_SYS_ID_BIT (0x0040) //(1 << DIS_SYS_ID_CHAR)
#define DIS_FEAT_IEEE_BIT (0x0080) //(1 << DIS_IEEE_CHAR)
#define DIS_FEAT_PNP_ID_BIT (0x0100) //(1 << DIS_PNP_ID_CHAR)
#define DIS_FEAT_ALL_SUP (0x01FF) // All features are supported
#define DIS_FEAT_SUP(val) (DIS_FEATURES & DIS_FEAT_##val##_BIT)
/// Device Value Indexes
enum dis_values
{
/// Manufacturer Name String
DIS_MANUF_NAME_CHAR,
/// Model Number String
DIS_MODEL_NB_STR_CHAR,
/// Serial Number String
DIS_SERIAL_NB_STR_CHAR,
/// Hardware Revision String
DIS_HW_REV_STR_CHAR,
/// Firmware Revision String
DIS_FW_REV_STR_CHAR,
/// Software Revision String
DIS_SW_REV_STR_CHAR,
/// System Identifier
DIS_SYS_ID_CHAR,
/// IEEE Certificate
DIS_IEEE_CHAR,
/// Plug and Play Identifier
DIS_PNP_ID_CHAR,
DIS_CHAR_MAX,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Device Information Profile in the DB.
* Customize via pre-define @see DIS_START_HDL @see DIS_FEATURES
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t diss_svc_init(void);
/**
****************************************************************************************
* @brief Get value for attribute read (__weak func)
*
* @param[in] val_idx Index of Value to set @see enum dis_values
* @param[out] p_len Value Length
*
* @return Value data pointer
****************************************************************************************
*/
const uint8_t *diss_value_get(uint8_t val_idx, uint16_t *p_len);
#endif /* PRF_DISS_H_ */

927
ble/prf/prf_hids.c Normal file
View File

@ -0,0 +1,927 @@
/**
****************************************************************************************
*
* @file prf_hids.c
*
* @brief HID Service Profile - Template Source.
*
* < Implementation according to user's application-specific >
****************************************************************************************
*/
#if (PRF_HIDS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "hid_desc.h" // application-specific, #include "prf_hids.h"
#if (DBG_HIDS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat,len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Support Boot Protocol Mode or Not
#if !defined(HID_BOOT_SUP)
#define HID_BOOT_SUP (0)
#define HID_BOOT_KB (0)
#define HID_BOOT_MOUSE (0)
#endif
/// Support Report Protocol Mode or Not
#if !defined(HID_REPORT_SUP)
#define HID_REPORT_SUP (1)
#define HID_RPT_KB (1)
#define HID_RPT_MEDIA (1)
#define HID_RPT_SYSTEM (1)
#define HID_RPT_MOUSE (1)
#define HID_RPT_PTP (0)
#endif
/// Support Number of HID Connections
#if !defined(HID_CONN_MAX)
#define HID_CONN_MAX (1) // always one, BLE_CONNECTION_MAX
#endif
/// Macro for Client Config value operation
#define HID_RPT_NTF_GET(conidx, ntf_idx) \
((hids_env.conn[conidx].rpt_ntfs >> (ntf_idx)) & PRF_CLI_START_NTF)
#define HID_RPT_NTF_CLR(conidx, ntf_idx) \
hids_env.conn[conidx].rpt_ntfs &= ~(PRF_CLI_START_NTF << (ntf_idx))
#define HID_RPT_NTF_SET(conidx, ntf_idx, conf) \
hids_env.conn[conidx].rpt_ntfs = (hids_env.conn[conidx].rpt_ntfs & ~(PRF_CLI_START_NTF << (ntf_idx))) | ((conf) << (ntf_idx))
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
typedef struct hid_conn_tag
{
// Client Config of peer devices, max_bits=RPT_IDX_NB
uint8_t rpt_ntfs;
// keyboard Locks (bit0:num lock, bit1:caps lock, bit2:scroll lock)
uint8_t led_lock;
// Control Point key @see enum hid_ctrl_pt
uint8_t ctrl_pt;
// Boot or Report mode, @see enum hid_proto_mode
uint8_t proto_mode;
} hid_conn_t;
/// HIDS Server Environment Sariable
typedef struct hids_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// Number of notify pkt
uint8_t nb_pkt;
// Connection Info
hid_conn_t conn[HID_CONN_MAX];
} hids_env_t;
/// Global Variable Declarations
__VAR_ENV hids_env_t hids_env;
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// HID Attributes Index
enum hid_att_idx
{
// Service Declaration, *MUST* Start at 0
HID_IDX_SVC,
// HID Information
HID_IDX_HID_INFO_CHAR,
HID_IDX_HID_INFO_VAL,
// HID Control Point
HID_IDX_HID_CTRL_PT_CHAR,
HID_IDX_HID_CTRL_PT_VAL,
// Report Map
HID_IDX_REPORT_MAP_CHAR, //5
HID_IDX_REPORT_MAP_VAL,
#if (HID_BOOT_SUP)
// Protocol Mode(0-BOOT, 1-REPORT)
HID_IDX_PROTO_MODE_CHAR,
HID_IDX_PROTO_MODE_VAL,
#if (HID_BOOT_KB)
// Boot Keyboard Input Report
HID_IDX_BOOT_KB_IN_RPT_CHAR,
HID_IDX_BOOT_KB_IN_RPT_VAL, //10
HID_IDX_BOOT_KB_IN_RPT_NTF_CFG,
// Boot Keyboard Output Report
HID_IDX_BOOT_KB_OUT_RPT_CHAR,
HID_IDX_BOOT_KB_OUT_RPT_VAL,
#endif //(HID_BOOT_KB)
#if (HID_BOOT_MOUSE)
// Boot Mouse Input Report
HID_IDX_BOOT_MOUSE_IN_RPT_CHAR,
HID_IDX_BOOT_MOUSE_IN_RPT_VAL, //15
HID_IDX_BOOT_MOUSE_IN_RPT_NTF_CFG,
#endif //(HID_BOOT_MOUSE)
#endif //(HID_BOOT_SUP)
#if (HID_REPORT_SUP)
#if (HID_RPT_KB)
// Keyboard Report IN
HID_IDX_KB_IN_RPT_CHAR,
HID_IDX_KB_IN_RPT_VAL,
HID_IDX_KB_IN_RPT_REF,
HID_IDX_KB_IN_RPT_NTF_CFG, //20
// Keyboard Report OUT
HID_IDX_KB_OUT_RPT_CHAR,
HID_IDX_KB_OUT_RPT_VAL,
HID_IDX_KB_OUT_RPT_REF,
#endif //(HID_RPT_KB)
#if (HID_RPT_MEDIA)
// Media IN Report
HID_IDX_MEDIA_IN_RPT_CHAR,
HID_IDX_MEDIA_IN_RPT_VAL, //25
HID_IDX_MEDIA_IN_RPT_REF,
HID_IDX_MEDIA_IN_RPT_NTF_CFG,
#endif //(HID_RPT_MEDIA)
#if (HID_RPT_SYSTEM)
// System IN Report
HID_IDX_SYS_IN_RPT_CHAR,
HID_IDX_SYS_IN_RPT_VAL,
HID_IDX_SYS_IN_RPT_REF, //30
HID_IDX_SYS_IN_RPT_NTF_CFG,
#endif //(HID_RPT_SYSTEM)
#if (HID_RPT_MOUSE)
// Mouse IN Report
HID_IDX_MOUSE_IN_RPT_CHAR,
HID_IDX_MOUSE_IN_RPT_VAL,
HID_IDX_MOUSE_IN_RPT_REF,
HID_IDX_MOUSE_IN_RPT_NTF_CFG, //35
#endif //(HID_RPT_MOUSE)
#if (HID_RPT_PTP)
// TouchPad IN Report
HID_IDX_TP_IN_RPT_CHAR,
HID_IDX_TP_IN_RPT_VAL,
HID_IDX_TP_IN_RPT_REF,
HID_IDX_TP_IN_RPT_NTF_CFG,
// MaxCnt FEAT Report
HID_IDX_MAXCNT_FEAT_RPT_CHAR, //40
HID_IDX_MAXCNT_FEAT_RPT_VAL,
HID_IDX_MAXCNT_FEAT_RPT_REF,
// PTPHQA FEAT Report
HID_IDX_PTPHQA_FEAT_RPT_CHAR,
HID_IDX_PTPHQA_FEAT_RPT_VAL,
HID_IDX_PTPHQA_FEAT_RPT_REF, //45
#endif //(HID_RPT_PTP)
#endif //(HID_REPORT_SUP)
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
HID_IDX_NB,
};
/// Attributes Description
const att_decl_t hid_atts[] =
{
// HID Information Char. Declaration and Value
ATT_ELMT_DECL_CHAR( HID_IDX_HID_INFO_CHAR ),
ATT_ELMT( HID_IDX_HID_INFO_VAL, ATT_CHAR_HID_INFO, PROP_RD, HID_INFO_SIZE ),
// HID Control Point Char. Declaration
ATT_ELMT_DECL_CHAR( HID_IDX_HID_CTRL_PT_CHAR ),
ATT_ELMT( HID_IDX_HID_CTRL_PT_VAL, ATT_CHAR_HID_CTRL_PT, PROP_WC, HID_CTRL_PT_SIZE ),
// Report Map Char. Declaration and Value
ATT_ELMT_DECL_CHAR( HID_IDX_REPORT_MAP_CHAR ),
ATT_ELMT( HID_IDX_REPORT_MAP_VAL, ATT_CHAR_REPORT_MAP, PROP_RD, 0 ),
#if (HID_BOOT_SUP)
// Protocol Mode Char. Declaration and Value
ATT_ELMT_DECL_CHAR( HID_IDX_PROTO_MODE_CHAR ),
ATT_ELMT( HID_IDX_PROTO_MODE_VAL, ATT_CHAR_PROTOCOL_MODE, PROP_RD | PROP_WC, HID_PROTO_MODE_SIZE ),
#if (HID_BOOT_KB)
// Boot Keyboard Input Report Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_BOOT_KB_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_BOOT_KB_IN_RPT_VAL, ATT_CHAR_BOOT_KB_IN_REPORT, PROP_RD | PROP_NTF, HID_BOOT_REPORT_MAX_LEN ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_BOOT_KB_IN_RPT_NTF_CFG ),
// Boot Keyboard Output Report Char. Declaration and Value
ATT_ELMT_DECL_CHAR( HID_IDX_BOOT_KB_OUT_RPT_CHAR ),
ATT_ELMT( HID_IDX_BOOT_KB_OUT_RPT_VAL, ATT_CHAR_BOOT_KB_OUT_REPORT, PROP_RD | PROP_WR | PROP_WC, HID_BOOT_REPORT_MAX_LEN ),
#endif //(HID_BOOT_KB)
#if (HID_BOOT_MOUSE)
// Boot Mouse Input Report Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_BOOT_MOUSE_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_BOOT_MOUSE_IN_RPT_VAL, ATT_CHAR_BOOT_MOUSE_IN_REPORT, PROP_RD | PROP_NTF, HID_BOOT_REPORT_MAX_LEN ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_BOOT_MOUSE_IN_RPT_NTF_CFG ),
#endif //(HID_BOOT_MOUSE)
#endif //(HID_BOOT_SUP)
#if (HID_REPORT_SUP)
#if (HID_RPT_KB)
// Keyboard IN Report Char. Declaration and Value, Report Ref. and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_KB_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_KB_IN_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_NTF, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_KB_IN_RPT_REF ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_KB_IN_RPT_NTF_CFG ),
// Keyboard OUT Report Char. Declaration and Value, Report Ref. Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_KB_OUT_RPT_CHAR ),
// Report Characteristic Value
ATT_ELMT( HID_IDX_KB_OUT_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_WR | PROP_WC, HID_REPORT_MAX_LEN ),
// Report Characteristic - Report Reference Descriptor
ATT_ELMT_DESC_REPORT_REF( HID_IDX_KB_OUT_RPT_REF ),
#endif //(HID_RPT_KB)
#if (HID_RPT_MEDIA)
// Media IN Report Char. Declaration and Value, Report Ref. and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_MEDIA_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_MEDIA_IN_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_NTF, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_MEDIA_IN_RPT_REF ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_MEDIA_IN_RPT_NTF_CFG ),
#endif //(HID_RPT_MEDIA)
#if (HID_RPT_SYSTEM)
// System IN Report Char. Declaration and Value, Report Ref. and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_SYS_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_SYS_IN_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_NTF, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_SYS_IN_RPT_REF ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_SYS_IN_RPT_NTF_CFG ),
#endif //(HID_RPT_SYSTEM)
#if (HID_RPT_MOUSE)
// Mouse IN Report Char. Declaration and Value, Report Ref. and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_MOUSE_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_MOUSE_IN_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_NTF, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_MOUSE_IN_RPT_REF ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_MOUSE_IN_RPT_NTF_CFG ),
#endif //(HID_RPT_MOUSE)
#if (HID_RPT_PTP)
// TouchPad IN Report Char. Declaration and Value, Report Ref. and CCC Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_TP_IN_RPT_CHAR ),
ATT_ELMT( HID_IDX_TP_IN_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_NTF, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_TP_IN_RPT_REF ),
ATT_ELMT_DESC_CLI_CHAR_CFG( HID_IDX_TP_IN_RPT_NTF_CFG ),
// Max Count Feature Report Char. Declaration and Value, Report Ref. Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_MAXCNT_FEAT_RPT_CHAR ),
ATT_ELMT( HID_IDX_MAXCNT_FEAT_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_WR, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_MAXCNT_FEAT_RPT_REF ),
// PTPHQA Feature Report Char. Declaration and Value, Report Ref. Descriptor
ATT_ELMT_DECL_CHAR( HID_IDX_PTPHQA_FEAT_RPT_CHAR ),
ATT_ELMT( HID_IDX_PTPHQA_FEAT_RPT_VAL, ATT_CHAR_REPORT, PROP_RD | PROP_WR, HID_REPORT_MAX_LEN ),
ATT_ELMT_DESC_REPORT_REF( HID_IDX_PTPHQA_FEAT_RPT_REF ),
#endif //(HID_RPT_PTP)
#endif //(HID_REPORT_SUP)
};
/// Service Description
const struct svc_decl hid_svc_db =
{
.uuid = ATT_SVC_HID,
.info = SVC_UUID(16) | SVC_SEC(UNAUTH),
.atts = hid_atts,
.nb_att = HID_IDX_NB - 1,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve attribute index form handle
static uint8_t hids_get_att_idx(uint16_t handle)
{
ASSERT_ERR((handle >= hids_env.start_hdl) && (handle < hids_env.start_hdl + HID_IDX_NB));
return (handle - hids_env.start_hdl);
}
/// Retrieve Report attribute handle from rpt_idx (@see rpt_ntf_idx) or ATT_INVALID_HDL
static uint16_t hids_get_rpt_handle(uint8_t rpt_idx)
{
uint8_t att_idx = 0;
switch (rpt_idx)
{
#if (HID_BOOT_SUP)
#if (HID_BOOT_KB)
case RPT_IDX_BOOT_KB:
{
att_idx = HID_IDX_BOOT_KB_IN_RPT_VAL;
} break;
#endif //(HID_BOOT_KB)
#if (HID_BOOT_MOUSE)
case RPT_IDX_BOOT_MOUSE:
{
att_idx = HID_IDX_BOOT_MOUSE_IN_RPT_VAL;
} break;
#endif //(HID_BOOT_MOUSE)
#endif //(HID_BOOT_SUP)
#if (HID_REPORT_SUP)
#if (HID_RPT_KB)
case RPT_IDX_KB:
{
att_idx = HID_IDX_KB_IN_RPT_VAL;
} break;
#endif //(HID_RPT_KB)
#if (HID_RPT_MEDIA)
case RPT_IDX_MEDIA:
{
att_idx = HID_IDX_MEDIA_IN_RPT_VAL;
} break;
#endif //(HID_RPT_MEDIA)
#if (HID_RPT_SYSTEM)
case RPT_IDX_SYSTEM:
{
att_idx = HID_IDX_SYS_IN_RPT_VAL;
} break;
#endif //(HID_RPT_SYSTEM)
#if (HID_RPT_MOUSE)
case RPT_IDX_MOUSE:
{
att_idx = HID_IDX_MOUSE_IN_RPT_VAL;
} break;
#endif //(HID_RPT_MOUSE)
#if (HID_RPT_PTP)
case RPT_IDX_TP:
{
att_idx = HID_IDX_TP_IN_RPT_VAL;
} break;
#endif //(HID_RPT_PTP)
#endif //(HID_REPORT_SUP)
default:
{
att_idx = 0; // error index
} break;
}
return (att_idx) ? (hids_env.start_hdl + att_idx) : ATT_INVALID_HDL;
}
/// update configuration if value for stop or NTF start
static uint8_t hids_rpt_ntf_cfg(uint8_t conidx, uint8_t rpt_idx, const struct atts_write_ind *ind)
{
uint8_t status = PRF_ERR_APP_ERROR;
if ((!ind->more) && (ind->length == sizeof(uint16_t)))
{
uint16_t cli_cfg = read16p(ind->value);
//if ((cli_cfg == PRF_CLI_STOP_NTFIND) || (cli_cfg == PRF_CLI_START_NTF))
if (cli_cfg <= PRF_CLI_START_NTF)
{
DEBUG(" RPT_NTF_CFG(idx:%d,cfg:%d)", rpt_idx, cli_cfg);
HID_RPT_NTF_SET(conidx, rpt_idx, cli_cfg);
status = LE_SUCCESS;
}
}
return status;
}
/// Confirm ATTS_WRITE_REQ
static void hids_att_write_cfm(uint8_t conidx, uint8_t att_idx, uint16_t handle, const struct atts_write_ind *ind)
{
uint8_t status = LE_SUCCESS;
switch (att_idx)
{
case HID_IDX_HID_CTRL_PT_VAL:
{
ASSERT_ERR(ind->length == HID_CTRL_PT_SIZE);
DEBUG(" HID_CTRL_PT:%d", ind->value[0]);
hids_env.conn[conidx].ctrl_pt = ind->value[0];
} break;
#if (HID_BOOT_SUP)
case HID_IDX_PROTO_MODE_VAL:
{
ASSERT_ERR(ind->length == HID_PROTO_MODE_SIZE);
DEBUG(" PROTO_MODE:%d", ind->value[0]);
hids_env.conn[conidx].proto_mode = ind->value[0];
} break;
#if (HID_BOOT_KB)
case HID_IDX_BOOT_KB_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_BOOT_KB, ind);
} break;
case HID_IDX_BOOT_KB_OUT_RPT_VAL:
{
ASSERT_ERR(ind->length == HID_KB_OUT_RPT_SIZE);
DEBUG(" Led_Lock(b0:num,b1:caps,b2:scroll):0x%02x", ind->value[0]);
hids_env.conn[conidx].led_lock = ind->value[0];
hids_led_lock(ind->value[0]);
} break;
#endif //(HID_BOOT_KB)
#if (HID_BOOT_MOUSE)
case HID_IDX_BOOT_MOUSE_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_BOOT_MOUSE, ind);
} break;
#endif //(HID_BOOT_MOUSE)
#endif //(HID_BOOT_SUP)
#if (HID_REPORT_SUP)
#if (HID_RPT_KB)
case HID_IDX_KB_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_KB, ind);
} break;
case HID_IDX_KB_OUT_RPT_VAL:
{
ASSERT_ERR(ind->length == HID_KB_OUT_RPT_SIZE);
DEBUG(" Led_Lock(b0:num,b1:caps,b2:scroll):0x%02x", ind->value[0]);
hids_env.conn[conidx].led_lock = ind->value[0];
hids_led_lock(ind->value[0]);
} break;
#endif //(HID_RPT_KB)
#if (HID_RPT_MEDIA)
case HID_IDX_MEDIA_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_MEDIA, ind);
} break;
#endif //(HID_RPT_MEDIA)
#if (HID_RPT_SYSTEM)
case HID_IDX_SYS_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_SYSTEM, ind);
} break;
#endif //(HID_RPT_SYSTEM)
#if (HID_RPT_MOUSE)
case HID_IDX_MOUSE_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_MOUSE, ind);
} break;
#endif //(HID_RPT_MOUSE)
#if (HID_RPT_PTP)
case HID_IDX_TP_IN_RPT_NTF_CFG:
{
status = hids_rpt_ntf_cfg(conidx, RPT_IDX_TP, ind);
} break;
case HID_IDX_MAXCNT_FEAT_RPT_VAL:
case HID_IDX_PTPHQA_FEAT_RPT_VAL:
{
// maybe do something
} break;
#endif //(HID_RPT_PTP)
#endif //(HID_REPORT_SUP)
default:
{
status = PRF_ERR_APP_ERROR;
} break;
}
// Send write confirm, if no more data.
if (!ind->more)
gatt_write_cfm(conidx, status, handle);
}
/// Confirm ATTS_READ_REQ
static void hids_att_read_cfm(uint8_t conidx, uint8_t att_idx, uint16_t handle)
{
uint16_t length = 0;
switch (att_idx)
{
case HID_IDX_HID_INFO_VAL:
{
struct hid_info_tag hid_info;
hid_info.bcdHID = HID_INFO_BCDHID;
hid_info.bCountryCode = HID_INFO_BCODE;
hid_info.flags = HID_INFO_FLAGS;
DEBUG(" Read HID_INFO(bcd:0x%04X)", hid_info.bcdHID);
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_INFO_SIZE, (uint8_t *)&hid_info);
} break;
case HID_IDX_REPORT_MAP_VAL:
{
const uint8_t *report_map = hid_get_report_map(&length);
DEBUG(" Read REPORT_MAP(size:%d)", length);
gatt_read_cfm(conidx, LE_SUCCESS, handle, length, report_map);
} break;
#if (HID_BOOT_SUP)
case HID_IDX_PROTO_MODE_VAL:
{
DEBUG(" Read PROTO_MODE(mode:%d)", hids_env.conn[conidx].proto_mode);
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_PROTO_MODE_SIZE, &(hids_env.conn[conidx].proto_mode));
} break;
#if (HID_BOOT_KB)
case HID_IDX_BOOT_KB_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_BOOT_KB_RPT_SIZE, NULL); // zero array
} break;
case HID_IDX_BOOT_KB_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_BOOT_KB);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
case HID_IDX_BOOT_KB_OUT_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_KB_OUT_RPT_SIZE, &(hids_env.conn[conidx].led_lock));
} break;
#endif //(HID_BOOT_KB)
#if (HID_BOOT_MOUSE)
case HID_IDX_BOOT_MOUSE_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_BOOT_MOUSE_RPT_SIZE, NULL); // zero array
} break;
case HID_IDX_BOOT_MOUSE_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_BOOT_MOUSE);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
#endif //(HID_BOOT_MOUSE)
#endif //(HID_BOOT_SUP)
#if (HID_REPORT_SUP)
#if (HID_RPT_KB)
case HID_IDX_KB_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, RPT_LEN_KB, NULL); // zero array
} break;
case HID_IDX_KB_IN_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_KB;
refer.report_type = HID_REPORT_INPUT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
case HID_IDX_KB_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_KB);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
case HID_IDX_KB_OUT_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_KB_OUT_RPT_SIZE, &(hids_env.conn[conidx].led_lock));
} break;
case HID_IDX_KB_OUT_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_KB;
refer.report_type = HID_REPORT_OUTPUT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
#endif //(HID_RPT_KB)
#if (HID_RPT_MEDIA)
case HID_IDX_MEDIA_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, RPT_LEN_MEDIA, NULL); // zero array
} break;
case HID_IDX_MEDIA_IN_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_MEDIA;
refer.report_type = HID_REPORT_INPUT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
case HID_IDX_MEDIA_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_MEDIA);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
#endif //(HID_RPT_MEDIA)
#if (HID_RPT_SYSTEM)
case HID_IDX_SYS_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, RPT_LEN_SYSTEM, NULL); // zero array
} break;
case HID_IDX_SYS_IN_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_SYSTEM;
refer.report_type = HID_REPORT_INPUT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
case HID_IDX_SYS_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_SYSTEM);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
#endif //(HID_RPT_SYSTEM)
#if (HID_RPT_MOUSE)
case HID_IDX_MOUSE_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, RPT_LEN_MOUSE, NULL); // zero array
} break;
case HID_IDX_MOUSE_IN_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_MOUSE;
refer.report_type = HID_REPORT_INPUT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
case HID_IDX_MOUSE_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_MOUSE);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
#endif //(HID_RPT_MOUSE)
#if (HID_RPT_PTP)
case HID_IDX_TP_IN_RPT_VAL:
{
gatt_read_cfm(conidx, LE_SUCCESS, handle, RPT_LEN_TP, NULL); // zero array
} break;
case HID_IDX_TP_IN_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_TP;
refer.report_type = HID_REPORT_INPUT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
case HID_IDX_TP_IN_RPT_NTF_CFG:
{
uint16_t ntf_cfg = HID_RPT_NTF_GET(conidx, RPT_IDX_TP);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);
} break;
case HID_IDX_MAXCNT_FEAT_RPT_VAL:
{
uint8_t finger = PTP_MAX_FINGER_CNT;
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint8_t), &finger);
} break;
case HID_IDX_MAXCNT_FEAT_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_MAXCNT;
refer.report_type = HID_REPORT_FEATURE;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
case HID_IDX_PTPHQA_FEAT_RPT_VAL:
{
const uint8_t *ptp_hqa = hid_get_ptphqa_blob(&length);
gatt_read_cfm(conidx, LE_SUCCESS, handle, length, ptp_hqa);
} break;
case HID_IDX_PTPHQA_FEAT_RPT_REF:
{
struct hid_report_ref refer;
refer.report_id = RPT_ID_PTPHQA;
refer.report_type = HID_REPORT_FEATURE;
gatt_read_cfm(conidx, LE_SUCCESS, handle, HID_REPORT_REF_SIZE, (uint8_t *)&refer);
} break;
#endif //(HID_RPT_PTP)
#endif //(HID_REPORT_SUP)
default:
{
// error response
gatt_read_cfm(conidx, PRF_ERR_APP_ERROR, handle, 0, NULL);
} break;
}
}
/// Handles reception of the atts request from peer device
static void hids_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t att_idx = hids_get_att_idx(handle);
ASSERT_ERR(coindx < HID_CONN_MAX);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,att:%d)", conidx, opcode, handle, att_idx);
switch (opcode)
{
case ATTS_READ_REQ:
{
hids_att_read_cfm(conidx, att_idx, handle);
} break;
case ATTS_WRITE_REQ:
{
const struct atts_write_ind *ind = param;
DEBUG(" write_req(hdl:0x%x,att:%d,wr:0x%x,len:%d)", handle, att_idx, ind->wrcode, ind->length);
hids_att_write_cfm(conidx, att_idx, handle, ind);
} break;
case ATTS_INFO_REQ:
{
uint16_t length = ATT_MAX_LEN_GET(att_idx, hid_atts);
// Send length-info confirm for prepWR judging.
DEBUG(" info_cfm(hdl:0x%x,att:%d,len:%d)", handle, att_idx, length);
gatt_info_cfm(conidx, LE_SUCCESS, handle, length);
} break;
case ATTS_CMP_EVT:
{
const struct atts_cmp_evt *evt = param;
hids_env.nb_pkt++; // release
DEBUG(" cmp_evt(op:0x%x,sta:0x%x,nb:%d)", evt->operation, evt->status, hids_env.nb_pkt);
// add 'if' to avoid warning #117-D: "evt" never referenced
if (evt->operation == GATT_NOTIFY)
{
// Notify result
}
} break;
default:
{
// nothing to do
} break;
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add HID Service Profile in the DB
* Customize via pre-define @see HID_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t hids_prf_init(void)
{
uint8_t status = LE_SUCCESS;
// Init Environment
hids_env.start_hdl = HID_START_HDL;
hids_env.nb_pkt = HID_NB_PKT_MAX;
for (uint8_t conidx = 0; conidx < HID_CONN_MAX; conidx++)
{
hids_env.conn[conidx].rpt_ntfs = RPT_NTF_ALL;
hids_env.conn[conidx].led_lock = 0;
hids_env.conn[conidx].proto_mode = HID_REPORT_PROTOCOL_MODE;
hids_env.conn[conidx].ctrl_pt = HID_CTRL_PT_EXIT_SUSPEND;
}
// Create Service in database
status = attmdb_svc_create(&hids_env.start_hdl, NULL, &hid_svc_db, hids_svc_func);
DEBUG("svc_init(sta:0x%X,shdl:%d,atts:%d)", status, hids_env.start_hdl, HID_IDX_NB-1);
return status;
}
/**
****************************************************************************************
* @brief Show LED Lock of Keyboard Output, User Implement! (__weak func)
*
* @param[in] leds Bits of Led_Lock(b0:num,b1:caps,b2:scroll)
****************************************************************************************
*/
__weak void hids_led_lock(uint8_t leds)
{
// todo LED play...
}
/**
****************************************************************************************
* @brief Enable HID Notification Configurations.
*
* @param[in] conidx Connection index
* @param[in] rpt_ntf Notification Config Bits @see enum rpt_ntf_idx
****************************************************************************************
*/
void hids_set_ccc(uint8_t conidx, uint8_t rpt_ntf)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
// update configuration
hids_env.conn[conidx].rpt_ntfs = rpt_ntf;
}
}
/**
****************************************************************************************
* @brief Send HID Report to Host peer.
*
* @param[in] conidx Connection Index
* @param[in] rep_idx Report Index
* @param[in] rep_len Report Length
* @param[in] rep_val Report Value
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t hids_report_send(uint8_t conidx, uint8_t rep_idx, uint16_t rep_len, const uint8_t* rep_val)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
if ((rep_len > 0) && (hids_env.nb_pkt > 0))
{
if (HID_RPT_NTF_GET(conidx, rep_idx) == PRF_CLI_START_NTF)
{
uint16_t handle = hids_get_rpt_handle(rep_idx);
if (handle != ATT_INVALID_HDL)
{
hids_env.nb_pkt--; // allocate
DEBUG("hid_ntf_send(len:%d,nb:%d)", rep_len, hids_env.nb_pkt);
debugHex(rep_val, rep_len);
gatt_ntf_send(conidx, handle, rep_len, rep_val);
status = LE_SUCCESS;
}
}
else
{
status = PRF_ERR_NTF_DISABLED;
}
}
return status;
}
#endif //(PRF_HIDS)

171
ble/prf/prf_hids.h Normal file
View File

@ -0,0 +1,171 @@
/**
****************************************************************************************
*
* @file prf_hids.h
*
* @brief Header file - HID Service Server Role
*
****************************************************************************************
*/
#ifndef PRF_HIDS_H_
#define PRF_HIDS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Server Start Handle(0 = dynamically allocated)
#if !defined(HID_START_HDL)
#define HID_START_HDL (0)
#endif
/// Number of reports that can be sent
#if !defined(HID_NB_PKT_MAX)
#define HID_NB_PKT_MAX (10)
#endif
/// Maximal length of Report/Boot Char. Value
#if !defined(HID_REPORT_MAX_LEN)
#define HID_REPORT_MAX_LEN (64)
#endif
/// Size of HID BOOT keyboard/mouse report
#define HID_BOOT_REPORT_MAX_LEN (8)
#define HID_BOOT_KB_RPT_SIZE (8) // 1B(ctrlKeys) + 1B(resv0) + 6B(KeyCode)
#define HID_BOOT_MOUSE_RPT_SIZE (4) // 1B(button) + 1B(X) + 1B(Y) + 1B(Wheel)
/// Size of HID keyboard Output report
#define HID_KB_OUT_RPT_SIZE (1) // 1B(leds)
/// Size of HID Information @see struct hid_info_tag
#define HID_INFO_SIZE (4)
/// Size of HID Control Point @see enum hid_ctrl_pt
#define HID_CTRL_PT_SIZE (1)
/// Size of HID Protocol Mode @see enum hid_proto_mode
#define HID_PROTO_MODE_SIZE (1)
/// Size of HID Report Ref. @see struct hid_report_ref
#define HID_REPORT_REF_SIZE (2)
/// HID Information, default value
#define HID_INFO_BCDHID (0x0111) // HID Version 1.11
#define HID_INFO_BCODE (0x00) // bCountryCode
#define HID_INFO_FLAGS (HID_REMOTE_WAKE_CAPABLE | HID_NORM_CONNECTABLE)
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// HID Information flags
enum hid_info_flags
{
/// Device capable of providing wake-up signal to a HID host
HID_REMOTE_WAKE_CAPABLE = 0x01,
/// Normally connectable support bit
HID_NORM_CONNECTABLE = 0x02,
};
/// Protocol Mode Char. value Keys
enum hid_proto_mode
{
/// Boot Protocol Mode
HID_BOOT_PROTOCOL_MODE = 0x00,
/// Report Protocol Mode
HID_REPORT_PROTOCOL_MODE = 0x01,
};
/// HID Control Point Characteristic value keys
enum hid_ctrl_pt
{
/// Suspend
HID_CTRL_PT_SUSPEND = 0x00,
/// Exit suspend
HID_CTRL_PT_EXIT_SUSPEND = 0x01,
};
/// Report Reference Char. Configuration Values
enum hid_report_type
{
/// Input Report(RD & NTF)
HID_REPORT_INPUT = 0x01,
/// Output Report(RD & WR & WC)
HID_REPORT_OUTPUT = 0x02,
/// Feature Report(RD & WR)
HID_REPORT_FEATURE = 0x03,
};
/// HID Information structure
struct hid_info_tag
{
/// bcdHID
uint16_t bcdHID;
/// bCountryCode
uint8_t bCountryCode;
/// Flags
uint8_t flags;
};
/// Report Reference structure
struct hid_report_ref
{
/// Report ID
uint8_t report_id;
/// Report Type
uint8_t report_type;
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add HID Service Profile in the DB
* Customize via pre-define @see HID_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t hids_prf_init(void);
/**
****************************************************************************************
* @brief Show LED Lock of Keyboard Output, User Implement! (__weak func)
*
* @param[in] leds Bits of Led_Lock(b0:num,b1:caps,b2:scroll)
****************************************************************************************
*/
void hids_led_lock(uint8_t leds);
/**
****************************************************************************************
* @brief Enable HID Notification Configurations.
*
* @param[in] conidx Connection index
* @param[in] rpt_ntf Notification Config Bits @see enum rpt_ntf_idx.
****************************************************************************************
*/
void hids_set_ccc(uint8_t conidx, uint8_t rpt_ntf);
/**
****************************************************************************************
* @brief Send HID Report to Host peer.
*
* @param[in] conidx Connection Index
* @param[in] rep_idx Report Index
* @param[in] rep_len Report Length
* @param[in] rep_val Report Value
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t hids_report_send(uint8_t conidx, uint8_t rep_idx, uint16_t rep_len, const uint8_t* rep_val);
#endif /* PRF_HIDS_H_ */

485
ble/prf/prf_otas.c Normal file
View File

@ -0,0 +1,485 @@
/**
****************************************************************************************
*
* @file prf_otas.c
*
* @brief OTA Service - Server Role Implementation.
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#if (PRF_OTAS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "prf_otas.h"
#if (DBG_OTAS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Max length of received once
#if !defined(OTA_RXD_MAX_LEN)
#define OTA_RXD_MAX_LEN (20)
#endif
/// Max number of notify/indicate pkt
#if !defined(OTA_NB_PKT_MAX)
#define OTA_NB_PKT_MAX (5)
#endif
/// Version String for OTA_IDX_READ_VAL Read
#define OTA_VERS_STR ("bleOTA v1.0")
#define OTA_VERS_STR_LEN (sizeof(OTA_VERS_STR) - 1)
/// Macro for Client Config value operation
#define OTA_NTF_CFG_GET(conidx) \
((otas_env.ntf_bits >> (conidx*2)) & (PRF_CLI_START_NTF | PRF_CLI_START_IND))
#define OTA_NTF_CFG_CLR(conidx) \
otas_env.ntf_bits &= ~((PRF_CLI_START_NTF | PRF_CLI_START_IND) << (conidx*2))
#define OTA_NTF_CFG_SET(conidx, conf) \
otas_env.ntf_bits = (otas_env.ntf_bits & ~((PRF_CLI_START_NTF | PRF_CLI_START_IND) << (conidx*2))) | ((conf) << (conidx*2))
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
/// Server Environment Variable
typedef struct otas_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// Client Config of peer devices - each 2Bits(NTF & IND), so max_peer=8.
uint16_t ntf_bits;
// Number of notify pkt
uint8_t nb_pkt;
} otas_env_t;
/// Global Variable Declarations
otas_env_t otas_env;
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// Attributes Index
enum ota_att_idx
{
// Service Declaration, *MUST* Start at 0
OTA_IDX_SVC,
// Serial TXD Char.
OTA_IDX_TXD_CHAR,
OTA_IDX_TXD_VAL,
OTA_IDX_TXD_NTF_CFG,
// Serial RXD Char.
OTA_IDX_RXD_CHAR,
OTA_IDX_RXD_VAL, //5
#if (OTA_READ_SUP)
// Serial READ Char.
OTA_IDX_READ_CHAR,
OTA_IDX_READ_VAL,
#endif
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
OTA_IDX_NB,
};
#if (OTA_UUID_128)
/// Characteristic Base UUID128 (User Customize)
#define OTA_ATT_UUID128(uuid) { 0xFC, 0x12, 0x41, 0x2A, 0xD2, 0xDE, 0x7E, 0x1D, \
0x4D, 0x47, 0xA2, 0x09, (uuid) & 0xFF, (uuid >> 8) & 0xFF, 0x00, 0x00 }
/// Serial Service UUID128
const uint8_t ota_svc_uuid[] = OTA_ATT_UUID128(0xFF50);
/// Serial Notify UUID128
const uint8_t ota_char_txd_notify[] = OTA_ATT_UUID128(0xFF51);
/// Serial Write Command UUID128
const uint8_t ota_char_rxd_write[] = OTA_ATT_UUID128(0xFF52);
/// Serial Read Command UUID128
const uint8_t ota_char_val_read[] = OTA_ATT_UUID128(0xFF53);
/// Attributes Description
const att_decl_t ota_atts[] =
{
// Serial Notify Char. Declaration and Value and Client Char. Configuration Descriptor
ATT_ELMT_DECL_CHAR( OTA_IDX_TXD_CHAR ),
ATT_ELMT128( OTA_IDX_TXD_VAL, ota_char_txd_notify, PROP_NTF | PROP_IND, 0 ),
ATT_ELMT_DESC_CLI_CHAR_CFG( OTA_IDX_TXD_NTF_CFG ),
// Serial Write Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( OTA_IDX_RXD_CHAR ),
ATT_ELMT128( OTA_IDX_RXD_VAL, ota_char_rxd_write, PROP_WC | PROP_WR, OTA_RXD_MAX_LEN ),
#if (OTA_READ_SUP)
// Serial Read Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( OTA_IDX_READ_CHAR ),
ATT_ELMT128( OTA_IDX_READ_VAL, ota_char_val_read, PROP_RD, 0 ),
#endif //(OTA_READ_SUP)
};
/// Service Description
const struct svc_decl ota_svc_db =
{
.uuid128 = ota_svc_uuid,
.info = SVC_UUID(128),
.atts = ota_atts,
.nb_att = OTA_IDX_NB - 1,
};
#else //(OTAS_UUID16)
/// Serial Service UUID
#define OTA_SVC_UUID ATT_UUID16(0xFF50)
/// Serial Notify UUID
#define OTA_CHAR_TXD_NOTIFY ATT_UUID16(0xFF51)
/// Serial Write Command UUID
#define OTA_CHAR_RXD_WRITE ATT_UUID16(0xFF52)
/// Serial Read Command UUID
#define OTA_CHAR_VAL_READ ATT_UUID16(0xFF53)
/// Attributes Description
const att_decl_t ota_atts[] =
{
// Serial Notify Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( OTA_IDX_TXD_CHAR ),
ATT_ELMT( OTA_IDX_TXD_VAL, OTA_CHAR_TXD_NOTIFY, PROP_NTF | PROP_IND, 0 ),
ATT_ELMT_DESC_CLI_CHAR_CFG( OTA_IDX_TXD_NTF_CFG ),
// Serial Write Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( OTA_IDX_RXD_CHAR ),
ATT_ELMT( OTA_IDX_RXD_VAL, OTA_CHAR_RXD_WRITE, PROP_WC | PROP_WR, OTA_RXD_MAX_LEN ),
#if (OTA_READ_SUP)
// Serial Read Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( OTA_IDX_READ_CHAR ),
ATT_ELMT( OTA_IDX_READ_VAL, OTA_CHAR_VAL_READ, PROP_RD, 0 ),
#endif //(OTA_READ_SUP)
};
/// Service Description
const struct svc_decl ota_svc_db =
{
.uuid = OTA_SVC_UUID,
.info = SVC_UUID(16),
.atts = ota_atts,
.nb_att = OTA_IDX_NB - 1,
};
#endif
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve attribute handle from index (@see ota_att_idx)
static uint16_t otas_get_att_handle(uint8_t att_idx)
{
ASSERT_ERR(att_idx < OTA_IDX_NB);
return att_idx + otas_env.start_hdl;
}
/// Retrieve attribute index form handle
static uint8_t otas_get_att_idx(uint16_t handle)
{
ASSERT_ERR((handle >= otas_env.start_hdl) && (handle < otas_env.start_hdl + OTA_IDX_NB));
return handle - otas_env.start_hdl;
}
/// Handles reception of the atts request from peer device
static void otas_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t att_idx = otas_get_att_idx(handle);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,att:%d)", conidx, opcode, handle, att_idx);
switch (opcode)
{
case ATTS_READ_REQ:
{
if (att_idx == OTA_IDX_TXD_NTF_CFG)
{
// retrieve notification config
uint16_t cli_cfg = OTA_NTF_CFG_GET(conidx);
DEBUG(" read_cfm(txd_ntf:%d)", cli_cfg);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
break;
}
#if (OTA_READ_SUP)
if (att_idx == OTA_IDX_READ_VAL)
{
otas_cb_rdv(conidx, att_idx, handle);
break;
}
#endif //(OTA_READ_SUP)
// Send error response
gatt_read_cfm(conidx, PRF_ERR_APP_ERROR, handle, 0, NULL);
} break;
case ATTS_WRITE_REQ:
{
const struct atts_write_ind *ind = param;
DEBUG(" write_req(hdl:0x%x,att:%d,wr:0x%x,len:%d)", handle, att_idx, ind->wrcode, ind->length);
if (att_idx == OTA_IDX_RXD_VAL)
{
// Send write conform first!
if (!ind->more) gatt_write_cfm(conidx, LE_SUCCESS, handle);
// Next to process data received
otas_cb_rxd(conidx, ind->length, ind->value);
break;
}
if (att_idx == OTA_IDX_TXD_NTF_CFG)
{
if ((!ind->more) && (ind->length == sizeof(uint16_t)))
{
uint16_t cli_cfg = read16p(ind->value);
// update configuration if value for stop or NTF/IND start
if (cli_cfg <= PRF_CLI_START_IND)
{
DEBUG(" set txd_ntf(cid:%d,cfg:%d)", conidx, cli_cfg);
OTA_NTF_CFG_SET(conidx, cli_cfg);
// Send write conform quickly!
gatt_write_cfm(conidx, LE_SUCCESS, handle);
#if (OTA_CLI_CFG)
// Next to process cli_cfg changed
otas_cb_ccc(conidx, cli_cfg);
#endif //(OTA_CLI_CFG)
break;
}
}
}
// Send write conform with error!
gatt_write_cfm(conidx, PRF_ERR_APP_ERROR, handle);
} break;
case ATTS_INFO_REQ:
{
uint8_t status = LE_SUCCESS;
uint16_t length = 0;
if (att_idx == OTA_IDX_RXD_VAL)
{
length = OTA_RXD_MAX_LEN; // accepted length
}
else if (att_idx == OTA_IDX_TXD_NTF_CFG)
{
length = sizeof(uint16_t); // CCC attribute
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
// Send length-info confirm for prepWR judging.
DEBUG(" info_cfm(hdl:0x%x,att:%d,sta:0x%X,len:%d)", handle, att_idx, status, length);
gatt_info_cfm(conidx, status, handle, length);
} break;
case ATTS_CMP_EVT:
{
const struct atts_cmp_evt *evt = param;
otas_env.nb_pkt++; // release
DEBUG(" cmp_evt(op:0x%x,sta:0x%x,nb:%d)", evt->operation, evt->status, otas_env.nb_pkt);
// add 'if' to avoid warning #117-D: "evt" never referenced
if (evt->operation == GATT_NOTIFY)
{
// Notify result
}
} break;
default:
{
// nothing to do
} break;
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Serial Service Profile in the DB.
* Customize via pre-define @see OTA_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t otas_svc_init(void)
{
uint8_t status = LE_SUCCESS;
// Init Environment
otas_env.start_hdl = OTA_START_HDL;
otas_env.nb_pkt = OTA_NB_PKT_MAX;
otas_env.ntf_bits = 0;
// Create Service in database
status = attmdb_svc_create(&otas_env.start_hdl, NULL, &ota_svc_db, otas_svc_func);
DEBUG("svc_init(sta:0x%X,shdl:%d,nb_pkt:%d,ntf_bits:0x%X)",
status, otas_env.start_hdl, otas_env.nb_pkt, otas_env.ntf_bits);
return status;
}
/**
****************************************************************************************
* @brief Enable setting client configuration characteristics
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void otas_set_ccc(uint8_t conidx, uint8_t cli_cfg)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
// update configuration
OTA_NTF_CFG_SET(conidx, cli_cfg);
}
}
/**
****************************************************************************************
* @brief Transmit data to peer device via NTF or IND
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t otas_txd_send(uint8_t conidx, uint16_t len, const uint8_t* data)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
if ((len > 0) && (otas_env.nb_pkt > 0))
{
uint8_t ntf_cfg = OTA_NTF_CFG_GET(conidx);
if (ntf_cfg != PRF_CLI_STOP_NTFIND)
{
status = LE_SUCCESS;
gatt_ntf_send(conidx, otas_get_att_handle(OTA_IDX_TXD_VAL), len, data);
otas_env.nb_pkt--; // allocate
DEBUG("txd_send(len:%d,nb:%d)", len, otas_env.nb_pkt);
}
else
{
status = PRF_ERR_NTF_DISABLED;
}
}
return status;
}
/**
****************************************************************************************
* @brief Callback on received data from peer device via WC or WQ (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
****************************************************************************************
*/
__weak void otas_cb_rxd(uint8_t conidx, uint16_t len, const uint8_t *data)
{
debugHex(data, len);
// Loopback to txd, just test.
//otas_txd_send(conidx, len, data);
}
#if (OTA_READ_SUP)
/**
****************************************************************************************
* @brief Callback to response 'READ' from peer device (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] attidx SESS attribute index, converted with 'handle'
* @param[in] handle SESS attribute handle to send read cfm
*
* @return Length of value been READ
****************************************************************************************
*/
__weak void otas_cb_rdv(uint8_t conidx, uint8_t attidx, uint16_t handle)
{
uint16_t length = OTA_VERS_STR_LEN;
const uint8_t *p_data = (const uint8_t *)OTA_VERS_STR;
DEBUG(" read_cfm(att:%d, len:%d)", attidx, length);
gatt_read_cfm(conidx, LE_SUCCESS, handle, length, p_data);
}
#endif //(OTA_READ_SUP)
#if (OTA_CLI_CFG)
/**
****************************************************************************************
* @brief Callback on enabled client config from peer device via WQ (__weak func)
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
__weak void otas_cb_ccc(uint8_t conidx, uint8_t cli_cfg)
{
// user override
}
#endif //(OTA_CLI_CFG)
#endif //PRF_OTAS

119
ble/prf/prf_otas.h Normal file
View File

@ -0,0 +1,119 @@
/**
****************************************************************************************
*
* @file prf_otas.h
*
* @brief Header file - OTA Service Profile (Server Role).
*
****************************************************************************************
*/
#ifndef PRF_OTAS_H_
#define PRF_OTAS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Service Start Handle(0 = dynamically allocated)
#if !defined(OTA_START_HDL)
#define OTA_START_HDL (0)
#endif
/// Use UUID 128bit or 16bit
#if !defined(OTA_UUID128)
#define OTA_UUID128 (1)
#endif
/// Support READ Characteristic
#if !defined(OTA_READ_SUP)
#define OTA_READ_SUP (1)
#endif
/// Callback of Client Config enable
#if !defined(OTA_CLI_CFG)
#define OTA_CLI_CFG (0)
#endif
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add OTA Service Profile in the DB
* Customize via pre-define @see OTA_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t otas_svc_init(void);
/**
****************************************************************************************
* @brief Enable setting client configuration characteristics
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void otas_set_ccc(uint8_t conidx, uint8_t cli_cfg);
/**
****************************************************************************************
* @brief Transmit data to peer device via NTF or IND
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t otas_txd_send(uint8_t conidx, uint16_t len, const uint8_t *data);
/**
****************************************************************************************
* @brief Callback on received data from peer device via WC or WQ (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
****************************************************************************************
*/
void otas_cb_rxd(uint8_t conidx, uint16_t len, const uint8_t *data);
#if (OTA_READ_SUP)
/**
****************************************************************************************
* @brief Callback to response 'READ' from peer device (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] attidx SESS attribute index, converted with 'handle'
* @param[in] handle SESS attribute handle to send read cfm
*
* @return Length of value been READ
****************************************************************************************
*/
void otas_cb_rdv(uint8_t conidx, uint8_t attidx, uint16_t handle);
#endif
#if (OTA_CLI_CFG)
/**
****************************************************************************************
* @brief Callback on enabled client config from peer device via WQ (__weak func)
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void otas_cb_ccc(uint8_t conidx, uint8_t cli_cfg);
#endif
#endif /* PRF_OTAS_H_ */

783
ble/prf/prf_ptss.c Normal file
View File

@ -0,0 +1,783 @@
/**
****************************************************************************************
*
* @file prf_ptss.c
*
* @brief Profile Testing Service - Server Role Implementation.
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#if (PRF_PTSS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "prf_ptss.h"
#if (DBG_PTSS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<PTSS>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Version String for Read
#define PTS_VERS_STR ("Ver:1.25")
#define PTS_VERS_STR_LEN (sizeof(PTS_VERS_STR) - 1)
/// Macro for Client Config value operation
#define PTS_CLI_CFG_GET(conidx) \
((ptss_env.cli_cfg >> (conidx*2)) & (PRF_CLI_START_NTF | PRF_CLI_START_IND))
#define PTS_CLI_CFG_CLR(conidx) \
ptss_env.cli_cfg &= ~((PRF_CLI_START_NTF | PRF_CLI_START_IND) << (conidx*2))
#define PTS_CLI_CFG_SET(conidx, conf) \
ptss_env.cli_cfg = (ptss_env.cli_cfg & ~((PRF_CLI_START_NTF | PRF_CLI_START_IND) << (conidx*2))) | ((conf) << (conidx*2))
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
/// Server Environment Variable
typedef struct ptss_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// CCC of peer devices(bits).
uint16_t cli_cfg;
} ptss_env_t;
/// Global Variable Declarations
ptss_env_t ptss_env;
/// Global state of bonded, changed in gapc
uint8_t pts_bond;
/// Buffer of received data
static uint16_t recv_len = PTS_DATA_MAX_LEN;
static uint8_t recv_buf[PTS_DATA_MAX_LEN];
/// Buffer of read data
static uint16_t read_len = PTS_DATA_MAX_LEN;
static uint8_t read_buf[PTS_DATA_MAX_LEN];
/// Buffer of desc data
static uint16_t desc_len = PTS_DESC_MAX_LEN;
static uint8_t desc_buf[PTS_DESC_MAX_LEN];
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// Service Attributes Indexes
enum pts_att_idx
{
// Service Declaration, *MUST* Start at 0
PTS_IDX_SVC,
// Attribute No.1: NTF/IND/RD
PTS_IDX_ATT1_CHAR,
PTS_IDX_ATT1_VAL,
PTS_IDX_ATT1_DESC,
// Attribute No.2: WR/WC/WS
PTS_IDX_ATT2_CHAR,
PTS_IDX_ATT2_VAL,
// Attribute No.3: RD
PTS_IDX_ATT3_CHAR,
PTS_IDX_ATT3_VAL,
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
PTS_IDX_NB,
};
/////////////////////////////////////////////////////////////////////////////
/// *** 0: Test for Normal ***
/////////////////////////////////////////////////////////////////////////////
#define PTS0_SVC_UUID ATT_UUID16(0xFF00)
#define PTS0_CHAR_ATT1 ATT_UUID16(0xFF01)
#define PTS0_CHAR_ATT2 ATT_UUID16(0xFF02)
#define PTS0_CHAR_ATT3 ATT_UUID16(0xFF03)
const att_decl_t pts0_atts[] =
{
// No.1 Characteristic Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT1_CHAR ),
ATT_ELMT( PTS_IDX_ATT1_VAL, PTS0_CHAR_ATT1, PROP_NTF|PROP_IND, 0 ),
ATT_ELMT_DESC_CLI_CHAR_CFG( PTS_IDX_ATT1_DESC ),
// No.2 Characteristic Declaration and Value
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT2_CHAR ),
ATT_ELMT( PTS_IDX_ATT2_VAL, PTS0_CHAR_ATT2, PROP_WC|PROP_WR|PROP_WS, PTS_DATA_MAX_LEN ),
// No.3 Characteristic Declaration and Value
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT3_CHAR ),
ATT_ELMT( PTS_IDX_ATT3_VAL, PTS0_CHAR_ATT3, PROP_RD, 0 ),
};
const struct svc_decl pts0_svc_db =
{
.uuid = PTS0_SVC_UUID,
.info = SVC_UUID(16),
.atts = pts0_atts,
.nb_att = PTS_IDX_NB - 1,
};
/////////////////////////////////////////////////////////////////////////////
/// *** 1: Test for ERROR ***
/////////////////////////////////////////////////////////////////////////////
#define PTS1_SVC_UUID ATT_UUID16(0xFF20)
#define PTS1_CHAR_ATT1 ATT_UUID16(0xFF21)
#define PTS1_CHAR_ATT2 ATT_UUID16(0xFF22)
#define PTS1_CHAR_ATT3 ATT_UUID16(0xFF23)
const att_decl_t pts1_atts[] =
{
// No.1 Characteristic Declaration and Value and User Descriptor
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT1_CHAR ),
ATT_ELMT( PTS_IDX_ATT1_VAL, PTS1_CHAR_ATT1, PROP_WC|PROP_WR|PROP_RD, PTS_DATA_MAX_LEN ),
ATT_ELMT( PTS_IDX_ATT1_DESC, ATT_DESC_CHAR_USER_DESCRIPTION, PROP_RD, 0 ),
// No.2 Characteristic Declaration and Value
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT2_CHAR ),
ATT_ELMT( PTS_IDX_ATT2_VAL, PTS1_CHAR_ATT2, PROP_WC|PROP_WR|PROP_RD, PTS_DATA_MAX_LEN ),
// No.3 Characteristic Declaration and Value
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT3_CHAR ),
ATT_ELMT( PTS_IDX_ATT3_VAL, PTS1_CHAR_ATT3, PROP_WC|PROP_WR|PROP_RD, PTS_DATA_MAX_LEN ),
};
const struct svc_decl pts1_svc_db =
{
.uuid = PTS1_SVC_UUID,
.info = SVC_UUID(16),
.atts = pts1_atts,
.nb_att = PTS_IDX_NB - 1,
};
/////////////////////////////////////////////////////////////////////////////
/// *** 2: Test for UUID128 ***
/////////////////////////////////////////////////////////////////////////////
#define PTS_ATT_UUID128(uuid) { 0x16, 0x0A, 0x10, 0x40, 0xD1, 0x9F, 0x4C, 0x6C, \
0xB4, 0x55, 0xE3, 0xF7, (uuid) & 0xFF, (uuid >> 8) & 0xFF, 0x00, 0x00}
const uint8_t PTS2_SVC_UUID[] = PTS_ATT_UUID128(0xFF00);
const uint8_t PTS2_CHAR_ATT1[] = PTS_ATT_UUID128(0xFF01);
const uint8_t PTS2_CHAR_ATT2[] = PTS_ATT_UUID128(0xFF02);
const uint8_t PTS2_CHAR_ATT3[] = PTS_ATT_UUID128(0xFF03);
const att_decl_t pts2_atts[] =
{
// No.1 Characteristic Declaration and Value and User Descriptor
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT1_CHAR ),
ATT_ELMT128( PTS_IDX_ATT1_VAL, PTS2_CHAR_ATT1, PROP_RD, 0 ),
ATT_ELMT( PTS_IDX_ATT1_DESC, ATT_DESC_CHAR_USER_DESCRIPTION, PROP_RD|PROP_WR, PTS_DESC_MAX_LEN ),
// No.2 Characteristic Declaration and Value
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT2_CHAR ),
ATT_ELMT128( PTS_IDX_ATT2_VAL, PTS2_CHAR_ATT2, PROP_WC|PROP_WR|PROP_RD, PTS_DATA_MAX_LEN ),
// No.3 Characteristic Declaration and Value
ATT_ELMT_DECL_CHAR( PTS_IDX_ATT3_CHAR ),
ATT_ELMT128( PTS_IDX_ATT3_VAL, PTS2_CHAR_ATT3, PROP_RD|PROP_WR, PTS_DATA_MAX_LEN ),
};
const struct svc_decl pts_svc_db2 =
{
.uuid128 = PTS2_SVC_UUID,
.info = SVC_UUID(128),
.atts = pts2_atts,
.nb_att = PTS_IDX_NB - 1,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve attribute handle from index (@see pts_att_idx)
static uint16_t ptss_get_att_handle(uint8_t att_idx)
{
ASSERT_ERR(att_idx < PTS_ATT_NB); //svr_idx=0
return (att_idx + ptss_env.start_hdl);
}
/// Retrieve attribute index form handle or ATT_INVALID_IDX if nothing found
static uint8_t ptss_get_att_idx(uint8_t *svr_idx, uint16_t handle)
{
uint8_t att_idx = ATT_INVALID_IDX;
if ((handle >= ptss_env.start_hdl) && (handle < ptss_env.start_hdl + PTS_IDX_NB))
{
att_idx = handle - ptss_env.start_hdl;
*svr_idx = 0;
}
else if ((handle >= ptss_env.start_hdl + PTS_IDX_NB) && (handle < ptss_env.start_hdl + PTS_IDX_NB*2))
{
att_idx = handle - (ptss_env.start_hdl + PTS_IDX_NB);
*svr_idx = 1;
}
else if ((handle >= ptss_env.start_hdl + PTS_IDX_NB*2) && (handle < ptss_env.start_hdl + PTS_IDX_NB*3))
{
att_idx = handle - (ptss_env.start_hdl + PTS_IDX_NB*2);
*svr_idx = 2;
}
return (att_idx);
}
/// Handles reception of the attribute info request message.
static void ptss_att_info_cfm(uint8_t conidx, uint8_t svr_idx, uint8_t att_idx, uint16_t handle)
{
uint16_t length = 0;
uint8_t status = LE_SUCCESS;
if (att_idx != ATT_INVALID_IDX)
{
if (svr_idx == 1) // PTS1 Error
{
// Long Write Error
if (att_idx == PTS_IDX_ATT1_VAL)
{
if ((pts_bond & GAP_AUTH_BOND) == 0)
status = ATT_ERR_INSUFF_AUTHOR;
else
length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT2_VAL)
{
if ((pts_bond & GAP_AUTH_MITM) == 0)
status = ATT_ERR_INSUFF_AUTHEN;
else
length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
//if (!pts_bond)
status = ATT_ERR_INSUFF_ENC_KEY_SIZE;
//else
// cfm->length = PTS_DATA_MAX_LEN;
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
}
else if (svr_idx == 2) // PTS2 Normal
{
if ((att_idx == PTS_IDX_ATT2_VAL) || (att_idx == PTS_IDX_ATT3_VAL))
{
length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
length = PTS_DESC_MAX_LEN;
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
}
else // PTS0 Normal
{
if (att_idx == PTS_IDX_ATT2_VAL)
{
length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
length = sizeof(uint16_t); // CCC attribute
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
}
}
else
{
status = PRF_ERR_APP_ERROR;
}
DEBUG(" info_cfm(svr:%d,hdl:0x%x,sta:0x%x,len:%d)", svr_idx, param->handle, status, length);
// Send info response
gatt_info_cfm(conidx, status, handle, length);
}
/// Confirm ATTS_WRITE_REQ
static void ptss_att_write_cfm(uint8_t conidx, uint8_t svr_idx, uint8_t att_idx, uint16_t handle, const struct atts_write_ind *ind)
{
uint8_t status = LE_SUCCESS;
if (att_idx != ATT_INVALID_IDX)
{
if (svr_idx == 1) // PTS1 Error
{
// Write Error
if (att_idx == PTS_IDX_ATT1_VAL)
{
if ((pts_bond & GAP_AUTH_BOND) == 0)
status = ATT_ERR_INSUFF_AUTHOR;
}
else if (att_idx == PTS_IDX_ATT2_VAL)
{
if ((pts_bond & GAP_AUTH_MITM) == 0)
status = ATT_ERR_INSUFF_AUTHEN;
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
//if (!pts_bond)
status = ATT_ERR_INSUFF_ENC_KEY_SIZE;
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
}
else if (svr_idx == 2) // PTS2 Normal
{
if ((att_idx == PTS_IDX_ATT2_VAL) || (att_idx == PTS_IDX_ATT3_VAL))
{
// received data to callback
ptss_cb_recv(conidx, ind->length, ind->value);
// Save data to read-back
if (att_idx == PTS_IDX_ATT2_VAL)
{
recv_len = ind->length;
memcpy(recv_buf, ind->value, ind->length);
}
else
{
read_len = ind->length;
memcpy(read_buf, ind->value, ind->length);
}
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
// Save desc to read-back
desc_len = ind->length;
memcpy(desc_buf, ind->value, desc_len);
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
}
else // PTS0 Normal
{
if (att_idx == PTS_IDX_ATT2_VAL)
{
// received data to callback
ptss_cb_recv(conidx, ind->length, ind->value);
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
// update configuration if value for stop or notification enable
uint8_t cli_cfg = ind->value[0] & (PRF_CLI_START_NTF | PRF_CLI_START_IND);
PTS_CLI_CFG_SET(conidx, cli_cfg);
// client conf to callback
ptss_cb_ccc(conidx, cli_cfg);
}
else
{
status = PRF_ERR_APP_ERROR;
}
}
}
else
{
status = PRF_ERR_APP_ERROR;
}
DEBUG(" --write_cfm(svr:%d,hdl:0x%x,sta:0x%x)", svr_idx, handle, status);
// Send write conform
gatt_write_cfm(conidx, status, handle);
}
/// Confirm ATTS_READ_REQ
static void ptss_att_read_cfm(uint8_t conidx, uint8_t svr_idx, uint8_t att_idx, uint16_t handle)
{
uint16_t length = 0;
uint8_t status = LE_SUCCESS;
if (att_idx != ATT_INVALID_IDX)
{
if (svr_idx == 1) // PTS1 Error
{
// Read Error
if (att_idx == PTS_IDX_ATT1_VAL)
{
if ((pts_bond & GAP_AUTH_BOND) == 0)
status = ATT_ERR_INSUFF_AUTHOR;
else
length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT2_VAL)
{
if ((pts_bond & GAP_AUTH_MITM) == 0)
status = ATT_ERR_INSUFF_AUTHEN;
else
length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
//if (!pts_bond)
status = ATT_ERR_INSUFF_ENC_KEY_SIZE;
//else
// length = PTS_DATA_MAX_LEN;
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
length = 2 * gatt_get_mtu(conidx) - 2;
}
else
{
status = ATT_ERR_READ_NOT_PERMITTED;
}
}
else if (svr_idx == 2) // PTS2 Normal
{
if (att_idx == PTS_IDX_ATT1_VAL)
{
length = gatt_get_mtu(conidx);
if (length < 512) length--;
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
length = desc_len;
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
length = read_len;
}
else if (att_idx == PTS_IDX_ATT2_VAL)
{
length = recv_len;
}
else
{
status = ATT_ERR_READ_NOT_PERMITTED;
}
}
else // PTS0 Normal
{
if (att_idx == PTS_IDX_ATT1_DESC)
{
length = sizeof(uint16_t);
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
//if (ptss_env.rdv_cb)
// length = ptss_env.rdv_cb(conidx, NULL);
length = gatt_get_mtu(conidx);
if (length < 512) length--;
}
else
{
status = ATT_ERR_READ_NOT_PERMITTED;
}
}
}
else
{
status = PRF_ERR_APP_ERROR;
}
DEBUG(" read_cfm(svr:%d,hdl:0x%x,sta:0x%x,len:%d)", svr_idx, param->handle, status, length);
// Send read response
if (status == LE_SUCCESS)
{
if (svr_idx == 2)
{
// PTS2 read-back
if (att_idx == PTS_IDX_ATT2_VAL)
{
gatt_read_cfm(conidx, status, handle, recv_len, recv_buf);
return;
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
gatt_read_cfm(conidx, status, handle, read_len, read_buf);
return;
}
else if (att_idx == PTS_IDX_ATT1_DESC)
{
gatt_read_cfm(conidx, status, handle, desc_len, desc_buf);
return;
}
}
else
{
// PTS0 fill data
if (att_idx == PTS_IDX_ATT1_DESC)
{
uint16_t cli_cfg = PTS_CLI_CFG_GET(conidx);
gatt_read_cfm(conidx, status, handle, length, (uint8_t *)&cli_cfg);
return;
}
else if (att_idx == PTS_IDX_ATT3_VAL)
{
ptss_cb_read(conidx, att_idx, handle);
return;
}
}
}
gatt_read_cfm(conidx, status, handle, length, NULL);
}
/// Handles reception of the atts request from peer device
static void ptss_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t svr_idx, att_idx;
att_idx = ptss_get_att_idx(&svr_idx, handle);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,svr:%d,att:%d)", conidx, opcode, handle, svr_idx, att_idx);
switch (opcode)
{
case ATTS_READ_REQ:
{
ptss_att_read_cfm(conidx, svr_idx, att_idx, handle);
} break;
case ATTS_WRITE_REQ:
{
const struct atts_write_ind *ind = param;
DEBUG(" write_req(hdl:0x%x,att:%d,wr:0x%x,len:%d)", handle, att_idx, ind->wrcode, ind->length);
ptss_att_write_cfm(conidx, svr_idx, att_idx, handle, ind);
} break;
case ATTS_INFO_REQ:
{
ptss_att_info_cfm(conidx, svr_idx, att_idx, handle);
} break;
case ATTS_CMP_EVT:
{
const struct atts_cmp_evt *evt = param;
DEBUG(" cmp_evt(op:0x%x,sta:0x%x,seq:%d)", evt->operation, evt->status, evt->seq_num);
// add 'if' to avoid warning #117-D: "evt" never referenced
if (evt->operation == GATT_NOTIFY)
{
// Notify result
}
} break;
default:
{
// nothing to do
} break;
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Service Profile in the DB
* Customize via pre-define @see PTSS_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t ptss_svc_init(void)
{
uint8_t status = LE_SUCCESS;
uint16_t next_hdl;
// Init Environment
ptss_env.start_hdl = PTS_START_HDL;
ptss_env.cli_cfg = 0;
#if (PTSS_START_HDL)
*start_hdl = PTSS_START_HDL; // at special handle
#endif
// Create Service in database
status = attmdb_svc_create(&ptss_env.start_hdl, NULL, &pts0_svc_db, ptss_svc_func);
DEBUG("svc_init0(sta:0x%X,shdl:%d)", status, ptss_env.start_hdl);
if (status != LE_SUCCESS)
{
return status;
}
next_hdl = ptss_env.start_hdl + PTS_IDX_NB;
status = attmdb_svc_create(&next_hdl, NULL, &pts1_svc_db, ptss_svc_func);
DEBUG("svc_init1(sta:0x%X,shdl:%d)", status, next_hdl);
if (status != LE_SUCCESS)
{
return status;
}
next_hdl += PTS_IDX_NB;
status = attmdb_svc_create(&next_hdl, NULL, &pts_svc_db2, ptss_svc_func);
if (status != LE_SUCCESS)
{
return status;
}
return status;
}
/**
****************************************************************************************
* @brief Enable setting client configuration characteristics
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
void ptss_set_ccc(uint8_t conidx, uint8_t cli_cfg)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
// update configuration
PTS_CLI_CFG_SET(conidx, cli_cfg);
}
}
/**
****************************************************************************************
* @brief Transmit data to peer device via NTF or IND
*
* @param[in] conidx peer destination connection index
* @param[in] handle Handle of NTF/IND
* @param[in] len Length of data
* @param[in] data pointer of buffer
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t ptss_evt_send(uint8_t conidx, uint16_t handle, uint16_t len, const uint8_t* data)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
if (len > 0)
{
uint8_t cli_cfg = PTS_CLI_CFG_GET(conidx);
if (cli_cfg != PRF_CLI_STOP_NTFIND)
{
uint8_t operation = (cli_cfg & PRF_CLI_START_NTF) ? GATT_NOTIFY : GATT_INDICATE;
if (handle == 0) ptss_get_att_handle(PTS_IDX_ATT1_VAL);
gatt_ntf_send(conidx, handle, len, data);
DEBUG("Send(hdl:0x%x,op:0x%x,len:%d)", handle, operation, len);
status = LE_SUCCESS;
}
else
{
status = PRF_ERR_NTF_DISABLED;
}
}
return status;
}
/**
****************************************************************************************
* @brief Callback on received data from peer device via WC or WQ (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
****************************************************************************************
*/
__weak void ptss_cb_recv(uint8_t conidx, uint16_t len, const uint8_t *data)
{
DEBUG("Recv(cid:%d,len:%d)", conidx, len);
debugHex(data, len);
}
/**
****************************************************************************************
* @brief Callback to response 'READ' from peer device (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] attidx SESS attribute index, converted with 'handle'
* @param[in] handle SESS attribute handle to send read cfm
*
* @return Length of value been READ
****************************************************************************************
*/
__weak void ptss_cb_read(uint8_t conidx, uint8_t attidx, uint16_t handle)
{
uint16_t length = PTS_VERS_STR_LEN;
const uint8_t *p_data = (const uint8_t *)PTS_VERS_STR;
DEBUG(" read_cfm(att:%d, len:%d)", attidx, length);
gatt_read_cfm(conidx, LE_SUCCESS, handle, length, p_data);
}
/**
****************************************************************************************
* @brief Callback on enabled client config from peer device via WQ (__weak func)
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
__weak void ptss_cb_ccc(uint8_t conidx, uint8_t cli_cfg)
{
DEBUG("Enable(cid:%d,cfg:%d)", conidx, cli_cfg);
}
#endif //PRF_PTSS

106
ble/prf/prf_ptss.h Normal file
View File

@ -0,0 +1,106 @@
/**
****************************************************************************************
*
* @file prf_ptss.h
*
* @brief Header file - Profile Testing Service (Server Role).
*
****************************************************************************************
*/
#ifndef PRF_PTSS_H_
#define PRF_PTSS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Service Start Handle(0 = dynamically allocated)
#if !defined(PTS_START_HDL)
#define PTS_START_HDL (0x50)
#endif
/// Max length of received once
#define PTS_DATA_MAX_LEN (22)
/// Max length of user description
#define PTS_DESC_MAX_LEN (22)
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Service Profile in the DB
* Customize via pre-define @see PTS_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t ptss_svc_init(void);
/**
****************************************************************************************
* @brief Enable setting client configuration characteristics
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void ptss_set_ccc(uint8_t conidx, uint8_t cli_cfg);
/**
****************************************************************************************
* @brief Transmit data to peer device via NTF or IND
*
* @param[in] conidx peer destination connection index
* @param[in] handle Handle of NTF/IND
* @param[in] len Length of data
* @param[in] data pointer of buffer
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t ptss_evt_send(uint8_t conidx, uint16_t handle, uint16_t len, const uint8_t* data);
/**
****************************************************************************************
* @brief Callback on received data from peer device via WC or WQ (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
****************************************************************************************
*/
void ptss_cb_recv(uint8_t conidx, uint16_t len, const uint8_t *data);
/**
****************************************************************************************
* @brief Callback to response 'READ' from peer device (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] attidx SESS attribute index, converted with 'handle'
* @param[in] handle SESS attribute handle to send read cfm
*
* @return Length of value been READ
****************************************************************************************
*/
void ptss_cb_read(uint8_t conidx, uint8_t attidx, uint16_t handle);
/**
****************************************************************************************
* @brief Callback on enabled client config from peer device via WQ (__weak func)
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void ptss_cb_ccc(uint8_t conidx, uint8_t cli_cfg);
#endif /* PRF_PTSS_H_ */

370
ble/prf/prf_scps.c Normal file
View File

@ -0,0 +1,370 @@
/**
****************************************************************************************
*
* @file prf_scps.c
*
* @brief Scan Parameters Profile Server Role.
*
****************************************************************************************
*/
#if (PRF_SCPS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "prf_scps.h"
#if (DBG_SCPS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<SCPS>" format "\r\n", ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Scan Interval Window Value length @see struct scp_scan_intv_wd
#define SCP_SCAN_INTV_WD_LEN (0x04)
/// Macro for Client Config value operation
#define SCP_NTF_CFG_GET(conidx) \
((scps_env.ntf_bits >> (conidx)) & (PRF_CLI_START_NTF))
#define SCP_NTF_CFG_CLR(conidx) \
scps_env.ntf_bits &= ~((PRF_CLI_START_NTF) << (conidx))
#define SCP_NTF_CFG_SET(conidx, conf) \
scps_env.ntf_bits = (scps_env.ntf_bits & ~((PRF_CLI_START_NTF) << (conidx))) | ((conf) << (conidx))
/// Requires scan refresh
enum spcs_refresh
{
SCPS_REQUIRES_REFRESH = 0x00,
};
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
/// SCP Server Environment Variable
typedef struct scps_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// Database configuration @see scp_features
uint8_t features;
// Notification config of peer devices, each 1-bit.
uint8_t ntf_bits;
} scps_env_t;
/// Global Variable Declarations
scps_env_t scps_env;
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// Attributes configure @see enum scp_att_index
#define SCP_CFG_ATT_MANDATORY_MASK 0x07
#define SCP_CFG_ATT_SCAN_REFRESH_MASK 0x38
/// Attributes Indexes
enum scp_att_index
{
// Service Declaration, *MUST* Start at 0
SCP_IDX_SVC,
// Scan Interval Window Char.
SCP_IDX_SCAN_INTV_WD_CHAR,
SCP_IDX_SCAN_INTV_WD_VAL,
// Scan Refresh Char.
SCP_IDX_SCAN_REFRESH_CHAR,
SCP_IDX_SCAN_REFRESH_VAL,
SCP_IDX_SCAN_REFRESH_NTF_CFG,
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
SCP_IDX_NB,
};
/// Full SCP Description
const att_decl_t scp_atts[] =
{
// Scan Interval Window Char. Declaration and Value
ATT_ELMT_DECL_CHAR( SCP_IDX_SCAN_INTV_WD_CHAR ),
// Scan Interval Window Characteristic Value
ATT_ELMT( SCP_IDX_SCAN_INTV_WD_VAL, ATT_CHAR_SCAN_INTV_WD, PROP_WC, SCP_SCAN_INTV_WD_LEN ),
// Scan Refresh Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( SCP_IDX_SCAN_REFRESH_CHAR ),
ATT_ELMT( SCP_IDX_SCAN_REFRESH_VAL, ATT_CHAR_SCAN_REFRESH, PROP_NTF, 0 ),
ATT_ELMT_DESC_CLI_CHAR_CFG( SCP_IDX_SCAN_REFRESH_NTF_CFG ),
};
const struct svc_decl scp_svc_db =
{
.uuid = ATT_SVC_SCAN_PARAMETERS,
.info = SVC_UUID(16),
.atts = scp_atts,
.nb_att = SCP_IDX_NB - 1,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve attribute handle from idx @see scp_att_index
#define scps_get_att_handle(idx) (scps_env.start_hdl + (idx))
/// Retrieve attribute index form handle
#define scps_get_att_idx(handle) (handle - scps_env.start_hdl)
/// Handles reception of the atts request from peer device
static void scps_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t att_idx = scps_get_att_idx(handle);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,att:%d)", conidx, opcode, handle, att_idx);
switch (opcode)
{
case ATTS_READ_REQ:
{
DEBUG("read_req(cid:%d,hdl:0x%x)", conidx, param->handle);
// Scan Refresh Notification Configuration
if (att_idx == SCP_IDX_SCAN_REFRESH_NTF_CFG)
{
if((scps_env.features & SCP_SCAN_REFRESH_SUP) != 0)
{
uint16_t cli_cfg = SCP_NTF_CFG_GET(conidx);;
DEBUG(" read_cfm(txd_ntf:%d)", cli_cfg);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
break;
}
}
// Send error response
gatt_read_cfm(conidx, PRF_ERR_APP_ERROR, handle, 0, NULL);
} break;
case ATTS_WRITE_REQ:
{
const struct atts_write_ind *ind = param;
DEBUG(" write_req(hdl:0x%x,att:%d,wr:0x%x,len:%d)", handle, att_idx, ind->wrcode, ind->length);
// Scan Interval Window Value
if (att_idx == SCP_IDX_SCAN_INTV_WD_VAL)
{
uint16_t scan_intv = read16(&ind->value[0]); // value align=2
uint16_t scan_window = read16(&ind->value[2]);
// Check interval and window validity
if ((scan_window <= scan_intv)
&& (scan_window <= SCP_SCAN_WINDOW_MAX) && (scan_window >= SCP_SCAN_WINDOW_MIN)
&& (scan_intv <= SCP_SCAN_INTERVAL_MAX) && (scan_intv >= SCP_SCAN_INTERVAL_MIN))
{
// Send write conform first!
gatt_write_cfm(conidx, LE_SUCCESS, handle);
scps_cb_scan_param(conidx, scan_intv, scan_window);
break;
}
}
// Scan Refresh Notification Configuration
else if (att_idx == SCP_IDX_SCAN_REFRESH_NTF_CFG)
{
// Check if Scan Refresh Characteristic is supported
if ((scps_env.features & SCP_SCAN_REFRESH_SUP) != 0)
{
uint8_t ntf_cfg = ind->value[0]; // 2bytes, only LSB used
// Only update configuration if value for stop or notification enable
if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
{
DEBUG(" NTF_CFG(cid:%d,cfg:%d)", conidx, ntf_cfg);
SCP_NTF_CFG_SET(conidx, ntf_cfg);
// Send write conform quickly!
gatt_write_cfm(conidx, LE_SUCCESS, handle);
break;
}
}
}
// Send write conform with error!
gatt_write_cfm(conidx, PRF_ERR_APP_ERROR, handle);
} break;
case ATTS_INFO_REQ:
{
uint8_t status = LE_SUCCESS;
uint16_t length = 0;
if (att_idx == SCP_IDX_SCAN_REFRESH_NTF_CFG)
{
length = sizeof(uint16_t); // CCC attribute
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
// Send length-info confirm for prepWR judging.
DEBUG(" info_cfm(hdl:0x%x,att:%d,sta:0x%X,len:%d)", handle, att_idx, status, length);
gatt_info_cfm(conidx, status, handle, length);
} break;
case ATTS_CMP_EVT:
{
const struct atts_cmp_evt *evt = param;
DEBUG(" cmp_evt(op:0x%x,sta:0x%x)", evt->operation, evt->status);
// add 'if' to avoid warning #117-D: "evt" never referenced
if (evt->operation == GATT_NOTIFY)
{
// Notify result
}
} break;
default:
{
// nothing to do
} break;
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Scan Parameters Profile in the DB
* Customize via pre-define @see SCP_START_HDL @see SCP_FEATURES
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t scps_svc_init(void)
{
uint8_t status = LE_SUCCESS;
uint8_t cfg_att = SCP_CFG_ATT_MANDATORY_MASK;
// Init Environment
scps_env.start_hdl = SCP_START_HDL;
scps_env.features = SCP_FEATURES;
scps_env.ntf_bits = 0;
// Compute Attributes supported
if (scps_env.features & SCP_SCAN_REFRESH_SUP)
{
cfg_att |= SCP_CFG_ATT_SCAN_REFRESH_MASK;
}
// Create Service in database
status = attmdb_svc_create(&scps_env.start_hdl, (uint8_t *)&cfg_att, &scp_svc_db, scps_svc_func);
DEBUG("svc_init(sta:0x%X,shdl:%d,feat:0x%X,cfg:0x%X)",
status, scps_env.start_hdl, scps_env.features, cfg_att);
return status;
}
/**
****************************************************************************************
* @brief Enable SCP Notification Configurations
*
* @param[in] conidx Connection index
* @param[in] ntf_cfg Scan Refresh Notification Config @see prf_cli_conf
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
void scps_set_ccc(uint8_t conidx, uint8_t ntf_cfg)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
SCP_NTF_CFG_SET(conidx, ntf_cfg);
}
}
/**
****************************************************************************************
* @brief Send a scan refresh to peer device via NTF
*
* @param[in] conidx Connection index
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t scps_scan_refresh(uint8_t conidx)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
// check if Notification supported
if (scps_env.features & SCP_SCAN_REFRESH_SUP)
{
if (SCP_NTF_CFG_GET(conidx) != PRF_CLI_STOP_NTFIND)
{
// send notification to peer device
uint8_t req = SCPS_REQUIRES_REFRESH;
DEBUG("Refresh Send");
gatt_ntf_send(conidx, scps_get_att_handle(SCP_IDX_SCAN_REFRESH_VAL), sizeof(uint8_t), &req);
status = LE_SUCCESS;
}
else
{
status = PRF_ERR_NTF_DISABLED;
}
}
return (status);
}
/**
****************************************************************************************
* @brief Callback on received scan params from peer device via WC (__weak func)
*
* @param[in] conidx Connection index
* @param[in] scan_intv Scan interval value
* @param[in] scan_wd Scan window value
*
****************************************************************************************
*/
__weak void scps_cb_scan_param(uint8_t conidx, uint16_t scan_intv, uint16_t scan_wd)
{
DEBUG("SCAN_PARAM(cid:%d,intv:%d,winw:%d)", conidx, scan_intv, scan_wd);
}
#endif //PRF_SCPS

101
ble/prf/prf_scps.h Normal file
View File

@ -0,0 +1,101 @@
/**
****************************************************************************************
*
* @file prf_scps.h
*
* @brief Header file - Scan Parameters Profile Server.
*
****************************************************************************************
*/
#ifndef PRF_SCPS_H_
#define PRF_SCPS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Server Start Handle(0 = dynamically allocated)
#if !defined(SCP_START_HDL)
#define SCP_START_HDL (0)
#endif
/// Scan Refresh Characteristic(Support or Not)
#if !defined(SCP_FEATURES)
#define SCP_FEATURES (SCP_SCAN_REFRESH_SUP)
#endif
/// Scanning set parameters range min
#define SCP_SCAN_INTERVAL_MIN 0x04
/// Scanning set parameters range max
#define SCP_SCAN_INTERVAL_MAX 0x4000
/// Scanning set parameters range min
#define SCP_SCAN_WINDOW_MIN 0x04
/// Scanning set parameters range max
#define SCP_SCAN_WINDOW_MAX 0x4000
/// Features Flag Masks
enum scp_features
{
/// Scan Refresh Characteristic is not supported
SCP_SCAN_REFRESH_NOT_SUP = 0,
/// Scan Refresh Characteristic is supported
SCP_SCAN_REFRESH_SUP,
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Scan Parameters Profile in the DB
* Customize via pre-define @see SCP_START_HDL @see SCP_FEATURES
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t scps_svc_init(void);
/**
****************************************************************************************
* @brief Enable SCP Notification Configurations
*
* @param[in] conidx Connection index
* @param[in] ntf_cfg Scan Refresh Notification Config @see prf_cli_conf
****************************************************************************************
*/
void scps_set_ccc(uint8_t conidx, uint8_t ntf_cfg);
/**
****************************************************************************************
* @brief Send a scan refresh to peer device via NTF
*
* @param[in] conidx Connection index
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t scps_scan_refresh(uint8_t conidx);
/**
****************************************************************************************
* @brief Callback on received scan params from peer device via WC (__weak func)
*
* @param[in] conidx Connection index
* @param[in] scan_intv Scan interval value
* @param[in] scan_wd Scan window value
*
****************************************************************************************
*/
void scps_cb_scan_param(uint8_t conidx, uint16_t scan_intv, uint16_t scan_wd);
#endif /* PRF_SCPS_H_ */

485
ble/prf/prf_sess.c Normal file
View File

@ -0,0 +1,485 @@
/**
****************************************************************************************
*
* @file prf_sess.c
*
* @brief Serial Service - Server Role Implementation.
*
* < If want to modify it, recommend to copy the file to 'user porject'/src >
****************************************************************************************
*/
#if (PRF_SESS)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "prf.h"
#include "prf_sess.h"
#if (DBG_SESS)
#include "dbg.h"
#define DEBUG(format, ...) debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
/*
* DEFINITIONS
****************************************************************************************
*/
/// Max length of received once
#if !defined(SES_RXD_MAX_LEN)
#define SES_RXD_MAX_LEN (0x200)
#endif
/// Max number of notify/indicate pkt
#if !defined(SES_NB_PKT_MAX)
#define SES_NB_PKT_MAX (5)
#endif
/// Version String for SES_IDX_READ_VAL Read
#define SES_VERS_STR ("Ver:1.25")
#define SES_VERS_STR_LEN (sizeof(SES_VERS_STR) - 1)
/// Macro for Client Config value operation
#define SES_NTF_CFG_GET(conidx) \
((sess_env.ntf_bits >> (conidx*2)) & (PRF_CLI_START_NTF | PRF_CLI_START_IND))
#define SES_NTF_CFG_CLR(conidx) \
sess_env.ntf_bits &= ~((PRF_CLI_START_NTF | PRF_CLI_START_IND) << (conidx*2))
#define SES_NTF_CFG_SET(conidx, conf) \
sess_env.ntf_bits = (sess_env.ntf_bits & ~((PRF_CLI_START_NTF | PRF_CLI_START_IND) << (conidx*2))) | ((conf) << (conidx*2))
/**
****************************************************************************************
* @section ENVIRONMENT DEFINITION
****************************************************************************************
*/
/// Server Environment Variable
typedef struct sess_env_tag
{
// Service Start Handle
uint16_t start_hdl;
// Client Config of peer devices - each 2Bits(NTF & IND), so max_peer=8.
uint16_t ntf_bits;
// Number of notify pkt
uint8_t nb_pkt;
} sess_env_t;
/// Global Variable Declarations
sess_env_t sess_env;
/**
****************************************************************************************
* @section ATTRIBUTES DEFINITION
****************************************************************************************
*/
/// Attributes Index
enum ses_att_idx
{
// Service Declaration, *MUST* Start at 0
SES_IDX_SVC,
// Serial TXD Char.
SES_IDX_TXD_CHAR,
SES_IDX_TXD_VAL,
SES_IDX_TXD_NTF_CFG,
// Serial RXD Char.
SES_IDX_RXD_CHAR,
SES_IDX_RXD_VAL, //5
#if (SES_READ_SUP)
// Serial READ Char.
SES_IDX_READ_CHAR,
SES_IDX_READ_VAL,
#endif
// Max Index, *NOTE* Minus 1(Svc Decl) is .nb_att
SES_IDX_NB,
};
#if (SES_UUID_128)
/// Characteristic Base UUID128 (User Customize)
#define SES_ATT_UUID128(uuid) { 0x16, 0x0A, 0x10, 0x40, 0xD1, 0x9F, 0x4C, 0x6C, \
0xB4, 0x55, 0xE3, 0xF7, (uuid) & 0xFF, (uuid >> 8) & 0xFF, 0x00, 0x00 }
/// Serial Service UUID128
const uint8_t ses_svc_uuid[] = SES_ATT_UUID128(0xFF00);
/// Serial Notify UUID128
const uint8_t ses_char_txd_notify[] = SES_ATT_UUID128(0xFF01);
/// Serial Write Command UUID128
const uint8_t ses_char_rxd_write[] = SES_ATT_UUID128(0xFF02);
/// Serial Read Command UUID128
const uint8_t ses_char_val_read[] = SES_ATT_UUID128(0xFF03);
/// Attributes Description
const att_decl_t ses_atts[] =
{
// Serial Notify Char. Declaration and Value and Client Char. Configuration Descriptor
ATT_ELMT_DECL_CHAR( SES_IDX_TXD_CHAR ),
ATT_ELMT128( SES_IDX_TXD_VAL, ses_char_txd_notify, PROP_NTF | PROP_IND, 0 ),
ATT_ELMT_DESC_CLI_CHAR_CFG( SES_IDX_TXD_NTF_CFG ),
// Serial Write Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( SES_IDX_RXD_CHAR ),
ATT_ELMT128( SES_IDX_RXD_VAL, ses_char_rxd_write, PROP_WC | PROP_WR, SES_RXD_MAX_LEN ),
#if (SES_READ_SUP)
// Serial Read Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( SES_IDX_READ_CHAR ),
ATT_ELMT128( SES_IDX_READ_VAL, ses_char_val_read, PROP_RD, 0 ),
#endif //(SES_READ_SUP)
};
/// Service Description
const struct svc_decl ses_svc_db =
{
{.uuid128 = ses_svc_uuid},
.info = SVC_UUID(128),
.atts = ses_atts,
.nb_att = SES_IDX_NB - 1,
};
#else //(SESS_UUID16)
/// Serial Service UUID
#define SES_SVC_UUID ATT_UUID16(0xFF00)
/// Serial Notify UUID
#define SES_CHAR_TXD_NOTIFY ATT_UUID16(0xFF01)
/// Serial Write Command UUID
#define SES_CHAR_RXD_WRITE ATT_UUID16(0xFF02)
/// Serial Read Command UUID
#define SES_CHAR_VAL_READ ATT_UUID16(0xFF03)
/// Attributes Description
const att_decl_t ses_atts[] =
{
// Serial Notify Char. Declaration and Value and CCC Descriptor
ATT_ELMT_DECL_CHAR( SES_IDX_TXD_CHAR ),
ATT_ELMT( SES_IDX_TXD_VAL, SES_CHAR_TXD_NOTIFY, PROP_NTF | PROP_IND, 0 ),
ATT_ELMT_DESC_CLI_CHAR_CFG( SES_IDX_TXD_NTF_CFG ),
// Serial Write Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( SES_IDX_RXD_CHAR ),
ATT_ELMT( SES_IDX_RXD_VAL, SES_CHAR_RXD_WRITE, PROP_WC | PROP_WR, SES_RXD_MAX_LEN ),
#if (SES_READ_SUP)
// Serial Read Command Char. Declaration and Value
ATT_ELMT_DECL_CHAR( SES_IDX_READ_CHAR ),
ATT_ELMT( SES_IDX_READ_VAL, SES_CHAR_VAL_READ, PROP_RD, 0 ),
#endif //(SES_READ_SUP)
};
/// Service Description
const struct svc_decl ses_svc_db =
{
.uuid = SES_SVC_UUID,
.info = SVC_UUID(16),
.atts = ses_atts,
.nb_att = SES_IDX_NB - 1,
};
#endif
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @section SVC FUNCTIONS
****************************************************************************************
*/
/// Retrieve attribute handle from index (@see ses_att_idx)
static uint16_t sess_get_att_handle(uint8_t att_idx)
{
ASSERT_ERR(att_idx < SES_IDX_NB);
return att_idx + sess_env.start_hdl;
}
/// Retrieve attribute index form handle
static uint8_t sess_get_att_idx(uint16_t handle)
{
ASSERT_ERR((handle >= sess_env.start_hdl) && (handle < sess_env.start_hdl + SES_IDX_NB));
return handle - sess_env.start_hdl;
}
/// Handles reception of the atts request from peer device
static void sess_svc_func(uint8_t conidx, uint8_t opcode, uint16_t handle, const void *param)
{
uint8_t att_idx = sess_get_att_idx(handle);
DEBUG("svc_func(cid:%d,op:0x%x,hdl:0x%x,att:%d)", conidx, opcode, handle, att_idx);
switch (opcode)
{
case ATTS_READ_REQ:
{
if (att_idx == SES_IDX_TXD_NTF_CFG)
{
// retrieve notification config
uint16_t cli_cfg = SES_NTF_CFG_GET(conidx);
DEBUG(" read_cfm(txd_ntf:%d)", cli_cfg);
gatt_read_cfm(conidx, LE_SUCCESS, handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
break;
}
#if (SES_READ_SUP)
if (att_idx == SES_IDX_READ_VAL)
{
sess_cb_rdv(conidx, att_idx, handle);
break;
}
#endif //(SES_READ_SUP)
// Send error response
gatt_read_cfm(conidx, PRF_ERR_APP_ERROR, handle, 0, NULL);
} break;
case ATTS_WRITE_REQ:
{
const struct atts_write_ind *ind = param;
DEBUG(" write_req(hdl:0x%x,att:%d,wr:0x%x,len:%d)", handle, att_idx, ind->wrcode, ind->length);
if (att_idx == SES_IDX_RXD_VAL)
{
// Send write conform first!
if (!ind->more) gatt_write_cfm(conidx, LE_SUCCESS, handle);
// Next to process data received
sess_cb_rxd(conidx, ind->length, ind->value);
break;
}
if (att_idx == SES_IDX_TXD_NTF_CFG)
{
if ((!ind->more) && (ind->length == sizeof(uint16_t)))
{
uint16_t cli_cfg = read16p(ind->value);
// update configuration if value for stop or NTF/IND start
if (cli_cfg <= PRF_CLI_START_IND)
{
DEBUG(" set txd_ntf(cid:%d,cfg:%d)", conidx, cli_cfg);
SES_NTF_CFG_SET(conidx, cli_cfg);
// Send write conform quickly!
gatt_write_cfm(conidx, LE_SUCCESS, handle);
#if (SES_CLI_CFG)
// Next to process cli_cfg changed
sess_cb_ccc(conidx, cli_cfg);
#endif //(SES_CLI_CFG)
break;
}
}
}
// Send write conform with error!
gatt_write_cfm(conidx, PRF_ERR_APP_ERROR, handle);
} break;
case ATTS_INFO_REQ:
{
uint8_t status = LE_SUCCESS;
uint16_t length = 0;
if (att_idx == SES_IDX_RXD_VAL)
{
length = SES_RXD_MAX_LEN; // accepted length
}
else if (att_idx == SES_IDX_TXD_NTF_CFG)
{
length = sizeof(uint16_t); // CCC attribute
}
else
{
status = ATT_ERR_WRITE_NOT_PERMITTED;
}
// Send length-info confirm for prepWR judging.
DEBUG(" info_cfm(hdl:0x%x,att:%d,sta:0x%X,len:%d)", handle, att_idx, status, length);
gatt_info_cfm(conidx, status, handle, length);
} break;
case ATTS_CMP_EVT:
{
const struct atts_cmp_evt *evt = param;
sess_env.nb_pkt++; // release
DEBUG(" cmp_evt(op:0x%x,sta:0x%x,nb:%d)", evt->operation, evt->status, sess_env.nb_pkt);
// add 'if' to avoid warning #117-D: "evt" never referenced
if (evt->operation == GATT_NOTIFY)
{
// Notify result
}
} break;
default:
{
// nothing to do
} break;
}
}
/**
****************************************************************************************
* @section API FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Serial Service Profile in the DB.
* Customize via pre-define @see SES_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t sess_svc_init(void)
{
uint8_t status = LE_SUCCESS;
// Init Environment
sess_env.start_hdl = SES_START_HDL;
sess_env.nb_pkt = SES_NB_PKT_MAX;
sess_env.ntf_bits = 0;
// Create Service in database
status = attmdb_svc_create(&sess_env.start_hdl, NULL, &ses_svc_db, sess_svc_func);
DEBUG("svc_init(sta:0x%X,shdl:%d,nb_pkt:%d,ntf_bits:0x%X)",
status, sess_env.start_hdl, sess_env.nb_pkt, sess_env.ntf_bits);
return status;
}
/**
****************************************************************************************
* @brief Enable setting client configuration characteristics
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void sess_set_ccc(uint8_t conidx, uint8_t cli_cfg)
{
//if (gapc_get_conhdl(conidx) != GAP_INVALID_CONHDL)
{
// update configuration
SES_NTF_CFG_SET(conidx, cli_cfg);
}
}
/**
****************************************************************************************
* @brief Transmit data to peer device via NTF or IND
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t sess_txd_send(uint8_t conidx, uint16_t len, const uint8_t* data)
{
uint8_t status = PRF_ERR_REQ_DISALLOWED;
if ((len > 0) && (sess_env.nb_pkt > 0))
{
uint8_t ntf_cfg = SES_NTF_CFG_GET(conidx);
if (ntf_cfg != PRF_CLI_STOP_NTFIND)
{
status = LE_SUCCESS;
gatt_ntf_send(conidx, sess_get_att_handle(SES_IDX_TXD_VAL), len, data);
sess_env.nb_pkt--; // allocate
DEBUG("txd_send(len:%d,nb:%d)", len, sess_env.nb_pkt);
}
else
{
status = PRF_ERR_NTF_DISABLED;
}
}
return status;
}
/**
****************************************************************************************
* @brief Callback on received data from peer device via WC or WQ (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
****************************************************************************************
*/
__weak void sess_cb_rxd(uint8_t conidx, uint16_t len, const uint8_t *data)
{
debugHex(data, len);
// Loopback to txd, just test.
//sess_txd_send(conidx, len, data);
}
#if (SES_READ_SUP)
/**
****************************************************************************************
* @brief Callback to response 'READ' from peer device (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] attidx SESS attribute index, converted with 'handle'
* @param[in] handle SESS attribute handle to send read cfm
*
* @return Length of value been READ
****************************************************************************************
*/
__weak void sess_cb_rdv(uint8_t conidx, uint8_t attidx, uint16_t handle)
{
uint16_t length = SES_VERS_STR_LEN;
const uint8_t *p_data = (const uint8_t *)SES_VERS_STR;
DEBUG(" read_cfm(att:%d, len:%d)", attidx, length);
gatt_read_cfm(conidx, LE_SUCCESS, handle, length, p_data);
}
#endif //(SES_READ_SUP)
#if (SES_CLI_CFG)
/**
****************************************************************************************
* @brief Callback on enabled client config from peer device via WQ (__weak func)
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
__weak void sess_cb_ccc(uint8_t conidx, uint8_t cli_cfg)
{
// user override
}
#endif //(SES_CLI_CFG)
#endif //PRF_SESS

119
ble/prf/prf_sess.h Normal file
View File

@ -0,0 +1,119 @@
/**
****************************************************************************************
*
* @file prf_sess.h
*
* @brief Header file - Serial Service Profile (Server Role).
*
****************************************************************************************
*/
#ifndef PRF_SESS_H_
#define PRF_SESS_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Service Start Handle(0 = dynamically allocated)
#if !defined(SES_START_HDL)
#define SES_START_HDL (0)
#endif
/// Use UUID 128bit or 16bit
#if !defined(SES_UUID_128)
#define SES_UUID_128 (0)
#endif
/// Support READ Characteristic
#if !defined(SES_READ_SUP)
#define SES_READ_SUP (0)
#endif
/// Callback of Client Config enable
#if !defined(SES_CLI_CFG)
#define SES_CLI_CFG (0)
#endif
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Add Serial Service Profile in the DB.
* Customize via pre-define @see SES_START_HDL
*
* @return Result status, LE_SUCCESS or Error Reason
****************************************************************************************
*/
uint8_t sess_svc_init(void);
/**
****************************************************************************************
* @brief Enable setting client configuration characteristics
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void sess_set_ccc(uint8_t conidx, uint8_t cli_cfg);
/**
****************************************************************************************
* @brief Transmit data to peer device via NTF or IND
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
*
* @return Status of the operation @see prf_err
****************************************************************************************
*/
uint8_t sess_txd_send(uint8_t conidx, uint16_t len, const uint8_t *data);
/**
****************************************************************************************
* @brief Callback on received data from peer device via WC or WQ (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] len Length of data
* @param[in] data pointer of buffer
****************************************************************************************
*/
void sess_cb_rxd(uint8_t conidx, uint16_t len, const uint8_t *data);
#if (SES_READ_SUP)
/**
****************************************************************************************
* @brief Callback to response 'READ' from peer device (__weak func)
*
* @param[in] conidx peer device connection index
* @param[in] attidx SESS attribute index, converted with 'handle'
* @param[in] handle SESS attribute handle to send read cfm
*
* @return Length of value been READ
****************************************************************************************
*/
void sess_cb_rdv(uint8_t conidx, uint8_t attidx, uint16_t handle);
#endif
#if (SES_CLI_CFG)
/**
****************************************************************************************
* @brief Callback on enabled client config from peer device via WQ (__weak func)
*
* @param[in] conidx Connection index
* @param[in] cli_cfg Client configuration @see prf_cli_conf
****************************************************************************************
*/
void sess_cb_ccc(uint8_t conidx, uint8_t cli_cfg);
#endif
#endif /* PRF_SESS_H_ */

133
core/b6x.h Normal file
View File

@ -0,0 +1,133 @@
#ifndef _B6X_H_
#define _B6X_H_
/*
* ==========================================================================
* ---------- Interrupt Number Definition -----------------------------------
* ==========================================================================
*/
typedef enum IRQn
{
/****** Cortex-M0 Processor Exceptions Numbers *************************************************/
NMI_IRQn = -14, /*!< 2 Non Maskable Interrupt */
HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */
/****** Cortex-M0 specific Interrupt Numbers **********************************************/
EXTI_IRQn = 0, /* 0 | EXTI Interrupt */
IWDT_IRQn = 1, /* 1 | IWDT Interrupt */
BLE_IRQn = 2, /* 2 | BLE Interrupt */
DMAC_IRQn = 3, /* 3 | DMAC Interrupt */
BB_LP_IRQn = 4, /* 4 | BB WAKEUP Interrupt */
BTMR_IRQn = 5, /* 5 | BTMR Interrupt */
CTMR_IRQn = 6, /* 6 | CTMR Interrupt */
ATMR_IRQn = 7, /* 7 | ATMR Interrupt */
RTC_IRQn = 8, /* 8 | RTC Interrupt */
I2C_IRQn = 9, /* 9 | I2C Interrupt */
SPIM_IRQn = 10, /* 10 | SPIM Interrupt */
SPIS_IRQn = 11, /* 11 | SPIS Interrupt */
UART1_IRQn = 12, /* 12 | UART1 Interrupt */
UART2_IRQn = 13, /* 13 | UART2 Interrupt */
AON_PMU_IRQn = 14, /* 14 | AON_PMU Interrupt */
LVD33_IRQn = 15, /* 15 | LVD33 Interrupt */
BOD12_IRQn = 16, /* 16 | BOD12 Interrupt */
USB_IRQn = 17, /* 17 | USB Interrupt */
USB_SOF_IRQn = 18, /* 18 | USB_SOF Interrupt */
FSHC_IRQn = 19, /* 19 | FSHC Interrupt */
MDM_IRQn = 20, /* 20 | Interrupt */
RF_IRQn = 21, /* 21 | Interrupt */
} IRQn_Type;
#define __IRQFN __attribute__((section("ram_func")))
/*
* ==========================================================================
* ----------- Processor and Core Peripheral Section ------------------------
* ==========================================================================
*/
/* Configuration of the Cortex-M0 Processor and Core Peripherals */
#define __MPU_PRESENT 0 /*!< cm0ikmcu does not provide a MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< cm0ikmcu Supports 2 Bits for the Priority Levels */
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
#if (1)
#define __VTOR_PRESENT 1
#include "core_cm0plus.h" /* Cortex-M0 plus processor and core peripherals */
#else
#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */
#endif
#if defined ( __CC_ARM )
#pragma anon_unions
#pragma diag_suppress 1296
#endif
/* SYSTICK - Cortex-M0 SysTick Register */
typedef struct
{
__IO uint32_t CSR; //0x0, Control and Status
__IO uint32_t RVR; //0x4, Reload Value
__IO uint32_t CVR; //0x8, Current Value
__IO uint32_t CALIB; //0xC, Calibration
} TICK_TypeDef;
/***************************************************************************/
/* Peripheral Memory map */
/***************************************************************************/
#define BOOTROM_BASE ((uint32_t)0x00000000) // Boot Memory (4KB)
#define FLASH_BASE ((uint32_t)0x18000000) // FLASH Controller (16MB)
#define CACHE_REG_BASE ((uint32_t)0x19000000) // CACHE Reg (4KB)
#define SRAM_BASE ((uint32_t)0x20003000) // SRAM Memory (20KB)
#define RETN_BASE ((uint32_t)0x20008000) // BLE EM Memory (8KB)
#define AHB_BASE ((uint32_t)0x40000000) // AHB Peripheral (64KB)
#define APB1_BASE ((uint32_t)0x40020000) // APB Peripheral (64KB)
#define APB2_BASE ((uint32_t)0x40030000) // APB Peripheral (64KB)
/*
* ==========================================================================
* ---------------------------- Common MACRO ------------------------------
* ==========================================================================
*/
/** @brief Enable interrupts globally in the system.
* This macro must be used when the initialization phase is over and the interrupts
* can start being handled by the system.
*/
#define GLOBAL_INT_START() __enable_irq() //__set_PRIMASK(0)
/** @brief Disable interrupts globally in the system.
* This macro must be used when the system wants to disable all the interrupt
* it could handle.
*/
#define GLOBAL_INT_STOP() __disable_irq() //__set_PRIMASK(1)
/** @brief Disable interrupts globally in the system.
* This macro must be used in conjunction with the @ref GLOBAL_INT_RESTORE macro since this
* last one will close the brace that the current macro opens. This means that both
* macros must be located at the same scope level.
*/
#define GLOBAL_INT_DISABLE() \
do { \
uint32_t __l_irq_rest = __get_PRIMASK(); \
__disable_irq();
/** @brief Restore interrupts from the previous global disable.
* @sa GLOBAL_INT_DISABLE
*/
//if (__l_irq_rest == 0) __enable_irq();
#define GLOBAL_INT_RESTORE() \
__set_PRIMASK(__l_irq_rest); \
} while(0)
#define WR_8(addr,value) (*(volatile uint8_t *)(addr)) = (value)
#define WR_32(addr,value) (*(volatile uint32_t *)(addr)) = (value)
#define RD_32(addr) (*(volatile uint32_t *)(addr))
#include "rom.h"
#endif //_B6X_H_

798
core/core_cm0.h Normal file
View File

@ -0,0 +1,798 @@
/**************************************************************************//**
* @file core_cm0.h
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
* @version V4.30
* @date 20. October 2015
******************************************************************************/
/* Copyright (c) 2009 - 2015 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CORE_CM0_H_GENERIC
#define __CORE_CM0_H_GENERIC
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
\page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
CMSIS violates the following MISRA-C:2004 rules:
\li Required Rule 8.5, object/function definition in header file.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
Function-like macros are used to allow more efficient code.
*/
/*******************************************************************************
* CMSIS definitions
******************************************************************************/
/**
\ingroup Cortex_M0
@{
*/
/* CMSIS CM0 definitions */
#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
__CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
#define __CORTEX_M (0x00U) /*!< Cortex-M Core */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
#define __STATIC_INLINE static inline
#elif defined ( __TMS470__ )
#define __ASM __asm /*!< asm keyword for TI CCS Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __CSMC__ )
#define __packed
#define __ASM _asm /*!< asm keyword for COSMIC Compiler */
#define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
#define __STATIC_INLINE static inline
#else
#error Unknown compiler
#endif
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
*/
#define __FPU_USED 0U
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#if defined __ARM_PCS_VFP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TMS470__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __CSMC__ )
#if ( __CSMC__ & 0x400U)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#include "core_cmInstr.h" /* Core Instruction Access */
#include "core_cmFunc.h" /* Core Function Access */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM0_H_GENERIC */
#ifndef __CMSIS_GENERIC
#ifndef __CORE_CM0_H_DEPENDANT
#define __CORE_CM0_H_DEPENDANT
#ifdef __cplusplus
extern "C" {
#endif
/* check device defines and use defaults */
#if defined __CHECK_DEVICE_DEFINES
#ifndef __CM0_REV
#define __CM0_REV 0x0000U
#warning "__CM0_REV not defined in device header file; using default!"
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 2U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0U
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CMSIS_glob_defs CMSIS Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
/*@} end of group Cortex_M0 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core NVIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/**
\defgroup CMSIS_core_register Defines and Type Definitions
\brief Type definitions and defines for Cortex-M processor based devices.
*/
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/**
\brief Union type to access the Application Program Status Register (APSR).
*/
typedef union
{
struct
{
uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} APSR_Type;
/* APSR Register Definitions */
#define APSR_N_Pos 31U /*!< APSR: N Position */
#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
#define APSR_Z_Pos 30U /*!< APSR: Z Position */
#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
#define APSR_C_Pos 29U /*!< APSR: C Position */
#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
#define APSR_V_Pos 28U /*!< APSR: V Position */
#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
/**
\brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
/* IPSR Register Definitions */
#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
/**
\brief Union type to access the Special-Purpose Program Status Registers (xPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} xPSR_Type;
/* xPSR Register Definitions */
#define xPSR_N_Pos 31U /*!< xPSR: N Position */
#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
#define xPSR_C_Pos 29U /*!< xPSR: C Position */
#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
#define xPSR_V_Pos 28U /*!< xPSR: V Position */
#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
/**
\brief Union type to access the Control Registers (CONTROL).
*/
typedef union
{
struct
{
uint32_t _reserved0:1; /*!< bit: 0 Reserved */
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CONTROL_Type;
/* CONTROL Register Definitions */
#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
/*@} end of group CMSIS_CORE */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
\brief Type definitions for the NVIC Registers
@{
*/
/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[31U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[31U];
uint32_t RESERVED4[64U];
__IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
} NVIC_Type;
/*@} end of group CMSIS_NVIC */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SCB System Control Block (SCB)
\brief Type definitions for the System Control Block Registers
@{
*/
/**
\brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
uint32_t RESERVED0;
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Application Interrupt and Reset Control Register Definitions */
#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
/* SCB System Control Register Definitions */
#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
/* SCB Configuration Control Register Definitions */
#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
/* SCB System Handler Control and State Register Definitions */
#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
/*@} end of group CMSIS_SCB */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
\brief Type definitions for the System Timer Registers.
@{
*/
/**
\brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
/*@} end of group CMSIS_SysTick */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
Therefore they are not covered by the Cortex-M0 header file.
@{
*/
/*@} end of group CMSIS_CoreDebug */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_bitfield Core register bit field macros
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
@{
*/
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
\param[in] value Value of the bit field.
\return Masked and shifted value.
*/
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
\param[in] value Value of register.
\return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of Cortex-M0 Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core NVIC Functions
- Core SysTick Functions
- Core Register Access Functions
******************************************************************************/
/**
\defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## NVIC functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
\brief Functions that manage interrupts and exceptions via the NVIC.
@{
*/
/* Interrupt Priorities are WORD accessible only under ARMv6M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
/**
\brief Enable External Interrupt
\details Enables a device-specific interrupt in the NVIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Disable External Interrupt
\details Disables a device-specific interrupt in the NVIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
{
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Get Pending Interrupt
\details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
\param [in] IRQn Interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
*/
__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
/**
\brief Set Pending Interrupt
\details Sets the pending bit of an external interrupt.
\param [in] IRQn Interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Clear Pending Interrupt
\details Clears the pending bit of an external interrupt.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Set Interrupt Priority
\details Sets the priority of an interrupt.
\note The priority cannot be set for every core interrupt.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
*/
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) < 0)
{
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
/**
\brief Get Interrupt Priority
\details Reads the priority of an interrupt.
The interrupt number can be positive to specify an external (device specific) interrupt,
or negative to specify an internal (core) interrupt.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) < 0)
{
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
__STATIC_INLINE void NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
for (;;) /* wait until reset */
{
__NOP();
}
}
/*@} end of CMSIS_Core_NVICFunctions */
/* ################################## SysTick function ############################################ */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
#endif
/*@} end of CMSIS_Core_SysTickFunctions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM0_H_DEPENDANT */
#endif /* __CMSIS_GENERIC */

813
core/core_cm0plus.h Normal file
View File

@ -0,0 +1,813 @@
/**************************************************************************//**
* @file core_cm0plus.h
* @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File
* @version V3.30
* @date 17. February 2014
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2014 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __CORE_CM0PLUS_H_GENERIC
#define __CORE_CM0PLUS_H_GENERIC
/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
CMSIS violates the following MISRA-C:2004 rules:
\li Required Rule 8.5, object/function definition in header file.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
Function-like macros are used to allow more efficient code.
*/
/*******************************************************************************
* CMSIS definitions
******************************************************************************/
/** \ingroup Cortex-M0+
@{
*/
/* CMSIS CM0P definitions */
#define __CM0PLUS_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */
#define __CM0PLUS_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */
#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16) | \
__CM0PLUS_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */
#define __CORTEX_M (0x00) /*!< Cortex-M Core */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
#define __STATIC_INLINE static inline
#elif defined ( __TMS470__ )
#define __ASM __asm /*!< asm keyword for TI CCS Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __CSMC__ ) /* Cosmic */
#define __packed
#define __ASM _asm /*!< asm keyword for COSMIC Compiler */
#define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */
#define __STATIC_INLINE static inline
#endif
/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all
*/
#define __FPU_USED 0
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TMS470__ )
#if defined __TI__VFP_SUPPORT____
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __CSMC__ ) /* Cosmic */
#if ( __CSMC__ & 0x400) // FPU present for parser
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#include <stdint.h> /* standard types definitions */
#include <core_cmInstr.h> /* Core Instruction Access */
#include <core_cmFunc.h> /* Core Function Access */
#endif /* __CORE_CM0PLUS_H_GENERIC */
#ifndef __CMSIS_GENERIC
#ifndef __CORE_CM0PLUS_H_DEPENDANT
#define __CORE_CM0PLUS_H_DEPENDANT
/* check device defines and use defaults */
#if defined __CHECK_DEVICE_DEFINES
#ifndef __CM0PLUS_REV
#define __CM0PLUS_REV 0x0000
#warning "__CM0PLUS_REV not defined in device header file; using default!"
#endif
#ifndef __MPU_PRESENT
#define __MPU_PRESENT 0
#warning "__MPU_PRESENT not defined in device header file; using default!"
#endif
#ifndef __VTOR_PRESENT
#define __VTOR_PRESENT 0
#warning "__VTOR_PRESENT not defined in device header file; using default!"
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 2
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CMSIS_glob_defs CMSIS Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/*@} end of group Cortex-M0+ */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core NVIC Register
- Core SCB Register
- Core SysTick Register
- Core MPU Register
******************************************************************************/
/** \defgroup CMSIS_core_register Defines and Type Definitions
\brief Type definitions and defines for Cortex-M processor based devices.
*/
/** \ingroup CMSIS_core_register
\defgroup CMSIS_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/** \brief Union type to access the Application Program Status Register (APSR).
*/
typedef union
{
struct
{
#if (__CORTEX_M != 0x04)
uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
#else
uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
#endif
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} APSR_Type;
/** \brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
#if (__CORTEX_M != 0x04)
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
#else
uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
#endif
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} xPSR_Type;
/** \brief Union type to access the Control Registers (CONTROL).
*/
typedef union
{
struct
{
uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CONTROL_Type;
/*@} end of group CMSIS_CORE */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
\brief Type definitions for the NVIC Registers
@{
*/
/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31];
__IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[31];
__IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31];
__IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[31];
uint32_t RESERVED4[64];
__IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
} NVIC_Type;
/*@} end of group CMSIS_NVIC */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_SCB System Control Block (SCB)
\brief Type definitions for the System Control Block Registers
@{
*/
/** \brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
#if (__VTOR_PRESENT == 1)
__IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
#else
uint32_t RESERVED0;
#endif
__IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
#if (__VTOR_PRESENT == 1)
/* SCB Interrupt Control State Register Definitions */
#define SCB_VTOR_TBLOFF_Pos 8 /*!< SCB VTOR: TBLOFF Position */
#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
#endif
/* SCB Application Interrupt and Reset Control Register Definitions */
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
/* SCB System Control Register Definitions */
#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
/* SCB Configuration Control Register Definitions */
#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
/* SCB System Handler Control and State Register Definitions */
#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
/*@} end of group CMSIS_SCB */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
\brief Type definitions for the System Timer Registers.
@{
*/
/** \brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */
/*@} end of group CMSIS_SysTick */
#if (__MPU_PRESENT == 1)
/** \ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
\brief Type definitions for the Memory Protection Unit (MPU)
@{
*/
/** \brief Structure type to access the Memory Protection Unit (MPU).
*/
typedef struct
{
__I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
__IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
__IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
__IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
__IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
} MPU_Type;
/* MPU Type Register */
#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */
#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */
#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */
#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */
/* MPU Control Register */
#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */
#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */
#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */
#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */
/* MPU Region Number Register */
#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */
#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */
/* MPU Region Base Address Register */
#define MPU_RBAR_ADDR_Pos 8 /*!< MPU RBAR: ADDR Position */
#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */
#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */
#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */
/* MPU Region Attribute and Size Register */
#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */
#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */
#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */
#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */
#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */
#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */
#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */
#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */
#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */
#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */
#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */
/*@} end of group CMSIS_MPU */
#endif
/** \ingroup CMSIS_core_register
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
\brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR)
are only accessible over DAP and not via processor. Therefore
they are not covered by the Cortex-M0 header file.
@{
*/
/*@} end of group CMSIS_CoreDebug */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of Cortex-M0+ Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
#if (__MPU_PRESENT == 1)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core NVIC Functions
- Core SysTick Functions
- Core Register Access Functions
******************************************************************************/
/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## NVIC functions #################################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
\brief Functions that manage interrupts and exceptions via the NVIC.
@{
*/
/* Interrupt Priorities are WORD accessible only under ARMv6M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
/** \brief Enable External Interrupt
The function enables a device-specific interrupt in the NVIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/** \brief Disable External Interrupt
The function disables a device-specific interrupt in the NVIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
{
NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/** \brief Get Pending Interrupt
The function reads the pending register in the NVIC and returns the pending bit
for the specified interrupt.
\param [in] IRQn Interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
*/
__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
}
/** \brief Set Pending Interrupt
The function sets the pending bit of an external interrupt.
\param [in] IRQn Interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/** \brief Clear Pending Interrupt
The function clears the pending bit of an external interrupt.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
}
/** \brief Set Interrupt Priority
The function sets the priority of an interrupt.
\note The priority cannot be set for every core interrupt.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
*/
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
else {
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
}
/** \brief Get Interrupt Priority
The function reads the priority of an interrupt. The interrupt
number can be positive to specify an external (device specific)
interrupt, or negative to specify an internal (core) interrupt.
\param [in] IRQn Interrupt number.
\return Interrupt Priority. Value is aligned automatically to the implemented
priority bits of the microcontroller.
*/
__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
{
if(IRQn < 0) {
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
else {
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
}
/** \brief System Reset
The function initiates a system reset request to reset the MCU.
*/
__STATIC_INLINE void NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
while(1); /* wait until reset */
}
/*@} end of CMSIS_Core_NVICFunctions */
/* ################################## SysTick function ############################################ */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if (__Vendor_SysTickConfig == 0)
/** \brief System Tick Configuration
The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
#endif
/*@} end of CMSIS_Core_SysTickFunctions */
#endif /* __CORE_CM0PLUS_H_DEPENDANT */
#endif /* __CMSIS_GENERIC */
#ifdef __cplusplus
}
#endif

637
core/core_cmFunc.h Normal file
View File

@ -0,0 +1,637 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V3.30
* @date 17. February 2014
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2014 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS for A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE for ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#ifndef __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1);
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i" : : : "memory");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i" : : : "memory");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f" : : : "memory");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f" : : : "memory");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
uint32_t result;
/* Empty asm statement works as a scheduling barrier */
__ASM volatile ("");
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
__ASM volatile ("");
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
/* Empty asm statement works as a scheduling barrier */
__ASM volatile ("");
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
__ASM volatile ("");
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
/* Cosmic specific functions */
#include <cmsis_csm.h>
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

687
core/core_cmInstr.h Normal file
View File

@ -0,0 +1,687 @@
/**************************************************************************//**
* @file core_cmInstr.h
* @brief CMSIS Cortex-M Core Instruction Access Header File
* @version V3.30
* @date 17. February 2014
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2014 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS for A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE for ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#ifndef __CORE_CMINSTR_H
#define __CORE_CMINSTR_H
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/** \brief Wait for Interrupt
Wait for Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
#define __WFI __wfi
/** \brief Wait for Event
Wait for Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) __strex(value, ptr)
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/* Define macros for porting to both thumb1 and thumb2.
* for thumb1, use low register (r0-r7), specified by constrant "l"
* Otherwise, use general registers, specified by constrant "r" */
#if defined (__thumb__) && !defined (__thumb2__)
#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
#define __CMSIS_GCC_USE_REG(r) "l" (r)
#else
#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
#define __CMSIS_GCC_USE_REG(r) "r" (r)
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
/** \brief Wait for Interrupt
Wait for Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
/** \brief Wait for Event
Wait for Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
{
__ASM volatile ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
{
__ASM volatile ("sev");
}
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
{
__ASM volatile ("isb");
}
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
{
__ASM volatile ("dsb");
}
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
{
__ASM volatile ("dmb");
}
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
return __builtin_bswap32(value);
#else
uint32_t result;
__ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
#endif
}
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
return (short)__builtin_bswap16(value);
#else
uint32_t result;
__ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
#endif
}
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
return (op1 >> op2) | (op1 << (32 - op2));
}
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __ASM volatile ("bkpt "#value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
__ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
#endif
return ((uint8_t) result); /* Add explicit type cast here */
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
__ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
#endif
return ((uint16_t) result); /* Add explicit type cast here */
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
return(result);
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
__ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
return(result);
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
__ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
return(result);
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
return(result);
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
{
__ASM volatile ("clrex" ::: "memory");
}
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
{
uint32_t result;
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return ((uint8_t) result); /* Add explicit type cast here */
}
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
/* Cosmic specific functions */
#include <cmsis_csm.h>
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H */

74
core/gnu/Makefile.common Normal file
View File

@ -0,0 +1,74 @@
SDK_ROOT ?= ../..
GNU_INSTALL_ROOT ?= $(SDK_ROOT)/tools/gcc-arm-none-eabi-10.3-2021.10
GNU_VERSION ?= 10.3.1
RM = rm -rf
## Selecting Core
CORTEX_M = 0
## Toolchain commands
GNU_PREFIX = arm-none-eabi
CC = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-gcc
CXX = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-c++
AS = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-as
AR = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ar -r
LD = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ld
NM = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-nm
OBJDUMP = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objdump
OBJCOPY = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objcopy
SIZE = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-size
STRIP = $(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-strip
## library file
LIBFILES ?= -lc_nano -lgcc -lnosys
## library path
LIBDIR += -L $(GNU_INSTALL_ROOT)/lib/gcc/arm-none-eabi/$(GNU_VERSION)/thumb/v6-m/nofp
LIBDIR += -L $(GNU_INSTALL_ROOT)/arm-none-eabi/lib/thumb/v6-m/nofp
LIBDIR += -L $(SDK_ROOT)/drivers/lib
## include
INC = $(GNU_INSTALL_ROOT)/arm-none-eabi/include
## Options for specific architecture
CORE = CM$(CORTEX_M)
ARCH_FLAGS = -mthumb -mcpu=cortex-m$(CORTEX_M)
## Startup code & linker script
STARTUP ?= $(SDK_ROOT)/core/gnu/startup.S
LINKER_SCRIPT ?= $(SDK_ROOT)/core/gnu/link_xip.ld
# Optimization flags
OPT ?= -Os -g
## C flags common to all targets
CFLAGS += $(OPT)
CFLAGS += $(ARCH_FLAGS)
# Generate .d file
#CFLAGS += -MP -MD
CFLAGS += -std=gnu11
CFLAGS += -Wall
#CFLAGS += -Werror
# close all warning
#CFLAGS += -w
CFLAGS += -msoft-float
# keep every function in a separate section, this allows linker to discard unused ones
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin -fshort-enums
## Assembler flags common to all targets
ASMFLAGS += $(ARCH_FLAGS)
# support ARM/Thumb interworking
ASMFLAGS += -mthumb-interwork
## Linker flags
LDFLAGS += $(OPT)
LDFLAGS += -T$(LINKER_SCRIPT) -nostdlib -EL
# Remove unused sections (on some targets)
LDFLAGS += --gc-sections
# Reduce code size by using target specific optimizations
LDFLAGS += --relax
# cross reference table
LDFLAGS += --cref

210
core/gnu/link_xip.ld Normal file
View File

@ -0,0 +1,210 @@
/* Linker script to configure memory regions.
* Need modifying for a specific board.
* FLASH.ORIGIN: starting address of flash
* FLASH.LENGTH: length of flash
* RAM.ORIGIN: starting address of RAM bank 0
* RAM.LENGTH: length of RAM bank 0
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x18008000, LENGTH = 0x38000
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x4000
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __copy_table_start__
* __copy_table_end__
* __zero_table_start__
* __zero_table_end__
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
KEEP(*(.text.user_irq_handler))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* To copy multiple ROM to RAM sections,
* uncomment .copy.table section and,
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
/*
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG (__data_end__ - __data_start__)
LONG (__etext2)
LONG (__data2_start__)
LONG (__data2_end__ - __data2_start__)
__copy_table_end__ = .;
} > FLASH
*/
/* To clear multiple BSS sections,
* uncomment .zero.table section and,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
/*
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
LONG (__bss2_start__)
LONG (__bss2_end__ - __bss2_start__)
__zero_table_end__ = .;
} > FLASH
*/
__etext = ALIGN (4);
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
/*
*(RAM_FSHLIST)
*(RAM_FSHCODE)
*/
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__end__ = .;
PROVIDE(end = .);
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
*(.stack*)
} > RAM
/DISCARD/ :
{
*(.debug)
*(.debug*)
*(.ARM.attributes)
*(.comment)
*(.stab)
*(.stabstr)
}
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

218
core/gnu/startup.S Normal file
View File

@ -0,0 +1,218 @@
.syntax unified
.arch armv6-m
.extern main
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0x600
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
.equ Heap_Size, 0
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.if Heap_Size
.space Heap_Size
.endif
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .isr_vector
.align 2
.globl __isr_vector
__isr_vector:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* External interrupts */
.long EXTI_IRQHandler /* 0 */
.long IWDT_IRQHandler /* 1 */
.long BLE_IRQHandler /* 2 */
.long DMAC_IRQHandler /* 3 */
.long BB_LP_IRQHandler /* 4 */
.long BTMR_IRQHandler /* 5 */
.long CTMR1_IRQHandler /* 6 */
.long ADMR1_IRQHandler /* 7 */
.long RTC_IRQHandler /* 8 */
.long I2C1_IRQHandler /* 9 */
.long SPIM_IRQHandler /* 10*/
.long SPIS_IRQHandler /* 11 */
.long UART1_IRQHandler /* 12 */
.long UART2_IRQHandler /* 13 */
.long AON_PMU_IRQHandler /* 14 */
.long LVD33_IRQHandler /* 15 */
.long BOD12_IRQHandler /* 16 */
.long USB_IRQHandler /* 17 */
.long USB_SOF_IRQHandler /* 18 */
.long FSHC_IRQHandler /* 19 */
.long 0 /* 20 Reserved*/
.long 0 /* 21 Reserved*/
.long 0 /* 22 Reserved*/
.long 0 /* 23 Reserved*/
.long 0 /* 24 Reserved*/
.long 0 /* 25 Reserved*/
.long 0 /* 26 Reserved*/
.long 0 /* 27 Reserved*/
.long 0 /* 28 Reserved*/
.long 0 /* 29 Reserved*/
.long 0 /* 30 Reserved*/
.long 0 /* 31 Reserved*/
.size __isr_vector, . - __isr_vector
.text
.thumb
.thumb_func
.align 1
.globl Reset_Handler
.type Reset_Handler, %function
.section ".text.user_irq_handler"
Reset_Handler:
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
subs r3, r2
ble .L_loop1_done
.L_loop1:
subs r3, #4
ldr r0, [r1,r3]
str r0, [r2,r3]
bgt .L_loop1
.L_loop1_done:
/* Single BSS section scheme.
*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
subs r2, r1
ble .L_loop3_done
.L_loop3:
subs r2, #4
str r0, [r1, r2]
bgt .L_loop3
.L_loop3_done:
bl main
.pool
.size Reset_Handler, . - Reset_Handler
/* Dummy Exception Handlers (infinite loops which can be modified) */
.weak NMI_Handler
.type NMI_Handler, %function
NMI_Handler:
b .
.size NMI_Handler, . - NMI_Handler
.weak HardFault_Handler
.type HardFault_Handler, %function
HardFault_Handler:
b .
.size HardFault_Handler, . - HardFault_Handler
.weak SVC_Handler
.type SVC_Handler, %function
SVC_Handler:
b .
.size SVC_Handler, . - SVC_Handler
.weak PendSV_Handler
.type PendSV_Handler, %function
PendSV_Handler:
b .
.size PendSV_Handler, . - PendSV_Handler
.weak SysTick_Handler
.type SysTick_Handler, %function
SysTick_Handler:
b .
.size SysTick_Handler, . - SysTick_Handler
.globl Default_Handler
.type Default_Handler, %function
Default_Handler:
b .
.size Default_Handler, . - Default_Handler
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_irq_handler handler_name
.weak \handler_name
.set \handler_name, Default_Handler
.endm
def_irq_handler EXTI_IRQHandler /* 0 */
def_irq_handler IWDT_IRQHandler /* 1 */
def_irq_handler BLE_IRQHandler /* 2 */
def_irq_handler DMAC_IRQHandler /* 3 */
def_irq_handler BB_LP_IRQHandler /* 4 */
def_irq_handler BTMR_IRQHandler /* 5 */
def_irq_handler CTMR1_IRQHandler /* 6 */
def_irq_handler ADMR1_IRQHandler /* 7 */
def_irq_handler RTC_IRQHandler /* 8 */
def_irq_handler I2C1_IRQHandler /* 9 */
def_irq_handler SPIM_IRQHandler /* 10*/
def_irq_handler SPIS_IRQHandler /* 11 */
def_irq_handler UART1_IRQHandler /* 12 */
def_irq_handler UART2_IRQHandler /* 13 */
def_irq_handler AON_PMU_IRQHandler /* 14 */
def_irq_handler LVD33_IRQHandler /* 15 */
def_irq_handler BOD12_IRQHandler /* 16 */
def_irq_handler USB_IRQHandler /* 17 */
def_irq_handler USB_SOF_IRQHandler /* 18 */
def_irq_handler FSHC_IRQHandler /* 19 */
.end

34
core/iar/link_xip.icf Normal file
View File

@ -0,0 +1,34 @@
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x18008000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x18008000;
define symbol __ICFEDIT_region_ROM_end__ = 0x18040000;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20004000;
/*
export symbol __ICFEDIT_region_RAM_start__;
export symbol __ICFEDIT_region_RAM_end__;
*/
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x600;
define symbol __ICFEDIT_size_heap__ = 0x000;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
keep { section .intvec };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place at end of RAM_region { block RamBottom with fixed order {readwrite, block CSTACK, block HEAP} };

201
core/iar/startup_iar.s Normal file
View File

@ -0,0 +1,201 @@
;********************************************************************************
;* File Name : startup_iar.s
;* Author : wq.
;* Version : V1.0.0
;* Date : 2021.7.15
;* Description : Dragon Devices vector table for EWARM toolchain.
;* This module performs:
;* - Set the initial SP
;* - Set the initial PC == __iar_program_start,
;* - Set the vector table entries with the exceptions ISR
;* address.
;* After Reset the Cortex-M0 processor is in Thread mode,
;* priority is Privileged, and the Stack is set to Main.
;********************************************************************************
;* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
;* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
;* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
;* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
;* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
;* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
;* FOR MORE INFORMATION PLEASE READ CAREFULLY THE LICENSE AGREEMENT FILE
;* LOCATED IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
;*******************************************************************************/
;
;
; The modules in this file are included in the libraries, and may be replaced
; by any user-defined modules that define the PUBLIC symbol _program_start or
; a user defined start symbol.
; To override the cstartup defined in the library, simply add your modified
; version to the workbench project.
;
; The vector table is normally located at address 0.
; When debugging in RAM, it can be located in RAM, aligned to at least 2^6.
; The name "__vector_table" has special meaning for C-SPY:
; it is where the SP start value is found, and the NVIC vector
; table register (VTOR) is initialized to this address if != 0.
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
EXTERN __iar_program_start
PUBLIC __vector_table
PUBLIC __Vectors
PUBLIC __Vectors_End
PUBLIC __Vectors_Size
DATA
__vector_table
DCD sfe(CSTACK) ; 0, load top of stack
DCD Reset_Handler ; 1, Reset Handler
DCD NMI_Handler ; 2, NMI Handler
DCD HardFault_Handler ; 3, Hard Fault Handler
DCD 0 ; 4, Reserved
DCD 0 ; 5, Reserved
DCD 0 ; 6, Reserved
DCD 0 ; 7, Reserved
DCD 0 ; 8, Reserved
DCD 0 ; 9, Reserved
DCD 0 ; 10, Reserved
DCD SVCall_Handler ; 11, SVCall Handler
DCD 0 ; 12, Reserved
DCD 0 ; 13, Reserved
DCD PendSV_Handler ; 14, PendSV Handler
DCD SysTick_Handler ; 15, SysTick Handler
; External Interrupts
DCD EXTI_IRQHandler ; 0, EXTI
DCD IWDT_IRQHandler ; 1, IWDT
DCD BLE_IRQHandler ; 2, BB
DCD DMAC_IRQHandler ; 3, DMAChannel
DCD BB_LP_IRQHandler ; 4, BB_LowPower
DCD BTMR_IRQHandler ; 5, DMAC
DCD CTMR1_IRQHandler ; 6, CTMR1
DCD ADMR1_IRQHandler ; 7, ATMR1
DCD RTC_IRQHandler ; 8, RTC
DCD I2C1_IRQHandler ; 9, I2C1
DCD SPIM_IRQHandler ; 10, SPI Master
DCD SPIS_IRQHandler ; 11, SPI Slave
DCD UART1_IRQHandler ; 12, UART1
DCD UART2_IRQHandler ; 13, UART2
DCD AON_PMU_IRQHandler ; 14, PMU
DCD LVD33_IRQHandler ; 15, LVD
DCD BOD12_IRQHandler ; 16, BOD
DCD USB_IRQHandler ; 17, USB
DCD USB_SOF_IRQHandler ; 18, USB_SOF
DCD FSHC_IRQHandler ; 19, FSHC
DCD 0 ; 20, Reserved
DCD 0 ; 21, Reserved
DCD 0 ; 22, Reserved
DCD 0 ; 23, Reserved
DCD 0 ; 24, Reserved
DCD 0 ; 25, Reserved
DCD 0 ; 26, Reserved
DCD 0 ; 27, Reserved
DCD 0 ; 28, Reserved
DCD 0 ; 29, Reserved
DCD 0 ; 30, Reserved
DCD 0 ; 31, Reserved
__Vectors_End
__Vectors EQU __vector_table
__Vectors_Size EQU __Vectors_End - __Vectors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Reset_Handler
;;
THUMB
PUBWEAK Reset_Handler
SECTION .text:CODE:NOROOT:REORDER(2)
Reset_Handler
LDR R0, =__iar_program_start
BX R0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dummy Exception Handlers
;; (infinite loops here, can be modified)
;;
PUBWEAK NMI_Handler
SECTION .text:CODE:NOROOT:REORDER(1)
NMI_Handler
B .
PUBWEAK HardFault_Handler
SECTION .text:CODE:NOROOT:REORDER(1)
HardFault_Handler
B .
PUBWEAK SVCall_Handler
SECTION .text:CODE:NOROOT:REORDER(1)
SVCall_Handler
B .
PUBWEAK PendSV_Handler
SECTION .text:CODE:NOROOT:REORDER(1)
PendSV_Handler
B .
PUBWEAK SysTick_Handler
SECTION .text:CODE:NOROOT:REORDER(1)
SysTick_Handler
B .
PUBWEAK EXTI_IRQHandler
PUBWEAK IWDT_IRQHandler
PUBWEAK BLE_IRQHandler
PUBWEAK DMAC_IRQHandler
PUBWEAK BB_LP_IRQHandler
PUBWEAK BTMR_IRQHandler
PUBWEAK CTMR1_IRQHandler
PUBWEAK ADMR1_IRQHandler
PUBWEAK RTC_IRQHandler
PUBWEAK I2C1_IRQHandler
PUBWEAK SPIM_IRQHandler
PUBWEAK SPIS_IRQHandler
PUBWEAK UART1_IRQHandler
PUBWEAK UART2_IRQHandler
PUBWEAK AON_PMU_IRQHandler
PUBWEAK LVD33_IRQHandler
PUBWEAK BOD12_IRQHandler
PUBWEAK USB_IRQHandler
PUBWEAK USB_SOF_IRQHandler
PUBWEAK FSHC_IRQHandler
SECTION .text:CODE:NOROOT:REORDER(1)
EXTI_IRQHandler
IWDT_IRQHandler
BLE_IRQHandler
DMAC_IRQHandler
BB_LP_IRQHandler
BTMR_IRQHandler
CTMR1_IRQHandler
ADMR1_IRQHandler
RTC_IRQHandler
I2C1_IRQHandler
SPIM_IRQHandler
SPIS_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
AON_PMU_IRQHandler
LVD33_IRQHandler
BOD12_IRQHandler
USB_IRQHandler
USB_SOF_IRQHandler
FSHC_IRQHandler
B .
END

21
core/mdk/link_sram.sct Normal file
View File

@ -0,0 +1,21 @@
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x20003600 0x4A00
{
ER_IROM1 +0
{
*.o (RESET, +First)
*(InRoot$$Sections)
startup*.o (+RO)
.ANY (+RO)
.ANY (+RW +ZI)
}
RW_IRAM_STACK 0x20003600-0x600 UNINIT 0x600
{
.ANY (STACK)
}
}

40
core/mdk/link_xip.sct Normal file
View File

@ -0,0 +1,40 @@
#! armcc -E -I ..\src\
#include "cfg.h"
#define SCT_FLASH_BASE (0x18004000)
#define SCT_FLASH_END (0x18020000)
#define SCT_FLASH_LEN (SCT_FLASH_END - SCT_FLASH_BASE)
LR_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
ER_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
*.o (RESET, +First)
*(InRoot$$Sections)
startup*.o (+RO)
.ANY (+RO)
}
RW_IRAM_VECT 0x20003000 EMPTY 152
{
; sram vector
}
RW_IRAM_USER +0
{
*.o(ram_func*)
.ANY (+RW +ZI)
}
RW_IRAM_STACK 0x20008000-0x600 UNINIT 0x600
{
.ANY (STACK)
}
RW_IRAM_RETN 0x20008000 UNINIT 0x2000
{
; retention memory 8KB
; user manual init
*.o(user_retention)
}
}

52
core/mdk/link_xip_ble.sct Normal file
View File

@ -0,0 +1,52 @@
#! armcc -E -I ..\src\ -I ..\..\..\ble\api
#include "cfg.h"
#include "blelib.h"
#define SCT_FLASH_BASE (0x18004000)
#define SCT_FLASH_END (0x18020000)
#define SCT_FLASH_LEN (SCT_FLASH_END - SCT_FLASH_BASE)
LR_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
ER_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
*.o (RESET, +First)
*(InRoot$$Sections)
startup*.o (+RO)
.ANY (+RO)
}
RW_IRAM_VECT 0x20003000 EMPTY 152
{
; sram vector
}
RW_IRAM_USER +0
{
*.o(ram_func*)
.ANY (+RW +ZI)
}
RW_IRAM_STACK 0x20008000-0x600 UNINIT 0x600
{
.ANY (STACK)
}
RW_IRAM_EXCH BLE_EXCH_BASE EMPTY BLE_EXCH_SIZE
{
; configured with BLE HW
}
RW_IRAM_HEAP BLE_HEAP_BASE EMPTY BLE_HEAP_SIZE
{
; configured with ble_heap()
}
RW_IRAM_RWZI BLE_RWZI_BASE UNINIT BLE_RWZI_SIZE
{
; ZI data, manual inited in lib
*ble6*.lib (+RW +ZI)
; user manual init
*.o(user_retention)
}
}

View File

@ -0,0 +1,51 @@
#! armcc -E -I ..\src\ -I ..\..\..\ble\api
#include "cfg.h"
#include "blelib.h"
#define SCT_FLASH_BASE (0x18004000)
#define SCT_FLASH_END (0x18020000)
#define SCT_FLASH_LEN (SCT_FLASH_END - SCT_FLASH_BASE)
LR_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
ER_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
*.o (RESET, +First)
*(InRoot$$Sections)
startup*.o (+RO)
.ANY (+RO)
}
RW_IRAM_VECT 0x20003000 EMPTY 152
{
; sram vector
}
RW_IRAM_USER +0
{
*.o(ram_func*)
;.ANY (+RW +ZI)
}
RW_IRAM_STACK 0x20008000-0x600 UNINIT 0x600
{
.ANY (STACK)
}
RW_IRAM_EXCH BLE_EXCH_BASE EMPTY BLE_EXCH_SIZE
{
; configured with BLE HW
}
RW_IRAM_HEAP BLE_HEAP_BASE EMPTY BLE_HEAP_SIZE
{
; configured with ble_heap()
}
RW_IRAM_RWZI BLE_RWZI_BASE UNINIT BLE_RWZI_SIZE
{
; ZI data, manual inited in lib
*ble6*.lib (+RW +ZI)
.ANY (+RW +ZI) ; retention
}
}

View File

@ -0,0 +1,52 @@
#! armcc -E -I ..\src\ -I ..\..\..\ble\api
#include "cfg.h"
#include "blelib.h"
#define SCT_FLASH_BASE (0x18004000)
#define SCT_FLASH_END (0x18040000)
#define SCT_FLASH_LEN (SCT_FLASH_END - SCT_FLASH_BASE)
LR_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
ER_IROM1 SCT_FLASH_BASE SCT_FLASH_LEN
{
*.o (RESET, +First)
*(InRoot$$Sections)
startup*.o (+RO)
.ANY (+RO)
}
RW_IRAM_VECT 0x20003000 EMPTY 152
{
; sram vector
}
RW_IRAM_USER +0
{
*.o(ram_func*)
.ANY (+RW +ZI)
}
RW_IRAM_STACK 0x20008000-0xA00 UNINIT 0xA00
{
.ANY (STACK) ; Mesh's STACK Size ~2.5K
}
RW_IRAM_EXCH BLE_EXCH_BASE EMPTY BLE_EXCH_SIZE
{
; configured with BLE HW
}
RW_IRAM_HEAP BLE_HEAP_BASE EMPTY BLE_HEAP_SIZE
{
; configured with ble_heap()
}
RW_IRAM_RWZI BLE_RWZI_BASE UNINIT BLE_RWZI_SIZE
{
; ZI data, manual inited in lib
*ble6*.lib (+RW +ZI)
; user manual init
*.o(user_retention)
}
}

225
core/mdk/startup.s Normal file
View File

@ -0,0 +1,225 @@
;ChipId: B6x
;Stack Configuration------------------------------------------------------------
Stack_Size EQU 0x600
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
;-------------------------------------------------------------------------------
;Heap Configuration-------------------------------------------------------------
Heap_Size EQU 0x200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
;-------------------------------------------------------------------------------
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset-------------------------------------
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors DCD __initial_sp ; 0, load top of stack
DCD Reset_Handler ; 1, Reset Handler
DCD NMI_Handler ; 2, NMI Handler
DCD HardFault_Handler ; 3, Hard Fault Handler
DCD 0 ; 4, Reserved
DCD 0 ; 5, Reserved
DCD 0 ; 6, Reserved
DCD 0 ; 7, Reserved
DCD 0 ; 8, Reserved
DCD 0 ; 9, Reserved
DCD 0 ; 10, Reserved
DCD SVCall_Handler ; 11, SVCall Handler
DCD 0 ; 12, Reserved
DCD 0 ; 13, Reserved
DCD PendSV_Handler ; 14, PendSV Handler
DCD SysTick_Handler ; 15, SysTick Handler
; External interrupts
DCD EXTI_IRQHandler ; 0, EXTI
DCD IWDT_IRQHandler ; 1, IWDT
DCD BLE_IRQHandler ; 2, BB
DCD DMAC_IRQHandler ; 3, DMAChannel
DCD BB_LP_IRQHandler ; 4, BB_LowPower
DCD BTMR_IRQHandler ; 5, BTMR
DCD CTMR_IRQHandler ; 6, CTMR
DCD ATMR_IRQHandler ; 7, ATMR
DCD RTC_IRQHandler ; 8, RTC
DCD I2C_IRQHandler ; 9, I2C
DCD SPIM_IRQHandler ; 10, SPI Master
DCD SPIS_IRQHandler ; 11, SPI Slave
DCD UART1_IRQHandler ; 12, UART1
DCD UART2_IRQHandler ; 13, UART2
DCD AON_PMU_IRQHandler ; 14, PMU
DCD LVD33_IRQHandler ; 15, LVD
DCD BOD12_IRQHandler ; 16, BOD
DCD USB_IRQHandler ; 17, USB
DCD USB_SOF_IRQHandler ; 18, USB_SOF
DCD FSHC_IRQHandler ; 19, FSHC
DCD MDM_IRQHandler ; 20, MODEM
DCD RF_IRQHandler ; 21, RF
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
;-------------------------------------------------------------------------------
AREA |.INT|, CODE, READONLY
;Reset Handler------------------------------------------------------------------
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT core_vector
IMPORT trim_load
;#ifndef CACHE_USE_SRAM
IF :LNOT::DEF:CACHE_USE_SRAM
;cache cfg
;SYSCFG->CACHSRAM_CFG = 0;
MOVS R0, #0x00
LDR R1, =0x4000102C
STR R0, [R1]
;CACHE->CRCR0.Word = 0x18004025;
LDR R0, =0x18004025
LDR R1, =0x1900000C
STR R0, [R1]
;CACHE->CCFR.CACHE_INST_DATA = 1;
;MOVS R0, #0x08
;LDR R1, =0x19000004
;STR R0, [R1]
;CACHE->CCR.CACHE_EN = 1;
MOVS R0, #0x01
LDR R1, =0x19000000
STR R0, [R1]
ENDIF
; copy vector to sram
LDR R0, =__Vectors
LDR R1, =core_vector
BLX R1
;APBMISC->XOSC16M_CTRL.Word = 0x00014894;
;.XOSC16M_LP=0 .XOSC16M_CAP_TR=0x14
LDR R0, =0x00014894
LDR R1, =0x40031054
STR R0, [R1]
; load ft trim
LDR R1, =trim_load
BLX R1
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops here, can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
SVCall_Handler PROC
EXPORT SVCall_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
;peripheral module int ---------------------------------------------------------
Default_Handler PROC
EXPORT EXTI_IRQHandler [WEAK]
EXPORT IWDT_IRQHandler [WEAK]
EXPORT BLE_IRQHandler [WEAK]
EXPORT DMAC_IRQHandler [WEAK]
EXPORT BB_LP_IRQHandler [WEAK]
EXPORT BTMR_IRQHandler [WEAK]
EXPORT CTMR_IRQHandler [WEAK]
EXPORT ATMR_IRQHandler [WEAK]
EXPORT RTC_IRQHandler [WEAK]
EXPORT I2C_IRQHandler [WEAK]
EXPORT SPIM_IRQHandler [WEAK]
EXPORT SPIS_IRQHandler [WEAK]
EXPORT UART1_IRQHandler [WEAK]
EXPORT UART2_IRQHandler [WEAK]
EXPORT AON_PMU_IRQHandler [WEAK]
EXPORT LVD33_IRQHandler [WEAK]
EXPORT BOD12_IRQHandler [WEAK]
EXPORT USB_IRQHandler [WEAK]
EXPORT USB_SOF_IRQHandler [WEAK]
EXPORT FSHC_IRQHandler [WEAK]
EXPORT MDM_IRQHandler [WEAK]
EXPORT RF_IRQHandler [WEAK]
EXTI_IRQHandler
IWDT_IRQHandler
BLE_IRQHandler
DMAC_IRQHandler
BB_LP_IRQHandler
BTMR_IRQHandler
CTMR_IRQHandler
ATMR_IRQHandler
RTC_IRQHandler
I2C_IRQHandler
SPIM_IRQHandler
SPIS_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
AON_PMU_IRQHandler
LVD33_IRQHandler
BOD12_IRQHandler
USB_IRQHandler
USB_SOF_IRQHandler
FSHC_IRQHandler
MDM_IRQHandler
RF_IRQHandler
B .
ENDP
ALIGN
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF :DEF:__MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, = (Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ALIGN
ENDIF
END

225
core/mdk/startup_mesh.s Normal file
View File

@ -0,0 +1,225 @@
;ChipId: B6x
;Stack Configuration------------------------------------------------------------
Stack_Size EQU 0xA00 ; Mesh's STACK Size ~2.5K
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
;-------------------------------------------------------------------------------
;Heap Configuration-------------------------------------------------------------
Heap_Size EQU 0x200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
;-------------------------------------------------------------------------------
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset-------------------------------------
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors DCD __initial_sp ; 0, load top of stack
DCD Reset_Handler ; 1, Reset Handler
DCD NMI_Handler ; 2, NMI Handler
DCD HardFault_Handler ; 3, Hard Fault Handler
DCD 0 ; 4, Reserved
DCD 0 ; 5, Reserved
DCD 0 ; 6, Reserved
DCD 0 ; 7, Reserved
DCD 0 ; 8, Reserved
DCD 0 ; 9, Reserved
DCD 0 ; 10, Reserved
DCD SVCall_Handler ; 11, SVCall Handler
DCD 0 ; 12, Reserved
DCD 0 ; 13, Reserved
DCD PendSV_Handler ; 14, PendSV Handler
DCD SysTick_Handler ; 15, SysTick Handler
; External interrupts
DCD EXTI_IRQHandler ; 0, EXTI
DCD IWDT_IRQHandler ; 1, IWDT
DCD BLE_IRQHandler ; 2, BB
DCD DMAC_IRQHandler ; 3, DMAChannel
DCD BB_LP_IRQHandler ; 4, BB_LowPower
DCD BTMR_IRQHandler ; 5, BTMR
DCD CTMR_IRQHandler ; 6, CTMR
DCD ATMR_IRQHandler ; 7, ATMR
DCD RTC_IRQHandler ; 8, RTC
DCD I2C_IRQHandler ; 9, I2C
DCD SPIM_IRQHandler ; 10, SPI Master
DCD SPIS_IRQHandler ; 11, SPI Slave
DCD UART1_IRQHandler ; 12, UART1
DCD UART2_IRQHandler ; 13, UART2
DCD AON_PMU_IRQHandler ; 14, PMU
DCD LVD33_IRQHandler ; 15, LVD
DCD BOD12_IRQHandler ; 16, BOD
DCD USB_IRQHandler ; 17, USB
DCD USB_SOF_IRQHandler ; 18, USB_SOF
DCD FSHC_IRQHandler ; 19, FSHC
DCD MDM_IRQHandler ; 20, MODEM
DCD RF_IRQHandler ; 21, RF
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
;-------------------------------------------------------------------------------
AREA |.INT|, CODE, READONLY
;Reset Handler------------------------------------------------------------------
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT core_vector
IMPORT trim_load
;#ifndef CACHE_USE_SRAM
IF :LNOT::DEF:CACHE_USE_SRAM
;cache cfg
;SYSCFG->CACHSRAM_CFG = 0;
MOVS R0, #0x00
LDR R1, =0x4000102C
STR R0, [R1]
;CACHE->CRCR0.Word = 0x18004025;
LDR R0, =0x18004025
LDR R1, =0x1900000C
STR R0, [R1]
;CACHE->CCFR.CACHE_INST_DATA = 1;
;MOVS R0, #0x08
;LDR R1, =0x19000004
;STR R0, [R1]
;CACHE->CCR.CACHE_EN = 1;
MOVS R0, #0x01
LDR R1, =0x19000000
STR R0, [R1]
ENDIF
; copy vector to sram
LDR R0, =__Vectors
LDR R1, =core_vector
BLX R1
;APBMISC->XOSC16M_CTRL.Word = 0x00014894;
;.XOSC16M_LP=0 .XOSC16M_CAP_TR=0x14
LDR R0, =0x00014894
LDR R1, =0x40031054
STR R0, [R1]
; load ft trim
LDR R1, =trim_load
BLX R1
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops here, can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
SVCall_Handler PROC
EXPORT SVCall_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
;peripheral module int ---------------------------------------------------------
Default_Handler PROC
EXPORT EXTI_IRQHandler [WEAK]
EXPORT IWDT_IRQHandler [WEAK]
EXPORT BLE_IRQHandler [WEAK]
EXPORT DMAC_IRQHandler [WEAK]
EXPORT BB_LP_IRQHandler [WEAK]
EXPORT BTMR_IRQHandler [WEAK]
EXPORT CTMR_IRQHandler [WEAK]
EXPORT ATMR_IRQHandler [WEAK]
EXPORT RTC_IRQHandler [WEAK]
EXPORT I2C_IRQHandler [WEAK]
EXPORT SPIM_IRQHandler [WEAK]
EXPORT SPIS_IRQHandler [WEAK]
EXPORT UART1_IRQHandler [WEAK]
EXPORT UART2_IRQHandler [WEAK]
EXPORT AON_PMU_IRQHandler [WEAK]
EXPORT LVD33_IRQHandler [WEAK]
EXPORT BOD12_IRQHandler [WEAK]
EXPORT USB_IRQHandler [WEAK]
EXPORT USB_SOF_IRQHandler [WEAK]
EXPORT FSHC_IRQHandler [WEAK]
EXPORT MDM_IRQHandler [WEAK]
EXPORT RF_IRQHandler [WEAK]
EXTI_IRQHandler
IWDT_IRQHandler
BLE_IRQHandler
DMAC_IRQHandler
BB_LP_IRQHandler
BTMR_IRQHandler
CTMR_IRQHandler
ATMR_IRQHandler
RTC_IRQHandler
I2C_IRQHandler
SPIM_IRQHandler
SPIS_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
AON_PMU_IRQHandler
LVD33_IRQHandler
BOD12_IRQHandler
USB_IRQHandler
USB_SOF_IRQHandler
FSHC_IRQHandler
MDM_IRQHandler
RF_IRQHandler
B .
ENDP
ALIGN
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF :DEF:__MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, = (Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ALIGN
ENDIF
END

325
core/reg/reg_aon.h Normal file
View File

@ -0,0 +1,325 @@
#ifndef _REG_AON_H_
#define _REG_AON_H_
#include "reg_base.h"
//================================
//BLOCK AON define
#define AON_BASE ((uint32_t)0x40030000)
#define AON_BACKUP0_ADDR_OFFSET 0x000
#define AON_BACKUP1_ADDR_OFFSET 0x004
#define AON_BKHOLD_CTRL_ADDR_OFFSET 0x008
#define AON_BACKUP2_ADDR_OFFSET 0x00c
#define AON_BLE_RTC_CTL_ADDR_OFFSET 0x010
#define AON_SCAN_MODE_CTRL_ADDR_OFFSET 0x014
#define AON_PMU_CTRL_ADDR_OFFSET 0x018
#define AON_PMU_WKUP_CTRL_ADDR_OFFSET 0x01c
#define AON_PMU_WKUP_ST_ADDR_OFFSET 0x020
#define AON_PMU_ANA_CTRL_ADDR_OFFSET 0x024
#define AON_XOSC16M_CTRL_ADDR_OFFSET 0x028
//================================
//BLOCK AON reg struct define
typedef union //0x008
{
struct
{
uint32_t RC32K_MSB_TRIM_CFG: 4; // bit[3:0]
uint32_t RC32K_LSB_TRIM_CFG: 10; // bit[13:4]
uint32_t XOSC_EST_MODE: 1; // bit14 ---
// 1: extarnal clock through XOSC16M_IN PAD into chip, and XOSC16M_OUT PAD is not driven by XOSC16M
// 0: the XOSC16M_IN & XOSC16M_OUT are connected with crystal oscillator.
uint32_t PIOA19_FUNC_SEL: 1; // bit15 ---
// 0: pioa19 used as reset pin
// 1: pioa19 used as GPIO
// can't be reset by pin reset
uint32_t AONLDO_TRIM_RUN: 4; // bit[19:16] --- LDOBK_TRIM,
// inverter the high two bits
// 0: 1.208
// 1: 1.253
// 2: 1.298
// 3: 1.335
// 4: 1.035
// 5: 1.080
// 6: 1.118
// 7: 1.163
// 8: 0.854
// 9: 0.899
// 10: 0.944
// 11: 0.989
// 12: 0.674
// 13: 0.719
// 14: 0.764
// 15: 0.809
uint32_t CORELDO_TRIM_RUN: 5; // bit[24:20] --- CORE LDO trim, used when ST_RUN
uint32_t RSV_END: 7; // bit[31:25]
};
uint32_t Word;
} AON_BKHOLD_CTRL_TypeDef; //0x008
//================================
#define AON_RC32K_MSB_TRIM_CFG_LSB 0
#define AON_RC32K_MSB_TRIM_CFG_WIDTH 4
#define AON_RC32K_LSB_TRIM_CFG_LSB 4
#define AON_RC32K_LSB_TRIM_CFG_WIDTH 10
#define AON_XOSC_EST_MODE_POS 14
#define AON_PIOA19_FUNC_SEL_POS 15
#define AON_AONLDO_TRIM_RUN_LSB 16
#define AON_AONLDO_TRIM_RUN_WIDTH 4
#define AON_CORELDO_TRIM_RUN_LSB 20
#define AON_CORELDO_TRIM_RUN_WIDTH 5
//================================
typedef union //0x010
{
struct
{
uint32_t BLELOWCLK_EN: 1; // bit0
uint32_t BLELOWCLK_SEL: 1; // bit1 --- BLE low power clock source select
// 0: lsi clock, 32K
// 1: HSE clock/500; 32K
// set as 1 condtion:
// chip is just in deepsleep mode, and makesure
uint32_t RTC_EN: 1; // bit2
// 0: RTC disable
// 1: RTC enable
uint32_t RSV_END: 29; // bit[31:3]
};
uint32_t Word;
} AON_BLE_RTC_CTL_TypeDef; //0x010
//================================
#define AON_BLELOWCLK_EN_POS 0
#define AON_BLELOWCLK_SEL_POS 1
#define AON_RTC_EN_POS 2
//================================
typedef union //0x014
{
struct
{
uint32_t SCAN_MODE_REQ: 1; // bit0
uint32_t SCAN_ZIP_CFG: 1; // bit1
uint32_t RSV_END: 30; // bit[31:2]
};
uint32_t Word;
} AON_SCAN_MODE_CTRL_TypeDef; //0x014
//================================
#define AON_SCAN_MODE_REQ_POS 0
#define AON_SCAN_ZIP_CFG_POS 1
//================================
typedef union //0x018
{
struct
{
uint32_t AUTO_DIS_RC32K: 1; // bit0
// when auto_dis_rc32k is 1
// RC32K is auto disable when chip in poweroff state or deepsleep state
// RC32K is auto enable when wakeup event happen for poweroff state or deepsleep
// the RTC and BB WAKE LP can't used as wakeup source for DEEPSLEEP or poweroff
// only GPIO or reset pin can be use
uint32_t CORELDO_EN_RUN: 1; // bit1 --- When PMU is on ST_RUN, CORE LDO enable is controlled by coreldo_en_run
uint32_t OSC_EN_RUN: 1; // bit2 --- When PMU is on ST_RUN, OSC enable is controlled by osc_en_run
uint32_t RC32K_EN_RUN: 1; // bit3 --- only use when PMU in ST_RUN, RC32K
uint32_t EM_PD_EN: 1; // bib4 ---
// 1 : EM is power down
// 0 : EN is power enable
uint32_t EM_ACCESS_EN: 1; // bit5 ---
// 1: EM is can be access
// 0: EM is isolation
// note:
// em_access_en set as 0 before em_pd_en set as 1
// em_access_en set as 1 after em_pd_en set as 0
uint32_t RSV_NOUSE1: 2; // bit[7:6] --- Ignore me
uint32_t POWEROFF_LOG: 1; // bit8 ---
// when is 1, chip is powerup from POWEROFF state
// else means chip is initial powerup or powerup from BOD event happen
// cleared by poweroff_log_clr
uint32_t EM_PD_ACK: 1; // bit9
uint32_t RSV_END: 22; // bit[31:10]
};
uint32_t Word;
} AON_PMU_CTRL_TypeDef; //0x018
//================================
#define AON_AUTO_DIS_RC32K_POS 0
#define AON_CORELDO_EN_RUN_POS 1
#define AON_OSC_EN_RUN_POS 2
#define AON_RC32K_EN_RUN_POS 3
#define AON_EM_PD_EN_POS 4
#define AON_EM_ACCESS_EN_POS 5
#define AON_POWEROFF_LOG_POS 8
#define AON_EM_PD_ACK_POS 9
//================================
typedef union //0x01c
{
struct
{
uint32_t BLE_WKUP_SEL: 2; // bit[1:0] --- both use when deepsleep or poweroff state
// 2'b00 disable ble wakeup
// 2'b01: select ble_osc_en as wakeup source
// 2'b10: select ble_radio_en as wakeup source
// 2'b11: select ble_wakeup_lp as wakeup source
// when poweroff mode, only ble_osc_en can be used
uint32_t BLE_LATCH_N: 1; // bit2 ---
// 0: latch the signal from BB to BLE LP counter
// 1: enable the signal from BB to BLE LP counter
// config as 0 before chip into poweroff mode
// set as 1 after chip powerup and retain the BB state
uint32_t IO_WKUP_EN: 1; // bit3 --- both use when deepsleep or poweroff state
uint32_t RTC_WKUP_EN: 1; // bit4 --- both use when deepsleep or poweroff state
uint32_t IO_LATCH_N: 1; // bit5 ---
// 0: latch the GPIO control signal from core to AON
// 1: enable the GPIO control signal from core to AON
// config as 0 before chip into poweroff mode
// set as 1 after chip powerup and retain the GPIO config
uint32_t RC32K_TRIM_SEL: 1; // bit6 ---
// 0: use rc32k_msb_trim_cfg and rc32k_lsb_trim_cfg control the RC32K freq
// 1: use RC32K calib result control the RC32K freq
uint32_t RSV_END: 25; // bit[31:7]
};
uint32_t Word;
} AON_PMU_WKUP_CTRL_TypeDef; //0x01c
//================================
#define AON_BLE_WKUP_SEL_LSB 0
#define AON_BLE_WKUP_SEL_WIDTH 2
#define AON_BLE_LATCH_N_POS 2
#define AON_IO_WKUP_EN_POS 3
#define AON_RTC_WKUP_EN_POS 4
#define AON_IO_LATCH_N_POS 5
#define AON_RC32K_TRIM_SEL_POS 6
//================================
typedef union //0x020
{
struct
{
uint32_t IO_WKUP_ST: 1; // bit0
uint32_t BLE_WKUP_ST: 1; // bit1
uint32_t RTC_WKUP_ST: 1; // bit2
uint32_t AON_PMU_INT: 1; // bit3
uint32_t RSV_NOUSE1: 4; // bit[7:4] --- Ignore me
uint32_t BOD12_OUT12_ST: 1; // bit8
uint32_t LVD33_OUT12_ST: 1; // bit9
uint32_t RSV_END: 22; // bit[31:10]
};
uint32_t Word;
} AON_PMU_WKUP_ST_TypeDef; //0x020
//================================
#define AON_IO_WKUP_ST_POS 0
#define AON_BLE_WKUP_ST_POS 1
#define AON_RTC_WKUP_ST_POS 2
#define AON_AON_PMU_INT_POS 3
#define AON_BOD12_OUT12_ST_POS 8
#define AON_LVD33_OUT12_ST_POS 9
//================================
typedef union //0x024
{
struct
{
uint32_t BK_BOD_TRIM: 3; // bit[2:0]
uint32_t LDO_BOD_EN: 1; // bit3 --- BOD function:
// detect the VDD12
// when VDD12 < vth: BOD12_OUT12 is 1
// else BOD12_OUT12 is 0
uint32_t LDO_BOD_RST_EN: 1; // bit4
uint32_t LDO12_IBSEL: 5; // bit[9:5]
uint32_t LDO_LVD_EN: 1; // bit10
uint32_t LDO_LVD_SEL: 3; // bit[13:11] --- BOD function:
// detect the VDD33
// when VDD33 < vth: LVD33_OUT12 is 1
// else BOD12_OUT12 is 0
uint32_t LDO_LVD_RST_EN: 1; // bit14
uint32_t RSV_NOUSE1: 1; // bit15 --- Ignore me
uint32_t ANA_RESV: 16; // bit[31:16] ---
// [0] LDO_DPLL VREG12_EN1 TEST EN
// [1] LDO_DPLL VREG12_EN2 TEST EN
// [2] LDO_DPLL EN
// [3] LDO32K TEST EN
// [4] LDOCORE TEST EN
// [7:5] LDODPLL_TRIM[2:0]
// [8] DPLL2 ref clock select:0-OSC 16M, 1-RC 16M
};
uint32_t Word;
} AON_PMU_ANA_CTRL_TypeDef; //0x024
//================================
#define AON_BK_BOD_TRIM_LSB 0
#define AON_BK_BOD_TRIM_WIDTH 3
#define AON_LDO_BOD_EN_POS 3
#define AON_LDO_BOD_RST_EN_POS 4
#define AON_LDO12_IBSEL_LSB 5
#define AON_LDO12_IBSEL_WIDTH 5
#define AON_LDO_LVD_EN_POS 10
#define AON_LDO_LVD_SEL_LSB 11
#define AON_LDO_LVD_SEL_WIDTH 3
#define AON_LDO_LVD_RST_EN_POS 14
#define AON_ANA_RESV_LSB 16
#define AON_ANA_RESV_WIDTH 16
//================================
typedef union //0x028
{
struct
{
uint32_t EN_LDO_XOSC_REG: 1; // bit0
uint32_t EN_LDO_SEL: 1; // bit1 --- EN_LDO_XOSC control select
// 0: EN_LDO_XOSC is controlled by XOSC16M_EN
// 1: EN_LDO_XOSC is controlled by EN_LDO_XOSC_REG
uint32_t BYPASS_LDO_XOSC: 1; // bit2
uint32_t RSV_END: 29; // bit[31:3]
};
uint32_t Word;
} AON_XOSC16M_CTRL_TypeDef; //0x028
//================================
#define AON_EN_LDO_XOSC_REG_POS 0
#define AON_EN_LDO_SEL_POS 1
#define AON_BYPASS_LDO_XOSC_POS 2
//================================
//================================
//BLOCK AON top struct define
typedef struct
{
__IO uint32_t BACKUP0 ; // 0x000, valid-bit:16
// can't be reset by pin reset, por12_bk_stb
__IO uint32_t BACKUP1 ; // 0x004, valid-bit:8
// can't be reset by pin reset por12_bk_stb
__IO AON_BKHOLD_CTRL_TypeDef BKHOLD_CTRL ; // 0x008,
// can't be reset by pin reset por12_bk_stb
__IO uint32_t BACKUP2 ; // 0x00c, valid-bit:8
// can be reset by pin reset
__IO AON_BLE_RTC_CTL_TypeDef BLE_RTC_CTL ; // 0x010,
__IO AON_SCAN_MODE_CTRL_TypeDef SCAN_MODE_CTRL ; // 0x014,
// how to into scan mode
// 1: CPU write this scan_mode_req
// 2: wait 200us;
__IO AON_PMU_CTRL_TypeDef PMU_CTRL ; // 0x018,
__IO AON_PMU_WKUP_CTRL_TypeDef PMU_WKUP_CTRL ; // 0x01c,
// set deepsleep poweroff wakeup source
__I AON_PMU_WKUP_ST_TypeDef PMU_WKUP_ST ; // 0x020,
__IO AON_PMU_ANA_CTRL_TypeDef PMU_ANA_CTRL ; // 0x024,
__IO AON_XOSC16M_CTRL_TypeDef XOSC16M_CTRL ; // 0x028,
} AON_TypeDef;
#define AON (( AON_TypeDef *) AON_BASE)
#endif

439
core/reg/reg_apbmisc.h Normal file
View File

@ -0,0 +1,439 @@
#ifndef _REG_APBMISC_H_
#define _REG_APBMISC_H_
#include "reg_base.h"
//================================
//BLOCK APBMISC define
#define APBMISC_BASE ((uint32_t)0x40031000)
#define APBMISC_RC32K_CALIB_ST_ADDR_OFFSET 0x000
#define APBMISC_RCCALIB_CTRL_ADDR_OFFSET 0x004
#define APBMISC_RCCALIB_START_ADDR_OFFSET 0x008
#define APBMISC_RCFREQ_GET_ADDR_OFFSET 0x00c
#define APBMISC_RC_FREQ_VAL_ADDR_OFFSET 0x010
#define APBMISC_RCCALIB_STCLR_ADDR_OFFSET 0x014
#define APBMISC_RC16M_CNT_CTRL_ADDR_OFFSET 0x018
#define APBMISC_RTCINT_CTRL_ADDR_OFFSET 0x01c
#define APBMISC_RTC_SEC_ADDR_OFFSET 0x020
#define APBMISC_RTC_MS_ADDR_OFFSET 0x024
#define APBMISC_RTC_ALARM_SEC_ADDR_OFFSET 0x028
#define APBMISC_RTC_ALARM_MS_ADDR_OFFSET 0x02c
#define APBMISC_RTC_SEC_SHD_ADDR_OFFSET 0x030
#define APBMISC_RTC_MS_SHD_ADDR_OFFSET 0x034
#define APBMISC_AON_PMU_CTRL_ADDR_OFFSET 0x038
#define APBMISC_LDO_UD_CTRL_ADDR_OFFSET 0x03c
#define APBMISC_PIOA_WKUP_POS_ADDR_OFFSET 0x040
#define APBMISC_PIOA_WKUP_NEG_ADDR_OFFSET 0x044
#define APBMISC_POWEROFF_WORD_CMD_ADDR_OFFSET 0x048
#define APBMISC_POWEROFF_LOG_CLR_ADDR_OFFSET 0x04c
#define APBMISC_RC16M_FREQ_TRIM_ADDR_OFFSET 0x050
#define APBMISC_XOSC16M_CTRL_ADDR_OFFSET 0x054
#define APBMISC_BLE_LP_CTRL_ADDR_OFFSET 0x058
#define APBMISC_BLE_SYNC_TIME_ADDR_OFFSET 0x05c
#define APBMISC_BLE_FINECNT_BOUND_ADDR_OFFSET 0x060
#define APBMISC_BLE_CLKNCNT_SAMP_ADDR_OFFSET 0x064
#define APBMISC_BLE_FINECNT_SAMP_ADDR_OFFSET 0x068
#define APBMISC_BLE_CLKNCNT_CFG_ADDR_OFFSET 0x06c
#define APBMISC_BLE_FINECNT_CFG_ADDR_OFFSET 0x070
#define APBMISC_BLE_DP_TWCORE_ADDR_OFFSET 0x074
#define APBMISC_BLE_UPLOAD_ADDR_OFFSET 0x078
#define APBMISC_DPLL_CTRL_ADDR_OFFSET 0x07c
#define APBMISC_ANAMISC_CTRL_ADDR_OFFSET 0x080
#define APBMISC_ANAMISC_ST_ADDR_OFFSET 0x084
//================================
//BLOCK APBMISC reg struct define
typedef union //0x000
{
struct
{
uint32_t RC32K_MSB_CALIB: 4; // bit[3:0] --- the final RC trim value
uint32_t RSV_NOUSE1: 12; // bit[15:4]--- Ignore me
uint32_t RC32K_LSB_CALIB: 10; // bit[25:16]
uint32_t RSV_END: 6; // bit[31:26]
};
uint32_t Word;
} APBMISC_RC32K_CALIB_ST_TypeDef; //0x000
//================================
#define APBMISC_RC32K_MSB_CALIB_LSB 0
#define APBMISC_RC32K_MSB_CALIB_WIDTH 4
#define APBMISC_RC32K_LSB_CALIB_LSB 16
#define APBMISC_RC32K_LSB_CALIB_WIDTH 10
//================================
typedef union //0x004
{
struct
{
uint32_t RCCALIB_TARGET: 20; // bit[19:0] --- rccalib_target = Fref * (rccalib_cycles+1) / Flsi
// when rccalib_clksel
// 2'b00: rccalib_target = 16e6 * rccalib_cycles /32000
// 2'b01: rccalib_target = 64e6 * rccalib_cycles /32000
// 2'b10: rccalib_target = 128e6 * rccalib_cycles /32000
uint32_t RCCALIB_CYCLES: 8; // bit[27:20] --- each RC calib step window is (rccalib_cycles+1) of LSI clock
uint32_t RCCALIB_SCAL_EN: 1; // bit28 ---
// 0: all calib step window is depend on rccalib_cycles
// 1: calib step window when search rc32k_msb_calib[3:0] & rc32k_lsb_calib[9:5] is scale down 2
// and calib step window rc32k_lsb_calib[4:0] is depend on rccalib_cycles
uint32_t RCCALIB_DLY: 1; // bit29 ---
// when is 1:add one LSI clock delay between msb_calib or lsb_calib change to start count
uint32_t RSV_END: 2; // bit[31:30]
};
uint32_t Word;
} APBMISC_RCCALIB_CTRL_TypeDef; //0x004
//================================
#define APBMISC_RCCALIB_TARGET_LSB 0
#define APBMISC_RCCALIB_TARGET_WIDTH 20
#define APBMISC_RCCALIB_CYCLES_LSB 20
#define APBMISC_RCCALIB_CYCLES_WIDTH 8
#define APBMISC_RCCALIB_SCAL_EN_POS 28
#define APBMISC_RCCALIB_DLY_POS 29
//================================
typedef union //0x014
{
struct
{
uint32_t RCCALIB_DONE: 1; // bit0
uint32_t RCFREQ_DONE: 1; // bit1
uint32_t RSV_NOUSE1: 6; // bit[7:2] --- Ignore me
uint32_t RCCALIB_DONE_CLR: 1; // bit8
uint32_t RCFREQ_DONE_CLR: 1; // bit9
uint32_t RSV_END: 22; // bit[31:10]
};
uint32_t Word;
} APBMISC_RCCALIB_STCLR_TypeDef; //0x014
//================================
#define APBMISC_RCCALIB_DONE_POS 0
#define APBMISC_RCFREQ_DONE_POS 1
#define APBMISC_RCCALIB_DONE_CLR_POS 8
#define APBMISC_RCFREQ_DONE_CLR_POS 9
//================================
typedef union //0x018
{
struct
{
uint32_t RC16M_WIN_SET: 15; // bit[14:0] --- RC16M cnt window
// (rc16m_win_set<<10) osc16m cycles
uint32_t RC16M_CNT_START: 1; // bit15
uint32_t RC16M_WIN_CNT: 15; // bit[30:16]
uint32_t RC16M_CNT_DONE: 1; // bit31
};
uint32_t Word;
} APBMISC_RC16M_CNT_CTRL_TypeDef; //0x018
//================================
#define APBMISC_RC16M_WIN_SET_LSB 0
#define APBMISC_RC16M_WIN_SET_WIDTH 15
#define APBMISC_RC16M_CNT_START_POS 15
#define APBMISC_RC16M_WIN_CNT_LSB 16
#define APBMISC_RC16M_WIN_CNT_WIDTH 15
#define APBMISC_RC16M_CNT_DONE_POS 31
//================================
typedef union //0x01c
{
struct
{
uint32_t RTC_INT_EN: 1; // bit0 --- rtc interrupt enable
uint32_t RTC_INT_CLR: 1; // bit1 --- rtc intrrrupt clear
uint32_t RTC_INT_ST: 1; // bit2 --- rtc interrupt status
uint32_t RTC_SET_BUSY: 1; // bit3
uint32_t RSV_END: 28; // bit[31:4]
};
uint32_t Word;
} APBMISC_RTCINT_CTRL_TypeDef; //0x01c
//================================
#define APBMISC_RTC_INT_EN_POS 0
#define APBMISC_RTC_INT_CLR_POS 1
#define APBMISC_RTC_INT_ST_POS 2
#define APBMISC_RTC_SET_BUSY_POS 3
//================================
typedef union //0x038
{
struct
{
uint32_t LDO_LP_SEL_RUN: 1; // bit0 ---
// 0: CORE LDO is HP mode
// 1: CORE LDO is lp mode
uint32_t AON_PWR_SEL_RUN: 1; // bit1 ---
// 0: select AON_LDO out as AON power
// 1: select CORE_LDO out as AON power
uint32_t HSI_EN_RUN: 1; // bit2 --- When PMU is on ST_RUN, hsi_en is controlled by hsi_en_run
// 1: RC16M enable
uint32_t FSH_PW_EN_RUN: 1; // bit3
uint32_t RSV_NOUSE1: 4; // bit[7:4] --- Ignore me
uint32_t LDO_LP_SEL_DP: 1; // bit8 --- When PMU is on ST_DP, CORE LDO lp mode is controlled by ldo_lp_sel_dp
uint32_t AON_PWR_SEL_DP: 1; // bit9 --- When PMU is on ST_DP, AON_PWR_SEL is controlled by aon_pwr_sel_dp
uint32_t OSC_EN_DP: 1; // bit10--- When PMU is on ST_DP, OSC enable is controlled by osc_en_dp
uint32_t HSI_EN_DP: 1; // bit11--- When PMU is on ST_DP, hsi_en is controlled by hsi_en_dp
// 1: RC16M enable
uint32_t FSH_PW_EN_DP: 1; // bit12
uint32_t RSV_NOUSE2: 3; // bit[15:13] --- Ignore me
uint32_t CLK_STB_TIME: 6; // bit[21:16] --- clock stable time for exit from deepsleep
// unit : 30.5us (RC32K clock period)
// stable time : 30.5* (clk_stb_time + 1)
// recommend value:
// 6'd3 (120us) for only wait RC16M stable when exit from deepsleep
// 6'd63(2ms) for both wait RC16M and HOSC16M stable when exit from deepsleep
uint32_t WKUP_ST_CLR: 1; // bit22
uint32_t AON_PMU_INT_CLR: 1; // bit23
uint32_t RSV_END: 8; // bit[31:24]
};
uint32_t Word;
} APBMISC_AON_PMU_CTRL_TypeDef; //0x038
//================================
#define APBMISC_LDO_LP_SEL_RUN_POS 0
#define APBMISC_AON_PWR_SEL_RUN_POS 1
#define APBMISC_HSI_EN_RUN_POS 2
#define APBMISC_FSH_PW_EN_RUN_POS 3
#define APBMISC_LDO_LP_SEL_DP_POS 8
#define APBMISC_AON_PWR_SEL_DP_POS 9
#define APBMISC_OSC_EN_DP_POS 10
#define APBMISC_HSI_EN_DP_POS 11
#define APBMISC_FSH_PW_EN_DP_POS 12
#define APBMISC_CLK_STB_TIME_LSB 16
#define APBMISC_CLK_STB_TIME_WIDTH 6
#define APBMISC_WKUP_ST_CLR_POS 22
#define APBMISC_AON_PMU_INT_CLR_POS 23
//================================
typedef union //0x03c
{
struct
{
uint32_t CORELDO_TRIM_DP: 5; // bit[4:0]
uint32_t RSV_NOUSE1: 3; // bit[7:5] --- Ignore me
uint32_t CORELDO_TRIM_STEP: 5; // bit[12:8]
uint32_t RSV_NOUSE2: 3; // bit[15:13]-- Ignore me
uint32_t AONLDO_TRIM_OFF: 4; // bit[19:16]
uint32_t AONLDO_UD_STEP: 3; // bit[22:20]-- LDOBK TRIM
uint32_t RSV_END: 9; // bit[31:23]
};
uint32_t Word;
} APBMISC_LDO_UD_CTRL_TypeDef; //0x03c
//================================
#define APBMISC_CORELDO_TRIM_DP_LSB 0
#define APBMISC_CORELDO_TRIM_DP_WIDTH 5
#define APBMISC_CORELDO_TRIM_STEP_LSB 8
#define APBMISC_CORELDO_TRIM_STEP_WIDTH 5
#define APBMISC_AONLDO_TRIM_OFF_LSB 16
#define APBMISC_AONLDO_TRIM_OFF_WIDTH 4
#define APBMISC_AONLDO_UD_STEP_LSB 20
#define APBMISC_AONLDO_UD_STEP_WIDTH 3
//================================
typedef union //0x054
{
struct
{
uint32_t XOSC16M_CAP_TR: 6; // bit[5:0]
uint32_t XOSC16M_LP: 1; // bit6
uint32_t EN_XO16MBUF: 1; // bit7
uint32_t XOSC16M_BIAS_ADJ: 4; // bit[11:8]
uint32_t XOSC16M_SEL: 1; // bit12
uint32_t RSV_NOUSE1: 1; // bit13 --- Ignore me
uint32_t LDO_XOSC_TR: 4; // bit[17:14]
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} APBMISC_XOSC16M_CTRL_TypeDef; //0x054
//================================
#define APBMISC_XOSC16M_CAP_TR_LSB 0
#define APBMISC_XOSC16M_CAP_TR_WIDTH 6
#define APBMISC_XOSC16M_LP_POS 6
#define APBMISC_EN_XO16MBUF_POS 7
#define APBMISC_XOSC16M_BIAS_ADJ_LSB 8
#define APBMISC_XOSC16M_BIAS_ADJ_WIDTH 4
#define APBMISC_XOSC16M_SEL_POS 12
#define APBMISC_LDO_XOSC_TR_LSB 14
#define APBMISC_LDO_XOSC_TR_WIDTH 4
//================================
typedef union //0x058
{
struct
{
uint32_t BLE_WAKEUP_REQ: 1; // bit0 --- software wakeup the BB from BB in deepsleep
uint32_t RSV_NOUSE1: 7; // bit[7:1] --- Ignore me
uint32_t BLE_OSC_EN_ST: 1; // bit8
uint32_t BLE_RADIO_EN_ST: 1; // bit9
uint32_t BLE_SAMP_VALID: 1; // bit10 ---
// when is 1, ble_clkncnt_samp & ble_finecnt_samp can be read
// auto cleared by HW
uint32_t BLE_DP_VALID: 1; // bit11 ---
// when is 1, BB is deepsleep, and the remained sleep time is larger than ble_dp_twcore
// auto cleared when BB exit deepsleep
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} APBMISC_BLE_LP_CTRL_TypeDef; //0x058
//================================
#define APBMISC_BLE_WAKEUP_REQ_POS 0
#define APBMISC_BLE_OSC_EN_ST_POS 8
#define APBMISC_BLE_RADIO_EN_ST_POS 9
#define APBMISC_BLE_SAMP_VALID_POS 10
#define APBMISC_BLE_DP_VALID_POS 11
//================================
typedef union //0x07c
{
struct
{
uint32_t RSV_NOUSE1: 2; // bit[1:0] --- Ignore me
uint32_t DPLL2_EN: 1; // bit2
uint32_t DPLL2_LOCK_BYPASS_EN: 1; // bit3
uint32_t DPLL2_EN_CLK48M: 1; // bit4
uint32_t RSV_END: 27; // bit[31:5]
};
uint32_t Word;
} APBMISC_DPLL_CTRL_TypeDef; //0x07c
//================================
#define APBMISC_DPLL2_EN_POS 2
#define APBMISC_DPLL2_LOCK_BYPASS_EN_POS 3
#define APBMISC_DPLL2_EN_CLK48M_POS 4
//================================
typedef union //0x078
{
struct
{
uint32_t TESTA_CONN2XO_EN: 1; // bit0
uint32_t LDO_BOD_TEST_EN: 1; // bit1
uint32_t LDO_BOD_INT_EN: 1; // bit2
uint32_t LDO_LVD_INT_EN: 1; // bit3
uint32_t BK_VBK_TEST_EN: 1; // bit4
uint32_t RSV_END: 27; // bit[31:5]
};
uint32_t Word;
} APBMISC_ANAMISC_CTRL_TypeDef; //0x078
//================================
#define APBMISC_TESTA_CONN2XO_EN_POS 0
#define APBMISC_LDO_BOD_TEST_EN_POS 1
#define APBMISC_LDO_BOD_INT_EN_POS 2
#define APBMISC_LDO_LVD_INT_EN_POS 3
#define APBMISC_BK_VBK_TEST_EN_POS 4
//================================
typedef union //0x084
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0 ---Ignore me
uint32_t DPLL2_LOCK_READY: 1; // bit1
uint32_t LVD_MODE: 1; // bit2 ---
// 0: 1.8V IO voltage
// 1: 3.3V IO valtage
uint32_t RSV_END: 29; // bit[31:3]
};
uint32_t Word;
} APBMISC_ANAMISC_ST_TypeDef; //0x07c
//================================
#define APBMISC_DPLL2_LOCK_READY_POS 1
#define APBMISC_LVD_MODE_POS 2
//================================
//================================
//BLOCK APBMISC top struct define
typedef struct
{
__I APBMISC_RC32K_CALIB_ST_TypeDef RC32K_CALIB_ST ; // 0x000,
__IO APBMISC_RCCALIB_CTRL_TypeDef RCCALIB_CTRL ; // 0x004,
__O uint32_t RCCALIB_START ; // 0x008,
// RC32K calib follow
// 0: set AON.rc32k_trim_sel =1
// 1: select calib ref clock: RCC.rccalib_clksel, enable calib clock : RCC.rccalib_clken=1
// 2: config rccalib_target and rccalib_cycles, set rccalib_start as 1
// 3: wait rccalib_done as 1
// 4: set rccalib_done_clr as 1 to clear status
// 5: read rc32k_msb_calib and rc32k_lsb_calib
// 6: write AON.rc32k_msb_trim_cfg and AON.rc32k_lsb_trim_cfg
// 7: set AON.rc32k_trim_sel =0
__O uint32_t RCFREQ_GET ; // 0x00c,
// 0: config rccalib_target and rccalib_cycles, set rcfreq_get as 1
// 1: wait rcfreq_done as 1
// 2: set rcfreq_done_clr as 1 to clear status
// 3: read rc_freq_val
__I uint32_t RC_FREQ_VAL ; // 0x010,
__IO APBMISC_RCCALIB_STCLR_TypeDef RCCALIB_STCLR ; // 0x014,
__IO APBMISC_RC16M_CNT_CTRL_TypeDef RC16M_CNT_CTRL ; // 0x018,
__IO APBMISC_RTCINT_CTRL_TypeDef RTCINT_CTRL ; // 0x01c,
__IO uint32_t RTC_SEC ; // 0x020,
// direct set current RTC value
__IO uint32_t RTC_MS ; // 0x024,
// direct set current RTC value
// note rtc_sec is must set before rtc_ms
__IO uint32_t RTC_ALARM_SEC ; // 0x028,
__IO uint32_t RTC_ALARM_MS ; // 0x02c,
__I uint32_t RTC_SEC_SHD ; // 0x030,
__I uint32_t RTC_MS_SHD ; // 0x034,
__IO APBMISC_AON_PMU_CTRL_TypeDef AON_PMU_CTRL ; // 0x038,
__IO APBMISC_LDO_UD_CTRL_TypeDef LDO_UD_CTRL ; // 0x03c,
__IO uint32_t PIOA_WKUP_POS ; // 0x040,
// enable the IO posedge wakeup the chip from deepsleep or poweroff
// IO0 ~ IO18
__IO uint32_t PIOA_WKUP_NEG ; // 0x044,
// enable the IO negedge wakeup the chip from deepsleep or poweroff
// IO0 ~ IO19
__O uint32_t POWEROFF_WORD_CMD ; // 0x048,
// software POWEROFF cmd
// when poweroff_word_cmd[31:0] is written as 32'h77ED_29B4, chip go to POWEROFF
__O uint32_t POWEROFF_LOG_CLR ; // 0x04c,
__IO uint32_t RC16M_FREQ_TRIM ; // 0x050,
// RC16M trim reg
__IO APBMISC_XOSC16M_CTRL_TypeDef XOSC16M_CTRL ; // 0x054,
__IO APBMISC_BLE_LP_CTRL_TypeDef BLE_LP_CTRL ; // 0x058,
__I uint32_t BLE_SYNC_TIME ; // 0x05c,
// the time from pos of sync_window to syncfound
// unit : 16M clock period
// ble_sync_time[19:4] is us
__IO uint32_t BLE_FINECNT_BOUND ; // 0x060,
// finecnt boundary
// set the half slot time : ( ble_finecnt_bound + 1 ) *0.5 us
// unit : 0.5us
// default is 312.5us ( BLE half slot time)
__I uint32_t BLE_CLKNCNT_SAMP ; // 0x064,
__I uint32_t BLE_FINECNT_SAMP ; // 0x068,
__O uint32_t BLE_CLKNCNT_CFG ; // 0x06c,
__O uint32_t BLE_FINECNT_CFG ; // 0x070,
__IO uint32_t BLE_DP_TWCORE ; // 0x074,
// the threhold for BB remained deepsleep time for Core go into Deepsleep
// unit: RC32K clock
// default is 5ms
__O uint32_t BLE_UPLOAD ; // 0x078,
// set as 1 when chip exit from poweroff and write back the BB reg
__IO APBMISC_DPLL_CTRL_TypeDef DPLL_CTRL ; // 0x07c,
__IO APBMISC_ANAMISC_CTRL_TypeDef ANAMISC_CTRL ; // 0x080,
__I APBMISC_ANAMISC_ST_TypeDef ANAMISC_ST ; // 0x084,
} APBMISC_TypeDef;
#define APBMISC (( APBMISC_TypeDef *) APBMISC_BASE)
#endif

29
core/reg/reg_base.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef REG_BASE_H_
#define REG_BASE_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define __I volatile const /* defines 'read only' permissions */
#define __O volatile /* defines 'write only' permissions */
#define __IO volatile /* defines 'read / write' permissions */
#define REG_RD(addr) (*(volatile uint32_t *)(addr))
#define REG_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value)
/*
* This macro is for use by other macros to form a fully valid C statement.
* Without this, the if/else conditionals could show unexpected behavior.
* (The while condition below evaluates false without generating a
* constant-controlling-loop type of warning on most compilers.)
*/
#if !defined(dowl)
#define dowl(x) do { x } while(__LINE__ == -1)
#endif
#if defined ( __CC_ARM )
#pragma anon_unions
#endif
#endif // REG_BASE_H_

105
core/reg/reg_btmr.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef _REG_BTMR_H_
#define _REG_BTMR_H_
#include "reg_base.h"
//================================
//BLOCK BTMR define
#define BTMR_BASE ((uint32_t)0x40020000)
#define BTMR_CR1_ADDR_OFFSET 0x000
#define BTMR_CR2_ADDR_OFFSET 0x004
#define BTMR_IER_ADDR_OFFSET 0x00c
#define BTMR_IDR_ADDR_OFFSET 0x010
#define BTMR_IVS_ADDR_OFFSET 0x014
#define BTMR_RIF_ADDR_OFFSET 0x018
#define BTMR_IFM_ADDR_OFFSET 0x01c
#define BTMR_ICR_ADDR_OFFSET 0x020
#define BTMR_EGR_ADDR_OFFSET 0x024
#define BTMR_CNT_ADDR_OFFSET 0x034
#define BTMR_PSC_ADDR_OFFSET 0x038
#define BTMR_ARR_ADDR_OFFSET 0x03c
#define BTMR_DMAEN_ADDR_OFFSET 0x058
//================================
//BLOCK BTMR reg struct define
typedef union //0x000
{
struct
{
uint32_t CEN: 1; // bit0 --- counter enable
uint32_t UDIS: 1; // bit1 --- update disable
uint32_t URS: 1; // bit2 --- update request source
uint32_t OPM: 1; // bit3 --- one plus mode
uint32_t RSV_NOUSE1: 3; // bit[6:4]-Ignore me
uint32_t ARPE: 1; // bit7 --- auto reload preload enable
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} BTMR_CR1_TypeDef; //0x000
//================================
#define BTMR_CEN_POS 0
#define BTMR_UDIS_POS 1
#define BTMR_URS_POS 2
#define BTMR_OPM_POS 3
#define BTMR_ARPE_POS 7
//================================
typedef union //0x004
{
struct
{
uint32_t RSV_NOUSE1: 4; // bit[3:0] --- Ignore me
uint32_t MMS: 3; // bit[6:4] --- master mode select=
uint32_t RSV_END: 25; // bit[31:7]
};
uint32_t Word;
} BTMR_CR2_TypeDef; //0x004
//================================
#define BTMR_MMS_LSB 4
#define BTMR_MMS_WIDTH 3
//================================
//================================
//BLOCK BTMR top struct define
typedef struct
{
__IO BTMR_CR1_TypeDef CR1 ; // 0x000,
// control register 1
__IO BTMR_CR2_TypeDef CR2 ; // 0x004,
// control register 2
__I uint32_t RSV0[1] ;
__O uint32_t IER ; // 0x00c,
// interrupt enable register
__O uint32_t IDR ; // 0x010,
// interrupt disable register
__I uint32_t IVS ; // 0x014,
// interrupt vaild status register
__I uint32_t RIF ; // 0x018,
// interrupt raw flag register
__I uint32_t IFM ; // 0x01c,
// interrupt masked flag register
__O uint32_t ICR ; // 0x020,
// interrupt clear status register
__IO uint32_t EGR ; // 0x024,
// event generation register
__I uint32_t RSV1[3] ;
__IO uint32_t CNT ; // 0x034,
// timer counter
__IO uint32_t PSC ; // 0x038,
// prescaler
__IO uint32_t ARR ; // 0x03c,
// auto-reload register
__I uint32_t RSV2[6] ;
__IO uint32_t DMAEN ; // 0x058,
// dma trigger event enable
} BTMR_TypeDef;
#define BTMR (( BTMR_TypeDef *) BTMR_BASE)
#endif

198
core/reg/reg_cache.h Normal file
View File

@ -0,0 +1,198 @@
#ifndef _REG_CACHE_H_
#define _REG_CACHE_H_
#include "reg_base.h"
//================================
//BLOCK CACHE define
#define CACHE_BASE ((uint32_t)0x19000000)
#define CACHE_CCR_ADDR_OFFSET 0x000
#define CACHE_CCFR_ADDR_OFFSET 0x004
#define CACHE_CIR_ADDR_OFFSET 0x008
#define CACHE_CRCR0_ADDR_OFFSET 0x00c
#define CACHE_CRCR1_ADDR_OFFSET 0x010
#define CACHE_CRCR2_ADDR_OFFSET 0x014
#define CACHE_CRCR3_ADDR_OFFSET 0x018
//================================
//BLOCK CACHE reg struct define
typedef union //0x000
{
struct
{
uint32_t CACHE_EN: 1; // bit0 ---
// 0: cache disable
// 1: cache enable
uint32_t RESERVED: 31; // bit[31:1]
};
uint32_t Word;
} CACHE_CCR_TypeDef; //0x000
//================================
#define CACHE_CACHE_EN_POS 0
#define CACHE_RESERVED_LSB 1
#define CACHE_RESERVED_WIDTH 31
//================================
typedef union //0x004
{
struct
{
uint32_t RSV_NOUSE1: 3; // bit[2:0] --- Ignore me
uint32_t CACHE_INST_DATA: 1; // bit3 the control bits of cached data type configuration
// 0: only instruction data can be cached
// 1: both instruction and common data can be cached
// note: it requires that arb_xx_hprot[0] indicate whether this access is instruction data
// request or common data request
uint32_t RSV_END: 28; // bit[31:4]
};
uint32_t Word;
} CACHE_CCFR_TypeDef; //0x004
//================================
#define CACHE_CACHE_INST_DATA_POS 3
//================================
typedef union //0x008
{
struct
{
uint32_t INV_ALL: 1; // bit0 --- The control bit of invalid all cache lines operation. Set this
// bit to start an invalid all cache lines operation, and the bit
// will be cleared when the operation is done.
uint32_t INV_ONE: 1; // bit1 --- The control bit of invalid one cache line operation. Set this
// bit to start an invalid one cache line operation, and the bit
// will be cleared when the operation is done.
uint32_t RSV_NOUSE1: 2; // bit[3:2] --- Ignore me
uint32_t INV_ADDR: 28; // bit[31:4]--- The high bits of cache line address of invalid one cache
// line operation.
};
uint32_t Word;
} CACHE_CIR_TypeDef; //0x008
//================================
#define CACHE_INV_ALL_POS 0
#define CACHE_INV_ONE_POS 1
#define CACHE_INV_ADDR_LSB 4
#define CACHE_INV_ADDR_WIDTH 28
//================================
typedef union //0x00c
{
struct
{
uint32_t CRCR0_EN: 1; // bit0 --- Cache region enable bit. Only enable bit is set that the
// cacheable region is valid.
uint32_t SIZE: 5; // bit[5:1] --- These control bits indicate the size of cacheable region.
// Detail is shown below table.
uint32_t RSV_NOUSE1: 4; // bit[9:6] --- Ignore me
uint32_t BASE_ADDR: 22; // bit[31:10]-- High 22 bits of base address of cacheable region.
};
uint32_t Word;
} CACHE_CRCR0_TypeDef; //0x00c
//================================
#define CACHE_CRCR0_EN_POS 0
#define CACHE_SIZE_LSB 1
#define CACHE_SIZE_WIDTH 5
#define CACHE_BASE_ADDR_LSB 10
#define CACHE_BASE_ADDR_WIDTH 22
//================================
typedef union //0x010
{
struct
{
uint32_t CRCR1_EN: 1; // bit0 --- Cache region enable bit. Only enable bit is set that the
// cacheable region is valid.
uint32_t SIZE: 5; // bit[5:1] --- These control bits indicate the size of cacheable region.
// Detail is shown below table.
uint32_t RSV_NOUSE1: 4; // bit[9:6] --- Ignore me
uint32_t BASE_ADDR: 22; // bit[31:10]-- High 22 bits of base address of cacheable region.
};
uint32_t Word;
} CACHE_CRCR1_TypeDef; //0x010
//================================
#define CACHE_CRCR1_EN_POS 0
#define CACHE_SIZE_LSB 1
#define CACHE_SIZE_WIDTH 5
#define CACHE_BASE_ADDR_LSB 10
#define CACHE_BASE_ADDR_WIDTH 22
//================================
typedef union //0x014
{
struct
{
uint32_t CRCR2_EN: 1; // bit0 --- Cache region enable bit. Only enable bit is set that the
// cacheable region is valid.
uint32_t SIZE: 5; // bit[5:1] --- These control bits indicate the size of cacheable region.
// Detail is shown below table.
uint32_t RSV_NOUSE1: 4; // bit[9:6] --- Ignore me
uint32_t BASE_ADDR: 22; // bit[31:10]-- High 22 bits of base address of cacheable region.
};
uint32_t Word;
} CACHE_CRCR2_TypeDef; //0x014
//================================
#define CACHE_CRCR2_EN_POS 0
#define CACHE_SIZE_LSB 1
#define CACHE_SIZE_WIDTH 5
#define CACHE_BASE_ADDR_LSB 10
#define CACHE_BASE_ADDR_WIDTH 22
//================================
typedef union //0x018
{
struct
{
uint32_t CRCR3_EN: 1; // bit0 --- Cache region enable bit. Only enable bit is set that the
// cacheable region is valid.
uint32_t SIZE: 5; // bit[5:1] --- These control bits indicate the size of cacheable region.
// Detail is shown below table.
uint32_t RSV_NOUSE1: 4; // bit[9:6] --- Ignore me
uint32_t BASE_ADDR: 22; // bit[31:10]-- High 22 bits of base address of cacheable region.
};
uint32_t Word;
} CACHE_CRCR3_TypeDef; //0x018
//================================
#define CACHE_CRCR3_EN_POS 0
#define CACHE_SIZE_LSB 1
#define CACHE_SIZE_WIDTH 5
#define CACHE_BASE_ADDR_LSB 10
#define CACHE_BASE_ADDR_WIDTH 22
//================================
//================================
//BLOCK CACHE top struct define
typedef struct
{
__IO CACHE_CCR_TypeDef CCR ; // 0x000,
// This register is responsible for making cache enable or disable.
__IO CACHE_CCFR_TypeDef CCFR ; // 0x004,
// This register controls the software configuration of cache. Note: The cache should be disabled before
// changing the configuration, or fatal errors may occur.
__IO CACHE_CIR_TypeDef CIR ; // 0x008,
// This register controls the invalid operation for cache, including invalid one cache line and invalid all.
__IO CACHE_CRCR0_TypeDef CRCR0 ; // 0x00c,
// This register controls the cacheable region. Request address must locate in the cacheable region and this
// region is enabled, or read data will not be cached.
__IO CACHE_CRCR1_TypeDef CRCR1 ; // 0x010,
__IO CACHE_CRCR2_TypeDef CRCR2 ; // 0x014,
__IO CACHE_CRCR3_TypeDef CRCR3 ; // 0x018,
} CACHE_TypeDef;
#define CACHE (( CACHE_TypeDef *) CACHE_BASE)
#endif

273
core/reg/reg_csc.h Normal file
View File

@ -0,0 +1,273 @@
#ifndef _REG_CSC_H_
#define _REG_CSC_H_
#include "reg_base.h"
//================================
//BLOCK CSC define
#define CSC_BASE ((uint32_t)0x40002000)
#define CSC_OUT_CTRL0_ADDR_OFFSET 0x000
#define CSC_OUT_CTRL1_ADDR_OFFSET 0x004
#define CSC_OUT_CTRL2_ADDR_OFFSET 0x008
#define CSC_OUT_CTRL3_ADDR_OFFSET 0x00c
#define CSC_OUT_CTRL4_ADDR_OFFSET 0x010
#define CSC_OUT_CTRL5_ADDR_OFFSET 0x014
#define CSC_OUT_CTRL6_ADDR_OFFSET 0x018
#define CSC_OUT_CTRL7_ADDR_OFFSET 0x01c
#define CSC_OUT_CTRL8_ADDR_OFFSET 0x020
#define CSC_OUT_CTRL9_ADDR_OFFSET 0x024
#define CSC_OUT_CTRL10_ADDR_OFFSET 0x028
#define CSC_OUT_CTRL11_ADDR_OFFSET 0x02c
#define CSC_OUT_CTRL12_ADDR_OFFSET 0x030
#define CSC_OUT_CTRL13_ADDR_OFFSET 0x034
#define CSC_OUT_CTRL14_ADDR_OFFSET 0x038
#define CSC_OUT_CTRL15_ADDR_OFFSET 0x03c
#define CSC_OUT_CTRL16_ADDR_OFFSET 0x040
#define CSC_OUT_CTRL17_ADDR_OFFSET 0x044
#define CSC_OUT_CTRL18_ADDR_OFFSET 0x048
#define CSC_OUT_CTRL19_ADDR_OFFSET 0x04c
#define CSC_IN_CTRL0_ADDR_OFFSET 0x080
#define CSC_IN_CTRL1_ADDR_OFFSET 0x084
#define CSC_IN_CTRL2_ADDR_OFFSET 0x088
#define CSC_IN_CTRL3_ADDR_OFFSET 0x08c
#define CSC_IN_CTRL4_ADDR_OFFSET 0x090
#define CSC_IN_CTRL5_ADDR_OFFSET 0x094
#define CSC_IN_CTRL6_ADDR_OFFSET 0x098
#define CSC_IN_CTRL7_ADDR_OFFSET 0x09c
#define CSC_IN_CTRL8_ADDR_OFFSET 0x0a0
#define CSC_IN_CTRL9_ADDR_OFFSET 0x0a4
#define CSC_IN_CTRL10_ADDR_OFFSET 0x0a8
#define CSC_IN_CTRL11_ADDR_OFFSET 0x0ac
#define CSC_IN_CTRL12_ADDR_OFFSET 0x0b0
#define CSC_IN_CTRL13_ADDR_OFFSET 0x0b4
#define CSC_PIOA00_CTRL_ADDR_OFFSET 0x100
#define CSC_PIOA01_CTRL_ADDR_OFFSET 0x104
#define CSC_PIOA02_CTRL_ADDR_OFFSET 0x108
#define CSC_PIOA03_CTRL_ADDR_OFFSET 0x10c
#define CSC_PIOA04_CTRL_ADDR_OFFSET 0x110
#define CSC_PIOA05_CTRL_ADDR_OFFSET 0x114
#define CSC_PIOA06_CTRL_ADDR_OFFSET 0x118
#define CSC_PIOA07_CTRL_ADDR_OFFSET 0x11c
#define CSC_PIOA08_CTRL_ADDR_OFFSET 0x120
#define CSC_PIOA09_CTRL_ADDR_OFFSET 0x124
#define CSC_PIOA10_CTRL_ADDR_OFFSET 0x128
#define CSC_PIOA11_CTRL_ADDR_OFFSET 0x12c
#define CSC_PIOA12_CTRL_ADDR_OFFSET 0x130
#define CSC_PIOA13_CTRL_ADDR_OFFSET 0x134
#define CSC_PIOA14_CTRL_ADDR_OFFSET 0x138
#define CSC_PIOA15_CTRL_ADDR_OFFSET 0x13c
#define CSC_PIOA16_CTRL_ADDR_OFFSET 0x140
#define CSC_PIOA17_CTRL_ADDR_OFFSET 0x144
#define CSC_PIOA18_CTRL_ADDR_OFFSET 0x148
#define CSC_PIOA19_CTRL_ADDR_OFFSET 0x14c
#define CSC_FSH_IO_CTRL_RUN_ADDR_OFFSET 0x180
#define CSC_FSH_IO_CTRL_DP_ADDR_OFFSET 0x184
typedef union
{
struct
{
uint32_t FSEL: 3; // bit[2:0] --- function select
uint32_t RSV_NOUSE1: 2; // bit[4:3] --- Ignore me
uint32_t DS: 1; // bit5 --- drive strength mode
uint32_t PUPDCTRL: 2; // bit[7:6] --- pull up/down
uint32_t IE: 1; // bit8 --- input enable
uint32_t CE: 1; // bit9 --- 1ma current spurce enable
uint32_t AE: 1; // bit10 --- analog enable
uint32_t ODE: 1; // bit11 --- open drain enable
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} CSC_IO_CTRL_TypeDef;
//================================
#define CSC_IO_FSEL_LSB 0
#define CSC_IO_FSEL_WIDTH 3
#define CSC_IO_DS_POS 5
#define CSC_IO_PUPDCTRL_LSB 6
#define CSC_IO_PUPDCTRL_WIDTH 2
#define CSC_IO_IE_POS 8
#define CSC_IO_CE_POS 9
#define CSC_IO_AE_POS 10
#define CSC_IO_ODE_POS 11
//================================
//
typedef union //0x000
{
struct
{
uint32_t CSC_FSEL: 5; // bit[4:0] --- pad output function select
// padio0 sel pad port, for example:pioa00,pioa01...
uint32_t RSV_NOUSE1: 2; // bit[6:5] --- Ignore me
uint32_t CSC_FEN: 1; // bit7 --- csc peripheral function enable
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} CSC_OUTPUT_CTRL_TypeDef;
//================================
#define CSC_FOUT_SEL_LSB 0
#define CSC_FOUT_SEL_WIDTH 5
#define CSC_FOUT_EN_POS 7
//================================
typedef union //0x000
{
struct
{
uint32_t CSC_FSEL: 5; // bit[4:0] --- pad input function select
// padio0 sel pad port, for example:pioa00,pioa01...
uint32_t RSV_NOUSE1: 2; // bit[6:5] --- Ignore me
uint32_t CSC_FEN: 1; // bit7 --- csc peripheral function enable
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} CSC_INPUT_CTRL_TypeDef;
//================================
#define CSC_FIN_SEL_LSB 0
#define CSC_FIN_SEL_WIDTH 5
#define CSC_FIN_EN_POS 7
//================================
typedef union //0x180
{
struct
{
uint32_t QSCK_OE_EN_RUN: 1; // bit0
uint32_t QSCK_PUPDCTRL_RUN: 2; // bit[2:1]
uint32_t QSCK_IE_RUN: 1; // bit3
uint32_t QCSN_OE_EN_RUN: 1; // bit4
uint32_t QCSN_PUPDCTRL_RUN: 2; // bit[6:5]
uint32_t QCSN_IE_RUN: 1; // bit7
uint32_t QIO0_OE_EN_RUN: 1; // bit8
uint32_t QIO0_PUPDCTRL_RUN: 2; // bit[10:9]
uint32_t QIO0_IE_RUN: 1; // bit11
uint32_t QIO1_OE_EN_RUN: 1; // bit12
uint32_t QIO1_PUPDCTRL_RUN: 2; // bit[14:13]
uint32_t QIO1_IE_RUN: 1; // bit15
uint32_t QIO2_OE_EN_RUN: 1; // bit16
uint32_t QIO2_PUPDCTRL_RUN: 2; // bit[18:17]
uint32_t QIO2_IE_RUN: 1; // bit19
uint32_t QIO3_OE_EN_RUN: 1; // bit20
uint32_t QIO3_PUPDCTRL_RUN: 2; // bit[22:21]
uint32_t QIO3_IE_RUN: 1; // bit23
uint32_t QSCK_DS_RUN: 1; // bit24
uint32_t QCSN_DS_RUN: 1; // bit25
uint32_t QIO0_DS_RUN: 1; // bit26
uint32_t QIO1_DS_RUN: 1; // bit27
uint32_t QIO2_DS_RUN: 1; // bit28
uint32_t QIO3_DS_RUN: 1; // bit29
uint32_t RSV_END: 2; // bit[31:30]
};
uint32_t Word;
} CSC_FSH_PAD_RUN_CTRL_TypeDef; //0x180
//================================
#define CSC_QSCK_OE_EN_RUN_POS 0
#define CSC_QSCK_PUPDCTRL_RUN_LSB 1
#define CSC_QSCK_PUPDCTRL_RUN_WIDTH 2
#define CSC_QSCK_IE_RUN_POS 3
#define CSC_QCSN_OE_EN_RUN_POS 4
#define CSC_QCSN_PUPDCTRL_RUN_LSB 5
#define CSC_QCSN_PUPDCTRL_RUN_WIDTH 2
#define CSC_QCSN_IE_RUN_POS 7
#define CSC_QIO0_OE_EN_RUN_POS 8
#define CSC_QIO0_PUPDCTRL_RUN_LSB 9
#define CSC_QIO0_PUPDCTRL_RUN_WIDTH 2
#define CSC_QIO0_IE_RUN_POS 11
#define CSC_QIO1_OE_EN_RUN_POS 12
#define CSC_QIO1_PUPDCTRL_RUN_LSB 13
#define CSC_QIO1_PUPDCTRL_RUN_WIDTH 2
#define CSC_QIO1_IE_RUN_POS 15
#define CSC_QIO2_OE_EN_RUN_POS 16
#define CSC_QIO2_PUPDCTRL_RUN_LSB 17
#define CSC_QIO2_PUPDCTRL_RUN_WIDTH 2
#define CSC_QIO2_IE_RUN_POS 19
#define CSC_QIO3_OE_EN_RUN_POS 20
#define CSC_QIO3_PUPDCTRL_RUN_LSB 21
#define CSC_QIO3_PUPDCTRL_RUN_WIDTH 2
#define CSC_QIO3_IE_RUN_POS 23
#define CSC_QSCK_DS_RUN_POS 24
#define CSC_QCSN_DS_RUN_POS 25
#define CSC_QIO0_DS_RUN_POS 26
#define CSC_QIO1_DS_RUN_POS 27
#define CSC_QIO2_DS_RUN_POS 28
#define CSC_QIO3_DS_RUN_POS 29
//================================
typedef union //0x184
{
struct
{
uint32_t QSCK_OE_EN_DP: 1; // bit0
uint32_t QSCK_PUPDCTRL_DP: 2; // bit[2:1]
uint32_t QSCK_IE_DP: 1; // bit3
uint32_t QCSN_OE_EN_DP: 1; // bit4
uint32_t QCSN_PUPDCTRL_DP: 2; // bit[6:5]
uint32_t QCSN_IE_DP: 1; // bit7
uint32_t QIO0_OE_EN_DP: 1; // bit8
uint32_t QIO0_PUPDCTRL_DP: 2; // bit[10:9]
uint32_t QIO0_IE_DP: 1; // bit11
uint32_t QIO1_OE_EN_DP: 1; // bit12
uint32_t QIO1_PUPDCTRL_DP: 2; // bit[14:13]
uint32_t QIO1_IE_DP: 1; // bit15
uint32_t QIO2_OE_EN_DP: 1; // bit16
uint32_t QIO2_PUPDCTRL_DP: 2; // bit[18:17]
uint32_t QIO2_IE_DP: 1; // bit19
uint32_t QIO3_OE_EN_DP: 1; // bit20
uint32_t QIO3_PUPDCTRL_DP: 2; // bit[22:21]
uint32_t QIO3_IE_DP: 1; // bit23
uint32_t RSV_END: 8; // bit[31:24]
};
uint32_t Word;
} CSC_FSH_PAD_DP_CTRL_TypeDef; //0x184
//================================
#define CSC_QSCK_OE_EN_DP_POS 0
#define CSC_QSCK_PUPDCTRL_DP_LSB 1
#define CSC_QSCK_PUPDCTRL_DP_WIDTH 2
#define CSC_QSCK_IE_DP_POS 3
#define CSC_QCSN_OE_EN_DP_POS 4
#define CSC_QCSN_PUPDCTRL_DP_LSB 5
#define CSC_QCSN_PUPDCTRL_DP_WIDTH 2
#define CSC_QCSN_IE_DP_POS 7
#define CSC_QIO0_OE_EN_DP_POS 8
#define CSC_QIO0_PUPDCTRL_DP_LSB 9
#define CSC_QIO0_PUPDCTRL_DP_WIDTH 2
#define CSC_QIO0_IE_DP_POS 11
#define CSC_QIO1_OE_EN_DP_POS 12
#define CSC_QIO1_PUPDCTRL_DP_LSB 13
#define CSC_QIO1_PUPDCTRL_DP_WIDTH 2
#define CSC_QIO1_IE_DP_POS 15
#define CSC_QIO2_OE_EN_DP_POS 16
#define CSC_QIO2_PUPDCTRL_DP_LSB 17
#define CSC_QIO2_PUPDCTRL_DP_WIDTH 2
#define CSC_QIO2_IE_DP_POS 19
#define CSC_QIO3_OE_EN_DP_POS 20
#define CSC_QIO3_PUPDCTRL_DP_LSB 21
#define CSC_QIO3_PUPDCTRL_DP_WIDTH 2
#define CSC_QIO3_IE_DP_POS 23
//================================
//================================
//BLOCK CSC top struct define
typedef struct
{
__IO CSC_OUTPUT_CTRL_TypeDef CSC_OUTPUT[20] ; // 0x000 ~ 0x04C,
__I uint32_t RSV0[12] ; // 0x050 ~ 0x07C,
__IO CSC_INPUT_CTRL_TypeDef CSC_INPUT[14] ; // 0x080 ~ 0x0B4,
__I uint32_t RSV1[18] ; // 0x0B8 ~ 0x0FC,
__IO CSC_IO_CTRL_TypeDef CSC_PIO[20] ; // 0x100 ~ 0x14C,
__I uint32_t RSV2[12] ; // 0x150 ~ 0x17C
__IO CSC_FSH_PAD_RUN_CTRL_TypeDef FSH_PAD_RUN_CTRL ; // 0x180,
__IO CSC_FSH_PAD_DP_CTRL_TypeDef FSH_PAD_DP_CTRL ; // 0x184,
} CSC_TypeDef;
#define CSC (( CSC_TypeDef *) CSC_BASE)
#endif

166
core/reg/reg_dma.h Normal file
View File

@ -0,0 +1,166 @@
#ifndef _REG_DMA_H_
#define _REG_DMA_H_
#include "reg_base.h"
//================================
//BLOCK DMA define
#define DMA_BASE ((uint32_t)0x40026000)
#define DMA_STATUS_ADDR_OFFSET 0x000
#define DMA_CFG_ADDR_OFFSET 0x004
#define DMA_CTRLBASE_POINTER_ADDR_OFFSET 0x008
#define DMA_ALTCTRLBASE_POINTER_ADDR_OFFSET 0x00c
#define DMA_WAIT_REQ_STA_ADDR_OFFSET 0x010
#define DMA_SOFT_REQ_ADDR_OFFSET 0x014
#define DMA_USEBURST_SET_ADDR_OFFSET 0x018
#define DMA_USEBURST_CLR_ADDR_OFFSET 0x01c
#define DMA_REQMSK_SET_ADDR_OFFSET 0x020
#define DMA_REQMSK_CLR_ADDR_OFFSET 0x024
#define DMA_CHNL_EN_SET_ADDR_OFFSET 0x028
#define DMA_CHNL_EN_CLR_ADDR_OFFSET 0x02c
#define DMA_PRIALT_SET_ADDR_OFFSET 0x030
#define DMA_PRIALT_CLR_ADDR_OFFSET 0x034
#define DMA_PRIORITY_SET_ADDR_OFFSET 0x038
#define DMA_PRIORITY_CLR_ADDR_OFFSET 0x03c
#define DMA_ERR_CLR_ADDR_OFFSET 0x04c
#define DMA_INTEGR_CFG_ADDR_OFFSET 0xe00
#define DMA_STALL_STA_ADDR_OFFSET 0xe08
#define DMA_REQ_STA_ADDR_OFFSET 0xe10
#define DMA_SREQ_STA_ADDR_OFFSET 0xe18
#define DMA_DONE_SET_ADDR_OFFSET 0xe20
#define DMA_DONE_CLR_ADDR_OFFSET 0xe24
#define DMA_ACTIVE_SET_ADDR_OFFSET 0xe28
#define DMA_ACTIVE_CLR_ADDR_OFFSET 0xe2c
#define DMA_ERR_SET_ADDR_OFFSET 0xe48
//================================
//BLOCK DMA reg struct define
typedef union //0x000
{
struct
{
uint32_t EN: 1; // bit0 ---
// 0: controller is disabled
// 1: controller is enabled
uint32_t RSV_NOUSE1: 3; // bit[3:1] --- Ignore me
uint32_t STATE: 4; // bit[7:4] --- current state of the control state machine
uint32_t RSV_NOUSE2: 8; // bit[15:8]--- Ignore me
uint32_t CHNLS_MINUS1: 5; // bit[20:16]-- number of availiable dma channels minus one
// for example 00000 = controller configured to use 1 dma channel
uint32_t RSV_NOUSE3: 7; // bit[27:21]-- Ignore me
uint32_t TEST_STATUS: 4; // bit[31:28]--
// 0: controller does not include the integration test logic
// 1: controller include the integration test logic
// 2-0xf = undefined
};
uint32_t Word;
} DMA_STATUS_TypeDef; //0x000
//================================
#define DMA_EN_POS 0
#define DMA_STATE_LSB 4
#define DMA_STATE_WIDTH 4
#define DMA_CHNLS_MINUS1_LSB 16
#define DMA_CHNLS_MINUS1_WIDTH 5
#define DMA_TEST_STATUS_LSB 28
#define DMA_TEST_STATUS_WIDTH 4
//================================
typedef union //0x004
{
struct
{
uint32_t EN: 1; // bit0 --- enble the controller
uint32_t RSV_NOUSE1: 4; // bit[4:1] --- Ignore me
uint32_t CHNL_PROT_CTRL: 3; // bit[7:5] --- [5]cacheable, [6]bufferable, [7]priviledged
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} DMA_CFG_TypeDef; //0x004
//================================
#define DMA_EN_POS 0
#define DMA_CHNL_PROT_CTRL_LSB 5
#define DMA_CHNL_PROT_CTRL_WIDTH 3
//================================
typedef union //0x008
{
struct
{
uint32_t RSV_NOUSE1: 8; // bit[7:0] --- Ignore me
uint32_t CTRL_BASE_PTR: 24; // bit[31:8]--- pointer to the base address of the primary data structure
};
uint32_t Word;
} DMA_CTRLBASE_POINTER_TypeDef; //0x008
//================================
#define DMA_CTRL_BASE_PTR_LSB 8
#define DMA_CTRL_BASE_PTR_WIDTH 24
//================================
//================================
//BLOCK DMA top struct define
typedef struct
{
__I DMA_STATUS_TypeDef STATUS ; // 0x000,
__O DMA_CFG_TypeDef CFG ; // 0x004,
__IO DMA_CTRLBASE_POINTER_TypeDef CTRLBASE_POINTER ; // 0x008,
__I uint32_t ALTCTRLBASE_POINTER ; // 0x00c,
__I uint32_t WAIT_REQ_STA ; // 0x010,
// channel 0 wait on request status
__O uint32_t SOFT_REQ ; // 0x014,
// channel 0 generate a software dma request
__IO uint32_t USEBURST_SET ; // 0x018,
// disable dma_sreq[0] generating dma requests
__IO uint32_t USEBURST_CLR ; // 0x01c,
// enable dma_sreq[0] dma requests
__IO uint32_t REQMSK_SET ; // 0x020,
// disable channel[0] generating dma requests
__IO uint32_t REQMSK_CLR ; // 0x024,
// enable channel[0] generating dma requests
__IO uint32_t CHNL_EN_SET ; // 0x028,
// enable channel[0]
__IO uint32_t CHNL_EN_CLR ; // 0x02c,
// disable channel[0]
__IO uint32_t PRIALT_SET ; // 0x030,
// config channel[] to use the alternate data structure
__IO uint32_t PRIALT_CLR ; // 0x034,
// config channel[0] to use the primary data structure
__IO uint32_t PRIORITY_SET ; // 0x038,
// config channel[0] priority
__IO uint32_t PRIORITY_CLR ; // 0x03c,
// clr channel[0] priority
__I uint32_t RSV0[3] ;
__IO uint32_t ERR_CLR ; // 0x04c,
__I uint32_t RSV1[876] ;
__IO uint32_t INTEGR_CFG ; // 0xe00,
__I uint32_t RSV2[1] ;
__I uint32_t STALL_STA ; // 0xe08,
__I uint32_t RSV3[1] ;
__I uint32_t REQ_STA ; // 0xe10,
// return status of dma_req[0]
__I uint32_t RSV4[1] ;
__I uint32_t SREQ_STA ; // 0xe18,
// return status of dma_sreq[0]
__I uint32_t RSV5[1] ;
__IO uint32_t DONE_SET ; // 0xe20,
// enable to assert dma_done[0] signals
__O uint32_t DONE_CLR ; // 0xe24,
// enable to deassert dma_done[0] signals
__IO uint32_t ACTIVE_SET ; // 0xe28,
// enable to assert dma_active[0] signals
__O uint32_t ACTIVE_CLR ; // 0xe2c,
// enable to desassert dma_active[0] signals
__I uint32_t RSV6[6] ;
__IO uint32_t ERR_SET ; // 0xe48,
} DMA_TypeDef;
#define DMA (( DMA_TypeDef *) DMA_BASE)
#endif

117
core/reg/reg_dmachcfg.h Normal file
View File

@ -0,0 +1,117 @@
#ifndef _REG_DMACHCFG_H_
#define _REG_DMACHCFG_H_
#include "reg_base.h"
//================================
//BLOCK DMACHCFG define
#define DMACHCFG_BASE ((uint32_t)0x40027000)
#define DMACHCFG_IFLAG0_ADDR_OFFSET 0x000
#define DMACHCFG_IFLAG1_ADDR_OFFSET 0x004
#define DMACHCFG_ISFR0_ADDR_OFFSET 0x008
#define DMACHCFG_ISFR1_ADDR_OFFSET 0x00c
#define DMACHCFG_ICFR0_ADDR_OFFSET 0x010
#define DMACHCFG_ICFR1_ADDR_OFFSET 0x014
#define DMACHCFG_IEFR0_ADDR_OFFSET 0x018
#define DMACHCFG_IEFR1_ADDR_OFFSET 0x01c
#define DMACHCFG_CHSEL0_CONTAIN_ADDR_OFFSET 0x100
#define DMACHCFG_CHSEL1_CONTAIN_ADDR_OFFSET 0x104
//================================
//BLOCK DMACHCFG reg struct define
typedef union //0x100
{
struct
{
uint32_t CH0_SEL: 6; // bit[5:0]
uint32_t RSV_NOUSE1: 2; // bit[7:6] --- Ignore me
uint32_t CH1_SEL: 6; // bit[13:8]
uint32_t RSV_NOUSE2: 2; // bit[15:14]-- Ignore me
uint32_t CH2_SEL: 6; // bit[21:16]
uint32_t RSV_NOUSE3: 2; // bit[23:22]-- Ignore me
uint32_t CH3_SEL: 6; // bit[29:24]
uint32_t RSV_END: 2; // bit[31:30]
};
uint32_t Word;
} DMACHCFG_CHSEL0_CONTAIN_TypeDef; //0x100
//================================
#define DMACHCFG_CH0_SEL_LSB 0
#define DMACHCFG_CH0_SEL_WIDTH 6
#define DMACHCFG_CH1_SEL_LSB 8
#define DMACHCFG_CH1_SEL_WIDTH 6
#define DMACHCFG_CH2_SEL_LSB 16
#define DMACHCFG_CH2_SEL_WIDTH 6
#define DMACHCFG_CH3_SEL_LSB 24
#define DMACHCFG_CH3_SEL_WIDTH 6
//================================
typedef union //0x104
{
struct
{
uint32_t CH4_SEL: 6; // bit[5:0]
uint32_t RSV_NOUSE1: 2; // bit[7:6] --- Ignore me
uint32_t CH5_SEL: 6; // bit[13:8]
uint32_t RSV_NOUSE2: 2; // bit[15:14]-- Ignore me
uint32_t CH6_SEL: 6; // bit[21:16]
uint32_t RSV_NOUSE3: 2; // bit[23:22]-- Ignore me
uint32_t CH7_SEL: 6; // bit[29:24]
uint32_t RSV_END: 2; // bit[31:30]
};
uint32_t Word;
} DMACHCFG_CHSEL1_CONTAIN_TypeDef; //0x104
//================================
#define DMACHCFG_CH4_SEL_LSB 0
#define DMACHCFG_CH4_SEL_WIDTH 6
#define DMACHCFG_CH5_SEL_LSB 8
#define DMACHCFG_CH5_SEL_WIDTH 6
#define DMACHCFG_CH6_SEL_LSB 16
#define DMACHCFG_CH6_SEL_WIDTH 6
#define DMACHCFG_CH7_SEL_LSB 24
#define DMACHCFG_CH7_SEL_WIDTH 6
//================================
//================================
//BLOCK DMACHCFG top struct define
typedef struct
{
__I uint32_t IFLAG0 ; // 0x000,
// dma interupt flag
__I uint32_t IFLAG1 ; // 0x004,
// dma err flag
__IO uint32_t ISFR0 ; // 0x008,
// no use
__IO uint32_t ISFR1 ; // 0x00c,
// no use
__O uint32_t ICFR0 ; // 0x010,
// clear dma channel interupt
__O uint32_t ICFR1 ; // 0x014,
// clear dma interupt error flag
__IO uint32_t IEFR0 ; // 0x018,
// enable dma channel[x] interupt
__IO uint32_t IEFR1 ; // 0x01c,
// enable dma error interrupt
__I uint32_t RSV0[56] ;
union
{
__IO uint32_t CHSEL[2];
struct
{
__IO DMACHCFG_CHSEL0_CONTAIN_TypeDef CHSEL0_CONTAIN ; // 0x100,
// include channel(0~3)
__IO DMACHCFG_CHSEL1_CONTAIN_TypeDef CHSEL1_CONTAIN ; // 0x104,
// include channel(4~7)
};
};
} DMACHCFG_TypeDef;
#define DMACHCFG (( DMACHCFG_TypeDef *) DMACHCFG_BASE)
#endif

131
core/reg/reg_exti.h Normal file
View File

@ -0,0 +1,131 @@
#ifndef _REG_EXTI_H_
#define _REG_EXTI_H_
#include "reg_base.h"
//================================
//BLOCK EXTI define
#define EXTI_BASE ((uint32_t)0x40028000)
#define EXTI_IER_ADDR_OFFSET 0x000
#define EXTI_IDR_ADDR_OFFSET 0x004
#define EXTI_IVS_ADDR_OFFSET 0x008
#define EXTI_RIF_ADDR_OFFSET 0x00c
#define EXTI_IFM_ADDR_OFFSET 0x010
#define EXTI_ICR_ADDR_OFFSET 0x014
#define EXTI_RTS_ADDR_OFFSET 0x018
#define EXTI_FTS_ADDR_OFFSET 0x01c
#define EXTI_SWI_ADDR_OFFSET 0x020
#define EXTI_ADTE_ADDR_OFFSET 0x024
#define EXTI_DB_ADDR_OFFSET 0x028
#define EXTI_DBC_ADDR_OFFSET 0x02c
//================================
//BLOCK EXTI reg struct define
typedef union //0x000
{
struct
{
uint32_t EXTI_SRC0: 1; // bit0
uint32_t EXTI_SRC1: 1; // bit1
uint32_t EXTI_SRC2: 1; // bit2
uint32_t EXTI_SRC3: 1; // bit3
uint32_t EXTI_SRC4: 1; // bit4
uint32_t EXTI_SRC5: 1; // bit5
uint32_t EXTI_SRC6: 1; // bit6
uint32_t EXTI_SRC7: 1; // bit7
uint32_t EXTI_SRC8: 1; // bit8
uint32_t EXTI_SRC9: 1; // bit9
uint32_t EXTI_SRC10: 1; // bit10
uint32_t EXTI_SRC11: 1; // bit11
uint32_t EXTI_SRC12: 1; // bit12
uint32_t EXTI_SRC13: 1; // bit13
uint32_t EXTI_SRC14: 1; // bit14
uint32_t EXTI_SRC15: 1; // bit15
uint32_t EXTI_SRC16: 1; // bit16
uint32_t EXTI_SRC17: 1; // bit17
uint32_t EXTI_SRC18: 1; // bit18
uint32_t EXTI_SRC19: 1; // bit19
uint32_t RSV_END: 12; // bit[31:20]
};
uint32_t Word;
} EXTI_LOCA_TypeDef; //0x000
//================================
#define EXTI_LOCAL_SRC0_POS 0
#define EXTI_LOCAL_SRC1_POS 1
#define EXTI_LOCAL_SRC2_POS 2
#define EXTI_LOCAL_SRC3_POS 3
#define EXTI_LOCAL_SRC4_POS 4
#define EXTI_LOCAL_SRC5_POS 5
#define EXTI_LOCAL_SRC6_POS 6
#define EXTI_LOCAL_SRC7_POS 7
#define EXTI_LOCAL_SRC8_POS 8
#define EXTI_LOCAL_SRC9_POS 9
#define EXTI_LOCAL_SRC10_POS 10
#define EXTI_LOCAL_SRC11_POS 11
#define EXTI_LOCAL_SRC12_POS 12
#define EXTI_LOCAL_SRC13_POS 13
#define EXTI_LOCAL_SRC14_POS 14
#define EXTI_LOCAL_SRC15_POS 15
#define EXTI_LOCAL_SRC16_POS 16
#define EXTI_LOCAL_SRC17_POS 17
#define EXTI_LOCAL_SRC18_POS 18
#define EXTI_LOCAL_SRC19_POS 19
//================================
typedef union //0x02c
{
struct
{
uint32_t DB_CNT: 3; // bit[2:0] --- debounce cnts, db_cnt = db_cnt_val + 1
uint32_t RSV_NOUSE1: 5; // bit[7:3] --- Ignore me
uint32_t DB_PRE: 8; // bit[15:8]--- debounce one cnt include current clk cycles, db_pre = db_pre_val + 1
uint32_t RSV_END: 16; // bit[31:16]
};
uint32_t Word;
} EXTI_DBC_TypeDef; //0x02c
//================================
#define EXTI_DB_CNT_LSB 0
#define EXTI_DB_CNT_WIDTH 3
#define EXTI_DB_PRE_LSB 8
#define EXTI_DB_PRE_WIDTH 8
//================================
//================================
//BLOCK EXTI top struct define
typedef struct
{
__O EXTI_LOCA_TypeDef IER; // 0x000,
// exti interrupt enable register
__O EXTI_LOCA_TypeDef IDR; // 0x004,
// exti interrupt disable register
__I EXTI_LOCA_TypeDef IVS; // 0x008,
// exti interrupt valid status register
__I EXTI_LOCA_TypeDef RIF; // 0x00c,
// exti raw interrupt flag status register
__I EXTI_LOCA_TypeDef IFM; // 0x010,
// exti interrupt flag masked status register
__O EXTI_LOCA_TypeDef ICR; // 0x014,
// exti interrupt clear register
__IO EXTI_LOCA_TypeDef RTS; // 0x018,
// exti rising edge trigger selection register
__IO EXTI_LOCA_TypeDef FTS; // 0x01c,
// exti falling edge trigger selection register
__IO EXTI_LOCA_TypeDef SWI; // 0x020,
// exti software interrupt event register
__IO EXTI_LOCA_TypeDef ADTE; // 0x024,
// exti ad trigger enable
__IO EXTI_LOCA_TypeDef DB; // 0x028,
// exti input debounce enable register
__IO EXTI_DBC_TypeDef DBC; // 0x02c,
// exti input debounce sample rate control register
} EXTI_TypeDef;
#define EXTI (( EXTI_TypeDef *) EXTI_BASE)
#endif

398
core/reg/reg_fshc.h Normal file
View File

@ -0,0 +1,398 @@
#ifndef _REG_FSHC_H_
#define _REG_FSHC_H_
#include "reg_base.h"
//================================
//BLOCK FSHC define
#define FSHC_BASE ((uint32_t)0x40006000)
#define FSHC_SPDR_RD_ADDR_OFFSET 0x000
#define FSHC_SPDR_WR_ADDR_OFFSET 0x004
#define FSHC_SPCR_ADDR_OFFSET 0x008
#define FSHC_RXTX_DAT_LEN_ADDR_OFFSET 0x00c
#define FSHC_CMD_REG_ADDR_OFFSET 0x010
#define FSHC_ADDR_REG_ADDR_OFFSET 0x014
#define FSHC_MCU_ADRCMD_BIT_LEN_ADDR_OFFSET 0x018
#define FSHC_SEND_CTRL_ADDR_OFFSET 0x01c
#define FSHC_SEND_EN_ADDR_OFFSET 0x020
#define FSHC_FIFO_STATUS_ADDR_OFFSET 0x024
#define FSHC_RXPTR_INC_EN_ADDR_OFFSET 0x028
#define FSHC_ST_ADDR_OFFSET 0x02c
#define FSHC_CACHE_CMD1_ADDR_OFFSET 0x030
#define FSHC_CACHE_CMD2_ADDR_OFFSET 0x034
#define FSHC_CACHE_DELAY_SET_ADDR_OFFSET 0x038
#define FSHC_CACHE_RESUME_DELAY_MAX_ADDR_OFFSET 0x03c
#define FSHC_DELAY_SET_ADDR_OFFSET 0x040
#define FSHC_BYPASS_HPM_ADDR_OFFSET 0x044
#define FSHC_ATOM_OP_EN_ADDR_OFFSET 0x048
#define FSHC_CLR_HPM_ADDR_OFFSET 0x04c
#define FSHC_CONTINUE_RD_MOD_INDEX_ADDR_OFFSET 0x050
#define FSHC_CONTINUE_STATUS_ADDR_OFFSET 0x054
#define FSHC_DLY_CFG_ADDR_OFFSET 0x058
#define FSHC_CACHE_ACCESS_STATUS_ADDR_OFFSET 0x05c
//================================
//BLOCK FSHC reg struct define
typedef union //0x008
{
struct
{
uint32_t CPOL: 1; // bit0 ---
// cpol = 1,spi_clk sample data_in at negedge,
// cpol = 0,spi_clk sample data_in at posedge,
uint32_t AUTO_CHECK_ST: 1; // bit1 --- auto_check_st is 1:
// auto read status before send suspend cmd
// note:set must before flash_busy set as 1
uint32_t FLASH_BUSY_SET: 1; // bit2 --- When this bit is set 1, cache will read flash with suspend and resume mode
// For example: flash in erase status, cache want to read, you should set this bit first;
uint32_t FLASH_BUSY_CLR: 1; // bit3 --- when auto_check_st is 0,
// use to clear flash_busy
// when auto_check_st is 1,
// use to clear flash_st_done
uint32_t FLASH_INT_EN: 1; // bit4 --- when is 1
// flash int is set when flash_st_done is 1
uint32_t RSV_END: 27; // bit[31:5]
};
uint32_t Word;
} FSHC_SPCR_TypeDef; //0x008
//================================
#define FSHC_CPOL_POS 0
#define FSHC_AUTO_CHECK_ST_POS 1
#define FSHC_FLASH_BUSY_SET_POS 2
#define FSHC_FLASH_BUSY_CLR_POS 3
#define FSHC_FLASH_INT_EN_POS 4
//================================
typedef union //0x018
{
struct
{
uint32_t MCU_ADR_MAX_LEN: 6; // bit[5:0] --- MCU adr cycle length,include dummy cycle, max is 32 bit, only 24 bit is valid, others is zero;
// we use largest flash is 16MByte, so max address bit number is 24 bit;
// transmit address with spi mode, mcu_adr_max_len = (address bit number - 1) + dummy cycle
// transmit address with qpi mode, mcu_adr_max_len = ((address bit number)/4 - 1) + dummy cycle
uint32_t MCU_CMD_MAX_LEN: 6; // bit[11:6] --- MCU cmd cycle length,include dummy cycle, max is 32 bit, only 8 bit is vaild, others is zero;
// transmit command with spi mode, mcu_cmd_max_len = 7 + dummy cycle
// transmit command with qpi mode, mcu_cmd_max_len = 1 + dummy cycle
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} FSHC_MCU_ADRCMD_BIT_LEN_TypeDef; //0x018
//================================
#define FSHC_MCU_ADR_MAX_LEN_LSB 0
#define FSHC_MCU_ADR_MAX_LEN_WIDTH 6
#define FSHC_MCU_CMD_MAX_LEN_LSB 6
#define FSHC_MCU_CMD_MAX_LEN_WIDTH 6
//================================
typedef union //0x01c
{
struct
{
uint32_t DATA_BIT_NUM: 2; // bit[1:0] --- MCU transmit data bit number
// 0/1: 1 bit spi mode, 2: 2bits dual mode, 3: 4bits quad mode
uint32_t ADDR_BIT_NUM: 2; // bit[3:2] --- MCU transmit address bit number
// 0/1: 1 bit spi mode, 2: 2bits dual mode, 3: 4bits quad mode
uint32_t CMD_BIT_NUM: 2; // bit[5:4] --- MCU transmit command bit number
// For GD, only 1bit command is used. For EON, 4bits #command can be used
// 0/1: 1 bit spi mode, 2: 2bits dual mode, 3: 4bits quad mode
uint32_t ADR_WITH_ARG: 2; // bit[7:6] --- MCU address argument
// 2'b00/2'b11: address followed by idle
// 2'b01: address followed by wdata
// 2'b10: address followed by rdata
uint32_t CMD_WITH_ARG: 3; // bit[10:8]--- MCU command argument
// 3'b011: command followed by address
// 3'b101: command followed by wdata
// 3'b110: command followed by rdata
// others: command followed by idle
uint32_t RSV_END: 21; // bit[31:11]
};
uint32_t Word;
} FSHC_SEND_CTRL_TypeDef; //0x01c
//================================
#define FSHC_DATA_BIT_NUM_LSB 0
#define FSHC_DATA_BIT_NUM_WIDTH 2
#define FSHC_ADDR_BIT_NUM_LSB 2
#define FSHC_ADDR_BIT_NUM_WIDTH 2
#define FSHC_CMD_BIT_NUM_LSB 4
#define FSHC_CMD_BIT_NUM_WIDTH 2
#define FSHC_ADR_WITH_ARG_LSB 6
#define FSHC_ADR_WITH_ARG_WIDTH 2
#define FSHC_CMD_WITH_ARG_LSB 8
#define FSHC_CMD_WITH_ARG_WIDTH 3
//================================
typedef union //0x024
{
struct
{
uint32_t RXFIFO_EMPTY: 1; // bit0 --- MCU rxfifo empty flag,when '1',fifo is empty,can't read;
// Additional one AHB cycle are needed to read this register bit versus a standard AHB read
uint32_t RXFIFO_FULL: 1; // bit1 --- MCU rxfifo full flag,when '1',fifo is full,can continue read data from rxfifo
uint32_t TXFIFO_EMPTY: 1; // bit2 --- MCU txfifo empty flag,when '1', fifo is empty,can continue write data to txfifo;
uint32_t TXFIFO_FULL: 1; // bit3 --- MCU txfifo full flag,when '1',fifo is full,can't write data to the fifo;
// Additional one AHB cycle are needed to read this register bit versus a standard AHB read
uint32_t RSV_END: 28; // bit[31:4]
};
uint32_t Word;
} FSHC_FIFO_STATUS_TypeDef; //0x024
//================================
#define FSHC_RXFIFO_EMPTY_POS 0
#define FSHC_RXFIFO_FULL_POS 1
#define FSHC_TXFIFO_EMPTY_POS 2
#define FSHC_TXFIFO_FULL_POS 3
//================================
typedef union //0x02c
{
struct
{
uint32_t CMD_SEND_STATUS: 1; // bit0 --- MCU
// 1: mcu request is not ack, can't configurate new command
// 0: allow configure new command
// Additional 3 AHB cycles are needed to read this register bit versus a standard AHB read
uint32_t FLASH_BUSY: 1; // bit1 --- set by flash_busy_set
// when auto_check_st is 0:
// cleared by flash_busy_clr
// when auto_check_st is 0:
// cleared by hardware flash_st_done
uint32_t FLASH_ST_DONE: 1; // bit2 --- only effect when auto_check_st is 1,
// cleared by flash_busy_clr
uint32_t RSV_END: 29; // bit[31:3]
};
uint32_t Word;
} FSHC_ST_TypeDef; //0x02c
//================================
#define FSHC_CMD_SEND_STATUS_POS 0
#define FSHC_FLASH_BUSY_POS 1
#define FSHC_FLASH_ST_DONE_POS 2
//================================
typedef union //0x030
{
struct
{
uint32_t READ_CMD: 8; // bit[7:0] --- Read command index,EBH,0BH etc
uint32_t SUS_CMD: 8; // bit[15:8] --- suspend command index, 75H
uint32_t RESUME_CMD: 8; // bit[23:16]--- resume command index,7AH
uint32_t HPM_CMD: 8; // bit[31:24]--- high performance mode command index,A3H
};
uint32_t Word;
} FSHC_CACHE_CMD1_TypeDef; //0x030
//================================
#define FSHC_READ_CMD_LSB 0
#define FSHC_READ_CMD_WIDTH 8
#define FSHC_SUS_CMD_LSB 8
#define FSHC_SUS_CMD_WIDTH 8
#define FSHC_RESUME_CMD_LSB 16
#define FSHC_RESUME_CMD_WIDTH 8
#define FSHC_HPM_CMD_LSB 24
#define FSHC_HPM_CMD_WIDTH 8
//================================
typedef union //0x034
{
struct
{
uint32_t EXITHPM_CMD: 8; // bit[7:0] --- exit high performance mode command index, 06H
uint32_t CONTINU_RD_MOD: 8; // bit[15:8] --- continuous read mode command, continu_rd_mod will be sent follow by address;
// Notice: continu_rd_mod and continue_rd_mod_index control flash in continuous read mode.
// Look at the continue_rd_mod_index for details.
uint32_t RD_STATUS_CMD: 8; // bit[23:16]--- read status cmd
// only used when both auto_check_st and flash_busy is 1
uint32_t RD_STATUS_MASK: 8; // bit[31:24]
};
uint32_t Word;
} FSHC_CACHE_CMD2_TypeDef; //0x034
//================================
#define FSHC_EXITHPM_CMD_LSB 0
#define FSHC_EXITHPM_CMD_WIDTH 8
#define FSHC_CONTINU_RD_MOD_LSB 8
#define FSHC_CONTINU_RD_MOD_WIDTH 8
#define FSHC_RD_STATUS_CMD_LSB 16
#define FSHC_RD_STATUS_CMD_WIDTH 8
#define FSHC_RD_STATUS_MASK_LSB 24
#define FSHC_RD_STATUS_MASK_WIDTH 8
//================================
typedef union //0x038
{
struct
{
uint32_t ADR_BIT_MAX: 5; // bit[4:0] --- Only use in cache read mode, other cache cmd don't have address.
// Cache address cycle length. adr_bit_max = address length cycle - 1 + dummy cycle.
// For example: In GD flash Quad I/O Fast Read, want address 8 cycles + dummy 4 cycles, so adr_bit_max = (8-1+4) = 11 (Decimal)
// For example: In GD flash SPI Fast Read (0BH), want address 24 cycles + dummy 8 cycles, so adr_bit_max = (24-1+8) = 31 (Decimal)
uint32_t SUS_DELAY_MAX: 16; // bit[20:5] --- Set the delay time after send hpm command,default is GigaDevice flash value(0.2us)
uint32_t HPM_DELAY_MAX: 6; // bit[26:21]--- The value of hpm_delay_max can not be 2+5n,(n=0,1,2,...) like 22,27,32,37.
// Best valus is 4+5n. like 24,29,34,39. Here 22,27,32,37 is decimal number.
// Set the delay time after sumpend command, default is GigaDevice flash value(2us)
uint32_t RSV_END: 5; // bit[31:27]
};
uint32_t Word;
} FSHC_CACHE_DELAY_SET_TypeDef; //0x038
//================================
#define FSHC_ADR_BIT_MAX_LSB 0
#define FSHC_ADR_BIT_MAX_WIDTH 5
#define FSHC_SUS_DELAY_MAX_LSB 5
#define FSHC_SUS_DELAY_MAX_WIDTH 16
#define FSHC_HPM_DELAY_MAX_LSB 21
#define FSHC_HPM_DELAY_MAX_WIDTH 6
//================================
typedef union //0x040
{
struct
{
uint32_t HPM_LEN: 6; // bit[5:0] --- hpm command length, default is 6'h1f,
// on quad command mode -------- hpm_len = (length of hpm_command)/4 - 1 + dummy cycle,
// on spi command mode -------- hpm_len = (length of hpm_command) + dummy cycle - 1
// cache_no_dummy_cmd_len/cache_cmd_len/hpm_len distinguish
// -------------------------------------------------------#
// cmd cmd length register
// hpm hpm_len
// qpi read cache_cmd_len
// suspend cache_no_dummy_cmd_len
// resume cache_no_dummy_cmd_len
// exit_hpm cache_no_dummy_cmd_len
// rst_continue cache_no_dummy_cmd_len
// set continue include in adr_bit_max
uint32_t CACHE_CMD_LEN: 4; // bit[9:6] --- only use in qpi read cmd, default is 4'h7,
// on quad command mode ----- cache_cmd_len = 1 + dummy cycle,
// on spi command mode ----- cache_cmd_len = 7 + dummy cycle
uint32_t CACHE_NO_DUMMY_CMD_LEN: 4; // bit[13:10]--- use in suspend/resume/exit_hpm cmd, default is 4'h7,
// on quad command mode -------- cache_no_dummy_cmd_len = (length of command)/4 - 1,
// on spi command mode -------- cache_no_dummy_cmd_len = (length of command) - 1.
uint32_t CACHE_ADDR_BIT_NUM: 2; // bit[15:14]--- CACHE transmit address bit number
// 0/1: 1 bit spi mode, 2: 2bits dual mode, 3: 4bits quad mode
uint32_t CACHE_CMD_BIT_NUM: 2; // bit[17:16]--- CACHE transmit command bit number
// /1: 1 bit spi mode, 2: 2bits dual mode, 3: 4bits quad mode
uint32_t CACHE_DATA_BIT_NUM: 2; // bit[19:18]--- CACHE transmit data bit number
// 0/1: 1 bit spi mode, 2: 2bits dual mode, 3: 4bits quad mod
uint32_t RSV_END: 12; // bit[31:20]
};
uint32_t Word;
} FSHC_DELAY_SET_TypeDef; //0x040
//================================
#define FSHC_HPM_LEN_LSB 0
#define FSHC_HPM_LEN_WIDTH 6
#define FSHC_CACHE_CMD_LEN_LSB 6
#define FSHC_CACHE_CMD_LEN_WIDTH 4
#define FSHC_CACHE_NO_DUMMY_CMD_LEN_LSB 10
#define FSHC_CACHE_NO_DUMMY_CMD_LEN_WIDTH 4
#define FSHC_CACHE_ADDR_BIT_NUM_LSB 14
#define FSHC_CACHE_ADDR_BIT_NUM_WIDTH 2
#define FSHC_CACHE_CMD_BIT_NUM_LSB 16
#define FSHC_CACHE_CMD_BIT_NUM_WIDTH 2
#define FSHC_CACHE_DATA_BIT_NUM_LSB 18
#define FSHC_CACHE_DATA_BIT_NUM_WIDTH 2
//================================
//================================
//BLOCK FSHC top struct define
typedef struct
{
__I uint32_t SPDR_RD ; // 0x000,
// mcu read rx fifo data via this register;
// read this register, should set rxptr_inc_en first;
// rxfifo_empty in fifo_status register,
// if rxfifo_empty is 1, means rxfifo is empty, mcu can't read
__O uint32_t SPDR_WR ; // 0x004,
// mcu write tx fifo data via this register;
// txfifo_full in fifo_status register,
// if txfifo_full is 1, means txfifo is full, mcu can't write;
__IO FSHC_SPCR_TypeDef SPCR ; // 0x008,
__IO uint32_t RXTX_DAT_LEN ; // 0x00c,
// set must before flash_busy set as 1
__IO uint32_t CMD_REG ; // 0x010,
// MCU access flash command.
__IO uint32_t ADDR_REG ; // 0x014,
// MCU access flash start address,byte address
__IO FSHC_MCU_ADRCMD_BIT_LEN_TypeDef MCU_ADRCMD_BIT_LEN ; // 0x018,
__IO FSHC_SEND_CTRL_TypeDef SEND_CTRL ; // 0x01c,
__O uint32_t SEND_EN ; // 0x020,
// MCU start transmit,write 1 to start transmit command/address/data,
// hardware will check the posedge of the signal
__I FSHC_FIFO_STATUS_TypeDef FIFO_STATUS ; // 0x024,
__IO uint32_t RXPTR_INC_EN ; // 0x028,
// MCU read rxfifo enable
// 1 ------ rx fifo rxptr increment enable
// 0 ------ rx fifo rxptr increment disable
__I FSHC_ST_TypeDef ST ; // 0x02c,
__IO FSHC_CACHE_CMD1_TypeDef CACHE_CMD1 ; // 0x030,
// cache command, Gigadevice command is supported in default
// cache access flash only use qpi_read/suspend/resume/hpm/exithpm/rst_continue/continu_rd_mod cmd;
// in these cmd, rst_continue is fixed 8'hFF, others can configure.
__IO FSHC_CACHE_CMD2_TypeDef CACHE_CMD2 ; // 0x034,
// cache command, Gigadevice command is supported in default
// cache access flash only use qpi_read/suspend/resume/hpm/exithpm/rst_continue/continu_rd_mod cmd;
// in these cmd, rst_continue is fixed 8'hFF, others can configure.
__IO FSHC_CACHE_DELAY_SET_TypeDef CACHE_DELAY_SET ; // 0x038,
__IO uint32_t CACHE_RESUME_DELAY_MAX; // 0x03c,
// resume delay time.
// This register control the interval time of two read when erase flash.
// delay time: (1/F(flash))*resume_delay_max.
__IO FSHC_DELAY_SET_TypeDef DELAY_SET ; // 0x040,
__IO uint32_t BYPASS_HPM ; // 0x044,
// 0----enable cache hpm
// 1----disable cache hpm
__IO uint32_t ATOM_OP_EN ; // 0x048,
// Set this bit, fshc won't ack cache request and cache request will be pended.
// Note: 1. if cache is reading in hpm mode or continue mode, MCU should exit hpm or rst continue first before accessing flash
// 2. The system will die when set this bit to 1 and CPU fetch instruct or data, because fshc won't ack cache request
__O uint32_t CLR_HPM ; // 0x04c,
// Set this bit to 1 before MCU send command when cache is working in hpm, and flash clock will be switched.
// For example: when cache reads flash in hpm, MCU want to access flash. In such case, MCU should set atom_op_en,
// then set this bit, then send exit hpm cmd.
__IO uint32_t CONTINUE_RD_MOD_INDEX ; // 0x050,
// continue_rd_mod valid indication
// if you want to enter continuous read mode
// 1.set continue_rd_mod with enter continue read mode value;
// 2.set continue_rd_mod == continue_rd_mod_index.
// both satisfy two condition, flash will entrance continuous read mode.
// if you don't want to enter continuous read mode
// 1.set continue_rd_mod with exit continue read mode value;
// 2.set continue_rd_mod != continue_rd_mod_index.
// both satisfy two condition, flash won't entrance continuous read mode.
// gigedevice ----- enter continue read mode value is 8'hAX, ex:8'ha0;
// exit continue read mode value is other value except 8'hAX, ex:8'h00,8'h55,8'hff;
// MACRONIX ----- enter performance enhance mode value is bit7 != bit3, bit6 != bit2, bit5 != bit1, bit4 != bit0, ex:8'ha5,8'h5a,8'h0f;
// exit performance enhance value mode bit7 = bit3, bit6 = bit2, bit5 = bit1, bit4 = bit0, ex: 8'haa,8'h00,8'hff;
// Winbond ----- enter continue read mode index,{2'bxx,2'b10,4'bxxxx},the value of continu_rd_mod = {2'bxx,2'b10,4'bxxxx} if want to use continue read mode,
// SST ----- don't have continuous read mode, so the value of continu_rd_mod != continue_rd_mod_index.
// EoN ----- enter performance enhance mode value bit7 != bit3, bit6 != bit2, bit5 != bit1, bit4 != bit0, ex:8'ha5,8'h5a,8'h0f;
// exit performance enhance value bit7 = bit3, bit6 = bit2, bit5 = bit1, bit4 = bit0, ex: 8'haa,8'h00,8'hff.
__I uint32_t CONTINUE_STATUS ; // 0x054,
// 1 ------ flash be in continue read mode for cache path.
__IO uint32_t DLY_CFG ; // 0x058,
// used delay cell number
// 0 - used 1 delay cell; 1 - used 2 delay cell; ... 7 - used 8 delay cell;
__I uint32_t CACHE_ACCESS_STATUS ; // 0x05c,
// This bit reflect cache access flash status. use for switching from cache to mcu access flash.
// 1: cache bus is busy, mcu not to break.
// 0: only when is 0, MCU can send cmd to access flash.
} FSHC_TypeDef;
#define FSHC (( FSHC_TypeDef *) FSHC_BASE)
#endif

58
core/reg/reg_gpio.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef _REG_GPIO_H_
#define _REG_GPIO_H_
#include "reg_base.h"
//================================
//BLOCK GPIO define
#define GPIO_BASE ((uint32_t)0x40010000)
#define GPIO_DAT_SET_ADDR_OFFSET 0x000
#define GPIO_DAT_CLR_ADDR_OFFSET 0x004
#define GPIO_DAT_TOG_ADDR_OFFSET 0x008
#define GPIO_DAT_MSK_ADDR_OFFSET 0x00c
#define GPIO_DAT_ADDR_OFFSET 0x010
#define GPIO_PIN_ADDR_OFFSET 0x014
#define GPIO_DIR_SET_ADDR_OFFSET 0x020
#define GPIO_DIR_CLR_ADDR_OFFSET 0x024
#define GPIO_DIR_TOG_ADDR_OFFSET 0x028
#define GPIO_DIR_MSK_ADDR_OFFSET 0x02c
#define GPIO_DIR_ADDR_OFFSET 0x030
//================================
//BLOCK GPIO top struct define
typedef struct
{
__O uint32_t DAT_SET; // 0x000,
// WR: (1: gpio is set high level, 0: no effect)
__O uint32_t DAT_CLR; // 0x004,
// WR: (1: gpio is set low level, 0: no effect)
__O uint32_t DAT_TOG; // 0x008,
// WR: (1: gpio state is overturn (1->0 or 0->1))
__IO uint32_t DAT_MSK; // 0x00c,
// WR: (1: dat_set, dat_clr, dat_tog, dat can not set, 0: no effect)
// RD: ()
__IO uint32_t DAT ; // 0x010,
// WR: (1: write this register equal to write dat_set, dat_clr, dat_tog)
// RD: (return current register value)
__I uint32_t PIN ; // 0x014,
// RD: (get gpio current state(1: high level, 0: low level))
__I uint32_t RSV0[2];
__O uint32_t DIR_SET; // 0x020,
// WR: (1: set gpio is output, 0: no effect)
__O uint32_t DIR_CLR; // 0x024,
// WR: (1: clear gpio output function, 0: no effect)
__O uint32_t DIR_TOG; // 0x028,
// WR: (1: gpio direction is overturn (1->0 or 0->1))
__IO uint32_t DIR_MSK; // 0x02c,
// WR: (1: dir_set, dir_clr, dir_tog, dir can not set, 0: no effect)
// RD: ()
__IO uint32_t DIR ; // 0x030,
// WR: (write this register equal to write dir_set, dir_clr, dir_tog)
// RD: (get gpio current direction (1: output, 0: input))
} GPIO_TypeDef;
#define GPIO (( GPIO_TypeDef *) GPIO_BASE)
#endif

355
core/reg/reg_i2c.h Normal file
View File

@ -0,0 +1,355 @@
#ifndef _REG_I2C_H_
#define _REG_I2C_H_
#include "reg_base.h"
//================================
//BLOCK I2C define
#define I2C_BASE ((uint32_t)0x40029000)
#define I2C_CONSET_ADDR_OFFSET 0x000
#define I2C_CONCLR_ADDR_OFFSET 0x004
#define I2C_SR_ADDR_OFFSET 0x008
#define I2C_DATA_ADDR_OFFSET 0x00c
#define I2C_CLK_ADDR_OFFSET 0x010
#define I2C_SADR0_ADDR_OFFSET 0x014
#define I2C_ADM0_ADDR_OFFSET 0x018
#define I2C_XSADR_ADDR_OFFSET 0x01c
#define I2C_XADM_ADDR_OFFSET 0x020
#define I2C_SRST_ADDR_OFFSET 0x024
#define I2C_SADR1_ADDR_OFFSET 0x028
#define I2C_ADM1_ADDR_OFFSET 0x02c
#define I2C_SADR2_ADDR_OFFSET 0x030
#define I2C_ADM2_ADDR_OFFSET 0x034
#define I2C_SADR3_ADDR_OFFSET 0x038
#define I2C_ADM3_ADDR_OFFSET 0x03c
//================================
//BLOCK I2C reg struct define
typedef union //0x000
{
struct
{
uint32_t SL7VAL: 1; // bit0 --- 7-bit addr control bit
uint32_t SL10VAL: 1; // bit1 --- 10-bit addr control bit
uint32_t AAK: 1; // bit2 ---
// 1.when this bit is 1 and satisfy any of the following conditions
// (1)rcv 7-bit addr first byte or 10-bit second byte
// (2)rcv radio addr and gcebab is 1
// (3)master or slaver mode receive data
// i2c will transmit a ack(sda low level)
// 2.if this bit is 0, when master or slaver mode receive data will not transmit ack
// 3.when slaver mode transmit data, clear this bit,slaver think this data is last
uint32_t IFLG: 1; // bit3 --- flag signal
uint32_t STP: 1; // bit4 --- master stop signal auto clear
// master mode set stp 1 will send stop signal
// slaver mode set stp 1, slaver think receive stop signal
uint32_t STA: 1; // bit5 --- master start signal auto clear
// master mode set sta 1, change into master and send start signal if already master mode, send restart signal
// slaver mode set sta 1, after ending current tasks then change into master mode
uint32_t ENAB: 1; // bit6 --- i2c enable
uint32_t IEN: 1; // bit7 --- i2c interrupt enable
uint32_t GCAVAL: 1; // bit8
uint32_t RSV_END: 23; // bit[31:9]
};
uint32_t Word;
} I2C_CONSET_TypeDef; //0x000
//================================
#define I2C_SL7VAL_POS 0
#define I2C_SL10VAL_POS 1
#define I2C_AAK_POS 2
#define I2C_IFLG_POS 3
#define I2C_STP_POS 4
#define I2C_STA_POS 5
#define I2C_ENAB_POS 6
#define I2C_IEN_POS 7
#define I2C_GCAVAL_POS 8
//================================
typedef union //0x004
{
struct
{
uint32_t RSV_NOUSE1: 2; // bit[1:0] --- Ignore me
uint32_t AAC: 1; // bit2
uint32_t IFLG: 1; // bit3
uint32_t RSV_NOUSE2: 1; // bit4 --- Ignore me
uint32_t STAC: 1; // bit5
uint32_t ENC: 1; // bit6
uint32_t IEC: 1; // bit7
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_CONCLR_TypeDef; //0x004
//================================
#define I2C_AAC_POS 2
#define I2C_IFLG_POS 3
#define I2C_STAC_POS 5
#define I2C_ENC_POS 6
#define I2C_IEC_POS 7
//================================
typedef union //0x008
{
struct
{
uint32_t RSV_NOUSE1: 3; // bit[2:0] --- Ignore me
uint32_t STATUS: 5; // bit[7:3] --- i2c_status
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_SR_TypeDef; //0x008
//================================
#define I2C_STATUS_LSB 3
#define I2C_STATUS_WIDTH 5
//================================
typedef union //0x00c
{
struct
{
uint32_t DATA: 8; // bit[7:0] --- transfer address/data
uint32_t REV_END: 24; // bit[31:7]
};
uint32_t Word;
} I2C_DATA_TypeDef; //0x00c
//================================
#define I2C_DATA_LSB 0
#define I2C_DATA_WIDTH 8
#define I2C_REV_END_LSB 8
#define I2C_REV_END_WIDTH 24
//================================
typedef union //0x010
{
struct
{
uint32_t M: 4; // bit[3:0] --- i2c master mode scl frequency
uint32_t N: 3; // bit[6:4] --- i2c samp frequency
uint32_t RSV_END: 25; // bit[31:7]
};
uint32_t Word;
} I2C_CLK_TypeDef; //0x010
//================================
#define I2C_M_LSB 0
#define I2C_M_WIDTH 4
#define I2C_N_LSB 4
#define I2C_N_WIDTH 3
//================================
typedef union //0x014
{
struct
{
uint32_t GCEBAB: 1; // bit0
uint32_t SADR: 7; // bit[7:1] --- slaa0
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_SADR0_TypeDef; //0x014
//================================
#define I2C_GCEBAB_POS 0
#define I2C_SADR_LSB 1
#define I2C_SADR_WIDTH 7
//================================
typedef union //0x018
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0
uint32_t MASK: 7; // bit[7:1] --- adm0
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_ADM0_TypeDef; //0x018
//================================
#define I2C_MASK_LSB 1
#define I2C_MASK_WIDTH 7
//================================
typedef union //0x01c
{
struct
{
uint32_t XGCENAB: 1; // bit0
uint32_t ADDR: 10; // bit[10:1] --- xsla
uint32_t RSV_END: 21; // bit[31:11]
};
uint32_t Word;
} I2C_XSADR_TypeDef; //0x01c
//================================
#define I2C_XGCENAB_POS 0
#define I2C_ADDR_LSB 1
#define I2C_ADDR_WIDTH 10
//================================
typedef union //0x020
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0 --- Ignore me
uint32_t MASK: 10; // bit[10:1]
uint32_t RSV_END: 21; // bit[31:11]
};
uint32_t Word;
} I2C_XADM_TypeDef; //0x020
//================================
#define I2C_XADM_MASK_LSB 1
#define I2C_XADM_MASK_WIDTH 10
//================================
typedef union //0x028
{
struct
{
uint32_t GCEBAB: 1; // bit0
uint32_t SADR: 7; // bit[7:1] --- slaa1
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_SADR1_TypeDef; //0x028
//================================
#define I2C_GCEBAB_POS 0
#define I2C_SADR_LSB 1
#define I2C_SADR_WIDTH 7
//================================
typedef union //0x02c
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0 --- Ignore me
uint32_t MASK: 7; // bit[7:1] --- adm1
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_ADM1_TypeDef; //0x02c
//================================
#define I2C_ADM_MASK_LSB 1
#define I2C_ADM_MASK_WIDTH 7
//================================
typedef union //0x030
{
struct
{
uint32_t GCEBAB: 1; // bit0
uint32_t SADR: 7; // bit[7:1] --- slaa2
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_SADR2_TypeDef; //0x030
//================================
#define I2C_GCEBAB_POS 0
#define I2C_SADR_LSB 1
#define I2C_SADR_WIDTH 7
//================================
typedef union //0x034
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0 --- Ignore me
uint32_t MASK: 7; // bit[7:1] --- adm2
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_ADM2_TypeDef; //0x034
typedef union //0x038
{
struct
{
uint32_t GCEBAB: 1; // bit0
uint32_t SADR: 7; // bit[7:1] --- slaa3
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_SADR3_TypeDef; //0x038
//================================
#define I2C_GCEBAB_POS 0
#define I2C_SADR_LSB 1
#define I2C_SADR_WIDTH 7
//================================
typedef union //0x03c
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0 --- Ignore me
uint32_t MASK: 7; // bit[7:1] --- adm3
uint32_t RSV_END: 24; // bit[31:8]
};
uint32_t Word;
} I2C_ADM3_TypeDef; //0x03c
//================================
//BLOCK I2C top struct define
typedef struct
{
__IO I2C_CONSET_TypeDef CONSET ; // 0x000,
// i2c control set register -- i2c control reg
__O I2C_CONCLR_TypeDef CONCLR ; // 0x004,
// i2c control clr register
__I I2C_SR_TypeDef SR ; // 0x008,
// i2c status register -- i2c status reg
__IO I2C_DATA_TypeDef DATA ; // 0x00c,
// i2c data register -- i2c data reg (addr+r/w and data) 8bits
__IO I2C_CLK_TypeDef CLK ; // 0x010,
// i2c ccrfs register -- i2c clock (scl) speed contorl reg
__IO I2C_SADR0_TypeDef SADR0 ; // 0x014,
// i2c slaa register -- slaver address reg
__IO I2C_ADM0_TypeDef ADM0 ; // 0x018,
// i2c adm0 register
__IO I2C_XSADR_TypeDef XSADR ; // 0x01c,
// i2c xsla register -- extension slaver address reg
__IO I2C_XADM_TypeDef XADM ; // 0x020,
// i2c xadm0 register
__O uint32_t SRST ; // 0x024,
// reserved
__IO I2C_SADR1_TypeDef SADR1 ; // 0x028,
// i2c slaa1 register
__IO I2C_ADM1_TypeDef ADM1 ; // 0x02c,
// i2c adm1 register
__IO I2C_SADR2_TypeDef SADR2 ; // 0x030,
// i2c slaa2 register
__IO I2C_ADM2_TypeDef ADM2 ; // 0x034,
// i2c adm2 register
__IO I2C_SADR3_TypeDef SADR3 ; // 0x038,
// i2c slaa3 register
__IO I2C_ADM3_TypeDef ADM3 ; // 0x03c,
// i2c adm3 register
} I2C_TypeDef;
#define I2C (( I2C_TypeDef *) I2C_BASE)
#endif

65
core/reg/reg_iwdt.h Normal file
View File

@ -0,0 +1,65 @@
#ifndef _REG_IWDT_H_
#define _REG_IWDT_H_
#include "reg_base.h"
//================================
//BLOCK IWDT define
#define IWDT_BASE ((uint32_t)0x4002a000)
#define IWDT_LOAD_ADDR_OFFSET 0x000
#define IWDT_VALUE_ADDR_OFFSET 0x004
#define IWDT_CTRL_ADDR_OFFSET 0x008
#define IWDT_INTCLR_ADDR_OFFSET 0x00c
#define IWDT_RIS_ADDR_OFFSET 0x010
#define IWDT_LOCK_ADDR_OFFSET 0x100
//================================
//BLOCK IWDT reg struct define
typedef union //0x008
{
struct
{
uint32_t EN: 1; // bit0 --- iwdg enable
uint32_t INTEN: 1; // bit1 --- iwdg interrupt enable
uint32_t RSTEN: 1; // bit2 --- iwdg reset enable
uint32_t CLKSEL: 1; // bit3 --- iwdg clk select
// 0:iwdt clk select apbclk
// 1:iwdt clk select lsi
uint32_t RSV_END: 28; // bit[31:4]
};
uint32_t Word;
} IWDT_CTRL_TypeDef; //0x008
//================================
#define IWDT_EN_POS 0
#define IWDT_INTEN_POS 1
#define IWDT_RSTEN_POS 2
#define IWDT_CLKSEL_POS 3
//================================
//================================
//BLOCK IWDT top struct define
typedef struct
{
__IO uint32_t LOAD ; // 0x000,
// reload value register
__I uint32_t VALUE ; // 0x004,
// current value register
__IO IWDT_CTRL_TypeDef CTRL ; // 0x008,
// control register
__O uint32_t INTCLR ; // 0x00c,
// interrupt flag clear register
__I uint32_t RIS ; // 0x010,
// interrupt flag register
__I uint32_t RSV0[59];
__IO uint32_t LOCK ; // 0x100,
// iwdg register locking register
// write 0x1ACCE551 to unlock
} IWDT_TypeDef;
#define IWDT (( IWDT_TypeDef *) IWDT_BASE)
#endif

251
core/reg/reg_mdm.h Normal file
View File

@ -0,0 +1,251 @@
#ifndef _REG_MDM_H_
#define _REG_MDM_H_
#include "reg_base.h"
//================================
//BLOCK MDM define
#define MDM_BASE ((uint32_t)0x40009000)
#define MDM_REG0_ADDR_OFFSET 0x000
#define MDM_REG1_ADDR_OFFSET 0x004
#define MDM_CRC_PRESET_ADDR_OFFSET 0x008
#define MDM_ACCESS_REG_ADDR_OFFSET 0x00c
#define MDM_DAT_CFG_ADDR_OFFSET 0x010
#define MDM_EXT_CTRL_ADDR_OFFSET 0x014
#define MDM_RXSYNC_WIN_ADDR_OFFSET 0x018
#define MDM_SLOT_SET_ADDR_OFFSET 0x01c
#define MDM_FINECNT_SET_ADDR_OFFSET 0x020
#define MDM_SLOTCNT_SET_ADDR_OFFSET 0x024
#define MDM_FINECNT_ADDR_OFFSET 0x028
#define MDM_SLOTCNT_ADDR_OFFSET 0x02c
#define MDM_EXT_TX_DAT_ADDR_OFFSET 0x030
#define MDM_EXT_RX_DAT_ADDR_OFFSET 0x034
#define MDM_EXT_ST_ADDR_OFFSET 0x038
//================================
//BLOCK MDM reg struct define
typedef union //0x000
{
struct
{
uint32_t RF_CHANNEL_NO: 6; // bit[5:0]
uint32_t WHITENING_ON: 1; // bit6
uint32_t CD1_EN: 1; // bit7
uint32_t ACC_REG_EN: 1; // bit8
uint32_t TX_INVERT: 1; // bit9
uint32_t RX_INVERT: 1; // bit10
uint32_t IQ_INVERT: 1; // bit11
uint32_t LI_INVERT: 1; // bit12
uint32_t LQ_INVERT: 1; // bit13
uint32_t ACC_INVERT: 1; // bit14
uint32_t FILT2_CLK_PH: 1; // bit15 --- no use
uint32_t TXCLK_PH: 1; // bit16 --- use for RF CTRL sample the modem out TX_DATA
// 0: use the posedge clk sample
// 1: use the negedge clk sample
uint32_t RSV_NOUSE1: 1; // bit17
uint32_t DEBUG_MODE: 4; // bit[21:18] --- debug out select
uint32_t TX_SCALE_EN: 1; // bit22
uint32_t TX_SCALE_COEF_1M: 3; // bit[25:23] ---
// tx_scale_coef[2]==1 : tx_out = tx_in *( 1 + tx_scale_coef[1:0]/16)
// tx_scale_coef[2]==0 : tx_out = tx_in *( 1 - tx_scale_coef[1:0]/16)
uint32_t TX_SCALE_COEF_2M: 3; // bit[28:26] ---
// tx_scale_coef[2]==1 : tx_out = tx_in *( 1 + tx_scale_coef[1:0]/16)
// tx_scale_coef[2]==0 : tx_out = tx_in *( 1 - tx_scale_coef[1:0]/16)
uint32_t RSV_END: 3; // bit[31:29]
};
uint32_t Word;
} MDM_REG0_TypeDef; //0x000
//================================
#define MDM_RF_CHANNEL_NO_LSB 0
#define MDM_RF_CHANNEL_NO_WIDTH 6
#define MDM_WHITENING_ON_POS 6
#define MDM_CD1_EN_POS 7
#define MDM_ACC_REG_EN_POS 8
#define MDM_TX_INVERT_POS 9
#define MDM_RX_INVERT_POS 10
#define MDM_IQ_INVERT_POS 11
#define MDM_LI_INVERT_POS 12
#define MDM_LQ_INVERT_POS 13
#define MDM_ACC_INVERT_POS 14
#define MDM_FILT2_CLK_PH_POS 15
#define MDM_TXCLK_PH_POS 16
#define MDM_DEBUG_MODE_LSB 18
#define MDM_DEBUG_MODE_WIDTH 4
#define MDM_TX_SCALE_EN_POS 22
#define MDM_TX_SCALE_COEF_1M_LSB 23
#define MDM_TX_SCALE_COEF_1M_WIDTH 3
#define MDM_TX_SCALE_COEF_2M_LSB 26
#define MDM_TX_SCALE_COEF_2M_WIDTH 3
//================================
typedef union //0x004
{
struct
{
uint32_t MIN_MAG_CONF: 11; // bit[10:0]
uint32_t RSV_NOUSE1: 1; // bit11
uint32_t DRIFT_COR_SET: 2; // bit[13:12]
uint32_t RSV_NOUSE2: 2; // bit[15:14]
uint32_t IF_SHIFT: 13; // bit[28:16]
uint32_t RSV_END: 3; // bit[31:29]
};
uint32_t Word;
} MDM_REG1_TypeDef; //0x004
//================================
#define MDM_MIN_MAG_CONF_LSB 0
#define MDM_MIN_MAG_CONF_WIDTH 11
#define MDM_DRIFT_COR_SET_LSB 12
#define MDM_DRIFT_COR_SET_WIDTH 2
#define MDM_IF_SHIFT_LSB 16
#define MDM_IF_SHIFT_WIDTH 13
//================================
typedef union //0x010
{
struct
{
uint32_t MDM_DAT_SET: 8; // bit[7:0]
uint32_t MDM_DIRECT_SET: 1; // bit8 ---
// 0: modem out use the gauss filter out
// 1: modem out data is use mdm_dat_set[7:0]
uint32_t RSV_END: 23; // bit[31:9]
};
uint32_t Word;
} MDM_DAT_CFG_TypeDef; //0x010
//================================
#define MDM_MDM_DAT_SET_LSB 0
#define MDM_MDM_DAT_SET_WIDTH 8
#define MDM_MDM_DIRECT_SET_POS 8
//================================
typedef union //0x014
{
struct
{
uint32_t MDM_EXT_EN: 1; // bit0 ---
uint32_t MDM_INT_EN: 5; // bit[5:1] ---
// [0] mdm_tx_done interrupt en
// [1] mdm_sync_err interrupt en
// [2] mdm_slot_int interrupt en
// [3] mdm_slot_over interrupt en
// [4] mdm_sync_found interrupt en
uint32_t MDM_SLOT_CNT_HOLD: 1; // bit6
uint32_t MDM_SLOT_UPLOAD: 1; // bit7
uint32_t MDM_SLOT_INT_CLR: 1; // bit8
uint32_t RSV_END: 23; // bit[31:9]
};
uint32_t Word;
} MDM_EXT_CTRL_TypeDef; //0x014
//================================
#define MDM_MDM_EXT_EN_POS 0
#define MDM_MDM_INT_EN_LSB 1
#define MDM_MDM_INT_EN_WIDTH 5
#define MDM_MDM_SLOT_CNT_HOLD_POS 6
#define MDM_MDM_SLOT_UPLOAD_POS 7
#define MDM_MDM_SLOT_INT_CLR_POS 8
//================================
typedef union //0x01c
{
struct
{
uint32_t MDM_SLOT_WIN: 12; // bit[11:0] ---
// slot window : (mdm_slot_win + 1 ) us
// max slot window : 4096 us
// default : 1ms
uint32_t MDM_SLOT_OFF: 12; // bit[23:12] ---
// slot interrput event offset
uint32_t RSV_END: 8; // bit[31:24]
};
uint32_t Word;
} MDM_SLOT_SET_TypeDef; //0x01c
//================================
#define MDM_MDM_SLOT_WIN_LSB 0
#define MDM_MDM_SLOT_WIN_WIDTH 12
#define MDM_MDM_SLOT_OFF_LSB 12
#define MDM_MDM_SLOT_OFF_WIDTH 12
//================================
typedef union //0x038
{
struct
{
uint32_t MDM_TX_DONE: 1; // bit0 ---
// when is 1
// TX fifo is empty and last bit is sent out
// cleared when tx_en is 0
uint32_t MDM_SYNC_ERR: 1; // bit1 ---
// when RX sync over time,
// mdm_sync_err is 1
// cleared by rx_en is 0
uint32_t MDM_SLOT_INT: 1; // bit2 ---
// cleared by mdm_slot_int_clr
uint32_t MDM_SLOT_OVER: 1; // bit3 ---
// cleared by mdm_slot_int_clr
uint32_t MDM_SYNC_FOUND: 1; // bit4 ---
// cleared by rx_en is 0
uint32_t FIFO_EMPTY: 1; // bit5
uint32_t FIFO_FULL: 1; // bit6
uint32_t FIFO_NUM: 3; // bit[9:7]
uint32_t MDM_SYNC_TIME: 12; // bit[21:10] ---
// only valid when mdm_sync_found is 1
// cleared when RX_EN is 0
uint32_t RSV_END: 10; // bit[31:22]
};
uint32_t Word;
} MDM_EXT_ST_TypeDef; //0x038
//================================
#define MDM_MDM_TX_DONE_POS 0
#define MDM_MDM_SYNC_ERR_POS 1
#define MDM_MDM_SLOT_INT_POS 2
#define MDM_MDM_SLOT_OVER_POS 3
#define MDM_MDM_SYNC_FOUND_POS 4
#define MDM_FIFO_EMPTY_POS 5
#define MDM_FIFO_FULL_POS 6
#define MDM_FIFO_NUM_LSB 7
#define MDM_FIFO_NUM_WIDTH 3
#define MDM_MDM_SYNC_TIME_LSB 10
#define MDM_MDM_SYNC_TIME_WIDTH 12
//================================
//================================
//BLOCK MDM top struct define
typedef struct
{
__IO MDM_REG0_TypeDef REG0 ; // 0x000,
__IO MDM_REG1_TypeDef REG1 ; // 0x004,
__IO uint32_t CRC_PRESET ; // 0x008,
__IO uint32_t ACCESS_REG ; // 0x00c,
__IO MDM_DAT_CFG_TypeDef DAT_CFG ; // 0x010,
__IO MDM_EXT_CTRL_TypeDef EXT_CTRL ; // 0x014,
__IO uint32_t RXSYNC_WIN ; // 0x018,
// ext rx sync window :
// (mdm_ext_rxsync_win + 1) us
// max sync time : 4096 us
// default is 2ms
__IO MDM_SLOT_SET_TypeDef SLOT_SET ; // 0x01c,
__IO uint32_t FINECNT_SET ; // 0x020,
__IO uint32_t SLOTCNT_SET ; // 0x024,
__I uint32_t FINECNT ; // 0x028,
__I uint32_t SLOTCNT ; // 0x02c,
__O uint32_t EXT_TX_DAT ; // 0x030,
__I uint32_t EXT_RX_DAT ; // 0x034,
__I MDM_EXT_ST_TypeDef EXT_ST ; // 0x038,
} MDM_TypeDef;
#define MDM (( MDM_TypeDef *) MDM_BASE)
#endif

582
core/reg/reg_rcc.h Normal file
View File

@ -0,0 +1,582 @@
#ifndef _REG_RCC_H_
#define _REG_RCC_H_
#include "reg_base.h"
//================================
//BLOCK RCC define
#define RCC_BASE ((uint32_t)0x40000000)
#define RCC_CLK_EN_ST_ADDR_OFFSET 0x000
#define RCC_AHBCLK_DIV_ADDR_OFFSET 0x004
#define RCC_APB1CLK_DIV_ADDR_OFFSET 0x008
#define RCC_APB2CLK_DIV_ADDR_OFFSET 0x00c
#define RCC_CFG_ADDR_OFFSET 0x010
#define RCC_STCALIB_ADDR_OFFSET 0x014
#define RCC_HSE_DET_CTRL_ADDR_OFFSET 0x018
#define RCC_CHIP_RSTREQ_ADDR_OFFSET 0x01c
#define RCC_AHBRST_CTRL_ADDR_OFFSET 0x020
#define RCC_APBRST_CTRL_ADDR_OFFSET 0x024
#define RCC_AHBCLK_EN_RUN_ADDR_OFFSET 0x028
#define RCC_APBCLK_EN_RUN_ADDR_OFFSET 0x02c
#define RCC_AHBCLK_EN_SLEEP_ADDR_OFFSET 0x030
#define RCC_APBCLK_EN_SLEEP_ADDR_OFFSET 0x034
#define RCC_AHBCLK_EN_DPSLEEP_ADDR_OFFSET 0x038
#define RCC_APBCLK_EN_DPSLEEP_ADDR_OFFSET 0x03c
#define RCC_BLE_CLKRST_CTRL_ADDR_OFFSET 0x040
#define RCC_CHIP_RST_ST_CLR_ADDR_OFFSET 0x044
//================================
//BLOCK RCC reg struct define
typedef union //0x000
{
struct
{
uint32_t HSE_DIG_EN: 1; // bit0
uint32_t LSI_DIG_EN: 1; // bit1
uint32_t HSI_DIG_EN: 1; // bit2
uint32_t DPLL_DIG_EN: 1; // bit3
uint32_t CSS_EN: 1; // bit4 --- HSE stable check enable
uint32_t RCCALIB_CLKEN: 1; // bit5
uint32_t BIST_CLK_EN: 1; // bit6
uint32_t RC16M_CNT_CLKEN: 1; // bit7
uint32_t FSHCCLK_SEL: 4; // bit[11:8] --- fshc clock source select
// 4'b0001: HSI clock
// 4'b0010: HSE clock
// 4'b0100: DPLL clock
// 4'b1000: DPLL 128M div out
// note: if fshc clock select DPLL 42M,
// fshcclk_diven must be set as 1 before fshcclk_sel
// config as 4'b1000
uint32_t RCCALIB_CLKSEL: 2; // bit[13:12]
uint32_t FSHCCLK_DIVEN: 1; // bit14 --- 1: 128M divider for fshc enable
uint32_t FSHCCLK_DIV_NUM: 3; // bit[17:15]--- note fshcclk_div_num must be larger than 0
// div clock = dpll_128m/(fshcclk_div_num + 1)
uint32_t IWDT_FCLK_DIS_DP: 1; // bit18 --- disable the IWDT function clock (RC32K clock) when chip is in DeepSleep
// Note : the IWDT function clock is auto enable, when chip is exit out DeepSleep
uint32_t CSS_FLAG: 1; // bit19
uint32_t HSI_RDY: 1; // bit20
uint32_t RSV_NOUSE1: 1; // bit21 --- Ignore me
uint32_t LSI_RDY: 1; // bit22
uint32_t HSE_RDY: 1; // bit23
uint32_t RSV_END: 8; // bit[31:24]
};
uint32_t Word;
} RCC_CLK_EN_ST_TypeDef; //0x000
//================================
#define RCC_HSE_DIG_EN_POS 0
#define RCC_LSI_DIG_EN_POS 1
#define RCC_HSI_DIG_EN_POS 2
#define RCC_DPLL_DIG_EN_POS 3
#define RCC_CSS_EN_POS 4
#define RCC_RCCALIB_CLKEN_POS 5
#define RCC_BIST_CLK_EN_POS 6
#define RCC_RC16M_CNT_CLKEN_POS 7
#define RCC_FSHCCLK_SEL_LSB 8
#define RCC_FSHCCLK_SEL_WIDTH 4
#define RCC_RCCALIB_CLKSEL_LSB 12
#define RCC_RCCALIB_CLKSEL_WIDTH 2
#define RCC_FSHCCLK_DIVEN_POS 14
#define RCC_FSHCCLK_DIV_NUM_LSB 15
#define RCC_FSHCCLK_DIV_NUM_WIDTH 3
#define RCC_IWDT_FCLK_DIS_DP_POS 18
#define RCC_CSS_FLAG_POS 19
#define RCC_HSI_RDY_POS 20
#define RCC_LSI_RDY_POS 22
#define RCC_HSE_RDY_POS 23
//================================
typedef union //0x010
{
struct
{
uint32_t SYSCLK_SW: 4; // bit[3:0] --- system clock source select
// 1: HSI clock
// 2: HSE clock
// 4: PLL 64M clock
// 8: LSI clock
uint32_t MCO_SW: 4; // bit[7:4] ---
// 0: no output
// 1: hsi clock
// 2: hse clock
// 3: PLL clock
// 4: lsi clock
// 5: system clock
// 6: ahb clock
// 7: apb clock
// 8: fshc clock
uint32_t DPLL_CLK_SW: 1; // bit8 ---
// 1'b0: DPLL clock is use 64M
// 1'b1: DPLL clock is use 48M
uint32_t RSV_END: 23; // bit[31:9]
};
uint32_t Word;
} RCC_CFG_TypeDef; //0x010
//================================
#define RCC_SYSCLK_SW_LSB 0
#define RCC_SYSCLK_SW_WIDTH 4
#define RCC_MCO_SW_LSB 4
#define RCC_MCO_SW_WIDTH 4
#define RCC_DPLL_CLK_SW_POS 8
//================================
typedef union //0x018
{
struct
{
uint32_t CLK_DET_EN: 1; // bit0 --- 1: HSE clock detect enable
uint32_t CLK_DET_RSTREQ: 1; // bit1 --- 1: reset the HSE clock detect module
uint32_t RSV_NOUSE1: 6; // bit[7:2] --- Ignore me
uint32_t CLK_DET_PASS: 1; // bit8
uint32_t CLK_DET_FAIL: 1; // bit9
uint32_t RSV_END: 22; // bit[31:10]
};
uint32_t Word;
} RCC_HSE_DET_CTRL_TypeDef; //0x018
//================================
#define RCC_CLK_DET_EN_POS 0
#define RCC_CLK_DET_RSTREQ_POS 1
#define RCC_CLK_DET_PASS_POS 8
#define RCC_CLK_DET_FAIL_POS 9
//================================
typedef union //0x020
{
struct
{
uint32_t RSV_NOUSE1: 1; // bit0 --- Ignore me
uint32_t SYSCFG_RSTREQ: 1; // bit1
uint32_t CSC_RSTREQ: 1; // bit2
uint32_t RSV_NOUSE2: 1; // bit3 --- Ignore me
uint32_t SPIM_RSTREQ: 1; // bit4
uint32_t SPIS_RSTREQ: 1; // bit5
uint32_t FSHC_RSTREQ: 1; // bit6
uint32_t ADC_RSTREQ: 1; // bit7
uint32_t GPIOA_RSTREQ: 1; // bit8
uint32_t AHB2P1_RSTREQ: 1; // bit9
uint32_t AHB2P2_RSTREQ: 1; // bit10
uint32_t CACHE_RSTREQ: 1; // bit11
uint32_t USB_RSTREQ: 1; // bit12 ---use for ahb2apb bridge
uint32_t RSV_END: 19; // bit[31:13]
};
uint32_t Word;
} RCC_AHBRST_CTRL_TypeDef; //0x020
//================================
#define RCC_SYSCFG_RSTREQ_POS 1
#define RCC_CSC_RSTREQ_POS 2
#define RCC_SPIM_RSTREQ_POS 4
#define RCC_SPIS_RSTREQ_POS 5
#define RCC_FSHC_RSTREQ_POS 6
#define RCC_ADC_RSTREQ_POS 7
#define RCC_GPIOA_RSTREQ_POS 8
#define RCC_AHB2P1_RSTREQ_POS 9
#define RCC_AHB2P2_RSTREQ_POS 10
#define RCC_CACHE_RSTREQ_POS 11
#define RCC_USB_RSTREQ_POS 12
//================================
typedef union //0x024
{
struct
{
uint32_t BTMR_RSTREQ: 1; // bit0
uint32_t CTMR_RSTREQ: 1; // bit1
uint32_t ATMR_RSTREQ: 1; // bit2
uint32_t UART1_RSTREQ: 1; // bit3
uint32_t UART2_RSTREQ: 1; // bit4
uint32_t RSV_NOUSE1: 1; // bit5 --- Ignore me
uint32_t DMAC_RSTREQ: 1; // bit6
uint32_t RSV_NOUSE2: 1; // bit7 --- Ignore me
uint32_t EXTI_RSTREQ: 1; // bit8
uint32_t I2C_RSTREQ: 1; // bit9
uint32_t RSV_NOUSE3: 1; // bit10 ---Ignore me
uint32_t MDM_RSTREQ: 1; // bit11
uint32_t RF_RSTREQ: 1; // bit12
uint32_t PLL_CAL_RSTREQ: 1; // bit13
uint32_t RCCALIB_RSTREQ: 1; // bit14
uint32_t RC16M_CNT_RSTREQ: 1; // bit15
uint32_t BLE_LOW_CLK_RSTREQ: 1; // bit16
uint32_t RTC_RST_REQ: 1; // bit17 ---
// 1:soft reset RTC
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} RCC_APBRST_CTRL_TypeDef; //0x024
//================================
#define RCC_BTMR_RSTREQ_POS 0
#define RCC_CTMR_RSTREQ_POS 1
#define RCC_ATMR_RSTREQ_POS 2
#define RCC_UART1_RSTREQ_POS 3
#define RCC_UART2_RSTREQ_POS 4
#define RCC_DMAC_RSTREQ_POS 6
#define RCC_EXTI_RSTREQ_POS 8
#define RCC_I2C_RSTREQ_POS 9
#define RCC_MDM_RSTREQ_POS 11
#define RCC_RF_RSTREQ_POS 12
#define RCC_PLL_CAL_RSTREQ_POS 13
#define RCC_RCCALIB_RSTREQ_POS 14
#define RCC_RC16M_CNT_RSTREQ_POS 15
#define RCC_BLE_LOW_CLK_RSTREQ_POS 16
#define RCC_RTC_RST_REQ_POS 17
//================================
typedef union //0x028
{
struct
{
uint32_t RCC_CLKEN_RUN: 1; // bit0
uint32_t SYSCFG_CLKEN_RUN: 1; // bit1
uint32_t RSV_NOUSE1: 2; // bit[3:2] --- Ignore me
uint32_t SPIM_CLKEN_RUN: 1; // bit4
uint32_t SPIS_CLKEN_RUN: 1; // bit5
uint32_t FSHC_CLKEN_RUN: 1; // bit6
uint32_t ADC_CLKEN_RUN: 1; // bit7
uint32_t RSV_NOUSE2: 1; // bit8 --- Ignore me
uint32_t AHB2P1_CLKEN_RUN: 1; // bit9 --- use for ahb2apb1 bridge
uint32_t AHB2P2_CLKEN_RUN: 1; // bit10 --- use for ahb2apb2 bridge
uint32_t CACHE_CLKEN_RUN: 1; // bit11
uint32_t USB_CLKEN_RUN: 1; // bit12
uint32_t RSV_END: 19; // bit[31:13]
};
uint32_t Word;
} RCC_AHBCLK_EN_RUN_TypeDef; //0x028
//================================
#define RCC_RCC_CLKEN_RUN_POS 0
#define RCC_SYSCFG_CLKEN_RUN_POS 1
#define RCC_SPIM_CLKEN_RUN_POS 4
#define RCC_SPIS_CLKEN_RUN_POS 5
#define RCC_FSHC_CLKEN_RUN_POS 6
#define RCC_ADC_CLKEN_RUN_POS 7
#define RCC_AHB2P1_CLKEN_RUN_POS 9
#define RCC_AHB2P2_CLKEN_RUN_POS 10
#define RCC_CACHE_CLKEN_RUN_POS 11
#define RCC_USB_CLKEN_RUN_POS 12
//================================
typedef union //0x02c
{
struct
{
uint32_t BTMR_CLKEN_RUN: 1; // bit0
uint32_t CTMR_CLKEN_RUN: 1; // bit1
uint32_t ATMR_CLKEN_RUN: 1; // bit2
uint32_t UART1_CLKEN_RUN: 1; // bit3
uint32_t UART2_CLKEN_RUN: 1; // bit4
uint32_t RSV_NOUSE1: 1; // bit5 --- Ignore me
uint32_t DMAC_CLKEN_RUN: 1; // bit6
uint32_t RSV_NOUSE2: 1; // bit7 --- Ignore me
uint32_t EXTI_CLKEN_RUN: 1; // bit8
uint32_t I2C_CLKEN_RUN: 1; // bit9
uint32_t IWDT_CLKEN_RUN: 1; // bit10
uint32_t MDM_CLKEN_RUN: 1; // bit11
uint32_t RF_CLKEN_RUN: 1; // bit12
uint32_t RSV_NOUSE3: 3; // bit[15:13] --- Ignore me
uint32_t AON_CLKEN_RUN: 1; // bit16
uint32_t APBMISC_CLKEN_RUN: 1; // bit17
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} RCC_APBCLK_EN_RUN_TypeDef; //0x02c
//================================
#define RCC_BTMR_CLKEN_RUN_POS 0
#define RCC_CTMR_CLKEN_RUN_POS 1
#define RCC_ATMR_CLKEN_RUN_POS 2
#define RCC_UART1_CLKEN_RUN_POS 3
#define RCC_UART2_CLKEN_RUN_POS 4
#define RCC_DMAC_CLKEN_RUN_POS 6
#define RCC_EXTI_CLKEN_RUN_POS 8
#define RCC_I2C_CLKEN_RUN_POS 9
#define RCC_IWDT_CLKEN_RUN_POS 10
#define RCC_MDM_CLKEN_RUN_POS 11
#define RCC_RF_CLKEN_RUN_POS 12
#define RCC_AON_CLKEN_RUN_POS 16
#define RCC_APBMISC_CLKEN_RUN_POS 17
//================================
typedef union //0x030
{
struct
{
uint32_t RCC_CLKEN_SLEEP: 1; // bit0
uint32_t SYSCFG_CLKEN_SLEEP: 1; // bit1
uint32_t RSV_NOUSE1: 2; // bit[3:2] --- Ignore me
uint32_t SPIM_CLKEN_SLEEP: 1; // bit4
uint32_t SPIS_CLKEN_SLEEP: 1; // bit5
uint32_t FSHC_CLKEN_SLEEP: 1; // bit6
uint32_t ADC_CLKEN_SLEEP: 1; // bit7
uint32_t RSV_NOUSE2: 1; // bit8 --- Ignore me
uint32_t AHB2P1_CLKEN_SLEEP: 1; // bit9 --- use for ahb2apb1 bridge
uint32_t AHB2P2_CLKEN_SLEEP: 1; // bit10 --- use for ahb2apb2 bridge
uint32_t CACHE_CLKEN_SLEEP: 1; // bit11
uint32_t USB_CLKEN_SLEEP: 1; // bit12
uint32_t RSV_END: 19; // bit[31:13]
};
uint32_t Word;
} RCC_AHBCLK_EN_SLEEP_TypeDef; //0x030
//================================
#define RCC_RCC_CLKEN_SLEEP_POS 0
#define RCC_SYSCFG_CLKEN_SLEEP_POS 1
#define RCC_SPIM_CLKEN_SLEEP_POS 4
#define RCC_SPIS_CLKEN_SLEEP_POS 5
#define RCC_FSHC_CLKEN_SLEEP_POS 6
#define RCC_ADC_CLKEN_SLEEP_POS 7
#define RCC_AHB2P1_CLKEN_SLEEP_POS 9
#define RCC_AHB2P2_CLKEN_SLEEP_POS 10
#define RCC_CACHE_CLKEN_SLEEP_POS 11
#define RCC_USB_CLKEN_SLEEP_POS 12
//================================
typedef union //0x034
{
struct
{
uint32_t BTMR_CLKEN_SLEEP: 1; // bit0
uint32_t CTMR_CLKEN_SLEEP: 1; // bit1
uint32_t ATMR_CLKEN_SLEEP: 1; // bit2
uint32_t UART1_CLKEN_SLEEP: 1; // bit3
uint32_t UART2_CLKEN_SLEEP: 1; // bit4
uint32_t RSV_NOUSE1: 1; // bit5 --- Ignore me
uint32_t DMAC_CLKEN_SLEEP: 1; // bit6
uint32_t RSV_NOUSE2: 1; // bit7 --- Ignore me
uint32_t EXTI_CLKEN_SLEEP: 1; // bit8
uint32_t I2C_CLKEN_SLEEP: 1; // bit9
uint32_t IWDT_CLKEN_SLEEP: 1; // bit10
uint32_t MDM_CLKEN_SLEEP: 1; // bit11
uint32_t RF_CLKEN_SLEEP: 1; // bit12
uint32_t RSV_NOUSE3: 3; // bit[15:13] --- Ignore me
uint32_t AON_CLKEN_SLEEP: 1; // bit16
uint32_t APBMISC_CLKEN_SLEEP: 1; // bit17
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} RCC_APBCLK_EN_SLEEP_TypeDef; //0x034
//================================
#define RCC_BTMR_CLKEN_SLEEP_POS 0
#define RCC_CTMR_CLKEN_SLEEP_POS 1
#define RCC_ATMR_CLKEN_SLEEP_POS 2
#define RCC_UART1_CLKEN_SLEEP_POS 3
#define RCC_UART2_CLKEN_SLEEP_POS 4
#define RCC_DMAC_CLKEN_SLEEP_POS 6
#define RCC_EXTI_CLKEN_SLEEP_POS 8
#define RCC_I2C_CLKEN_SLEEP_POS 9
#define RCC_IWDT_CLKEN_SLEEP_POS 10
#define RCC_MDM_CLKEN_SLEEP_POS 11
#define RCC_RF_CLKEN_SLEEP_POS 12
#define RCC_AON_CLKEN_SLEEP_POS 16
#define RCC_APBMISC_CLKEN_SLEEP_POS 17
//================================
typedef union //0x038
{
struct
{
uint32_t RCC_CLKEN_DPSLEEP: 1; // bit0
uint32_t SYSCFG_CLKEN_DPSLEEP: 1; // bit1
uint32_t RSV_NOUSE1: 2; // bit[3:2] --- Ignore me
uint32_t SPIM_CLKEN_DPSLEEP: 1; // bit4
uint32_t SPIS_CLKEN_DPSLEEP: 1; // bit5
uint32_t FSHC_CLKEN_DPSLEEP: 1; // bit6
uint32_t ADC_CLKEN_DPSLEEP: 1; // bit7
uint32_t RSV_NOUSE2: 1; // bit8 --- Ignore me
uint32_t AHB2P1_CLKEN_DPSLEEP: 1; // bit9 --- use for ahb2apb1 bridge
uint32_t AHB2P2_CLKEN_DPSLEEP: 1; // bit10 --- use for ahb2apb2 bridge
uint32_t CACHE_CLKEN_DPSLEEP: 1; // bit11
uint32_t USB_CLKEN_DPSLEEP: 1; // bit12
uint32_t RSV_END: 19; // bit[31:13]
};
uint32_t Word;
} RCC_AHBCLK_EN_DPSLEEP_TypeDef; //0x038
//================================
#define RCC_RCC_CLKEN_DPSLEEP_POS 0
#define RCC_SYSCFG_CLKEN_DPSLEEP_POS 1
#define RCC_SPIM_CLKEN_DPSLEEP_POS 4
#define RCC_SPIS_CLKEN_DPSLEEP_POS 5
#define RCC_FSHC_CLKEN_DPSLEEP_POS 6
#define RCC_ADC_CLKEN_DPSLEEP_POS 7
#define RCC_AHB2P1_CLKEN_DPSLEEP_POS 9
#define RCC_AHB2P2_CLKEN_DPSLEEP_POS 10
#define RCC_CACHE_CLKEN_DPSLEEP_POS 11
#define RCC_USB_CLKEN_DPSLEEP_POS 12
//================================
typedef union //0x03c
{
struct
{
uint32_t BTMR_CLKEN_DPSLEEP: 1; // bit0
uint32_t CTMR_CLKEN_DPSLEEP: 1; // bit1
uint32_t ATMR_CLKEN_DPSLEEP: 1; // bit2
uint32_t UART1_CLKEN_DPSLEEP: 1; // bit3
uint32_t UART2_CLKEN_DPSLEEP: 1; // bit4
uint32_t RSV_NOUSE1: 1; // bit5 --- Ignore me
uint32_t DMAC_CLKEN_DPSLEEP: 1; // bit6
uint32_t RSV_NOUSE2: 1; // bit7 --- Ignore me
uint32_t EXTI_CLKEN_DPSLEEP: 1; // bit8
uint32_t I2C_CLKEN_DPSLEEP: 1; // bit9
uint32_t IWDT_CLKEN_DPSLEEP: 1; // bit10
uint32_t MDM_CLKEN_DPSLEEP: 1; // bit11
uint32_t RF_CLKEN_DPSLEEP: 1; // bit12
uint32_t RSV_NOUSE3: 3; // bit[15:13] --- Ignore me
uint32_t AON_CLKEN_DPSLEEP: 1; // bit16
uint32_t APBMISC_CLKEN_DPSLEEP: 1; // bit17
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} RCC_APBCLK_EN_DPSLEEP_TypeDef; //0x03c
//================================
#define RCC_BTMR_CLKEN_DPSLEEP_POS 0
#define RCC_CTMR_CLKEN_DPSLEEP_POS 1
#define RCC_ATMR_CLKEN_DPSLEEP_POS 2
#define RCC_UART1_CLKEN_DPSLEEP_POS 3
#define RCC_UART2_CLKEN_DPSLEEP_POS 4
#define RCC_DMAC_CLKEN_DPSLEEP_POS 6
#define RCC_EXTI_CLKEN_DPSLEEP_POS 8
#define RCC_I2C_CLKEN_DPSLEEP_POS 9
#define RCC_IWDT_CLKEN_DPSLEEP_POS 10
#define RCC_MDM_CLKEN_DPSLEEP_POS 11
#define RCC_RF_CLKEN_DPSLEEP_POS 12
#define RCC_AON_CLKEN_DPSLEEP_POS 16
#define RCC_APBMISC_CLKEN_DPSLEEP_POS 17
//================================
typedef union //0x040
{
struct
{
uint32_t BLE_AHB_RSTREQ: 1; // bit0
uint32_t BLE_CRYPT_RSTREQ: 1; // bit1
uint32_t BLE_MASTER_RSTREQ: 1; // bit2
uint32_t BLE_AHBEN: 1; // bit3
uint32_t BLECLK_DIV: 2; // bit[5:4] --- BLE master clock source select
// 0: CPU_HCLK, used when system clock select as HSE clock;
// 1: CPU_HCLK/2, used when system clock is select as PLL 64M, and hclk_scal config as /2
// 2: CPU_HCLK/3, used when system clock is select as PLL 48M,
// 3: CPU_HCLK/4, used when system clock is select as PLL 64M,
uint32_t RSV_END: 26; // bit[31:6]
};
uint32_t Word;
} RCC_BLE_CLKRST_CTRL_TypeDef; //0x040
//================================
#define RCC_BLE_AHB_RSTREQ_POS 0
#define RCC_BLE_CRYPT_RSTREQ_POS 1
#define RCC_BLE_MASTER_RSTREQ_POS 2
#define RCC_BLE_AHBEN_POS 3
#define RCC_BLECLK_DIV_LSB 4
#define RCC_BLECLK_DIV_WIDTH 2
//================================
typedef union //0x044
{
struct
{
uint32_t POR12_BK_FLG: 1; // bit0
uint32_t LVD33_OUT_RST_FLG: 1; // bit1
uint32_t BOD12_OUT_RST_FLG: 1; // bit2
uint32_t PIN_RSTN_FLG: 1; // bit3
uint32_t POR12_CORE_FLG: 1; // bit4
uint32_t IWDTRST_FLG: 1; // bit5
uint32_t CHIPRST_FLG: 1; // bit6
uint32_t SYSRST_FLG: 1; // bit7
uint32_t POR12_BK_FLG_CLR: 1; // bit8
uint32_t LVD33_OUT_RST_FLG_CLR: 1; // bit9
uint32_t BOD12_OUT_RST_FLG_CLR: 1; // bit10
uint32_t PIN_RSTN_FLG_CLR: 1; // bit11
uint32_t POR12_CORE_FLG_CLR: 1; // bit12
uint32_t IWDTRST_FLG_CLR: 1; // bit13
uint32_t CHIPRST_FLG_CLR: 1; // bit14
uint32_t SYSRST_FLG_CLR: 1; // bit15
uint32_t RSV_END: 16; // bit[31:16]
};
uint32_t Word;
} RCC_CHIP_RST_ST_CLR_TypeDef; //0x044
//================================
#define RCC_POR12_BK_FLG_POS 0
#define RCC_LVD33_OUT_RST_FLG_POS 1
#define RCC_BOD12_OUT_RST_FLG_POS 2
#define RCC_PIN_RSTN_FLG_POS 3
#define RCC_POR12_CORE_FLG_POS 4
#define RCC_IWDTRST_FLG_POS 5
#define RCC_CHIPRST_FLG_POS 6
#define RCC_SYSRST_FLG_POS 7
#define RCC_POR12_BK_FLG_CLR_POS 8
#define RCC_LVD33_OUT_RST_FLG_CLR_POS 9
#define RCC_BOD12_OUT_RST_FLG_CLR_POS 10
#define RCC_PIN_RSTN_FLG_CLR_POS 11
#define RCC_POR12_CORE_FLG_CLR_POS 12
#define RCC_IWDTRST_FLG_CLR_POS 13
#define RCC_CHIPRST_FLG_CLR_POS 14
#define RCC_SYSRST_FLG_CLR_POS 15
//================================
//================================
//BLOCK RCC top struct define
typedef struct
{
__IO RCC_CLK_EN_ST_TypeDef CLK_EN_ST ; // 0x000,
__IO uint32_t AHBCLK_DIV ; // 0x004,
// ahb clock div value: value arange : 0 ~255
// ahb_clk = sys_clk/(ahbclk_div+1);
// default is ahb_clk = sys_clk;
__IO uint32_t APB1CLK_DIV ; // 0x008,
// apb1 clock div value: value arange : 0 ~255
// apb1_clk = ahb_clk/(apb1clk_div+1);
// default is apb1_clk = ahb_clk;
__IO uint32_t APB2CLK_DIV ; // 0x00c,
// apb2 clock div value: value arange : 0 ~255
// apb2_clk = ahb_clk/(apb2clk_div+1);
// default is apb2_clk = ahb_clk;
// Note: maske sure the apb2_clk is not large than 16M
// that means :
// when sys_clk is DPLL 64M, the apb2clk_div must set as 8'h3
__IO RCC_CFG_TypeDef CFG ; // 0x010,
__IO uint32_t STCALIB ; // 0x014,
__IO RCC_HSE_DET_CTRL_TypeDef HSE_DET_CTRL ; // 0x018,
__I uint32_t RSV ; // 0x01c,
__IO RCC_AHBRST_CTRL_TypeDef AHBRST_CTRL ; // 0x020,
__IO RCC_APBRST_CTRL_TypeDef APBRST_CTRL ; // 0x024,
__IO RCC_AHBCLK_EN_RUN_TypeDef AHBCLK_EN_RUN ; // 0x028,
// this reg is used when CPU is normal running mode
__IO RCC_APBCLK_EN_RUN_TypeDef APBCLK_EN_RUN ; // 0x02c,
// this reg is used when CPU is normal running mode
__IO RCC_AHBCLK_EN_SLEEP_TypeDef AHBCLK_EN_SLEEP ; // 0x030,
// this reg is used when CPU is sleeping mode
__IO RCC_APBCLK_EN_SLEEP_TypeDef APBCLK_EN_SLEEP ; // 0x034,
// this reg is used when CPU is sleeping mode
__IO RCC_AHBCLK_EN_DPSLEEP_TypeDef AHBCLK_EN_DPSLEEP ; // 0x038,
// this reg is used when CPU is Deepsleep mode
__IO RCC_APBCLK_EN_DPSLEEP_TypeDef APBCLK_EN_DPSLEEP ; // 0x03c,
// this reg is used when CPU is Deepsleep mode
__IO RCC_BLE_CLKRST_CTRL_TypeDef BLE_CLKRST_CTRL ; // 0x040,
__IO RCC_CHIP_RST_ST_CLR_TypeDef CHIP_RST_ST_CLR ; // 0x044,
} RCC_TypeDef;
#define RCC (( RCC_TypeDef *) RCC_BASE)
#endif

1268
core/reg/reg_rf.h Normal file

File diff suppressed because it is too large Load Diff

315
core/reg/reg_sadc.h Normal file
View File

@ -0,0 +1,315 @@
#ifndef _REG_SADC_H_
#define _REG_SADC_H_
#include "reg_base.h"
//================================
//BLOCK SADC define
#define SADC_BASE ((uint32_t)0x40007000)
#define SADC_CTRL_ADDR_OFFSET 0x000
#define SADC_AUTO_SW_CTRL_ADDR_OFFSET 0x004
#define SADC_CH_CTRL_ADDR_OFFSET 0x008
#define SADC_STCTRL_ADDR_OFFSET 0x00c
#define SADC_DC_OFFSET_ADDR_OFFSET 0x010
#define SADC_AUX_ST_ADDR_OFFSET 0x014
#define SADC_PCM_DAT_ADDR_OFFSET 0x018
#define SADC_SADC_CALIB_DATIN_ADDR_OFFSET 0x01c
#define SADC_SADC_CALIB_DATSEL_ADDR_OFFSET 0x020
#define SADC_SADC_CALIB_DATOUT_ADDR_OFFSET 0x024
#define SADC_SADC_ANA_CTRL_ADDR_OFFSET 0x028
#define SADC_MIC_CTRL_ADDR_OFFSET 0x02c
//================================
//BLOCK SADC reg struct define
typedef union //0x000
{
struct
{
uint32_t SADC_SOC: 1; // bit0
uint32_t SADC_CALIB_MODE: 1; // bit1
uint32_t SADC_CONV_MODE: 1; // bit2
uint32_t SADC_DMAC_EN: 1; // bit3
uint32_t SADC_CLK_PH: 1; // bit4
uint32_t SADC_SAMP_MOD: 2; // bit[6:5] ---
// 2'b00: software mode(normal mode)
// 2'b01: RSSI sample mode( ADC controlled by BB)
// 2'b10: decimation filter mode ( sample vioce data, must enable DMA)
// 2'b11: SOC is from ADTIM adctrg
uint32_t SADC_DECIM_END: 1; // bit7 --- write as 1 to stop decimation filter
uint32_t SADC_RSSI_SAMP_DLY: 6; // bit[13:8]--- delay time from rssi_req to SADC sample RSSI
// unit: one 16M clock period
// range: 0 ~ 4us
uint32_t SADC_DBG_CTRL: 1; // bit14 ---
// 0: normal mode
// 1: chip is configed as SADC analog IP
// the SOC & CLK is from external chip
uint32_t RSV_NOUSE1: 1; // bit15 --- Ignore me
uint32_t SADC_HPF_COEF: 4; // bit[19:16]-- decimation filter high pass filter coef
// 0: high pass filter is bypass
// 1~12: y(n)= (1-2^-sadc_hpf_coef)*y(n-1) + x(n) - x(n-1)
uint32_t SADC_AUX_CLK_DIV: 10; // bit[29:20]-- adc function clock = hclk / (sadc_aux_clk_div + 1 )
// note
// 1: make sure adc function clock is not more than 16M
// 2: when sadc_samp_mod is 2'b10 ( decimation filter mode)
// please makesure adc function clock is 16M
uint32_t RSV_END: 2; // bit[31:30]
};
uint32_t Word;
} SADC_CTRL_TypeDef; //0x000
//================================
#define SADC_SADC_SOC_POS 0
#define SADC_SADC_CALIB_MODE_POS 1
#define SADC_SADC_CONV_MODE_POS 2
#define SADC_SADC_DMAC_EN_POS 3
#define SADC_SADC_CLK_PH_POS 4
#define SADC_SADC_SAMP_MOD_LSB 5
#define SADC_SADC_SAMP_MOD_WIDTH 2
#define SADC_SADC_DECIM_END_POS 7
#define SADC_SADC_RSSI_SAMP_DLY_LSB 8
#define SADC_SADC_RSSI_SAMP_DLY_WIDTH 6
#define SADC_SADC_DBG_CTRL_POS 14
#define SADC_SADC_HPF_COEF_LSB 16
#define SADC_SADC_HPF_COEF_WIDTH 4
#define SADC_SADC_AUX_CLK_DIV_LSB 20
#define SADC_SADC_AUX_CLK_DIV_WIDTH 10
//================================
typedef union //0x004
{
struct
{
uint32_t AUTO_SW_CH: 1; // bit0 --- when is 1
// ADC_VIN_SEL is auto change
// only used when sadc_samp_mod is 2'b11
uint32_t AUTO_CH_NUM: 3; // bit[3:1] --- swith order:
uint32_t RSV_END: 28; // bit[31:4]
};
uint32_t Word;
} SADC_AUTO_SW_CTRL_TypeDef; //0x004
//================================
#define SADC_AUTO_SW_CH_POS 0
#define SADC_AUTO_CH_NUM_LSB 1
#define SADC_AUTO_CH_NUM_WIDTH 3
//================================
typedef union //0x008
{
struct
{
uint32_t SADC_CH_SET0: 4; // bit[3:0] --- when auto_sw_ch is 0
// SADC_VIN_SEL is sadc_ch_set0
// 0: VDD33/2
// 1: PAD_VBK
// 2: PAD_VDD12
// 3: PGAOUT
// 4: MICIN
// 5~14: ADCIN0 ~ ADCIN9
// 15: RF
// RF.RF_RSV[0] : RF TEMP
// RF.RF_RSV[1] : RF BANDGAP
// RF.RF_RSV[2] : RF RSSI
// RF.RF_RSV[3] : RF VDD_IF
uint32_t SADC_CH_SET1: 4; // bit[7:4]
uint32_t SADC_CH_SET2: 4; // bit[11:8]
uint32_t SADC_CH_SET3: 4; // bit[15:12]
uint32_t SADC_CH_SET4: 4; // bit[19:16]
uint32_t SADC_CH_SET5: 4; // bit[23:20]
uint32_t SADC_CH_SET6: 4; // bit[27:24]
uint32_t SADC_CH_SET7: 4; // bit[31:28]
};
uint32_t Word;
} SADC_CH_CTRL_TypeDef; //0x008
//================================
#define SADC_SADC_CH_SET0_LSB 0
#define SADC_SADC_CH_SET0_WIDTH 4
#define SADC_SADC_CH_SET1_LSB 4
#define SADC_SADC_CH_SET1_WIDTH 4
#define SADC_SADC_CH_SET2_LSB 8
#define SADC_SADC_CH_SET2_WIDTH 4
#define SADC_SADC_CH_SET3_LSB 12
#define SADC_SADC_CH_SET3_WIDTH 4
#define SADC_SADC_CH_SET4_LSB 16
#define SADC_SADC_CH_SET4_WIDTH 4
#define SADC_SADC_CH_SET5_LSB 20
#define SADC_SADC_CH_SET5_WIDTH 4
#define SADC_SADC_CH_SET6_LSB 24
#define SADC_SADC_CH_SET6_WIDTH 4
#define SADC_SADC_CH_SET7_LSB 28
#define SADC_SADC_CH_SET7_WIDTH 4
//================================
typedef union //0x00c
{
struct
{
uint32_t SADC_AUX_FLG: 1; // bit0
uint32_t SADC_FILTER_BUSY: 1; // bit1
uint32_t SADC_AUX_FLG_CLR: 1; // bit2
uint32_t RSV_END: 29; // bit[31:3]
};
uint32_t Word;
} SADC_STCTRL_TypeDef; //0x00c
//================================
#define SADC_SADC_AUX_FLG_POS 0
#define SADC_SADC_FILTER_BUSY_POS 1
#define SADC_SADC_AUX_FLG_CLR_POS 2
//================================
typedef union //0x014
{
struct
{
uint32_t SADC_AUX_DOUT: 10; // bit[9:0]
uint32_t RSV_NOUSE1: 2; // bit[11:10] --- Ignore me
uint32_t SADC_CH_ST: 4; // bit[15:12]
uint32_t RSV_END: 16; // bit[31:16]
};
uint32_t Word;
} SADC_AUX_ST_TypeDef; //0x014
//================================
#define SADC_SADC_AUX_DOUT_LSB 0
#define SADC_SADC_AUX_DOUT_WIDTH 10
#define SADC_SADC_CH_ST_LSB 12
#define SADC_SADC_CH_ST_WIDTH 4
//================================
typedef union //0x028
{
struct
{
uint32_t SADC_EN: 1; // bit0
uint32_t SADC_VREF_TRIM: 2; // bit[2:1] ---
// 0: 1.2V
// 1: 1.8V
// 2: 2.4V
// 3: 3V
uint32_t SADC_IBSEL_CMP: 3; // bit[5:3] ---
// 000: 15uA
// 111: 105uA
// 15uA/step
uint32_t SADC_IBSEL_VCM: 3; // bit[8:6] ---
// 000: 15uA
// 111: 105uA
// 15uA/step
uint32_t SADC_IBSEL_VREF: 3; // bit[11:9] ---
// 000: 15uA
// 111: 105uA
// 15uA/step
uint32_t SADC_IBSEL_BUF: 3; // bit[14:12] ---
// 000: 15uA
// 111: 105uA
// 15uA/step
uint32_t SADC_VREF_SEL: 1; // bit15 ---
// 0: ref is from VDDA
// 1: ref is gen from VBG
uint32_t SADC_CALCAP_SEL: 2; // bit[17:16] ---
// 01: most precision but narrow range
// 11: widest range but less precision
uint32_t SADC_CAL_OS: 2; // bit[19:18] ---
// 01: single ended tie to GND
// 01: single ended tie to VREF
uint32_t SADC_INBUF_BYPSS: 1; // bit20 ---
// 0: through input buffer
// 1: bypass input buffer
uint32_t RSV_END: 11; // bit[31:21]
};
uint32_t Word;
} SADC_SADC_ANA_CTRL_TypeDef; //0x028
//================================
#define SADC_SADC_EN_POS 0
#define SADC_SADC_VREF_TRIM_LSB 1
#define SADC_SADC_VREF_TRIM_WIDTH 2
#define SADC_SADC_IBSEL_CMP_LSB 3
#define SADC_SADC_IBSEL_CMP_WIDTH 3
#define SADC_SADC_IBSEL_VCM_LSB 6
#define SADC_SADC_IBSEL_VCM_WIDTH 3
#define SADC_SADC_IBSEL_VREF_LSB 9
#define SADC_SADC_IBSEL_VREF_WIDTH 3
#define SADC_SADC_IBSEL_BUF_LSB 12
#define SADC_SADC_IBSEL_BUF_WIDTH 3
#define SADC_SADC_VREF_SEL_POS 15
#define SADC_SADC_CALCAP_SEL_LSB 16
#define SADC_SADC_CALCAP_SEL_WIDTH 2
#define SADC_SADC_CAL_OS_LSB 18
#define SADC_SADC_CAL_OS_WIDTH 2
#define SADC_SADC_INBUF_BYPSS_POS 20
//================================
typedef union //0x02c
{
struct
{
uint32_t MIC_MODE_SEL: 1; // bit0 --- Analog microphone connect mode selected
// 1: connect without cap and res
// 0: connect with coupling cap
uint32_t MIC_PD: 1; // bit1 --- Micbias powerdown signal
uint32_t MIC_TRIM: 7; // bit[8:2] --- Micbias output voltage trimming signal
uint32_t MIC_VREF_SEL: 1; // bit9 --- Micbias Internal voltage reference selected
// 0: 750mV
// 1: 1.5V
uint32_t PGA_BIAS_SEL: 2; // bit[11:10]-- PGA enable signal, high active
uint32_t PGA_EN: 1; // bit 12
uint32_t PGA_VOL: 5; // bit[17:13]
uint32_t PGA_VREF_SEL: 1; // bit18 -- pga Internal voltage reference selected
// 0: 750mV
// 1: 1.5V
uint32_t RSV_END: 13; // bit[31:19]
};
uint32_t Word;
} SADC_MIC_CTRL_TypeDef; //0x024
//================================
//#define SADC_MIC_MODE_SEL_POS 0
//#define SADC_MIC_PD_POS 1
//#define SADC_MIC_TRIM_LSB 2
//#define SADC_MIC_TRIM_WIDTH 7
//#define SADC_MIC_VREF_SEL_POS 9
//#define SADC_PGA_BIAS_SEL_LSB 10
//#define SADC_PGA_BIAS_SEL_WIDTH 2
//#define SADC_PGA_EN_POS 12
//#define SADC_PGA_VOL_LSB 13
//#define SADC_PGA_VOL_WIDTH 5
//#define SADC_PGA_VREF_SEL_POS 18
//================================
//================================
//BLOCK SADC top struct define
typedef struct
{
__IO SADC_CTRL_TypeDef CTRL ; // 0x000,
__IO SADC_AUTO_SW_CTRL_TypeDef AUTO_SW_CTRL ; // 0x004,
__IO SADC_CH_CTRL_TypeDef CH_CTRL ; // 0x008,
__IO SADC_STCTRL_TypeDef STCTRL ; // 0x00c,
__IO uint32_t DC_OFFSET ; // 0x010,
// DC offset
// final out = ana_out + sadc_dc_off
// is sadc_dc_off is signed data
// data arrange : -8 ~ 7 for software or RSSI function
// command value for decimation is 10'h200
__I SADC_AUX_ST_TypeDef AUX_ST ; // 0x014,
__I uint32_t PCM_DAT ; // 0x018,
__IO uint32_t SADC_CALIB_DATIN ; // 0x01c,
__IO uint32_t SADC_CALIB_DATSEL ; // 0x020,
__I uint32_t SADC_CALIB_DATOUT ; // 0x024,
__IO SADC_SADC_ANA_CTRL_TypeDef SADC_ANA_CTRL ; // 0x028,
__IO SADC_MIC_CTRL_TypeDef MIC_CTRL ; // 0x02c,
} SADC_TypeDef;
#define SADC (( SADC_TypeDef *) SADC_BASE)
#endif

135
core/reg/reg_spim.h Normal file
View File

@ -0,0 +1,135 @@
#ifndef _REG_SPIM_H_
#define _REG_SPIM_H_
#include "reg_base.h"
//================================
//BLOCK SPIM define
#define SPIM_BASE ((uint32_t)0x40004000)
#define SPIM_RX_DATA_ADDR_OFFSET 0x000
#define SPIM_TX_DATA_ADDR_OFFSET 0x004
#define SPIM_TXRX_BGN_ADDR_OFFSET 0x008
#define SPIM_CTRL_ADDR_OFFSET 0x00c
#define SPIM_STATUS_CLR_ADDR_OFFSET 0x010
#define SPIM_STATUS_ADDR_OFFSET 0x014
#define SPIM_DAT_LEN_ADDR_OFFSET 0x018
//================================
//BLOCK SPIM reg struct define
typedef union //0x00c
{
struct
{
uint32_t SPIM_CRAT: 4; // bit[3:0] --- clock rate select,clk/2^(crat+1)
// 0-11 is supported
uint32_t SPIM_CPHA: 1; // bit4 --- clock phase bit
// 0: sck sample data in first edge;
// 1: sck sample data in second edge;
uint32_t SPIM_CPOL: 1; // bit5 --- clock polarity bit
// 0: sck is low in idle status;
// 1: sck is high in idle status;
uint32_t SPIM_TX_DMA_EN: 1; // bit6 ---
// 0: TX work as mcu mode
// 1: TX work as dma mode,after configure dma cfg,set txrx bgn to 1 to start the dma transission
uint32_t SPIM_RX_DMA_EN: 1; // bit7 ---
// 0: RX work as mcu mode
// 1: RX work as dma mode,after configure dma cfg,set txrx bgn to 1 to start the dma transission
uint32_t SPIM_INT_EN: 1; // bit8 --- interrupt enable bit
uint32_t SPIM_TX_EN: 1; // bit9 --- transmit to SPI slave enable
uint32_t SPIM_RX_EN: 1; // bit10--- receive from SPI slave enable
uint32_t SPIM_MSB_FST: 1; // bit11---
// 0: LSB first
// 1: MSB first
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} SPIM_CTRL_TypeDef; //0x00c
//================================
#define SPIM_SPIM_CRAT_LSB 0
#define SPIM_SPIM_CRAT_WIDTH 4
#define SPIM_SPIM_CPHA_POS 4
#define SPIM_SPIM_CPOL_POS 5
#define SPIM_SPIM_TX_DMA_EN_POS 6
#define SPIM_SPIM_RX_DMA_EN_POS 7
#define SPIM_SPIM_INT_EN_POS 8
#define SPIM_SPIM_TX_EN_POS 9
#define SPIM_SPIM_RX_EN_POS 10
#define SPIM_SPIM_MSB_FST_POS 11
#define SPIM_SPIM_RX_PH_POS 12
//================================
typedef union //0x010
{
struct
{
uint32_t SPIM_TXDAT_CLR: 1; // bit0 --- set 1 to clear spi TX fifo status and inner counter
uint32_t SPIM_RXDAT_CLR: 1; // bit1 --- set 1 to clear spi RX fifo status and inner counter
uint32_t SPIM_CLR_INTF: 1; // bit2 --- write 1 to clear intf status
uint32_t RSV_END: 29; // bit[31:3]
};
uint32_t Word;
} SPIM_STATUS_CLR_TypeDef; //0x010
//================================
#define SPIM_SPIM_TXDAT_CLR_POS 0
#define SPIM_SPIM_RXDAT_CLR_POS 1
#define SPIM_SPIM_CLR_INTF_POS 2
//================================
typedef union //0x014
{
struct
{
uint32_t SPIM_TX_FEMPTY: 1; // bit0 --- tx fifo empty
uint32_t SPIM_TX_FFULL: 1; // bit1 --- tx fifo full
uint32_t SPIM_TX_FNUM: 3; // bit[4:2] --- data number in tx fifo
uint32_t SPIM_RX_FEMPTY: 1; // bit5 --- rx fifo empty
uint32_t SPIM_RX_FFULL: 1; // bit6 --- rx fifo full
uint32_t SPIM_RX_FNUM: 3; // bit[9:7] --- data length in rx fifo
uint32_t SPIM_INTF: 1; // bit10 --- rx/tx interrupt flag
uint32_t SPIM_BUSY: 1; // bit11 --- spim transfer busy signal
// 0: spim idle
// 1: spim busy,tx/rx is running
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} SPIM_STATUS_TypeDef; //0x014
//================================
#define SPIM_SPIM_TX_FEMPTY_POS 0
#define SPIM_SPIM_TX_FFULL_POS 1
#define SPIM_SPIM_TX_FNUM_LSB 2
#define SPIM_SPIM_TX_FNUM_WIDTH 3
#define SPIM_SPIM_RX_FEMPTY_POS 5
#define SPIM_SPIM_RX_FFULL_POS 6
#define SPIM_SPIM_RX_FNUM_LSB 7
#define SPIM_SPIM_RX_FNUM_WIDTH 3
#define SPIM_SPIM_INTF_POS 10
#define SPIM_SPIM_BUSY_POS 11
//================================
//================================
//BLOCK SPIM top struct define
typedef struct
{
__I uint32_t RX_DATA ; // 0x000,
__O uint32_t TX_DATA ; // 0x004,
__O uint32_t TXRX_BGN ; // 0x008,
// used when dullplex mode or only RX mode
__IO SPIM_CTRL_TypeDef CTRL ; // 0x00c,
__O SPIM_STATUS_CLR_TypeDef STATUS_CLR ; // 0x010,
__I SPIM_STATUS_TypeDef STATUS ; // 0x014,
__IO uint32_t DAT_LEN ; // 0x018,
// data length for RX in MCU or DMA mode
// valid bit[15:0]
} SPIM_TypeDef;
#define SPIM (( SPIM_TypeDef *) SPIM_BASE)
#endif

162
core/reg/reg_spis.h Normal file
View File

@ -0,0 +1,162 @@
#ifndef _REG_SPIS_H_
#define _REG_SPIS_H_
#include "reg_base.h"
//================================
//BLOCK SPIS define
#define SPIS_BASE ((uint32_t)0x40005000)
#define SPIS_CTRL_ADDR_OFFSET 0x000
#define SPIS_STATUS_ADDR_OFFSET 0x004
#define SPIS_INFO_CLR_ADDR_OFFSET 0x008
#define SPIS_TX_DAT_ADDR_OFFSET 0x00c
#define SPIS_RX_DAT_ADDR_OFFSET 0x010
//================================
//BLOCK SPIS reg struct define
typedef union //0x000
{
struct
{
uint32_t SPIS_LSBFIRST: 1; // bit0 ---
// 0: MSB first for SPIS TX/RX;
// 1: LSB first for SPIS TX/RX;
uint32_t SPIS_CPOL: 1; // bit1 --- spi clock polarity control bit when SPIS is IDLE(cs is 1);
// 0: sample the data at the first clock edge
// 1: sample the data at the second clock edge
uint32_t SPIS_CPHA: 1; // bit2 --- clock phase used for sample data
// 0: sample the data at the first clock edge
// 1: sample the data at the second clock edge
uint32_t SPIS_RX_EN: 1; // bit3 --- spis rx control signal
// default is enable
// 0: spis RX disable
// 1: spis RX enable
// SPIS RX enable only when both spis en and spis rx en set as 1
uint32_t SPIS_RXINT_EN: 1; // bit4 ---
// 0: spis_rxint interrupt disable
// 1: spis_rxint interrupt enable
uint32_t SPIS_TX_DMA_MODE: 1; // bit5 --- SPIS TX operation mode control signal
// 1: DMA mode
// 0: MCU mode
uint32_t SPIS_RX_DMA_MODE: 1; // bit6 --- SPIS RX operation mode control signal
// 1: DMA mode
// 0: MCU mode
uint32_t SPIS_EN: 1; // bit7 ---
// 0: SPIS work disable
// 1: spis work enable
// [Note:the spis lsfirst,spis spol and spis spha can be configured only when spis en is 0]
uint32_t SPIS_OT_WIN: 8; // bit[15:8] --- config overtime window
// unit : bit width time
uint32_t SPIS_OT_EN: 1; // bit16 --- SPIS overtime enable
uint32_t SPIS_OTINT_EN: 1; // bit17
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} SPIS_CTRL_TypeDef; //0x000
//================================
#define SPIS_SPIS_LSBFIRST_POS 0
#define SPIS_SPIS_CPOL_POS 1
#define SPIS_SPIS_CPHA_POS 2
#define SPIS_SPIS_RX_EN_POS 3
#define SPIS_SPIS_RXINT_EN_POS 4
#define SPIS_SPIS_TX_DMA_MODE_POS 5
#define SPIS_SPIS_RX_DMA_MODE_POS 6
#define SPIS_SPIS_EN_POS 7
#define SPIS_SPIS_OT_WIN_LSB 8
#define SPIS_SPIS_OT_WIN_WIDTH 8
#define SPIS_SPIS_OT_EN_POS 16
#define SPIS_SPIS_OTINT_EN_POS 17
//================================
typedef union //0x004
{
struct
{
uint32_t SPIS_RXFIFO_EMPTY: 1; // bit0 ---
// 0: spis_rxfifo is not empty
// 1: spis_rxfifo is empty
uint32_t SPIS_RXFIFO_FULL: 1; // bit1 ---
// 0: spis_rxfifo is not full
// 1: spis_rxfifo is full
uint32_t SPIS_RXFIFO_NUM: 3; // bit[4:2] --- the SPIS RX data number in rxfifo
uint32_t RSV_NOUSE1: 1; // bit5 --- Ignore me
uint32_t SPIS_RX_OVERRUN: 1; // bit6 --- SPIS rxfifo overrun error signal
// 0: cleared by spis rx overrun clr
// 1: rxfifo overrun error
uint32_t SPIS_CS: 1; // bit7 --- the signal pin SPIS_CS
// 0: SPIS is selected
// 1: SPIS is not selected
uint32_t SPIS_TXFIFO_EMPTY: 1; // bit8 ---
// 0: spis_txfifo is not empty
// 1: spis_txfifo is empty
uint32_t SPIS_TXFIFO_FULL: 1; // bit9 ---
// 0: spis_txfifo is not full
// 1: spis_txfifo is full
// [Note:When txfifo is not full,MCU can write tx dat reg
uint32_t SPIS_TXFIFO_NUM: 3; // bit[12:10] --- the SPIS TX data number in txfifo
uint32_t RSV_NOUSE2: 3; // bit[15:13] --- Ignore me
uint32_t SPIS_RXINT_ST: 1; // bit16 --- when SPIS RX 1 byte,spis_rxint is 1
// cleared by spis_rxint_clr
uint32_t SPIS_OTINT_ST: 1; // bit17 --- set as 1 when SPIS overtime event happen
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} SPIS_STATUS_TypeDef; //0x004
//================================
#define SPIS_SPIS_RXFIFO_EMPTY_POS 0
#define SPIS_SPIS_RXFIFO_FULL_POS 1
#define SPIS_SPIS_RXFIFO_NUM_LSB 2
#define SPIS_SPIS_RXFIFO_NUM_WIDTH 3
#define SPIS_SPIS_RX_OVERRUN_POS 6
#define SPIS_SPIS_CS_POS 7
#define SPIS_SPIS_TXFIFO_EMPTY_POS 8
#define SPIS_SPIS_TXFIFO_FULL_POS 9
#define SPIS_SPIS_TXFIFO_NUM_LSB 10
#define SPIS_SPIS_TXFIFO_NUM_WIDTH 3
#define SPIS_SPIS_RXINT_ST_POS 16
#define SPIS_SPIS_OTINT_ST_POS 17
//================================
typedef union //0x008
{
struct
{
uint32_t SPIS_RX_OVERRUN_CLR: 1; // bit0 --- use to clear spis_rx_overrun
uint32_t SPIS_TXDAT_CLR: 1; // bit1 --- use to clear SPIS txfifo point and data reg
uint32_t SPIS_RXDAT_CLR: 1; // bit2 --- use to clear SPIS rxfifo point and data reg
uint32_t SPIS_RXINT_CLR: 1; // bit3 --- use clear spis_rxint
uint32_t SPIS_OTINT_CLR: 1; // bit4
uint32_t RSV_END: 27; // bit[31:5]
};
uint32_t Word;
} SPIS_INFO_CLR_TypeDef; //0x008
//================================
#define SPIS_SPIS_RX_OVERRUN_CLR_POS 0
#define SPIS_SPIS_TXDAT_CLR_POS 1
#define SPIS_SPIS_RXDAT_CLR_POS 2
#define SPIS_SPIS_RXINT_CLR_POS 3
#define SPIS_SPIS_OTINT_CLR_POS 4
//================================
//================================
//BLOCK SPIS top struct define
typedef struct
{
__IO SPIS_CTRL_TypeDef CTRL ; // 0x000,
__I SPIS_STATUS_TypeDef STATUS ; // 0x004,
__O SPIS_INFO_CLR_TypeDef INFO_CLR ; // 0x008,
__O uint32_t TX_DAT ; // 0x00c,
__I uint32_t RX_DAT ; // 0x010,
} SPIS_TypeDef;
#define SPIS (( SPIS_TypeDef *) SPIS_BASE)
#endif

239
core/reg/reg_syscfg.h Normal file
View File

@ -0,0 +1,239 @@
#ifndef _REG_SYSCFG_H_
#define _REG_SYSCFG_H_
#include "reg_base.h"
//================================
//BLOCK SYSCFG define
#define SYSCFG_BASE ((uint32_t)0x40001000)
#define SYSCFG_BB_PMU_ENABLE_ADDR_OFFSET 0x000
#define SYSCFG_AHB_MATRIX_PRIORITY_ADDR_OFFSET 0x004
#define SYSCFG_DBG_CTRL_ADDR_OFFSET 0x008
#define SYSCFG_USB_CTRL_ADDR_OFFSET 0x00c
#define SYSCFG_ROM_CTRL_ADDR_OFFSET 0x010
#define SYSCFG_SRAM_CTRL_ADDR_OFFSET 0x014
#define SYSCFG_ROM_SIGNATURE_TARGET_ADDR_OFFSET 0x018
#define SYSCFG_BIST_MODE_ADDR_OFFSET 0x01c
#define SYSCFG_BIST_STATUS_ADDR_OFFSET 0x020
#define SYSCFG_BIST_STATUS_CLR_ADDR_OFFSET 0x024
#define SYSCFG_ROM_SIGNATURE_RPT_ADDR_OFFSET 0x028
#define SYSCFG_CACHSRAM_CFG_ADDR_OFFSET 0x02c
#define SYSCFG_EM_BASE_CFG_ADDR_OFFSET 0x030
#define SYSCFG_CACHE_ACCESS_CNT_ADDR_OFFSET 0x034
#define SYSCFG_CACHE_HIT_CNT_ADDR_OFFSET 0x038
#define SYSCFG_ACC_CCR_BUSY_ADDR_OFFSET 0x03c
#define SYSCFG_MFV_ARRAY_D_ADDR_OFFSET 0x040
#define SYSCFG_SYS_BACKUP0_ADDR_OFFSET 0x044
//================================
//BLOCK SYSCFG reg struct define
typedef union //0x008
{
struct
{
uint32_t SYS_DEBUG_SEL: 2; // bit[1:0] ---
// 2'b00: rf_debug port enable
// 2'b01: BB debug port enable
// 2'b10: MODEM debug port enable
// 2'b11: USB debug port enable
uint32_t RF_EXT_EN: 1; // bit2 --- chip set as RF IP block
// 0: rf reg is controlled by on chip logic;
// 1: rf reg is controlled by external through SPI interface
uint32_t RF_SPI_EN: 1; // bit3 ---
// 0: RF reg is direct controlled by APB interface
// 1: RF reg is controlled by SPI interface
// note
// {rf_ext_en,rf_spi_en}
// 00: rf reg is controlled by on chip APB interface
// 01: rf reg is controlled by BB througth SPI interface
// 11: rf reg is controlled by external Chip through SPI interface
// 10: forbidden
uint32_t IWDT_DEBUG: 1; // bit4
uint32_t USB_DBG_SEL: 2; // bit[6:5]
uint32_t RSV_END: 25; // bit[31:7]
};
uint32_t Word;
} SYSCFG_DBG_CTRL_TypeDef; //0x008
//================================
#define SYSCFG_SYS_DEBUG_SEL_LSB 0
#define SYSCFG_SYS_DEBUG_SEL_WIDTH 2
#define SYSCFG_RF_EXT_EN_POS 2
#define SYSCFG_RF_SPI_EN_POS 3
#define SYSCFG_IWDT_DEBUG_POS 4
#define SYSCFG_USB_DBG_SEL_LSB 5
#define SYSCFG_USB_DBG_SEL_WIDTH 2
//================================
typedef union //0x00c
{
struct
{
uint32_t USB_SOF_INT_EN: 1; // bit0 --- when is 1, USB SOF signal can be used as interrupt
uint32_t USB_PHY_MOD: 1; // bit1 ---
// 1: the chip is set as USB PHY
uint32_t DIG_USB_PU: 2; // bit[3:2] --- set as 1 when USB function enable
// when is 1, enable pullup 1.5K for DP
uint32_t DIG_USB_RXEN: 1; // bit4
uint32_t RSV_NOUSE1: 3; // bit[7:5] --- Ignore me
uint32_t USB_NRSTO: 1; // bit8 --- when is 1, USB is exit reset
uint32_t USB_SUSPEND: 1; // bit9
uint32_t RSV_END: 22; // bit[31:10]
};
uint32_t Word;
} SYSCFG_USB_CTRL_TypeDef; //0x00c
//================================
#define SYSCFG_USB_SOF_INT_EN_POS 0
#define SYSCFG_USB_PHY_MOD_POS 1
#define SYSCFG_DIG_USB_PU_LSB 2
#define SYSCFG_DIG_USB_PU_WIDTH 2
#define SYSCFG_DIG_USB_RXEN_POS 4
#define SYSCFG_USB_NRSTO_POS 8
#define SYSCFG_USB_SUSPEND_POS 9
//================================
typedef union //0x010
{
struct
{
uint32_t ROM_RDMG: 4; // bit[3:0]
uint32_t ROM_RDMG_EN: 1; // bit4
uint32_t MEM_SCAN_IN: 1; // bit5
uint32_t RSV_NOUSE1: 2; // bit[7:6] --- Ignore me
uint32_t MDM_RDMG: 3; // bit[10:8]
uint32_t MDM_RDMG_EN: 1; // bit11
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} SYSCFG_ROM_CTRL_TypeDef; //0x010
//================================
#define SYSCFG_ROM_RDMG_LSB 0
#define SYSCFG_ROM_RDMG_WIDTH 4
#define SYSCFG_ROM_RDMG_EN_POS 4
#define SYSCFG_MEM_SCAN_IN_POS 5
#define SYSCFG_MDM_RDMG_LSB 8
#define SYSCFG_MDM_RDMG_WIDTH 3
#define SYSCFG_MDM_RDMG_EN_POS 11
//================================
typedef union //0x014
{
struct
{
uint32_t TAG_RDMG: 4; // bit[3:0]
uint32_t CACHE_RDMG: 4; // bit[7:4]
uint32_t EM_RDMG: 4; // bit[11:8]
uint32_t SADCMEM_RDMG: 4; // bit[15:12]
uint32_t USBMEM_RDMG: 4; // bit[19:16]
uint32_t DSRAM_RDMG: 3; // bit[22:20]
uint32_t RSV_NOUSE1: 1; // bit23 --- Ignore me
uint32_t TAG_RDMG_EN: 1; // bit24
uint32_t CACHE_RDMG_EN: 1; // bit25
uint32_t EM_RDMG_EN: 1; // bit26
uint32_t SADCMEM_RDMG_EN: 1; // bit27
uint32_t USBMEM_RDMG_EN: 1; // bit28
uint32_t DSRAM_RDMG_EN: 1; // bit29
uint32_t RSV_END: 2; // bit[31:30]
};
uint32_t Word;
} SYSCFG_SRAM_CTRL_TypeDef; //0x014
//================================
#define SYSCFG_TAG_RDMG_LSB 0
#define SYSCFG_TAG_RDMG_WIDTH 4
#define SYSCFG_CACHE_RDMG_LSB 4
#define SYSCFG_CACHE_RDMG_WIDTH 4
#define SYSCFG_EM_RDMG_LSB 8
#define SYSCFG_EM_RDMG_WIDTH 4
#define SYSCFG_SADCMEM_RDMG_LSB 12
#define SYSCFG_SADCMEM_RDMG_WIDTH 4
#define SYSCFG_USBMEM_RDMG_LSB 16
#define SYSCFG_USBMEM_RDMG_WIDTH 4
#define SYSCFG_DSRAM_RDMG_LSB 20
#define SYSCFG_DSRAM_RDMG_WIDTH 3
#define SYSCFG_TAG_RDMG_EN_POS 24
#define SYSCFG_CACHE_RDMG_EN_POS 25
#define SYSCFG_EM_RDMG_EN_POS 26
#define SYSCFG_SADCMEM_RDMG_EN_POS 27
#define SYSCFG_USBMEM_RDMG_EN_POS 28
#define SYSCFG_DSRAM_RDMG_EN_POS 29
//================================
//================================
//BLOCK SYSCFG top struct define
typedef struct
{
__IO uint32_t BB_PMU_ENABLE ; // 0x000,
__IO uint32_t AHB_MATRIX_PRIORITY ; // 0x004,
__IO SYSCFG_DBG_CTRL_TypeDef DBG_CTRL ; // 0x008,
__IO SYSCFG_USB_CTRL_TypeDef USB_CTRL ; // 0x00c,
__IO SYSCFG_ROM_CTRL_TypeDef ROM_CTRL ; // 0x010,
__IO SYSCFG_SRAM_CTRL_TypeDef SRAM_CTRL ; // 0x014,
__IO uint32_t ROM_SIGNATURE_TARGET; // 0x018,
// set rom_target_signature value before bist_mode as 1
__IO uint32_t BIST_MODE ; // 0x01c,
// all sram and rom bist start
// note: bist follow
// mode 1 : get report from GPIO
// 1) : config GPIO for glb_bist_done and glb_bist_fail
// 2) : set rom_signature_target value
// 3) : set bist_mode as 1
// 4) : wait a fixed time
// 5) : check the glb_bist_done and glb_bist_fail state through GPIO
//
// mode 2 : get report from bist_statues
// 1) : set rom_signature_target value
// 2) : set bist_mode as 1
// 3) : wait a fixed time
// 4) : reset chip, and reconnect chip through UART
// 5) : check the glb_bist_done and glb_bist_fail state through bist_status[1:0]
// option step 6) : set bist_status_clr as 1 for clear status
__I uint32_t BIST_STATUS ; // 0x020,
// [0] global bist done
// [1] global bist fail
// [2] em_bist_done
// [3] sram_bist_done
// [4] sadcmem_bist_done
// [5] mdm_bist_done
// [6] rom_bist_done
// [7] em_bist_fail
// [8] sram_bist_fail
// [9] sadcmem_bist_fail
// [10] mdmmem_bist_fail
// [11] rom_bist_fail
__O uint32_t BIST_STATUS_CLR ; // 0x024,
__I uint32_t ROM_SIGNATURE_RPT ; // 0x028,
// rom signature report, just use for debug
__IO uint32_t CACHSRAM_CFG ; // 0x02c,
// 0: the 4KB sram use as CACHE
// 1: the 4KB sram use as DATA SRAM: 0x2000_6000 ~ 0x2000_6FFF
__IO uint32_t EM_BASE_CFG ; // 0x030,
// 1KB step
// 0: BB EM base addr: 0x2000_8000, EM size : 8KB
// 1: BB EM base addr: 0x2000_8400, EM size : 7KB
// 2: BB EM base addr: 0x2000_8800, EM size : 6KB
// 3: BB EM base addr: 0x2000_8c00, EM size : 5KB
// 4: BB EM base addr: 0x2000_9000, EM size : 4KB
// 5: BB EM base addr: 0x2000_9400, EM size : 3KB
// 6: BB EM base addr: 0x2000_9800, EM size : 2KB
// 7: BB EM base addr: 0x2000_9c00, EM size : 1KB
__I uint32_t CACHE_ACCESS_CNT ; // 0x034,
__I uint32_t CACHE_HIT_CNT ; // 0x038,
__I uint32_t ACC_CCR_BUSY ; // 0x03c,
// cache status
__I uint32_t MFV_ARRAY_D ; // 0x040,
__IO uint32_t SYS_BACKUP0 ; // 0x044,
// only reset by core por12_core_stb
} SYSCFG_TypeDef;
#define SYSCFG (( SYSCFG_TypeDef *) SYSCFG_BASE)
#endif

444
core/reg/reg_timer.h Normal file
View File

@ -0,0 +1,444 @@
#ifndef _REG_TIMER_H_
#define _REG_TIMER_H_
#include "reg_base.h"
#define CTMR_BASE 0x40021000
#define ATMR_BASE 0x40022000
typedef union // 0x000 TIM_CR1
{
struct
{
uint32_t CEN: 1; // bit0 --- Counter Enable
uint32_t UDIS: 1; // bit1 --- Update Disable
uint32_t URS: 1; // bit2 --- Update Request Source
uint32_t OPM: 1; // bit3 --- One Pluse Mode
uint32_t DIR: 1; // bit4 --- Direction
uint32_t CMS: 2; // bit[6:5] --- Center-aligned Mode Select
uint32_t ARPE: 1; // bit7 --- Auto-Reload Preload Enable
uint32_t CKD: 2; // bit[9:8] --- Clock Division
uint32_t CMPSEL: 2; // bit[11:10]--- Compare input Select (Only ADTMR1)
uint32_t RES: 20; // bit[31:12]--- Reserved
};
uint32_t Word;
} TIMER_CR1_Typedef;
//================================
#define TIMER_CEN_POS 0
#define TIMER_UDIS_POS 1
#define TIMER_URS_POS 2
#define TIMER_OPM_POS 3
#define TIMER_DIR_POS 4
#define TIMER_CMS_LSB 5
#define TIMER_CMS_WIDTH 2
#define TIMER_ARPE_POS 7
#define TIMER_CKD_LSB 8
#define TIMER_CKD_WIDTH 2
#define TIMER_CMP_SEL_LSB 10
#define TIMER_CMP_SEL_WIDTH 2
//================================
typedef union // 0x004 TIM_CR2
{
struct
{
uint32_t CCPC: 1; // bit0 --- Capture/Compare Preload Control
uint32_t RES0: 1; // bit1 --- Reserved
uint32_t CCUS: 1; // bit2 --- Capture/Compare Control Update Select
uint32_t CCDS: 1; // bit3 --- Capture/Compare DMA Select
uint32_t MMS: 3; // bit[6:4] --- Master Mode Select
uint32_t TI1S: 1; // bit7 --- TI1 Select
uint32_t OIS1: 1; // bit8 --- Output Idle State1(OC1 Output)
uint32_t OIS1N: 1; // bit9 --- Output Idle State1(OC1N Output)
uint32_t OIS2: 1; // bit10 --- Output Idle State2(OC2 Output)
uint32_t OIS2N: 1; // bit11 --- Output Idle State2(OC2N Output)
uint32_t OIS3: 1; // bit12 --- Output Idle State3(OC3 Output)
uint32_t OIS3N: 1; // bit13 --- Output Idle State3(OC3N Output)
uint32_t OIS4: 1; // bit14 --- Output Idle State4(OC4 Output)
uint32_t RES1: 17; // bit[31:15]--- Reserved
};
uint32_t Word;
} TIMER_CR2_Typedef;
//================================
#define TIMER_CCPC_POS 0
#define TIMER_CCUS_POS 2
#define TIMER_CCDS_POS 3
#define TIMER_MMS_LSB 4
#define TIMER_MMS_WIDTH 3
#define TIMER_TI1S_POS 7
#define TIMER_OIS1_POS 8
#define TIMER_OIS1N_POS 9
#define TIMER_OIS2_POS 10
#define TIMER_OIS2N_POS 11
#define TIMER_OIS3_POS 12
#define TIMER_OIS3N_POS 13
#define TIMER_OIS4_POS 14
//================================
typedef union // 0x008 TIM_SMCR
{
struct
{
uint32_t SMS: 3; // bit[2:0] --- Slave Mode Select
uint32_t RES0: 1; // bit3 --- Reserved
uint32_t TS: 3; // bit[6:4] --- Trigger Select
uint32_t MSM: 1; // bit7 --- Master/Slave Mode
uint32_t ETF: 4; // bit[11:8] --- External Trigger Filter
uint32_t ETPS: 2; // bit[13:12]--- External Trigger Prescaler
uint32_t ETE: 1; // bit14 --- External Clock Enable
uint32_t ETP: 1; // bit15 --- External Trigger Polarity
uint32_t RES1: 16; // bit[31:16]--- Reserved
};
uint32_t Word;
} TIMER_SMCR_Typedef;
//================================
#define TIMER_SMS_LSB 0
#define TIMER_SMS_WIDTH 3
#define TIMER_TS_LSB 4
#define TIMER_TS_WIDTH 3
#define TIMER_MSM_POS 7
#define TIMER_ETF_LSB 8
#define TIMER_ETF_WIDTH 4
#define TIMER_ETPS_LSB 12
#define TIMER_ETPS_WIDTH 2
#define TIMER_ETE_POS 14
#define TIMER_ETP_POS 15
//================================
typedef union // 0x00C/0x010/0x014/0x018/0x01C/0x020 TIM_IER/IDR/IVS/RIF/IFM/ICR
{
struct
{
uint32_t UI: 1; // bit0 --- Update Interrupt
uint32_t CC1I: 1; // bit1 --- Capture/Compare 1 Interrupt
uint32_t CC2I: 1; // bit2 --- Capture/Compare 2 Interrupt
uint32_t CC3I: 1; // bit3 --- Capture/Compare 3 Interrupt
uint32_t CC4I: 1; // bit4 --- Capture/Compare 4 Interrupt
uint32_t COMI: 1; // bit5 --- COM Interrupt
uint32_t TI: 1; // bit6 --- Trigger Interrupt
uint32_t BI: 1; // bit7 --- Break Interrupt
uint32_t RES0: 1; // bit8 --- Reserved
uint32_t CC1OI: 1; // bit9 --- Capture/Compare 1 Overcapture Interrupt
uint32_t CC2OI: 1; // bit10 --- Capture/Compare 2 Overcapture Interrupt
uint32_t CC3OI: 1; // bit11 --- Capture/Compare 3 Overcapture Interrupt
uint32_t CC4OI: 1; // bit12 --- Capture/Compare 4 Overcapture Interrupt
uint32_t RES1: 19; // bit[31:13]--- Reserved
};
uint32_t Word;
} TIMER_INT_Typedef;
//================================
#define TIMER_UI_POS 0
#define TIMER_CC1I_POS 1
#define TIMER_CC2I_POS 2
#define TIMER_CC3I_POS 3
#define TIMER_CC4I_POS 4
#define TIMER_COMI_POS 5
#define TIMER_TI_POS 6
#define TIMER_BI_POS 7
#define TIMER_CC1OI_POS 9
#define TIMER_CC2OI_POS 10
#define TIMER_CC3OI_POS 11
#define TIMER_CC4OI_POS 12
//================================
typedef union // 0x024 TIM_EGR
{
struct
{
uint32_t UG: 1; // bit0 --- Update Generation
uint32_t CC1G: 1; // bit1 --- Capture/Compare 1 Generation
uint32_t CC2G: 1; // bit2 --- Capture/Compare 2 Generation
uint32_t CC3G: 1; // bit3 --- Capture/Compare 3 Generation
uint32_t CC4G: 1; // bit4 --- Capture/Compare 4 Generation
uint32_t COMG: 1; // bit5 --- Capture/Compare Control Update Generation
uint32_t TG: 1; // bit6 --- Trigger Generation
uint32_t BG: 1; // bit7 --- Break Generation
uint32_t RES: 24; // bit[31:8]--- Reserved
};
uint32_t Word;
} TIMER_EGR_Typedef;
//================================
#define TIMER_UG_POS 0
#define TIMER_CC1G_POS 1
#define TIMER_CC2G_POS 2
#define TIMER_CC3G_POS 3
#define TIMER_CC4G_POS 4
#define TIMER_COMG_POS 5
#define TIMER_TG_POS 6
#define TIMER_BG_POS 7
//================================
typedef union // 0x028 TIM_CCMR1
{
struct
{
uint32_t CC1S: 2; // bit[1:0] --- Capture/Compare 1 Select
uint32_t OC1FE: 1; // bit2 --- Output Compare 1 Fast Enable
uint32_t OC1PE: 1; // bit3 --- Output Compare 1 Preload Enable
uint32_t OC1M: 3; // bit[6:4] --- Output Compare 1 Mode
uint32_t OC1CE: 1; // bit7 --- Output Compare 1 Clear Enable
uint32_t CC2S: 2; // bit[9:8] --- Capture/Compare 2 Select
uint32_t OC2FE: 1; // bit10 --- Output Compare 2 Fast Enable
uint32_t OC2PE: 1; // bit11 --- Output Compare 2 Preload Enable
uint32_t OC2M: 3; // bit[14:12]--- Output Compare 2 Mode
uint32_t OC2CE: 1; // bit15 --- Output Compare 2 Clear Enable
uint32_t RES: 16; // bit[31:16]--- Reserved
}OUTPUT;
struct
{
uint32_t CC1S: 2; // bit[1:0] --- Capture/Compare 1 Select
uint32_t IC1PSC: 2; // bit[3:2] --- Input Capture 1 Prescaler
uint32_t IC1F: 4; // bit[7:4] --- Input Capture 1 Filter
uint32_t CC2S: 2; // bit[9:8] --- Capture/Compare 2 Select
uint32_t IC2PSC: 2; // bit[11:10]--- Input Capture 2 Prescaler
uint32_t IC2F: 4; // bit[15:12]--- Input Capture 2 Filter
uint32_t RES: 16; // bit[31:16]--- Reserved
}INPUT;
uint32_t Word;
} TIMER_CCMR1_Typedef;
//================================
#define TIMER_OUT_CC1S_LSB 0
#define TIMER_OUT_CC1S_WIDTH 2
#define TIMER_OUT_OC1FE_POS 2
#define TIMER_OUT_OC1PE_POS 3
#define TIMER_OUT_OC1M_LSB 4
#define TIMER_OUT_OC1M_WIDTH 3
#define TIMER_OUT_OC1CE_POS 7
#define TIMER_OUT_CC2S_LSB 8
#define TIMER_OUT_CC2S_WIDTH 2
#define TIMER_OUT_OC2FE_POS 10
#define TIMER_OUT_OC2PE_POS 11
#define TIMER_OUT_OC2M_LSB 12
#define TIMER_OUT_OC2M_WIDTH 3
#define TIMER_OUT_OC2CE_POS 15
//================================
#define TIMER_IN_CC1S_LSB 0
#define TIMER_IN_CC1S_WIDTH 2
#define TIMER_IN_IC1PSC_LSB 2
#define TIMER_IN_IC1PSC_WIDTH 2
#define TIMER_IN_IC1F_LSB 4
#define TIMER_IN_IC1F_WIDTH 4
#define TIMER_IN_CC2S_LSB 8
#define TIMER_IN_CC2S_WIDTH 2
#define TIMER_IN_IC2PSC_LSB 10
#define TIMER_IN_IC2PSC_WIDTH 2
#define TIMER_IN_IC2F_LSB 12
#define TIMER_IN_IC2F_WIDTH 4
//================================
typedef union // 0x02C TIM_CCMR2
{
struct
{
uint32_t CC3S: 2; // bit[1:0] --- Capture/Compare 3 Select
uint32_t OC3FE: 1; // bit2 --- Output Compare 3 Fast Enable
uint32_t OC3PE: 1; // bit3 --- Output Compare 3 Preload Enable
uint32_t OC3M: 3; // bit[6:4] --- Output Compare 3 Mode
uint32_t OC3CE: 1; // bit7 --- Output Compare 3 Clear Enable
uint32_t CC4S: 2; // bit[9:8] --- Capture/Compare 4 Select
uint32_t OC4FE: 1; // bit10 --- Output Compare 4 Fast Enable
uint32_t OC4PE: 1; // bit11 --- Output Compare 4 Preload Enable
uint32_t OC4M: 3; // bit[14:12]--- Output Compare 4 Mode
uint32_t OC4CE: 1; // bit15 --- Output Compare 4 Clear Enable
uint32_t RES: 16; // bit[31:16]--- Reserved
}OUTPUT;
struct
{
uint32_t CC3S: 2; // bit[1:0] --- Capture/Compare 3 Select
uint32_t IC3PSC: 2; // bit[3:2] --- Input Capture 3 Prescaler
uint32_t IC3F: 4; // bit[7:4] --- Input Capture 3 Filter
uint32_t CC4S: 2; // bit[9:8] --- Capture/Compare 4 Select
uint32_t IC4PSC: 2; // bit[11:10]--- Input Capture 4 Prescaler
uint32_t IC4F: 4; // bit[15:12]--- Input Capture 4 Filter
uint32_t RES: 16; // bit[31:16]--- Reserved
}INPUT;
uint32_t Word;
} TIMER_CCMR2_Typedef;
//================================
#define TIMER_OUT_CC3S_LSB 0
#define TIMER_OUT_CC3S_WIDTH 2
#define TIMER_OUT_OC3FE_POS 2
#define TIMER_OUT_OC3PE_POS 3
#define TIMER_OUT_OC3M_LSB 4
#define TIMER_OUT_OC3M_WIDTH 3
#define TIMER_OUT_OC3CE_POS 7
#define TIMER_OUT_CC4S_LSB 8
#define TIMER_OUT_CC4S_WIDTH 2
#define TIMER_OUT_OC4FE_POS 10
#define TIMER_OUT_OC4PE_POS 11
#define TIMER_OUT_OC4M_LSB 12
#define TIMER_OUT_OC4M_WIDTH 3
#define TIMER_OUT_OC4CE_POS 15
//================================
#define TIMER_IN_CC3S_LSB 0
#define TIMER_IN_CC3S_WIDTH 2
#define TIMER_IN_IC3PSC_LSB 2
#define TIMER_IN_IC3PSC_WIDTH 2
#define TIMER_IN_IC3F_LSB 4
#define TIMER_IN_IC3F_WIDTH 4
#define TIMER_IN_CC4S_LSB 8
#define TIMER_IN_CC4S_WIDTH 2
#define TIMER_IN_IC4PSC_LSB 10
#define TIMER_IN_IC4PSC_WIDTH 2
#define TIMER_IN_IC4F_LSB 12
#define TIMER_IN_IC4F_WIDTH 4
//================================
typedef union // 0x030 TIM_CCER
{
struct
{
uint32_t CC1E: 1; //bit0 --- Capture/Compare 1 Output Enable
uint32_t CC1P: 1; //bit1 --- Capture/Compare 1 Output Polarity
uint32_t CC1NE: 1; //bit2 --- Capture/Compare 1 Complementary Output Enable
uint32_t CC1NP: 1; //bit3 --- Capture/Compare 1 Complementary Output Polarity
uint32_t CC2E: 1; //bit4 --- Capture/Compare 2 Output Enable
uint32_t CC2P: 1; //bit5 --- Capture/Compare 2 Output Polarity
uint32_t CC2NE: 1; //bit6 --- Capture/Compare 2 Complementary Output Enable
uint32_t CC2NP: 1; //bit7 --- Capture/Compare 2 Complementary Output Polarity
uint32_t CC3E: 1; //bit8 --- Capture/Compare 3 Output Enable
uint32_t CC3P: 1; //bit9 --- Capture/Compare 3 Output Polarity
uint32_t CC3NE: 1; //bit10 --- Capture/Compare 3 Complementary Output Enable
uint32_t CC3NP: 1; //bit11 --- Capture/Compare 3 Complementary Output Polarity
uint32_t CC4E: 1; //bit12 --- Capture/Compare 4 Output Enable
uint32_t CC4P: 1; //bit13 --- Capture/Compare 4 Output Polarity
uint32_t RES: 18; //bit[31:14]--- Reserved
};
uint32_t Word;
} TIMER_CCER_Typedef;
//================================
#define TIMER_CC1E_POS 0
#define TIMER_CC1P_POS 1
#define TIMER_CC1NE_POS 2
#define TIMER_CC1NP_POS 3
#define TIMER_CC2E_POS 4
#define TIMER_CC2P_POS 5
#define TIMER_CC2NE_POS 6
#define TIMER_CC2NP_POS 7
#define TIMER_CC3E_POS 8
#define TIMER_CC3P_POS 9
#define TIMER_CC3NE_POS 10
#define TIMER_CC3NP_POS 11
#define TIMER_CC4E_POS 12
#define TIMER_CC4P_POS 13
//================================
typedef union // 0x054 TIM_BDTR
{
struct
{
uint32_t DTG: 8; // bit[7:0] --- Dead-Time Generator Setup
uint32_t LOCK: 2; // bit[9:8] --- Lock Configuration
uint32_t OSSI: 1; // bit10 --- Off-state Selection for Idle Mode
uint32_t OSSR: 1; // bit11 --- Off-state Selection for Run Mode
uint32_t BKE: 1; // bit12 --- Break Enable
uint32_t BKP: 1; // bit13 --- Break Polarity
uint32_t AOE: 1; // bit14 --- Automatic Output Enable
uint32_t MOE: 1; // bit15 --- Main Output Enable
uint32_t RES: 16; // bit[31:16]--- Reserved
};
uint32_t Word;
} TIMER_BDTR_Typedef;
//================================
#define TIMER_DTG_LSB 0
#define TIMER_DTG_WIDTH 8
#define TIMER_LOCK_LSB 8
#define TIMER_LOCK_WIDTH 2
#define TIMER_OSSI_POS 10
#define TIMER_OSSR_POS 11
#define TIMER_BKE_POS 12
#define TIMER_BKP_POS 13
#define TIMER_AOE_POS 14
#define TIMER_MOE_POS 15
//===================================
typedef union // 0x058 TIM_DMAEN
{
struct
{
uint32_t UDE: 1; // bit0 --- Update DMA Request Enable
uint32_t CC1DE: 1; // bit1 --- Capture/Compare 1 DMA Request Enable
uint32_t CC2DE: 1; // bit2 --- Capture/Compare 2 DMA Request Enable
uint32_t CC3DE: 1; // bit3 --- Capture/Compare 3 DMA Request Enable
uint32_t CC4DE: 1; // bit4 --- Capture/Compare 4 DMA Request Enable
uint32_t COMDE: 1; // bit5 --- COM DMA Request Enable
uint32_t TDE: 1; // bit6 --- Trigger DMA Request Enable
uint32_t RES: 25; // bit[31:7]--- Reserved
};
uint32_t Word;
} TIMER_DMAEN_Typedef;
//================================
#define TIMER_UDE_POS 0
#define TIMER_CC1DE_POS 1
#define TIMER_CC2DE_POS 2
#define TIMER_CC3DE_POS 3
#define TIMER_CC4DE_POS 4
#define TIMER_COMDE_POS 5
#define TIMER_TDE_POS 6
//================================
typedef struct
{
__IO TIMER_CR1_Typedef CR1 ; // 0x000 --- Control register 1
__IO TIMER_CR2_Typedef CR2 ; // 0x004 --- Control register 2
__IO TIMER_SMCR_Typedef SMCR ; // 0x008 --- Slave mode control register
__O TIMER_INT_Typedef IER ; // 0x00C --- Interrupt Enable register
__O TIMER_INT_Typedef IDR ; // 0x010 --- Interrupt Disable register
__I TIMER_INT_Typedef IVS ; // 0x014 --- Interrupt Valid status register
__I TIMER_INT_Typedef RIF ; // 0x018 --- Interrupt Raw interrupt Flag
__I TIMER_INT_Typedef IFM ; // 0x01C --- Interrupt Masked interrupt Flag
__O TIMER_INT_Typedef ICR ; // 0x020 --- Interrupt Clear status register
__IO TIMER_EGR_Typedef EGR ; // 0x024 --- Event generation register
union {
__IO uint32_t CCMR[2];
struct {
__IO TIMER_CCMR1_Typedef CCMR1; // 0x028 Capture/compare mode register 1
__IO TIMER_CCMR2_Typedef CCMR2; // 0x02C Capture/compare mode register 2
};
};
__IO TIMER_CCER_Typedef CCER ; // 0x030 --- Capture/compare enable register
__IO uint32_t CNT ; // 0x034 --- Timer Counter
__IO uint32_t PSC ; // 0x038 --- Prescaler
__IO uint32_t ARR ; // 0x03C --- Auto-reload register
__IO uint32_t RCR ; // 0x040 --- Repetition counter register
union {
__IO uint32_t CCR[4];
struct {
__IO uint32_t CCR1 ; // 0x044 --- Capture/compare register 1
__IO uint32_t CCR2 ; // 0x048 --- Capture/compare register 2
__IO uint32_t CCR3 ; // 0x04C --- Capture/compare register 3
__IO uint32_t CCR4 ; // 0x050 --- Capture/compare register 4
};
};
__IO TIMER_BDTR_Typedef BDTR ; // 0x054 --- Break and dead-time register
__IO TIMER_DMAEN_Typedef DMAEN; // 0x058 --- DMA trigger event enable
} TIMER_TypeDef;
#define CTMR ((TIMER_TypeDef *) CTMR_BASE)
#define ATMR ((TIMER_TypeDef *) ATMR_BASE)
#endif // _REG_TIMER_H_

426
core/reg/reg_uart.h Normal file
View File

@ -0,0 +1,426 @@
#ifndef _REG_UART_H_
#define _REG_UART_H_
#include "reg_base.h"
//================================
//BLOCK UART define
#define UART1_BASE ((uint32_t)0x40023000)
#define UART2_BASE ((uint32_t)0x40024000)
#define UART_RBR_ADDR_OFFSET 0x000
#define UART_TBR_ADDR_OFFSET 0x004
#define UART_BRR_ADDR_OFFSET 0x008
#define UART_LCR_ADDR_OFFSET 0x00c
#define UART_MCR_ADDR_OFFSET 0x010
#define UART_CR_ADDR_OFFSET 0x014
#define UART_RTOR_ADDR_OFFSET 0x018
#define UART_FCR_ADDR_OFFSET 0x01c
#define UART_SR_ADDR_OFFSET 0x020
#define UART_IER_ADDR_OFFSET 0x024
#define UART_IDR_ADDR_OFFSET 0x028
#define UART_IVS_ADDR_OFFSET 0x02c
#define UART_RIF_ADDR_OFFSET 0x030
#define UART_IFM_ADDR_OFFSET 0x034
#define UART_ICR_ADDR_OFFSET 0x038
//================================
//BLOCK UART reg struct define
typedef union //0x00c
{
struct
{
uint32_t DLS: 2; // bit[1:0] --- data length select
uint32_t STOP: 1; // bit2 --- stop bit select
uint32_t PE: 1; // bit3 --- parity enable bit
uint32_t PS: 1; // bit4 --- parity mode select
uint32_t RXEN: 1; // bit5 --- uart receive enable
uint32_t BC: 1; // bit6 --- break control
uint32_t BRWEN: 1; // bit7 --- baud rate write enable
uint32_t RTOEN: 1; // bit8 --- receive time out enable
uint32_t MSBFIRST: 1; // bit9 --- the most significant bit first
uint32_t DATAINV: 1; // bit10 --- binary data inversion
uint32_t RXINV: 1; // bit11 --- rx pin active level inversion
uint32_t TXINV: 1; // bit12 --- tx pin active level inversion
uint32_t SWAP: 1; // bit13 --- swap tx/rx pin
uint32_t RTO_SEL: 1; // bit14 --- receiver timeout mode select: 0:CPU; 1:DMA
uint32_t RSV_END: 17; // bit[31:15]
};
uint32_t Word;
} UART_LCR_TypeDef; //0x00c
//================================
#define UART_DLS_LSB 0
#define UART_DLS_WIDTH 2
#define UART_STOP_POS 2
#define UART_PE_POS 3
#define UART_PS_POS 4
#define UART_RXEN_POS 5
#define UART_BC_POS 6
#define UART_BRWEN_POS 7
#define UART_RTOEN_POS 8
#define UART_MSBFIRST_POS 9
#define UART_DATAINV_POS 10
#define UART_RXINV_POS 11
#define UART_TXINV_POS 12
#define UART_SWAP_POS 13
#define UART_RTO_SEL_POS 14
//================================
typedef union //0x010
{
struct
{
uint32_t IREN: 1; // bit0 --- irDA mode enable (only uart)
uint32_t LBEN: 1; // bit1 --- loopback enable
uint32_t AFCEN: 1; // bit2 --- auto flow control enable
uint32_t RTSCTRL: 1; // bit3 --- auto flow RTS
uint32_t AADEN: 1; // bit4 --- 485 auto address en
uint32_t AADNOR: 1; // bit5 --- 485 auto address normal
uint32_t AADDIR: 1; // bit6 --- 485 auto address direction control en
uint32_t AADINV: 1; // bit7 --- 485 auto address RTS invert
uint32_t LINEN: 1; // bit8 --- lin mode en
uint32_t BKREQ: 1; // bit9 --- lin break request
uint32_t LINBDL: 1; // bit10 --- lin break detection length
uint32_t DMAEN: 1; // bit11 --- DMA en
uint32_t ABREN: 1; // bit12 --- auto baud
uint32_t ABRMOD: 2; // bit[14:13] --- auto baud rate
uint32_t ABRRS: 1; // bit15 --- auto baud restart
uint32_t SCEN: 1; // bit16 --- smart en
uint32_t SCNACK: 1; // bit17 --- smart nack
uint32_t SCCNT: 3; // bit[20:18] --- smart error
uint32_t CLKEN: 1; // bit21 --- smart clock
uint32_t HDSEL: 1; // bit22 --- half-duplex seletion
uint32_t RSV_END: 9; // bit[31:23]
};
uint32_t Word;
} UART_MCR_TypeDef; //0x010
//================================
#define UART_IREN_POS 0
#define UART_LBEN_POS 1
#define UART_AFCEN_POS 2
#define UART_RTSCTRL_POS 3
#define UART_AADEN_POS 4
#define UART_AADNOR_POS 5
#define UART_AADDIR_POS 6
#define UART_AADINV_POS 7
#define UART_LINEN_POS 8
#define UART_BKREQ_POS 9
#define UART_LINBDL_POS 10
#define UART_DMAEN_POS 11
#define UART_ABREN_POS 12
#define UART_ABRMOD_LSB 13
#define UART_ABRMOD_WIDTH 2
#define UART_ABRRS_POS 15
#define UART_SCEN_POS 16
#define UART_SCNACK_POS 17
#define UART_SCCNT_LSB 18
#define UART_SCCNT_WIDTH 3
#define UART_CLKEN_POS 21
#define UART_HDSEL_POS 22
//================================
typedef union //0x014
{
struct
{
uint32_t ADDR: 8; // bit[7:0] --- rs485 address match value
uint32_t DLY: 8; // bit[15:8] --- rs485 delay value
uint32_t PSC: 8; // bit[23:16] --- prescaler value (only uart)
uint32_t GT: 8; // bit[31:24] --- guard time value (only uart)
};
uint32_t Word;
} UART_CR_TypeDef; //0x014
//================================
#define UART_ADDR_LSB 0
#define UART_ADDR_WIDTH 8
#define UART_DLY_LSB 8
#define UART_DLY_WIDTH 8
#define UART_PSC_LSB 16
#define UART_PSC_WIDTH 8
#define UART_GT_LSB 24
#define UART_GT_WIDTH 8
//================================
typedef union //0x018
{
struct
{
uint32_t RTO: 24; // bit[23:0] --- receive timeout value
uint32_t BLEN: 8; // bit[31:24] --- block length
};
uint32_t Word;
} UART_RTOR_TypeDef; //0x018
//================================
#define UART_RTO_LSB 0
#define UART_RTO_WIDTH 24
#define UART_BLEN_LSB 24
#define UART_BLEN_WIDTH 8
//================================
typedef union //0x01c
{
struct
{
uint32_t FIFOEN: 1; // bit0 --- fifo enable
uint32_t RFRST: 1; // bit1 --- fifo rx reset data
uint32_t TFRST: 1; // bit2 --- fifo tx reset data
uint32_t RSV_NOUSE1: 1; // bit3 --- Ignore me
uint32_t RXTL: 2; // bit[5:4] --- fifo rx trigger level
uint32_t TXTL: 2; // bit[7:6] --- fifo tx trigger level
uint32_t RXFL: 5; // bit[12:8] --- fifo rx level counter
uint32_t TXFL: 5; // bit[17:13] --- fifo tx level counter
uint32_t RSV_END: 14; // bit[31:18]
};
uint32_t Word;
} UART_FCR_TypeDef; //0x01c
//================================
#define UART_FIFOEN_POS 0
#define UART_RFRST_POS 1
#define UART_TFRST_POS 2
#define UART_RXTL_LSB 4
#define UART_RXTL_WIDTH 2
#define UART_TXTL_LSB 6
#define UART_TXTL_WIDTH 2
#define UART_RXFL_LSB 8
#define UART_RXFL_WIDTH 5
#define UART_TXFL_LSB 13
#define UART_TXFL_WIDTH 5
//================================
typedef union //0x020
{
struct
{
uint32_t DR: 1; // bit0 --- data ready
uint32_t OE: 1; // bit1 --- overrun error
uint32_t PE: 1; // bit2 --- parity error
uint32_t FE: 1; // bit3 --- framing error
uint32_t BF: 1; // bit4 --- break interrupt
uint32_t TBEM: 1; // bit5 --- transmit buffer register empty
uint32_t TEM: 1; // bit6 --- transmitter empty
uint32_t RFE: 1; // bit7 --- receiver fifo data error
uint32_t BUSY: 1; // bit8 --- uart busy
uint32_t TFNF: 1; // bit9 --- transmit fifo not full
uint32_t TFEM: 1; // bit10 --- transmit fifo empty
uint32_t RFNE: 1; // bit11 --- receive fifo not empty
uint32_t RFF: 1; // bit12 --- receive fifo full
uint32_t DCTS: 1; // bit13 --- delta clear to send
uint32_t CTS: 1; // bit14 --- clear to send
uint32_t RSV_END: 17; // bit[31:15]
};
uint32_t Word;
} UART_SR_TypeDef; //0x020
//================================
#define UART_SR_DR_POS 0
#define UART_SR_OE_POS 1
#define UART_SR_PE_POS 2
#define UART_SR_FE_POS 3
#define UART_SR_BF_POS 4
#define UART_SR_TBEM_POS 5
#define UART_SR_TEM_POS 6
#define UART_SR_RFE_POS 7
#define UART_SR_BUSY_POS 8
#define UART_SR_TFNF_POS 9
#define UART_SR_TFEM_POS 10
#define UART_SR_RFNE_POS 11
#define UART_SR_RFF_POS 12
#define UART_SR_DCTS_POS 13
#define UART_SR_CTS_POS 14
//================================
typedef union //0x024
{
struct
{
uint32_t RXRD: 1; // bit0 --- receive data available interrupt enable status
uint32_t TXS: 1; // bit1 --- thr empty interrupt enable status
uint32_t RXS: 1; // bit2 --- receiver line status interrupt enable status
uint32_t MDS: 1; // bit3 --- modem status interrupt enable status
uint32_t RTO: 1; // bit4 --- receiver timeout enable status
uint32_t BUSY: 1; // bit5 --- busy detect interrupt enable status
uint32_t ABE: 1; // bit6 --- auto baud rate end interrupt enable status
uint32_t ABTO: 1; // bit7 --- auto baud rate timeout interrupt enable status
uint32_t LINBK: 1; // bit8 --- lin break detection interrupt enable status
uint32_t TC: 1; // bit9 --- transmission complete interrupt enable status
uint32_t EOB: 1; // bit10 --- end of block interrupt enable status
uint32_t CM: 1; // bit11 --- character match interrupt enable status
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} UART_IER_TypeDef; //0x024
//================================
#define UART_INT_RXRD_POS 0
#define UART_INT_TXS_POS 1
#define UART_INT_RXS_POS 2
#define UART_INT_MDS_POS 3
#define UART_INT_RTO_POS 4
#define UART_INT_BUSY_POS 5
#define UART_INT_ABE_POS 6
#define UART_INT_ABTO_POS 7
#define UART_INT_LINBK_POS 8
#define UART_INT_TC_POS 9
#define UART_INT_EOB_POS 10
#define UART_INT_CM_POS 11
//================================
typedef union //0x028
{
struct
{
uint32_t RXRD: 1; // bit0 --- receive data available interrupt enable status
uint32_t TXS: 1; // bit1 --- thr empty interrupt enable status
uint32_t RXS: 1; // bit2 --- receiver line status interrupt enable status
uint32_t MDS: 1; // bit3 --- modem status interrupt enable status
uint32_t RTO: 1; // bit4 --- receiver timeout enable status
uint32_t BUSY: 1; // bit5 --- busy detect interrupt enable status
uint32_t ABE: 1; // bit6 --- auto baud rate end interrupt enable status
uint32_t ABTO: 1; // bit7 --- auto baud rate timeout interrupt enable status
uint32_t LINBK: 1; // bit8 --- lin break detection interrupt enable status
uint32_t TC: 1; // bit9 --- transmission complete interrupt enable status
uint32_t EOB: 1; // bit10 --- end of block interrupt enable status
uint32_t CM: 1; // bit11 --- character match interrupt enable status
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} UART_IDR_TypeDef; //0x028
typedef union //0x02c
{
struct
{
uint32_t RXRD: 1; // bit0 --- receive data available interrupt enable status
uint32_t TXS: 1; // bit1 --- thr empty interrupt enable status
uint32_t RXS: 1; // bit2 --- receiver line status interrupt enable status
uint32_t MDS: 1; // bit3 --- modem status interrupt enable status
uint32_t RTO: 1; // bit4 --- receiver timeout enable status
uint32_t BUSY: 1; // bit5 --- busy detect interrupt enable status
uint32_t ABE: 1; // bit6 --- auto baud rate end interrupt enable status
uint32_t ABTO: 1; // bit7 --- auto baud rate timeout interrupt enable status
uint32_t LINBK: 1; // bit8 --- lin break detection interrupt enable status
uint32_t TC: 1; // bit9 --- transmission complete interrupt enable status
uint32_t EOB: 1; // bit10 --- end of block interrupt enable status
uint32_t CM: 1; // bit11 --- character match interrupt enable status
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} UART_IVS_TypeDef; //0x02c
typedef union //0x030
{
struct
{
uint32_t RXRD: 1; // bit0 --- receive data available interrupt enable status
uint32_t TXS: 1; // bit1 --- thr empty interrupt enable status
uint32_t RXS: 1; // bit2 --- receiver line status interrupt enable status
uint32_t MDS: 1; // bit3 --- modem status interrupt enable status
uint32_t RTO: 1; // bit4 --- receiver timeout enable status
uint32_t BUSY: 1; // bit5 --- busy detect interrupt enable status
uint32_t ABE: 1; // bit6 --- auto baud rate end interrupt enable status
uint32_t ABTO: 1; // bit7 --- auto baud rate timeout interrupt enable status
uint32_t LINBK: 1; // bit8 --- lin break detection interrupt enable status
uint32_t TC: 1; // bit9 --- transmission complete interrupt enable status
uint32_t EOB: 1; // bit10 --- end of block interrupt enable status
uint32_t CM: 1; // bit11 --- character match interrupt enable status
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} UART_RIF_TypeDef; //0x030
typedef union //0x034
{
struct
{
uint32_t RXRD: 1; // bit0 --- receive data available interrupt enable status
uint32_t TXS: 1; // bit1 --- thr empty interrupt enable status
uint32_t RXS: 1; // bit2 --- receiver line status interrupt enable status
uint32_t MDS: 1; // bit3 --- modem status interrupt enable status
uint32_t RTO: 1; // bit4 --- receiver timeout enable status
uint32_t BUSY: 1; // bit5 --- busy detect interrupt enable status
uint32_t ABE: 1; // bit6 --- auto baud rate end interrupt enable status
uint32_t ABTO: 1; // bit7 --- auto baud rate timeout interrupt enable status
uint32_t LINBK: 1; // bit8 --- lin break detection interrupt enable status
uint32_t TC: 1; // bit9 --- transmission complete interrupt enable status
uint32_t EOB: 1; // bit10 --- end of block interrupt enable status
uint32_t CM: 1; // bit11 --- character match interrupt enable status
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} UART_IFM_TypeDef; //0x034
typedef union //0x038
{
struct
{
uint32_t RXRD: 1; // bit0 --- receive data available interrupt enable status
uint32_t TXS: 1; // bit1 --- thr empty interrupt enable status
uint32_t RXS: 1; // bit2 --- receiver line status interrupt enable status
uint32_t MDS: 1; // bit3 --- modem status interrupt enable status
uint32_t RTO: 1; // bit4 --- receiver timeout enable status
uint32_t BUSY: 1; // bit5 --- busy detect interrupt enable status
uint32_t ABE: 1; // bit6 --- auto baud rate end interrupt enable status
uint32_t ABTO: 1; // bit7 --- auto baud rate timeout interrupt enable status
uint32_t LINBK: 1; // bit8 --- lin break detection interrupt enable status
uint32_t TC: 1; // bit9 --- transmission complete interrupt enable status
uint32_t EOB: 1; // bit10 --- end of block interrupt enable status
uint32_t CM: 1; // bit11 --- character match interrupt enable status
uint32_t RSV_END: 20; // bit[31:12]
};
uint32_t Word;
} UART_ICR_TypeDef; //0x038
//================================
//BLOCK UART top struct define
typedef struct
{
__IO uint32_t RBR ; // 0x000,
// Receive buffer register
__IO uint32_t TBR ; // 0x004,
// Transmit buffer register
__IO uint32_t BRR ; // 0x008,
// Baud rate register
__IO UART_LCR_TypeDef LCR ; // 0x00c,
// Line control register
__IO UART_MCR_TypeDef MCR ; // 0x010,
// Mode control register
__IO UART_CR_TypeDef CR ; // 0x014,
// Control register
__IO UART_RTOR_TypeDef RTOR; // 0x018,
// Receiver timeout register
__IO UART_FCR_TypeDef FCR ; // 0x01c,
// FIFO control register
__IO UART_SR_TypeDef SR ; // 0x020,
// Status register
__O UART_IER_TypeDef IER ; // 0x024,
// Interrupt enable register
__O UART_IDR_TypeDef IDR ; // 0x028,
// Interrupt disable register
__I UART_IVS_TypeDef IVS ; // 0x02c,
// Interrupt valid status
__I UART_RIF_TypeDef RIF ; // 0x030,
// Raw interrupt flag
__I UART_IFM_TypeDef IFM ; // 0x034,
// Interrupt flag masked
__O UART_ICR_TypeDef ICR ; // 0x038,
// Interrupt clear register
} UART_TypeDef;
#define UART1 (( UART_TypeDef *) UART1_BASE)
#define UART2 (( UART_TypeDef *) UART2_BASE)
#endif

27
core/reg/regs.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _REGS_H_
#define _REGS_H_
#include "reg_aon.h"
#include "reg_apbmisc.h"
#include "reg_btmr.h"
#include "reg_cache.h"
#include "reg_csc.h"
#include "reg_dma.h"
#include "reg_dmachcfg.h"
#include "reg_exti.h"
#include "reg_fshc.h"
#include "reg_gpio.h"
#include "reg_i2c.h"
#include "reg_iwdt.h"
#include "reg_mdm.h"
#include "reg_rcc.h"
#include "reg_rf.h"
#include "reg_sadc.h"
#include "reg_spim.h"
#include "reg_spis.h"
#include "reg_syscfg.h"
#include "reg_timer.h"
#include "reg_uart.h"
#endif // _REGS_H_

268
core/rom.h Normal file
View File

@ -0,0 +1,268 @@
/**
****************************************************************************************
*
* @file rom.h
*
* @brief Header file - Drivers defined in ROM
*
****************************************************************************************
*/
#ifndef _ROM_H_
#define _ROM_H_
#include <stdint.h>
/*
* DEFINES
****************************************************************************************
*/
/// Address Pointer of APIs
enum ROM_POINTER {
ROM_BOOTLOADER = 0x000001b9,
ROM_PUART_CONF = 0x0000032d,
ROM_PUART_GETC = 0x00000379,
ROM_PUART_PUTC = 0x00000387,
ROM_PUART_WAIT = 0x00000393,
ROM_PUART_INIT = 0x000003a3,
ROM_UARTSYNC = 0x00000469,
ROM_UARTPARSE = 0x000004a9,
ROM_SYSJUMPTO = 0x00000731,
ROM_BTMR_DELAY = 0x00000749,
ROM_XO16M_EN = 0x00000777,
ROM_EXTCLK_EN = 0x0000079b,
ROM_DPLL_EN = 0x000007bd,
ROM_DEEPSLEEP = 0x000007df,
ROM_RSTCLR = 0x00000845,
ROM_RCC_FSHCLK_SET = 0x00000877,
ROM_IWDT_CONF = 0x000008d1,
ROM_RC16M_CALIB = 0x000008fd,
ROM_TRIMVALLOAD = 0x0000097d,
ROM_FSHC_XIP_CONF = 0x00000abd,
ROM_FSHC_SUSPEND_CONF = 0x00000ae1,
ROM_FSHC_HPM_CONF = 0x00000b1f,
ROM_FSHC_EN_CMD = 0x00000b59,
ROM_FSHC_WR_STA = 0x00000b73,
ROM_FSHC_RD_STA = 0x00000b9d,
ROM_FSHC_WR_CFG = 0x00000bcd,
ROM_FSHC_WR_FIFO = 0x00000beb,
ROM_FSHC_RD_CFG = 0x00000c21,
ROM_FSHC_RD_FIFO = 0x00000c41,
ROM_FSHC_ERASE = 0x00000c63,
ROM_FSHC_WRITE = 0x00000cb9,
ROM_FSHC_READ = 0x00000d1d,
ROM_FLASHINIT = 0x00000d6d,
ROM_FSHC_CAPDLY_CFG = 0x00000dc9,
ROM_FSHC_QUAD_MODE = 0x00000e25,
ROM_PUYA_QUADHPMXIPMODE = 0x00000e41,
ROM_PUYA_ENTER_HPM = 0x00000e61,
ROM_PUYA_EXIT_HPM = 0x00000ead,
ROM_XMEMCPY = 0x00000f19,
ROM_XMEMMOVE = 0x00000f59,
ROM_XMEMSET = 0x00000f75,
ROM_XMEMCMP = 0x00000fa3,
};
/// Flash Data length type
typedef uint32_t flen_t;
/*
* APIs : Memory Operation
****************************************************************************************
*/
/// Same as memcpy, direct copy uint32_t if aligned
#define xmemcpy ((void (*)(void *dst, const void *src, uint32_t size))ROM_XMEMCPY)
/// Same as memmove, reverse copy or inner call xmemcpy
#define xmemmove ((void (*)(void * dst, const void * src, uint32_t size))ROM_XMEMMOVE)
/// Same as xmemset, fill cccc to uint32_t when address aligned
#define xmemset ((void (*)(void *m, uint8_t c, uint32_t size))ROM_XMEMSET)
/// Same as memcmp, direct compare uint32_t if aligned
#define xmemcmp ((int (*)(const void *m1, const void *m2, uint32_t size))ROM_XMEMCMP)
/*
* APIs : Core Utility
****************************************************************************************
*/
/// Core enter deep sleep mode, inner call __wfi
#define deepsleep ((void (*)(void))ROM_DEEPSLEEP)
/// Clear states of Core reset and wakeup, return the reason and source
/// @see enum rst_src_bfs
#define rstrsn ((uint16_t (*)(void))ROM_RSTCLR)
/// Jump to the running 'addr' of application, SP PC STACK reinited
#define sysJumpTo ((void (*)(uint32_t addr))ROM_SYSJUMPTO)
/// Enable xosc16m Oscillator mode, wait 2ms for stable
#define xo16m_en ((void (*)(void))ROM_XO16M_EN)
/// Enable extarnal clock mode, through XOSC16M_IN PAD into chip
#define extclk_en ((void (*)(void))ROM_EXTCLK_EN)
/// Enable dpll power and clk, wait 50us for stable
#define dpll_en ((void (*)(void))ROM_DPLL_EN)
/// Delay via basic timer, wait 'tcnt' count in 'tpsc' prescaler
/// eg. btmr_delay(16, 1000) means delay 1Ms when sysclk is 16MHz
#define btmr_delay ((void (*)(uint16_t tpsc, uint16_t tcnt))ROM_BTMR_DELAY)
/// time must great than 1
#if (SYS_CLK == 1)
#define bootDelayMs(time) btmr_delay(32000, time)
#define bootDelayUs(time) btmr_delay(32, time)
#elif (SYS_CLK == 2)
#define bootDelayMs(time) btmr_delay(48000, time)
#define bootDelayUs(time) btmr_delay(48, time)
#elif (SYS_CLK == 3)
#define bootDelayMs(time) btmr_delay(64000, time)
#define bootDelayUs(time) btmr_delay(64, time)
#else
#define bootDelayMs(time) btmr_delay(16000, time)
#define bootDelayUs(time) btmr_delay(16, time)
#endif //SYS_CLK
/// Config IWDT, disable if 'load' equl 0
#define iwdt_conf ((uint32_t (*)(uint32_t load))ROM_IWDT_CONF)
/// Calib rc16m, return trim value(range 0~63)
#define rc16m_calib ((uint8_t (*)(void))ROM_RC16M_CALIB)
/*
* APIs : Boot Uart(UART1)
****************************************************************************************
*/
/// Csc PA6 PA7 as pUart PIN
#define pUart_init ((void (*)(void))ROM_PUART_INIT)
/// Config pUart params
#define pUart_conf ((void (*)(uint16_t cfg_BRR, uint16_t cfg_LCR))ROM_PUART_CONF)
/// Get one data from pUart RXD(Blocking)
#define pUart_getc ((uint8_t (*)(void))ROM_PUART_GETC)
/// Put one byte via pUart TXD(Blocking)
#define pUart_putc ((void (*)(uint8_t ch))ROM_PUART_PUTC)
/// Wait pUart finished(not busy)
#define pUart_wait ((void (*)(void))ROM_PUART_WAIT)
/*
* APIs: Flash Controlor(FSHC) Driver
****************************************************************************************
*/
/// Set Fshc Clock Selection @see enum fsh_clk_sel
#define rcc_fshclk_set ((void (*)(uint8_t fclk_sel))ROM_RCC_FSHCLK_SET)
/// Config XIP mode
#define fshc_xip_conf ((void (*)(uint8_t rdCmd, uint8_t adrBits, uint32_t dlySet))ROM_FSHC_XIP_CONF)
/// Config HPM mode
#define fshc_hpm_conf ((void (*)(bool en, uint8_t crIdx, uint8_t crCmd))ROM_FSHC_HPM_CONF)
/// Config Suspend/Resume
#define fshc_suspend_conf ((void (*)(uint8_t susCmd, uint8_t rsmCmd, uint16_t susTime, uint32_t rsmTime))ROM_FSHC_SUSPEND_CONF)
/**
****************************************************************************************
* @brief Send control/enable command without value
*
* @param[in] cmd Command opcode(eg. FSH_CMD_RST_EN FSH_CMD_RESET FSH_CMD_EXIT_HMP
* FSH_CMD_WR_EN FSH_CMD_WR_STA_EN)
*
****************************************************************************************
*/
#define fshc_en_cmd ((void (*)(uint8_t cmd))ROM_FSHC_EN_CMD)
/**
****************************************************************************************
* @brief Write value to flash state register
*
* @param[in] cmd Command opcode(eg. FSH_CMD_WR_STA)
* @param[in] len Length of value, range 1~4 Bytes
* @param[in] val State value, valid range 8/16/24/32bits by 'len'
*
****************************************************************************************
*/
#define fshc_wr_sta ((void (*)(uint8_t cmd, uint8_t len, uint32_t val))ROM_FSHC_WR_STA)
/**
****************************************************************************************
* @brief Read value from flash state register
*
* @param[in] cmd Command opcode(eg. FSH_CMD_RD_ID FSH_CMD_RD_STA0 FSH_CMD_RD_STA1)
* @param[in] len Length of value, range 1~4 Bytes
*
* @return value State value, valid range 8/16/24/32bits by 'len'
****************************************************************************************
*/
#define fshc_rd_sta ((uint32_t (*)(uint8_t cmd, uint8_t len))ROM_FSHC_RD_STA)
/**
****************************************************************************************
* @brief Perpare write data to flash
*
* @param[in] cmd fshc access cmd (example read cmd: 0x03)
* @param[in] offset access flash addr offset
* @param[in] len access flash data len, unit is byte
* @param[in] sctrl access flash mode config(example: spi mode, dual mode...)
* @param[in] acbit dummy cycle
*
****************************************************************************************
*/
#define fshc_wr_cfg ((void (*)(uint8_t cmd, uint32_t offset, flen_t len, uint16_t sctrl, uint16_t acbit))ROM_FSHC_WR_CFG)
/// Fill 'data'(unit in uint32_t, length='wlen') to Fshc Write-FiFo in 'fcmd' mode
#define fshc_wr_fifo ((flen_t (*)(const uint32_t *data, flen_t wlen, uint16_t fcmd))fshc_wr_fifo)
/**
****************************************************************************************
* @brief Perpare read data from flash
*
* @param[in] cmd fshc access cmd (example read cmd: 0x03)
* @param[in] offset access flash addr offset
* @param[in] len access flash data len, unit is byte
* @param[in] sctrl access flash mode config(example: spi mode, dual mode...)
* @param[in] acbit dummy cycle
*
****************************************************************************************
*/
#define fshc_rd_cfg ((void (*)(uint8_t cmd, uint32_t offset, flen_t len, uint16_t sctrl, uint16_t acbit))ROM_FSHC_RD_CFG)
/// Get data from Fshc Read-FiFo to 'buff'(unit in uint32_t, length='wlen') in 'fcmd' mode
#define fshc_rd_fifo ((flen_t (*)(uint32_t *buff, flen_t wlen, uint16_t fcmd))ROM_FSHC_RD_FIFO)
/// Erase Flash in 'fcmd' config, inner call fshc_en_cmd() fshc_wr_cfg()
#define fshc_erase ((void (*)(uint32_t offset, uint16_t fcmd))ROM_FSHC_ERASE)
/// Read Flash in 'fcmd' config, inner call fshc_rd_cfg() fshc_rd_fifo()
#define fshc_read ((flen_t (*)(uint32_t offset, uint32_t *buff, flen_t wlen, uint16_t fcmd))ROM_FSHC_READ)
/// Write Flash in 'fcmd' config, inner call fshc_en_cmd() fshc_wr_cfg()fshc_wr_fifo()
#define fshc_write ((flen_t (*)(uint32_t offset, const uint32_t *data, flen_t wlen, uint16_t fcmd))ROM_FSHC_WRITE)
/// Config Flash Cap Dealy cell(0~7, default 5), auto search if 'dly' > 7
#define fshc_capdly_cfg ((uint8_t (*)(uint8_t dly))ROM_FSHC_CAPDLY_CFG)
/// Config Flash Access Mode, enter/exit Quad mode with special 'val'
#define fshc_quad_mode ((void (*)(uint16_t val))ROM_FSHC_QUAD_MODE)
/// BoYa Flash enter HPM mode
#define boya_enter_hpm ((void (*)(void))ROM_PUYA_ENTER_HPM)
/// BoYa Flash exit HPM Mode
#define boya_exit_hpm ((void (*)(void))ROM_PUYA_EXIT_HPM)
#endif // _ROM_H_

523
core/string.h Normal file
View File

@ -0,0 +1,523 @@
/* string.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.11 */
/* Copyright (C) Codemist Ltd., 1988-1993. */
/* Copyright 1991-1993 ARM Limited. All rights reserved. */
/* version 0.04 */
/*
* RCS $Revision$
* Checkin $Date$
*/
/*
* string.h declares one type and several functions, and defines one macro
* useful for manipulating character arrays and other objects treated as
* character arrays. Various methods are used for determining the lengths of
* the arrays, but in all cases a char * or void * argument points to the
* initial (lowest addresses) character of the array. If an array is written
* beyond the end of an object, the behaviour is undefined.
*/
#ifndef __string_h
#define __string_h
#define _ARMABI __declspec(__nothrow)
#ifndef __STRING_DECLS
#define __STRING_DECLS
#undef __CLIBNS
#ifdef __cplusplus
namespace std {
#define __CLIBNS std::
extern "C" {
#else
#define __CLIBNS
#endif /* __cplusplus */
#if defined(__cplusplus) || !defined(__STRICT_ANSI__)
/* unconditional in C++ and non-strict C for consistency of debug info */
#if __sizeof_ptr == 8
typedef unsigned long size_t; /* see <stddef.h> */
#else
typedef unsigned int size_t; /* see <stddef.h> */
#endif
#elif !defined(__size_t)
#define __size_t 1
#if __sizeof_ptr == 8
typedef unsigned long size_t; /* see <stddef.h> */
#else
typedef unsigned int size_t; /* see <stddef.h> */
#endif
#endif
#undef NULL
#define NULL 0 /* see <stddef.h> */
#if (MEM_API)
extern _ARMABI void *memcpy(void * __restrict /*s1*/,
const void * __restrict /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
/*
* copies n characters from the object pointed to by s2 into the object
* pointed to by s1. If copying takes place between objects that overlap,
* the behaviour is undefined.
* Returns: the value of s1.
*/
extern _ARMABI void *memmove(void * /*s1*/,
const void * /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
/*
* copies n characters from the object pointed to by s2 into the object
* pointed to by s1. Copying takes place as if the n characters from the
* object pointed to by s2 are first copied into a temporary array of n
* characters that does not overlap the objects pointed to by s1 and s2,
* and then the n characters from the temporary array are copied into the
* object pointed to by s1.
* Returns: the value of s1.
*/
#else //(ROM_API)
/// Same as memcpy, direct copy uint32_t if aligned
#define memcpy ((void (*)(void *dst, const void *src, unsigned int size))0x00000f19) //ROM_XMEMCPY)
/// Same as memmove, reverse copy or inner call xmemcpy
#define memmove ((void (*)(void * dst, const void * src, unsigned int size))0x00000f59)//ROM_XMEMMOVE)
#endif //(MEM_API)
extern _ARMABI char *strcpy(char * __restrict /*s1*/, const char * __restrict /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* copies the string pointed to by s2 (including the terminating nul
* character) into the array pointed to by s1. If copying takes place
* between objects that overlap, the behaviour is undefined.
* Returns: the value of s1.
*/
extern _ARMABI char *strncpy(char * __restrict /*s1*/, const char * __restrict /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
/*
* copies not more than n characters (characters that follow a null
* character are not copied) from the array pointed to by s2 into the array
* pointed to by s1. If copying takes place between objects that overlap,
* the behaviour is undefined.
* Returns: the value of s1.
*/
extern _ARMABI char *strcat(char * __restrict /*s1*/, const char * __restrict /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* appends a copy of the string pointed to by s2 (including the terminating
* null character) to the end of the string pointed to by s1. The initial
* character of s2 overwrites the null character at the end of s1.
* Returns: the value of s1.
*/
extern _ARMABI char *strncat(char * __restrict /*s1*/, const char * __restrict /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
/*
* appends not more than n characters (a null character and characters that
* follow it are not appended) from the array pointed to by s2 to the end of
* the string pointed to by s1. The initial character of s2 overwrites the
* null character at the end of s1. A terminating null character is always
* appended to the result.
* Returns: the value of s1.
*/
/*
* The sign of a nonzero value returned by the comparison functions is
* determined by the sign of the difference between the values of the first
* pair of characters (both interpreted as unsigned char) that differ in the
* objects being compared.
*/
#if (MEM_API)
extern _ARMABI int memcmp(const void * /*s1*/, const void * /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
#else //(ROM_API)
/// Same as memcmp, direct compare uint32_t if aligned
#define memcmp ((int (*)(const void *m1, const void *m2, unsigned int size))0x00000fa3) //ROM_XMEMCMP)
#endif //(MEM_API)
/*
* compares the first n characters of the object pointed to by s1 to the
* first n characters of the object pointed to by s2.
* Returns: an integer greater than, equal to, or less than zero, according
* as the object pointed to by s1 is greater than, equal to, or
* less than the object pointed to by s2.
*/
extern _ARMABI int strcmp(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* compares the string pointed to by s1 to the string pointed to by s2.
* Returns: an integer greater than, equal to, or less than zero, according
* as the string pointed to by s1 is greater than, equal to, or
* less than the string pointed to by s2.
*/
extern _ARMABI int strncmp(const char * /*s1*/, const char * /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
/*
* compares not more than n characters (characters that follow a null
* character are not compared) from the array pointed to by s1 to the array
* pointed to by s2.
* Returns: an integer greater than, equal to, or less than zero, according
* as the string pointed to by s1 is greater than, equal to, or
* less than the string pointed to by s2.
*/
extern _ARMABI int strcasecmp(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* compares the string pointed to by s1 to the string pointed to by s2,
* case-insensitively as defined by the current locale.
* Returns: an integer greater than, equal to, or less than zero, according
* as the string pointed to by s1 is greater than, equal to, or
* less than the string pointed to by s2.
*/
extern _ARMABI int strncasecmp(const char * /*s1*/, const char * /*s2*/, size_t /*n*/) __attribute__((__nonnull__(1,2)));
/*
* compares not more than n characters (characters that follow a null
* character are not compared) from the array pointed to by s1 to the array
* pointed to by s2, case-insensitively as defined by the current locale.
* Returns: an integer greater than, equal to, or less than zero, according
* as the string pointed to by s1 is greater than, equal to, or
* less than the string pointed to by s2.
*/
extern _ARMABI int strcoll(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* compares the string pointed to by s1 to the string pointed to by s2, both
* interpreted as appropriate to the LC_COLLATE category of the current
* locale.
* Returns: an integer greater than, equal to, or less than zero, according
* as the string pointed to by s1 is greater than, equal to, or
* less than the string pointed to by s2 when both are interpreted
* as appropriate to the current locale.
*/
extern _ARMABI size_t strxfrm(char * __restrict /*s1*/, const char * __restrict /*s2*/, size_t /*n*/) __attribute__((__nonnull__(2)));
/*
* transforms the string pointed to by s2 and places the resulting string
* into the array pointed to by s1. The transformation function is such that
* if the strcmp function is applied to two transformed strings, it returns
* a value greater than, equal to or less than zero, corresponding to the
* result of the strcoll function applied to the same two original strings.
* No more than n characters are placed into the resulting array pointed to
* by s1, including the terminating null character. If n is zero, s1 is
* permitted to be a null pointer. If copying takes place between objects
* that overlap, the behaviour is undefined.
* Returns: The length of the transformed string is returned (not including
* the terminating null character). If the value returned is n or
* more, the contents of the array pointed to by s1 are
* indeterminate.
*/
#ifdef __cplusplus
extern _ARMABI const void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/) __attribute__((__nonnull__(1)));
extern "C++" void *memchr(void * __s, int __c, size_t __n) __attribute__((__nonnull__(1)));
extern "C++" inline void *memchr(void * __s, int __c, size_t __n)
{ return const_cast<void *>(memchr(const_cast<const void *>(__s), __c, __n)); }
#else
extern _ARMABI void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/) __attribute__((__nonnull__(1)));
#endif
/*
* locates the first occurence of c (converted to an unsigned char) in the
* initial n characters (each interpreted as unsigned char) of the object
* pointed to by s.
* Returns: a pointer to the located character, or a null pointer if the
* character does not occur in the object.
*/
#ifdef __cplusplus
extern _ARMABI const char *strchr(const char * /*s*/, int /*c*/) __attribute__((__nonnull__(1)));
extern "C++" char *strchr(char * __s, int __c) __attribute__((__nonnull__(1)));
extern "C++" inline char *strchr(char * __s, int __c)
{ return const_cast<char *>(strchr(const_cast<const char *>(__s), __c)); }
#else
extern _ARMABI char *strchr(const char * /*s*/, int /*c*/) __attribute__((__nonnull__(1)));
#endif
/*
* locates the first occurence of c (converted to an char) in the string
* pointed to by s (including the terminating null character).
* Returns: a pointer to the located character, or a null pointer if the
* character does not occur in the string.
*/
extern _ARMABI size_t strcspn(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* computes the length of the initial segment of the string pointed to by s1
* which consists entirely of characters not from the string pointed to by
* s2. The terminating null character is not considered part of s2.
* Returns: the length of the segment.
*/
#ifdef __cplusplus
extern _ARMABI const char *strpbrk(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
extern "C++" char *strpbrk(char * __s1, const char * __s2) __attribute__((__nonnull__(1,2)));
extern "C++" inline char *strpbrk(char * __s1, const char * __s2)
{ return const_cast<char *>(strpbrk(const_cast<const char *>(__s1), __s2)); }
#else
extern _ARMABI char *strpbrk(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
#endif
/*
* locates the first occurence in the string pointed to by s1 of any
* character from the string pointed to by s2.
* Returns: returns a pointer to the character, or a null pointer if no
* character form s2 occurs in s1.
*/
#ifdef __cplusplus
extern _ARMABI const char *strrchr(const char * /*s*/, int /*c*/) __attribute__((__nonnull__(1)));
extern "C++" char *strrchr(char * __s, int __c) __attribute__((__nonnull__(1)));
extern "C++" inline char *strrchr(char * __s, int __c)
{ return const_cast<char *>(strrchr(const_cast<const char *>(__s), __c)); }
#else
extern _ARMABI char *strrchr(const char * /*s*/, int /*c*/) __attribute__((__nonnull__(1)));
#endif
/*
* locates the last occurence of c (converted to a char) in the string
* pointed to by s. The terminating null character is considered part of
* the string.
* Returns: returns a pointer to the character, or a null pointer if c does
* not occur in the string.
*/
extern _ARMABI size_t strspn(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
/*
* computes the length of the initial segment of the string pointed to by s1
* which consists entirely of characters from the string pointed to by S2
* Returns: the length of the segment.
*/
#ifdef __cplusplus
extern _ARMABI const char *strstr(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
extern "C++" char *strstr(char * __s1, const char * __s2) __attribute__((__nonnull__(1,2)));
extern "C++" inline char *strstr(char * __s1, const char * __s2)
{ return const_cast<char *>(strstr(const_cast<const char *>(__s1), __s2)); }
#else
extern _ARMABI char *strstr(const char * /*s1*/, const char * /*s2*/) __attribute__((__nonnull__(1,2)));
#endif
/*
* locates the first occurence in the string pointed to by s1 of the
* sequence of characters (excluding the terminating null character) in the
* string pointed to by s2.
* Returns: a pointer to the located string, or a null pointer if the string
* is not found.
*/
extern _ARMABI char *strtok(char * __restrict /*s1*/, const char * __restrict /*s2*/) __attribute__((__nonnull__(2)));
extern _ARMABI char *_strtok_r(char * /*s1*/, const char * /*s2*/, char ** /*ptr*/) __attribute__((__nonnull__(2,3)));
#ifndef __STRICT_ANSI__
extern _ARMABI char *strtok_r(char * /*s1*/, const char * /*s2*/, char ** /*ptr*/) __attribute__((__nonnull__(2,3)));
#endif
/*
* A sequence of calls to the strtok function breaks the string pointed to
* by s1 into a sequence of tokens, each of which is delimited by a
* character from the string pointed to by s2. The first call in the
* sequence has s1 as its first argument, and is followed by calls with a
* null pointer as their first argument. The separator string pointed to by
* s2 may be different from call to call.
* The first call in the sequence searches for the first character that is
* not contained in the current separator string s2. If no such character
* is found, then there are no tokens in s1 and the strtok function returns
* a null pointer. If such a character is found, it is the start of the
* first token.
* The strtok function then searches from there for a character that is
* contained in the current separator string. If no such character is found,
* the current token extends to the end of the string pointed to by s1, and
* subsequent searches for a token will fail. If such a character is found,
* it is overwritten by a null character, which terminates the current
* token. The strtok function saves a pointer to the following character,
* from which the next search for a token will start.
* Each subsequent call, with a null pointer as the value for the first
* argument, starts searching from the saved pointer and behaves as
* described above.
* Returns: pointer to the first character of a token, or a null pointer if
* there is no token.
*
* strtok_r() is a common extension which works exactly like
* strtok(), but instead of storing its state in a hidden
* library variable, requires the user to pass in a pointer to a
* char * variable which will be used instead. Any sequence of
* calls to strtok_r() passing the same char ** pointer should
* behave exactly like the corresponding sequence of calls to
* strtok(). This means that strtok_r() can safely be used in
* multi-threaded programs, and also that you can tokenise two
* strings in parallel.
*/
#if (MEM_API)
extern _ARMABI void *memset(void * /*s*/, int /*c*/, size_t /*n*/) __attribute__((__nonnull__(1)));
#else //(ROM_API)
/// Same as xmemset, fill cccc to uint32_t when address aligned
#define memset ((void (*)(void *m, uint8_t c, unsigned int size))0x00000f75)
#endif //(MEM_API)
/*
* copies the value of c (converted to an unsigned char) into each of the
* first n charactes of the object pointed to by s.
* Returns: the value of s.
*/
extern _ARMABI char *strerror(int /*errnum*/);
/*
* maps the error number in errnum to an error message string.
* Returns: a pointer to the string, the contents of which are
* implementation-defined. The array pointed to shall not be
* modified by the program, but may be overwritten by a
* subsequent call to the strerror function.
*/
extern _ARMABI size_t strlen(const char * /*s*/) __attribute__((__nonnull__(1)));
/*
* computes the length of the string pointed to by s.
* Returns: the number of characters that precede the terminating null
* character.
*/
extern _ARMABI size_t strlcpy(char * /*dst*/, const char * /*src*/, size_t /*len*/) __attribute__((__nonnull__(1,2)));
/*
* copies the string src into the string dst, using no more than
* len bytes of dst. Always null-terminates dst _within the
* length len (i.e. will copy at most len-1 bytes of string plus
* a NUL), unless len is actually zero.
*
* Return value is the length of the string that _would_ have
* been written, i.e. the length of src. Thus, the operation
* succeeded without truncation if and only if ret < len;
* otherwise, the value in ret tells you how big to make dst if
* you decide to reallocate it. (That value does _not_ include
* the NUL.)
*
* This is a BSD-derived library extension, which we are
* permitted to declare in a standard header because ISO defines
* function names beginning with 'str' as reserved for future
* expansion of <string.h>.
*/
extern _ARMABI size_t strlcat(char * /*dst*/, const char * /*src*/, size_t /*len*/) __attribute__((__nonnull__(1,2)));
/*
* concatenates the string src to the string dst, using no more
* than len bytes of dst. Always null-terminates dst _within the
* length len (i.e. will copy at most len-1 bytes of string plus
* a NUL), unless len is actually zero.
*
* Return value is the length of the string that _would_ have
* been written, i.e. the length of src plus the original length
* of dst. Thus, the operation succeeded without truncation if
* and only if ret < len; otherwise, the value in ret tells you
* how big to make dst if you decide to reallocate it. (That
* value does _not_ include the NUL.)
*
* If no NUL is encountered within the first len bytes of dst,
* then the length of dst is considered to have been equal to
* len for the purposes of the return value (as if there were a
* NUL at dst[len]). Thus, the return value in this case is len
* + strlen(src).
*
* This is a BSD-derived library extension, which we are
* permitted to declare in a standard header because ISO defines
* function names beginning with 'str' as reserved for future
* expansion of <string.h>.
*/
extern _ARMABI void _membitcpybl(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitcpybb(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitcpyhl(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitcpyhb(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitcpywl(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitcpywb(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitmovebl(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitmovebb(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitmovehl(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitmovehb(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitmovewl(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
extern _ARMABI void _membitmovewb(void * /*dest*/, const void * /*src*/, int /*destoffset*/, int /*srcoffset*/, size_t /*nbits*/) __attribute__((__nonnull__(1,2)));
/*
* Copies or moves a piece of memory from one place to another,
* with one-bit granularity. So you can start or finish a copy
* part way through a byte, and you can copy between regions
* with different alignment within a byte.
*
* All these functions have the same prototype: two void *
* pointers for destination and source, then two integers
* giving the bit offset from those pointers, and finally the
* number of bits to copy.
*
* Just like memcpy and memmove, the "cpy" functions copy as
* fast as they can in the assumption that the memory regions
* do not overlap, while the "move" functions cope correctly
* with overlap.
*
* Treating memory as a stream of individual bits requires
* defining a convention about what order those bits are
* considered to be arranged in. The above functions support
* multiple conventions:
*
* - the "bl" functions consider the unit of memory to be the
* byte, and consider the bits within each byte to be
* arranged in little-endian fashion, so that the LSB comes
* first. (For example, membitcpybl(a,b,0,7,1) would copy
* the MSB of the byte at b to the LSB of the byte at a.)
*
* - the "bb" functions consider the unit of memory to be the
* byte, and consider the bits within each byte to be
* arranged in big-endian fashion, so that the MSB comes
* first.
*
* - the "hl" functions consider the unit of memory to be the
* 16-bit halfword, and consider the bits within each word
* to be arranged in little-endian fashion.
*
* - the "hb" functions consider the unit of memory to be the
* 16-bit halfword, and consider the bits within each word
* to be arranged in big-endian fashion.
*
* - the "wl" functions consider the unit of memory to be the
* 32-bit word, and consider the bits within each word to be
* arranged in little-endian fashion.
*
* - the "wb" functions consider the unit of memory to be the
* 32-bit word, and consider the bits within each word to be
* arranged in big-endian fashion.
*/
#ifdef __cplusplus
} /* extern "C" */
} /* namespace std */
#endif /* __cplusplus */
#endif /* __STRING_DECLS */
#ifdef __cplusplus
#ifndef __STRING_NO_EXPORTS
using ::std::size_t;
using ::std::memcpy;
using ::std::memmove;
using ::std::strcpy;
using ::std::strncpy;
using ::std::strcat;
using ::std::strncat;
using ::std::memcmp;
using ::std::strcmp;
using ::std::strncmp;
using ::std::strcasecmp;
using ::std::strncasecmp;
using ::std::strcoll;
using ::std::strxfrm;
using ::std::memchr;
using ::std::strchr;
using ::std::strcspn;
using ::std::strpbrk;
using ::std::strrchr;
using ::std::strspn;
using ::std::strstr;
using ::std::strtok;
#ifndef __STRICT_ANSI__
using ::std::strtok_r;
#endif
using ::std::_strtok_r;
using ::std::memset;
using ::std::strerror;
using ::std::strlen;
using ::std::strlcpy;
using ::std::strlcat;
using ::std::_membitcpybl;
using ::std::_membitcpybb;
using ::std::_membitcpyhl;
using ::std::_membitcpyhb;
using ::std::_membitcpywl;
using ::std::_membitcpywb;
using ::std::_membitmovebl;
using ::std::_membitmovebb;
using ::std::_membitmovehl;
using ::std::_membitmovehb;
using ::std::_membitmovewl;
using ::std::_membitmovewb;
#endif /* __STRING_NO_EXPORTS */
#endif /* __cplusplus */
#endif
/* end of string.h */

BIN
doc/APIs/APIs.zip Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More